use std::{env, path::PathBuf, str::FromStr};
use cosmwasm_std::StdError;
use regex::Regex;
use std::time::Duration;
const DEFAULT_TX_QUERY_RETRIES: usize = 50;
pub const STATE_FILE_ENV_NAME: &str = "STATE_FILE";
pub const GAS_BUFFER_ENV_NAME: &str = "CW_ORCH_GAS_BUFFER";
pub const MIN_GAS_ENV_NAME: &str = "CW_ORCH_MIN_GAS";
pub const MAX_TX_QUERIES_RETRY_ENV_NAME: &str = "CW_ORCH_MAX_TX_QUERY_RETRIES";
pub const MIN_BLOCK_SPEED_ENV_NAME: &str = "CW_ORCH_MIN_BLOCK_SPEED";
pub const WALLET_BALANCE_ASSERTION_ENV_NAME: &str = "CW_ORCH_WALLET_BALANCE_ASSERTION";
pub const LOGS_ACTIVATION_MESSAGE_ENV_NAME: &str = "CW_ORCH_LOGS_ACTIVATION_MESSAGE";
pub const MAIN_MNEMONIC_ENV_NAME: &str = "MAIN_MNEMONIC";
pub const TEST_MNEMONIC_ENV_NAME: &str = "TEST_MNEMONIC";
pub const LOCAL_MNEMONIC_ENV_NAME: &str = "LOCAL_MNEMONIC";
pub struct DaemonEnvVars {}
impl DaemonEnvVars {
pub fn state_file() -> PathBuf {
let state_file_string = env::var(STATE_FILE_ENV_NAME).unwrap_or("state.json".to_string());
parse_with_log(state_file_string, STATE_FILE_ENV_NAME)
}
pub fn gas_buffer() -> Option<f64> {
if let Ok(str_value) = env::var(GAS_BUFFER_ENV_NAME) {
Some(parse_with_log(str_value, GAS_BUFFER_ENV_NAME))
} else {
None
}
}
pub fn min_gas() -> Option<u64> {
if let Ok(str_value) = env::var(MIN_GAS_ENV_NAME) {
Some(parse_with_log(str_value, MIN_GAS_ENV_NAME))
} else {
None
}
}
pub fn max_tx_query_retries() -> usize {
if let Ok(str_value) = env::var(MAX_TX_QUERIES_RETRY_ENV_NAME) {
parse_with_log(str_value, MAX_TX_QUERIES_RETRY_ENV_NAME)
} else {
DEFAULT_TX_QUERY_RETRIES
}
}
pub fn min_block_speed() -> Duration {
if let Ok(str_value) = env::var(MIN_BLOCK_SPEED_ENV_NAME) {
let ms_re = Regex::new(r"(\d+)ms").unwrap();
let s_re = Regex::new(r"(\d+)s").unwrap();
if let Some(caps) = ms_re.captures(&str_value) {
if let Some(ms) = caps.get(1) {
let milliseconds: u64 =
parse_with_log(ms.as_str().to_string(), MIN_BLOCK_SPEED_ENV_NAME);
Duration::from_millis(milliseconds)
} else {
panic!("Couldn't parse content of env var {MIN_BLOCK_SPEED_ENV_NAME}, error : Didn't find a match for format `{{int}}ms");
}
} else if let Some(caps) = s_re.captures(&str_value) {
if let Some(s) = caps.get(1) {
let seconds: u64 =
parse_with_log(s.as_str().to_string(), MIN_BLOCK_SPEED_ENV_NAME);
Duration::from_secs(seconds)
} else {
panic!("Couldn't parse content of env var {MIN_BLOCK_SPEED_ENV_NAME}, error : Didn't find a match for format `{{int}}s");
}
} else {
let seconds: u64 = parse_with_log(str_value, MIN_BLOCK_SPEED_ENV_NAME);
Duration::from_secs(seconds)
}
} else {
Duration::from_secs(1)
}
}
pub fn wallet_balance_assertion() -> bool {
if let Ok(str_value) = env::var(WALLET_BALANCE_ASSERTION_ENV_NAME) {
parse_with_log(str_value, WALLET_BALANCE_ASSERTION_ENV_NAME)
} else {
true
}
}
pub fn logs_message() -> bool {
if let Ok(str_value) = env::var(LOGS_ACTIVATION_MESSAGE_ENV_NAME) {
parse_with_log(str_value, LOGS_ACTIVATION_MESSAGE_ENV_NAME)
} else {
true
}
}
pub fn main_mnemonic() -> Option<String> {
env::var(MAIN_MNEMONIC_ENV_NAME).ok()
}
pub fn test_mnemonic() -> Option<String> {
env::var(TEST_MNEMONIC_ENV_NAME).ok()
}
pub fn local_mnemonic() -> Option<String> {
env::var(LOCAL_MNEMONIC_ENV_NAME).ok()
}
}
pub fn default_state_folder() -> Result<PathBuf, StdError> {
dirs::home_dir().map(|home| home.join(".cw-orchestrator"))
.ok_or( StdError::generic_err(
format!(
"Your machine doesn't have a home folder. You can't use relative path for the state file such as 'state.json'.
Please use an absolute path ('/home/root/state.json') or a dot-prefixed-relative path ('./state.json') in the {} env variable.",
STATE_FILE_ENV_NAME
)))
}
fn parse_with_log<F: FromStr<Err = E>, E: std::fmt::Display>(
value: String,
env_var_name: &str,
) -> F {
match value.parse() {
Ok(parsed) => parsed,
Err(e) => panic!("Couldn't parse content of env var {env_var_name}, error : {e}"),
}
}