|
@@ -186,35 +186,84 @@ impl Default for Ln {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
#[cfg(feature = "lnbits")]
|
|
#[cfg(feature = "lnbits")]
|
|
|
-#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
|
|
|
|
|
|
+#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
|
pub struct LNbits {
|
|
pub struct LNbits {
|
|
|
pub admin_api_key: String,
|
|
pub admin_api_key: String,
|
|
|
pub invoice_api_key: String,
|
|
pub invoice_api_key: String,
|
|
|
pub lnbits_api: String,
|
|
pub lnbits_api: String,
|
|
|
|
|
+ #[serde(default = "default_fee_percent")]
|
|
|
pub fee_percent: f32,
|
|
pub fee_percent: f32,
|
|
|
|
|
+ #[serde(default = "default_reserve_fee_min")]
|
|
|
pub reserve_fee_min: Amount,
|
|
pub reserve_fee_min: Amount,
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+#[cfg(feature = "lnbits")]
|
|
|
|
|
+impl Default for LNbits {
|
|
|
|
|
+ fn default() -> Self {
|
|
|
|
|
+ Self {
|
|
|
|
|
+ admin_api_key: String::new(),
|
|
|
|
|
+ invoice_api_key: String::new(),
|
|
|
|
|
+ lnbits_api: String::new(),
|
|
|
|
|
+ fee_percent: 0.02,
|
|
|
|
|
+ reserve_fee_min: 2.into(),
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
#[cfg(feature = "cln")]
|
|
#[cfg(feature = "cln")]
|
|
|
-#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
|
|
|
|
|
|
+#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
|
pub struct Cln {
|
|
pub struct Cln {
|
|
|
pub rpc_path: PathBuf,
|
|
pub rpc_path: PathBuf,
|
|
|
- #[serde(default)]
|
|
|
|
|
|
|
+ #[serde(default = "default_cln_bolt12")]
|
|
|
pub bolt12: bool,
|
|
pub bolt12: bool,
|
|
|
|
|
+ #[serde(default = "default_fee_percent")]
|
|
|
pub fee_percent: f32,
|
|
pub fee_percent: f32,
|
|
|
|
|
+ #[serde(default = "default_reserve_fee_min")]
|
|
|
pub reserve_fee_min: Amount,
|
|
pub reserve_fee_min: Amount,
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+#[cfg(feature = "cln")]
|
|
|
|
|
+impl Default for Cln {
|
|
|
|
|
+ fn default() -> Self {
|
|
|
|
|
+ Self {
|
|
|
|
|
+ rpc_path: PathBuf::new(),
|
|
|
|
|
+ bolt12: true,
|
|
|
|
|
+ fee_percent: 0.02,
|
|
|
|
|
+ reserve_fee_min: 2.into(),
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+#[cfg(feature = "cln")]
|
|
|
|
|
+fn default_cln_bolt12() -> bool {
|
|
|
|
|
+ true
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
#[cfg(feature = "lnd")]
|
|
#[cfg(feature = "lnd")]
|
|
|
-#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
|
|
|
|
|
|
+#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
|
pub struct Lnd {
|
|
pub struct Lnd {
|
|
|
pub address: String,
|
|
pub address: String,
|
|
|
pub cert_file: PathBuf,
|
|
pub cert_file: PathBuf,
|
|
|
pub macaroon_file: PathBuf,
|
|
pub macaroon_file: PathBuf,
|
|
|
|
|
+ #[serde(default = "default_fee_percent")]
|
|
|
pub fee_percent: f32,
|
|
pub fee_percent: f32,
|
|
|
|
|
+ #[serde(default = "default_reserve_fee_min")]
|
|
|
pub reserve_fee_min: Amount,
|
|
pub reserve_fee_min: Amount,
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+#[cfg(feature = "lnd")]
|
|
|
|
|
+impl Default for Lnd {
|
|
|
|
|
+ fn default() -> Self {
|
|
|
|
|
+ Self {
|
|
|
|
|
+ address: String::new(),
|
|
|
|
|
+ cert_file: PathBuf::new(),
|
|
|
|
|
+ macaroon_file: PathBuf::new(),
|
|
|
|
|
+ fee_percent: 0.02,
|
|
|
|
|
+ reserve_fee_min: 2.into(),
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
#[cfg(feature = "ldk-node")]
|
|
#[cfg(feature = "ldk-node")]
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
|
pub struct LdkNode {
|
|
pub struct LdkNode {
|
|
@@ -323,6 +372,15 @@ impl Default for FakeWallet {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Helper functions to provide default values
|
|
// Helper functions to provide default values
|
|
|
|
|
+// Common fee defaults for all backends
|
|
|
|
|
+fn default_fee_percent() -> f32 {
|
|
|
|
|
+ 0.02
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+fn default_reserve_fee_min() -> Amount {
|
|
|
|
|
+ 2.into()
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
#[cfg(feature = "fakewallet")]
|
|
#[cfg(feature = "fakewallet")]
|
|
|
fn default_min_delay_time() -> u64 {
|
|
fn default_min_delay_time() -> u64 {
|
|
|
1
|
|
1
|
|
@@ -333,14 +391,37 @@ fn default_max_delay_time() -> u64 {
|
|
|
3
|
|
3
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
|
|
|
|
|
|
|
+#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
|
|
|
pub struct GrpcProcessor {
|
|
pub struct GrpcProcessor {
|
|
|
|
|
+ #[serde(default)]
|
|
|
pub supported_units: Vec<CurrencyUnit>,
|
|
pub supported_units: Vec<CurrencyUnit>,
|
|
|
|
|
+ #[serde(default = "default_grpc_addr")]
|
|
|
pub addr: String,
|
|
pub addr: String,
|
|
|
|
|
+ #[serde(default = "default_grpc_port")]
|
|
|
pub port: u16,
|
|
pub port: u16,
|
|
|
|
|
+ #[serde(default)]
|
|
|
pub tls_dir: Option<PathBuf>,
|
|
pub tls_dir: Option<PathBuf>,
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+impl Default for GrpcProcessor {
|
|
|
|
|
+ fn default() -> Self {
|
|
|
|
|
+ Self {
|
|
|
|
|
+ supported_units: Vec::new(),
|
|
|
|
|
+ addr: default_grpc_addr(),
|
|
|
|
|
+ port: default_grpc_port(),
|
|
|
|
|
+ tls_dir: None,
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+fn default_grpc_addr() -> String {
|
|
|
|
|
+ "127.0.0.1".to_string()
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+fn default_grpc_port() -> u16 {
|
|
|
|
|
+ 50051
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
|
|
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
|
|
|
#[serde(rename_all = "lowercase")]
|
|
#[serde(rename_all = "lowercase")]
|
|
|
pub enum DatabaseEngine {
|
|
pub enum DatabaseEngine {
|
|
@@ -579,46 +660,6 @@ impl Settings {
|
|
|
.build()?;
|
|
.build()?;
|
|
|
let settings: Settings = config.try_deserialize()?;
|
|
let settings: Settings = config.try_deserialize()?;
|
|
|
|
|
|
|
|
- match settings.ln.ln_backend {
|
|
|
|
|
- LnBackend::None => panic!("Ln backend must be set"),
|
|
|
|
|
- #[cfg(feature = "cln")]
|
|
|
|
|
- LnBackend::Cln => assert!(
|
|
|
|
|
- settings.cln.is_some(),
|
|
|
|
|
- "CLN backend requires a valid config."
|
|
|
|
|
- ),
|
|
|
|
|
- #[cfg(feature = "lnbits")]
|
|
|
|
|
- LnBackend::LNbits => assert!(
|
|
|
|
|
- settings.lnbits.is_some(),
|
|
|
|
|
- "LNbits backend requires a valid config"
|
|
|
|
|
- ),
|
|
|
|
|
- #[cfg(feature = "lnd")]
|
|
|
|
|
- LnBackend::Lnd => {
|
|
|
|
|
- assert!(
|
|
|
|
|
- settings.lnd.is_some(),
|
|
|
|
|
- "LND backend requires a valid config."
|
|
|
|
|
- )
|
|
|
|
|
- }
|
|
|
|
|
- #[cfg(feature = "ldk-node")]
|
|
|
|
|
- LnBackend::LdkNode => {
|
|
|
|
|
- assert!(
|
|
|
|
|
- settings.ldk_node.is_some(),
|
|
|
|
|
- "LDK Node backend requires a valid config."
|
|
|
|
|
- )
|
|
|
|
|
- }
|
|
|
|
|
- #[cfg(feature = "fakewallet")]
|
|
|
|
|
- LnBackend::FakeWallet => assert!(
|
|
|
|
|
- settings.fake_wallet.is_some(),
|
|
|
|
|
- "FakeWallet backend requires a valid config."
|
|
|
|
|
- ),
|
|
|
|
|
- #[cfg(feature = "grpc-processor")]
|
|
|
|
|
- LnBackend::GrpcProcessor => {
|
|
|
|
|
- assert!(
|
|
|
|
|
- settings.grpc_processor.is_some(),
|
|
|
|
|
- "GRPC backend requires a valid config."
|
|
|
|
|
- )
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
Ok(settings)
|
|
Ok(settings)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -692,4 +733,374 @@ mod tests {
|
|
|
assert!(!debug_output.contains("特殊字符 !@#$%^&*()"));
|
|
assert!(!debug_output.contains("特殊字符 !@#$%^&*()"));
|
|
|
assert!(debug_output.contains("<hashed: "));
|
|
assert!(debug_output.contains("<hashed: "));
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ /// Test that configuration can be loaded purely from environment variables
|
|
|
|
|
+ /// without requiring a config.toml file with backend sections.
|
|
|
|
|
+ ///
|
|
|
|
|
+ /// This test runs sequentially for all enabled backends to avoid env var interference.
|
|
|
|
|
+ #[test]
|
|
|
|
|
+ fn test_env_var_only_config_all_backends() {
|
|
|
|
|
+ // Run each backend test sequentially
|
|
|
|
|
+ #[cfg(feature = "lnd")]
|
|
|
|
|
+ test_lnd_env_config();
|
|
|
|
|
+
|
|
|
|
|
+ #[cfg(feature = "cln")]
|
|
|
|
|
+ test_cln_env_config();
|
|
|
|
|
+
|
|
|
|
|
+ #[cfg(feature = "lnbits")]
|
|
|
|
|
+ test_lnbits_env_config();
|
|
|
|
|
+
|
|
|
|
|
+ #[cfg(feature = "fakewallet")]
|
|
|
|
|
+ test_fakewallet_env_config();
|
|
|
|
|
+
|
|
|
|
|
+ #[cfg(feature = "grpc-processor")]
|
|
|
|
|
+ test_grpc_processor_env_config();
|
|
|
|
|
+
|
|
|
|
|
+ #[cfg(feature = "ldk-node")]
|
|
|
|
|
+ test_ldk_node_env_config();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ #[cfg(feature = "lnd")]
|
|
|
|
|
+ fn test_lnd_env_config() {
|
|
|
|
|
+ use std::path::PathBuf;
|
|
|
|
|
+ use std::{env, fs};
|
|
|
|
|
+
|
|
|
|
|
+ // Create a temporary directory for config file
|
|
|
|
|
+ let temp_dir = env::temp_dir().join("cdk_test_env_vars");
|
|
|
|
|
+ fs::create_dir_all(&temp_dir).expect("Failed to create temp dir");
|
|
|
|
|
+ let config_path = temp_dir.join("config.toml");
|
|
|
|
|
+
|
|
|
|
|
+ // Create a minimal config.toml with backend set but NO [lnd] section
|
|
|
|
|
+ let config_content = r#"
|
|
|
|
|
+[ln]
|
|
|
|
|
+backend = "lnd"
|
|
|
|
|
+min_mint = 1
|
|
|
|
|
+max_mint = 500000
|
|
|
|
|
+min_melt = 1
|
|
|
|
|
+max_melt = 500000
|
|
|
|
|
+"#;
|
|
|
|
|
+ fs::write(&config_path, config_content).expect("Failed to write config file");
|
|
|
|
|
+
|
|
|
|
|
+ // Set environment variables for LND configuration
|
|
|
|
|
+ env::set_var(crate::env_vars::ENV_LN_BACKEND, "lnd");
|
|
|
|
|
+ env::set_var(crate::env_vars::ENV_LND_ADDRESS, "https://localhost:10009");
|
|
|
|
|
+ env::set_var(crate::env_vars::ENV_LND_CERT_FILE, "/tmp/test_tls.cert");
|
|
|
|
|
+ env::set_var(
|
|
|
|
|
+ crate::env_vars::ENV_LND_MACAROON_FILE,
|
|
|
|
|
+ "/tmp/test_admin.macaroon",
|
|
|
|
|
+ );
|
|
|
|
|
+ env::set_var(crate::env_vars::ENV_LND_FEE_PERCENT, "0.01");
|
|
|
|
|
+ env::set_var(crate::env_vars::ENV_LND_RESERVE_FEE_MIN, "4");
|
|
|
|
|
+
|
|
|
|
|
+ // Load settings and apply environment variables (same as production code)
|
|
|
|
|
+ let mut settings = Settings::new(Some(&config_path));
|
|
|
|
|
+ settings.from_env().expect("Failed to apply env vars");
|
|
|
|
|
+
|
|
|
|
|
+ // Verify that settings were populated from env vars
|
|
|
|
|
+ assert!(settings.lnd.is_some());
|
|
|
|
|
+ let lnd_config = settings.lnd.as_ref().unwrap();
|
|
|
|
|
+ assert_eq!(lnd_config.address, "https://localhost:10009");
|
|
|
|
|
+ assert_eq!(lnd_config.cert_file, PathBuf::from("/tmp/test_tls.cert"));
|
|
|
|
|
+ assert_eq!(
|
|
|
|
|
+ lnd_config.macaroon_file,
|
|
|
|
|
+ PathBuf::from("/tmp/test_admin.macaroon")
|
|
|
|
|
+ );
|
|
|
|
|
+ assert_eq!(lnd_config.fee_percent, 0.01);
|
|
|
|
|
+ let reserve_fee_u64: u64 = lnd_config.reserve_fee_min.into();
|
|
|
|
|
+ assert_eq!(reserve_fee_u64, 4);
|
|
|
|
|
+
|
|
|
|
|
+ // Cleanup env vars
|
|
|
|
|
+ env::remove_var(crate::env_vars::ENV_LN_BACKEND);
|
|
|
|
|
+ env::remove_var(crate::env_vars::ENV_LND_ADDRESS);
|
|
|
|
|
+ env::remove_var(crate::env_vars::ENV_LND_CERT_FILE);
|
|
|
|
|
+ env::remove_var(crate::env_vars::ENV_LND_MACAROON_FILE);
|
|
|
|
|
+ env::remove_var(crate::env_vars::ENV_LND_FEE_PERCENT);
|
|
|
|
|
+ env::remove_var(crate::env_vars::ENV_LND_RESERVE_FEE_MIN);
|
|
|
|
|
+
|
|
|
|
|
+ // Cleanup test file
|
|
|
|
|
+ let _ = fs::remove_dir_all(&temp_dir);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ #[cfg(feature = "cln")]
|
|
|
|
|
+ fn test_cln_env_config() {
|
|
|
|
|
+ use std::path::PathBuf;
|
|
|
|
|
+ use std::{env, fs};
|
|
|
|
|
+
|
|
|
|
|
+ // Create a temporary directory for config file
|
|
|
|
|
+ let temp_dir = env::temp_dir().join("cdk_test_env_vars_cln");
|
|
|
|
|
+ fs::create_dir_all(&temp_dir).expect("Failed to create temp dir");
|
|
|
|
|
+ let config_path = temp_dir.join("config.toml");
|
|
|
|
|
+
|
|
|
|
|
+ // Create a minimal config.toml with backend set but NO [cln] section
|
|
|
|
|
+ let config_content = r#"
|
|
|
|
|
+[ln]
|
|
|
|
|
+backend = "cln"
|
|
|
|
|
+min_mint = 1
|
|
|
|
|
+max_mint = 500000
|
|
|
|
|
+min_melt = 1
|
|
|
|
|
+max_melt = 500000
|
|
|
|
|
+"#;
|
|
|
|
|
+ fs::write(&config_path, config_content).expect("Failed to write config file");
|
|
|
|
|
+
|
|
|
|
|
+ // Set environment variables for CLN configuration
|
|
|
|
|
+ env::set_var(crate::env_vars::ENV_LN_BACKEND, "cln");
|
|
|
|
|
+ env::set_var(crate::env_vars::ENV_CLN_RPC_PATH, "/tmp/lightning-rpc");
|
|
|
|
|
+ env::set_var(crate::env_vars::ENV_CLN_BOLT12, "false");
|
|
|
|
|
+ env::set_var(crate::env_vars::ENV_CLN_FEE_PERCENT, "0.01");
|
|
|
|
|
+ env::set_var(crate::env_vars::ENV_CLN_RESERVE_FEE_MIN, "4");
|
|
|
|
|
+
|
|
|
|
|
+ // Load settings and apply environment variables (same as production code)
|
|
|
|
|
+ let mut settings = Settings::new(Some(&config_path));
|
|
|
|
|
+ settings.from_env().expect("Failed to apply env vars");
|
|
|
|
|
+
|
|
|
|
|
+ // Verify that settings were populated from env vars
|
|
|
|
|
+ assert!(settings.cln.is_some());
|
|
|
|
|
+ let cln_config = settings.cln.as_ref().unwrap();
|
|
|
|
|
+ assert_eq!(cln_config.rpc_path, PathBuf::from("/tmp/lightning-rpc"));
|
|
|
|
|
+ assert_eq!(cln_config.bolt12, false);
|
|
|
|
|
+ assert_eq!(cln_config.fee_percent, 0.01);
|
|
|
|
|
+ let reserve_fee_u64: u64 = cln_config.reserve_fee_min.into();
|
|
|
|
|
+ assert_eq!(reserve_fee_u64, 4);
|
|
|
|
|
+
|
|
|
|
|
+ // Cleanup env vars
|
|
|
|
|
+ env::remove_var(crate::env_vars::ENV_LN_BACKEND);
|
|
|
|
|
+ env::remove_var(crate::env_vars::ENV_CLN_RPC_PATH);
|
|
|
|
|
+ env::remove_var(crate::env_vars::ENV_CLN_BOLT12);
|
|
|
|
|
+ env::remove_var(crate::env_vars::ENV_CLN_FEE_PERCENT);
|
|
|
|
|
+ env::remove_var(crate::env_vars::ENV_CLN_RESERVE_FEE_MIN);
|
|
|
|
|
+
|
|
|
|
|
+ // Cleanup test file
|
|
|
|
|
+ let _ = fs::remove_dir_all(&temp_dir);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ #[cfg(feature = "lnbits")]
|
|
|
|
|
+ fn test_lnbits_env_config() {
|
|
|
|
|
+ use std::{env, fs};
|
|
|
|
|
+
|
|
|
|
|
+ // Create a temporary directory for config file
|
|
|
|
|
+ let temp_dir = env::temp_dir().join("cdk_test_env_vars_lnbits");
|
|
|
|
|
+ fs::create_dir_all(&temp_dir).expect("Failed to create temp dir");
|
|
|
|
|
+ let config_path = temp_dir.join("config.toml");
|
|
|
|
|
+
|
|
|
|
|
+ // Create a minimal config.toml with backend set but NO [lnbits] section
|
|
|
|
|
+ let config_content = r#"
|
|
|
|
|
+[ln]
|
|
|
|
|
+backend = "lnbits"
|
|
|
|
|
+min_mint = 1
|
|
|
|
|
+max_mint = 500000
|
|
|
|
|
+min_melt = 1
|
|
|
|
|
+max_melt = 500000
|
|
|
|
|
+"#;
|
|
|
|
|
+ fs::write(&config_path, config_content).expect("Failed to write config file");
|
|
|
|
|
+
|
|
|
|
|
+ // Set environment variables for LNbits configuration
|
|
|
|
|
+ env::set_var(crate::env_vars::ENV_LN_BACKEND, "lnbits");
|
|
|
|
|
+ env::set_var(crate::env_vars::ENV_LNBITS_ADMIN_API_KEY, "test_admin_key");
|
|
|
|
|
+ env::set_var(
|
|
|
|
|
+ crate::env_vars::ENV_LNBITS_INVOICE_API_KEY,
|
|
|
|
|
+ "test_invoice_key",
|
|
|
|
|
+ );
|
|
|
|
|
+ env::set_var(
|
|
|
|
|
+ crate::env_vars::ENV_LNBITS_API,
|
|
|
|
|
+ "https://lnbits.example.com",
|
|
|
|
|
+ );
|
|
|
|
|
+ env::set_var(crate::env_vars::ENV_LNBITS_FEE_PERCENT, "0.02");
|
|
|
|
|
+ env::set_var(crate::env_vars::ENV_LNBITS_RESERVE_FEE_MIN, "5");
|
|
|
|
|
+
|
|
|
|
|
+ // Load settings and apply environment variables (same as production code)
|
|
|
|
|
+ let mut settings = Settings::new(Some(&config_path));
|
|
|
|
|
+ settings.from_env().expect("Failed to apply env vars");
|
|
|
|
|
+
|
|
|
|
|
+ // Verify that settings were populated from env vars
|
|
|
|
|
+ assert!(settings.lnbits.is_some());
|
|
|
|
|
+ let lnbits_config = settings.lnbits.as_ref().unwrap();
|
|
|
|
|
+ assert_eq!(lnbits_config.admin_api_key, "test_admin_key");
|
|
|
|
|
+ assert_eq!(lnbits_config.invoice_api_key, "test_invoice_key");
|
|
|
|
|
+ assert_eq!(lnbits_config.lnbits_api, "https://lnbits.example.com");
|
|
|
|
|
+ assert_eq!(lnbits_config.fee_percent, 0.02);
|
|
|
|
|
+ let reserve_fee_u64: u64 = lnbits_config.reserve_fee_min.into();
|
|
|
|
|
+ assert_eq!(reserve_fee_u64, 5);
|
|
|
|
|
+
|
|
|
|
|
+ // Cleanup env vars
|
|
|
|
|
+ env::remove_var(crate::env_vars::ENV_LN_BACKEND);
|
|
|
|
|
+ env::remove_var(crate::env_vars::ENV_LNBITS_ADMIN_API_KEY);
|
|
|
|
|
+ env::remove_var(crate::env_vars::ENV_LNBITS_INVOICE_API_KEY);
|
|
|
|
|
+ env::remove_var(crate::env_vars::ENV_LNBITS_API);
|
|
|
|
|
+ env::remove_var(crate::env_vars::ENV_LNBITS_FEE_PERCENT);
|
|
|
|
|
+ env::remove_var(crate::env_vars::ENV_LNBITS_RESERVE_FEE_MIN);
|
|
|
|
|
+
|
|
|
|
|
+ // Cleanup test file
|
|
|
|
|
+ let _ = fs::remove_dir_all(&temp_dir);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ #[cfg(feature = "fakewallet")]
|
|
|
|
|
+ fn test_fakewallet_env_config() {
|
|
|
|
|
+ use std::{env, fs};
|
|
|
|
|
+
|
|
|
|
|
+ // Create a temporary directory for config file
|
|
|
|
|
+ let temp_dir = env::temp_dir().join("cdk_test_env_vars_fakewallet");
|
|
|
|
|
+ fs::create_dir_all(&temp_dir).expect("Failed to create temp dir");
|
|
|
|
|
+ let config_path = temp_dir.join("config.toml");
|
|
|
|
|
+
|
|
|
|
|
+ // Create a minimal config.toml with backend set but NO [fake_wallet] section
|
|
|
|
|
+ let config_content = r#"
|
|
|
|
|
+[ln]
|
|
|
|
|
+backend = "fakewallet"
|
|
|
|
|
+min_mint = 1
|
|
|
|
|
+max_mint = 500000
|
|
|
|
|
+min_melt = 1
|
|
|
|
|
+max_melt = 500000
|
|
|
|
|
+"#;
|
|
|
|
|
+ fs::write(&config_path, config_content).expect("Failed to write config file");
|
|
|
|
|
+
|
|
|
|
|
+ // Set environment variables for FakeWallet configuration
|
|
|
|
|
+ env::set_var(crate::env_vars::ENV_LN_BACKEND, "fakewallet");
|
|
|
|
|
+ env::set_var(crate::env_vars::ENV_FAKE_WALLET_SUPPORTED_UNITS, "sat,msat");
|
|
|
|
|
+ env::set_var(crate::env_vars::ENV_FAKE_WALLET_FEE_PERCENT, "0.0");
|
|
|
|
|
+ env::set_var(crate::env_vars::ENV_FAKE_WALLET_RESERVE_FEE_MIN, "0");
|
|
|
|
|
+ env::set_var(crate::env_vars::ENV_FAKE_WALLET_MIN_DELAY, "0");
|
|
|
|
|
+ env::set_var(crate::env_vars::ENV_FAKE_WALLET_MAX_DELAY, "5");
|
|
|
|
|
+
|
|
|
|
|
+ // Load settings and apply environment variables (same as production code)
|
|
|
|
|
+ let mut settings = Settings::new(Some(&config_path));
|
|
|
|
|
+ settings.from_env().expect("Failed to apply env vars");
|
|
|
|
|
+
|
|
|
|
|
+ // Verify that settings were populated from env vars
|
|
|
|
|
+ assert!(settings.fake_wallet.is_some());
|
|
|
|
|
+ let fakewallet_config = settings.fake_wallet.as_ref().unwrap();
|
|
|
|
|
+ assert_eq!(fakewallet_config.fee_percent, 0.0);
|
|
|
|
|
+ let reserve_fee_u64: u64 = fakewallet_config.reserve_fee_min.into();
|
|
|
|
|
+ assert_eq!(reserve_fee_u64, 0);
|
|
|
|
|
+ assert_eq!(fakewallet_config.min_delay_time, 0);
|
|
|
|
|
+ assert_eq!(fakewallet_config.max_delay_time, 5);
|
|
|
|
|
+
|
|
|
|
|
+ // Cleanup env vars
|
|
|
|
|
+ env::remove_var(crate::env_vars::ENV_LN_BACKEND);
|
|
|
|
|
+ env::remove_var(crate::env_vars::ENV_FAKE_WALLET_SUPPORTED_UNITS);
|
|
|
|
|
+ env::remove_var(crate::env_vars::ENV_FAKE_WALLET_FEE_PERCENT);
|
|
|
|
|
+ env::remove_var(crate::env_vars::ENV_FAKE_WALLET_RESERVE_FEE_MIN);
|
|
|
|
|
+ env::remove_var(crate::env_vars::ENV_FAKE_WALLET_MIN_DELAY);
|
|
|
|
|
+ env::remove_var(crate::env_vars::ENV_FAKE_WALLET_MAX_DELAY);
|
|
|
|
|
+
|
|
|
|
|
+ // Cleanup test file
|
|
|
|
|
+ let _ = fs::remove_dir_all(&temp_dir);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ #[cfg(feature = "grpc-processor")]
|
|
|
|
|
+ fn test_grpc_processor_env_config() {
|
|
|
|
|
+ use std::{env, fs};
|
|
|
|
|
+
|
|
|
|
|
+ // Create a temporary directory for config file
|
|
|
|
|
+ let temp_dir = env::temp_dir().join("cdk_test_env_vars_grpc");
|
|
|
|
|
+ fs::create_dir_all(&temp_dir).expect("Failed to create temp dir");
|
|
|
|
|
+ let config_path = temp_dir.join("config.toml");
|
|
|
|
|
+
|
|
|
|
|
+ // Create a minimal config.toml with backend set but NO [grpc_processor] section
|
|
|
|
|
+ let config_content = r#"
|
|
|
|
|
+[ln]
|
|
|
|
|
+backend = "grpcprocessor"
|
|
|
|
|
+min_mint = 1
|
|
|
|
|
+max_mint = 500000
|
|
|
|
|
+min_melt = 1
|
|
|
|
|
+max_melt = 500000
|
|
|
|
|
+"#;
|
|
|
|
|
+ fs::write(&config_path, config_content).expect("Failed to write config file");
|
|
|
|
|
+
|
|
|
|
|
+ // Set environment variables for GRPC Processor configuration
|
|
|
|
|
+ env::set_var(crate::env_vars::ENV_LN_BACKEND, "grpcprocessor");
|
|
|
|
|
+ env::set_var(
|
|
|
|
|
+ crate::env_vars::ENV_GRPC_PROCESSOR_SUPPORTED_UNITS,
|
|
|
|
|
+ "sat,msat",
|
|
|
|
|
+ );
|
|
|
|
|
+ env::set_var(crate::env_vars::ENV_GRPC_PROCESSOR_ADDRESS, "localhost");
|
|
|
|
|
+ env::set_var(crate::env_vars::ENV_GRPC_PROCESSOR_PORT, "50051");
|
|
|
|
|
+
|
|
|
|
|
+ // Load settings and apply environment variables (same as production code)
|
|
|
|
|
+ let mut settings = Settings::new(Some(&config_path));
|
|
|
|
|
+ settings.from_env().expect("Failed to apply env vars");
|
|
|
|
|
+
|
|
|
|
|
+ // Verify that settings were populated from env vars
|
|
|
|
|
+ assert!(settings.grpc_processor.is_some());
|
|
|
|
|
+ let grpc_config = settings.grpc_processor.as_ref().unwrap();
|
|
|
|
|
+ assert_eq!(grpc_config.addr, "localhost");
|
|
|
|
|
+ assert_eq!(grpc_config.port, 50051);
|
|
|
|
|
+
|
|
|
|
|
+ // Cleanup env vars
|
|
|
|
|
+ env::remove_var(crate::env_vars::ENV_LN_BACKEND);
|
|
|
|
|
+ env::remove_var(crate::env_vars::ENV_GRPC_PROCESSOR_SUPPORTED_UNITS);
|
|
|
|
|
+ env::remove_var(crate::env_vars::ENV_GRPC_PROCESSOR_ADDRESS);
|
|
|
|
|
+ env::remove_var(crate::env_vars::ENV_GRPC_PROCESSOR_PORT);
|
|
|
|
|
+
|
|
|
|
|
+ // Cleanup test file
|
|
|
|
|
+ let _ = fs::remove_dir_all(&temp_dir);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ #[cfg(feature = "ldk-node")]
|
|
|
|
|
+ fn test_ldk_node_env_config() {
|
|
|
|
|
+ use std::{env, fs};
|
|
|
|
|
+
|
|
|
|
|
+ // Create a temporary directory for config file
|
|
|
|
|
+ let temp_dir = env::temp_dir().join("cdk_test_env_vars_ldk");
|
|
|
|
|
+ fs::create_dir_all(&temp_dir).expect("Failed to create temp dir");
|
|
|
|
|
+ let config_path = temp_dir.join("config.toml");
|
|
|
|
|
+
|
|
|
|
|
+ // Create a minimal config.toml with backend set but NO [ldk_node] section
|
|
|
|
|
+ let config_content = r#"
|
|
|
|
|
+[ln]
|
|
|
|
|
+backend = "ldknode"
|
|
|
|
|
+min_mint = 1
|
|
|
|
|
+max_mint = 500000
|
|
|
|
|
+min_melt = 1
|
|
|
|
|
+max_melt = 500000
|
|
|
|
|
+"#;
|
|
|
|
|
+ fs::write(&config_path, config_content).expect("Failed to write config file");
|
|
|
|
|
+
|
|
|
|
|
+ // Set environment variables for LDK Node configuration
|
|
|
|
|
+ env::set_var(crate::env_vars::ENV_LN_BACKEND, "ldknode");
|
|
|
|
|
+ env::set_var(crate::env_vars::LDK_NODE_FEE_PERCENT_ENV_VAR, "0.01");
|
|
|
|
|
+ env::set_var(crate::env_vars::LDK_NODE_RESERVE_FEE_MIN_ENV_VAR, "4");
|
|
|
|
|
+ env::set_var(crate::env_vars::LDK_NODE_BITCOIN_NETWORK_ENV_VAR, "regtest");
|
|
|
|
|
+ env::set_var(
|
|
|
|
|
+ crate::env_vars::LDK_NODE_CHAIN_SOURCE_TYPE_ENV_VAR,
|
|
|
|
|
+ "esplora",
|
|
|
|
|
+ );
|
|
|
|
|
+ env::set_var(
|
|
|
|
|
+ crate::env_vars::LDK_NODE_ESPLORA_URL_ENV_VAR,
|
|
|
|
|
+ "http://localhost:3000",
|
|
|
|
|
+ );
|
|
|
|
|
+ env::set_var(
|
|
|
|
|
+ crate::env_vars::LDK_NODE_STORAGE_DIR_PATH_ENV_VAR,
|
|
|
|
|
+ "/tmp/ldk",
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ // Load settings and apply environment variables (same as production code)
|
|
|
|
|
+ let mut settings = Settings::new(Some(&config_path));
|
|
|
|
|
+ settings.from_env().expect("Failed to apply env vars");
|
|
|
|
|
+
|
|
|
|
|
+ // Verify that settings were populated from env vars
|
|
|
|
|
+ assert!(settings.ldk_node.is_some());
|
|
|
|
|
+ let ldk_config = settings.ldk_node.as_ref().unwrap();
|
|
|
|
|
+ assert_eq!(ldk_config.fee_percent, 0.01);
|
|
|
|
|
+ let reserve_fee_u64: u64 = ldk_config.reserve_fee_min.into();
|
|
|
|
|
+ assert_eq!(reserve_fee_u64, 4);
|
|
|
|
|
+ assert_eq!(ldk_config.bitcoin_network, Some("regtest".to_string()));
|
|
|
|
|
+ assert_eq!(ldk_config.chain_source_type, Some("esplora".to_string()));
|
|
|
|
|
+ assert_eq!(
|
|
|
|
|
+ ldk_config.esplora_url,
|
|
|
|
|
+ Some("http://localhost:3000".to_string())
|
|
|
|
|
+ );
|
|
|
|
|
+ assert_eq!(ldk_config.storage_dir_path, Some("/tmp/ldk".to_string()));
|
|
|
|
|
+
|
|
|
|
|
+ // Cleanup env vars
|
|
|
|
|
+ env::remove_var(crate::env_vars::ENV_LN_BACKEND);
|
|
|
|
|
+ env::remove_var(crate::env_vars::LDK_NODE_FEE_PERCENT_ENV_VAR);
|
|
|
|
|
+ env::remove_var(crate::env_vars::LDK_NODE_RESERVE_FEE_MIN_ENV_VAR);
|
|
|
|
|
+ env::remove_var(crate::env_vars::LDK_NODE_BITCOIN_NETWORK_ENV_VAR);
|
|
|
|
|
+ env::remove_var(crate::env_vars::LDK_NODE_CHAIN_SOURCE_TYPE_ENV_VAR);
|
|
|
|
|
+ env::remove_var(crate::env_vars::LDK_NODE_ESPLORA_URL_ENV_VAR);
|
|
|
|
|
+ env::remove_var(crate::env_vars::LDK_NODE_STORAGE_DIR_PATH_ENV_VAR);
|
|
|
|
|
+
|
|
|
|
|
+ // Cleanup test file
|
|
|
|
|
+ let _ = fs::remove_dir_all(&temp_dir);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|