Explorar el Código

Merge branch 'main' into feature/wallet-key-manager

C hace 2 semanas
padre
commit
a3dcb0d697
Se han modificado 2 ficheros con 50 adiciones y 61 borrados
  1. 5 36
      crates/cdk-integration-tests/tests/fake_wallet.rs
  2. 45 25
      crates/cdk/src/wallet/reclaim.rs

+ 5 - 36
crates/cdk-integration-tests/tests/fake_wallet.rs

@@ -54,8 +54,6 @@ async fn test_fake_tokens_pending() {
         .expect("payment")
         .expect("no error");
 
-    let old_balance = wallet.total_balance().await.expect("balance");
-
     let fake_description = FakeInvoiceDescription {
         pay_invoice_state: MeltQuoteState::Pending,
         check_payment_state: MeltQuoteState::Pending,
@@ -72,12 +70,7 @@ async fn test_fake_tokens_pending() {
     assert!(melt.is_err());
 
     // melt failed, but there is new code to reclaim unspent proofs
-    assert_eq!(
-        old_balance,
-        wallet.total_balance().await.expect("new balance")
-    );
-
-    assert!(wallet
+    assert!(!wallet
         .localstore
         .get_proofs(None, None, Some(vec![State::Pending]), None)
         .await
@@ -139,7 +132,7 @@ async fn test_fake_melt_payment_fail() {
     assert!(melt.is_err());
 
     let wallet_bal = wallet.total_balance().await.unwrap();
-    assert_eq!(wallet_bal, 100.into());
+    assert_eq!(wallet_bal, 98.into());
 }
 
 /// Tests that when both the pay_invoice and check_invoice both fail,
@@ -165,8 +158,6 @@ async fn test_fake_melt_payment_fail_and_check() {
         .expect("payment")
         .expect("no error");
 
-    let old_balance = wallet.total_balance().await.expect("balance");
-
     let fake_description = FakeInvoiceDescription {
         pay_invoice_state: MeltQuoteState::Unknown,
         check_payment_state: MeltQuoteState::Unknown,
@@ -182,13 +173,7 @@ async fn test_fake_melt_payment_fail_and_check() {
     let melt = wallet.melt(&melt_quote.id).await;
     assert!(melt.is_err());
 
-    // melt failed, but there is new code to reclaim unspent proofs
-    assert_eq!(
-        old_balance,
-        wallet.total_balance().await.expect("new balance")
-    );
-
-    assert!(wallet
+    assert!(!wallet
         .localstore
         .get_proofs(None, None, Some(vec![State::Pending]), None)
         .await
@@ -226,8 +211,6 @@ async fn test_fake_melt_payment_return_fail_status() {
         check_err: false,
     };
 
-    let old_balance = wallet.total_balance().await.expect("balance");
-
     let invoice = create_fake_invoice(7000, serde_json::to_string(&fake_description).unwrap());
 
     let melt_quote = wallet.melt_quote(invoice.to_string(), None).await.unwrap();
@@ -261,14 +244,9 @@ async fn test_fake_melt_payment_return_fail_status() {
     let melt = wallet.melt(&melt_quote.id).await;
     assert!(melt.is_err());
 
-    assert_eq!(
-        old_balance,
-        wallet.total_balance().await.expect("new balance")
-    );
-
     wallet.check_all_pending_proofs().await.unwrap();
 
-    assert!(wallet
+    assert!(!wallet
         .localstore
         .get_proofs(None, None, Some(vec![State::Pending]), None)
         .await
@@ -299,8 +277,6 @@ async fn test_fake_melt_payment_error_unknown() {
         .expect("payment")
         .expect("no error");
 
-    let old_balance = wallet.total_balance().await.expect("balance");
-
     let fake_description = FakeInvoiceDescription {
         pay_invoice_state: MeltQuoteState::Failed,
         check_payment_state: MeltQuoteState::Unknown,
@@ -331,14 +307,7 @@ async fn test_fake_melt_payment_error_unknown() {
     let melt = wallet.melt(&melt_quote.id).await;
     assert!(melt.is_err());
 
-    wallet.check_all_pending_proofs().await.unwrap();
-
-    assert_eq!(
-        old_balance,
-        wallet.total_balance().await.expect("new balance")
-    );
-
-    assert!(wallet
+    assert!(!wallet
         .localstore
         .get_proofs(None, None, Some(vec![State::Pending]), None)
         .await

+ 45 - 25
crates/cdk/src/wallet/reclaim.rs

@@ -1,6 +1,10 @@
+use std::collections::HashMap;
 use std::future::Future;
 
-use crate::nuts::{Proofs, State};
+use cdk_common::{CheckStateRequest, ProofsMethods};
+use tracing::instrument;
+
+use crate::nuts::Proofs;
 use crate::{Error, Wallet};
 
 #[cfg(not(target_arch = "wasm32"))]
@@ -30,9 +34,42 @@ impl<T: ?Sized> MaybeSend for T {}
 const BATCH_PROOF_SIZE: usize = 100;
 
 impl Wallet {
+    /// Synchronizes the states with the mint
+    #[instrument(skip(self, proofs))]
+    pub async fn sync_proofs_state(&self, proofs: Proofs) -> Result<(), Error> {
+        let proof_ys = proofs.ys()?;
+
+        let statuses = self
+            .client
+            .post_check_state(CheckStateRequest { ys: proof_ys })
+            .await?
+            .states;
+
+        for (state, unspent) in proofs
+            .into_iter()
+            .zip(statuses)
+            .map(|(p, s)| (s.state, p))
+            .fold(HashMap::<_, Vec<_>>::new(), |mut acc, (cat, item)| {
+                acc.entry(cat).or_default().push(item);
+                acc
+            })
+        {
+            self.localstore
+                .update_proofs_state(
+                    unspent
+                        .iter()
+                        .map(|x| x.y())
+                        .collect::<Result<Vec<_>, _>>()?,
+                    state,
+                )
+                .await?;
+        }
+
+        Ok(())
+    }
+
     /// Perform an async task, which is assumed to be a foreign mint call that can fail. If fails,
-    /// the proofs used in the request are set as unspent, then they are swapped, as they are
-    /// believed to be already shown to the mint
+    /// the proofs used in the request are synchronize with the mint and update it locally
     #[inline(always)]
     pub(crate) fn try_proof_operation_or_reclaim<'a, F, R>(
         &'a self,
@@ -69,28 +106,11 @@ impl Wallet {
                             inputs.len()
                         );
                         for proofs in inputs.chunks(BATCH_PROOF_SIZE) {
-                            if let Err(inner_err) = self.reclaim_unspent(proofs.to_owned()).await {
-                                println!(
-                                    "Failed to swap exposed proofs ({}), updating local database instead", inner_err
-                                );
-                                tracing::warn!(
-                                    "Failed to swap exposed proofs ({}), updating local database instead", inner_err
-                                );
-
-                                let _ = self
-                                    .localstore
-                                    .update_proofs_state(
-                                        proofs
-                                            .iter()
-                                            .map(|x| x.y())
-                                            .collect::<Result<Vec<_>, _>>()?,
-                                        State::Unspent,
-                                    )
-                                    .await
-                                    .inspect_err(|err| {
-                                        tracing::error!("Failed err update_proofs_state {}", err)
-                                    });
-                            }
+                            let _ = self.sync_proofs_state(proofs.to_owned()).await.inspect_err(
+                                |err| {
+                                    tracing::warn!("Failed to swap exposed proofs ({})", err);
+                                },
+                            );
                         }
 
                         self.in_error_swap_reverted_proofs