| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692 |
- //! Integration tests for MultiMintWallet
- //!
- //! These tests verify the multi-mint wallet functionality including:
- //! - Basic mint/melt operations across multiple mints
- //! - Token receive and send operations
- //! - Automatic mint selection for melts
- //! - Cross-mint transfers
- //!
- //! Tests use the fake wallet backend for deterministic behavior.
- use std::env;
- use std::path::PathBuf;
- use std::str::FromStr;
- use std::sync::Arc;
- use bip39::Mnemonic;
- use cdk::amount::{Amount, SplitTarget};
- use cdk::mint_url::MintUrl;
- use cdk::nuts::nut00::ProofsMethods;
- use cdk::nuts::{CurrencyUnit, MeltQuoteState, MintQuoteState, Token};
- use cdk::wallet::{MultiMintReceiveOptions, MultiMintSendOptions, MultiMintWallet};
- use cdk_integration_tests::{create_invoice_for_env, get_mint_url_from_env, pay_if_regtest};
- use cdk_sqlite::wallet::memory;
- use lightning_invoice::Bolt11Invoice;
- // Helper function to get temp directory from environment or fallback
- fn get_test_temp_dir() -> PathBuf {
- match env::var("CDK_ITESTS_DIR") {
- Ok(dir) => PathBuf::from(dir),
- Err(_) => panic!("Unknown test dir"),
- }
- }
- /// Helper to create a MultiMintWallet with a fresh seed and in-memory database
- async fn create_test_multi_mint_wallet() -> MultiMintWallet {
- let seed = Mnemonic::generate(12).unwrap().to_seed_normalized("");
- let localstore = Arc::new(memory::empty().await.unwrap());
- MultiMintWallet::new(localstore, seed, CurrencyUnit::Sat)
- .await
- .expect("failed to create multi mint wallet")
- }
- /// Helper to fund a MultiMintWallet at a specific mint
- async fn fund_multi_mint_wallet(
- wallet: &MultiMintWallet,
- mint_url: &MintUrl,
- amount: Amount,
- ) -> Amount {
- let mint_quote = wallet.mint_quote(mint_url, amount, None).await.unwrap();
- let invoice = Bolt11Invoice::from_str(&mint_quote.request).unwrap();
- pay_if_regtest(&get_test_temp_dir(), &invoice)
- .await
- .unwrap();
- let proofs = wallet
- .wait_for_mint_quote(
- mint_url,
- &mint_quote.id,
- SplitTarget::default(),
- None,
- std::time::Duration::from_secs(60),
- )
- .await
- .expect("mint failed");
- proofs.total_amount().unwrap()
- }
- /// Test the direct mint() function on MultiMintWallet
- ///
- /// This test verifies:
- /// 1. Create a mint quote
- /// 2. Pay the invoice
- /// 3. Poll until quote is paid (like a real wallet would)
- /// 4. Call mint() directly (not wait_for_mint_quote)
- /// 5. Verify tokens are received
- #[tokio::test(flavor = "multi_thread", worker_threads = 1)]
- async fn test_multi_mint_wallet_mint() {
- let multi_mint_wallet = create_test_multi_mint_wallet().await;
- let mint_url = MintUrl::from_str(&get_mint_url_from_env()).expect("invalid mint url");
- multi_mint_wallet
- .add_mint(mint_url.clone())
- .await
- .expect("failed to add mint");
- // Create mint quote
- let mint_quote = multi_mint_wallet
- .mint_quote(&mint_url, 100.into(), None)
- .await
- .unwrap();
- // Pay the invoice (in regtest mode) - for fake wallet, payment is simulated automatically
- let invoice = Bolt11Invoice::from_str(&mint_quote.request).unwrap();
- pay_if_regtest(&get_test_temp_dir(), &invoice)
- .await
- .unwrap();
- // Poll for quote to be paid (like a real wallet would)
- let mut quote_status = multi_mint_wallet
- .check_mint_quote(&mint_url, &mint_quote.id)
- .await
- .unwrap();
- let timeout = tokio::time::Duration::from_secs(30);
- let start = tokio::time::Instant::now();
- while quote_status.state != MintQuoteState::Paid && quote_status.state != MintQuoteState::Issued
- {
- if start.elapsed() > timeout {
- panic!(
- "Timeout waiting for quote to be paid, state: {:?}",
- quote_status.state
- );
- }
- tokio::time::sleep(tokio::time::Duration::from_millis(500)).await;
- quote_status = multi_mint_wallet
- .check_mint_quote(&mint_url, &mint_quote.id)
- .await
- .unwrap();
- }
- // Call mint() directly (quote should be Paid at this point)
- let proofs = multi_mint_wallet
- .mint(&mint_url, &mint_quote.id, SplitTarget::default(), None)
- .await
- .unwrap();
- let minted_amount = proofs.total_amount().unwrap();
- assert_eq!(minted_amount, 100.into(), "Should mint exactly 100 sats");
- // Verify balance
- let balance = multi_mint_wallet.total_balance().await.unwrap();
- assert_eq!(balance, 100.into(), "Total balance should be 100 sats");
- }
- /// Test the melt() function with automatic mint selection
- ///
- /// This test verifies:
- /// 1. Fund wallet at a mint
- /// 2. Call melt() without specifying mint (auto-selection)
- /// 3. Verify payment is made
- #[tokio::test(flavor = "multi_thread", worker_threads = 1)]
- async fn test_multi_mint_wallet_melt_auto_select() {
- let multi_mint_wallet = create_test_multi_mint_wallet().await;
- let mint_url = MintUrl::from_str(&get_mint_url_from_env()).expect("invalid mint url");
- multi_mint_wallet
- .add_mint(mint_url.clone())
- .await
- .expect("failed to add mint");
- // Fund the wallet
- let funded_amount = fund_multi_mint_wallet(&multi_mint_wallet, &mint_url, 100.into()).await;
- assert_eq!(funded_amount, 100.into());
- // Create an invoice to pay
- let invoice = create_invoice_for_env(Some(50)).await.unwrap();
- // Use melt() with auto-selection (no specific mint specified)
- let melt_result = multi_mint_wallet.melt(&invoice, None, None).await.unwrap();
- assert_eq!(
- melt_result.state,
- MeltQuoteState::Paid,
- "Melt should be paid"
- );
- assert_eq!(melt_result.amount, 50.into(), "Should melt 50 sats");
- // Verify balance decreased
- let balance = multi_mint_wallet.total_balance().await.unwrap();
- assert!(
- balance < 100.into(),
- "Balance should be less than 100 after melt"
- );
- }
- /// Test the receive() function on MultiMintWallet
- ///
- /// This test verifies:
- /// 1. Create a token from a wallet
- /// 2. Receive the token in a different MultiMintWallet
- /// 3. Verify the token value is received
- #[tokio::test(flavor = "multi_thread", worker_threads = 1)]
- async fn test_multi_mint_wallet_receive() {
- // Create sender wallet and fund it
- let sender_wallet = create_test_multi_mint_wallet().await;
- let mint_url = MintUrl::from_str(&get_mint_url_from_env()).expect("invalid mint url");
- sender_wallet
- .add_mint(mint_url.clone())
- .await
- .expect("failed to add mint");
- let funded_amount = fund_multi_mint_wallet(&sender_wallet, &mint_url, 100.into()).await;
- assert_eq!(funded_amount, 100.into());
- // Create a token to send
- let send_options = MultiMintSendOptions::default();
- let prepared_send = sender_wallet
- .prepare_send(mint_url.clone(), 50.into(), send_options)
- .await
- .unwrap();
- let token = prepared_send.confirm(None).await.unwrap();
- let token_string = token.to_string();
- // Create receiver wallet
- let receiver_wallet = create_test_multi_mint_wallet().await;
- // Add the same mint as trusted
- receiver_wallet
- .add_mint(mint_url.clone())
- .await
- .expect("failed to add mint");
- // Receive the token
- let receive_options = MultiMintReceiveOptions::default();
- let received_amount = receiver_wallet
- .receive(&token_string, receive_options)
- .await
- .unwrap();
- // Note: received amount may be slightly less due to fees
- assert!(
- received_amount > Amount::ZERO,
- "Should receive some amount, got {:?}",
- received_amount
- );
- // Verify receiver balance
- let receiver_balance = receiver_wallet.total_balance().await.unwrap();
- assert!(
- receiver_balance > Amount::ZERO,
- "Receiver should have balance"
- );
- // Verify sender balance decreased
- let sender_balance = sender_wallet.total_balance().await.unwrap();
- assert!(
- sender_balance < 100.into(),
- "Sender balance should be less than 100 after send"
- );
- }
- /// Test the receive() function with allow_untrusted option
- ///
- /// This test verifies:
- /// 1. Create a token from a known mint
- /// 2. Receive with a wallet that doesn't have the mint added
- /// 3. With allow_untrusted=true, the mint should be added automatically
- #[tokio::test(flavor = "multi_thread", worker_threads = 1)]
- async fn test_multi_mint_wallet_receive_untrusted() {
- // Create sender wallet and fund it
- let sender_wallet = create_test_multi_mint_wallet().await;
- let mint_url = MintUrl::from_str(&get_mint_url_from_env()).expect("invalid mint url");
- sender_wallet
- .add_mint(mint_url.clone())
- .await
- .expect("failed to add mint");
- let funded_amount = fund_multi_mint_wallet(&sender_wallet, &mint_url, 100.into()).await;
- assert_eq!(funded_amount, 100.into());
- // Create a token to send
- let send_options = MultiMintSendOptions::default();
- let prepared_send = sender_wallet
- .prepare_send(mint_url.clone(), 50.into(), send_options)
- .await
- .unwrap();
- let token = prepared_send.confirm(None).await.unwrap();
- let token_string = token.to_string();
- // Create receiver wallet WITHOUT adding the mint
- let receiver_wallet = create_test_multi_mint_wallet().await;
- // First, verify that receiving without allow_untrusted fails
- let receive_options = MultiMintReceiveOptions::default();
- let result = receiver_wallet
- .receive(&token_string, receive_options)
- .await;
- assert!(result.is_err(), "Should fail without allow_untrusted");
- // Now receive with allow_untrusted=true
- let receive_options = MultiMintReceiveOptions::default().allow_untrusted(true);
- let received_amount = receiver_wallet
- .receive(&token_string, receive_options)
- .await
- .unwrap();
- assert!(received_amount > Amount::ZERO, "Should receive some amount");
- // Verify the mint was added to the wallet
- assert!(
- receiver_wallet.has_mint(&mint_url).await,
- "Mint should be added to wallet"
- );
- }
- /// Test prepare_send() happy path
- ///
- /// This test verifies:
- /// 1. Fund wallet
- /// 2. Call prepare_send() successfully
- /// 3. Confirm the send and get a token
- /// 4. Verify the token is valid
- #[tokio::test(flavor = "multi_thread", worker_threads = 1)]
- async fn test_multi_mint_wallet_prepare_send_happy_path() {
- let multi_mint_wallet = create_test_multi_mint_wallet().await;
- let mint_url = MintUrl::from_str(&get_mint_url_from_env()).expect("invalid mint url");
- multi_mint_wallet
- .add_mint(mint_url.clone())
- .await
- .expect("failed to add mint");
- // Fund the wallet
- let funded_amount = fund_multi_mint_wallet(&multi_mint_wallet, &mint_url, 100.into()).await;
- assert_eq!(funded_amount, 100.into());
- // Prepare send
- let send_options = MultiMintSendOptions::default();
- let prepared_send = multi_mint_wallet
- .prepare_send(mint_url.clone(), 50.into(), send_options)
- .await
- .unwrap();
- // Get the token
- let token = prepared_send.confirm(None).await.unwrap();
- let token_string = token.to_string();
- // Verify the token can be parsed back
- let parsed_token = Token::from_str(&token_string).unwrap();
- let token_mint_url = parsed_token.mint_url().unwrap();
- assert_eq!(token_mint_url, mint_url, "Token mint URL should match");
- // Get token data to verify value
- let token_data = multi_mint_wallet
- .get_token_data(&parsed_token)
- .await
- .unwrap();
- assert_eq!(token_data.value, 50.into(), "Token value should be 50 sats");
- // Verify wallet balance decreased
- let balance = multi_mint_wallet.total_balance().await.unwrap();
- assert_eq!(balance, 50.into(), "Remaining balance should be 50 sats");
- }
- /// Test get_balances() across multiple operations
- ///
- /// This test verifies:
- /// 1. Empty wallet has zero balances
- /// 2. After minting, balance is updated
- /// 3. get_balances() returns per-mint breakdown
- #[tokio::test(flavor = "multi_thread", worker_threads = 1)]
- async fn test_multi_mint_wallet_get_balances() {
- let multi_mint_wallet = create_test_multi_mint_wallet().await;
- let mint_url = MintUrl::from_str(&get_mint_url_from_env()).expect("invalid mint url");
- multi_mint_wallet
- .add_mint(mint_url.clone())
- .await
- .expect("failed to add mint");
- // Check initial balances
- let balances = multi_mint_wallet.get_balances().await.unwrap();
- let initial_balance = balances.get(&mint_url).cloned().unwrap_or(Amount::ZERO);
- assert_eq!(initial_balance, Amount::ZERO, "Initial balance should be 0");
- // Fund the wallet
- fund_multi_mint_wallet(&multi_mint_wallet, &mint_url, 100.into()).await;
- // Check balances again
- let balances = multi_mint_wallet.get_balances().await.unwrap();
- let balance = balances.get(&mint_url).cloned().unwrap_or(Amount::ZERO);
- assert_eq!(balance, 100.into(), "Balance should be 100 sats");
- // Verify total_balance matches
- let total = multi_mint_wallet.total_balance().await.unwrap();
- assert_eq!(total, 100.into(), "Total balance should match");
- }
- /// Test list_proofs() function
- ///
- /// This test verifies:
- /// 1. Empty wallet has no proofs
- /// 2. After minting, proofs are listed correctly
- #[tokio::test(flavor = "multi_thread", worker_threads = 1)]
- async fn test_multi_mint_wallet_list_proofs() {
- let multi_mint_wallet = create_test_multi_mint_wallet().await;
- let mint_url = MintUrl::from_str(&get_mint_url_from_env()).expect("invalid mint url");
- multi_mint_wallet
- .add_mint(mint_url.clone())
- .await
- .expect("failed to add mint");
- // Check initial proofs
- let proofs = multi_mint_wallet.list_proofs().await.unwrap();
- let mint_proofs = proofs.get(&mint_url).cloned().unwrap_or_default();
- assert!(mint_proofs.is_empty(), "Should have no proofs initially");
- // Fund the wallet
- fund_multi_mint_wallet(&multi_mint_wallet, &mint_url, 100.into()).await;
- // Check proofs again
- let proofs = multi_mint_wallet.list_proofs().await.unwrap();
- let mint_proofs = proofs.get(&mint_url).cloned().unwrap_or_default();
- assert!(!mint_proofs.is_empty(), "Should have proofs after minting");
- // Verify proof total matches balance
- let proof_total: Amount = mint_proofs.total_amount().unwrap();
- assert_eq!(proof_total, 100.into(), "Proof total should be 100 sats");
- }
- /// Test mint management functions (add_mint, remove_mint, has_mint)
- ///
- /// This test verifies:
- /// 1. has_mint returns false for unknown mints
- /// 2. add_mint adds the mint
- /// 3. has_mint returns true after adding
- /// 4. remove_mint removes the mint
- /// 5. has_mint returns false after removal
- #[tokio::test(flavor = "multi_thread", worker_threads = 1)]
- async fn test_multi_mint_wallet_mint_management() {
- let multi_mint_wallet = create_test_multi_mint_wallet().await;
- let mint_url = MintUrl::from_str(&get_mint_url_from_env()).expect("invalid mint url");
- // Initially mint should not be in wallet
- assert!(
- !multi_mint_wallet.has_mint(&mint_url).await,
- "Mint should not be in wallet initially"
- );
- // Add the mint
- multi_mint_wallet
- .add_mint(mint_url.clone())
- .await
- .expect("failed to add mint");
- // Now mint should be in wallet
- assert!(
- multi_mint_wallet.has_mint(&mint_url).await,
- "Mint should be in wallet after adding"
- );
- // Get wallets should include this mint
- let wallets = multi_mint_wallet.get_wallets().await;
- assert!(!wallets.is_empty(), "Should have at least one wallet");
- // Get specific wallet
- let wallet = multi_mint_wallet.get_wallet(&mint_url).await;
- assert!(wallet.is_some(), "Should be able to get wallet for mint");
- // Remove the mint
- multi_mint_wallet.remove_mint(&mint_url).await;
- // Now mint should not be in wallet
- assert!(
- !multi_mint_wallet.has_mint(&mint_url).await,
- "Mint should not be in wallet after removal"
- );
- }
- /// Test check_all_mint_quotes() function
- ///
- /// This test verifies:
- /// 1. Create a mint quote
- /// 2. Pay the quote
- /// 3. Poll until quote is paid (like a real wallet would)
- /// 4. check_all_mint_quotes() processes paid quotes
- #[tokio::test(flavor = "multi_thread", worker_threads = 1)]
- async fn test_multi_mint_wallet_check_all_mint_quotes() {
- let multi_mint_wallet = create_test_multi_mint_wallet().await;
- let mint_url = MintUrl::from_str(&get_mint_url_from_env()).expect("invalid mint url");
- multi_mint_wallet
- .add_mint(mint_url.clone())
- .await
- .expect("failed to add mint");
- // Create a mint quote
- let mint_quote = multi_mint_wallet
- .mint_quote(&mint_url, 100.into(), None)
- .await
- .unwrap();
- // Pay the invoice (in regtest mode) - for fake wallet, payment is simulated automatically
- let invoice = Bolt11Invoice::from_str(&mint_quote.request).unwrap();
- pay_if_regtest(&get_test_temp_dir(), &invoice)
- .await
- .unwrap();
- // Poll for quote to be paid (like a real wallet would)
- let mut quote_status = multi_mint_wallet
- .check_mint_quote(&mint_url, &mint_quote.id)
- .await
- .unwrap();
- let timeout = tokio::time::Duration::from_secs(30);
- let start = tokio::time::Instant::now();
- while quote_status.state != MintQuoteState::Paid {
- if start.elapsed() > timeout {
- panic!(
- "Timeout waiting for quote to be paid, state: {:?}",
- quote_status.state
- );
- }
- tokio::time::sleep(tokio::time::Duration::from_millis(500)).await;
- quote_status = multi_mint_wallet
- .check_mint_quote(&mint_url, &mint_quote.id)
- .await
- .unwrap();
- }
- // Check all mint quotes - this should find the paid quote and mint
- let minted_amount = multi_mint_wallet
- .check_all_mint_quotes(Some(mint_url.clone()))
- .await
- .unwrap();
- assert_eq!(
- minted_amount,
- 100.into(),
- "Should mint 100 sats from paid quote"
- );
- // Verify balance
- let balance = multi_mint_wallet.total_balance().await.unwrap();
- assert_eq!(balance, 100.into(), "Balance should be 100 sats");
- }
- /// Test restore() function
- ///
- /// This test verifies:
- /// 1. Create and fund a wallet with a specific seed
- /// 2. Create a new wallet with the same seed
- /// 3. Call restore() to recover the proofs
- #[tokio::test(flavor = "multi_thread", worker_threads = 1)]
- async fn test_multi_mint_wallet_restore() {
- let seed = Mnemonic::generate(12).unwrap().to_seed_normalized("");
- let mint_url = MintUrl::from_str(&get_mint_url_from_env()).expect("invalid mint url");
- // Create first wallet and fund it
- {
- let localstore = Arc::new(memory::empty().await.unwrap());
- let wallet1 = MultiMintWallet::new(localstore, seed, CurrencyUnit::Sat)
- .await
- .expect("failed to create wallet");
- wallet1
- .add_mint(mint_url.clone())
- .await
- .expect("failed to add mint");
- let funded = fund_multi_mint_wallet(&wallet1, &mint_url, 100.into()).await;
- assert_eq!(funded, 100.into());
- }
- // wallet1 goes out of scope
- // Create second wallet with same seed but fresh storage
- let localstore2 = Arc::new(memory::empty().await.unwrap());
- let wallet2 = MultiMintWallet::new(localstore2, seed, CurrencyUnit::Sat)
- .await
- .expect("failed to create wallet");
- wallet2
- .add_mint(mint_url.clone())
- .await
- .expect("failed to add mint");
- // Initially should have no balance
- let balance_before = wallet2.total_balance().await.unwrap();
- assert_eq!(balance_before, Amount::ZERO, "Should start with no balance");
- // Restore from mint
- let restored = wallet2.restore(&mint_url).await.unwrap();
- assert_eq!(restored, 100.into(), "Should restore 100 sats");
- }
- /// Test melt_with_mint() with explicit mint selection
- ///
- /// This test verifies:
- /// 1. Fund wallet
- /// 2. Create melt quote at specific mint
- /// 3. Execute melt_with_mint()
- /// 4. Verify payment succeeded
- #[tokio::test(flavor = "multi_thread", worker_threads = 1)]
- async fn test_multi_mint_wallet_melt_with_mint() {
- let multi_mint_wallet = create_test_multi_mint_wallet().await;
- let mint_url = MintUrl::from_str(&get_mint_url_from_env()).expect("invalid mint url");
- multi_mint_wallet
- .add_mint(mint_url.clone())
- .await
- .expect("failed to add mint");
- // Fund the wallet
- fund_multi_mint_wallet(&multi_mint_wallet, &mint_url, 100.into()).await;
- // Create an invoice to pay
- let invoice = create_invoice_for_env(Some(50)).await.unwrap();
- // Create melt quote at specific mint
- let melt_quote = multi_mint_wallet
- .melt_quote(&mint_url, invoice, None)
- .await
- .unwrap();
- // Execute melt with specific mint
- let melt_result = multi_mint_wallet
- .melt_with_mint(&mint_url, &melt_quote.id)
- .await
- .unwrap();
- assert_eq!(
- melt_result.state,
- MeltQuoteState::Paid,
- "Melt should be paid"
- );
- // Check melt quote status
- let quote_status = multi_mint_wallet
- .check_melt_quote(&mint_url, &melt_quote.id)
- .await
- .unwrap();
- assert_eq!(
- quote_status.state,
- MeltQuoteState::Paid,
- "Quote status should be paid"
- );
- }
- /// Test unit() function returns correct currency unit
- #[tokio::test(flavor = "multi_thread", worker_threads = 1)]
- async fn test_multi_mint_wallet_unit() {
- let seed = Mnemonic::generate(12).unwrap().to_seed_normalized("");
- let localstore = Arc::new(memory::empty().await.unwrap());
- let wallet = MultiMintWallet::new(localstore, seed, CurrencyUnit::Sat)
- .await
- .expect("failed to create wallet");
- assert_eq!(wallet.unit(), &CurrencyUnit::Sat, "Unit should be Sat");
- }
- /// Test list_transactions() function
- ///
- /// This test verifies:
- /// 1. Initially no transactions
- /// 2. After minting, transaction is recorded
- /// 3. After melting, transaction is recorded
- #[tokio::test(flavor = "multi_thread", worker_threads = 1)]
- async fn test_multi_mint_wallet_list_transactions() {
- let multi_mint_wallet = create_test_multi_mint_wallet().await;
- let mint_url = MintUrl::from_str(&get_mint_url_from_env()).expect("invalid mint url");
- multi_mint_wallet
- .add_mint(mint_url.clone())
- .await
- .expect("failed to add mint");
- // Fund the wallet (this creates a mint transaction)
- fund_multi_mint_wallet(&multi_mint_wallet, &mint_url, 100.into()).await;
- // List all transactions
- let transactions = multi_mint_wallet.list_transactions(None).await.unwrap();
- assert!(
- !transactions.is_empty(),
- "Should have at least one transaction after minting"
- );
- // Create an invoice and melt (this creates a melt transaction)
- let invoice = create_invoice_for_env(Some(50)).await.unwrap();
- let melt_quote = multi_mint_wallet
- .melt_quote(&mint_url, invoice, None)
- .await
- .unwrap();
- multi_mint_wallet
- .melt_with_mint(&mint_url, &melt_quote.id)
- .await
- .unwrap();
- // List transactions again
- let transactions_after = multi_mint_wallet.list_transactions(None).await.unwrap();
- assert!(
- transactions_after.len() > transactions.len(),
- "Should have more transactions after melt"
- );
- }
|