config.rs 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. use std::path::PathBuf;
  2. use cdk::nuts::{CurrencyUnit, PublicKey};
  3. use cdk::Amount;
  4. use config::{Config, ConfigError, File};
  5. use serde::{Deserialize, Serialize};
  6. #[derive(Debug, Clone, Serialize, Deserialize, Default)]
  7. pub struct Info {
  8. pub url: String,
  9. pub listen_host: String,
  10. pub listen_port: u16,
  11. pub mnemonic: String,
  12. pub seconds_quote_is_valid_for: Option<u64>,
  13. pub seconds_to_cache_requests_for: Option<u64>,
  14. pub seconds_to_extend_cache_by: Option<u64>,
  15. pub input_fee_ppk: Option<u64>,
  16. /// When this is set to true, the mint exposes a Swagger UI for it's API at
  17. /// `[listen_host]:[listen_port]/swagger-ui`
  18. ///
  19. /// This requires `mintd` was built with the `swagger` feature flag.
  20. pub enable_swagger_ui: Option<bool>,
  21. }
  22. #[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
  23. #[serde(rename_all = "lowercase")]
  24. pub enum LnBackend {
  25. #[default]
  26. Cln,
  27. Strike,
  28. LNbits,
  29. FakeWallet,
  30. Phoenixd,
  31. Lnd,
  32. }
  33. #[derive(Debug, Clone, Serialize, Deserialize)]
  34. pub struct Ln {
  35. pub ln_backend: LnBackend,
  36. pub invoice_description: Option<String>,
  37. pub min_mint: Amount,
  38. pub max_mint: Amount,
  39. pub min_melt: Amount,
  40. pub max_melt: Amount,
  41. }
  42. impl Default for Ln {
  43. fn default() -> Self {
  44. Ln {
  45. ln_backend: LnBackend::default(),
  46. invoice_description: None,
  47. min_mint: 1.into(),
  48. max_mint: 500_000.into(),
  49. min_melt: 1.into(),
  50. max_melt: 500_000.into(),
  51. }
  52. }
  53. }
  54. #[derive(Debug, Clone, Serialize, Deserialize, Default)]
  55. pub struct Strike {
  56. pub api_key: String,
  57. pub supported_units: Option<Vec<CurrencyUnit>>,
  58. }
  59. #[derive(Debug, Clone, Serialize, Deserialize, Default)]
  60. pub struct LNbits {
  61. pub admin_api_key: String,
  62. pub invoice_api_key: String,
  63. pub lnbits_api: String,
  64. pub fee_percent: f32,
  65. pub reserve_fee_min: Amount,
  66. }
  67. #[derive(Debug, Clone, Serialize, Deserialize, Default)]
  68. pub struct Cln {
  69. pub rpc_path: PathBuf,
  70. pub bolt12: bool,
  71. pub fee_percent: f32,
  72. pub reserve_fee_min: Amount,
  73. }
  74. #[derive(Debug, Clone, Serialize, Deserialize, Default)]
  75. pub struct Lnd {
  76. pub address: String,
  77. pub cert_file: PathBuf,
  78. pub macaroon_file: PathBuf,
  79. pub fee_percent: f32,
  80. pub reserve_fee_min: Amount,
  81. }
  82. #[derive(Debug, Clone, Serialize, Deserialize, Default)]
  83. pub struct Phoenixd {
  84. pub api_password: String,
  85. pub api_url: String,
  86. pub bolt12: bool,
  87. pub fee_percent: f32,
  88. pub reserve_fee_min: Amount,
  89. }
  90. #[derive(Debug, Clone, Serialize, Deserialize)]
  91. pub struct FakeWallet {
  92. pub supported_units: Vec<CurrencyUnit>,
  93. pub fee_percent: f32,
  94. pub reserve_fee_min: Amount,
  95. pub min_delay_time: u64,
  96. pub max_delay_time: u64,
  97. }
  98. impl Default for FakeWallet {
  99. fn default() -> Self {
  100. Self {
  101. supported_units: vec![CurrencyUnit::Sat],
  102. fee_percent: 0.02,
  103. reserve_fee_min: 2.into(),
  104. min_delay_time: 1,
  105. max_delay_time: 3,
  106. }
  107. }
  108. }
  109. #[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
  110. #[serde(rename_all = "lowercase")]
  111. pub enum DatabaseEngine {
  112. #[default]
  113. Sqlite,
  114. Redb,
  115. }
  116. #[derive(Debug, Clone, Serialize, Deserialize, Default)]
  117. pub struct Database {
  118. pub engine: DatabaseEngine,
  119. }
  120. /// CDK settings, derived from `config.toml`
  121. #[derive(Debug, Clone, Serialize, Deserialize, Default)]
  122. pub struct Settings {
  123. pub info: Info,
  124. pub mint_info: MintInfo,
  125. pub ln: Ln,
  126. pub cln: Option<Cln>,
  127. pub strike: Option<Strike>,
  128. pub lnbits: Option<LNbits>,
  129. pub phoenixd: Option<Phoenixd>,
  130. pub lnd: Option<Lnd>,
  131. pub fake_wallet: Option<FakeWallet>,
  132. pub database: Database,
  133. }
  134. #[derive(Debug, Clone, Serialize, Deserialize, Default)]
  135. pub struct MintInfo {
  136. /// name of the mint and should be recognizable
  137. pub name: String,
  138. /// hex pubkey of the mint
  139. pub pubkey: Option<PublicKey>,
  140. /// short description of the mint
  141. pub description: String,
  142. /// long description
  143. pub description_long: Option<String>,
  144. /// url to the mint icon
  145. pub icon_url: Option<String>,
  146. /// message of the day that the wallet must display to the user
  147. pub motd: Option<String>,
  148. /// Nostr publickey
  149. pub contact_nostr_public_key: Option<String>,
  150. /// Contact email
  151. pub contact_email: Option<String>,
  152. }
  153. impl Settings {
  154. #[must_use]
  155. pub fn new(config_file_name: &Option<PathBuf>) -> Self {
  156. let default_settings = Self::default();
  157. // attempt to construct settings with file
  158. let from_file = Self::new_from_default(&default_settings, config_file_name);
  159. match from_file {
  160. Ok(f) => f,
  161. Err(e) => {
  162. tracing::warn!("Error reading config file ({:?})", e);
  163. default_settings
  164. }
  165. }
  166. }
  167. fn new_from_default(
  168. default: &Settings,
  169. config_file_name: &Option<PathBuf>,
  170. ) -> Result<Self, ConfigError> {
  171. let mut default_config_file_name = home::home_dir()
  172. .ok_or(ConfigError::NotFound("Config Path".to_string()))?
  173. .join("cashu-rs-mint");
  174. default_config_file_name.push("config.toml");
  175. let config: String = match config_file_name {
  176. Some(value) => value.clone().to_string_lossy().to_string(),
  177. None => default_config_file_name.to_string_lossy().to_string(),
  178. };
  179. let builder = Config::builder();
  180. let config: Config = builder
  181. // use defaults
  182. .add_source(Config::try_from(default)?)
  183. // override with file contents
  184. .add_source(File::with_name(&config))
  185. .build()?;
  186. let settings: Settings = config.try_deserialize()?;
  187. match settings.ln.ln_backend {
  188. LnBackend::Cln => assert!(settings.cln.is_some()),
  189. LnBackend::Strike => assert!(settings.strike.is_some()),
  190. LnBackend::LNbits => assert!(settings.lnbits.is_some()),
  191. LnBackend::Phoenixd => assert!(settings.phoenixd.is_some()),
  192. LnBackend::Lnd => assert!(settings.lnd.is_some()),
  193. LnBackend::FakeWallet => (),
  194. }
  195. Ok(settings)
  196. }
  197. }