mirror of
https://github.com/aljazceru/cdk.git
synced 2026-01-28 01:06:18 +01:00
Merge pull request #963 from crodas/feature/wait-for-invoice
Add `wait_for_payment` function in the wallet
This commit is contained in:
@@ -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),
|
||||||
|
|||||||
@@ -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, "e.id, 60).await?;
|
wallet
|
||||||
|
.wait_for_payment("e, Duration::from_secs(60))
|
||||||
|
.await?;
|
||||||
|
|
||||||
Ok(wallet
|
Ok(wallet
|
||||||
.mint("e.id, split_target.unwrap_or_default(), None)
|
.mint("e.id, split_target.unwrap_or_default(), None)
|
||||||
|
|||||||
@@ -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, "e.id, 60)
|
wallet
|
||||||
|
.wait_for_payment("e, Duration::from_secs(60))
|
||||||
.await
|
.await
|
||||||
.expect("Waiting for mint failed");
|
.expect("wait for mint failed");
|
||||||
|
|
||||||
let _proofs = wallet
|
let _proofs = wallet
|
||||||
.mint("e.id, SplitTarget::default(), None)
|
.mint("e.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");
|
||||||
|
|||||||
@@ -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, "e_one.id, 60).await?;
|
|
||||||
|
wallet_one
|
||||||
|
.wait_for_payment("e_one, Duration::from_secs(60))
|
||||||
|
.await?;
|
||||||
|
|
||||||
let proofs_one = wallet_one
|
let proofs_one = wallet_one
|
||||||
.mint_bolt12("e_one.id, None, SplitTarget::default(), None)
|
.mint_bolt12("e_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, "e_two.id, 60).await?;
|
|
||||||
|
wallet_two
|
||||||
|
.wait_for_payment("e_two, Duration::from_secs(60))
|
||||||
|
.await?;
|
||||||
|
|
||||||
let proofs_two = wallet_two
|
let proofs_two = wallet_two
|
||||||
.mint_bolt12("e_two.id, None, SplitTarget::default(), None)
|
.mint_bolt12("e_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?;
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|
||||||
|
|||||||
@@ -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, "e.id, 60)
|
wallet1
|
||||||
|
.wait_for_payment("e, 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, "e.id, 60)
|
wallet2
|
||||||
|
.wait_for_payment("e, 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, "e.id, 60)
|
wallet
|
||||||
|
.wait_for_payment("e, Duration::from_secs(60))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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("e.id, SplitTarget::default(), None).await?;
|
let receive_amount = proofs.await?;
|
||||||
|
|
||||||
println!("Received: {}", receive_amount.total_amount()?);
|
println!("Received: {}", receive_amount.total_amount()?);
|
||||||
|
|
||||||
|
|||||||
@@ -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("e.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);
|
||||||
|
|
||||||
|
|||||||
@@ -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("e.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);
|
||||||
|
|
||||||
|
|||||||
@@ -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("e.id, SplitTarget::default(), None).await?;
|
let received_proofs = proofs.await?;
|
||||||
println!(
|
println!(
|
||||||
"Minted nuts: {:?}",
|
"Minted nuts: {:?}",
|
||||||
received_proofs
|
received_proofs
|
||||||
|
|||||||
@@ -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("e.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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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("e.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("e.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);
|
||||||
|
|
||||||
|
|||||||
@@ -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};
|
||||||
|
|||||||
138
crates/cdk/src/wallet/wait.rs
Normal file
138
crates/cdk/src/wallet/wait.rs
Normal 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("e, timeout_duration).await?;
|
||||||
|
self.mint("e.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)?
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user