|
|
@@ -1,10 +1,11 @@
|
|
|
+use std::collections::HashMap;
|
|
|
use std::future::Future;
|
|
|
|
|
|
use cdk_common::wallet::TransactionId;
|
|
|
use cdk_common::{CheckStateRequest, ProofsMethods};
|
|
|
use tracing::instrument;
|
|
|
|
|
|
-use crate::nuts::{Proofs, State};
|
|
|
+use crate::nuts::Proofs;
|
|
|
use crate::{Error, Wallet};
|
|
|
|
|
|
#[cfg(not(target_arch = "wasm32"))]
|
|
|
@@ -34,37 +35,38 @@ impl<T: ?Sized> MaybeSend for T {}
|
|
|
const BATCH_PROOF_SIZE: usize = 100;
|
|
|
|
|
|
impl Wallet {
|
|
|
- /// Reclaim unspent proofs from the local database
|
|
|
- ///
|
|
|
- /// Checks the stats of [`Proofs`] updating in their status in the wallet's database if unspent
|
|
|
- ///
|
|
|
+ /// Synchronizes the states with the mint
|
|
|
#[instrument(skip(self, proofs))]
|
|
|
- pub async fn update_proofs_state(&self, proofs: Proofs) -> Result<(), Error> {
|
|
|
+ pub async fn sync_proofs_state(&self, proofs: Proofs) -> Result<(), Error> {
|
|
|
let proof_ys = proofs.ys()?;
|
|
|
|
|
|
let transaction_id = TransactionId::new(proof_ys.clone());
|
|
|
|
|
|
- let spendable = self
|
|
|
+ let statuses = self
|
|
|
.client
|
|
|
.post_check_state(CheckStateRequest { ys: proof_ys })
|
|
|
.await?
|
|
|
.states;
|
|
|
|
|
|
- let unspent: Proofs = proofs
|
|
|
+ for (state, unspent) in proofs
|
|
|
.into_iter()
|
|
|
- .zip(spendable)
|
|
|
- .filter_map(|(p, s)| (s.state == State::Unspent).then_some(p))
|
|
|
- .collect();
|
|
|
-
|
|
|
- self.localstore
|
|
|
- .update_proofs_state(
|
|
|
- unspent
|
|
|
- .iter()
|
|
|
- .map(|x| x.y())
|
|
|
- .collect::<Result<Vec<_>, _>>()?,
|
|
|
- State::Unspent,
|
|
|
- )
|
|
|
- .await?;
|
|
|
+ .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?;
|
|
|
+ }
|
|
|
|
|
|
match self.localstore.remove_transaction(transaction_id).await {
|
|
|
Ok(_) => (),
|
|
|
@@ -77,8 +79,7 @@ impl Wallet {
|
|
|
}
|
|
|
|
|
|
/// 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,
|
|
|
@@ -93,6 +94,11 @@ impl Wallet {
|
|
|
match f.await {
|
|
|
Ok(r) => Ok(r),
|
|
|
Err(err) => {
|
|
|
+ println!(
|
|
|
+ "Http operation failed with \"{}\", revering {} proofs states to UNSPENT",
|
|
|
+ err,
|
|
|
+ inputs.len()
|
|
|
+ );
|
|
|
tracing::error!(
|
|
|
"Http operation failed with \"{}\", revering {} proofs states to UNSPENT",
|
|
|
err,
|
|
|
@@ -115,27 +121,11 @@ impl Wallet {
|
|
|
inputs.len()
|
|
|
);
|
|
|
for proofs in inputs.chunks(BATCH_PROOF_SIZE) {
|
|
|
- if let Err(inner_err) =
|
|
|
- self.update_proofs_state(proofs.to_owned()).await
|
|
|
- {
|
|
|
- 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
|