Преглед на файлове

Merge pull request #653 from ok300/ok300-fix-update-mint-url

Wallet: fix `update_mint_url`
ok300 преди 1 месец
родител
ревизия
72dff95322

+ 1 - 1
crates/cdk-integration-tests/Cargo.toml

@@ -36,7 +36,7 @@ serde.workspace = true
 serde_json.workspace = true
 # ln-regtest-rs = { path = "../../../../ln-regtest-rs" }
 ln-regtest-rs = { git = "https://github.com/thesimplekid/ln-regtest-rs", rev = "ed24716" }
-lightning-invoice = { version = "0.32.0", features = ["serde", "std"] }
+lightning-invoice.workspace = true
 tracing.workspace = true
 tracing-subscriber.workspace = true
 tokio-tungstenite.workspace = true

+ 35 - 9
crates/cdk-integration-tests/src/init_pure_tests.rs

@@ -3,6 +3,7 @@ use std::fmt::{Debug, Formatter};
 use std::str::FromStr;
 use std::sync::Arc;
 
+use anyhow::{anyhow, Result};
 use async_trait::async_trait;
 use bip39::Mnemonic;
 use cdk::amount::SplitTarget;
@@ -21,7 +22,7 @@ use cdk::wallet::client::MintConnector;
 use cdk::wallet::Wallet;
 use cdk::{Amount, Error, Mint};
 use cdk_fake_wallet::FakeWallet;
-use tokio::sync::Notify;
+use tokio::sync::{Mutex, Notify};
 use tracing_subscriber::EnvFilter;
 use uuid::Uuid;
 
@@ -142,7 +143,7 @@ impl MintConnector for DirectMintConnection {
     }
 }
 
-pub async fn create_and_start_test_mint() -> anyhow::Result<Arc<Mint>> {
+pub fn setup_tracing() {
     let default_filter = "debug";
 
     let sqlx_filter = "sqlx=warn";
@@ -153,8 +154,14 @@ pub async fn create_and_start_test_mint() -> anyhow::Result<Arc<Mint>> {
         default_filter, sqlx_filter, hyper_filter
     ));
 
-    tracing_subscriber::fmt().with_env_filter(env_filter).init();
+    // Ok if successful, Err if already initialized
+    // Allows us to setup tracing at the start of several parallel tests
+    let _ = tracing_subscriber::fmt()
+        .with_env_filter(env_filter)
+        .try_init();
+}
 
+pub async fn create_and_start_test_mint() -> Result<Arc<Mint>> {
     let mut mint_builder = MintBuilder::new();
 
     let database = cdk_sqlite::mint::memory::empty().await?;
@@ -188,6 +195,7 @@ pub async fn create_and_start_test_mint() -> anyhow::Result<Arc<Mint>> {
     mint_builder = mint_builder
         .with_name("pure test mint".to_string())
         .with_description("pure test mint".to_string())
+        .with_urls(vec!["https://aaa".to_string()])
         .with_seed(mnemonic.to_seed_normalized("").to_vec());
 
     localstore
@@ -210,23 +218,41 @@ pub async fn create_and_start_test_mint() -> anyhow::Result<Arc<Mint>> {
     Ok(mint_arc)
 }
 
-pub async fn create_test_wallet_for_mint(mint: Arc<Mint>) -> anyhow::Result<Arc<Wallet>> {
-    let connector = DirectMintConnection::new(mint);
+async fn create_test_wallet_for_mint(mint: Arc<Mint>) -> Result<Wallet> {
+    let connector = DirectMintConnection::new(mint.clone());
+
+    let mint_info = mint.mint_info().await?;
+    let mint_url = mint_info
+        .urls
+        .as_ref()
+        .ok_or(anyhow!("Test mint URLs list is unset"))?
+        .first()
+        .ok_or(anyhow!("Test mint has empty URLs list"))?;
 
     let seed = Mnemonic::generate(12)?.to_seed_normalized("");
-    let mint_url = "http://aa".to_string();
     let unit = CurrencyUnit::Sat;
     let localstore = cdk_sqlite::wallet::memory::empty().await?;
-    let mut wallet = Wallet::new(&mint_url, unit, Arc::new(localstore), &seed, None)?;
+    let mut wallet = Wallet::new(mint_url, unit, Arc::new(localstore), &seed, None)?;
 
     wallet.set_client(connector);
 
-    Ok(Arc::new(wallet))
+    Ok(wallet)
+}
+
+pub async fn create_test_wallet_arc_for_mint(mint: Arc<Mint>) -> Result<Arc<Wallet>> {
+    create_test_wallet_for_mint(mint).await.map(Arc::new)
+}
+
+pub async fn create_test_wallet_arc_mut_for_mint(mint: Arc<Mint>) -> Result<Arc<Mutex<Wallet>>> {
+    create_test_wallet_for_mint(mint)
+        .await
+        .map(Mutex::new)
+        .map(Arc::new)
 }
 
 /// Creates a mint quote for the given amount and checks its state in a loop. Returns when
 /// amount is minted.
-pub async fn fund_wallet(wallet: Arc<Wallet>, amount: u64) -> anyhow::Result<Amount> {
+pub async fn fund_wallet(wallet: Arc<Wallet>, amount: u64) -> Result<Amount> {
     let desired_amount = Amount::from(amount);
     let quote = wallet.mint_quote(desired_amount, None).await?;
 

+ 45 - 5
crates/cdk-integration-tests/tests/integration_tests_pure.rs

@@ -4,14 +4,13 @@ use cdk::amount::SplitTarget;
 use cdk::nuts::nut00::ProofsMethods;
 use cdk::wallet::SendKind;
 use cdk::Amount;
-use cdk_integration_tests::init_pure_tests::{
-    create_and_start_test_mint, create_test_wallet_for_mint, fund_wallet,
-};
+use cdk_integration_tests::init_pure_tests::*;
 
 #[tokio::test]
 async fn test_swap_to_send() -> anyhow::Result<()> {
+    setup_tracing();
     let mint_bob = create_and_start_test_mint().await?;
-    let wallet_alice = create_test_wallet_for_mint(mint_bob.clone()).await?;
+    let wallet_alice = create_test_wallet_arc_for_mint(mint_bob.clone()).await?;
 
     // Alice gets 64 sats
     fund_wallet(wallet_alice.clone(), 64).await?;
@@ -33,7 +32,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()).await?;
+    let wallet_carol = create_test_wallet_arc_for_mint(mint_bob.clone()).await?;
     let received_amount = wallet_carol
         .receive_proofs(token.proofs(), SplitTarget::None, &[], &[])
         .await?;
@@ -43,3 +42,44 @@ async fn test_swap_to_send() -> anyhow::Result<()> {
 
     Ok(())
 }
+
+/// Pure integration tests related to NUT-06 (Mint Information)
+mod nut06 {
+    use std::str::FromStr;
+    use std::sync::Arc;
+
+    use anyhow::Result;
+    use cashu::mint_url::MintUrl;
+    use cashu::Amount;
+    use cdk_integration_tests::init_pure_tests::*;
+
+    #[tokio::test]
+    async fn test_swap_to_send() -> Result<()> {
+        setup_tracing();
+        let mint_bob = create_and_start_test_mint().await?;
+        let wallet_alice_guard = create_test_wallet_arc_mut_for_mint(mint_bob.clone()).await?;
+        let mut wallet_alice = wallet_alice_guard.lock().await;
+
+        // Alice gets 64 sats
+        fund_wallet(Arc::new(wallet_alice.clone()), 64).await?;
+        let balance_alice = wallet_alice.total_balance().await?;
+        assert_eq!(Amount::from(64), balance_alice);
+
+        let initial_mint_url = wallet_alice.mint_url.clone();
+        let mint_info_before = wallet_alice.get_mint_info().await?.unwrap();
+        assert!(mint_info_before
+            .urls
+            .unwrap()
+            .contains(&initial_mint_url.to_string()));
+
+        // Wallet updates mint URL
+        let new_mint_url = MintUrl::from_str("https://new-mint-url")?;
+        wallet_alice.update_mint_url(new_mint_url.clone()).await?;
+
+        // Check balance after mint URL was updated
+        let balance_alice_after = wallet_alice.total_balance().await?;
+        assert_eq!(Amount::from(64), balance_alice_after);
+
+        Ok(())
+    }
+}

+ 6 - 0
crates/cdk/src/mint/builder.rs

@@ -78,6 +78,12 @@ impl MintBuilder {
         self
     }
 
+    /// Set initial mint URLs
+    pub fn with_urls(mut self, urls: Vec<String>) -> Self {
+        self.mint_info.urls = Some(urls);
+        self
+    }
+
     /// Set icon url
     pub fn with_icon_url(mut self, icon_url: String) -> Self {
         self.mint_info.icon_url = Some(icon_url);

+ 5 - 4
crates/cdk/src/wallet/mod.rs

@@ -218,13 +218,14 @@ impl Wallet {
     /// its URL
     #[instrument(skip(self))]
     pub async fn update_mint_url(&mut self, new_mint_url: MintUrl) -> Result<(), Error> {
-        self.mint_url = new_mint_url.clone();
-        // Where the mint_url is in the database it must be updated
+        // Update the mint URL in the wallet DB
         self.localstore
-            .update_mint_url(self.mint_url.clone(), new_mint_url)
+            .update_mint_url(self.mint_url.clone(), new_mint_url.clone())
             .await?;
 
-        self.localstore.remove_mint(self.mint_url.clone()).await?;
+        // Update the mint URL in the wallet struct field
+        self.mint_url = new_mint_url;
+
         Ok(())
     }