multi-mint-wallet.rs 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. #![allow(missing_docs)]
  2. use std::collections::HashMap;
  3. use std::str::FromStr;
  4. use std::sync::Arc;
  5. use std::time::Duration;
  6. use bip39::Mnemonic;
  7. use cdk::amount::SplitTarget;
  8. use cdk::mint_url::MintUrl;
  9. use cdk::nuts::nut00::ProofsMethods;
  10. use cdk::nuts::{CurrencyUnit, PaymentMethod};
  11. use cdk::wallet::multi_mint_wallet::MultiMintWallet;
  12. use cdk::wallet::{MultiMintReceiveOptions, SendOptions};
  13. use cdk::Amount;
  14. use cdk_fake_wallet::create_fake_invoice;
  15. use cdk_sqlite::wallet::memory;
  16. /// This example demonstrates the MultiMintWallet API for managing multiple mints.
  17. ///
  18. /// It shows:
  19. /// - Creating a MultiMintWallet
  20. /// - Adding a mint
  21. /// - Minting proofs
  22. /// - Sending tokens
  23. /// - Receiving tokens
  24. /// - Melting (paying Lightning invoices)
  25. /// - Querying balances
  26. #[tokio::main]
  27. async fn main() -> Result<(), Box<dyn std::error::Error>> {
  28. // Configuration
  29. let mint_url = MintUrl::from_str("https://fake.thesimplekid.dev")?;
  30. let unit = CurrencyUnit::Sat;
  31. // Generate a seed from a mnemonic (in production, store this securely!)
  32. let mnemonic = Mnemonic::generate(12)?;
  33. let seed = mnemonic.to_seed_normalized("");
  34. println!("Generated mnemonic (save this!): {}", mnemonic);
  35. // Create the MultiMintWallet
  36. let localstore = Arc::new(memory::empty().await?);
  37. let wallet = MultiMintWallet::new(localstore, seed, unit.clone()).await?;
  38. println!("\nCreated MultiMintWallet");
  39. // Add a mint to the wallet
  40. wallet.add_mint(mint_url.clone()).await?;
  41. println!("Added mint: {}", mint_url);
  42. // ========================================
  43. // MINT: Create proofs from Lightning invoice
  44. // ========================================
  45. let mint_amount = Amount::from(100);
  46. println!("\n--- MINT ---");
  47. println!("Creating mint quote for {} sats...", mint_amount);
  48. let mint_quote = wallet
  49. .mint_quote(
  50. &mint_url,
  51. PaymentMethod::BOLT11,
  52. Some(mint_amount),
  53. None,
  54. None,
  55. )
  56. .await?;
  57. println!("Invoice to pay: {}", mint_quote.request);
  58. // Wait for quote to be paid and mint proofs
  59. // With the fake mint, this happens automatically
  60. let proofs = wallet
  61. .wait_for_mint_quote(
  62. &mint_url,
  63. &mint_quote.id,
  64. SplitTarget::default(),
  65. None,
  66. Duration::from_secs(30),
  67. )
  68. .await?;
  69. let minted_amount = proofs.total_amount()?;
  70. println!("Minted {} sats", minted_amount);
  71. // Check balance
  72. let balance = wallet.total_balance().await?;
  73. println!("Total balance: {} sats", balance);
  74. // ========================================
  75. // SEND: Create a token to send to someone
  76. // ========================================
  77. let send_amount = Amount::from(25);
  78. println!("\n--- SEND ---");
  79. println!("Preparing to send {} sats...", send_amount);
  80. let prepared_send = wallet
  81. .prepare_send(mint_url.clone(), send_amount, SendOptions::default())
  82. .await?;
  83. let token = prepared_send.confirm(None).await?;
  84. println!("Token created:\n{}", token);
  85. // Check balance after send
  86. let balance = wallet.total_balance().await?;
  87. println!("Balance after send: {} sats", balance);
  88. // ========================================
  89. // RECEIVE: Receive a token (using a second wallet)
  90. // ========================================
  91. println!("\n--- RECEIVE ---");
  92. // Create a second wallet to receive the token
  93. let receiver_seed = Mnemonic::generate(12)?.to_seed_normalized("");
  94. let receiver_store = Arc::new(memory::empty().await?);
  95. let receiver_wallet = MultiMintWallet::new(receiver_store, receiver_seed, unit).await?;
  96. // Add the mint (or use allow_untrusted)
  97. receiver_wallet.add_mint(mint_url.clone()).await?;
  98. // Receive the token
  99. let received = receiver_wallet
  100. .receive(&token.to_string(), MultiMintReceiveOptions::default())
  101. .await?;
  102. println!("Receiver got {} sats", received);
  103. // Check receiver balance
  104. let receiver_balance = receiver_wallet.total_balance().await?;
  105. println!("Receiver balance: {} sats", receiver_balance);
  106. // ========================================
  107. // MELT: Pay a Lightning invoice
  108. // ========================================
  109. let melt_amount_sats: u64 = 10;
  110. println!("\n--- MELT ---");
  111. println!("Creating invoice for {} sats to melt...", melt_amount_sats);
  112. // Create a fake invoice (works with fake.thesimplekid.dev)
  113. let invoice = create_fake_invoice(melt_amount_sats * 1000, "test melt".to_string());
  114. println!("Invoice: {}", invoice);
  115. // Create melt quote
  116. let melt_quote = wallet
  117. .melt_quote(
  118. &mint_url,
  119. PaymentMethod::BOLT11,
  120. invoice.to_string(),
  121. None,
  122. None,
  123. )
  124. .await?;
  125. println!(
  126. "Melt quote: {} sats + {} fee reserve",
  127. melt_quote.amount, melt_quote.fee_reserve
  128. );
  129. // Prepare and execute melt
  130. let prepared_melt = wallet
  131. .prepare_melt(&mint_url, &melt_quote.id, HashMap::new())
  132. .await?;
  133. let melt_result = prepared_melt.confirm().await?;
  134. println!("Melt completed! State: {:?}", melt_result.state());
  135. // ========================================
  136. // BALANCE: Query balances
  137. // ========================================
  138. println!("\n--- BALANCES ---");
  139. let total = wallet.total_balance().await?;
  140. println!("Total balance: {} sats", total);
  141. let per_mint = wallet.get_balances().await?;
  142. for (url, amount) in per_mint {
  143. println!(" {}: {} sats", url, amount);
  144. }
  145. // List all mints
  146. println!("\nMints in wallet:");
  147. let wallets = wallet.get_wallets().await;
  148. for w in wallets {
  149. println!(" - {} ({})", w.mint_url, w.unit);
  150. }
  151. Ok(())
  152. }