Skip to content

Commit

Permalink
feat: wait invoice response
Browse files Browse the repository at this point in the history
  • Loading branch information
thesimplekid committed Oct 30, 2024
1 parent 5f3b198 commit cbe72d9
Show file tree
Hide file tree
Showing 10 changed files with 92 additions and 30 deletions.
12 changes: 9 additions & 3 deletions crates/cdk-cln/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use async_trait::async_trait;
use cdk::amount::{amount_for_offer, to_unit, Amount};
use cdk::cdk_lightning::{
self, Bolt12PaymentQuoteResponse, CreateInvoiceResponse, CreateOfferResponse, MintLightning,
PayInvoiceResponse, PaymentQuoteResponse, Settings,
PayInvoiceResponse, PaymentQuoteResponse, Settings, WaitInvoiceResponse,
};
use cdk::mint::types::PaymentRequest;
use cdk::mint::FeeReserve;
Expand Down Expand Up @@ -105,7 +105,7 @@ impl MintLightning for Cln {
// Clippy thinks select is not stable but it compiles fine on MSRV (1.63.0)
async fn wait_any_invoice(
&self,
) -> Result<Pin<Box<dyn Stream<Item = (String, Amount)> + Send>>, Self::Err> {
) -> Result<Pin<Box<dyn Stream<Item = WaitInvoiceResponse> + Send>>, Self::Err> {
let last_pay_index = self.get_last_pay_index().await?;
let cln_client = cln_rpc::ClnRpc::new(&self.rpc_socket).await?;

Expand Down Expand Up @@ -197,7 +197,13 @@ impl MintLightning for Cln {
None => payment_hash,
};

break Some(((request_look_up, amount_sats.into()), (cln_client, last_pay_idx, cancel_token, is_active)));
let response = WaitInvoiceResponse {
payment_lookup_id: request_look_up,
payment_amount: amount_sats.into(),
unit: CurrencyUnit::Sat
};

break Some((response, (cln_client, last_pay_idx, cancel_token, is_active)));
}
Err(e) => {
tracing::warn!("Error fetching invoice: {e}");
Expand Down
11 changes: 8 additions & 3 deletions crates/cdk-fake-wallet/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use bitcoin::secp256k1::{Secp256k1, SecretKey};
use cdk::amount::{to_unit, Amount};
use cdk::cdk_lightning::{
self, Bolt12PaymentQuoteResponse, CreateInvoiceResponse, CreateOfferResponse, MintLightning,
PayInvoiceResponse, PaymentQuoteResponse, Settings,
PayInvoiceResponse, PaymentQuoteResponse, Settings, WaitInvoiceResponse,
};
use cdk::mint;
use cdk::mint::types::PaymentRequest;
Expand Down Expand Up @@ -122,11 +122,16 @@ impl MintLightning for FakeWallet {

async fn wait_any_invoice(
&self,
) -> Result<Pin<Box<dyn Stream<Item = (String, Amount)> + Send>>, Self::Err> {
) -> Result<Pin<Box<dyn Stream<Item = WaitInvoiceResponse> + Send>>, Self::Err> {
let receiver = self.receiver.lock().await.take().ok_or(Error::NoReceiver)?;
let receiver_stream = ReceiverStream::new(receiver);
self.wait_invoice_is_active.store(true, Ordering::SeqCst);
Ok(Box::pin(receiver_stream.map(|label| (label, Amount::ZERO))))

Ok(Box::pin(receiver_stream.map(|label| WaitInvoiceResponse {
payment_lookup_id: label,
payment_amount: Amount::ZERO,
unit: CurrencyUnit::Sat,
})))
}

async fn get_payment_quote(
Expand Down
10 changes: 8 additions & 2 deletions crates/cdk-integration-tests/tests/mint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use anyhow::{bail, Result};
use bip39::Mnemonic;
use cdk::amount::{Amount, SplitTarget};
use cdk::cdk_database::mint_memory::MintMemoryDatabase;
use cdk::cdk_lightning::WaitInvoiceResponse;
use cdk::dhke::construct_proofs;
use cdk::mint::MintQuote;
use cdk::nuts::{
Expand Down Expand Up @@ -79,8 +80,13 @@ async fn mint_proofs(

mint.localstore.add_mint_quote(quote.clone()).await?;

mint.pay_mint_quote_for_request_id(&request_lookup, amount)
.await?;
let wait_invoice = WaitInvoiceResponse {
payment_lookup_id: request_lookup,
payment_amount: amount,
unit: CurrencyUnit::Sat,
};

mint.pay_mint_quote_for_request_id(wait_invoice).await?;
let keyset_id = Id::from(&keys);

let premint = PreMintSecrets::random(keyset_id, amount, split_target)?;
Expand Down
12 changes: 9 additions & 3 deletions crates/cdk-lnbits/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use axum::Router;
use cdk::amount::{to_unit, Amount, MSAT_IN_SAT};
use cdk::cdk_lightning::{
self, Bolt12PaymentQuoteResponse, CreateInvoiceResponse, CreateOfferResponse, MintLightning,
PayInvoiceResponse, PaymentQuoteResponse, Settings,
PayInvoiceResponse, PaymentQuoteResponse, Settings, WaitInvoiceResponse,
};
use cdk::mint::types::PaymentRequest;
use cdk::mint::FeeReserve;
Expand Down Expand Up @@ -92,7 +92,7 @@ impl MintLightning for LNbits {
#[allow(clippy::incompatible_msrv)]
async fn wait_any_invoice(
&self,
) -> Result<Pin<Box<dyn Stream<Item = (String, Amount)> + Send>>, Self::Err> {
) -> Result<Pin<Box<dyn Stream<Item = WaitInvoiceResponse> + Send>>, Self::Err> {
let receiver = self
.receiver
.lock()
Expand Down Expand Up @@ -129,7 +129,13 @@ impl MintLightning for LNbits {
match check {
Ok(state) => {
if state {
Some(((msg, Amount::ZERO), (receiver, lnbits_api, cancel_token, is_active)))
let response = WaitInvoiceResponse {
payment_lookup_id: msg,
payment_amount: Amount::ZERO,
unit: CurrencyUnit::Sat
};

Some((response , (receiver, lnbits_api, cancel_token, is_active)))
} else {
None
}
Expand Down
13 changes: 10 additions & 3 deletions crates/cdk-lnd/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use async_trait::async_trait;
use cdk::amount::{to_unit, Amount, MSAT_IN_SAT};
use cdk::cdk_lightning::{
self, Bolt12PaymentQuoteResponse, CreateInvoiceResponse, CreateOfferResponse, MintLightning,
PayInvoiceResponse, PaymentQuoteResponse, Settings,
PayInvoiceResponse, PaymentQuoteResponse, Settings, WaitInvoiceResponse,
};
use cdk::mint::types::PaymentRequest;
use cdk::mint::FeeReserve;
Expand Down Expand Up @@ -99,7 +99,7 @@ impl MintLightning for Lnd {

async fn wait_any_invoice(
&self,
) -> Result<Pin<Box<dyn Stream<Item = (String, Amount)> + Send>>, Self::Err> {
) -> Result<Pin<Box<dyn Stream<Item = WaitInvoiceResponse> + Send>>, Self::Err> {
let mut client =
fedimint_tonic_lnd::connect(self.address.clone(), &self.cert_file, &self.macaroon_file)
.await
Expand Down Expand Up @@ -141,7 +141,14 @@ impl MintLightning for Lnd {
match msg {
Ok(Some(msg)) => {
if msg.state == 1 {
Some(((hex::encode(msg.r_hash), Amount::ZERO), (stream, cancel_token, is_active)))
let wait_response = WaitInvoiceResponse {
payment_lookup_id: hex::encode(msg.r_hash),
payment_amount: Amount::ZERO,
unit: CurrencyUnit::Sat

};

Some((wait_response , (stream, cancel_token, is_active)))
} else {
None
}
Expand Down
11 changes: 8 additions & 3 deletions crates/cdk-phoenixd/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use axum::Router;
use cdk::amount::{amount_for_offer, to_unit, Amount};
use cdk::cdk_lightning::{
self, Bolt12PaymentQuoteResponse, CreateInvoiceResponse, CreateOfferResponse, MintLightning,
PayInvoiceResponse, PaymentQuoteResponse, Settings,
PayInvoiceResponse, PaymentQuoteResponse, Settings, WaitInvoiceResponse,
};
use cdk::mint::types::PaymentRequest;
use cdk::mint::FeeReserve;
Expand Down Expand Up @@ -101,7 +101,7 @@ impl MintLightning for Phoenixd {
#[allow(clippy::incompatible_msrv)]
async fn wait_any_invoice(
&self,
) -> Result<Pin<Box<dyn Stream<Item = (String, Amount)> + Send>>, Self::Err> {
) -> Result<Pin<Box<dyn Stream<Item = WaitInvoiceResponse> + Send>>, Self::Err> {
let receiver = self
.receiver
.lock()
Expand Down Expand Up @@ -135,8 +135,13 @@ impl MintLightning for Phoenixd {
match check {
Ok(state) => {
if state.is_paid {
let wait_invoice = WaitInvoiceResponse {
payment_lookup_id: msg.payment_hash,
payment_amount: Amount::ZERO,
unit: CurrencyUnit::Sat
};
// Yield the payment hash and continue the stream
Some(((msg.payment_hash, Amount::ZERO), (receiver, phoenixd_api, cancel_token, is_active)))
Some((wait_invoice, (receiver, phoenixd_api, cancel_token, is_active)))
} else {
// Invoice not paid yet, continue waiting
// We need to continue the stream, so we return the same state
Expand Down
15 changes: 11 additions & 4 deletions crates/cdk-strike/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use axum::Router;
use cdk::amount::Amount;
use cdk::cdk_lightning::{
self, Bolt12PaymentQuoteResponse, CreateInvoiceResponse, CreateOfferResponse, MintLightning,
PayInvoiceResponse, PaymentQuoteResponse, Settings,
PayInvoiceResponse, PaymentQuoteResponse, Settings, WaitInvoiceResponse,
};
use cdk::nuts::{
CurrencyUnit, MeltQuoteBolt11Request, MeltQuoteBolt12Request, MeltQuoteState, MintQuoteState,
Expand Down Expand Up @@ -89,7 +89,7 @@ impl MintLightning for Strike {
#[allow(clippy::incompatible_msrv)]
async fn wait_any_invoice(
&self,
) -> Result<Pin<Box<dyn Stream<Item = (String, Amount)> + Send>>, Self::Err> {
) -> Result<Pin<Box<dyn Stream<Item = WaitInvoiceResponse> + Send>>, Self::Err> {
self.strike_api
.subscribe_to_invoice_webhook(self.webhook_url.clone())
.await?;
Expand All @@ -103,15 +103,17 @@ impl MintLightning for Strike {

let strike_api = self.strike_api.clone();
let cancel_token = self.wait_invoice_cancel_token.clone();
let unit = self.unit.clone();

Ok(futures::stream::unfold(
(
receiver,
strike_api,
cancel_token,
Arc::clone(&self.wait_invoice_is_active),
unit
),
|(mut receiver, strike_api, cancel_token, is_active)| async move {
|(mut receiver, strike_api, cancel_token, is_active, unit)| async move {
tokio::select! {

_ = cancel_token.cancelled() => {
Expand All @@ -129,7 +131,12 @@ impl MintLightning for Strike {
match check {
Ok(state) => {
if state.state == InvoiceState::Paid {
Some(((msg, Amount::ZERO), (receiver, strike_api, cancel_token, is_active)))
let wait_response = WaitInvoiceResponse {
payment_lookup_id: msg,
payment_amount: Amount::ZERO,
unit
};
Some((wait_response , (receiver, strike_api, cancel_token, is_active, unit)))
} else {
None
}
Expand Down
13 changes: 12 additions & 1 deletion crates/cdk/src/cdk_lightning/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,17 @@ pub enum Error {
Amount(#[from] crate::amount::Error),
}

/// Wait any invoice response
#[derive(Debug, Clone, Hash, Serialize, Deserialize, Default)]
pub struct WaitInvoiceResponse {
/// Payment look up id
pub payment_lookup_id: String,
/// Payment amount
pub payment_amount: Amount,
/// Unit
pub unit: CurrencyUnit,
}

/// MintLighting Trait
#[async_trait]
pub trait MintLightning {
Expand Down Expand Up @@ -88,7 +99,7 @@ pub trait MintLightning {
/// Returns a stream of request_lookup_id once invoices are paid
async fn wait_any_invoice(
&self,
) -> Result<Pin<Box<dyn Stream<Item = (String, Amount)> + Send>>, Self::Err>;
) -> Result<Pin<Box<dyn Stream<Item = WaitInvoiceResponse> + Send>>, Self::Err>;

/// Is wait invoice active
fn is_wait_invoice_active(&self) -> bool;
Expand Down
21 changes: 15 additions & 6 deletions crates/cdk/src/mint/mint_nut04.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use tracing::instrument;

use crate::{nuts::MintQuoteState, types::LnKey, util::unix_time, Amount, Error};
use crate::{
cdk_lightning::WaitInvoiceResponse, nuts::MintQuoteState, types::LnKey, util::unix_time,
Amount, Error,
};

use super::{
nut04, CurrencyUnit, Mint, MintQuote, MintQuoteBolt11Request, MintQuoteBolt11Response,
Expand Down Expand Up @@ -193,18 +196,22 @@ impl Mint {
#[instrument(skip_all)]
pub async fn pay_mint_quote_for_request_id(
&self,
request_lookup_id: &str,
amount: Amount,
wait_invoice_response: WaitInvoiceResponse,
) -> Result<(), Error> {
let WaitInvoiceResponse {
payment_lookup_id,
payment_amount,
unit,
} = wait_invoice_response;
if let Ok(Some(mint_quote)) = self
.localstore
.get_mint_quote_by_request_lookup_id(request_lookup_id)
.get_mint_quote_by_request_lookup_id(&payment_lookup_id)
.await
{
tracing::debug!(
"Quote {} paid by lookup id {}",
mint_quote.id,
request_lookup_id
payment_lookup_id
);
self.localstore
.update_mint_quote_state(&mint_quote.id, MintQuoteState::Paid)
Expand All @@ -215,7 +222,9 @@ impl Mint {
.await?
.unwrap();

let amount_paid = quote.amount_paid + amount;
let amount_paid = quote.amount_paid + payment_amount;

assert!(unit == quote.unit);

let quote = MintQuote {
id: quote.id,
Expand Down
4 changes: 2 additions & 2 deletions crates/cdk/src/mint/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,8 +209,8 @@ impl Mint {
result = ln.wait_any_invoice() => {
match result {
Ok(mut stream) => {
while let Some(request_lookup_id) = stream.next().await {
if let Err(err) = mint.pay_mint_quote_for_request_id(&request_lookup_id.0, request_lookup_id.1).await {
while let Some(wait_invoice_response) = stream.next().await {
if let Err(err) = mint.pay_mint_quote_for_request_id(wait_invoice_response).await {
tracing::warn!("{:?}", err);
}
}
Expand Down

0 comments on commit cbe72d9

Please sign in to comment.