Explorar o código

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<Mint>

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
C hai 3 semanas
pai
achega
f7d9a1b5db

+ 8 - 5
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<Arc<Mint>> {
 
     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<Arc<Mint>> {
     Ok(mint_arc)
 }
 
-pub fn create_test_wallet_for_mint(mint: Arc<Mint>) -> anyhow::Result<Arc<Wallet>> {
+pub async fn create_test_wallet_for_mint(mint: Arc<Mint>) -> anyhow::Result<Arc<Wallet>> {
     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);

+ 28 - 29
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,
     )?;

+ 2 - 2
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?;

+ 9 - 12
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<Mint> = 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);
 

+ 12 - 12
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,
     )?;

+ 29 - 0
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<Pool<Sqlite>, 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)
+}

+ 2 - 0
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")]

+ 61 - 0
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<MintSqliteDatabase, database::Error> {
+    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<CurrencyUnit, Id>,
+    keysets: Vec<MintKeySetInfo>,
+    mint_quotes: Vec<MintQuote>,
+    melt_quotes: Vec<mint::MeltQuote>,
+    pending_proofs: Proofs,
+    spent_proofs: Proofs,
+    melt_request: Vec<(MeltBolt11Request<Uuid>, LnKey)>,
+    mint_info: MintInfo,
+) -> Result<MintSqliteDatabase, database::Error> {
+    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)
+}

+ 10 - 18
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<Sqlite>,
 }
 
 impl MintSqliteDatabase {
     /// Create new [`MintSqliteDatabase`]
-    pub async fn new(path: &Path) -> Result<Self, Error> {
-        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<P: AsRef<Path>>(path: P) -> Result<Self, Error> {
+        Ok(Self {
+            pool: create_sqlite_pool(path.as_ref().to_str().ok_or(Error::InvalidDbPath)?).await?,
+        })
     }
 
     /// Migrate [`MintSqliteDatabase`]

+ 12 - 0
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<WalletSqliteDatabase, Error> {
+    let db = WalletSqliteDatabase::new(":memory:").await?;
+    db.migrate().await;
+    Ok(db)
+}

+ 10 - 16
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<Sqlite>,
 }
 
 impl WalletSqliteDatabase {
     /// Create new [`WalletSqliteDatabase`]
-    pub async fn new(path: &Path) -> Result<Self, Error> {
-        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<P: AsRef<Path>>(path: P) -> Result<Self, Error> {
+        Ok(Self {
+            pool: create_sqlite_pool(path.as_ref().to_str().ok_or(Error::InvalidDbPath)?).await?,
+        })
     }
 
     /// Migrate [`WalletSqliteDatabase`]

+ 1 - 0
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]]

+ 3 - 3
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
 ```
 

+ 2 - 2
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]>();

+ 2 - 2
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]>();

+ 2 - 2
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<dyn std::error::Error>> {
     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)?;

+ 2 - 2
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<dyn std::error::Error>> {
     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)?;

+ 0 - 493
crates/cdk/src/cdk_database/mint_memory.rs

@@ -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<RwLock<HashMap<CurrencyUnit, Id>>>,
-    keysets: Arc<RwLock<HashMap<Id, MintKeySetInfo>>>,
-    mint_quotes: Arc<RwLock<HashMap<Uuid, MintQuote>>>,
-    melt_quotes: Arc<RwLock<HashMap<Uuid, mint::MeltQuote>>>,
-    proofs: Arc<RwLock<HashMap<[u8; 33], Proof>>>,
-    proof_state: Arc<Mutex<HashMap<[u8; 33], nut07::State>>>,
-    quote_proofs: Arc<Mutex<HashMap<Uuid, Vec<PublicKey>>>>,
-    blinded_signatures: Arc<RwLock<HashMap<[u8; 33], BlindSignature>>>,
-    quote_signatures: Arc<RwLock<HashMap<Uuid, Vec<BlindSignature>>>>,
-    melt_requests: Arc<RwLock<HashMap<Uuid, (MeltBolt11Request<Uuid>, LnKey)>>>,
-    mint_info: Arc<RwLock<MintInfo>>,
-    quote_ttl: Arc<RwLock<QuoteTTL>>,
-}
-
-impl MintMemoryDatabase {
-    /// Create new [`MintMemoryDatabase`]
-    #[allow(clippy::too_many_arguments)]
-    pub fn new(
-        active_keysets: HashMap<CurrencyUnit, Id>,
-        keysets: Vec<MintKeySetInfo>,
-        mint_quotes: Vec<MintQuote>,
-        melt_quotes: Vec<mint::MeltQuote>,
-        pending_proofs: Proofs,
-        spent_proofs: Proofs,
-        quote_proofs: HashMap<Uuid, Vec<PublicKey>>,
-        blinded_signatures: HashMap<[u8; 33], BlindSignature>,
-        quote_signatures: HashMap<Uuid, Vec<BlindSignature>>,
-        melt_request: Vec<(MeltBolt11Request<Uuid>, LnKey)>,
-        mint_info: MintInfo,
-        quote_ttl: QuoteTTL,
-    ) -> Result<Self, Error> {
-        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<Option<Id>, Self::Err> {
-        Ok(self.active_keysets.read().await.get(unit).cloned())
-    }
-
-    async fn get_active_keysets(&self) -> Result<HashMap<CurrencyUnit, Id>, 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<Option<MintKeySetInfo>, Self::Err> {
-        Ok(self.keysets.read().await.get(keyset_id).cloned())
-    }
-
-    async fn get_keyset_infos(&self) -> Result<Vec<MintKeySetInfo>, 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<Option<MintQuote>, 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<MintQuoteState, Self::Err> {
-        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<Option<MintQuote>, Self::Err> {
-        let quotes = self.get_mint_quotes().await?;
-
-        let quote = quotes
-            .into_iter()
-            .filter(|q| q.request_lookup_id.eq(request))
-            .collect::<Vec<MintQuote>>()
-            .first()
-            .cloned();
-
-        Ok(quote)
-    }
-    async fn get_mint_quote_by_request(
-        &self,
-        request: &str,
-    ) -> Result<Option<MintQuote>, Self::Err> {
-        let quotes = self.get_mint_quotes().await?;
-
-        let quote = quotes
-            .into_iter()
-            .filter(|q| q.request.eq(request))
-            .collect::<Vec<MintQuote>>()
-            .first()
-            .cloned();
-
-        Ok(quote)
-    }
-
-    async fn get_mint_quotes(&self) -> Result<Vec<MintQuote>, Self::Err> {
-        Ok(self.mint_quotes.read().await.values().cloned().collect())
-    }
-
-    async fn get_mint_quotes_with_state(
-        &self,
-        state: MintQuoteState,
-    ) -> Result<Vec<MintQuote>, 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<Option<mint::MeltQuote>, 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<MeltQuoteState, Self::Err> {
-        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<Vec<mint::MeltQuote>, 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<Uuid>,
-        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<Option<(MeltBolt11Request<Uuid>, 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<Uuid>) -> 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<Uuid>,
-    ) -> 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(&quote_id);
-        }
-
-        Ok(())
-    }
-
-    async fn get_proofs_by_ys(&self, ys: &[PublicKey]) -> Result<Vec<Option<Proof>>, 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<Vec<PublicKey>, 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<Vec<Option<State>>, 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<Vec<Option<State>>, 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<Option<State>>), 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<Uuid>,
-    ) -> 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<Vec<Option<BlindSignature>>, 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<Vec<BlindSignature>, 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<Vec<BlindSignature>, 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<MintInfo, Self::Err> {
-        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<QuoteTTL, Self::Err> {
-        let quote_ttl = self.quote_ttl.read().await;
-
-        Ok(*quote_ttl)
-    }
-}

+ 0 - 11
crates/cdk/src/cdk_database/mod.rs

@@ -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;

+ 0 - 356
crates/cdk/src/cdk_database/wallet_memory.rs

@@ -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<RwLock<HashMap<MintUrl, Option<MintInfo>>>>,
-    mint_keysets: Arc<RwLock<HashMap<MintUrl, HashSet<Id>>>>,
-    keysets: Arc<RwLock<HashMap<Id, KeySetInfo>>>,
-    mint_quotes: Arc<RwLock<HashMap<String, MintQuote>>>,
-    melt_quotes: Arc<RwLock<HashMap<String, wallet::MeltQuote>>>,
-    mint_keys: Arc<RwLock<HashMap<Id, Keys>>>,
-    proofs: Arc<RwLock<HashMap<PublicKey, ProofInfo>>>,
-    keyset_counter: Arc<RwLock<HashMap<Id, u32>>>,
-    nostr_last_checked: Arc<RwLock<HashMap<PublicKey, u32>>>,
-}
-
-impl WalletMemoryDatabase {
-    /// Create new [`WalletMemoryDatabase`]
-    pub fn new(
-        mint_quotes: Vec<MintQuote>,
-        melt_quotes: Vec<wallet::MeltQuote>,
-        mint_keys: Vec<Keys>,
-        keyset_counter: HashMap<Id, u32>,
-        nostr_last_checked: HashMap<PublicKey, u32>,
-    ) -> 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<MintInfo>,
-    ) -> 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<Option<MintInfo>, Self::Err> {
-        Ok(self.mints.read().await.get(&mint_url).cloned().flatten())
-    }
-
-    async fn get_mints(&self) -> Result<HashMap<MintUrl, Option<MintInfo>>, 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<ProofInfo> = 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<MintQuote> = 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<KeySetInfo>,
-    ) -> 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<Option<Vec<KeySetInfo>>, 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<Option<KeySetInfo>, 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<Option<MintQuote>, Error> {
-        Ok(self.mint_quotes.read().await.get(quote_id).cloned())
-    }
-
-    async fn get_mint_quotes(&self) -> Result<Vec<MintQuote>, 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<Option<wallet::MeltQuote>, 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<Option<Keys>, 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<ProofInfo>,
-        removed_ys: Vec<PublicKey>,
-    ) -> 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<PublicKey>) -> 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<PublicKey>) -> 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<PublicKey>) -> 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<MintUrl>,
-        unit: Option<CurrencyUnit>,
-        state: Option<Vec<State>>,
-        spending_conditions: Option<Vec<SpendingConditions>>,
-    ) -> Result<Vec<ProofInfo>, Error> {
-        let proofs = self.proofs.read().await;
-
-        let proofs: Vec<ProofInfo> = 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<Option<u32>, Error> {
-        Ok(self.keyset_counter.read().await.get(id).cloned())
-    }
-
-    async fn get_nostr_last_checked(
-        &self,
-        verifying_key: &PublicKey,
-    ) -> Result<Option<u32>, 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(())
-    }
-}

+ 4 - 2
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;

+ 4 - 11
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<MeltQuote>,
         pending_proofs: Proofs,
         spent_proofs: Proofs,
-        blinded_signatures: HashMap<[u8; 33], BlindSignature>,
-        quote_proofs: HashMap<Uuid, Vec<PublicKey>>,
-        quote_signatures: HashMap<Uuid, Vec<BlindSignature>>,
         seed: &'a [u8],
         mint_info: MintInfo,
         supported_units: HashMap<CurrencyUnit, (u64, u8)>,
         melt_requests: Vec<(MeltBolt11Request<Uuid>, LnKey)>,
-        quote_ttl: QuoteTTL,
     }
 
     async fn create_mint(config: MintConfig<'_>) -> Result<Mint, Error> {
         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(),
         );
 

+ 10 - 6
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(())
+  }
 ```

+ 2 - 0
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<KeySetInfo, Error> {
+        // Important
+        let _ = self.get_mint_info().await?;
         let active_keysets = self.get_active_mint_keysets().await?;
 
         let keyset_with_lowest_fee = active_keysets

+ 4 - 4
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?;

+ 4 - 4
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);
     ///

+ 9 - 6
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,

+ 4 - 4
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?;

+ 1 - 2
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 &