In anchor the "top" of any program features a declare_id!()
statement. The input to that statement is a Pubkey
, typically in the form of a hard coded string. 12Factor Methodology typically dictates that hard coded configuration values like this should be avoided. However trying to not hard code the value has me pulling out my hair.
declare_id!(std::env::var("VARIABLE_NAME"));
Does not work because the env::var
call executes at runtime while the macro executes at compile time.
declare_id!(env!("VARIABLE_NAME"));
Does not work because env!
returns a &str
.
declare_id!(Pubkey::from_str(env!("VARIABLE_NAME")));
Does not work because Pubkey::from_str
can fail and as such returns a Result
declare_id!(Pubkey::from_str(env!("VARIABLE_NAME")).unwrap());
Does not work because declare_id!
requires a constant and constants cannot be made from unwrap
(Its probably more nuanced than that, but I'm new to rust) and ?
fails for the same reason.
Bonus points:
env::var()
returns a Result<&str>
env::var_os()
returns a Result<&OsStr>
env!()
returns a &str
env_os!()
does not exist in core
How do you handle an OsStr
environment variable at build time? Why would you not need to be able to?
Working with env vars seems troublesome, since most of the ways of creating a Pubkey
aren't const fn
. To me, this seems like an issue with the anchor-lang
crate, usually env vars aren't this troublesome.
That said, you could write the key to a config file somewhere, and read that in using include_bytes
, and pass that to Pubkey::new_from_array
, which is const:
// this works because concat! expands to a string literal
const BYTES: &[u8; 32] = include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/key"));
anchor_lang::declare_id!(Pubkey::new_from_array(*BYTES));
If you don't want to store the file in the repo, you can point include_bytes!()
at any location, even one read from an env var. For example, you could have:
const BYTES: &[u8; 32] = include_bytes!(env!("ANCHOR_KEY_LOCATION"));
anchor_lang::declare_id!(Pubkey::new_from_array(*BYTES));
which will read the key bytes from a file at $ANCHOR_KEY_LOCATION