From de4285bd9c36ae20a9f509174dcdc869f71c02dd Mon Sep 17 00:00:00 2001 From: ok300 <106775972+ok300@users.noreply.github.com> Date: Wed, 26 Mar 2025 15:55:57 +0000 Subject: [PATCH] Simplify `MultiMintWallet` interface (#664) --- crates/cdk-cli/src/main.rs | 42 ++++--------------- .../src/sub_commands/cat_device_login.rs | 20 ++++----- crates/cdk-cli/src/sub_commands/cat_login.rs | 20 ++++----- crates/cdk-cli/src/sub_commands/mint.rs | 13 ++---- .../src/sub_commands/mint_blind_auth.rs | 13 ++---- crates/cdk-cli/src/sub_commands/receive.rs | 26 ++++-------- crates/cdk-cli/src/sub_commands/restore.rs | 13 ++---- .../tests/payment_processor.rs | 3 +- crates/cdk-integration-tests/tests/regtest.rs | 10 ++--- crates/cdk/README.md | 4 +- crates/cdk/examples/mint-token.rs | 8 ++-- crates/cdk/examples/p2pk.rs | 8 ++-- crates/cdk/examples/proof-selection.rs | 8 ++-- crates/cdk/examples/wallet.rs | 8 ++-- crates/cdk/src/wallet/README.md | 4 +- crates/cdk/src/wallet/melt.rs | 8 ++-- crates/cdk/src/wallet/mint.rs | 8 ++-- crates/cdk/src/wallet/mod.rs | 4 +- crates/cdk/src/wallet/multi_mint_wallet.rs | 38 +++++++++++++++-- crates/cdk/src/wallet/receive.rs | 8 ++-- 20 files changed, 117 insertions(+), 149 deletions(-) diff --git a/crates/cdk-cli/src/main.rs b/crates/cdk-cli/src/main.rs index f7e07daa..64290add 100644 --- a/crates/cdk-cli/src/main.rs +++ b/crates/cdk-cli/src/main.rs @@ -165,6 +165,7 @@ async fn main() -> Result<()> { mnemonic } }; + let seed = mnemonic.to_seed_normalized(""); let mut wallets: Vec = Vec::new(); @@ -187,7 +188,7 @@ async fn main() -> Result<()> { wallets.push(wallet); } - let multi_mint_wallet = MultiMintWallet::new(wallets); + let multi_mint_wallet = MultiMintWallet::new(localstore, Arc::new(seed), wallets); match &args.command { Commands::DecodeToken(sub_command_args) => { @@ -198,14 +199,7 @@ async fn main() -> Result<()> { sub_commands::melt::pay(&multi_mint_wallet, sub_command_args).await } Commands::Receive(sub_command_args) => { - sub_commands::receive::receive( - &multi_mint_wallet, - localstore, - &mnemonic.to_seed_normalized(""), - sub_command_args, - &work_dir, - ) - .await + sub_commands::receive::receive(&multi_mint_wallet, sub_command_args, &work_dir).await } Commands::Send(sub_command_args) => { sub_commands::send::send(&multi_mint_wallet, sub_command_args).await @@ -217,13 +211,7 @@ async fn main() -> Result<()> { sub_commands::mint_info::mint_info(args.proxy, sub_command_args).await } Commands::Mint(sub_command_args) => { - sub_commands::mint::mint( - &multi_mint_wallet, - &mnemonic.to_seed_normalized(""), - localstore, - sub_command_args, - ) - .await + sub_commands::mint::mint(&multi_mint_wallet, sub_command_args).await } Commands::MintPending => { sub_commands::pending_mints::mint_pending(&multi_mint_wallet).await @@ -232,13 +220,7 @@ async fn main() -> Result<()> { sub_commands::burn::burn(&multi_mint_wallet, sub_command_args).await } Commands::Restore(sub_command_args) => { - sub_commands::restore::restore( - &multi_mint_wallet, - &mnemonic.to_seed_normalized(""), - localstore, - sub_command_args, - ) - .await + sub_commands::restore::restore(&multi_mint_wallet, sub_command_args).await } Commands::UpdateMintUrl(sub_command_args) => { sub_commands::update_mint_url::update_mint_url(&multi_mint_wallet, sub_command_args) @@ -259,28 +241,18 @@ async fn main() -> Result<()> { Commands::MintBlindAuth(sub_command_args) => { sub_commands::mint_blind_auth::mint_blind_auth( &multi_mint_wallet, - &mnemonic.to_seed_normalized(""), - localstore, sub_command_args, &work_dir, ) .await } Commands::CatLogin(sub_command_args) => { - sub_commands::cat_login::cat_login( - &multi_mint_wallet, - &mnemonic.to_seed_normalized(""), - localstore, - sub_command_args, - &work_dir, - ) - .await + sub_commands::cat_login::cat_login(&multi_mint_wallet, sub_command_args, &work_dir) + .await } Commands::CatDeviceLogin(sub_command_args) => { sub_commands::cat_device_login::cat_device_login( &multi_mint_wallet, - &mnemonic.to_seed_normalized(""), - localstore, sub_command_args, &work_dir, ) diff --git a/crates/cdk-cli/src/sub_commands/cat_device_login.rs b/crates/cdk-cli/src/sub_commands/cat_device_login.rs index 12b885fe..52232f95 100644 --- a/crates/cdk-cli/src/sub_commands/cat_device_login.rs +++ b/crates/cdk-cli/src/sub_commands/cat_device_login.rs @@ -1,14 +1,12 @@ use std::path::Path; use std::str::FromStr; -use std::sync::Arc; use std::time::Duration; -use anyhow::Result; -use cdk::cdk_database::{Error, WalletDatabase}; +use anyhow::{anyhow, Result}; use cdk::mint_url::MintUrl; use cdk::nuts::{CurrencyUnit, MintInfo}; use cdk::wallet::types::WalletKey; -use cdk::wallet::{MultiMintWallet, Wallet}; +use cdk::wallet::MultiMintWallet; use cdk::OidcClient; use clap::Args; use serde::{Deserialize, Serialize}; @@ -32,8 +30,6 @@ pub struct CatDeviceLoginSubCommand { pub async fn cat_device_login( multi_mint_wallet: &MultiMintWallet, - seed: &[u8], - localstore: Arc + Sync + Send>, sub_command_args: &CatDeviceLoginSubCommand, work_dir: &Path, ) -> Result<()> { @@ -46,14 +42,16 @@ pub async fn cat_device_login( { Some(wallet) => wallet.clone(), None => { - let wallet = Wallet::new(&mint_url.to_string(), unit, localstore, seed, None)?; - - multi_mint_wallet.add_wallet(wallet.clone()).await; - wallet + multi_mint_wallet + .create_and_add_wallet(&mint_url.to_string(), unit, None) + .await? } }; - let mint_info = wallet.get_mint_info().await?.expect("Mint info not found"); + let mint_info = wallet + .get_mint_info() + .await? + .ok_or(anyhow!("Mint info not found"))?; let (access_token, refresh_token) = get_device_code_token(&mint_info, &sub_command_args.client_id).await; diff --git a/crates/cdk-cli/src/sub_commands/cat_login.rs b/crates/cdk-cli/src/sub_commands/cat_login.rs index 6a06dfb9..13e73f92 100644 --- a/crates/cdk-cli/src/sub_commands/cat_login.rs +++ b/crates/cdk-cli/src/sub_commands/cat_login.rs @@ -1,13 +1,11 @@ use std::path::Path; use std::str::FromStr; -use std::sync::Arc; -use anyhow::Result; -use cdk::cdk_database::{Error, WalletDatabase}; +use anyhow::{anyhow, Result}; use cdk::mint_url::MintUrl; use cdk::nuts::{CurrencyUnit, MintInfo}; use cdk::wallet::types::WalletKey; -use cdk::wallet::{MultiMintWallet, Wallet}; +use cdk::wallet::MultiMintWallet; use cdk::OidcClient; use clap::Args; use serde::{Deserialize, Serialize}; @@ -34,8 +32,6 @@ pub struct CatLoginSubCommand { pub async fn cat_login( multi_mint_wallet: &MultiMintWallet, - seed: &[u8], - localstore: Arc + Sync + Send>, sub_command_args: &CatLoginSubCommand, work_dir: &Path, ) -> Result<()> { @@ -48,14 +44,16 @@ pub async fn cat_login( { Some(wallet) => wallet.clone(), None => { - let wallet = Wallet::new(&mint_url.to_string(), unit, localstore, seed, None)?; - - multi_mint_wallet.add_wallet(wallet.clone()).await; - wallet + multi_mint_wallet + .create_and_add_wallet(&mint_url.to_string(), unit, None) + .await? } }; - let mint_info = wallet.get_mint_info().await?.expect("Mint info not found"); + let mint_info = wallet + .get_mint_info() + .await? + .ok_or(anyhow!("Mint info not found"))?; let (access_token, refresh_token) = get_access_token( &mint_info, diff --git a/crates/cdk-cli/src/sub_commands/mint.rs b/crates/cdk-cli/src/sub_commands/mint.rs index 9b465c45..b7976b74 100644 --- a/crates/cdk-cli/src/sub_commands/mint.rs +++ b/crates/cdk-cli/src/sub_commands/mint.rs @@ -1,14 +1,12 @@ use std::str::FromStr; -use std::sync::Arc; use anyhow::{anyhow, Result}; use cdk::amount::SplitTarget; -use cdk::cdk_database::{Error, WalletDatabase}; use cdk::mint_url::MintUrl; use cdk::nuts::nut00::ProofsMethods; use cdk::nuts::{CurrencyUnit, MintQuoteState, NotificationPayload}; use cdk::wallet::types::WalletKey; -use cdk::wallet::{MultiMintWallet, Wallet, WalletSubscription}; +use cdk::wallet::{MultiMintWallet, WalletSubscription}; use cdk::Amount; use clap::Args; use serde::{Deserialize, Serialize}; @@ -32,8 +30,6 @@ pub struct MintSubCommand { pub async fn mint( multi_mint_wallet: &MultiMintWallet, - seed: &[u8], - localstore: Arc + Sync + Send>, sub_command_args: &MintSubCommand, ) -> Result<()> { let mint_url = sub_command_args.mint_url.clone(); @@ -46,10 +42,9 @@ pub async fn mint( { Some(wallet) => wallet.clone(), None => { - let wallet = Wallet::new(&mint_url.to_string(), unit, localstore, seed, None)?; - - multi_mint_wallet.add_wallet(wallet.clone()).await; - wallet + multi_mint_wallet + .create_and_add_wallet(&mint_url.to_string(), unit, None) + .await? } }; diff --git a/crates/cdk-cli/src/sub_commands/mint_blind_auth.rs b/crates/cdk-cli/src/sub_commands/mint_blind_auth.rs index a13d0ff7..d67b5ed3 100644 --- a/crates/cdk-cli/src/sub_commands/mint_blind_auth.rs +++ b/crates/cdk-cli/src/sub_commands/mint_blind_auth.rs @@ -1,13 +1,11 @@ use std::path::Path; use std::str::FromStr; -use std::sync::Arc; use anyhow::{anyhow, Result}; -use cdk::cdk_database::{Error, WalletDatabase}; use cdk::mint_url::MintUrl; use cdk::nuts::{CurrencyUnit, MintInfo}; use cdk::wallet::types::WalletKey; -use cdk::wallet::{MultiMintWallet, Wallet}; +use cdk::wallet::MultiMintWallet; use cdk::{Amount, OidcClient}; use clap::Args; use serde::{Deserialize, Serialize}; @@ -31,8 +29,6 @@ pub struct MintBlindAuthSubCommand { pub async fn mint_blind_auth( multi_mint_wallet: &MultiMintWallet, - seed: &[u8], - localstore: Arc + Sync + Send>, sub_command_args: &MintBlindAuthSubCommand, work_dir: &Path, ) -> Result<()> { @@ -45,10 +41,9 @@ pub async fn mint_blind_auth( { Some(wallet) => wallet.clone(), None => { - let wallet = Wallet::new(&mint_url.to_string(), unit, localstore, seed, None)?; - - multi_mint_wallet.add_wallet(wallet.clone()).await; - wallet + multi_mint_wallet + .create_and_add_wallet(&mint_url.to_string(), unit, None) + .await? } }; diff --git a/crates/cdk-cli/src/sub_commands/receive.rs b/crates/cdk-cli/src/sub_commands/receive.rs index 4ce212f5..9b34af78 100644 --- a/crates/cdk-cli/src/sub_commands/receive.rs +++ b/crates/cdk-cli/src/sub_commands/receive.rs @@ -1,15 +1,12 @@ use std::collections::HashSet; use std::path::Path; use std::str::FromStr; -use std::sync::Arc; use anyhow::{anyhow, Result}; -use cdk::cdk_database::{self, WalletDatabase}; use cdk::nuts::{SecretKey, Token}; use cdk::util::unix_time; use cdk::wallet::multi_mint_wallet::MultiMintWallet; use cdk::wallet::types::WalletKey; -use cdk::wallet::Wallet; use cdk::Amount; use clap::Args; use nostr_sdk::nips::nip04; @@ -40,8 +37,6 @@ pub struct ReceiveSubCommand { pub async fn receive( multi_mint_wallet: &MultiMintWallet, - localstore: Arc + Send + Sync>, - seed: &[u8], sub_command_args: &ReceiveSubCommand, work_dir: &Path, ) -> Result<()> { @@ -68,8 +63,6 @@ pub async fn receive( Some(token_str) => { receive_token( multi_mint_wallet, - localstore, - seed, token_str, &signing_keys, &sub_command_args.preimage, @@ -110,8 +103,6 @@ pub async fn receive( for token_str in &tokens { match receive_token( multi_mint_wallet, - localstore.clone(), - seed, token_str, &signing_keys, &sub_command_args.preimage, @@ -138,8 +129,6 @@ pub async fn receive( async fn receive_token( multi_mint_wallet: &MultiMintWallet, - localstore: Arc + Send + Sync>, - seed: &[u8], token_str: &str, signing_keys: &[SecretKey], preimage: &[String], @@ -151,14 +140,13 @@ async fn receive_token( let wallet_key = WalletKey::new(mint_url.clone(), token.unit().unwrap_or_default()); if multi_mint_wallet.get_wallet(&wallet_key).await.is_none() { - let wallet = Wallet::new( - &mint_url.to_string(), - token.unit().unwrap_or_default(), - localstore, - seed, - None, - )?; - multi_mint_wallet.add_wallet(wallet).await; + multi_mint_wallet + .create_and_add_wallet( + &mint_url.to_string(), + token.unit().unwrap_or_default(), + None, + ) + .await?; } let amount = multi_mint_wallet diff --git a/crates/cdk-cli/src/sub_commands/restore.rs b/crates/cdk-cli/src/sub_commands/restore.rs index 41d7839b..e67bb794 100644 --- a/crates/cdk-cli/src/sub_commands/restore.rs +++ b/crates/cdk-cli/src/sub_commands/restore.rs @@ -1,12 +1,10 @@ use std::str::FromStr; -use std::sync::Arc; use anyhow::Result; -use cdk::cdk_database::{Error, WalletDatabase}; use cdk::mint_url::MintUrl; use cdk::nuts::CurrencyUnit; use cdk::wallet::types::WalletKey; -use cdk::wallet::{MultiMintWallet, Wallet}; +use cdk::wallet::MultiMintWallet; use clap::Args; #[derive(Args)] @@ -20,8 +18,6 @@ pub struct RestoreSubCommand { pub async fn restore( multi_mint_wallet: &MultiMintWallet, - seed: &[u8], - localstore: Arc + Sync + Send>, sub_command_args: &RestoreSubCommand, ) -> Result<()> { let unit = CurrencyUnit::from_str(&sub_command_args.unit)?; @@ -33,10 +29,9 @@ pub async fn restore( { Some(wallet) => wallet.clone(), None => { - let wallet = Wallet::new(&mint_url.to_string(), unit, localstore, seed, None)?; - - multi_mint_wallet.add_wallet(wallet.clone()).await; - wallet + multi_mint_wallet + .create_and_add_wallet(&mint_url.to_string(), unit, None) + .await? } }; diff --git a/crates/cdk-integration-tests/tests/payment_processor.rs b/crates/cdk-integration-tests/tests/payment_processor.rs index 5a6b1ab2..5e9088dc 100644 --- a/crates/cdk-integration-tests/tests/payment_processor.rs +++ b/crates/cdk-integration-tests/tests/payment_processor.rs @@ -121,12 +121,11 @@ async fn test_pay_invoice_twice() -> Result<()> { return Ok(()); } - let seed = Mnemonic::generate(12)?.to_seed_normalized(""); let wallet = Wallet::new( &get_mint_url("0"), CurrencyUnit::Sat, Arc::new(memory::empty().await?), - &seed, + &Mnemonic::generate(12)?.to_seed_normalized(""), None, )?; diff --git a/crates/cdk-integration-tests/tests/regtest.rs b/crates/cdk-integration-tests/tests/regtest.rs index 4c38f152..2a781bc0 100644 --- a/crates/cdk-integration-tests/tests/regtest.rs +++ b/crates/cdk-integration-tests/tests/regtest.rs @@ -257,12 +257,11 @@ async fn test_restore() -> Result<()> { async fn test_pay_invoice_twice() -> anyhow::Result<()> { let lnd_client = init_lnd_client().await; - let seed = Mnemonic::generate(12).unwrap().to_seed_normalized(""); let wallet = Wallet::new( &get_mint_url("0"), CurrencyUnit::Sat, Arc::new(memory::empty().await.unwrap()), - &seed, + &Mnemonic::generate(12).unwrap().to_seed_normalized(""), None, )?; @@ -328,12 +327,11 @@ async fn test_pay_invoice_twice() -> anyhow::Result<()> { async fn test_internal_payment() -> Result<()> { let lnd_client = init_lnd_client().await; - let seed = Mnemonic::generate(12)?.to_seed_normalized(""); let wallet = Wallet::new( &get_mint_url("0"), CurrencyUnit::Sat, Arc::new(memory::empty().await?), - &seed, + &Mnemonic::generate(12)?.to_seed_normalized(""), None, )?; @@ -349,13 +347,11 @@ async fn test_internal_payment() -> Result<()> { assert!(wallet.total_balance().await? == 100.into()); - let seed = Mnemonic::generate(12)?.to_seed_normalized(""); - let wallet_2 = Wallet::new( &get_mint_url("0"), CurrencyUnit::Sat, Arc::new(memory::empty().await?), - &seed, + &Mnemonic::generate(12)?.to_seed_normalized(""), None, )?; diff --git a/crates/cdk/README.md b/crates/cdk/README.md index 06cdc35a..bc844672 100644 --- a/crates/cdk/README.md +++ b/crates/cdk/README.md @@ -59,14 +59,14 @@ use cdk::wallet::Wallet; #[cfg(feature = "wallet")] use cdk::wallet::SendOptions; use cdk::Amount; -use rand::Rng; +use rand::random; use tokio::time::sleep; #[tokio::main] async fn main() { #[cfg(feature = "wallet")] { - let seed = rand::thread_rng().gen::<[u8; 32]>(); + let seed = random::<[u8; 32]>(); let mint_url = "https://testnut.cashu.space"; let unit = CurrencyUnit::Sat; diff --git a/crates/cdk/examples/mint-token.rs b/crates/cdk/examples/mint-token.rs index c327b5b4..cc2e3a2b 100644 --- a/crates/cdk/examples/mint-token.rs +++ b/crates/cdk/examples/mint-token.rs @@ -7,7 +7,7 @@ use cdk::nuts::{CurrencyUnit, MintQuoteState, NotificationPayload}; use cdk::wallet::{SendOptions, Wallet, WalletSubscription}; use cdk::Amount; use cdk_sqlite::wallet::memory; -use rand::Rng; +use rand::random; use tracing_subscriber::EnvFilter; #[tokio::main] @@ -22,10 +22,10 @@ async fn main() -> Result<(), Error> { tracing_subscriber::fmt().with_env_filter(env_filter).init(); // Initialize the memory store for the wallet - let localstore = memory::empty().await?; + let localstore = Arc::new(memory::empty().await?); // Generate a random seed for the wallet - let seed = rand::thread_rng().gen::<[u8; 32]>(); + let seed = random::<[u8; 32]>(); // Define the mint URL and currency unit let mint_url = "https://testnut.cashu.space"; @@ -33,7 +33,7 @@ async fn main() -> Result<(), Error> { let amount = Amount::from(10); // Create a new wallet - let wallet = Wallet::new(mint_url, unit, Arc::new(localstore), &seed, None)?; + let wallet = Wallet::new(mint_url, unit, localstore, &seed, None)?; // Request a mint quote from the wallet let quote = wallet.mint_quote(amount, None).await?; diff --git a/crates/cdk/examples/p2pk.rs b/crates/cdk/examples/p2pk.rs index 9060fec7..87060a30 100644 --- a/crates/cdk/examples/p2pk.rs +++ b/crates/cdk/examples/p2pk.rs @@ -6,7 +6,7 @@ use cdk::nuts::{CurrencyUnit, MintQuoteState, NotificationPayload, SecretKey, Sp use cdk::wallet::{SendOptions, Wallet, WalletSubscription}; use cdk::Amount; use cdk_sqlite::wallet::memory; -use rand::Rng; +use rand::random; use tracing_subscriber::EnvFilter; #[tokio::main] @@ -21,10 +21,10 @@ async fn main() -> Result<(), Error> { tracing_subscriber::fmt().with_env_filter(env_filter).init(); // Initialize the memory store for the wallet - let localstore = memory::empty().await?; + let localstore = Arc::new(memory::empty().await?); // Generate a random seed for the wallet - let seed = rand::thread_rng().gen::<[u8; 32]>(); + let seed = random::<[u8; 32]>(); // Define the mint URL and currency unit let mint_url = "https://testnut.cashu.space"; @@ -32,7 +32,7 @@ async fn main() -> Result<(), Error> { let amount = Amount::from(100); // Create a new wallet - let wallet = Wallet::new(mint_url, unit, Arc::new(localstore), &seed, None).unwrap(); + let wallet = Wallet::new(mint_url, unit, localstore, &seed, None).unwrap(); // Request a mint quote from the wallet let quote = wallet.mint_quote(amount, None).await?; diff --git a/crates/cdk/examples/proof-selection.rs b/crates/cdk/examples/proof-selection.rs index 95b60156..4f830403 100644 --- a/crates/cdk/examples/proof-selection.rs +++ b/crates/cdk/examples/proof-selection.rs @@ -9,22 +9,22 @@ use cdk::nuts::{CurrencyUnit, MintQuoteState, NotificationPayload}; use cdk::wallet::{Wallet, WalletSubscription}; use cdk::Amount; use cdk_sqlite::wallet::memory; -use rand::Rng; +use rand::random; #[tokio::main] async fn main() -> Result<(), Box> { // Generate a random seed for the wallet - let seed = rand::thread_rng().gen::<[u8; 32]>(); + let seed = random::<[u8; 32]>(); // Mint URL and currency unit let mint_url = "https://testnut.cashu.space"; let unit = CurrencyUnit::Sat; // Initialize the memory store - let localstore = memory::empty().await?; + let localstore = Arc::new(memory::empty().await?); // Create a new wallet - let wallet = Wallet::new(mint_url, unit, Arc::new(localstore), &seed, None).unwrap(); + let wallet = Wallet::new(mint_url, unit, localstore, &seed, None)?; // Amount to mint for amount in [64] { diff --git a/crates/cdk/examples/wallet.rs b/crates/cdk/examples/wallet.rs index c17bd83f..b5f9fe4e 100644 --- a/crates/cdk/examples/wallet.rs +++ b/crates/cdk/examples/wallet.rs @@ -7,13 +7,13 @@ use cdk::nuts::{CurrencyUnit, MintQuoteState}; use cdk::wallet::{SendOptions, Wallet}; use cdk::Amount; use cdk_sqlite::wallet::memory; -use rand::Rng; +use rand::random; use tokio::time::sleep; #[tokio::main] async fn main() -> Result<(), Box> { // Generate a random seed for the wallet - let seed = rand::thread_rng().gen::<[u8; 32]>(); + let seed = random::<[u8; 32]>(); // Mint URL and currency unit let mint_url = "https://testnut.cashu.space"; @@ -21,10 +21,10 @@ async fn main() -> Result<(), Box> { let amount = Amount::from(10); // Initialize the memory store - let localstore = memory::empty().await?; + let localstore = Arc::new(memory::empty().await?); // Create a new wallet - let wallet = Wallet::new(mint_url, unit, Arc::new(localstore), &seed, None).unwrap(); + let wallet = Wallet::new(mint_url, unit, localstore, &seed, None)?; // Request a mint quote from the wallet let quote = wallet.mint_quote(amount, None).await?; diff --git a/crates/cdk/src/wallet/README.md b/crates/cdk/src/wallet/README.md index ec9daaa6..59a5fa54 100644 --- a/crates/cdk/src/wallet/README.md +++ b/crates/cdk/src/wallet/README.md @@ -11,11 +11,11 @@ The CDK [`Wallet`] is a high level Cashu wallet. The [`Wallet`] is for a single use cdk::nuts::CurrencyUnit; use cdk::wallet::Wallet; use cdk_sqlite::wallet::memory; - use rand::Rng; + use rand::random; #[tokio::main] async fn main() -> anyhow::Result<()> { - let seed = rand::thread_rng().gen::<[u8; 32]>(); + let seed = random::<[u8; 32]>(); let mint_url = "https://testnut.cashu.space"; let unit = CurrencyUnit::Sat; diff --git a/crates/cdk/src/wallet/melt.rs b/crates/cdk/src/wallet/melt.rs index ada8686a..efca827a 100644 --- a/crates/cdk/src/wallet/melt.rs +++ b/crates/cdk/src/wallet/melt.rs @@ -23,11 +23,11 @@ impl Wallet { /// use cdk_sqlite::wallet::memory; /// use cdk::nuts::CurrencyUnit; /// use cdk::wallet::Wallet; - /// use rand::Rng; + /// use rand::random; /// /// #[tokio::main] /// async fn main() -> anyhow::Result<()> { - /// let seed = rand::thread_rng().gen::<[u8; 32]>(); + /// let seed = random::<[u8; 32]>(); /// let mint_url = "https://testnut.cashu.space"; /// let unit = CurrencyUnit::Sat; /// @@ -254,11 +254,11 @@ impl Wallet { /// use cdk_sqlite::wallet::memory; /// use cdk::nuts::CurrencyUnit; /// use cdk::wallet::Wallet; - /// use rand::Rng; + /// use rand::random; /// /// #[tokio::main] /// async fn main() -> anyhow::Result<()> { - /// let seed = rand::thread_rng().gen::<[u8; 32]>(); + /// let seed = random::<[u8; 32]>(); /// let mint_url = "https://testnut.cashu.space"; /// let unit = CurrencyUnit::Sat; /// diff --git a/crates/cdk/src/wallet/mint.rs b/crates/cdk/src/wallet/mint.rs index 21b76a4b..a4e3e5f3 100644 --- a/crates/cdk/src/wallet/mint.rs +++ b/crates/cdk/src/wallet/mint.rs @@ -24,11 +24,11 @@ impl Wallet { /// use cdk_sqlite::wallet::memory; /// use cdk::nuts::CurrencyUnit; /// use cdk::wallet::Wallet; - /// use rand::Rng; + /// use rand::random; /// /// #[tokio::main] /// async fn main() -> anyhow::Result<()> { - /// let seed = rand::thread_rng().gen::<[u8; 32]>(); + /// let seed = random::<[u8; 32]>(); /// let mint_url = "https://testnut.cashu.space"; /// let unit = CurrencyUnit::Sat; /// @@ -147,11 +147,11 @@ impl Wallet { /// use cdk::nuts::nut00::ProofsMethods; /// use cdk::nuts::CurrencyUnit; /// use cdk::wallet::Wallet; - /// use rand::Rng; + /// use rand::random; /// /// #[tokio::main] /// async fn main() -> Result<()> { - /// let seed = rand::thread_rng().gen::<[u8; 32]>(); + /// let seed = random::<[u8; 32]>(); /// let mint_url = "https://testnut.cashu.space"; /// let unit = CurrencyUnit::Sat; /// diff --git a/crates/cdk/src/wallet/mod.rs b/crates/cdk/src/wallet/mod.rs index 74c998ec..88b1f451 100644 --- a/crates/cdk/src/wallet/mod.rs +++ b/crates/cdk/src/wallet/mod.rs @@ -139,10 +139,10 @@ impl Wallet { /// use cdk_sqlite::wallet::memory; /// use cdk::nuts::CurrencyUnit; /// use cdk::wallet::{Wallet, WalletBuilder}; - /// use rand::Rng; + /// use rand::random; /// /// async fn test() -> anyhow::Result<()> { - /// let seed = rand::thread_rng().gen::<[u8; 32]>(); + /// let seed = random::<[u8; 32]>(); /// let mint_url = "https://testnut.cashu.space"; /// let unit = CurrencyUnit::Sat; /// diff --git a/crates/cdk/src/wallet/multi_mint_wallet.rs b/crates/cdk/src/wallet/multi_mint_wallet.rs index 5fd43dcc..f5980da7 100644 --- a/crates/cdk/src/wallet/multi_mint_wallet.rs +++ b/crates/cdk/src/wallet/multi_mint_wallet.rs @@ -7,6 +7,9 @@ use std::collections::{BTreeMap, HashMap}; use std::str::FromStr; use std::sync::Arc; +use anyhow::Result; +use cdk_common::database; +use cdk_common::database::WalletDatabase; use cdk_common::wallet::WalletKey; use tokio::sync::Mutex; use tracing::instrument; @@ -23,14 +26,23 @@ use crate::{ensure_cdk, Amount, Wallet}; /// Multi Mint Wallet #[derive(Debug, Clone)] pub struct MultiMintWallet { + /// Storage backend + pub localstore: Arc + Send + Sync>, + seed: Arc<[u8]>, /// Wallets pub wallets: Arc>>, } impl MultiMintWallet { - /// New Multimint wallet - pub fn new(wallets: Vec) -> Self { + /// Create a new [MultiMintWallet] with initial wallets + pub fn new( + localstore: Arc + Send + Sync>, + seed: Arc<[u8]>, + wallets: Vec, + ) -> Self { Self { + localstore, + seed, wallets: Arc::new(Mutex::new( wallets .into_iter() @@ -40,7 +52,7 @@ impl MultiMintWallet { } } - /// Add wallet to MultiMintWallet + /// Adds a [Wallet] to this [MultiMintWallet] #[instrument(skip(self, wallet))] pub async fn add_wallet(&self, wallet: Wallet) { let wallet_key = WalletKey::new(wallet.mint_url.clone(), wallet.unit.clone()); @@ -50,6 +62,26 @@ impl MultiMintWallet { wallets.insert(wallet_key, wallet); } + /// Creates a new [Wallet] and adds it to this [MultiMintWallet] + pub async fn create_and_add_wallet( + &self, + mint_url: &str, + unit: CurrencyUnit, + target_proof_count: Option, + ) -> Result { + let wallet = Wallet::new( + mint_url, + unit, + self.localstore.clone(), + self.seed.as_ref(), + target_proof_count, + )?; + + self.add_wallet(wallet.clone()).await; + + Ok(wallet) + } + /// Remove Wallet from MultiMintWallet #[instrument(skip(self))] pub async fn remove_wallet(&self, wallet_key: &WalletKey) { diff --git a/crates/cdk/src/wallet/receive.rs b/crates/cdk/src/wallet/receive.rs index 4402053e..a7a2cec8 100644 --- a/crates/cdk/src/wallet/receive.rs +++ b/crates/cdk/src/wallet/receive.rs @@ -167,11 +167,11 @@ impl Wallet { /// use cdk_sqlite::wallet::memory; /// use cdk::nuts::CurrencyUnit; /// use cdk::wallet::Wallet; - /// use rand::Rng; + /// use rand::random; /// /// #[tokio::main] /// async fn main() -> anyhow::Result<()> { - /// let seed = rand::thread_rng().gen::<[u8; 32]>(); + /// let seed = random::<[u8; 32]>(); /// let mint_url = "https://testnut.cashu.space"; /// let unit = CurrencyUnit::Sat; /// @@ -221,11 +221,11 @@ impl Wallet { /// use cdk::nuts::CurrencyUnit; /// use cdk::wallet::Wallet; /// use cdk::util::hex; - /// use rand::Rng; + /// use rand::random; /// /// #[tokio::main] /// async fn main() -> anyhow::Result<()> { - /// let seed = rand::thread_rng().gen::<[u8; 32]>(); + /// let seed = random::<[u8; 32]>(); /// let mint_url = "https://testnut.cashu.space"; /// let unit = CurrencyUnit::Sat; ///