Modify WalletDatabase trait to better support db transactions

This commit is contained in:
David Caseria
2024-08-21 08:12:43 -04:00
committed by thesimplekid
parent 9a009ef125
commit d0d7281c77
6 changed files with 335 additions and 261 deletions

View File

@@ -10,7 +10,7 @@ use async_trait::async_trait;
use cdk::cdk_database::WalletDatabase;
use cdk::mint_url::MintUrl;
use cdk::nuts::{
CurrencyUnit, Id, KeySetInfo, Keys, MintInfo, Proofs, PublicKey, SpendingConditions, State,
CurrencyUnit, Id, KeySetInfo, Keys, MintInfo, PublicKey, SpendingConditions, State,
};
use cdk::types::ProofInfo;
use cdk::util::unix_time;
@@ -151,6 +151,47 @@ impl WalletRedbDatabase {
db: Arc::new(Mutex::new(db)),
})
}
async fn update_proof_states(
&self,
ys: Vec<PublicKey>,
state: State,
) -> Result<(), cdk_database::Error> {
let db = self.db.lock().await;
let read_txn = db.begin_read().map_err(Error::from)?;
let table = read_txn.open_table(PROOFS_TABLE).map_err(Error::from)?;
let write_txn = db.begin_write().map_err(Error::from)?;
for y in ys {
let y_slice = y.to_bytes();
let proof = table
.get(y_slice.as_slice())
.map_err(Error::from)?
.ok_or(Error::UnknownY)?;
let mut proof_info =
serde_json::from_str::<ProofInfo>(proof.value()).map_err(Error::from)?;
proof_info.state = state;
{
let mut table = write_txn.open_table(PROOFS_TABLE).map_err(Error::from)?;
table
.insert(
y_slice.as_slice(),
serde_json::to_string(&proof_info)
.map_err(Error::from)?
.as_str(),
)
.map_err(Error::from)?;
}
}
write_txn.commit().map_err(Error::from)?;
Ok(())
}
}
#[async_trait]
@@ -260,7 +301,7 @@ impl WalletDatabase for WalletRedbDatabase {
.collect();
if !updated_proofs.is_empty() {
self.add_proofs(updated_proofs).await?;
self.update_proofs(updated_proofs, vec![]).await?;
}
}
@@ -566,8 +607,12 @@ impl WalletDatabase for WalletRedbDatabase {
Ok(())
}
#[instrument(skip(self, proofs_info))]
async fn add_proofs(&self, proofs_info: Vec<ProofInfo>) -> Result<(), Self::Err> {
#[instrument(skip(self, added, deleted_ys))]
async fn update_proofs(
&self,
added: Vec<ProofInfo>,
deleted_ys: Vec<PublicKey>,
) -> Result<(), Self::Err> {
let db = self.db.lock().await;
let write_txn = db.begin_write().map_err(Error::from)?;
@@ -575,7 +620,7 @@ impl WalletDatabase for WalletRedbDatabase {
{
let mut table = write_txn.open_table(PROOFS_TABLE).map_err(Error::from)?;
for proof_info in proofs_info.iter() {
for proof_info in added.iter() {
table
.insert(
proof_info.y.to_bytes().as_slice(),
@@ -585,12 +630,31 @@ impl WalletDatabase for WalletRedbDatabase {
)
.map_err(Error::from)?;
}
for y in deleted_ys.iter() {
table.remove(y.to_bytes().as_slice()).map_err(Error::from)?;
}
}
write_txn.commit().map_err(Error::from)?;
Ok(())
}
#[instrument(skip(self, ys))]
async fn set_pending_proofs(&self, ys: Vec<PublicKey>) -> Result<(), Self::Err> {
self.update_proof_states(ys, State::Pending).await
}
#[instrument(skip(self, ys))]
async fn reserve_proofs(&self, ys: Vec<PublicKey>) -> Result<(), Self::Err> {
self.update_proof_states(ys, State::Reserved).await
}
#[instrument(skip(self, ys))]
async fn set_unspent_proofs(&self, ys: Vec<PublicKey>) -> Result<(), Self::Err> {
self.update_proof_states(ys, State::Unspent).await
}
#[instrument(skip_all)]
async fn get_proofs(
&self,
@@ -630,61 +694,6 @@ impl WalletDatabase for WalletRedbDatabase {
Ok(proofs)
}
#[instrument(skip(self, proofs))]
async fn remove_proofs(&self, proofs: &Proofs) -> Result<(), Self::Err> {
let db = self.db.lock().await;
let write_txn = db.begin_write().map_err(Error::from)?;
{
let mut table = write_txn.open_table(PROOFS_TABLE).map_err(Error::from)?;
for proof in proofs {
let y_slice = proof.y().map_err(Error::from)?.to_bytes();
table.remove(y_slice.as_slice()).map_err(Error::from)?;
}
}
write_txn.commit().map_err(Error::from)?;
Ok(())
}
#[instrument(skip(self, y))]
async fn set_proof_state(&self, y: PublicKey, state: State) -> Result<(), Self::Err> {
let db = self.db.lock().await;
let read_txn = db.begin_read().map_err(Error::from)?;
let table = read_txn.open_table(PROOFS_TABLE).map_err(Error::from)?;
let y_slice = y.to_bytes();
let proof = table
.get(y_slice.as_slice())
.map_err(Error::from)?
.ok_or(Error::UnknownY)?;
let write_txn = db.begin_write().map_err(Error::from)?;
let mut proof_info =
serde_json::from_str::<ProofInfo>(proof.value()).map_err(Error::from)?;
proof_info.state = state;
{
let mut table = write_txn.open_table(PROOFS_TABLE).map_err(Error::from)?;
table
.insert(
y_slice.as_slice(),
serde_json::to_string(&proof_info)
.map_err(Error::from)?
.as_str(),
)
.map_err(Error::from)?;
}
write_txn.commit().map_err(Error::from)?;
Ok(())
}
#[instrument(skip(self), fields(keyset_id = %keyset_id))]
async fn increment_keyset_counter(&self, keyset_id: &Id, count: u32) -> Result<(), Self::Err> {
let db = self.db.lock().await;

View File

@@ -5,10 +5,10 @@ use std::rc::Rc;
use std::result::Result;
use async_trait::async_trait;
use cdk::cdk_database::WalletDatabase;
use cdk::cdk_database::{self, WalletDatabase};
use cdk::mint_url::MintUrl;
use cdk::nuts::{
CurrencyUnit, Id, KeySetInfo, Keys, MintInfo, Proofs, PublicKey, SpendingConditions, State,
CurrencyUnit, Id, KeySetInfo, Keys, MintInfo, PublicKey, SpendingConditions, State,
};
use cdk::types::ProofInfo;
use cdk::util::unix_time;
@@ -108,6 +108,44 @@ impl WalletRexieDatabase {
db: Rc::new(Mutex::new(rexie)),
})
}
async fn set_proof_states(
&self,
ys: Vec<PublicKey>,
state: State,
) -> Result<(), cdk_database::Error> {
let rexie = self.db.lock().await;
let transaction = rexie
.transaction(&[PROOFS], TransactionMode::ReadWrite)
.map_err(Error::from)?;
let proofs_store = transaction.store(PROOFS).map_err(Error::from)?;
for y in ys {
let y = serde_wasm_bindgen::to_value(&y).map_err(Error::from)?;
let mut proof: ProofInfo = proofs_store
.get(y.clone())
.await
.map_err(Error::from)?
.and_then(|p| serde_wasm_bindgen::from_value(p).ok())
.ok_or(Error::NotFound)?;
proof.state = state;
let proof = serde_wasm_bindgen::to_value(&proof).map_err(Error::from)?;
proofs_store
.put(&proof, Some(&y))
.await
.map_err(Error::from)?;
}
transaction.done().await.map_err(Error::from)?;
Ok(())
}
}
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
@@ -224,7 +262,7 @@ impl WalletDatabase for WalletRexieDatabase {
.collect();
if !updated_proofs.is_empty() {
self.add_proofs(updated_proofs).await?;
self.update_proofs(updated_proofs, vec![]).await?;
}
// Update mint quotes
@@ -567,7 +605,11 @@ impl WalletDatabase for WalletRexieDatabase {
Ok(())
}
async fn add_proofs(&self, proofs: Vec<ProofInfo>) -> Result<(), Self::Err> {
async fn update_proofs(
&self,
added: Vec<ProofInfo>,
removed_ys: Vec<PublicKey>,
) -> Result<(), Self::Err> {
let rexie = self.db.lock().await;
let transaction = rexie
@@ -576,9 +618,8 @@ impl WalletDatabase for WalletRexieDatabase {
let proofs_store = transaction.store(PROOFS).map_err(Error::from)?;
for proof in proofs {
let y = proof.y;
let y = serde_wasm_bindgen::to_value(&y).map_err(Error::from)?;
for proof in added {
let y = serde_wasm_bindgen::to_value(&proof.y).map_err(Error::from)?;
let proof = serde_wasm_bindgen::to_value(&proof).map_err(Error::from)?;
proofs_store
@@ -587,11 +628,29 @@ impl WalletDatabase for WalletRexieDatabase {
.map_err(Error::from)?;
}
for y in removed_ys {
let y = serde_wasm_bindgen::to_value(&y).map_err(Error::from)?;
proofs_store.delete(y).await.map_err(Error::from)?;
}
transaction.done().await.map_err(Error::from)?;
Ok(())
}
async fn set_pending_proofs(&self, ys: Vec<PublicKey>) -> Result<(), Self::Err> {
self.set_proof_states(ys, State::Pending).await
}
async fn reserve_proofs(&self, ys: Vec<PublicKey>) -> Result<(), Self::Err> {
self.set_proof_states(ys, State::Reserved).await
}
async fn set_unspent_proofs(&self, ys: Vec<PublicKey>) -> Result<(), Self::Err> {
self.set_proof_states(ys, State::Unspent).await
}
async fn get_proofs(
&self,
mint_url: Option<MintUrl>,
@@ -638,58 +697,6 @@ impl WalletDatabase for WalletRexieDatabase {
Ok(proofs)
}
async fn remove_proofs(&self, proofs: &Proofs) -> Result<(), Self::Err> {
let rexie = self.db.lock().await;
let transaction = rexie
.transaction(&[PROOFS], TransactionMode::ReadWrite)
.map_err(Error::from)?;
let proofs_store = transaction.store(PROOFS).map_err(Error::from)?;
for proof in proofs {
let y = serde_wasm_bindgen::to_value(&proof.y()?).map_err(Error::from)?;
proofs_store.delete(y).await.map_err(Error::from)?;
}
transaction.done().await.map_err(Error::from)?;
Ok(())
}
async fn set_proof_state(&self, y: PublicKey, state: State) -> Result<(), Self::Err> {
let rexie = self.db.lock().await;
let transaction = rexie
.transaction(&[PROOFS], TransactionMode::ReadWrite)
.map_err(Error::from)?;
let proofs_store = transaction.store(PROOFS).map_err(Error::from)?;
let y = serde_wasm_bindgen::to_value(&y).map_err(Error::from)?;
let mut proof: ProofInfo = proofs_store
.get(y.clone())
.await
.map_err(Error::from)?
.and_then(|p| serde_wasm_bindgen::from_value(p).ok())
.ok_or(Error::NotFound)?;
proof.state = state;
let proof = serde_wasm_bindgen::to_value(&proof).map_err(Error::from)?;
proofs_store
.put(&proof, Some(&y))
.await
.map_err(Error::from)?;
transaction.done().await.map_err(Error::from)?;
Ok(())
}
async fn increment_keyset_counter(&self, keyset_id: &Id, count: u32) -> Result<(), Self::Err> {
let rexie = self.db.lock().await;

View File

@@ -9,8 +9,8 @@ use cdk::amount::Amount;
use cdk::cdk_database::{self, WalletDatabase};
use cdk::mint_url::MintUrl;
use cdk::nuts::{
CurrencyUnit, Id, KeySetInfo, Keys, MeltQuoteState, MintInfo, MintQuoteState, Proof, Proofs,
PublicKey, SpendingConditions, State,
CurrencyUnit, Id, KeySetInfo, Keys, MeltQuoteState, MintInfo, MintQuoteState, Proof, PublicKey,
SpendingConditions, State,
};
use cdk::secret::Secret;
use cdk::types::ProofInfo;
@@ -53,6 +53,23 @@ impl WalletSqliteDatabase {
.await
.expect("Could not run migrations");
}
async fn set_proof_state(&self, y: PublicKey, state: State) -> Result<(), cdk_database::Error> {
sqlx::query(
r#"
UPDATE proof
SET state=?
WHERE y IS ?;
"#,
)
.bind(state.to_string())
.bind(y.to_bytes().to_vec())
.execute(&self.pool)
.await
.map_err(Error::from)?;
Ok(())
}
}
#[async_trait]
@@ -513,14 +530,17 @@ WHERE id=?
Ok(())
}
#[instrument(skip_all)]
async fn add_proofs(&self, proof_info: Vec<ProofInfo>) -> Result<(), Self::Err> {
for proof in proof_info {
async fn update_proofs(
&self,
added: Vec<ProofInfo>,
removed_ys: Vec<PublicKey>,
) -> Result<(), Self::Err> {
for proof in added {
sqlx::query(
r#"
INSERT OR REPLACE INTO proof
(y, mint_url, state, spending_condition, unit, amount, keyset_id, secret, c, witness)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
INSERT OR REPLACE INTO proof
(y, mint_url, state, spending_condition, unit, amount, keyset_id, secret, c, witness)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
"#,
)
.bind(proof.y.to_bytes().to_vec())
@@ -547,6 +567,44 @@ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
.map_err(Error::from)?;
}
// TODO: Generate a IN clause
for y in removed_ys {
sqlx::query(
r#"
DELETE FROM proof
WHERE y = ?
"#,
)
.bind(y.to_bytes().to_vec())
.execute(&self.pool)
.await
.map_err(Error::from)?;
}
Ok(())
}
async fn set_pending_proofs(&self, ys: Vec<PublicKey>) -> Result<(), Self::Err> {
for y in ys {
self.set_proof_state(y, State::Pending).await?;
}
Ok(())
}
async fn reserve_proofs(&self, ys: Vec<PublicKey>) -> Result<(), Self::Err> {
for y in ys {
self.set_proof_state(y, State::Reserved).await?;
}
Ok(())
}
async fn set_unspent_proofs(&self, ys: Vec<PublicKey>) -> Result<(), Self::Err> {
for y in ys {
self.set_proof_state(y, State::Unspent).await?;
}
Ok(())
}
@@ -602,43 +660,6 @@ FROM proof;
}
}
#[instrument(skip_all)]
async fn remove_proofs(&self, proofs: &Proofs) -> Result<(), Self::Err> {
// TODO: Generate a IN clause
for proof in proofs {
sqlx::query(
r#"
DELETE FROM proof
WHERE y = ?
"#,
)
.bind(proof.y()?.to_bytes().to_vec())
.execute(&self.pool)
.await
.map_err(Error::from)?;
}
Ok(())
}
#[instrument(skip(self, y))]
async fn set_proof_state(&self, y: PublicKey, state: State) -> Result<(), Self::Err> {
sqlx::query(
r#"
UPDATE proof
SET state=?
WHERE y IS ?;
"#,
)
.bind(state.to_string())
.bind(y.to_bytes().to_vec())
.execute(&self.pool)
.await
.map_err(Error::from)?;
Ok(())
}
#[instrument(skip(self), fields(keyset_id = %keyset_id))]
async fn increment_keyset_counter(&self, keyset_id: &Id, count: u32) -> Result<(), Self::Err> {
sqlx::query(

View File

@@ -17,9 +17,9 @@ use crate::mint::MintQuote as MintMintQuote;
#[cfg(feature = "wallet")]
use crate::mint_url::MintUrl;
#[cfg(feature = "mint")]
use crate::nuts::{BlindSignature, MeltQuoteState, MintQuoteState, Proof};
use crate::nuts::{BlindSignature, MeltQuoteState, MintQuoteState, Proof, Proofs};
#[cfg(any(feature = "wallet", feature = "mint"))]
use crate::nuts::{CurrencyUnit, Id, Proofs, PublicKey, State};
use crate::nuts::{CurrencyUnit, Id, PublicKey, State};
#[cfg(feature = "wallet")]
use crate::nuts::{KeySetInfo, Keys, MintInfo, SpendingConditions};
#[cfg(feature = "wallet")]
@@ -124,8 +124,18 @@ pub trait WalletDatabase: Debug {
/// Remove [`Keys`] from storage
async fn remove_keys(&self, id: &Id) -> Result<(), Self::Err>;
/// Add [`Proofs`] to storage
async fn add_proofs(&self, proof_info: Vec<ProofInfo>) -> Result<(), Self::Err>;
/// Update the proofs in storage by adding new proofs or removing proofs by their Y value.
async fn update_proofs(
&self,
added: Vec<ProofInfo>,
removed_ys: Vec<PublicKey>,
) -> Result<(), Self::Err>;
/// Set proofs as pending in storage. Proofs are identified by their Y value.
async fn set_pending_proofs(&self, ys: Vec<PublicKey>) -> Result<(), Self::Err>;
/// Reserve proofs in storage. Proofs are identified by their Y value.
async fn reserve_proofs(&self, ys: Vec<PublicKey>) -> Result<(), Self::Err>;
/// Set proofs as unspent in storage. Proofs are identified by their Y value.
async fn set_unspent_proofs(&self, ys: Vec<PublicKey>) -> Result<(), Self::Err>;
/// Get proofs from storage
async fn get_proofs(
&self,
@@ -134,11 +144,6 @@ pub trait WalletDatabase: Debug {
state: Option<Vec<State>>,
spending_conditions: Option<Vec<SpendingConditions>>,
) -> Result<Vec<ProofInfo>, Self::Err>;
/// Remove proofs from storage
async fn remove_proofs(&self, proofs: &Proofs) -> Result<(), Self::Err>;
/// Set Proof state
async fn set_proof_state(&self, y: PublicKey, state: State) -> Result<(), Self::Err>;
/// Increment Keyset counter
async fn increment_keyset_counter(&self, keyset_id: &Id, count: u32) -> Result<(), Self::Err>;

View File

@@ -10,7 +10,7 @@ use super::WalletDatabase;
use crate::cdk_database::Error;
use crate::mint_url::MintUrl;
use crate::nuts::{
CurrencyUnit, Id, KeySetInfo, Keys, MintInfo, Proofs, PublicKey, SpendingConditions, State,
CurrencyUnit, Id, KeySetInfo, Keys, MintInfo, PublicKey, SpendingConditions, State,
};
use crate::types::ProofInfo;
use crate::util::unix_time;
@@ -109,7 +109,7 @@ impl WalletDatabase for WalletMemoryDatabase {
})
.collect();
self.add_proofs(updated_proofs).await?;
self.update_proofs(updated_proofs, vec![]).await?;
}
// Update mint quotes
@@ -238,13 +238,57 @@ impl WalletDatabase for WalletMemoryDatabase {
Ok(())
}
async fn add_proofs(&self, proofs_info: Vec<ProofInfo>) -> Result<(), Error> {
async fn update_proofs(
&self,
added: Vec<ProofInfo>,
removed_ys: Vec<PublicKey>,
) -> Result<(), Error> {
let mut all_proofs = self.proofs.write().await;
for proof_info in proofs_info.into_iter() {
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<PublicKey>) -> 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<PublicKey>) -> 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<PublicKey>) -> 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(())
}
@@ -272,34 +316,6 @@ impl WalletDatabase for WalletMemoryDatabase {
Ok(proofs)
}
async fn remove_proofs(&self, proofs: &Proofs) -> Result<(), Error> {
let mut mint_proofs = self.proofs.write().await;
for proof in proofs {
mint_proofs.remove(&proof.y().map_err(Error::from)?);
}
Ok(())
}
async fn set_proof_state(&self, y: PublicKey, state: State) -> Result<(), Self::Err> {
let mint_proofs = self.proofs.read().await;
let mint_proof = mint_proofs.get(&y).cloned();
drop(mint_proofs);
let mut mint_proofs = self.proofs.write().await;
if let Some(proof_info) = mint_proof {
let mut proof_info = proof_info.clone();
proof_info.state = state;
mint_proofs.insert(y, proof_info);
}
Ok(())
}
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);

View File

@@ -259,11 +259,7 @@ impl Wallet {
/// Return proofs to unspent allowing them to be selected and spent
#[instrument(skip(self))]
pub async fn unreserve_proofs(&self, ys: Vec<PublicKey>) -> Result<(), Error> {
for y in ys {
self.localstore.set_proof_state(y, State::Unspent).await?;
}
Ok(())
Ok(self.localstore.set_unspent_proofs(ys).await?)
}
/// Qeury mint for current mint information
@@ -461,7 +457,10 @@ impl Wallet {
let amount = pending_proofs.iter().map(|p| p.proof.amount).sum();
self.localstore
.remove_proofs(&non_pending_proofs.into_iter().map(|p| p.proof).collect())
.update_proofs(
vec![],
non_pending_proofs.into_iter().map(|p| p.y).collect(),
)
.await?;
balance += amount;
@@ -701,7 +700,7 @@ impl Wallet {
.collect::<Result<Vec<ProofInfo>, _>>()?;
// Add new proofs to store
self.localstore.add_proofs(proofs).await?;
self.localstore.update_proofs(proofs, vec![]).await?;
Ok(minted_amount)
}
@@ -776,12 +775,8 @@ impl Wallet {
// Desired amount is either amount passed or value of all proof
let proofs_total: Amount = proofs.iter().map(|p| p.amount).sum();
for proof in proofs.iter() {
self.localstore
.set_proof_state(proof.y()?, State::Pending)
.await
.ok();
}
let ys: Vec<PublicKey> = proofs.iter().map(|p| p.y()).collect::<Result<_, _>>()?;
self.localstore.set_pending_proofs(ys).await?;
let fee = self.get_proofs_fee(&proofs).await?;
@@ -932,9 +927,9 @@ impl Wallet {
.increment_keyset_counter(&active_keyset_id, pre_swap.derived_secret_count)
.await?;
let mut added_proofs = Vec::new();
let change_proofs;
let send_proofs;
match amount {
Some(amount) => {
let (proofs_with_condition, proofs_without_condition): (Proofs, Proofs) =
@@ -982,8 +977,7 @@ impl Wallet {
.into_iter()
.map(|proof| ProofInfo::new(proof, mint_url.clone(), State::Reserved, *unit))
.collect::<Result<Vec<ProofInfo>, _>>()?;
self.localstore.add_proofs(send_proofs_info).await?;
added_proofs = send_proofs_info;
change_proofs = proofs_to_keep;
send_proofs = Some(proofs_to_send);
@@ -998,12 +992,17 @@ impl Wallet {
.into_iter()
.map(|proof| ProofInfo::new(proof, mint_url.clone(), State::Unspent, *unit))
.collect::<Result<Vec<ProofInfo>, _>>()?;
self.localstore.add_proofs(keep_proofs).await?;
added_proofs.extend(keep_proofs);
// Remove spent proofs used as inputs
self.localstore.remove_proofs(&input_proofs).await?;
let deleted_ys = input_proofs
.into_iter()
.map(|proof| proof.y())
.collect::<Result<Vec<PublicKey>, _>>()?;
self.localstore
.update_proofs(added_proofs, deleted_ys)
.await?;
Ok(send_proofs)
}
@@ -1053,11 +1052,11 @@ impl Wallet {
/// Send specific proofs
#[instrument(skip(self))]
pub async fn send_proofs(&self, memo: Option<String>, proofs: Proofs) -> Result<Token, Error> {
for proof in proofs.iter() {
self.localstore
.set_proof_state(proof.y()?, State::Reserved)
.await?;
}
let ys = proofs
.iter()
.map(|p| p.y())
.collect::<Result<Vec<PublicKey>, _>>()?;
self.localstore.reserve_proofs(ys).await?;
Ok(Token::new(
self.mint_url.clone(),
@@ -1358,11 +1357,11 @@ impl Wallet {
return Err(Error::QuoteUnknown);
};
for proof in proofs.iter() {
self.localstore
.set_proof_state(proof.y()?, State::Pending)
.await?;
}
let ys = proofs
.iter()
.map(|p| p.y())
.collect::<Result<Vec<PublicKey>, _>>()?;
self.localstore.set_pending_proofs(ys).await?;
let active_keyset_id = self.get_active_mint_keyset().await?.id;
@@ -1429,7 +1428,8 @@ impl Wallet {
change: change_proofs.clone(),
};
if let Some(change_proofs) = change_proofs {
let change_proof_infos = match change_proofs {
Some(change_proofs) => {
tracing::debug!(
"Change amount returned from melt: {}",
change_proofs.iter().map(|p| p.amount).sum::<Amount>()
@@ -1440,7 +1440,7 @@ impl Wallet {
.increment_keyset_counter(&active_keyset_id, change_proofs.len() as u32)
.await?;
let change_proofs_info = change_proofs
change_proofs
.into_iter()
.map(|proof| {
ProofInfo::new(
@@ -1450,14 +1450,20 @@ impl Wallet {
quote_info.unit,
)
})
.collect::<Result<Vec<ProofInfo>, _>>()?;
self.localstore.add_proofs(change_proofs_info).await?;
.collect::<Result<Vec<ProofInfo>, _>>()?
}
None => Vec::new(),
};
self.localstore.remove_melt_quote(&quote_info.id).await?;
self.localstore.remove_proofs(&proofs).await?;
let deleted_ys = proofs
.iter()
.map(|p| p.y())
.collect::<Result<Vec<PublicKey>, _>>()?;
self.localstore
.update_proofs(change_proof_infos, deleted_ys)
.await?;
Ok(melted)
}
@@ -1716,6 +1722,14 @@ impl Wallet {
}
}
// Since the proofs are unknown they need to be added to the database
let proofs_info = proofs
.clone()
.into_iter()
.map(|p| ProofInfo::new(p, self.mint_url.clone(), State::Pending, self.unit))
.collect::<Result<Vec<ProofInfo>, _>>()?;
self.localstore.update_proofs(proofs_info, vec![]).await?;
let mut pre_swap = self
.create_swap(None, amount_split_target, proofs, None, false)
.await?;
@@ -1755,7 +1769,7 @@ impl Wallet {
.into_iter()
.map(|proof| ProofInfo::new(proof, mint.clone(), State::Unspent, self.unit))
.collect::<Result<Vec<ProofInfo>, _>>()?;
self.localstore.add_proofs(proofs).await?;
self.localstore.update_proofs(proofs, vec![]).await?;
}
Ok(total_amount)
@@ -1919,7 +1933,9 @@ impl Wallet {
})
.collect::<Result<Vec<ProofInfo>, _>>()?;
self.localstore.add_proofs(unspent_proofs).await?;
self.localstore
.update_proofs(unspent_proofs, vec![])
.await?;
empty_batch = 0;
start_counter += 100;