From 58864ea52a1a177160d2955cf90afa7229b0a4f0 Mon Sep 17 00:00:00 2001 From: thesimplekid Date: Wed, 6 Nov 2024 08:43:30 +0000 Subject: [PATCH] feat: add mint builder --- crates/cdk/src/mint/builder.rs | 217 +++++++++++++++++++++++++++++++++ crates/cdk/src/mint/mod.rs | 2 + 2 files changed, 219 insertions(+) create mode 100644 crates/cdk/src/mint/builder.rs diff --git a/crates/cdk/src/mint/builder.rs b/crates/cdk/src/mint/builder.rs new file mode 100644 index 00000000..07b6840e --- /dev/null +++ b/crates/cdk/src/mint/builder.rs @@ -0,0 +1,217 @@ +//! Mint Builder + +use std::{collections::HashMap, sync::Arc}; + +use anyhow::anyhow; + +use crate::{ + amount::Amount, + cdk_database::{self, MintDatabase}, + cdk_lightning::{self, MintLightning}, + mint::Mint, + nuts::{ + ContactInfo, CurrencyUnit, MeltMethodSettings, MintInfo, MintMethodSettings, MintVersion, + MppMethodSettings, PaymentMethod, + }, + types::{LnKey, QuoteTTL}, +}; + +/// Cashu Mint +#[derive(Default)] +pub struct MintBuilder { + /// Mint Url + mint_url: Option, + /// Mint Info + mint_info: MintInfo, + /// Mint Storage backend + localstore: Option + Send + Sync>>, + /// Ln backends for mint + ln: Option + Send + Sync>>>, + seed: Option>, + quote_ttl: Option, + supported_units: HashMap, +} + +impl MintBuilder { + /// New mint builder + pub fn new() -> MintBuilder { + MintBuilder::default() + } + + /// Set localstore + pub fn with_localstore( + mut self, + localstore: Arc + Send + Sync>, + ) -> MintBuilder { + self.localstore = Some(localstore); + self + } + + /// Set mint url + pub fn with_mint_url(mut self, mint_url: String) -> Self { + self.mint_url = Some(mint_url); + self + } + + /// Set seed + pub fn with_seed(mut self, seed: Vec) -> Self { + self.seed = Some(seed); + self + } + + /// Set name + pub fn with_name(mut self, name: String) -> Self { + self.mint_info.name = Some(name); + self + } + + /// Set icon url + pub fn with_icon_url(mut self, icon_url: String) -> Self { + self.mint_info.icon_url = Some(icon_url); + self + } + + /// Set icon url + pub fn with_motd(mut self, motd: String) -> Self { + self.mint_info.motd = Some(motd); + self + } + + /// Set description + pub fn with_description(mut self, description: String) -> Self { + self.mint_info.description = Some(description); + self + } + + /// Set long description + pub fn with_long_description(mut self, description: String) -> Self { + self.mint_info.description_long = Some(description); + self + } + + /// Set version + pub fn with_version(mut self, version: MintVersion) -> Self { + self.mint_info.version = Some(version); + self + } + + /// Set contact info + pub fn add_contact_info(mut self, contact_info: ContactInfo) -> Self { + let mut contacts = self.mint_info.contact.clone().unwrap_or_default(); + contacts.push(contact_info); + self.mint_info.contact = Some(contacts); + self + } + + /// Add ln backend + pub fn add_ln_backend( + mut self, + unit: CurrencyUnit, + method: PaymentMethod, + limits: MintMeltLimits, + ln_backend: Arc + Send + Sync>, + ) -> Self { + let ln_key = LnKey { + unit: unit.clone(), + method, + }; + + let mut ln = self.ln.unwrap_or_default(); + + let settings = ln_backend.get_settings(); + + if settings.mpp { + let mpp_settings = MppMethodSettings { + method, + unit: unit.clone(), + mpp: true, + }; + let mut mpp = self.mint_info.nuts.nut15.clone(); + + mpp.methods.push(mpp_settings); + + self.mint_info.nuts.nut15 = mpp; + } + + match method { + PaymentMethod::Bolt11 => { + let mint_method_settings = MintMethodSettings { + method, + unit: unit.clone(), + min_amount: Some(limits.mint_min), + max_amount: Some(limits.mint_max), + description: settings.invoice_description, + }; + + self.mint_info.nuts.nut04.methods.push(mint_method_settings); + self.mint_info.nuts.nut04.disabled = false; + + let melt_method_settings = MeltMethodSettings { + method, + unit, + min_amount: Some(limits.melt_min), + max_amount: Some(limits.melt_max), + }; + self.mint_info.nuts.nut05.methods.push(melt_method_settings); + self.mint_info.nuts.nut05.disabled = false; + } + } + + ln.insert(ln_key.clone(), ln_backend); + + let mut supported_units = self.supported_units.clone(); + + supported_units.insert(ln_key.unit, (0, 32)); + self.supported_units = supported_units; + + self.ln = Some(ln); + + self + } + + /// Set quote ttl + pub fn with_quote_ttl(mut self, mint_ttl: u64, melt_ttl: u64) -> Self { + let quote_ttl = QuoteTTL { mint_ttl, melt_ttl }; + + self.quote_ttl = Some(quote_ttl); + + self + } + + /// Set pubkey + pub fn with_pubkey(mut self, pubkey: crate::nuts::PublicKey) -> Self { + self.mint_info.pubkey = Some(pubkey); + + self + } + + /// Build mint + pub async fn build(&self) -> anyhow::Result { + Ok(Mint::new( + self.mint_url.as_ref().ok_or(anyhow!("Mint url not set"))?, + self.seed.as_ref().ok_or(anyhow!("Mint seed not set"))?, + self.mint_info.clone(), + self.quote_ttl.ok_or(anyhow!("Quote ttl not set"))?, + self.localstore + .clone() + .ok_or(anyhow!("Localstore not set"))?, + self.ln.clone().ok_or(anyhow!("Ln backends not set"))?, + self.supported_units.clone(), + HashMap::new(), + ) + .await?) + } +} + +/// Mint Melt Limits +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +pub struct MintMeltLimits { + /// Min mint amount + pub mint_min: Amount, + /// Max mint amount + pub mint_max: Amount, + /// Min melt amount + pub melt_min: Amount, + /// Max melt amount + pub melt_max: Amount, +} diff --git a/crates/cdk/src/mint/mod.rs b/crates/cdk/src/mint/mod.rs index 7cc3837c..7f41be09 100644 --- a/crates/cdk/src/mint/mod.rs +++ b/crates/cdk/src/mint/mod.rs @@ -23,6 +23,7 @@ use crate::types::{LnKey, QuoteTTL}; use crate::util::unix_time; use crate::Amount; +mod builder; mod check_spendable; mod info; mod keysets; @@ -31,6 +32,7 @@ mod mint_nut04; mod swap; pub mod types; +pub use builder::{MintBuilder, MintMeltLimits}; pub use types::{MeltQuote, MintQuote}; /// Cashu Mint