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 &