Merge pull request #963 from crodas/feature/wait-for-invoice

Add `wait_for_payment` function in the wallet
This commit is contained in:
C
2025-08-18 08:57:45 -03:00
committed by GitHub
parent da21ce655a
commit f8d58e419f
18 changed files with 299 additions and 301 deletions

View File

@@ -111,6 +111,10 @@ pub enum Error {
#[error("Could not parse bolt12")] #[error("Could not parse bolt12")]
Bolt12parse, Bolt12parse,
/// Operation timeout
#[error("Operation timeout")]
Timeout,
/// Internal Error - Send error /// Internal Error - Send error
#[error("Internal send error: {0}")] #[error("Internal send error: {0}")]
SendError(String), SendError(String),

View File

@@ -3,6 +3,7 @@ use std::fmt::{Debug, Formatter};
use std::path::PathBuf; use std::path::PathBuf;
use std::str::FromStr; use std::str::FromStr;
use std::sync::Arc; use std::sync::Arc;
use std::time::Duration;
use std::{env, fs}; use std::{env, fs};
use anyhow::{anyhow, bail, Result}; use anyhow::{anyhow, bail, Result};
@@ -28,8 +29,6 @@ use tokio::sync::RwLock;
use tracing_subscriber::EnvFilter; use tracing_subscriber::EnvFilter;
use uuid::Uuid; use uuid::Uuid;
use crate::wait_for_mint_to_be_paid;
pub struct DirectMintConnection { pub struct DirectMintConnection {
pub mint: Mint, pub mint: Mint,
auth_wallet: Arc<RwLock<Option<AuthWallet>>>, auth_wallet: Arc<RwLock<Option<AuthWallet>>>,
@@ -362,7 +361,9 @@ pub async fn fund_wallet(
let desired_amount = Amount::from(amount); let desired_amount = Amount::from(amount);
let quote = wallet.mint_quote(desired_amount, None).await?; let quote = wallet.mint_quote(desired_amount, None).await?;
wait_for_mint_to_be_paid(&wallet, &quote.id, 60).await?; wallet
.wait_for_payment(&quote, Duration::from_secs(60))
.await?;
Ok(wallet Ok(wallet
.mint(&quote.id, split_target.unwrap_or_default(), None) .mint(&quote.id, split_target.unwrap_or_default(), None)

View File

@@ -21,15 +21,14 @@ use std::path::Path;
use std::sync::Arc; use std::sync::Arc;
use anyhow::{anyhow, bail, Result}; use anyhow::{anyhow, bail, Result};
use cashu::{Bolt11Invoice, PaymentMethod}; use cashu::Bolt11Invoice;
use cdk::amount::{Amount, SplitTarget}; use cdk::amount::{Amount, SplitTarget};
use cdk::nuts::{MintQuoteState, NotificationPayload, State}; use cdk::nuts::State;
use cdk::wallet::WalletSubscription;
use cdk::Wallet; use cdk::Wallet;
use cdk_fake_wallet::create_fake_invoice; use cdk_fake_wallet::create_fake_invoice;
use init_regtest::{get_lnd_dir, LND_RPC_ADDR}; use init_regtest::{get_lnd_dir, LND_RPC_ADDR};
use ln_regtest_rs::ln_client::{LightningClient, LndClient}; use ln_regtest_rs::ln_client::{LightningClient, LndClient};
use tokio::time::{sleep, timeout, Duration}; use tokio::time::Duration;
pub mod cli; pub mod cli;
pub mod init_auth_mint; pub mod init_auth_mint;
@@ -43,9 +42,10 @@ pub async fn fund_wallet(wallet: Arc<Wallet>, amount: Amount) {
.await .await
.expect("Could not get mint quote"); .expect("Could not get mint quote");
wait_for_mint_to_be_paid(&wallet, &quote.id, 60) wallet
.wait_for_payment(&quote, Duration::from_secs(60))
.await .await
.expect("Waiting for mint failed"); .expect("wait for mint failed");
let _proofs = wallet let _proofs = wallet
.mint(&quote.id, SplitTarget::default(), None) .mint(&quote.id, SplitTarget::default(), None)
@@ -104,88 +104,6 @@ pub async fn attempt_to_swap_pending(wallet: &Wallet) -> Result<()> {
Ok(()) Ok(())
} }
pub async fn wait_for_mint_to_be_paid(
wallet: &Wallet,
mint_quote_id: &str,
timeout_secs: u64,
) -> Result<()> {
let mut subscription = wallet
.subscribe(WalletSubscription::Bolt11MintQuoteState(vec![
mint_quote_id.to_owned(),
]))
.await;
// Create the timeout future
let wait_future = async {
while let Some(msg) = subscription.recv().await {
if let NotificationPayload::MintQuoteBolt11Response(response) = msg {
if response.state == MintQuoteState::Paid {
return Ok(());
}
} else if let NotificationPayload::MintQuoteBolt12Response(response) = msg {
if response.amount_paid > Amount::ZERO {
return Ok(());
}
}
}
Err(anyhow!("Subscription ended without quote being paid"))
};
let timeout_future = timeout(Duration::from_secs(timeout_secs), wait_future);
let check_interval = Duration::from_secs(5);
let method = wallet
.localstore
.get_mint_quote(mint_quote_id)
.await?
.map(|q| q.payment_method)
.unwrap_or_default();
let periodic_task = async {
loop {
match method {
PaymentMethod::Bolt11 => match wallet.mint_quote_state(mint_quote_id).await {
Ok(result) => {
if result.state == MintQuoteState::Paid {
tracing::info!("mint quote paid via poll");
return Ok(());
}
}
Err(e) => {
tracing::error!("Could not check mint quote status: {:?}", e);
}
},
PaymentMethod::Bolt12 => {
match wallet.mint_bolt12_quote_state(mint_quote_id).await {
Ok(result) => {
if result.amount_paid > Amount::ZERO {
return Ok(());
}
}
Err(e) => {
tracing::error!("Could not check mint quote status: {:?}", e);
}
}
}
PaymentMethod::Custom(_) => (),
}
sleep(check_interval).await;
}
};
tokio::select! {
result = timeout_future => {
match result {
Ok(payment_result) => payment_result,
Err(_) => Err(anyhow!("Timeout waiting for mint quote ({}) to be paid", mint_quote_id)),
}
}
result = periodic_task => {
result // Now propagates the result from periodic checks
}
}
}
// This is the ln wallet we use to send/receive ln payements as the wallet // This is the ln wallet we use to send/receive ln payements as the wallet
pub async fn init_lnd_client(work_dir: &Path) -> LndClient { pub async fn init_lnd_client(work_dir: &Path) -> LndClient {
let lnd_dir = get_lnd_dir(work_dir, "one"); let lnd_dir = get_lnd_dir(work_dir, "one");

View File

@@ -1,6 +1,7 @@
use std::env; use std::env;
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::Arc; use std::sync::Arc;
use std::time::Duration;
use anyhow::{bail, Result}; use anyhow::{bail, Result};
use bip39::Mnemonic; use bip39::Mnemonic;
@@ -8,8 +9,8 @@ use cashu::amount::SplitTarget;
use cashu::nut23::Amountless; use cashu::nut23::Amountless;
use cashu::{Amount, CurrencyUnit, MintRequest, PreMintSecrets, ProofsMethods}; use cashu::{Amount, CurrencyUnit, MintRequest, PreMintSecrets, ProofsMethods};
use cdk::wallet::{HttpClient, MintConnector, Wallet}; use cdk::wallet::{HttpClient, MintConnector, Wallet};
use cdk_integration_tests::get_mint_url_from_env;
use cdk_integration_tests::init_regtest::{get_cln_dir, get_temp_dir}; use cdk_integration_tests::init_regtest::{get_cln_dir, get_temp_dir};
use cdk_integration_tests::{get_mint_url_from_env, wait_for_mint_to_be_paid};
use cdk_sqlite::wallet::memory; use cdk_sqlite::wallet::memory;
use ln_regtest_rs::ln_client::ClnClient; use ln_regtest_rs::ln_client::ClnClient;
@@ -115,7 +116,9 @@ async fn test_regtest_bolt12_mint_multiple() -> Result<()> {
.await .await
.unwrap(); .unwrap();
wait_for_mint_to_be_paid(&wallet, &mint_quote.id, 60).await?; wallet
.wait_for_payment(&mint_quote, Duration::from_secs(60))
.await?;
wallet.mint_bolt12_quote_state(&mint_quote.id).await?; wallet.mint_bolt12_quote_state(&mint_quote.id).await?;
@@ -127,11 +130,13 @@ async fn test_regtest_bolt12_mint_multiple() -> Result<()> {
assert_eq!(proofs.total_amount().unwrap(), 10.into()); assert_eq!(proofs.total_amount().unwrap(), 10.into());
cln_client cln_client
.pay_bolt12_offer(Some(11_000), mint_quote.request) .pay_bolt12_offer(Some(11_000), mint_quote.request.clone())
.await .await
.unwrap(); .unwrap();
wait_for_mint_to_be_paid(&wallet, &mint_quote.id, 60).await?; wallet
.wait_for_payment(&mint_quote, Duration::from_secs(60))
.await?;
wallet.mint_bolt12_quote_state(&mint_quote.id).await?; wallet.mint_bolt12_quote_state(&mint_quote.id).await?;
@@ -181,7 +186,11 @@ async fn test_regtest_bolt12_multiple_wallets() -> Result<()> {
cln_client cln_client
.pay_bolt12_offer(None, quote_one.request.clone()) .pay_bolt12_offer(None, quote_one.request.clone())
.await?; .await?;
wait_for_mint_to_be_paid(&wallet_one, &quote_one.id, 60).await?;
wallet_one
.wait_for_payment(&quote_one, Duration::from_secs(60))
.await?;
let proofs_one = wallet_one let proofs_one = wallet_one
.mint_bolt12(&quote_one.id, None, SplitTarget::default(), None) .mint_bolt12(&quote_one.id, None, SplitTarget::default(), None)
.await?; .await?;
@@ -195,7 +204,10 @@ async fn test_regtest_bolt12_multiple_wallets() -> Result<()> {
cln_client cln_client
.pay_bolt12_offer(None, quote_two.request.clone()) .pay_bolt12_offer(None, quote_two.request.clone())
.await?; .await?;
wait_for_mint_to_be_paid(&wallet_two, &quote_two.id, 60).await?;
wallet_two
.wait_for_payment(&quote_two, Duration::from_secs(60))
.await?;
let proofs_two = wallet_two let proofs_two = wallet_two
.mint_bolt12(&quote_two.id, None, SplitTarget::default(), None) .mint_bolt12(&quote_two.id, None, SplitTarget::default(), None)
@@ -271,7 +283,9 @@ async fn test_regtest_bolt12_melt() -> Result<()> {
.await?; .await?;
// Wait for payment to be processed // Wait for payment to be processed
wait_for_mint_to_be_paid(&wallet, &mint_quote.id, 60).await?; wallet
.wait_for_payment(&mint_quote, Duration::from_secs(60))
.await?;
let offer = cln_client let offer = cln_client
.get_bolt12_offer(Some(10_000), true, "hhhhhhhh".to_string()) .get_bolt12_offer(Some(10_000), true, "hhhhhhhh".to_string())
@@ -330,7 +344,9 @@ async fn test_regtest_bolt12_mint_extra() -> Result<()> {
.pay_bolt12_offer(Some(pay_amount_msats), mint_quote.request.clone()) .pay_bolt12_offer(Some(pay_amount_msats), mint_quote.request.clone())
.await?; .await?;
wait_for_mint_to_be_paid(&wallet, &mint_quote.id, 10).await?; wallet
.wait_for_payment(&mint_quote, Duration::from_secs(10))
.await?;
let state = wallet.mint_bolt12_quote_state(&mint_quote.id).await?; let state = wallet.mint_bolt12_quote_state(&mint_quote.id).await?;

View File

@@ -1,6 +1,7 @@
use std::env; use std::env;
use std::str::FromStr; use std::str::FromStr;
use std::sync::Arc; use std::sync::Arc;
use std::time::Duration;
use bip39::Mnemonic; use bip39::Mnemonic;
use cashu::{MintAuthRequest, MintInfo}; use cashu::{MintAuthRequest, MintInfo};
@@ -15,7 +16,7 @@ use cdk::nuts::{
use cdk::wallet::{AuthHttpClient, AuthMintConnector, HttpClient, MintConnector, WalletBuilder}; use cdk::wallet::{AuthHttpClient, AuthMintConnector, HttpClient, MintConnector, WalletBuilder};
use cdk::{Error, OidcClient}; use cdk::{Error, OidcClient};
use cdk_fake_wallet::create_fake_invoice; use cdk_fake_wallet::create_fake_invoice;
use cdk_integration_tests::{fund_wallet, wait_for_mint_to_be_paid}; use cdk_integration_tests::fund_wallet;
use cdk_sqlite::wallet::memory; use cdk_sqlite::wallet::memory;
const MINT_URL: &str = "http://127.0.0.1:8087"; const MINT_URL: &str = "http://127.0.0.1:8087";
@@ -329,19 +330,12 @@ async fn test_mint_with_auth() {
let mint_amount: Amount = 100.into(); let mint_amount: Amount = 100.into();
let mint_quote = wallet let (_, proofs) = wallet
.mint_quote(mint_amount, None) .mint_once_paid(mint_amount, None, Duration::from_secs(10))
.await .await
.expect("failed to get mint quote"); .unwrap();
wait_for_mint_to_be_paid(&wallet, &mint_quote.id, 60) let proofs = proofs.await.expect("could not mint");
.await
.expect("failed to wait for payment");
let proofs = wallet
.mint(&mint_quote.id, SplitTarget::default(), None)
.await
.expect("could not mint");
assert!(proofs.total_amount().expect("Could not get proofs amount") == mint_amount); assert!(proofs.total_amount().expect("Could not get proofs amount") == mint_amount);
} }

View File

@@ -15,6 +15,7 @@
//! - Duplicate proof detection //! - Duplicate proof detection
use std::sync::Arc; use std::sync::Arc;
use std::time::Duration;
use bip39::Mnemonic; use bip39::Mnemonic;
use cashu::Amount; use cashu::Amount;
@@ -27,7 +28,7 @@ use cdk::nuts::{
use cdk::wallet::types::TransactionDirection; use cdk::wallet::types::TransactionDirection;
use cdk::wallet::{HttpClient, MintConnector, Wallet}; use cdk::wallet::{HttpClient, MintConnector, Wallet};
use cdk_fake_wallet::{create_fake_invoice, FakeInvoiceDescription}; use cdk_fake_wallet::{create_fake_invoice, FakeInvoiceDescription};
use cdk_integration_tests::{attempt_to_swap_pending, wait_for_mint_to_be_paid}; use cdk_integration_tests::attempt_to_swap_pending;
use cdk_sqlite::wallet::memory; use cdk_sqlite::wallet::memory;
const MINT_URL: &str = "http://127.0.0.1:8086"; const MINT_URL: &str = "http://127.0.0.1:8086";
@@ -46,7 +47,8 @@ async fn test_fake_tokens_pending() {
let mint_quote = wallet.mint_quote(100.into(), None).await.unwrap(); let mint_quote = wallet.mint_quote(100.into(), None).await.unwrap();
wait_for_mint_to_be_paid(&wallet, &mint_quote.id, 60) wallet
.wait_for_payment(&mint_quote, Duration::from_secs(60))
.await .await
.unwrap(); .unwrap();
@@ -88,7 +90,8 @@ async fn test_fake_melt_payment_fail() {
let mint_quote = wallet.mint_quote(100.into(), None).await.unwrap(); let mint_quote = wallet.mint_quote(100.into(), None).await.unwrap();
wait_for_mint_to_be_paid(&wallet, &mint_quote.id, 60) wallet
.wait_for_payment(&mint_quote, Duration::from_secs(60))
.await .await
.unwrap(); .unwrap();
@@ -153,7 +156,8 @@ async fn test_fake_melt_payment_fail_and_check() {
let mint_quote = wallet.mint_quote(100.into(), None).await.unwrap(); let mint_quote = wallet.mint_quote(100.into(), None).await.unwrap();
wait_for_mint_to_be_paid(&wallet, &mint_quote.id, 60) wallet
.wait_for_payment(&mint_quote, Duration::from_secs(60))
.await .await
.unwrap(); .unwrap();
@@ -201,7 +205,8 @@ async fn test_fake_melt_payment_return_fail_status() {
let mint_quote = wallet.mint_quote(100.into(), None).await.unwrap(); let mint_quote = wallet.mint_quote(100.into(), None).await.unwrap();
wait_for_mint_to_be_paid(&wallet, &mint_quote.id, 60) wallet
.wait_for_payment(&mint_quote, Duration::from_secs(60))
.await .await
.unwrap(); .unwrap();
@@ -264,7 +269,8 @@ async fn test_fake_melt_payment_error_unknown() {
let mint_quote = wallet.mint_quote(100.into(), None).await.unwrap(); let mint_quote = wallet.mint_quote(100.into(), None).await.unwrap();
wait_for_mint_to_be_paid(&wallet, &mint_quote.id, 60) wallet
.wait_for_payment(&mint_quote, Duration::from_secs(60))
.await .await
.unwrap(); .unwrap();
@@ -327,7 +333,8 @@ async fn test_fake_melt_payment_err_paid() {
let mint_quote = wallet.mint_quote(100.into(), None).await.unwrap(); let mint_quote = wallet.mint_quote(100.into(), None).await.unwrap();
wait_for_mint_to_be_paid(&wallet, &mint_quote.id, 60) wallet
.wait_for_payment(&mint_quote, Duration::from_secs(60))
.await .await
.unwrap(); .unwrap();
@@ -368,7 +375,8 @@ async fn test_fake_melt_change_in_quote() {
let mint_quote = wallet.mint_quote(100.into(), None).await.unwrap(); let mint_quote = wallet.mint_quote(100.into(), None).await.unwrap();
wait_for_mint_to_be_paid(&wallet, &mint_quote.id, 60) wallet
.wait_for_payment(&mint_quote, Duration::from_secs(60))
.await .await
.unwrap(); .unwrap();
@@ -437,7 +445,8 @@ async fn test_fake_mint_with_witness() {
.expect("failed to create new wallet"); .expect("failed to create new wallet");
let mint_quote = wallet.mint_quote(100.into(), None).await.unwrap(); let mint_quote = wallet.mint_quote(100.into(), None).await.unwrap();
wait_for_mint_to_be_paid(&wallet, &mint_quote.id, 60) wallet
.wait_for_payment(&mint_quote, Duration::from_secs(60))
.await .await
.unwrap(); .unwrap();
@@ -465,7 +474,8 @@ async fn test_fake_mint_without_witness() {
let mint_quote = wallet.mint_quote(100.into(), None).await.unwrap(); let mint_quote = wallet.mint_quote(100.into(), None).await.unwrap();
wait_for_mint_to_be_paid(&wallet, &mint_quote.id, 60) wallet
.wait_for_payment(&mint_quote, Duration::from_secs(60))
.await .await
.unwrap(); .unwrap();
@@ -505,7 +515,8 @@ async fn test_fake_mint_with_wrong_witness() {
let mint_quote = wallet.mint_quote(100.into(), None).await.unwrap(); let mint_quote = wallet.mint_quote(100.into(), None).await.unwrap();
wait_for_mint_to_be_paid(&wallet, &mint_quote.id, 60) wallet
.wait_for_payment(&mint_quote, Duration::from_secs(60))
.await .await
.unwrap(); .unwrap();
@@ -551,7 +562,8 @@ async fn test_fake_mint_inflated() {
let mint_quote = wallet.mint_quote(100.into(), None).await.unwrap(); let mint_quote = wallet.mint_quote(100.into(), None).await.unwrap();
wait_for_mint_to_be_paid(&wallet, &mint_quote.id, 60) wallet
.wait_for_payment(&mint_quote, Duration::from_secs(60))
.await .await
.unwrap(); .unwrap();
@@ -609,7 +621,8 @@ async fn test_fake_mint_multiple_units() {
let mint_quote = wallet.mint_quote(100.into(), None).await.unwrap(); let mint_quote = wallet.mint_quote(100.into(), None).await.unwrap();
wait_for_mint_to_be_paid(&wallet, &mint_quote.id, 60) wallet
.wait_for_payment(&mint_quote, Duration::from_secs(60))
.await .await
.unwrap(); .unwrap();
@@ -688,7 +701,8 @@ async fn test_fake_mint_multiple_unit_swap() {
let mint_quote = wallet.mint_quote(100.into(), None).await.unwrap(); let mint_quote = wallet.mint_quote(100.into(), None).await.unwrap();
wait_for_mint_to_be_paid(&wallet, &mint_quote.id, 60) wallet
.wait_for_payment(&mint_quote, Duration::from_secs(60))
.await .await
.unwrap(); .unwrap();
@@ -709,7 +723,8 @@ async fn test_fake_mint_multiple_unit_swap() {
let mint_quote = wallet_usd.mint_quote(100.into(), None).await.unwrap(); let mint_quote = wallet_usd.mint_quote(100.into(), None).await.unwrap();
wait_for_mint_to_be_paid(&wallet_usd, &mint_quote.id, 60) wallet
.wait_for_payment(&mint_quote, Duration::from_secs(60))
.await .await
.unwrap(); .unwrap();
@@ -802,7 +817,8 @@ async fn test_fake_mint_multiple_unit_melt() {
let mint_quote = wallet.mint_quote(100.into(), None).await.unwrap(); let mint_quote = wallet.mint_quote(100.into(), None).await.unwrap();
wait_for_mint_to_be_paid(&wallet, &mint_quote.id, 60) wallet
.wait_for_payment(&mint_quote, Duration::from_secs(60))
.await .await
.unwrap(); .unwrap();
@@ -825,7 +841,8 @@ async fn test_fake_mint_multiple_unit_melt() {
let mint_quote = wallet_usd.mint_quote(100.into(), None).await.unwrap(); let mint_quote = wallet_usd.mint_quote(100.into(), None).await.unwrap();
println!("Minted quote usd"); println!("Minted quote usd");
wait_for_mint_to_be_paid(&wallet_usd, &mint_quote.id, 60) wallet
.wait_for_payment(&mint_quote, Duration::from_secs(60))
.await .await
.unwrap(); .unwrap();
@@ -920,7 +937,8 @@ async fn test_fake_mint_input_output_mismatch() {
let mint_quote = wallet.mint_quote(100.into(), None).await.unwrap(); let mint_quote = wallet.mint_quote(100.into(), None).await.unwrap();
wait_for_mint_to_be_paid(&wallet, &mint_quote.id, 60) wallet
.wait_for_payment(&mint_quote, Duration::from_secs(60))
.await .await
.unwrap(); .unwrap();
@@ -978,7 +996,8 @@ async fn test_fake_mint_swap_inflated() {
let mint_quote = wallet.mint_quote(100.into(), None).await.unwrap(); let mint_quote = wallet.mint_quote(100.into(), None).await.unwrap();
wait_for_mint_to_be_paid(&wallet, &mint_quote.id, 60) wallet
.wait_for_payment(&mint_quote, Duration::from_secs(60))
.await .await
.unwrap(); .unwrap();
@@ -1022,7 +1041,8 @@ async fn test_fake_mint_swap_spend_after_fail() {
let mint_quote = wallet.mint_quote(100.into(), None).await.unwrap(); let mint_quote = wallet.mint_quote(100.into(), None).await.unwrap();
wait_for_mint_to_be_paid(&wallet, &mint_quote.id, 60) wallet
.wait_for_payment(&mint_quote, Duration::from_secs(60))
.await .await
.unwrap(); .unwrap();
@@ -1093,7 +1113,8 @@ async fn test_fake_mint_melt_spend_after_fail() {
let mint_quote = wallet.mint_quote(100.into(), None).await.unwrap(); let mint_quote = wallet.mint_quote(100.into(), None).await.unwrap();
wait_for_mint_to_be_paid(&wallet, &mint_quote.id, 60) wallet
.wait_for_payment(&mint_quote, Duration::from_secs(60))
.await .await
.unwrap(); .unwrap();
@@ -1165,7 +1186,8 @@ async fn test_fake_mint_duplicate_proofs_swap() {
let mint_quote = wallet.mint_quote(100.into(), None).await.unwrap(); let mint_quote = wallet.mint_quote(100.into(), None).await.unwrap();
wait_for_mint_to_be_paid(&wallet, &mint_quote.id, 60) wallet
.wait_for_payment(&mint_quote, Duration::from_secs(60))
.await .await
.unwrap(); .unwrap();
@@ -1245,7 +1267,8 @@ async fn test_fake_mint_duplicate_proofs_melt() {
let mint_quote = wallet.mint_quote(100.into(), None).await.unwrap(); let mint_quote = wallet.mint_quote(100.into(), None).await.unwrap();
wait_for_mint_to_be_paid(&wallet, &mint_quote.id, 60) wallet
.wait_for_payment(&mint_quote, Duration::from_secs(60))
.await .await
.unwrap(); .unwrap();

View File

@@ -22,9 +22,7 @@ use cdk::amount::{Amount, SplitTarget};
use cdk::nuts::nut00::ProofsMethods; use cdk::nuts::nut00::ProofsMethods;
use cdk::nuts::{CurrencyUnit, MeltQuoteState, NotificationPayload, State}; use cdk::nuts::{CurrencyUnit, MeltQuoteState, NotificationPayload, State};
use cdk::wallet::{HttpClient, MintConnector, Wallet}; use cdk::wallet::{HttpClient, MintConnector, Wallet};
use cdk_integration_tests::{ use cdk_integration_tests::{create_invoice_for_env, get_mint_url_from_env, pay_if_regtest};
create_invoice_for_env, get_mint_url_from_env, pay_if_regtest, wait_for_mint_to_be_paid,
};
use cdk_sqlite::wallet::memory; use cdk_sqlite::wallet::memory;
use futures::{SinkExt, StreamExt}; use futures::{SinkExt, StreamExt};
use lightning_invoice::Bolt11Invoice; use lightning_invoice::Bolt11Invoice;
@@ -111,7 +109,8 @@ async fn test_happy_mint_melt_round_trip() {
.await .await
.unwrap(); .unwrap();
wait_for_mint_to_be_paid(&wallet, &mint_quote.id, 10) wallet
.wait_for_payment(&mint_quote, Duration::from_secs(60))
.await .await
.unwrap(); .unwrap();
@@ -234,7 +233,8 @@ async fn test_happy_mint() {
.await .await
.unwrap(); .unwrap();
wait_for_mint_to_be_paid(&wallet, &mint_quote.id, 60) wallet
.wait_for_payment(&mint_quote, Duration::from_secs(60))
.await .await
.unwrap(); .unwrap();
@@ -281,7 +281,8 @@ async fn test_restore() {
.await .await
.unwrap(); .unwrap();
wait_for_mint_to_be_paid(&wallet, &mint_quote.id, 60) wallet
.wait_for_payment(&mint_quote, Duration::from_secs(60))
.await .await
.unwrap(); .unwrap();
@@ -360,7 +361,8 @@ async fn test_fake_melt_change_in_quote() {
pay_if_regtest(&get_test_temp_dir(), &bolt11).await.unwrap(); pay_if_regtest(&get_test_temp_dir(), &bolt11).await.unwrap();
wait_for_mint_to_be_paid(&wallet, &mint_quote.id, 60) wallet
.wait_for_payment(&mint_quote, Duration::from_secs(60))
.await .await
.unwrap(); .unwrap();
@@ -431,7 +433,8 @@ async fn test_pay_invoice_twice() {
.await .await
.unwrap(); .unwrap();
wait_for_mint_to_be_paid(&wallet, &mint_quote.id, 60) wallet
.wait_for_payment(&mint_quote, Duration::from_secs(60))
.await .await
.unwrap(); .unwrap();

View File

@@ -27,9 +27,7 @@ use cdk::nuts::{
}; };
use cdk::wallet::{HttpClient, MintConnector, Wallet, WalletSubscription}; use cdk::wallet::{HttpClient, MintConnector, Wallet, WalletSubscription};
use cdk_integration_tests::init_regtest::{get_lnd_dir, LND_RPC_ADDR}; use cdk_integration_tests::init_regtest::{get_lnd_dir, LND_RPC_ADDR};
use cdk_integration_tests::{ use cdk_integration_tests::{get_mint_url_from_env, get_second_mint_url_from_env};
get_mint_url_from_env, get_second_mint_url_from_env, wait_for_mint_to_be_paid,
};
use cdk_sqlite::wallet::{self, memory}; use cdk_sqlite::wallet::{self, memory};
use futures::join; use futures::join;
use ln_regtest_rs::ln_client::{LightningClient, LndClient}; use ln_regtest_rs::ln_client::{LightningClient, LndClient};
@@ -84,11 +82,12 @@ async fn test_internal_payment() {
let mint_quote = wallet.mint_quote(100.into(), None).await.unwrap(); let mint_quote = wallet.mint_quote(100.into(), None).await.unwrap();
lnd_client lnd_client
.pay_invoice(mint_quote.request) .pay_invoice(mint_quote.request.clone())
.await .await
.expect("failed to pay invoice"); .expect("failed to pay invoice");
wait_for_mint_to_be_paid(&wallet, &mint_quote.id, 60) wallet
.wait_for_payment(&mint_quote, Duration::from_secs(60))
.await .await
.unwrap(); .unwrap();
@@ -119,7 +118,8 @@ async fn test_internal_payment() {
let _melted = wallet.melt(&melt.id).await.unwrap(); let _melted = wallet.melt(&melt.id).await.unwrap();
wait_for_mint_to_be_paid(&wallet_2, &mint_quote.id, 60) wallet_2
.wait_for_payment(&mint_quote, Duration::from_secs(60))
.await .await
.unwrap(); .unwrap();
@@ -261,7 +261,8 @@ async fn test_multimint_melt() {
.pay_invoice(quote.request.clone()) .pay_invoice(quote.request.clone())
.await .await
.expect("failed to pay invoice"); .expect("failed to pay invoice");
wait_for_mint_to_be_paid(&wallet1, &quote.id, 60) wallet1
.wait_for_payment(&quote, Duration::from_secs(60))
.await .await
.unwrap(); .unwrap();
wallet1 wallet1
@@ -274,7 +275,8 @@ async fn test_multimint_melt() {
.pay_invoice(quote.request.clone()) .pay_invoice(quote.request.clone())
.await .await
.expect("failed to pay invoice"); .expect("failed to pay invoice");
wait_for_mint_to_be_paid(&wallet2, &quote.id, 60) wallet2
.wait_for_payment(&quote, Duration::from_secs(60))
.await .await
.unwrap(); .unwrap();
wallet2 wallet2
@@ -334,7 +336,8 @@ async fn test_cached_mint() {
.await .await
.expect("failed to pay invoice"); .expect("failed to pay invoice");
wait_for_mint_to_be_paid(&wallet, &quote.id, 60) wallet
.wait_for_payment(&quote, Duration::from_secs(60))
.await .await
.unwrap(); .unwrap();

View File

@@ -1,5 +1,6 @@
use std::str::FromStr; use std::str::FromStr;
use std::sync::Arc; use std::sync::Arc;
use std::time::Duration;
use bip39::Mnemonic; use bip39::Mnemonic;
use cashu::{Bolt11Invoice, ProofsMethods}; use cashu::{Bolt11Invoice, ProofsMethods};
@@ -7,9 +8,7 @@ use cdk::amount::{Amount, SplitTarget};
use cdk::nuts::CurrencyUnit; use cdk::nuts::CurrencyUnit;
use cdk::wallet::{ReceiveOptions, SendKind, SendOptions, Wallet}; use cdk::wallet::{ReceiveOptions, SendKind, SendOptions, Wallet};
use cdk_integration_tests::init_regtest::get_temp_dir; use cdk_integration_tests::init_regtest::get_temp_dir;
use cdk_integration_tests::{ use cdk_integration_tests::{create_invoice_for_env, get_mint_url_from_env, pay_if_regtest};
create_invoice_for_env, get_mint_url_from_env, pay_if_regtest, wait_for_mint_to_be_paid,
};
use cdk_sqlite::wallet::memory; use cdk_sqlite::wallet::memory;
#[tokio::test(flavor = "multi_thread", worker_threads = 1)] #[tokio::test(flavor = "multi_thread", worker_threads = 1)]
@@ -29,7 +28,8 @@ async fn test_swap() {
let invoice = Bolt11Invoice::from_str(&mint_quote.request).unwrap(); let invoice = Bolt11Invoice::from_str(&mint_quote.request).unwrap();
pay_if_regtest(&get_temp_dir(), &invoice).await.unwrap(); pay_if_regtest(&get_temp_dir(), &invoice).await.unwrap();
wait_for_mint_to_be_paid(&wallet, &mint_quote.id, 10) wallet
.wait_for_payment(&mint_quote, Duration::from_secs(60))
.await .await
.unwrap(); .unwrap();
@@ -96,7 +96,8 @@ async fn test_fake_melt_change_in_quote() {
pay_if_regtest(&get_temp_dir(), &bolt11).await.unwrap(); pay_if_regtest(&get_temp_dir(), &bolt11).await.unwrap();
wait_for_mint_to_be_paid(&wallet, &mint_quote.id, 60) wallet
.wait_for_payment(&mint_quote, Duration::from_secs(60))
.await .await
.unwrap(); .unwrap();

View File

@@ -12,7 +12,7 @@ license.workspace = true
[features] [features]
default = ["mint", "wallet", "auth"] default = ["mint", "wallet", "auth"]
wallet = ["dep:reqwest", "cdk-common/wallet", "dep:rustls"] wallet = ["dep:futures", "dep:reqwest", "cdk-common/wallet", "dep:rustls"]
mint = ["dep:futures", "dep:reqwest", "cdk-common/mint", "cdk-signatory"] mint = ["dep:futures", "dep:reqwest", "cdk-common/mint", "cdk-signatory"]
auth = ["dep:jsonwebtoken", "cdk-common/auth", "cdk-common/auth"] auth = ["dep:jsonwebtoken", "cdk-common/auth", "cdk-common/auth"]
# We do not commit to a MSRV with swagger enabled # We do not commit to a MSRV with swagger enabled

View File

@@ -1,9 +1,9 @@
use std::sync::Arc; use std::sync::Arc;
use std::time::Duration;
use cdk::amount::SplitTarget;
use cdk::error::Error; use cdk::error::Error;
use cdk::nuts::{CurrencyUnit, MintQuoteState, NotificationPayload}; use cdk::nuts::CurrencyUnit;
use cdk::wallet::{SendOptions, Wallet, WalletSubscription}; use cdk::wallet::{SendOptions, Wallet};
use cdk::{Amount, OidcClient}; use cdk::{Amount, OidcClient};
use cdk_common::{MintInfo, ProofsMethods}; use cdk_common::{MintInfo, ProofsMethods};
use cdk_sqlite::wallet::memory; use cdk_sqlite::wallet::memory;
@@ -57,27 +57,12 @@ async fn main() -> Result<(), Error> {
.await .await
.expect("Could not mint blind auth"); .expect("Could not mint blind auth");
// Request a mint quote from the wallet let (_invoice_to_pay, proofs) = wallet
let quote = wallet.mint_quote(amount, None).await?; .mint_once_paid(amount, None, Duration::from_secs(10))
.await?;
// Subscribe to updates on the mint quote state
let mut subscription = wallet
.subscribe(WalletSubscription::Bolt11MintQuoteState(vec![quote
.id
.clone()]))
.await;
// Wait for the mint quote to be paid
while let Some(msg) = subscription.recv().await {
if let NotificationPayload::MintQuoteBolt11Response(response) = msg {
if response.state == MintQuoteState::Paid {
break;
}
}
}
// Mint the received amount // Mint the received amount
let receive_amount = wallet.mint(&quote.id, SplitTarget::default(), None).await?; let receive_amount = proofs.await?;
println!("Received: {}", receive_amount.total_amount()?); println!("Received: {}", receive_amount.total_amount()?);

View File

@@ -1,13 +1,13 @@
use std::sync::Arc; use std::sync::Arc;
use std::time::Duration;
use bitcoin::hashes::{sha256, Hash}; use bitcoin::hashes::{sha256, Hash};
use bitcoin::hex::prelude::FromHex; use bitcoin::hex::prelude::FromHex;
use bitcoin::secp256k1::Secp256k1; use bitcoin::secp256k1::Secp256k1;
use cdk::amount::SplitTarget;
use cdk::error::Error; use cdk::error::Error;
use cdk::nuts::nut00::ProofsMethods; use cdk::nuts::nut00::ProofsMethods;
use cdk::nuts::{CurrencyUnit, MintQuoteState, NotificationPayload, SecretKey}; use cdk::nuts::{CurrencyUnit, SecretKey};
use cdk::wallet::{Wallet, WalletSubscription}; use cdk::wallet::Wallet;
use cdk::Amount; use cdk::Amount;
use cdk_sqlite::wallet::memory; use cdk_sqlite::wallet::memory;
use lightning_invoice::{Currency, InvoiceBuilder, PaymentSecret}; use lightning_invoice::{Currency, InvoiceBuilder, PaymentSecret};
@@ -29,28 +29,12 @@ async fn main() -> Result<(), Error> {
// Create a new wallet // Create a new wallet
let wallet = Wallet::new(mint_url, unit, Arc::new(localstore), seed, None)?; let wallet = Wallet::new(mint_url, unit, Arc::new(localstore), seed, None)?;
// Request a mint quote from the wallet let (_invoice_to_pay, proofs) = wallet
let quote = wallet.mint_quote(amount, None).await?; .mint_once_paid(amount, None, Duration::from_secs(10))
println!("Quote: {:#?}", quote); .await?;
// Subscribe to updates on the mint quote state
let mut subscription = wallet
.subscribe(WalletSubscription::Bolt11MintQuoteState(vec![quote
.id
.clone()]))
.await;
// Wait for the mint quote to be paid
while let Some(msg) = subscription.recv().await {
if let NotificationPayload::MintQuoteBolt11Response(response) = msg {
if response.state == MintQuoteState::Paid {
break;
}
}
}
// Mint the received amount // Mint the received amount
let proofs = wallet.mint(&quote.id, SplitTarget::default(), None).await?; let proofs = proofs.await?;
let receive_amount = proofs.total_amount()?; let receive_amount = proofs.total_amount()?;
println!("Received {} from mint {}", receive_amount, mint_url); println!("Received {} from mint {}", receive_amount, mint_url);

View File

@@ -1,10 +1,10 @@
use std::sync::Arc; use std::sync::Arc;
use std::time::Duration;
use cdk::amount::SplitTarget;
use cdk::error::Error; use cdk::error::Error;
use cdk::nuts::nut00::ProofsMethods; use cdk::nuts::nut00::ProofsMethods;
use cdk::nuts::{CurrencyUnit, MintQuoteState, NotificationPayload}; use cdk::nuts::CurrencyUnit;
use cdk::wallet::{SendOptions, Wallet, WalletSubscription}; use cdk::wallet::{SendOptions, Wallet};
use cdk::Amount; use cdk::Amount;
use cdk_sqlite::wallet::memory; use cdk_sqlite::wallet::memory;
use rand::random; use rand::random;
@@ -35,28 +35,12 @@ async fn main() -> Result<(), Error> {
// Create a new wallet // Create a new wallet
let wallet = Wallet::new(mint_url, unit, localstore, seed, None)?; let wallet = Wallet::new(mint_url, unit, localstore, seed, None)?;
// Request a mint quote from the wallet let (_invoice_to_pay, proofs) = wallet
let quote = wallet.mint_quote(amount, None).await?; .mint_once_paid(amount, None, Duration::from_secs(10))
println!("Quote: {:#?}", quote); .await?;
// Subscribe to updates on the mint quote state
let mut subscription = wallet
.subscribe(WalletSubscription::Bolt11MintQuoteState(vec![quote
.id
.clone()]))
.await;
// Wait for the mint quote to be paid
while let Some(msg) = subscription.recv().await {
if let NotificationPayload::MintQuoteBolt11Response(response) = msg {
if response.state == MintQuoteState::Paid {
break;
}
}
}
// Mint the received amount // Mint the received amount
let proofs = wallet.mint(&quote.id, SplitTarget::default(), None).await?; let proofs = proofs.await?;
let receive_amount = proofs.total_amount()?; let receive_amount = proofs.total_amount()?;
println!("Received {} from mint {}", receive_amount, mint_url); println!("Received {} from mint {}", receive_amount, mint_url);

View File

@@ -1,9 +1,9 @@
use std::sync::Arc; use std::sync::Arc;
use std::time::Duration;
use cdk::amount::SplitTarget;
use cdk::error::Error; use cdk::error::Error;
use cdk::nuts::{CurrencyUnit, MintQuoteState, NotificationPayload, SecretKey, SpendingConditions}; use cdk::nuts::{CurrencyUnit, SecretKey, SpendingConditions};
use cdk::wallet::{ReceiveOptions, SendOptions, Wallet, WalletSubscription}; use cdk::wallet::{ReceiveOptions, SendOptions, Wallet};
use cdk::Amount; use cdk::Amount;
use cdk_sqlite::wallet::memory; use cdk_sqlite::wallet::memory;
use rand::random; use rand::random;
@@ -34,29 +34,12 @@ async fn main() -> Result<(), Error> {
// Create a new wallet // Create a new wallet
let wallet = Wallet::new(mint_url, unit, localstore, seed, None).unwrap(); let wallet = Wallet::new(mint_url, unit, localstore, seed, None).unwrap();
// Request a mint quote from the wallet let (_invoice_to_pay, proofs) = wallet
let quote = wallet.mint_quote(amount, None).await?; .mint_once_paid(amount, None, Duration::from_secs(10))
.await?;
println!("Minting nuts ...");
// Subscribe to updates on the mint quote state
let mut subscription = wallet
.subscribe(WalletSubscription::Bolt11MintQuoteState(vec![quote
.id
.clone()]))
.await;
// Wait for the mint quote to be paid
while let Some(msg) = subscription.recv().await {
if let NotificationPayload::MintQuoteBolt11Response(response) = msg {
if response.state == MintQuoteState::Paid {
break;
}
}
}
// Mint the received amount // Mint the received amount
let received_proofs = wallet.mint(&quote.id, SplitTarget::default(), None).await?; let received_proofs = proofs.await?;
println!( println!(
"Minted nuts: {:?}", "Minted nuts: {:?}",
received_proofs received_proofs

View File

@@ -2,11 +2,11 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::Arc; use std::sync::Arc;
use std::time::Duration;
use cdk::amount::SplitTarget;
use cdk::nuts::nut00::ProofsMethods; use cdk::nuts::nut00::ProofsMethods;
use cdk::nuts::{CurrencyUnit, MintQuoteState, NotificationPayload}; use cdk::nuts::CurrencyUnit;
use cdk::wallet::{Wallet, WalletSubscription}; use cdk::wallet::Wallet;
use cdk::Amount; use cdk::Amount;
use cdk_common::nut02::KeySetInfosMethods; use cdk_common::nut02::KeySetInfosMethods;
use cdk_sqlite::wallet::memory; use cdk_sqlite::wallet::memory;
@@ -31,28 +31,12 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
for amount in [64] { for amount in [64] {
let amount = Amount::from(amount); let amount = Amount::from(amount);
// Request a mint quote from the wallet let (_invoice_to_pay, proofs) = wallet
let quote = wallet.mint_quote(amount, None).await?; .mint_once_paid(amount, None, Duration::from_secs(10))
println!("Pay request: {}", quote.request); .await?;
// Subscribe to the wallet for updates on the mint quote state
let mut subscription = wallet
.subscribe(WalletSubscription::Bolt11MintQuoteState(vec![quote
.id
.clone()]))
.await;
// Wait for the mint quote to be paid
while let Some(msg) = subscription.recv().await {
if let NotificationPayload::MintQuoteBolt11Response(response) = msg {
if response.state == MintQuoteState::Paid {
break;
}
}
}
// Mint the received amount // Mint the received amount
let proofs = wallet.mint(&quote.id, SplitTarget::default(), None).await?; let proofs = proofs.await?;
let receive_amount = proofs.total_amount()?; let receive_amount = proofs.total_amount()?;
println!("Minted {}", receive_amount); println!("Minted {}", receive_amount);
} }

View File

@@ -1,14 +1,12 @@
use std::sync::Arc; use std::sync::Arc;
use std::time::Duration; use std::time::Duration;
use cdk::amount::SplitTarget;
use cdk::nuts::nut00::ProofsMethods; use cdk::nuts::nut00::ProofsMethods;
use cdk::nuts::{CurrencyUnit, MintQuoteState}; use cdk::nuts::CurrencyUnit;
use cdk::wallet::{SendOptions, Wallet}; use cdk::wallet::{SendOptions, Wallet};
use cdk::Amount; use cdk::Amount;
use cdk_sqlite::wallet::memory; use cdk_sqlite::wallet::memory;
use rand::random; use rand::random;
use tokio::time::sleep;
#[tokio::main] #[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> { async fn main() -> Result<(), Box<dyn std::error::Error>> {
@@ -26,34 +24,12 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create a new wallet // Create a new wallet
let wallet = Wallet::new(mint_url, unit, localstore, seed, None)?; let wallet = Wallet::new(mint_url, unit, localstore, seed, None)?;
// Request a mint quote from the wallet let (_invoice_to_pay, proofs) = wallet
let quote = wallet.mint_quote(amount, None).await?; .mint_once_paid(amount, None, Duration::from_secs(10))
.await?;
println!("Pay request: {}", quote.request);
// Check the quote state in a loop with a timeout
let timeout = Duration::from_secs(60); // Set a timeout duration
let start = std::time::Instant::now();
loop {
let status = wallet.mint_quote_state(&quote.id).await?;
if status.state == MintQuoteState::Paid {
break;
}
if start.elapsed() >= timeout {
eprintln!("Timeout while waiting for mint quote to be paid");
return Err("Timeout while waiting for mint quote to be paid".into());
}
println!("Quote state: {}", status.state);
sleep(Duration::from_secs(5)).await;
}
// Mint the received amount // Mint the received amount
let proofs = wallet.mint(&quote.id, SplitTarget::default(), None).await?; let proofs = proofs.await?;
let receive_amount = proofs.total_amount()?; let receive_amount = proofs.total_amount()?;
println!("Minted {}", receive_amount); println!("Minted {}", receive_amount);

View File

@@ -45,6 +45,7 @@ pub mod subscription;
mod swap; mod swap;
mod transactions; mod transactions;
pub mod util; pub mod util;
mod wait;
#[cfg(feature = "auth")] #[cfg(feature = "auth")]
pub use auth::{AuthMintConnector, AuthWallet}; pub use auth::{AuthMintConnector, AuthWallet};

View File

@@ -0,0 +1,138 @@
use std::future::Future;
use cdk_common::amount::SplitTarget;
use cdk_common::wallet::{MeltQuote, MintQuote};
use cdk_common::{
Amount, Error, MeltQuoteState, MintQuoteState, NotificationPayload, Proofs, SpendingConditions,
};
use futures::future::BoxFuture;
use tokio::time::{timeout, Duration};
use super::{Wallet, WalletSubscription};
#[allow(private_bounds)]
enum WaitableEvent {
MeltQuote(String),
MintQuote(String),
}
impl From<&MeltQuote> for WaitableEvent {
fn from(event: &MeltQuote) -> Self {
WaitableEvent::MeltQuote(event.id.to_owned())
}
}
impl From<&MintQuote> for WaitableEvent {
fn from(event: &MintQuote) -> Self {
WaitableEvent::MintQuote(event.id.to_owned())
}
}
impl From<WaitableEvent> for WalletSubscription {
fn from(val: WaitableEvent) -> Self {
match val {
WaitableEvent::MeltQuote(quote_id) => {
WalletSubscription::Bolt11MeltQuoteState(vec![quote_id])
}
WaitableEvent::MintQuote(quote_id) => {
WalletSubscription::Bolt11MintQuoteState(vec![quote_id])
}
}
}
}
impl Wallet {
#[inline(always)]
async fn wait_and_mint_quote(
&self,
quote: MintQuote,
amount_split_target: SplitTarget,
spending_conditions: Option<SpendingConditions>,
timeout_duration: Duration,
) -> Result<Proofs, Error> {
self.wait_for_payment(&quote, timeout_duration).await?;
self.mint(&quote.id, amount_split_target, spending_conditions)
.await
}
/// Mints an amount and returns the invoice to be paid, and a BoxFuture that will finalize the
/// mint once the invoice has been paid
pub async fn mint_once_paid(
&self,
amount: Amount,
description: Option<String>,
timeout_duration: Duration,
) -> Result<(String, impl Future<Output = Result<Proofs, Error>> + '_), Error> {
self.mint_once_paid_ex(
amount,
description,
Default::default(),
None,
timeout_duration,
)
.await
}
/// Similar function to mint_once_paid but with no default options
pub async fn mint_once_paid_ex(
&self,
amount: Amount,
description: Option<String>,
amount_split_target: SplitTarget,
spending_conditions: Option<SpendingConditions>,
timeout_duration: Duration,
) -> Result<(String, impl Future<Output = Result<Proofs, Error>> + '_), Error> {
let quote = self.mint_quote(amount, description).await?;
Ok((
quote.request.clone(),
self.wait_and_mint_quote(
quote,
amount_split_target,
spending_conditions,
timeout_duration,
),
))
}
/// Returns a BoxFuture that will wait for payment on the given event with a timeout check
#[allow(private_bounds)]
pub fn wait_for_payment<T>(
&self,
event: T,
timeout_duration: Duration,
) -> BoxFuture<'_, Result<(), Error>>
where
T: Into<WaitableEvent>,
{
let subs = self.subscribe::<WalletSubscription>(event.into().into());
Box::pin(async move {
timeout(timeout_duration, async {
let mut subscription = subs.await;
loop {
match subscription.recv().await.ok_or(Error::Internal)? {
NotificationPayload::MintQuoteBolt11Response(info) => {
if info.state == MintQuoteState::Paid {
return Ok(());
}
}
NotificationPayload::MintQuoteBolt12Response(info) => {
if info.amount_paid > Amount::ZERO {
return Ok(());
}
}
NotificationPayload::MeltQuoteBolt11Response(info) => {
if info.state == MeltQuoteState::Paid {
return Ok(());
}
}
_ => {}
}
}
})
.await
.map_err(|_| Error::Timeout)?
})
}
}