From f7d9a1b5dbb446c33ebcb82ac13ab65fb161abc5 Mon Sep 17 00:00:00 2001 From: C Date: Tue, 4 Mar 2025 16:44:34 -0300 Subject: [PATCH] Drop the in-memory database (#613) * Drop the in-memory database Fixes #607 This PR drops the implementation of in-memory database traits. They are useful for testing purposes since the tests should test our codebase and assume the database works as expected (although a follow-up PR should write a sanity test suite for all database trait implementors). As complexity is worth with database requirements to simplify complexity and add more robustness, for instance, with the following plans to add support for transactions or buffered writes, it would become more complex and time-consuming to support a correct database trait. This PR drops the implementation and replaces it with a SQLite memory instance * Remove OnceCell Without this change, a single Mint is shared for all tests, and the first tests to run and shutdown makes the other databases (not-reachable, as dropping the tokio engine would also drop the database instance). There is no real reason, other than perhaps performance. The mint should perhaps run in their own tokio engine and share channels as API interfaces, or a new instance should be created in each tests * Fixed bug with foreign keys [1] https://gist.github.com/crodas/bad00997c63bd5ac58db3c5bd90747ed * Show more debug on failure * Remove old code * Remove old references to WalletMemoryDatabase --- .../src/init_pure_tests.rs | 13 +- .../tests/fake_wallet.rs | 57 +- .../tests/integration_tests_pure.rs | 4 +- crates/cdk-integration-tests/tests/mint.rs | 21 +- crates/cdk-integration-tests/tests/regtest.rs | 24 +- crates/cdk-sqlite/src/common.rs | 29 ++ crates/cdk-sqlite/src/lib.rs | 2 + crates/cdk-sqlite/src/mint/memory.rs | 61 +++ crates/cdk-sqlite/src/mint/mod.rs | 28 +- crates/cdk-sqlite/src/wallet/memory.rs | 12 + crates/cdk-sqlite/src/wallet/mod.rs | 26 +- crates/cdk/Cargo.toml | 1 + crates/cdk/README.md | 6 +- crates/cdk/examples/mint-token.rs | 4 +- crates/cdk/examples/p2pk.rs | 4 +- crates/cdk/examples/proof-selection.rs | 4 +- crates/cdk/examples/wallet.rs | 4 +- crates/cdk/src/cdk_database/mint_memory.rs | 493 ------------------ crates/cdk/src/cdk_database/mod.rs | 11 - crates/cdk/src/cdk_database/wallet_memory.rs | 356 ------------- crates/cdk/src/lib.rs | 6 +- crates/cdk/src/mint/mod.rs | 15 +- crates/cdk/src/wallet/README.md | 16 +- crates/cdk/src/wallet/keysets.rs | 2 + crates/cdk/src/wallet/melt.rs | 8 +- crates/cdk/src/wallet/mint.rs | 8 +- crates/cdk/src/wallet/mod.rs | 15 +- crates/cdk/src/wallet/receive.rs | 8 +- misc/itests.sh | 3 +- 29 files changed, 237 insertions(+), 1004 deletions(-) create mode 100644 crates/cdk-sqlite/src/common.rs create mode 100644 crates/cdk-sqlite/src/mint/memory.rs create mode 100644 crates/cdk-sqlite/src/wallet/memory.rs delete mode 100644 crates/cdk/src/cdk_database/mint_memory.rs delete mode 100644 crates/cdk/src/cdk_database/mod.rs delete mode 100644 crates/cdk/src/cdk_database/wallet_memory.rs diff --git a/crates/cdk-integration-tests/src/init_pure_tests.rs b/crates/cdk-integration-tests/src/init_pure_tests.rs index b0527b7f..86c6c914 100644 --- a/crates/cdk-integration-tests/src/init_pure_tests.rs +++ b/crates/cdk-integration-tests/src/init_pure_tests.rs @@ -6,8 +6,7 @@ use std::sync::Arc; use async_trait::async_trait; use bip39::Mnemonic; use cdk::amount::SplitTarget; -use cdk::cdk_database::mint_memory::MintMemoryDatabase; -use cdk::cdk_database::{MintDatabase, WalletMemoryDatabase}; +use cdk::cdk_database::MintDatabase; use cdk::mint::{FeeReserve, MintBuilder, MintMeltLimits}; use cdk::nuts::nut00::ProofsMethods; use cdk::nuts::{ @@ -158,7 +157,9 @@ pub async fn create_and_start_test_mint() -> anyhow::Result> { let mut mint_builder = MintBuilder::new(); - let database = MintMemoryDatabase::default(); + let database = cdk_sqlite::mint::memory::empty() + .await + .expect("valid db instance"); let localstore = Arc::new(database); mint_builder = mint_builder.with_localstore(localstore.clone()); @@ -209,13 +210,15 @@ pub async fn create_and_start_test_mint() -> anyhow::Result> { Ok(mint_arc) } -pub fn create_test_wallet_for_mint(mint: Arc) -> anyhow::Result> { +pub async fn create_test_wallet_for_mint(mint: Arc) -> anyhow::Result> { let connector = DirectMintConnection::new(mint); let seed = Mnemonic::generate(12)?.to_seed_normalized(""); let mint_url = "http://aa".to_string(); let unit = CurrencyUnit::Sat; - let localstore = WalletMemoryDatabase::default(); + let localstore = cdk_sqlite::wallet::memory::empty() + .await + .expect("valid db instance"); let mut wallet = Wallet::new(&mint_url, unit, Arc::new(localstore), &seed, None)?; wallet.set_client(connector); diff --git a/crates/cdk-integration-tests/tests/fake_wallet.rs b/crates/cdk-integration-tests/tests/fake_wallet.rs index e41149c4..fd195d83 100644 --- a/crates/cdk-integration-tests/tests/fake_wallet.rs +++ b/crates/cdk-integration-tests/tests/fake_wallet.rs @@ -3,7 +3,6 @@ use std::sync::Arc; use anyhow::{bail, Result}; use bip39::Mnemonic; use cdk::amount::SplitTarget; -use cdk::cdk_database::WalletMemoryDatabase; use cdk::nuts::nut00::ProofsMethods; use cdk::nuts::{ CurrencyUnit, MeltBolt11Request, MeltQuoteState, MintBolt11Request, PreMintSecrets, Proofs, @@ -13,6 +12,7 @@ use cdk::wallet::client::{HttpClient, MintConnector}; use cdk::wallet::Wallet; use cdk_fake_wallet::{create_fake_invoice, FakeInvoiceDescription}; use cdk_integration_tests::{attempt_to_swap_pending, wait_for_mint_to_be_paid}; +use cdk_sqlite::wallet::memory; const MINT_URL: &str = "http://127.0.0.1:8086"; @@ -22,7 +22,7 @@ async fn test_fake_tokens_pending() -> Result<()> { let wallet = Wallet::new( MINT_URL, CurrencyUnit::Sat, - Arc::new(WalletMemoryDatabase::default()), + Arc::new(memory::empty().await?), &Mnemonic::generate(12)?.to_seed_normalized(""), None, )?; @@ -62,7 +62,7 @@ async fn test_fake_melt_payment_fail() -> Result<()> { let wallet = Wallet::new( MINT_URL, CurrencyUnit::Sat, - Arc::new(WalletMemoryDatabase::default()), + Arc::new(memory::empty().await?), &Mnemonic::generate(12)?.to_seed_normalized(""), None, )?; @@ -113,7 +113,7 @@ async fn test_fake_melt_payment_fail() -> Result<()> { } let wallet_bal = wallet.total_balance().await?; - assert!(wallet_bal == 100.into()); + assert_eq!(wallet_bal, 100.into()); Ok(()) } @@ -125,7 +125,7 @@ async fn test_fake_melt_payment_fail_and_check() -> Result<()> { let wallet = Wallet::new( MINT_URL, CurrencyUnit::Sat, - Arc::new(WalletMemoryDatabase::default()), + Arc::new(memory::empty().await?), &Mnemonic::generate(12)?.to_seed_normalized(""), None, )?; @@ -170,7 +170,7 @@ async fn test_fake_melt_payment_return_fail_status() -> Result<()> { let wallet = Wallet::new( MINT_URL, CurrencyUnit::Sat, - Arc::new(WalletMemoryDatabase::default()), + Arc::new(memory::empty().await?), &Mnemonic::generate(12)?.to_seed_normalized(""), None, )?; @@ -230,7 +230,7 @@ async fn test_fake_melt_payment_error_unknown() -> Result<()> { let wallet = Wallet::new( MINT_URL, CurrencyUnit::Sat, - Arc::new(WalletMemoryDatabase::default()), + Arc::new(memory::empty().await?), &Mnemonic::generate(12)?.to_seed_normalized(""), None, )?; @@ -256,7 +256,7 @@ async fn test_fake_melt_payment_error_unknown() -> Result<()> { // The melt should error at the payment invoice command let melt = wallet.melt(&melt_quote.id).await; - assert!(melt.is_err()); + assert_eq!(melt.unwrap_err().to_string(), "Payment failed"); let fake_description = FakeInvoiceDescription { pay_invoice_state: MeltQuoteState::Unknown, @@ -271,7 +271,7 @@ async fn test_fake_melt_payment_error_unknown() -> Result<()> { // The melt should error at the payment invoice command let melt = wallet.melt(&melt_quote.id).await; - assert!(melt.is_err()); + assert_eq!(melt.unwrap_err().to_string(), "Payment failed"); let pending = wallet .localstore @@ -291,7 +291,7 @@ async fn test_fake_melt_payment_err_paid() -> Result<()> { let wallet = Wallet::new( MINT_URL, CurrencyUnit::Sat, - Arc::new(WalletMemoryDatabase::default()), + Arc::new(memory::empty().await?), &Mnemonic::generate(12)?.to_seed_normalized(""), None, )?; @@ -329,7 +329,7 @@ async fn test_fake_melt_change_in_quote() -> Result<()> { let wallet = Wallet::new( MINT_URL, CurrencyUnit::Sat, - Arc::new(WalletMemoryDatabase::default()), + Arc::new(memory::empty().await?), &Mnemonic::generate(12)?.to_seed_normalized(""), None, )?; @@ -417,7 +417,7 @@ async fn test_fake_mint_with_witness() -> Result<()> { let wallet = Wallet::new( MINT_URL, CurrencyUnit::Sat, - Arc::new(WalletMemoryDatabase::default()), + Arc::new(memory::empty().await?), &Mnemonic::generate(12)?.to_seed_normalized(""), None, )?; @@ -441,7 +441,7 @@ async fn test_fake_mint_without_witness() -> Result<()> { let wallet = Wallet::new( MINT_URL, CurrencyUnit::Sat, - Arc::new(WalletMemoryDatabase::default()), + Arc::new(memory::empty().await?), &Mnemonic::generate(12)?.to_seed_normalized(""), None, )?; @@ -477,7 +477,7 @@ async fn test_fake_mint_with_wrong_witness() -> Result<()> { let wallet = Wallet::new( MINT_URL, CurrencyUnit::Sat, - Arc::new(WalletMemoryDatabase::default()), + Arc::new(memory::empty().await?), &Mnemonic::generate(12)?.to_seed_normalized(""), None, )?; @@ -517,7 +517,7 @@ async fn test_fake_mint_inflated() -> Result<()> { let wallet = Wallet::new( MINT_URL, CurrencyUnit::Sat, - Arc::new(WalletMemoryDatabase::default()), + Arc::new(memory::empty().await?), &Mnemonic::generate(12)?.to_seed_normalized(""), None, )?; @@ -569,7 +569,7 @@ async fn test_fake_mint_multiple_units() -> Result<()> { let wallet = Wallet::new( MINT_URL, CurrencyUnit::Sat, - Arc::new(WalletMemoryDatabase::default()), + Arc::new(memory::empty().await?), &Mnemonic::generate(12)?.to_seed_normalized(""), None, )?; @@ -585,7 +585,7 @@ async fn test_fake_mint_multiple_units() -> Result<()> { let wallet_usd = Wallet::new( MINT_URL, CurrencyUnit::Usd, - Arc::new(WalletMemoryDatabase::default()), + Arc::new(memory::empty().await?), &Mnemonic::generate(12)?.to_seed_normalized(""), None, )?; @@ -639,7 +639,7 @@ async fn test_fake_mint_multiple_unit_swap() -> Result<()> { let wallet = Wallet::new( MINT_URL, CurrencyUnit::Sat, - Arc::new(WalletMemoryDatabase::default()), + Arc::new(memory::empty().await?), &Mnemonic::generate(12)?.to_seed_normalized(""), None, )?; @@ -653,7 +653,7 @@ async fn test_fake_mint_multiple_unit_swap() -> Result<()> { let wallet_usd = Wallet::new( MINT_URL, CurrencyUnit::Usd, - Arc::new(WalletMemoryDatabase::default()), + Arc::new(memory::empty().await?), &Mnemonic::generate(12)?.to_seed_normalized(""), None, )?; @@ -743,7 +743,7 @@ async fn test_fake_mint_multiple_unit_melt() -> Result<()> { let wallet = Wallet::new( MINT_URL, CurrencyUnit::Sat, - Arc::new(WalletMemoryDatabase::default()), + Arc::new(memory::empty().await?), &Mnemonic::generate(12)?.to_seed_normalized(""), None, )?; @@ -762,7 +762,7 @@ async fn test_fake_mint_multiple_unit_melt() -> Result<()> { let wallet_usd = Wallet::new( MINT_URL, CurrencyUnit::Usd, - Arc::new(WalletMemoryDatabase::default()), + Arc::new(memory::empty().await?), &Mnemonic::generate(12)?.to_seed_normalized(""), None, )?; @@ -863,7 +863,7 @@ async fn test_fake_mint_input_output_mismatch() -> Result<()> { let wallet = Wallet::new( MINT_URL, CurrencyUnit::Sat, - Arc::new(WalletMemoryDatabase::default()), + Arc::new(memory::empty().await?), &Mnemonic::generate(12)?.to_seed_normalized(""), None, )?; @@ -877,11 +877,10 @@ async fn test_fake_mint_input_output_mismatch() -> Result<()> { let wallet_usd = Wallet::new( MINT_URL, CurrencyUnit::Usd, - Arc::new(WalletMemoryDatabase::default()), + Arc::new(memory::empty().await?), &Mnemonic::generate(12)?.to_seed_normalized(""), None, )?; - let usd_active_keyset_id = wallet_usd.get_active_mint_keyset().await?.id; let inputs = proofs; @@ -919,7 +918,7 @@ async fn test_fake_mint_swap_inflated() -> Result<()> { let wallet = Wallet::new( MINT_URL, CurrencyUnit::Sat, - Arc::new(WalletMemoryDatabase::default()), + Arc::new(memory::empty().await?), &Mnemonic::generate(12)?.to_seed_normalized(""), None, )?; @@ -961,7 +960,7 @@ async fn test_fake_mint_swap_spend_after_fail() -> Result<()> { let wallet = Wallet::new( MINT_URL, CurrencyUnit::Sat, - Arc::new(WalletMemoryDatabase::default()), + Arc::new(memory::empty().await?), &Mnemonic::generate(12)?.to_seed_normalized(""), None, )?; @@ -1041,7 +1040,7 @@ async fn test_fake_mint_melt_spend_after_fail() -> Result<()> { let wallet = Wallet::new( MINT_URL, CurrencyUnit::Sat, - Arc::new(WalletMemoryDatabase::default()), + Arc::new(memory::empty().await?), &Mnemonic::generate(12)?.to_seed_normalized(""), None, )?; @@ -1121,7 +1120,7 @@ async fn test_fake_mint_duplicate_proofs_swap() -> Result<()> { let wallet = Wallet::new( MINT_URL, CurrencyUnit::Sat, - Arc::new(WalletMemoryDatabase::default()), + Arc::new(memory::empty().await?), &Mnemonic::generate(12)?.to_seed_normalized(""), None, )?; @@ -1195,7 +1194,7 @@ async fn test_fake_mint_duplicate_proofs_melt() -> Result<()> { let wallet = Wallet::new( MINT_URL, CurrencyUnit::Sat, - Arc::new(WalletMemoryDatabase::default()), + Arc::new(memory::empty().await?), &Mnemonic::generate(12)?.to_seed_normalized(""), None, )?; diff --git a/crates/cdk-integration-tests/tests/integration_tests_pure.rs b/crates/cdk-integration-tests/tests/integration_tests_pure.rs index 3190f48c..61458575 100644 --- a/crates/cdk-integration-tests/tests/integration_tests_pure.rs +++ b/crates/cdk-integration-tests/tests/integration_tests_pure.rs @@ -11,7 +11,7 @@ use cdk_integration_tests::init_pure_tests::{ #[tokio::test] async fn test_swap_to_send() -> anyhow::Result<()> { let mint_bob = create_and_start_test_mint().await?; - let wallet_alice = create_test_wallet_for_mint(mint_bob.clone())?; + let wallet_alice = create_test_wallet_for_mint(mint_bob.clone()).await?; // Alice gets 64 sats fund_wallet(wallet_alice.clone(), 64).await?; @@ -33,7 +33,7 @@ async fn test_swap_to_send() -> anyhow::Result<()> { assert_eq!(Amount::from(24), wallet_alice.total_balance().await?); // Alice sends cashu, Carol receives - let wallet_carol = create_test_wallet_for_mint(mint_bob.clone())?; + let wallet_carol = create_test_wallet_for_mint(mint_bob.clone()).await?; let received_amount = wallet_carol .receive_proofs(token.proofs(), SplitTarget::None, &[], &[]) .await?; diff --git a/crates/cdk-integration-tests/tests/mint.rs b/crates/cdk-integration-tests/tests/mint.rs index 6e6131b0..11680a1a 100644 --- a/crates/cdk-integration-tests/tests/mint.rs +++ b/crates/cdk-integration-tests/tests/mint.rs @@ -7,7 +7,6 @@ use std::time::Duration; use anyhow::{bail, Result}; use bip39::Mnemonic; use cdk::amount::{Amount, SplitTarget}; -use cdk::cdk_database::mint_memory::MintMemoryDatabase; use cdk::cdk_database::MintDatabase; use cdk::dhke::construct_proofs; use cdk::mint::{FeeReserve, MintBuilder, MintMeltLimits, MintQuote}; @@ -21,13 +20,11 @@ use cdk::types::QuoteTTL; use cdk::util::unix_time; use cdk::Mint; use cdk_fake_wallet::FakeWallet; -use tokio::sync::OnceCell; +use cdk_sqlite::mint::memory; use tokio::time::sleep; pub const MINT_URL: &str = "http://127.0.0.1:8088"; -static INSTANCE: OnceCell = OnceCell::const_new(); - async fn new_mint(fee: u64) -> Mint { let mut supported_units = HashMap::new(); supported_units.insert(CurrencyUnit::Sat, (fee, 32)); @@ -43,7 +40,7 @@ async fn new_mint(fee: u64) -> Mint { let mint_info = MintInfo::new().nuts(nuts); - let localstore = MintMemoryDatabase::default(); + let localstore = memory::empty().await.expect("valid db instance"); localstore .set_mint_info(mint_info) @@ -62,8 +59,8 @@ async fn new_mint(fee: u64) -> Mint { .unwrap() } -async fn initialize() -> &'static Mint { - INSTANCE.get_or_init(|| new_mint(0)).await +async fn initialize() -> Mint { + new_mint(0).await } async fn mint_proofs( @@ -115,7 +112,7 @@ async fn test_mint_double_spend() -> Result<()> { let keys = mint.pubkeys().await?.keysets.first().unwrap().clone().keys; let keyset_id = Id::from(&keys); - let proofs = mint_proofs(mint, 100.into(), &SplitTarget::default(), keys).await?; + let proofs = mint_proofs(&mint, 100.into(), &SplitTarget::default(), keys).await?; let preswap = PreMintSecrets::random(keyset_id, 100.into(), &SplitTarget::default())?; @@ -149,7 +146,7 @@ async fn test_attempt_to_swap_by_overflowing() -> Result<()> { let keys = mint.pubkeys().await?.keysets.first().unwrap().clone().keys; let keyset_id = Id::from(&keys); - let proofs = mint_proofs(mint, 100.into(), &SplitTarget::default(), keys).await?; + let proofs = mint_proofs(&mint, 100.into(), &SplitTarget::default(), keys).await?; let amount = 2_u64.pow(63); @@ -188,7 +185,7 @@ pub async fn test_p2pk_swap() -> Result<()> { let keys = mint.pubkeys().await?.keysets.first().unwrap().clone().keys; let keyset_id = Id::from(&keys); - let proofs = mint_proofs(mint, 100.into(), &SplitTarget::default(), keys).await?; + let proofs = mint_proofs(&mint, 100.into(), &SplitTarget::default(), keys).await?; let secret = SecretKey::generate(); @@ -306,7 +303,7 @@ async fn test_swap_unbalanced() -> Result<()> { let keys = mint.pubkeys().await?.keysets.first().unwrap().clone().keys; let keyset_id = Id::from(&keys); - let proofs = mint_proofs(mint, 100.into(), &SplitTarget::default(), keys).await?; + let proofs = mint_proofs(&mint, 100.into(), &SplitTarget::default(), keys).await?; let preswap = PreMintSecrets::random(keyset_id, 95.into(), &SplitTarget::default())?; @@ -450,7 +447,7 @@ async fn test_correct_keyset() -> Result<()> { percent_fee_reserve: 1.0, }; - let database = MintMemoryDatabase::default(); + let database = memory::empty().await.expect("valid db instance"); let fake_wallet = FakeWallet::new(fee_reserve, HashMap::default(), HashSet::default(), 0); diff --git a/crates/cdk-integration-tests/tests/regtest.rs b/crates/cdk-integration-tests/tests/regtest.rs index 499a735f..96a2673b 100644 --- a/crates/cdk-integration-tests/tests/regtest.rs +++ b/crates/cdk-integration-tests/tests/regtest.rs @@ -7,7 +7,6 @@ use anyhow::{bail, Result}; use bip39::Mnemonic; use cashu::{MeltOptions, Mpp}; use cdk::amount::{Amount, SplitTarget}; -use cdk::cdk_database::WalletMemoryDatabase; use cdk::nuts::nut00::ProofsMethods; use cdk::nuts::{ CurrencyUnit, MeltQuoteState, MintBolt11Request, MintQuoteState, NotificationPayload, @@ -21,6 +20,7 @@ use cdk_integration_tests::init_regtest::{ get_mint_url, get_mint_ws_url, LND_RPC_ADDR, LND_TWO_RPC_ADDR, }; use cdk_integration_tests::wait_for_mint_to_be_paid; +use cdk_sqlite::wallet::{self, memory}; use futures::{join, SinkExt, StreamExt}; use lightning_invoice::Bolt11Invoice; use ln_regtest_rs::ln_client::{ClnClient, LightningClient, LndClient}; @@ -83,7 +83,7 @@ async fn test_regtest_mint_melt_round_trip() -> Result<()> { let wallet = Wallet::new( &get_mint_url("0"), CurrencyUnit::Sat, - Arc::new(WalletMemoryDatabase::default()), + Arc::new(memory::empty().await?), &Mnemonic::generate(12)?.to_seed_normalized(""), None, )?; @@ -167,7 +167,7 @@ async fn test_regtest_mint_melt() -> Result<()> { let wallet = Wallet::new( &get_mint_url("0"), CurrencyUnit::Sat, - Arc::new(WalletMemoryDatabase::default()), + Arc::new(memory::empty().await?), &Mnemonic::generate(12)?.to_seed_normalized(""), None, )?; @@ -201,7 +201,7 @@ async fn test_restore() -> Result<()> { let wallet = Wallet::new( &get_mint_url("0"), CurrencyUnit::Sat, - Arc::new(WalletMemoryDatabase::default()), + Arc::new(memory::empty().await?), &seed, None, )?; @@ -221,7 +221,7 @@ async fn test_restore() -> Result<()> { let wallet_2 = Wallet::new( &get_mint_url("0"), CurrencyUnit::Sat, - Arc::new(WalletMemoryDatabase::default()), + Arc::new(memory::empty().await?), &seed, None, )?; @@ -260,7 +260,7 @@ async fn test_pay_invoice_twice() -> Result<()> { let wallet = Wallet::new( &get_mint_url("0"), CurrencyUnit::Sat, - Arc::new(WalletMemoryDatabase::default()), + Arc::new(memory::empty().await?), &seed, None, )?; @@ -319,7 +319,7 @@ async fn test_internal_payment() -> Result<()> { let wallet = Wallet::new( &get_mint_url("0"), CurrencyUnit::Sat, - Arc::new(WalletMemoryDatabase::default()), + Arc::new(memory::empty().await?), &seed, None, )?; @@ -341,7 +341,7 @@ async fn test_internal_payment() -> Result<()> { let wallet_2 = Wallet::new( &get_mint_url("0"), CurrencyUnit::Sat, - Arc::new(WalletMemoryDatabase::default()), + Arc::new(memory::empty().await?), &seed, None, )?; @@ -414,7 +414,7 @@ async fn test_cached_mint() -> Result<()> { let wallet = Wallet::new( &get_mint_url("0"), CurrencyUnit::Sat, - Arc::new(WalletMemoryDatabase::default()), + Arc::new(memory::empty().await?), &Mnemonic::generate(12)?.to_seed_normalized(""), None, )?; @@ -453,7 +453,7 @@ async fn test_websocket_connection() -> Result<()> { let wallet = Wallet::new( &get_mint_url("0"), CurrencyUnit::Sat, - Arc::new(WalletMemoryDatabase::default()), + Arc::new(wallet::memory::empty().await?), &Mnemonic::generate(12)?.to_seed_normalized(""), None, )?; @@ -508,14 +508,14 @@ async fn test_multimint_melt() -> Result<()> { let wallet1 = Wallet::new( &get_mint_url("0"), CurrencyUnit::Sat, - Arc::new(WalletMemoryDatabase::default()), + Arc::new(memory::empty().await?), &Mnemonic::generate(12)?.to_seed_normalized(""), None, )?; let wallet2 = Wallet::new( &get_mint_url("1"), CurrencyUnit::Sat, - Arc::new(WalletMemoryDatabase::default()), + Arc::new(memory::empty().await?), &Mnemonic::generate(12)?.to_seed_normalized(""), None, )?; diff --git a/crates/cdk-sqlite/src/common.rs b/crates/cdk-sqlite/src/common.rs new file mode 100644 index 00000000..3aba92a7 --- /dev/null +++ b/crates/cdk-sqlite/src/common.rs @@ -0,0 +1,29 @@ +use std::str::FromStr; +use std::time::Duration; + +use sqlx::sqlite::{SqliteConnectOptions, SqlitePoolOptions}; +use sqlx::{Error, Pool, Sqlite}; + +#[inline(always)] +pub async fn create_sqlite_pool(path: &str) -> Result, Error> { + let db_options = SqliteConnectOptions::from_str(path)? + .busy_timeout(Duration::from_secs(10)) + .read_only(false) + .pragma("busy_timeout", "5000") + .pragma("journal_mode", "wal") + .pragma("synchronous", "normal") + .pragma("temp_store", "memory") + .pragma("mmap_size", "30000000000") + .shared_cache(true) + .create_if_missing(true); + + let pool = SqlitePoolOptions::new() + .min_connections(1) + .max_connections(1) + .idle_timeout(None) + .max_lifetime(None) + .connect_with(db_options) + .await?; + + Ok(pool) +} diff --git a/crates/cdk-sqlite/src/lib.rs b/crates/cdk-sqlite/src/lib.rs index ea1e51df..4c50a5ff 100644 --- a/crates/cdk-sqlite/src/lib.rs +++ b/crates/cdk-sqlite/src/lib.rs @@ -3,6 +3,8 @@ #![warn(missing_docs)] #![warn(rustdoc::bare_urls)] +mod common; + #[cfg(feature = "mint")] pub mod mint; #[cfg(feature = "wallet")] diff --git a/crates/cdk-sqlite/src/mint/memory.rs b/crates/cdk-sqlite/src/mint/memory.rs new file mode 100644 index 00000000..6dd134db --- /dev/null +++ b/crates/cdk-sqlite/src/mint/memory.rs @@ -0,0 +1,61 @@ +//! In-memory database that is provided by the `cdk-sqlite` crate, mainly for testing purposes. +use std::collections::HashMap; + +use cdk_common::common::LnKey; +use cdk_common::database::{self, MintDatabase}; +use cdk_common::mint::{self, MintKeySetInfo, MintQuote}; +use cdk_common::nuts::{CurrencyUnit, Id, MeltBolt11Request, Proofs}; +use cdk_common::MintInfo; +use uuid::Uuid; + +use super::MintSqliteDatabase; + +/// Creates a new in-memory [`MintSqliteDatabase`] instance +pub async fn empty() -> Result { + let db = MintSqliteDatabase::new(":memory:").await?; + db.migrate().await; + Ok(db) +} + +/// Creates a new in-memory [`MintSqliteDatabase`] instance with the given state +#[allow(clippy::too_many_arguments)] +pub async fn new_with_state( + active_keysets: HashMap, + keysets: Vec, + mint_quotes: Vec, + melt_quotes: Vec, + pending_proofs: Proofs, + spent_proofs: Proofs, + melt_request: Vec<(MeltBolt11Request, LnKey)>, + mint_info: MintInfo, +) -> Result { + let db = empty().await?; + + for active_keyset in active_keysets { + db.set_active_keyset(active_keyset.0, active_keyset.1) + .await?; + } + + for keyset in keysets { + db.add_keyset_info(keyset).await?; + } + + for quote in mint_quotes { + db.add_mint_quote(quote).await?; + } + + for quote in melt_quotes { + db.add_melt_quote(quote).await?; + } + + db.add_proofs(pending_proofs, None).await?; + db.add_proofs(spent_proofs, None).await?; + + for (melt_request, ln_key) in melt_request { + db.add_melt_request(melt_request, ln_key).await?; + } + + db.set_mint_info(mint_info).await?; + + Ok(db) +} diff --git a/crates/cdk-sqlite/src/mint/mod.rs b/crates/cdk-sqlite/src/mint/mod.rs index 7076c754..366d57e9 100644 --- a/crates/cdk-sqlite/src/mint/mod.rs +++ b/crates/cdk-sqlite/src/mint/mod.rs @@ -3,7 +3,6 @@ use std::collections::HashMap; use std::path::Path; use std::str::FromStr; -use std::time::Duration; use async_trait::async_trait; use bitcoin::bip32::DerivationPath; @@ -20,35 +19,28 @@ use cdk_common::{ }; use error::Error; use lightning_invoice::Bolt11Invoice; -use sqlx::sqlite::{SqliteConnectOptions, SqlitePool, SqlitePoolOptions, SqliteRow}; -use sqlx::Row; +use sqlx::sqlite::SqliteRow; +use sqlx::{Pool, Row, Sqlite}; use uuid::fmt::Hyphenated; use uuid::Uuid; +use crate::common::create_sqlite_pool; + pub mod error; +pub mod memory; /// Mint SQLite Database #[derive(Debug, Clone)] pub struct MintSqliteDatabase { - pool: SqlitePool, + pool: Pool, } impl MintSqliteDatabase { /// Create new [`MintSqliteDatabase`] - pub async fn new(path: &Path) -> Result { - let path = path.to_str().ok_or(Error::InvalidDbPath)?; - let db_options = SqliteConnectOptions::from_str(path)? - .busy_timeout(Duration::from_secs(5)) - .read_only(false) - .create_if_missing(true) - .auto_vacuum(sqlx::sqlite::SqliteAutoVacuum::Full); - - let pool = SqlitePoolOptions::new() - .max_connections(1) - .connect_with(db_options) - .await?; - - Ok(Self { pool }) + pub async fn new>(path: P) -> Result { + Ok(Self { + pool: create_sqlite_pool(path.as_ref().to_str().ok_or(Error::InvalidDbPath)?).await?, + }) } /// Migrate [`MintSqliteDatabase`] diff --git a/crates/cdk-sqlite/src/wallet/memory.rs b/crates/cdk-sqlite/src/wallet/memory.rs new file mode 100644 index 00000000..df495073 --- /dev/null +++ b/crates/cdk-sqlite/src/wallet/memory.rs @@ -0,0 +1,12 @@ +//! Wallet in memory database + +use cdk_common::database::Error; + +use super::WalletSqliteDatabase; + +/// Creates a new in-memory [`WalletSqliteDatabase`] instance +pub async fn empty() -> Result { + let db = WalletSqliteDatabase::new(":memory:").await?; + db.migrate().await; + Ok(db) +} diff --git a/crates/cdk-sqlite/src/wallet/mod.rs b/crates/cdk-sqlite/src/wallet/mod.rs index 22547b96..2b19f8eb 100644 --- a/crates/cdk-sqlite/src/wallet/mod.rs +++ b/crates/cdk-sqlite/src/wallet/mod.rs @@ -16,33 +16,27 @@ use cdk_common::{ SpendingConditions, State, }; use error::Error; -use sqlx::sqlite::{SqliteConnectOptions, SqlitePool, SqliteRow}; -use sqlx::{ConnectOptions, Row}; +use sqlx::sqlite::SqliteRow; +use sqlx::{Pool, Row, Sqlite}; use tracing::instrument; +use crate::common::create_sqlite_pool; + pub mod error; +pub mod memory; /// Wallet SQLite Database #[derive(Debug, Clone)] pub struct WalletSqliteDatabase { - pool: SqlitePool, + pool: Pool, } impl WalletSqliteDatabase { /// Create new [`WalletSqliteDatabase`] - pub async fn new(path: &Path) -> Result { - let path = path.to_str().ok_or(Error::InvalidDbPath)?; - let _conn = SqliteConnectOptions::from_str(path)? - .journal_mode(sqlx::sqlite::SqliteJournalMode::Wal) - .read_only(false) - .create_if_missing(true) - .auto_vacuum(sqlx::sqlite::SqliteAutoVacuum::Full) - .connect() - .await?; - - let pool = SqlitePool::connect(path).await?; - - Ok(Self { pool }) + pub async fn new>(path: P) -> Result { + Ok(Self { + pool: create_sqlite_pool(path.as_ref().to_str().ok_or(Error::InvalidDbPath)?).await?, + }) } /// Migrate [`WalletSqliteDatabase`] diff --git a/crates/cdk/Cargo.toml b/crates/cdk/Cargo.toml index 4bbf57f0..b239c9a9 100644 --- a/crates/cdk/Cargo.toml +++ b/crates/cdk/Cargo.toml @@ -100,6 +100,7 @@ required-features = ["wallet"] rand = "0.8.5" bip39 = "2.0" tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } +cdk-sqlite = { path = "../cdk-sqlite" } criterion = "0.5.1" [[bench]] diff --git a/crates/cdk/README.md b/crates/cdk/README.md index cc843351..c00aad19 100644 --- a/crates/cdk/README.md +++ b/crates/cdk/README.md @@ -27,7 +27,7 @@ use std::sync::Arc; use std::time::Duration; use cdk::amount::SplitTarget; -use cdk::cdk_database::WalletMemoryDatabase; +use cdk_sqlite::wallet::memory; use cdk::nuts::{CurrencyUnit, MintQuoteState}; use cdk::wallet::Wallet; use cdk::Amount; @@ -42,7 +42,7 @@ async fn main() { let unit = CurrencyUnit::Sat; let amount = Amount::from(10); - let localstore = WalletMemoryDatabase::default(); + let localstore = memory::empty().await.unwrap(); let wallet = Wallet::new(mint_url, unit, Arc::new(localstore), &seed); @@ -94,7 +94,7 @@ cargo update -p reqwest --precise 0.12.4 cargo update -p serde_with --precise 3.1.0 cargo update -p regex --precise 1.9.6 cargo update -p backtrace --precise 0.3.58 -# For wasm32-unknown-unknown target +# For wasm32-unknown-unknown target cargo update -p bumpalo --precise 3.12.0 ``` diff --git a/crates/cdk/examples/mint-token.rs b/crates/cdk/examples/mint-token.rs index 9b945192..544152fe 100644 --- a/crates/cdk/examples/mint-token.rs +++ b/crates/cdk/examples/mint-token.rs @@ -1,19 +1,19 @@ use std::sync::Arc; use cdk::amount::SplitTarget; -use cdk::cdk_database::WalletMemoryDatabase; use cdk::error::Error; use cdk::nuts::nut00::ProofsMethods; use cdk::nuts::{CurrencyUnit, MintQuoteState, NotificationPayload}; use cdk::wallet::types::SendKind; use cdk::wallet::{Wallet, WalletSubscription}; use cdk::Amount; +use cdk_sqlite::wallet::memory; use rand::Rng; #[tokio::main] async fn main() -> Result<(), Error> { // Initialize the memory store for the wallet - let localstore = WalletMemoryDatabase::default(); + let localstore = memory::empty().await?; // Generate a random seed for the wallet let seed = rand::thread_rng().gen::<[u8; 32]>(); diff --git a/crates/cdk/examples/p2pk.rs b/crates/cdk/examples/p2pk.rs index ca3639d8..05e7181c 100644 --- a/crates/cdk/examples/p2pk.rs +++ b/crates/cdk/examples/p2pk.rs @@ -1,12 +1,12 @@ use std::sync::Arc; use cdk::amount::SplitTarget; -use cdk::cdk_database::WalletMemoryDatabase; use cdk::error::Error; use cdk::nuts::{CurrencyUnit, MintQuoteState, NotificationPayload, SecretKey, SpendingConditions}; use cdk::wallet::types::SendKind; use cdk::wallet::{Wallet, WalletSubscription}; use cdk::Amount; +use cdk_sqlite::wallet::memory; use rand::Rng; use tracing_subscriber::EnvFilter; @@ -22,7 +22,7 @@ async fn main() -> Result<(), Error> { tracing_subscriber::fmt().with_env_filter(env_filter).init(); // Initialize the memory store for the wallet - let localstore = WalletMemoryDatabase::default(); + let localstore = memory::empty().await?; // Generate a random seed for the wallet let seed = rand::thread_rng().gen::<[u8; 32]>(); diff --git a/crates/cdk/examples/proof-selection.rs b/crates/cdk/examples/proof-selection.rs index dfd59616..ee77b21f 100644 --- a/crates/cdk/examples/proof-selection.rs +++ b/crates/cdk/examples/proof-selection.rs @@ -3,11 +3,11 @@ use std::sync::Arc; use cdk::amount::SplitTarget; -use cdk::cdk_database::WalletMemoryDatabase; use cdk::nuts::nut00::ProofsMethods; use cdk::nuts::{CurrencyUnit, MintQuoteState, NotificationPayload}; use cdk::wallet::{Wallet, WalletSubscription}; use cdk::Amount; +use cdk_sqlite::wallet::memory; use rand::Rng; #[tokio::main] @@ -20,7 +20,7 @@ async fn main() -> Result<(), Box> { let unit = CurrencyUnit::Sat; // Initialize the memory store - let localstore = WalletMemoryDatabase::default(); + let localstore = memory::empty().await?; // Create a new wallet let wallet = Wallet::new(mint_url, unit, Arc::new(localstore), &seed, None)?; diff --git a/crates/cdk/examples/wallet.rs b/crates/cdk/examples/wallet.rs index dfaca401..28f564af 100644 --- a/crates/cdk/examples/wallet.rs +++ b/crates/cdk/examples/wallet.rs @@ -2,12 +2,12 @@ use std::sync::Arc; use std::time::Duration; use cdk::amount::SplitTarget; -use cdk::cdk_database::WalletMemoryDatabase; use cdk::nuts::nut00::ProofsMethods; use cdk::nuts::{CurrencyUnit, MintQuoteState}; use cdk::wallet::types::SendKind; use cdk::wallet::Wallet; use cdk::Amount; +use cdk_sqlite::wallet::memory; use rand::Rng; use tokio::time::sleep; @@ -22,7 +22,7 @@ async fn main() -> Result<(), Box> { let amount = Amount::from(10); // Initialize the memory store - let localstore = WalletMemoryDatabase::default(); + let localstore = memory::empty().await?; // Create a new wallet let wallet = Wallet::new(mint_url, unit, Arc::new(localstore), &seed, None)?; diff --git a/crates/cdk/src/cdk_database/mint_memory.rs b/crates/cdk/src/cdk_database/mint_memory.rs deleted file mode 100644 index 7f7b35fe..00000000 --- a/crates/cdk/src/cdk_database/mint_memory.rs +++ /dev/null @@ -1,493 +0,0 @@ -//! Mint in memory database - -use std::collections::HashMap; -use std::sync::Arc; - -use async_trait::async_trait; -use cdk_common::common::QuoteTTL; -use cdk_common::database::{Error, MintDatabase}; -use cdk_common::mint::MintKeySetInfo; -use cdk_common::nut00::ProofsMethods; -use cdk_common::MintInfo; -use tokio::sync::{Mutex, RwLock}; -use uuid::Uuid; - -use crate::dhke::hash_to_curve; -use crate::mint::{self, MintQuote}; -use crate::nuts::nut07::State; -use crate::nuts::{ - nut07, BlindSignature, CurrencyUnit, Id, MeltBolt11Request, MeltQuoteState, MintQuoteState, - Proof, Proofs, PublicKey, -}; -use crate::types::LnKey; - -/// Mint Memory Database -#[derive(Debug, Clone, Default)] -#[allow(clippy::type_complexity)] -pub struct MintMemoryDatabase { - active_keysets: Arc>>, - keysets: Arc>>, - mint_quotes: Arc>>, - melt_quotes: Arc>>, - proofs: Arc>>, - proof_state: Arc>>, - quote_proofs: Arc>>>, - blinded_signatures: Arc>>, - quote_signatures: Arc>>>, - melt_requests: Arc, LnKey)>>>, - mint_info: Arc>, - quote_ttl: Arc>, -} - -impl MintMemoryDatabase { - /// Create new [`MintMemoryDatabase`] - #[allow(clippy::too_many_arguments)] - pub fn new( - active_keysets: HashMap, - keysets: Vec, - mint_quotes: Vec, - melt_quotes: Vec, - pending_proofs: Proofs, - spent_proofs: Proofs, - quote_proofs: HashMap>, - blinded_signatures: HashMap<[u8; 33], BlindSignature>, - quote_signatures: HashMap>, - melt_request: Vec<(MeltBolt11Request, LnKey)>, - mint_info: MintInfo, - quote_ttl: QuoteTTL, - ) -> Result { - let mut proofs = HashMap::new(); - let mut proof_states = HashMap::new(); - - for proof in pending_proofs { - let y = hash_to_curve(&proof.secret.to_bytes())?.to_bytes(); - proofs.insert(y, proof); - proof_states.insert(y, State::Pending); - } - - for proof in spent_proofs { - let y = hash_to_curve(&proof.secret.to_bytes())?.to_bytes(); - proofs.insert(y, proof); - proof_states.insert(y, State::Spent); - } - - let melt_requests = melt_request - .into_iter() - .map(|(request, ln_key)| (request.quote, (request, ln_key))) - .collect(); - - Ok(Self { - active_keysets: Arc::new(RwLock::new(active_keysets)), - keysets: Arc::new(RwLock::new( - keysets.into_iter().map(|k| (k.id, k)).collect(), - )), - mint_quotes: Arc::new(RwLock::new( - mint_quotes.into_iter().map(|q| (q.id, q)).collect(), - )), - melt_quotes: Arc::new(RwLock::new( - melt_quotes.into_iter().map(|q| (q.id, q)).collect(), - )), - proofs: Arc::new(RwLock::new(proofs)), - proof_state: Arc::new(Mutex::new(proof_states)), - blinded_signatures: Arc::new(RwLock::new(blinded_signatures)), - quote_proofs: Arc::new(Mutex::new(quote_proofs)), - quote_signatures: Arc::new(RwLock::new(quote_signatures)), - melt_requests: Arc::new(RwLock::new(melt_requests)), - mint_info: Arc::new(RwLock::new(mint_info)), - quote_ttl: Arc::new(RwLock::new(quote_ttl)), - }) - } -} - -#[async_trait] -impl MintDatabase for MintMemoryDatabase { - type Err = Error; - - async fn set_active_keyset(&self, unit: CurrencyUnit, id: Id) -> Result<(), Self::Err> { - self.active_keysets.write().await.insert(unit, id); - Ok(()) - } - - async fn get_active_keyset_id(&self, unit: &CurrencyUnit) -> Result, Self::Err> { - Ok(self.active_keysets.read().await.get(unit).cloned()) - } - - async fn get_active_keysets(&self) -> Result, Self::Err> { - Ok(self.active_keysets.read().await.clone()) - } - - async fn add_keyset_info(&self, keyset: MintKeySetInfo) -> Result<(), Self::Err> { - self.keysets.write().await.insert(keyset.id, keyset); - Ok(()) - } - - async fn get_keyset_info(&self, keyset_id: &Id) -> Result, Self::Err> { - Ok(self.keysets.read().await.get(keyset_id).cloned()) - } - - async fn get_keyset_infos(&self) -> Result, Self::Err> { - Ok(self.keysets.read().await.values().cloned().collect()) - } - - async fn add_mint_quote(&self, quote: MintQuote) -> Result<(), Self::Err> { - self.mint_quotes.write().await.insert(quote.id, quote); - Ok(()) - } - - async fn get_mint_quote(&self, quote_id: &Uuid) -> Result, Self::Err> { - Ok(self.mint_quotes.read().await.get(quote_id).cloned()) - } - - async fn update_mint_quote_state( - &self, - quote_id: &Uuid, - state: MintQuoteState, - ) -> Result { - let mut mint_quotes = self.mint_quotes.write().await; - - let mut quote = mint_quotes - .get(quote_id) - .cloned() - .ok_or(Error::UnknownQuote)?; - - let current_state = quote.state; - - quote.state = state; - - mint_quotes.insert(*quote_id, quote.clone()); - - Ok(current_state) - } - - async fn get_mint_quote_by_request_lookup_id( - &self, - request: &str, - ) -> Result, Self::Err> { - let quotes = self.get_mint_quotes().await?; - - let quote = quotes - .into_iter() - .filter(|q| q.request_lookup_id.eq(request)) - .collect::>() - .first() - .cloned(); - - Ok(quote) - } - async fn get_mint_quote_by_request( - &self, - request: &str, - ) -> Result, Self::Err> { - let quotes = self.get_mint_quotes().await?; - - let quote = quotes - .into_iter() - .filter(|q| q.request.eq(request)) - .collect::>() - .first() - .cloned(); - - Ok(quote) - } - - async fn get_mint_quotes(&self) -> Result, Self::Err> { - Ok(self.mint_quotes.read().await.values().cloned().collect()) - } - - async fn get_mint_quotes_with_state( - &self, - state: MintQuoteState, - ) -> Result, Self::Err> { - let mint_quotes = self.mint_quotes.read().await; - - let pending_quotes = mint_quotes - .values() - .filter(|q| q.state == state) - .cloned() - .collect(); - - Ok(pending_quotes) - } - - async fn remove_mint_quote(&self, quote_id: &Uuid) -> Result<(), Self::Err> { - self.mint_quotes.write().await.remove(quote_id); - - Ok(()) - } - - async fn add_melt_quote(&self, quote: mint::MeltQuote) -> Result<(), Self::Err> { - self.melt_quotes.write().await.insert(quote.id, quote); - Ok(()) - } - - async fn get_melt_quote(&self, quote_id: &Uuid) -> Result, Self::Err> { - Ok(self.melt_quotes.read().await.get(quote_id).cloned()) - } - - async fn update_melt_quote_state( - &self, - quote_id: &Uuid, - state: MeltQuoteState, - ) -> Result { - let mut melt_quotes = self.melt_quotes.write().await; - - let mut quote = melt_quotes - .get(quote_id) - .cloned() - .ok_or(Error::UnknownQuote)?; - - let current_state = quote.state; - - quote.state = state; - - melt_quotes.insert(*quote_id, quote.clone()); - - Ok(current_state) - } - - async fn get_melt_quotes(&self) -> Result, Self::Err> { - Ok(self.melt_quotes.read().await.values().cloned().collect()) - } - - async fn remove_melt_quote(&self, quote_id: &Uuid) -> Result<(), Self::Err> { - self.melt_quotes.write().await.remove(quote_id); - - Ok(()) - } - - async fn add_melt_request( - &self, - melt_request: MeltBolt11Request, - ln_key: LnKey, - ) -> Result<(), Self::Err> { - let mut melt_requests = self.melt_requests.write().await; - melt_requests.insert(melt_request.quote, (melt_request, ln_key)); - Ok(()) - } - - async fn get_melt_request( - &self, - quote_id: &Uuid, - ) -> Result, LnKey)>, Self::Err> { - let melt_requests = self.melt_requests.read().await; - - let melt_request = melt_requests.get(quote_id); - - Ok(melt_request.cloned()) - } - - async fn add_proofs(&self, proofs: Proofs, quote_id: Option) -> Result<(), Self::Err> { - let mut db_proofs = self.proofs.write().await; - - let mut ys = Vec::with_capacity(proofs.capacity()); - - for proof in proofs { - let y = hash_to_curve(&proof.secret.to_bytes())?; - ys.push(y); - - let y = y.to_bytes(); - - db_proofs.insert(y, proof); - } - - if let Some(quote_id) = quote_id { - let mut db_quote_proofs = self.quote_proofs.lock().await; - - db_quote_proofs.insert(quote_id, ys); - } - - Ok(()) - } - - async fn remove_proofs( - &self, - ys: &[PublicKey], - quote_id: Option, - ) -> Result<(), Self::Err> { - { - let mut db_proofs = self.proofs.write().await; - - ys.iter().for_each(|y| { - db_proofs.remove(&y.to_bytes()); - }); - } - - { - let mut db_proofs_state = self.proof_state.lock().await; - - ys.iter().for_each(|y| { - db_proofs_state.remove(&y.to_bytes()); - }); - } - - if let Some(quote_id) = quote_id { - let mut quote_proofs = self.quote_proofs.lock().await; - quote_proofs.remove("e_id); - } - - Ok(()) - } - - async fn get_proofs_by_ys(&self, ys: &[PublicKey]) -> Result>, Self::Err> { - let spent_proofs = self.proofs.read().await; - - let mut proofs = Vec::with_capacity(ys.len()); - - for y in ys { - let proof = spent_proofs.get(&y.to_bytes()).cloned(); - - proofs.push(proof); - } - - Ok(proofs) - } - - async fn get_proof_ys_by_quote_id(&self, quote_id: &Uuid) -> Result, Self::Err> { - let quote_proofs = &__self.quote_proofs.lock().await; - - match quote_proofs.get(quote_id) { - Some(ys) => Ok(ys.clone()), - None => Ok(vec![]), - } - } - - async fn update_proofs_states( - &self, - ys: &[PublicKey], - proof_state: State, - ) -> Result>, Self::Err> { - let mut proofs_states = self.proof_state.lock().await; - - let mut states = Vec::new(); - - for y in ys { - let state = proofs_states.insert(y.to_bytes(), proof_state); - states.push(state); - } - - Ok(states) - } - - async fn get_proofs_states(&self, ys: &[PublicKey]) -> Result>, Self::Err> { - let proofs_states = self.proof_state.lock().await; - - let mut states = Vec::new(); - - for y in ys { - let state = proofs_states.get(&y.to_bytes()).cloned(); - states.push(state); - } - - Ok(states) - } - - async fn get_proofs_by_keyset_id( - &self, - keyset_id: &Id, - ) -> Result<(Proofs, Vec>), Self::Err> { - let proofs = self.proofs.read().await; - - let proofs_for_id: Proofs = proofs - .iter() - .filter_map(|(_, p)| match &p.keyset_id == keyset_id { - true => Some(p), - false => None, - }) - .cloned() - .collect(); - - let proof_ys = proofs_for_id.ys()?; - - assert_eq!(proofs_for_id.len(), proof_ys.len()); - - let states = self.get_proofs_states(&proof_ys).await?; - - Ok((proofs_for_id, states)) - } - - async fn add_blind_signatures( - &self, - blinded_message: &[PublicKey], - blind_signatures: &[BlindSignature], - quote_id: Option, - ) -> Result<(), Self::Err> { - let mut current_blinded_signatures = self.blinded_signatures.write().await; - - for (blinded_message, blind_signature) in blinded_message.iter().zip(blind_signatures) { - current_blinded_signatures.insert(blinded_message.to_bytes(), blind_signature.clone()); - } - - if let Some(quote_id) = quote_id { - let mut current_quote_signatures = self.quote_signatures.write().await; - current_quote_signatures.insert(quote_id, blind_signatures.to_vec()); - } - - Ok(()) - } - - async fn get_blind_signatures( - &self, - blinded_messages: &[PublicKey], - ) -> Result>, Self::Err> { - let mut signatures = Vec::with_capacity(blinded_messages.len()); - - let blinded_signatures = self.blinded_signatures.read().await; - - for blinded_message in blinded_messages { - let signature = blinded_signatures.get(&blinded_message.to_bytes()).cloned(); - - signatures.push(signature) - } - - Ok(signatures) - } - - async fn get_blind_signatures_for_keyset( - &self, - keyset_id: &Id, - ) -> Result, Self::Err> { - let blinded_signatures = self.blinded_signatures.read().await; - - Ok(blinded_signatures - .values() - .filter(|b| &b.keyset_id == keyset_id) - .cloned() - .collect()) - } - - /// Get [`BlindSignature`]s for quote - async fn get_blind_signatures_for_quote( - &self, - quote_id: &Uuid, - ) -> Result, Self::Err> { - let ys = self.quote_signatures.read().await; - - Ok(ys.get(quote_id).cloned().unwrap_or_default()) - } - - async fn set_mint_info(&self, mint_info: MintInfo) -> Result<(), Self::Err> { - let mut current_mint_info = self.mint_info.write().await; - - *current_mint_info = mint_info; - - Ok(()) - } - async fn get_mint_info(&self) -> Result { - let mint_info = self.mint_info.read().await; - - Ok(mint_info.clone()) - } - - async fn set_quote_ttl(&self, quote_ttl: QuoteTTL) -> Result<(), Self::Err> { - let mut current_quote_ttl = self.quote_ttl.write().await; - - *current_quote_ttl = quote_ttl; - - Ok(()) - } - async fn get_quote_ttl(&self) -> Result { - let quote_ttl = self.quote_ttl.read().await; - - Ok(*quote_ttl) - } -} diff --git a/crates/cdk/src/cdk_database/mod.rs b/crates/cdk/src/cdk_database/mod.rs deleted file mode 100644 index e2ec6458..00000000 --- a/crates/cdk/src/cdk_database/mod.rs +++ /dev/null @@ -1,11 +0,0 @@ -//! CDK Database - -#[cfg(feature = "mint")] -pub mod mint_memory; -#[cfg(feature = "wallet")] -pub mod wallet_memory; - -/// re-export types -pub use cdk_common::database::{Error, MintDatabase, WalletDatabase}; -#[cfg(feature = "wallet")] -pub use wallet_memory::WalletMemoryDatabase; diff --git a/crates/cdk/src/cdk_database/wallet_memory.rs b/crates/cdk/src/cdk_database/wallet_memory.rs deleted file mode 100644 index 5c2785db..00000000 --- a/crates/cdk/src/cdk_database/wallet_memory.rs +++ /dev/null @@ -1,356 +0,0 @@ -//! Wallet in memory database - -use std::collections::{HashMap, HashSet}; -use std::sync::Arc; - -use async_trait::async_trait; -use cdk_common::database::{Error, WalletDatabase}; -use tokio::sync::RwLock; - -use crate::mint_url::MintUrl; -use crate::nuts::{ - CurrencyUnit, Id, KeySetInfo, Keys, MintInfo, PublicKey, SpendingConditions, State, -}; -use crate::types::ProofInfo; -use crate::util::unix_time; -use crate::wallet; -use crate::wallet::types::MintQuote; - -/// Wallet in Memory Database -#[derive(Debug, Clone, Default)] -pub struct WalletMemoryDatabase { - mints: Arc>>>, - mint_keysets: Arc>>>, - keysets: Arc>>, - mint_quotes: Arc>>, - melt_quotes: Arc>>, - mint_keys: Arc>>, - proofs: Arc>>, - keyset_counter: Arc>>, - nostr_last_checked: Arc>>, -} - -impl WalletMemoryDatabase { - /// Create new [`WalletMemoryDatabase`] - pub fn new( - mint_quotes: Vec, - melt_quotes: Vec, - mint_keys: Vec, - keyset_counter: HashMap, - nostr_last_checked: HashMap, - ) -> Self { - Self { - mints: Arc::new(RwLock::new(HashMap::new())), - mint_keysets: Arc::new(RwLock::new(HashMap::new())), - keysets: Arc::new(RwLock::new(HashMap::new())), - mint_quotes: Arc::new(RwLock::new( - mint_quotes.into_iter().map(|q| (q.id.clone(), q)).collect(), - )), - melt_quotes: Arc::new(RwLock::new( - melt_quotes.into_iter().map(|q| (q.id.clone(), q)).collect(), - )), - mint_keys: Arc::new(RwLock::new( - mint_keys.into_iter().map(|k| (Id::from(&k), k)).collect(), - )), - proofs: Arc::new(RwLock::new(HashMap::new())), - keyset_counter: Arc::new(RwLock::new(keyset_counter)), - nostr_last_checked: Arc::new(RwLock::new(nostr_last_checked)), - } - } -} - -#[cfg_attr(target_arch = "wasm32", async_trait(?Send))] -#[cfg_attr(not(target_arch = "wasm32"), async_trait)] -impl WalletDatabase for WalletMemoryDatabase { - type Err = Error; - - async fn add_mint( - &self, - mint_url: MintUrl, - mint_info: Option, - ) -> Result<(), Self::Err> { - self.mints.write().await.insert(mint_url, mint_info); - Ok(()) - } - - async fn remove_mint(&self, mint_url: MintUrl) -> Result<(), Self::Err> { - let mut mints = self.mints.write().await; - mints.remove(&mint_url); - - Ok(()) - } - - async fn get_mint(&self, mint_url: MintUrl) -> Result, Self::Err> { - Ok(self.mints.read().await.get(&mint_url).cloned().flatten()) - } - - async fn get_mints(&self) -> Result>, Error> { - Ok(self.mints.read().await.clone()) - } - - async fn update_mint_url( - &self, - old_mint_url: MintUrl, - new_mint_url: MintUrl, - ) -> Result<(), Self::Err> { - let proofs = self - .get_proofs(Some(old_mint_url), None, None, None) - .await?; - - // Update proofs - { - let updated_proofs: Vec = proofs - .into_iter() - .map(|mut p| { - p.mint_url = new_mint_url.clone(); - p - }) - .collect(); - - self.update_proofs(updated_proofs, vec![]).await?; - } - - // Update mint quotes - { - let quotes = self.get_mint_quotes().await?; - - let unix_time = unix_time(); - - let quotes: Vec = quotes - .into_iter() - .filter_map(|mut q| { - if q.expiry < unix_time { - q.mint_url = new_mint_url.clone(); - Some(q) - } else { - None - } - }) - .collect(); - - for quote in quotes { - self.add_mint_quote(quote).await?; - } - } - - Ok(()) - } - - async fn add_mint_keysets( - &self, - mint_url: MintUrl, - keysets: Vec, - ) -> Result<(), Error> { - let mut current_mint_keysets = self.mint_keysets.write().await; - let mut current_keysets = self.keysets.write().await; - - for keyset in keysets { - current_mint_keysets - .entry(mint_url.clone()) - .and_modify(|ks| { - ks.insert(keyset.id); - }) - .or_insert(HashSet::from_iter(vec![keyset.id])); - - current_keysets.insert(keyset.id, keyset); - } - - Ok(()) - } - - async fn get_mint_keysets(&self, mint_url: MintUrl) -> Result>, Error> { - match self.mint_keysets.read().await.get(&mint_url) { - Some(keyset_ids) => { - let mut keysets = vec![]; - - let db_keysets = self.keysets.read().await; - - for id in keyset_ids { - if let Some(keyset) = db_keysets.get(id) { - keysets.push(keyset.clone()); - } - } - - Ok(Some(keysets)) - } - None => Ok(None), - } - } - - async fn get_keyset_by_id(&self, keyset_id: &Id) -> Result, Error> { - Ok(self.keysets.read().await.get(keyset_id).cloned()) - } - - async fn add_mint_quote(&self, quote: MintQuote) -> Result<(), Error> { - self.mint_quotes - .write() - .await - .insert(quote.id.clone(), quote); - Ok(()) - } - - async fn get_mint_quote(&self, quote_id: &str) -> Result, Error> { - Ok(self.mint_quotes.read().await.get(quote_id).cloned()) - } - - async fn get_mint_quotes(&self) -> Result, Error> { - let quotes = self.mint_quotes.read().await; - Ok(quotes.values().cloned().collect()) - } - - async fn remove_mint_quote(&self, quote_id: &str) -> Result<(), Error> { - self.mint_quotes.write().await.remove(quote_id); - - Ok(()) - } - - async fn add_melt_quote(&self, quote: wallet::MeltQuote) -> Result<(), Error> { - self.melt_quotes - .write() - .await - .insert(quote.id.clone(), quote); - Ok(()) - } - - async fn get_melt_quote(&self, quote_id: &str) -> Result, Error> { - Ok(self.melt_quotes.read().await.get(quote_id).cloned()) - } - - async fn remove_melt_quote(&self, quote_id: &str) -> Result<(), Error> { - self.melt_quotes.write().await.remove(quote_id); - - Ok(()) - } - - async fn add_keys(&self, keys: Keys) -> Result<(), Error> { - self.mint_keys.write().await.insert(Id::from(&keys), keys); - Ok(()) - } - - async fn get_keys(&self, id: &Id) -> Result, Error> { - Ok(self.mint_keys.read().await.get(id).cloned()) - } - - async fn remove_keys(&self, id: &Id) -> Result<(), Error> { - self.mint_keys.write().await.remove(id); - Ok(()) - } - - async fn update_proofs( - &self, - added: Vec, - removed_ys: Vec, - ) -> Result<(), Error> { - let mut all_proofs = self.proofs.write().await; - - for proof_info in added.into_iter() { - all_proofs.insert(proof_info.y, proof_info); - } - - for y in removed_ys.into_iter() { - all_proofs.remove(&y); - } - - Ok(()) - } - - async fn set_pending_proofs(&self, ys: Vec) -> Result<(), Error> { - let mut all_proofs = self.proofs.write().await; - - for y in ys.into_iter() { - if let Some(proof_info) = all_proofs.get_mut(&y) { - proof_info.state = State::Pending; - } - } - - Ok(()) - } - - async fn reserve_proofs(&self, ys: Vec) -> Result<(), Error> { - let mut all_proofs = self.proofs.write().await; - - for y in ys.into_iter() { - if let Some(proof_info) = all_proofs.get_mut(&y) { - proof_info.state = State::Reserved; - } - } - - Ok(()) - } - - async fn set_unspent_proofs(&self, ys: Vec) -> Result<(), Error> { - let mut all_proofs = self.proofs.write().await; - - for y in ys.into_iter() { - if let Some(proof_info) = all_proofs.get_mut(&y) { - proof_info.state = State::Unspent; - } - } - - Ok(()) - } - - async fn get_proofs( - &self, - mint_url: Option, - unit: Option, - state: Option>, - spending_conditions: Option>, - ) -> Result, Error> { - let proofs = self.proofs.read().await; - - let proofs: Vec = proofs - .clone() - .into_values() - .filter_map(|proof_info| { - match proof_info.matches_conditions(&mint_url, &unit, &state, &spending_conditions) - { - true => Some(proof_info), - false => None, - } - }) - .collect(); - - Ok(proofs) - } - - async fn increment_keyset_counter(&self, keyset_id: &Id, count: u32) -> Result<(), Error> { - let keyset_counter = self.keyset_counter.read().await; - let current_counter = keyset_counter.get(keyset_id).cloned().unwrap_or(0); - drop(keyset_counter); - - self.keyset_counter - .write() - .await - .insert(*keyset_id, current_counter + count); - Ok(()) - } - - async fn get_keyset_counter(&self, id: &Id) -> Result, Error> { - Ok(self.keyset_counter.read().await.get(id).cloned()) - } - - async fn get_nostr_last_checked( - &self, - verifying_key: &PublicKey, - ) -> Result, Self::Err> { - Ok(self - .nostr_last_checked - .read() - .await - .get(verifying_key) - .cloned()) - } - async fn add_nostr_last_checked( - &self, - verifying_key: PublicKey, - last_checked: u32, - ) -> Result<(), Self::Err> { - self.nostr_last_checked - .write() - .await - .insert(verifying_key, last_checked); - - Ok(()) - } -} diff --git a/crates/cdk/src/lib.rs b/crates/cdk/src/lib.rs index 9fffadb3..fb2e34ce 100644 --- a/crates/cdk/src/lib.rs +++ b/crates/cdk/src/lib.rs @@ -3,8 +3,10 @@ #![warn(missing_docs)] #![warn(rustdoc::bare_urls)] -#[cfg(any(feature = "wallet", feature = "mint"))] -pub mod cdk_database; +pub mod cdk_database { + //! CDK Database + pub use cdk_common::database::{Error, MintDatabase, WalletDatabase}; +} #[cfg(feature = "mint")] pub mod mint; diff --git a/crates/cdk/src/mint/mod.rs b/crates/cdk/src/mint/mod.rs index 9456514a..caee81d0 100644 --- a/crates/cdk/src/mint/mod.rs +++ b/crates/cdk/src/mint/mod.rs @@ -503,12 +503,12 @@ mod tests { use std::str::FromStr; use bitcoin::Network; - use cdk_common::common::{LnKey, QuoteTTL}; + use cdk_common::common::LnKey; + use cdk_sqlite::mint::memory::new_with_state; use secp256k1::Secp256k1; use uuid::Uuid; use super::*; - use crate::cdk_database::mint_memory::MintMemoryDatabase; #[test] fn mint_mod_generate_keyset_from_seed() { @@ -604,32 +604,25 @@ mod tests { melt_quotes: Vec, pending_proofs: Proofs, spent_proofs: Proofs, - blinded_signatures: HashMap<[u8; 33], BlindSignature>, - quote_proofs: HashMap>, - quote_signatures: HashMap>, seed: &'a [u8], mint_info: MintInfo, supported_units: HashMap, melt_requests: Vec<(MeltBolt11Request, LnKey)>, - quote_ttl: QuoteTTL, } async fn create_mint(config: MintConfig<'_>) -> Result { let localstore = Arc::new( - MintMemoryDatabase::new( + new_with_state( config.active_keysets, config.keysets, config.mint_quotes, config.melt_quotes, config.pending_proofs, config.spent_proofs, - config.quote_proofs, - config.blinded_signatures, - config.quote_signatures, config.melt_requests, config.mint_info, - config.quote_ttl, ) + .await .unwrap(), ); diff --git a/crates/cdk/src/wallet/README.md b/crates/cdk/src/wallet/README.md index 49d8114c..ec9daaa6 100644 --- a/crates/cdk/src/wallet/README.md +++ b/crates/cdk/src/wallet/README.md @@ -8,15 +8,19 @@ The CDK [`Wallet`] is a high level Cashu wallet. The [`Wallet`] is for a single ### Create [`Wallet`] ```rust use std::sync::Arc; - use cdk::cdk_database::WalletMemoryDatabase; use cdk::nuts::CurrencyUnit; use cdk::wallet::Wallet; + use cdk_sqlite::wallet::memory; use rand::Rng; - let seed = rand::thread_rng().gen::<[u8; 32]>(); - let mint_url = "https://testnut.cashu.space"; - let unit = CurrencyUnit::Sat; + #[tokio::main] + async fn main() -> anyhow::Result<()> { + let seed = rand::thread_rng().gen::<[u8; 32]>(); + let mint_url = "https://testnut.cashu.space"; + let unit = CurrencyUnit::Sat; - let localstore = WalletMemoryDatabase::default(); - let wallet = Wallet::new(mint_url, unit, Arc::new(localstore), &seed, None); + let localstore = memory::empty().await?; + let wallet = Wallet::new(mint_url, unit, Arc::new(localstore), &seed, None); + Ok(()) + } ``` diff --git a/crates/cdk/src/wallet/keysets.rs b/crates/cdk/src/wallet/keysets.rs index a605a060..b19d3ec3 100644 --- a/crates/cdk/src/wallet/keysets.rs +++ b/crates/cdk/src/wallet/keysets.rs @@ -89,6 +89,8 @@ impl Wallet { /// keysets #[instrument(skip(self))] pub async fn get_active_mint_keyset(&self) -> Result { + // Important + let _ = self.get_mint_info().await?; let active_keysets = self.get_active_mint_keysets().await?; let keyset_with_lowest_fee = active_keysets diff --git a/crates/cdk/src/wallet/melt.rs b/crates/cdk/src/wallet/melt.rs index 81aacffd..37ad7f0a 100644 --- a/crates/cdk/src/wallet/melt.rs +++ b/crates/cdk/src/wallet/melt.rs @@ -20,7 +20,7 @@ impl Wallet { /// ```rust /// use std::sync::Arc; /// - /// use cdk::cdk_database::WalletMemoryDatabase; + /// use cdk_sqlite::wallet::memory; /// use cdk::nuts::CurrencyUnit; /// use cdk::wallet::Wallet; /// use rand::Rng; @@ -31,7 +31,7 @@ impl Wallet { /// let mint_url = "https://testnut.cashu.space"; /// let unit = CurrencyUnit::Sat; /// - /// let localstore = WalletMemoryDatabase::default(); + /// let localstore = memory::empty().await?; /// let wallet = Wallet::new(mint_url, unit, Arc::new(localstore), &seed, None).unwrap(); /// let bolt11 = "lnbc100n1pnvpufspp5djn8hrq49r8cghwye9kqw752qjncwyfnrprhprpqk43mwcy4yfsqdq5g9kxy7fqd9h8vmmfvdjscqzzsxqyz5vqsp5uhpjt36rj75pl7jq2sshaukzfkt7uulj456s4mh7uy7l6vx7lvxs9qxpqysgqedwz08acmqwtk8g4vkwm2w78suwt2qyzz6jkkwcgrjm3r3hs6fskyhvud4fan3keru7emjm8ygqpcrwtlmhfjfmer3afs5hhwamgr4cqtactdq".to_string(); /// let quote = wallet.melt_quote(bolt11, None).await?; @@ -249,7 +249,7 @@ impl Wallet { /// ```rust, no_run /// use std::sync::Arc; /// - /// use cdk::cdk_database::WalletMemoryDatabase; + /// use cdk_sqlite::wallet::memory; /// use cdk::nuts::CurrencyUnit; /// use cdk::wallet::Wallet; /// use rand::Rng; @@ -260,7 +260,7 @@ impl Wallet { /// let mint_url = "https://testnut.cashu.space"; /// let unit = CurrencyUnit::Sat; /// - /// let localstore = WalletMemoryDatabase::default(); + /// let localstore = memory::empty().await?; /// let wallet = Wallet::new(mint_url, unit, Arc::new(localstore), &seed, None).unwrap(); /// let bolt11 = "lnbc100n1pnvpufspp5djn8hrq49r8cghwye9kqw752qjncwyfnrprhprpqk43mwcy4yfsqdq5g9kxy7fqd9h8vmmfvdjscqzzsxqyz5vqsp5uhpjt36rj75pl7jq2sshaukzfkt7uulj456s4mh7uy7l6vx7lvxs9qxpqysgqedwz08acmqwtk8g4vkwm2w78suwt2qyzz6jkkwcgrjm3r3hs6fskyhvud4fan3keru7emjm8ygqpcrwtlmhfjfmer3afs5hhwamgr4cqtactdq".to_string(); /// let quote = wallet.melt_quote(bolt11, None).await?; diff --git a/crates/cdk/src/wallet/mint.rs b/crates/cdk/src/wallet/mint.rs index e340cca3..b8da56a4 100644 --- a/crates/cdk/src/wallet/mint.rs +++ b/crates/cdk/src/wallet/mint.rs @@ -20,7 +20,7 @@ impl Wallet { /// use std::sync::Arc; /// /// use cdk::amount::Amount; - /// use cdk::cdk_database::WalletMemoryDatabase; + /// use cdk_sqlite::wallet::memory; /// use cdk::nuts::CurrencyUnit; /// use cdk::wallet::Wallet; /// use rand::Rng; @@ -31,7 +31,7 @@ impl Wallet { /// let mint_url = "https://testnut.cashu.space"; /// let unit = CurrencyUnit::Sat; /// - /// let localstore = WalletMemoryDatabase::default(); + /// let localstore = memory::empty().await?; /// let wallet = Wallet::new(mint_url, unit, Arc::new(localstore), &seed, None)?; /// let amount = Amount::from(100); /// @@ -144,7 +144,7 @@ impl Wallet { /// /// use anyhow::Result; /// use cdk::amount::{Amount, SplitTarget}; - /// use cdk::cdk_database::WalletMemoryDatabase; + /// use cdk_sqlite::wallet::memory; /// use cdk::nuts::nut00::ProofsMethods; /// use cdk::nuts::CurrencyUnit; /// use cdk::wallet::Wallet; @@ -156,7 +156,7 @@ impl Wallet { /// let mint_url = "https://testnut.cashu.space"; /// let unit = CurrencyUnit::Sat; /// - /// let localstore = WalletMemoryDatabase::default(); + /// let localstore = memory::empty().await?; /// let wallet = Wallet::new(mint_url, unit, Arc::new(localstore), &seed, None).unwrap(); /// let amount = Amount::from(100); /// diff --git a/crates/cdk/src/wallet/mod.rs b/crates/cdk/src/wallet/mod.rs index 68dd2599..cafc011e 100644 --- a/crates/cdk/src/wallet/mod.rs +++ b/crates/cdk/src/wallet/mod.rs @@ -119,17 +119,20 @@ impl Wallet { /// ```rust /// use std::sync::Arc; /// - /// use cdk::cdk_database::WalletMemoryDatabase; + /// use cdk_sqlite::wallet::memory; /// use cdk::nuts::CurrencyUnit; /// use cdk::wallet::Wallet; /// use rand::Rng; /// - /// let seed = rand::thread_rng().gen::<[u8; 32]>(); - /// let mint_url = "https://testnut.cashu.space"; - /// let unit = CurrencyUnit::Sat; + /// async fn test() -> anyhow::Result<()> { + /// let seed = rand::thread_rng().gen::<[u8; 32]>(); + /// let mint_url = "https://testnut.cashu.space"; + /// let unit = CurrencyUnit::Sat; /// - /// let localstore = WalletMemoryDatabase::default(); - /// let wallet = Wallet::new(mint_url, unit, Arc::new(localstore), &seed, None); + /// let localstore = memory::empty().await?; + /// let wallet = Wallet::new(mint_url, unit, Arc::new(localstore), &seed, None); + /// Ok(()) + /// } /// ``` pub fn new( mint_url: &str, diff --git a/crates/cdk/src/wallet/receive.rs b/crates/cdk/src/wallet/receive.rs index 1baddf34..a08ab029 100644 --- a/crates/cdk/src/wallet/receive.rs +++ b/crates/cdk/src/wallet/receive.rs @@ -164,7 +164,7 @@ impl Wallet { /// use std::sync::Arc; /// /// use cdk::amount::SplitTarget; - /// use cdk::cdk_database::WalletMemoryDatabase; + /// use cdk_sqlite::wallet::memory; /// use cdk::nuts::CurrencyUnit; /// use cdk::wallet::Wallet; /// use rand::Rng; @@ -175,7 +175,7 @@ impl Wallet { /// let mint_url = "https://testnut.cashu.space"; /// let unit = CurrencyUnit::Sat; /// - /// let localstore = WalletMemoryDatabase::default(); + /// let localstore = memory::empty().await?; /// let wallet = Wallet::new(mint_url, unit, Arc::new(localstore), &seed, None).unwrap(); /// let token = "cashuAeyJ0b2tlbiI6W3sicHJvb2ZzIjpbeyJhbW91bnQiOjEsInNlY3JldCI6ImI0ZjVlNDAxMDJhMzhiYjg3NDNiOTkwMzU5MTU1MGYyZGEzZTQxNWEzMzU0OTUyN2M2MmM5ZDc5MGVmYjM3MDUiLCJDIjoiMDIzYmU1M2U4YzYwNTMwZWVhOWIzOTQzZmRhMWEyY2U3MWM3YjNmMGNmMGRjNmQ4NDZmYTc2NWFhZjc3OWZhODFkIiwiaWQiOiIwMDlhMWYyOTMyNTNlNDFlIn1dLCJtaW50IjoiaHR0cHM6Ly90ZXN0bnV0LmNhc2h1LnNwYWNlIn1dLCJ1bml0Ijoic2F0In0="; /// let amount_receive = wallet.receive(token, SplitTarget::default(), &[], &[]).await?; @@ -223,7 +223,7 @@ impl Wallet { /// use std::sync::Arc; /// /// use cdk::amount::SplitTarget; - /// use cdk::cdk_database::WalletMemoryDatabase; + /// use cdk_sqlite::wallet::memory; /// use cdk::nuts::CurrencyUnit; /// use cdk::wallet::Wallet; /// use cdk::util::hex; @@ -235,7 +235,7 @@ impl Wallet { /// let mint_url = "https://testnut.cashu.space"; /// let unit = CurrencyUnit::Sat; /// - /// let localstore = WalletMemoryDatabase::default(); + /// let localstore = memory::empty().await?; /// let wallet = Wallet::new(mint_url, unit, Arc::new(localstore), &seed, None).unwrap(); /// let token_raw = hex::decode("6372617742a4617481a261694800ad268c4d1f5826617081a3616101617378403961366462623834376264323332626137366462306466313937323136623239643362386363313435353363643237383237666331636339343266656462346561635821038618543ffb6b8695df4ad4babcde92a34a96bdcd97dcee0d7ccf98d4721267926164695468616e6b20796f75616d75687474703a2f2f6c6f63616c686f73743a33333338617563736174").unwrap(); /// let amount_receive = wallet.receive_raw(&token_raw, SplitTarget::default(), &[], &[]).await?; diff --git a/misc/itests.sh b/misc/itests.sh index dbfb689b..abaf75a3 100755 --- a/misc/itests.sh +++ b/misc/itests.sh @@ -77,8 +77,6 @@ echo "Starting regtest mint" # cargo run --bin regtest_mint & export CDK_MINTD_CLN_RPC_PATH="$cdk_itests/cln/one/regtest/lightning-rpc"; - - export CDK_MINTD_URL="http://$cdk_itests_mint_addr:$cdk_itests_mint_port_0"; export CDK_MINTD_WORK_DIR="$cdk_itests"; export CDK_MINTD_LISTEN_HOST=$cdk_itests_mint_addr; @@ -86,6 +84,7 @@ export CDK_MINTD_LISTEN_PORT=$cdk_itests_mint_port_0; export CDK_MINTD_LN_BACKEND="cln"; export CDK_MINTD_MNEMONIC="eye survey guilt napkin crystal cup whisper salt luggage manage unveil loyal"; export CDK_MINTD_DATABASE=$MINT_DATABASE; +export RUST_BACKTRACE=1 echo "Starting cln mintd"; cargo run --bin cdk-mintd &