#![allow(missing_docs)]
#![allow(clippy::unwrap_used)]
#![allow(clippy::use_debug)]
use std::sync::Arc;
use std::time::Duration;
use bitcoin::hashes::{sha256, Hash};
use bitcoin::hex::prelude::FromHex;
use bitcoin::secp256k1::Secp256k1;
use cdk::error::Error;
use cdk::nuts::{CurrencyUnit, PaymentMethod, SecretKey};
use cdk::wallet::{MeltOutcome, Wallet};
use cdk::Amount;
use cdk_sqlite::wallet::memory;
use lightning_invoice::{Currency, InvoiceBuilder, PaymentSecret};
use rand::Rng;
#[tokio::main]
async fn main() -> Result<(), Error> {
let localstore = memory::empty().await?;
let seed = rand::rng().random::<[u8; 64]>();
let mint_url = "https://fake.thesimplekid.dev";
let unit = CurrencyUnit::Sat;
let amount = Amount::from(20);
let wallet = Wallet::new(mint_url, unit, Arc::new(localstore), seed, None)?;
let quote = wallet
.mint_quote(PaymentMethod::BOLT11, Some(amount), None, None)
.await?;
let _proofs = wallet
.wait_and_mint_quote(
quote,
Default::default(),
Default::default(),
Duration::from_secs(10),
)
.await?;
let balance = wallet.total_balance().await?;
println!("Minted {} sats from {}", balance, mint_url);
let create_test_invoice = |amount_msats: u64, description: &str| {
let private_key = SecretKey::from_slice(
&<[u8; 32]>::from_hex(
"e126f68f7eafcc8b74f54d269fe206be715000f94dac067d1c04a8ca3b2db734",
)
.unwrap(),
)
.unwrap();
let random_bytes = rand::rng().random::<[u8; 32]>();
let payment_hash = sha256::Hash::from_slice(&random_bytes).unwrap();
let payment_secret = PaymentSecret([42u8; 32]);
InvoiceBuilder::new(Currency::Bitcoin)
.amount_milli_satoshis(amount_msats)
.description(description.into())
.payment_hash(payment_hash)
.payment_secret(payment_secret)
.current_timestamp()
.min_final_cltv_expiry_delta(144)
.build_signed(|hash| Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key))
.unwrap()
.to_string()
};
println!("\n=== Example 1: Synchronous Confirm ===");
println!("This approach blocks until the payment completes.");
println!("Use this when you need to wait for completion before continuing.");
let invoice1 = create_test_invoice(5 * 1000, "Sync melt example");
let melt_quote1 = wallet
.melt_quote(PaymentMethod::BOLT11, invoice1, None, None)
.await?;
println!(
"Melt quote 1: {} sats, fee reserve: {:?}",
melt_quote1.amount, melt_quote1.fee_reserve
);
let prepared1 = wallet
.prepare_melt(&melt_quote1.id, std::collections::HashMap::new())
.await?;
println!(
"Prepared melt - Amount: {}, Total Fee: {}",
prepared1.amount(),
prepared1.total_fee()
);
let confirmed1 = prepared1.confirm().await?;
println!(
"Sync melt completed: state={:?}, amount={}, fee_paid={}",
confirmed1.state(),
confirmed1.amount(),
confirmed1.fee_paid()
);
println!("\n=== Example 2: Async Confirm ===");
println!(
"This approach sends the request with async preference and waits for the mint's response."
);
println!(
"If the mint supports async payments, it may return Pending quickly without waiting for"
);
println!("the payment to complete. If not, it may block until the payment completes.");
let invoice2 = create_test_invoice(5 * 1000, "Async melt example");
let melt_quote2 = wallet
.melt_quote(PaymentMethod::BOLT11, invoice2, None, None)
.await?;
println!(
"Melt quote 2: {} sats, fee reserve: {:?}",
melt_quote2.amount, melt_quote2.fee_reserve
);
let prepared2 = wallet
.prepare_melt(&melt_quote2.id, std::collections::HashMap::new())
.await?;
println!(
"Prepared melt - Amount: {}, Total Fee: {}",
prepared2.amount(),
prepared2.total_fee()
);
let result = prepared2.confirm_prefer_async().await?;
match result {
MeltOutcome::Paid(finalized) => {
println!(
"Async melt completed immediately: state={:?}, amount={}, fee_paid={}",
finalized.state(),
finalized.amount(),
finalized.fee_paid()
);
}
MeltOutcome::Pending(pending) => {
println!("Melt is pending, waiting for completion via WebSocket...");
let finalized = pending.await?;
println!(
"Async melt completed after waiting: state={:?}, amount={}, fee_paid={}",
finalized.state(),
finalized.amount(),
finalized.fee_paid()
);
}
}
let final_balance = wallet.total_balance().await?;
println!("\nFinal balance: {} sats", final_balance);
Ok(())
}