Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crates/cdk-mintd/example.config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ enabled = false
#[prometheus]
#enabled = true
#address = "127.0.0.1"
#port = 9090
#port = 9000
#
[info.http_cache]
# memory or redis
Expand Down
63 changes: 45 additions & 18 deletions crates/cdk-mintd/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ pub struct LoggingConfig {
}

#[derive(Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct Info {
pub url: String,
pub listen_host: String,
Expand Down Expand Up @@ -175,6 +176,7 @@ impl std::str::FromStr for LnBackend {
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct Ln {
pub ln_backend: LnBackend,
pub invoice_description: Option<String>,
Expand All @@ -199,6 +201,7 @@ impl Default for Ln {

#[cfg(feature = "lnbits")]
#[derive(Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct LNbits {
pub admin_api_key: String,
pub invoice_api_key: String,
Expand Down Expand Up @@ -237,6 +240,7 @@ impl Default for LNbits {

#[cfg(feature = "cln")]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct Cln {
pub rpc_path: PathBuf,
#[serde(default = "default_cln_bolt12")]
Expand Down Expand Up @@ -269,6 +273,7 @@ fn default_cln_bolt12() -> bool {

#[cfg(feature = "lnd")]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct Lnd {
pub address: String,
pub cert_file: PathBuf,
Expand All @@ -294,6 +299,7 @@ impl Default for Lnd {

#[cfg(feature = "ldk-node")]
#[derive(Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct LdkNode {
/// Fee percentage (e.g., 0.02 for 2%)
#[serde(default = "default_ldk_fee_percent")]
Expand Down Expand Up @@ -437,6 +443,7 @@ fn default_keyset_version() -> String {

#[cfg(feature = "fakewallet")]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct FakeWallet {
pub supported_units: Vec<CurrencyUnit>,
pub fee_percent: f32,
Expand Down Expand Up @@ -487,6 +494,7 @@ fn default_max_delay_time() -> u64 {
}

#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
#[serde(default)]
pub struct GrpcProcessor {
#[serde(default)]
pub supported_units: Vec<CurrencyUnit>,
Expand Down Expand Up @@ -538,17 +546,20 @@ impl std::str::FromStr for DatabaseEngine {
}

#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(default)]
pub struct Database {
pub engine: DatabaseEngine,
pub postgres: Option<PostgresConfig>,
}

#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(default)]
pub struct AuthDatabase {
pub postgres: Option<PostgresAuthConfig>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct PostgresAuthConfig {
pub url: String,
pub tls_mode: Option<String>,
Expand All @@ -568,6 +579,7 @@ impl Default for PostgresAuthConfig {
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct PostgresConfig {
pub url: String,
pub tls_mode: Option<String>,
Expand Down Expand Up @@ -609,6 +621,7 @@ impl std::str::FromStr for AuthType {
}

#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(default)]
pub struct Auth {
#[serde(default)]
pub auth_enabled: bool,
Expand Down Expand Up @@ -644,6 +657,7 @@ fn default_blind() -> AuthType {

/// CDK settings, derived from `config.toml`
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(default)]
pub struct Settings {
pub info: Info,
pub mint_info: MintInfo,
Expand All @@ -668,11 +682,13 @@ pub struct Settings {
pub mint_management_rpc: Option<MintManagementRpc>,
pub auth: Option<Auth>,
#[cfg(feature = "prometheus")]
#[serde(default, skip_serializing_if = "Option::is_none")]
pub prometheus: Option<Prometheus>,
}

#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[cfg(feature = "prometheus")]
#[serde(default)]
pub struct Prometheus {
pub enabled: bool,
pub address: Option<String>,
Expand Down Expand Up @@ -708,6 +724,7 @@ fn default_max_outputs() -> usize {
}

#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(default)]
pub struct MintInfo {
/// name of the mint and should be recognizable
pub name: String,
Expand All @@ -731,6 +748,7 @@ pub struct MintInfo {

#[cfg(feature = "management-rpc")]
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(default)]
pub struct MintManagementRpc {
/// When this is set to `true` the mint use the config file for the initial set up on first start.
/// Changes to the `[mint_info]` after this **MUST** be made via the RPC changes to the config file or env vars will be ignored.
Expand All @@ -741,23 +759,30 @@ pub struct MintManagementRpc {
}

impl Settings {
pub fn try_new<P>(config_file_name: Option<P>) -> Result<Self, ConfigError>
where
P: Into<PathBuf>,
{
let default_settings = Self::default();
Self::new_from_default(&default_settings, config_file_name)
}

/// Loads settings from defaults and an optional config file.
///
/// Prefer [`Self::try_new`] in any code path that can surface a recoverable
/// config error; this constructor exists for callers that want a hard fail.
///
/// # Panics
///
/// Panics if the config file cannot be read or deserialized. Unlike earlier
/// versions, this never silently falls back to defaults — silent fallback
/// hid real misconfiguration.
#[must_use]
pub fn new<P>(config_file_name: Option<P>) -> Self
where
P: Into<PathBuf>,
{
let default_settings = Self::default();
// attempt to construct settings with file
let from_file = Self::new_from_default(&default_settings, config_file_name);
match from_file {
Ok(f) => f,
Err(e) => {
tracing::error!(
"Error reading config file, falling back to defaults. Error: {e:?}"
);
default_settings
}
}
Self::try_new(config_file_name).unwrap_or_else(|e| panic!("Error reading config file: {e}"))
}

fn new_from_default<P>(
Expand Down Expand Up @@ -865,6 +890,8 @@ mod tests {
/// This test runs sequentially for all enabled backends to avoid env var interference.
#[test]
fn test_env_var_only_config_all_backends() {
let _env_lock = crate::test_utils::env_lock();

// Run each backend test sequentially
#[cfg(feature = "lnd")]
test_lnd_env_config();
Expand Down Expand Up @@ -918,7 +945,7 @@ max_melt = 500000
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));
let mut settings = Settings::try_new(Some(&config_path)).expect("Failed to load config");
settings.from_env().expect("Failed to apply env vars");

// Verify that settings were populated from env vars
Expand Down Expand Up @@ -975,7 +1002,7 @@ max_melt = 500000
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));
let mut settings = Settings::try_new(Some(&config_path)).expect("Failed to load config");
settings.from_env().expect("Failed to apply env vars");

// Verify that settings were populated from env vars
Expand Down Expand Up @@ -1033,7 +1060,7 @@ max_melt = 500000
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));
let mut settings = Settings::try_new(Some(&config_path)).expect("Failed to load config");
settings.from_env().expect("Failed to apply env vars");

// Verify that settings were populated from env vars
Expand Down Expand Up @@ -1087,7 +1114,7 @@ max_melt = 500000
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));
let mut settings = Settings::try_new(Some(&config_path)).expect("Failed to load config");
settings.from_env().expect("Failed to apply env vars");

// Verify that settings were populated from env vars
Expand Down Expand Up @@ -1141,7 +1168,7 @@ max_melt = 500000
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));
let mut settings = Settings::try_new(Some(&config_path)).expect("Failed to load config");
settings.from_env().expect("Failed to apply env vars");

// Verify that settings were populated from env vars
Expand Down Expand Up @@ -1199,7 +1226,7 @@ max_melt = 500000
);

// Load settings and apply environment variables (same as production code)
let mut settings = Settings::new(Some(&config_path));
let mut settings = Settings::try_new(Some(&config_path)).expect("Failed to load config");
settings.from_env().expect("Failed to apply env vars");

// Verify that settings were populated from env vars
Expand Down
2 changes: 1 addition & 1 deletion crates/cdk-mintd/src/env_vars/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ impl Settings {
self.grpc_processor =
Some(self.grpc_processor.clone().unwrap_or_default().from_env());
}
LnBackend::None => bail!("Ln backend must be set"),
LnBackend::None => {}
#[allow(unreachable_patterns)]
_ => bail!("Selected Ln backend is not enabled in this build"),
}
Expand Down
Loading
Loading