diff --git a/crates/cdk/src/mint/melt.rs b/crates/cdk/src/mint/melt.rs index 8d2ddc06..10307915 100644 --- a/crates/cdk/src/mint/melt.rs +++ b/crates/cdk/src/mint/melt.rs @@ -62,17 +62,7 @@ impl Mint { options: _, } = melt_request; - let amount = match melt_request.options { - Some(mpp_amount) => mpp_amount.amount, - None => { - let amount_msat = request - .amount_milli_satoshis() - .ok_or(Error::InvoiceAmountUndefined)?; - - to_unit(amount_msat, &CurrencyUnit::Msat, unit) - .map_err(|_err| Error::UnsupportedUnit)? - } - }; + let amount = melt_request.amount_msat()?; self.check_melt_request_acceptable(amount, unit.clone(), PaymentMethod::Bolt11)?; diff --git a/crates/cdk/src/nuts/nut05.rs b/crates/cdk/src/nuts/nut05.rs index bd2b5af5..22c7fb34 100644 --- a/crates/cdk/src/nuts/nut05.rs +++ b/crates/cdk/src/nuts/nut05.rs @@ -28,6 +28,12 @@ pub enum Error { /// Amount overflow #[error("Amount Overflow")] AmountOverflow, + /// Invalid Amount + #[error("Invalid Request")] + InvalidAmountRequest, + /// Unsupported unit + #[error("Unsupported unit")] + UnsupportedUnit, } /// Melt quote request [NUT-05] @@ -40,7 +46,39 @@ pub struct MeltQuoteBolt11Request { /// Unit wallet would like to pay with pub unit: CurrencyUnit, /// Payment Options - pub options: Option, + pub options: Option, +} + +/// Options for Melt Request +#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "lowercase", untagged)] +pub enum Options { + /// Multi partpayment option + Mpp { + /// mpp + mpp: Mpp, + }, +} + +impl Options { + /// Create new [`Options::Mpp`] + pub fn new_mpp(amount: A) -> Self + where + A: Into, + { + Self::Mpp { + mpp: Mpp { + amount: amount.into(), + }, + } + } + + /// Payment amount + pub fn amount_msat(&self) -> Amount { + match self { + Self::Mpp { mpp } => mpp.amount, + } + } } /// Possible states of a quote @@ -280,6 +318,29 @@ pub struct MeltBolt11Request { pub outputs: Option>, } +impl MeltQuoteBolt11Request { + /// Amount from [`MeltQuoteBolt11Request`] + /// + /// Amount can either be defined in the bolt11 invoice, + /// in the request for an amountless bolt11 or in MPP option. + pub fn amount_msat(&self) -> Result { + let MeltQuoteBolt11Request { + request, + unit: _, + options, + .. + } = self; + + match options { + None => Ok(request + .amount_milli_satoshis() + .ok_or(Error::InvalidAmountRequest)? + .into()), + Some(Options::Mpp { mpp }) => Ok(mpp.amount), + } + } +} + #[cfg(feature = "mint")] impl TryFrom> for MeltBolt11Request { type Error = uuid::Error; @@ -364,3 +425,18 @@ impl Default for Settings { } } } + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn test_melt_request_mpp_deser() { + let melt: MeltQuoteBolt11Request = serde_json::from_str( + r#"{"request":"lntbs200n1pnhsp43pp5ysnjp6uwqpmyv25qccwrgj2zah50ce66027pqcc8jpqp9tap8gushp57t8sp5tcchfv0y29yg46nqujktk2ufwcjcc7zvyd8rteadd7rjyscqzzsxqyz5vqrzjq0w0f29u6f7yrrpr5y6wj45gtnyhtch9u2m2j7qrws8eevrw90c72pqnycqq0agqquzltcgqqqqqqqqqfqsp5akuep6uk00wdm4qm5t0jln3tjc98maruwt04rnwqaxryxux2nngq9p4gqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpqysgqjt60cck80lumnzteyd997xqhwjlvfnr4j3k0weukshgqafq244mq9jcgcw6s74a0hxdu4xlkr6zhp5fdf0fuz3urk7t003srfusa54qqxcft2g","unit":"sat","options":{"mpp":{"amount":19}}}"#, + ).unwrap(); + + println!("{:?}", melt); + } +} diff --git a/crates/cdk/src/wallet/melt.rs b/crates/cdk/src/wallet/melt.rs index 8e1910e0..57915197 100644 --- a/crates/cdk/src/wallet/melt.rs +++ b/crates/cdk/src/wallet/melt.rs @@ -6,8 +6,9 @@ use tracing::instrument; use super::MeltQuote; use crate::dhke::construct_proofs; use crate::nuts::nut00::ProofsMethods; +use crate::nuts::nut05::Options; use crate::nuts::{ - CurrencyUnit, MeltBolt11Request, MeltQuoteBolt11Request, MeltQuoteBolt11Response, Mpp, + CurrencyUnit, MeltBolt11Request, MeltQuoteBolt11Request, MeltQuoteBolt11Response, PreMintSecrets, Proofs, State, }; use crate::types::{Melted, ProofInfo}; @@ -43,7 +44,7 @@ impl Wallet { pub async fn melt_quote( &self, request: String, - mpp: Option, + options: Option, ) -> Result { let invoice = Bolt11Invoice::from_str(&request)?; @@ -57,8 +58,6 @@ impl Wallet { _ => return Err(Error::UnitUnsupported), }; - let options = mpp.map(|amount| Mpp { amount }); - let quote_request = MeltQuoteBolt11Request { request: Bolt11Invoice::from_str(&request)?, unit: self.unit.clone(),