feat: check pending proofs

This commit is contained in:
thesimplekid
2024-05-18 23:04:12 +01:00
parent 5203182b38
commit 34e2e15378
3 changed files with 80 additions and 1 deletions

View File

@@ -51,6 +51,26 @@ impl JsWallet {
Ok(self.inner.total_balance().await.map_err(into_err)?.into())
}
#[wasm_bindgen(js_name = totalPendingBalance)]
pub async fn total_pending_balance(&self) -> Result<JsAmount> {
Ok(self
.inner
.total_pending_balance()
.await
.map_err(into_err)?
.into())
}
#[wasm_bindgen(js_name = checkAllPendingProofs)]
pub async fn check_all_pending_proofs(&self) -> Result<JsAmount> {
Ok(self
.inner
.check_all_pending_proofs
.await
.map_err(into_err)?
.into())
}
#[wasm_bindgen(js_name = mintBalances)]
pub async fn mint_balances(&self) -> Result<JsValue> {
let mint_balances = self.inner.mint_balances().await.map_err(into_err)?;

View File

@@ -16,7 +16,7 @@ use url::Url;
use super::nut10;
use super::nut11::SpendingConditions;
use crate::dhke::blind_message;
use crate::dhke::{blind_message, hash_to_curve};
use crate::nuts::nut01::{PublicKey, SecretKey};
use crate::nuts::nut11::{serde_p2pk_witness, P2PKWitness};
use crate::nuts::nut12::BlindSignatureDleq;
@@ -200,6 +200,10 @@ impl Proof {
dleq: None,
}
}
pub fn y(&self) -> Result<PublicKey, Error> {
Ok(hash_to_curve(self.secret.as_bytes())?)
}
}
impl Hash for Proof {

View File

@@ -129,6 +129,23 @@ impl Wallet {
Ok(balance)
}
/// Total Balance of wallet
#[instrument(skip(self))]
pub async fn total_pending_balance(&self) -> Result<Amount, Error> {
let mints = self.localstore.get_mints().await?;
let mut balance = Amount::ZERO;
for (mint, _) in mints {
if let Some(proofs) = self.localstore.get_pending_proofs(mint.clone()).await? {
let amount = proofs.iter().map(|p| p.amount).sum();
balance += amount;
}
}
Ok(balance)
}
#[instrument(skip(self))]
pub async fn mint_balances(&self) -> Result<HashMap<UncheckedUrl, Amount>, Error> {
let mints = self.localstore.get_mints().await?;
@@ -292,6 +309,44 @@ impl Wallet {
Ok(spendable.states)
}
/// Checks pending proofs for spent status
#[instrument(skip(self))]
pub async fn check_all_pending_proofs(&self) -> Result<Amount, Error> {
let mints = self.localstore.get_mints().await?;
let mut balance = Amount::ZERO;
for (mint, _) in mints {
if let Some(proofs) = self.localstore.get_pending_proofs(mint.clone()).await? {
let states = self
.check_proofs_spent(mint.clone(), proofs.clone())
.await?;
// Both `State::Pending` and `State::Unspent` should be included in the pending table.
// This is because a proof that has been crated to send will be stored in the pending table
// in order to avoid accidentally double spending but to allow it to be explicitly reclaimed
let pending_states: HashSet<PublicKey> = states
.into_iter()
.filter(|s| s.state.ne(&State::Spent))
.map(|s| s.y)
.collect();
let (pending_proofs, non_pending_proofs): (Proofs, Proofs) = proofs
.into_iter()
.partition(|p| p.y().map(|y| pending_states.contains(&y)).unwrap_or(false));
let amount = pending_proofs.iter().map(|p| p.amount).sum();
self.localstore
.remove_pending_proofs(mint, &non_pending_proofs)
.await?;
balance += amount;
}
}
Ok(balance)
}
/// Mint Quote
#[instrument(skip(self), fields(mint_url = %mint_url))]
pub async fn mint_quote(