diff --git a/crates/cdk-common/src/error.rs b/crates/cdk-common/src/error.rs index 6c2471c2..27b66676 100644 --- a/crates/cdk-common/src/error.rs +++ b/crates/cdk-common/src/error.rs @@ -2,6 +2,7 @@ use std::fmt; +use cashu::{CurrencyUnit, PaymentMethod}; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use serde_json::Value; use thiserror::Error; @@ -51,6 +52,12 @@ pub enum Error { /// Amountless Invoice Not supported #[error("Amount Less Invoice is not allowed")] AmountLessNotAllowed, + /// Multi-Part Internal Melt Quotes are not supported + #[error("Multi-Part Internal Melt Quotes are not supported")] + InternalMultiPartMeltQuote, + /// Multi-Part Payment not supported for unit and method + #[error("Multi-Part payment is not supported for unit `{0}` and method `{1}`")] + MppUnitMethodNotSupported(CurrencyUnit, PaymentMethod), // Mint Errors /// Minting is disabled diff --git a/crates/cdk/src/mint/melt.rs b/crates/cdk/src/mint/melt.rs index 064efdc6..ac55266a 100644 --- a/crates/cdk/src/mint/melt.rs +++ b/crates/cdk/src/mint/melt.rs @@ -3,6 +3,7 @@ use std::str::FromStr; use anyhow::bail; use cdk_common::nut00::ProofsMethods; +use cdk_common::MeltOptions; use lightning_invoice::Bolt11Invoice; use tracing::instrument; use uuid::Uuid; @@ -22,14 +23,17 @@ use crate::{cdk_lightning, Amount, Error}; impl Mint { #[instrument(skip_all)] - fn check_melt_request_acceptable( + async fn check_melt_request_acceptable( &self, amount: Amount, unit: CurrencyUnit, method: PaymentMethod, + request: String, + options: Option, ) -> Result<(), Error> { let mint_info = self.mint_info(); let nut05 = mint_info.nuts.nut05; + let nut15 = mint_info.nuts.nut15; if nut05.disabled { return Err(Error::MeltingDisabled); @@ -39,6 +43,22 @@ impl Mint { .get_settings(&unit, &method) .ok_or(Error::UnitUnsupported)?; + if matches!(options, Some(MeltOptions::Mpp { mpp: _ })) { + // Verify there is no corresponding mint quote. + // Otherwise a wallet is trying to pay someone internally, but + // with a multi-part quote. And that's just not possible. + if (self.localstore.get_mint_quote_by_request(&request).await?).is_some() { + return Err(Error::InternalMultiPartMeltQuote); + } + // Verify MPP is enabled for unit and method + if !nut15 + .methods + .into_iter() + .any(|m| m.method == method && m.unit == unit) + { + return Err(Error::MppUnitMethodNotSupported(unit, method)); + } + } let is_above_max = matches!(settings.max_amount, Some(max) if amount > max); let is_below_min = matches!(settings.min_amount, Some(min) if amount < min); match is_above_max || is_below_min { @@ -68,7 +88,14 @@ impl Mint { let amount_quote_unit = to_unit(amount_msats, &CurrencyUnit::Msat, unit)?; - self.check_melt_request_acceptable(amount_quote_unit, unit.clone(), PaymentMethod::Bolt11)?; + self.check_melt_request_acceptable( + amount_quote_unit, + unit.clone(), + PaymentMethod::Bolt11, + request.to_string(), + *options, + ) + .await?; let ln = self .ln