fix: non sat amounts on melt (#839)

This commit is contained in:
thesimplekid
2025-06-25 14:08:00 +01:00
committed by GitHub
parent 4f4605df9e
commit 738202b957
10 changed files with 60 additions and 31 deletions

View File

@@ -201,6 +201,7 @@ impl MintPayment for Cln {
Ok(PaymentQuoteResponse {
request_lookup_id: bolt11.payment_hash().to_string(),
amount,
unit: unit.clone(),
fee: fee.into(),
state: MeltQuoteState::Unpaid,
})

View File

@@ -155,6 +155,8 @@ pub struct PaymentQuoteResponse {
pub amount: Amount,
/// Fee required for melt
pub fee: Amount,
/// Currency unit of `amount` and `fee`
pub unit: CurrencyUnit,
/// Status
pub state: MeltQuoteState,
}

View File

@@ -23,3 +23,4 @@ serde.workspace = true
serde_json.workspace = true
lightning-invoice.workspace = true
tokio-stream.workspace = true
reqwest.workspace = true

View File

@@ -29,6 +29,7 @@ use error::Error;
use futures::stream::StreamExt;
use futures::Stream;
use lightning_invoice::{Bolt11Invoice, Currency, InvoiceBuilder, PaymentSecret};
use reqwest::Client;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use tokio::sync::Mutex;
@@ -150,7 +151,27 @@ impl MintPayment for FakeWallet {
.into(),
};
let amount = to_unit(amount_msat, &CurrencyUnit::Msat, unit)?;
let amount = if unit != &CurrencyUnit::Sat && unit != &CurrencyUnit::Msat {
let client = Client::new();
let response: Value = client
.get("https://mempool.space/api/v1/prices")
.send()
.await
.map_err(|_| Error::UnknownInvoice)?
.json()
.await
.unwrap();
let price = response.get(unit.to_string().to_uppercase()).unwrap();
let bitcoin_amount = u64::from(amount_msat) as f64 / 100_000_000_000.0;
let total_price = price.as_f64().unwrap() * bitcoin_amount;
Amount::from((total_price * 100.0).ceil() as u64)
} else {
to_unit(amount_msat, &CurrencyUnit::Msat, unit)?
};
let relative_fee_reserve =
(self.fee_reserve.percent_fee_reserve * u64::from(amount) as f32) as u64;
@@ -163,6 +184,7 @@ impl MintPayment for FakeWallet {
request_lookup_id: bolt11.payment_hash().to_string(),
amount,
fee: fee.into(),
unit: unit.clone(),
state: MeltQuoteState::Unpaid,
})
}

View File

@@ -183,6 +183,7 @@ impl MintPayment for LNbits {
Ok(PaymentQuoteResponse {
request_lookup_id: bolt11.payment_hash().to_string(),
amount,
unit: unit.clone(),
fee: fee.into(),
state: MeltQuoteState::Unpaid,
})

View File

@@ -231,6 +231,7 @@ impl MintPayment for Lnd {
Ok(PaymentQuoteResponse {
request_lookup_id: bolt11.payment_hash().to_string(),
amount,
unit: unit.clone(),
fee: fee.into(),
state: MeltQuoteState::Unpaid,
})

View File

@@ -79,6 +79,7 @@ impl From<cdk_common::payment::PaymentQuoteResponse> for PaymentQuoteResponse {
amount: value.amount.into(),
fee: value.fee.into(),
state: QuoteState::from(value.state).into(),
unit: value.unit.to_string(),
}
}
}
@@ -121,6 +122,7 @@ impl From<PaymentQuoteResponse> for cdk_common::payment::PaymentQuoteResponse {
Self {
request_lookup_id: value.request_lookup_id.clone(),
amount: value.amount.into(),
unit: CurrencyUnit::from_str(&value.unit).unwrap_or_default(),
fee: value.fee.into(),
state: value.state().into(),
}

View File

@@ -68,6 +68,7 @@ message PaymentQuoteResponse {
uint64 amount = 2;
uint64 fee = 3;
QuoteState state = 4;
string unit = 5;
}
message MeltQuote {

View File

@@ -108,19 +108,6 @@ impl Mint {
..
} = melt_request;
let amount_msats = melt_request.amount_msat()?;
let amount_quote_unit = to_unit(amount_msats, &CurrencyUnit::Msat, unit)?;
self.check_melt_request_acceptable(
amount_quote_unit,
unit.clone(),
PaymentMethod::Bolt11,
request.to_string(),
*options,
)
.await?;
let ln = self
.ln
.get(&PaymentProcessorKey::new(
@@ -150,6 +137,15 @@ impl Mint {
Error::UnsupportedUnit
})?;
self.check_melt_request_acceptable(
payment_quote.amount,
unit.clone(),
PaymentMethod::Bolt11,
request.to_string(),
*options,
)
.await?;
// We only want to set the msats_to_pay of the melt quote if the invoice is amountless
// or we want to ignore the amount and do an mpp payment
let msats_to_pay = options.map(|opt| opt.amount_msat());
@@ -169,7 +165,7 @@ impl Mint {
tracing::debug!(
"New melt quote {} for {} {} with request id {}",
quote.id,
amount_quote_unit,
payment_quote.amount,
unit,
payment_quote.request_lookup_id
);

View File

@@ -50,20 +50,21 @@ impl Wallet {
) -> Result<MeltQuote, Error> {
let invoice = Bolt11Invoice::from_str(&request)?;
let amount_msat = options
.map(|opt| opt.amount_msat().into())
.or_else(|| invoice.amount_milli_satoshis())
.ok_or(Error::InvoiceAmountUndefined)?;
let amount_quote_unit = to_unit(amount_msat, &CurrencyUnit::Msat, &self.unit).unwrap();
let quote_request = MeltQuoteBolt11Request {
request: Bolt11Invoice::from_str(&request)?,
unit: self.unit.clone(),
options,
};
let quote_res = self.client.post_melt_quote(quote_request).await.unwrap();
let quote_res = self.client.post_melt_quote(quote_request).await?;
if self.unit == CurrencyUnit::Msat || self.unit == CurrencyUnit::Sat {
let amount_msat = options
.map(|opt| opt.amount_msat().into())
.or_else(|| invoice.amount_milli_satoshis())
.ok_or(Error::InvoiceAmountUndefined)?;
let amount_quote_unit = to_unit(amount_msat, &CurrencyUnit::Msat, &self.unit)?;
if quote_res.amount != amount_quote_unit {
tracing::warn!(
@@ -73,10 +74,11 @@ impl Wallet {
);
return Err(Error::IncorrectQuoteAmount);
}
}
let quote = MeltQuote {
id: quote_res.quote,
amount: amount_quote_unit,
amount: quote_res.amount,
request,
unit: self.unit.clone(),
fee_reserve: quote_res.fee_reserve,