mirror of
https://github.com/aljazceru/cdk.git
synced 2025-12-20 22:24:54 +01:00
Modify WalletDatabase trait to better support db transactions
This commit is contained in:
committed by
thesimplekid
parent
9a009ef125
commit
d0d7281c77
@@ -10,7 +10,7 @@ use async_trait::async_trait;
|
|||||||
use cdk::cdk_database::WalletDatabase;
|
use cdk::cdk_database::WalletDatabase;
|
||||||
use cdk::mint_url::MintUrl;
|
use cdk::mint_url::MintUrl;
|
||||||
use cdk::nuts::{
|
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::types::ProofInfo;
|
||||||
use cdk::util::unix_time;
|
use cdk::util::unix_time;
|
||||||
@@ -151,6 +151,47 @@ impl WalletRedbDatabase {
|
|||||||
db: Arc::new(Mutex::new(db)),
|
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]
|
#[async_trait]
|
||||||
@@ -260,7 +301,7 @@ impl WalletDatabase for WalletRedbDatabase {
|
|||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
if !updated_proofs.is_empty() {
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(skip(self, proofs_info))]
|
#[instrument(skip(self, added, deleted_ys))]
|
||||||
async fn add_proofs(&self, proofs_info: Vec<ProofInfo>) -> Result<(), Self::Err> {
|
async fn update_proofs(
|
||||||
|
&self,
|
||||||
|
added: Vec<ProofInfo>,
|
||||||
|
deleted_ys: Vec<PublicKey>,
|
||||||
|
) -> Result<(), Self::Err> {
|
||||||
let db = self.db.lock().await;
|
let db = self.db.lock().await;
|
||||||
|
|
||||||
let write_txn = db.begin_write().map_err(Error::from)?;
|
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)?;
|
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
|
table
|
||||||
.insert(
|
.insert(
|
||||||
proof_info.y.to_bytes().as_slice(),
|
proof_info.y.to_bytes().as_slice(),
|
||||||
@@ -585,12 +630,31 @@ impl WalletDatabase for WalletRedbDatabase {
|
|||||||
)
|
)
|
||||||
.map_err(Error::from)?;
|
.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)?;
|
write_txn.commit().map_err(Error::from)?;
|
||||||
|
|
||||||
Ok(())
|
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)]
|
#[instrument(skip_all)]
|
||||||
async fn get_proofs(
|
async fn get_proofs(
|
||||||
&self,
|
&self,
|
||||||
@@ -630,61 +694,6 @@ impl WalletDatabase for WalletRedbDatabase {
|
|||||||
Ok(proofs)
|
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))]
|
#[instrument(skip(self), fields(keyset_id = %keyset_id))]
|
||||||
async fn increment_keyset_counter(&self, keyset_id: &Id, count: u32) -> Result<(), Self::Err> {
|
async fn increment_keyset_counter(&self, keyset_id: &Id, count: u32) -> Result<(), Self::Err> {
|
||||||
let db = self.db.lock().await;
|
let db = self.db.lock().await;
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ use std::rc::Rc;
|
|||||||
use std::result::Result;
|
use std::result::Result;
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use cdk::cdk_database::WalletDatabase;
|
use cdk::cdk_database::{self, WalletDatabase};
|
||||||
use cdk::mint_url::MintUrl;
|
use cdk::mint_url::MintUrl;
|
||||||
use cdk::nuts::{
|
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::types::ProofInfo;
|
||||||
use cdk::util::unix_time;
|
use cdk::util::unix_time;
|
||||||
@@ -108,6 +108,44 @@ impl WalletRexieDatabase {
|
|||||||
db: Rc::new(Mutex::new(rexie)),
|
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))]
|
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
|
||||||
@@ -224,7 +262,7 @@ impl WalletDatabase for WalletRexieDatabase {
|
|||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
if !updated_proofs.is_empty() {
|
if !updated_proofs.is_empty() {
|
||||||
self.add_proofs(updated_proofs).await?;
|
self.update_proofs(updated_proofs, vec![]).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update mint quotes
|
// Update mint quotes
|
||||||
@@ -567,7 +605,11 @@ impl WalletDatabase for WalletRexieDatabase {
|
|||||||
Ok(())
|
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 rexie = self.db.lock().await;
|
||||||
|
|
||||||
let transaction = rexie
|
let transaction = rexie
|
||||||
@@ -576,9 +618,8 @@ impl WalletDatabase for WalletRexieDatabase {
|
|||||||
|
|
||||||
let proofs_store = transaction.store(PROOFS).map_err(Error::from)?;
|
let proofs_store = transaction.store(PROOFS).map_err(Error::from)?;
|
||||||
|
|
||||||
for proof in proofs {
|
for proof in added {
|
||||||
let y = proof.y;
|
let y = serde_wasm_bindgen::to_value(&proof.y).map_err(Error::from)?;
|
||||||
let y = serde_wasm_bindgen::to_value(&y).map_err(Error::from)?;
|
|
||||||
let proof = serde_wasm_bindgen::to_value(&proof).map_err(Error::from)?;
|
let proof = serde_wasm_bindgen::to_value(&proof).map_err(Error::from)?;
|
||||||
|
|
||||||
proofs_store
|
proofs_store
|
||||||
@@ -587,11 +628,29 @@ impl WalletDatabase for WalletRexieDatabase {
|
|||||||
.map_err(Error::from)?;
|
.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)?;
|
transaction.done().await.map_err(Error::from)?;
|
||||||
|
|
||||||
Ok(())
|
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(
|
async fn get_proofs(
|
||||||
&self,
|
&self,
|
||||||
mint_url: Option<MintUrl>,
|
mint_url: Option<MintUrl>,
|
||||||
@@ -638,58 +697,6 @@ impl WalletDatabase for WalletRexieDatabase {
|
|||||||
Ok(proofs)
|
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> {
|
async fn increment_keyset_counter(&self, keyset_id: &Id, count: u32) -> Result<(), Self::Err> {
|
||||||
let rexie = self.db.lock().await;
|
let rexie = self.db.lock().await;
|
||||||
|
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ use cdk::amount::Amount;
|
|||||||
use cdk::cdk_database::{self, WalletDatabase};
|
use cdk::cdk_database::{self, WalletDatabase};
|
||||||
use cdk::mint_url::MintUrl;
|
use cdk::mint_url::MintUrl;
|
||||||
use cdk::nuts::{
|
use cdk::nuts::{
|
||||||
CurrencyUnit, Id, KeySetInfo, Keys, MeltQuoteState, MintInfo, MintQuoteState, Proof, Proofs,
|
CurrencyUnit, Id, KeySetInfo, Keys, MeltQuoteState, MintInfo, MintQuoteState, Proof, PublicKey,
|
||||||
PublicKey, SpendingConditions, State,
|
SpendingConditions, State,
|
||||||
};
|
};
|
||||||
use cdk::secret::Secret;
|
use cdk::secret::Secret;
|
||||||
use cdk::types::ProofInfo;
|
use cdk::types::ProofInfo;
|
||||||
@@ -53,6 +53,23 @@ impl WalletSqliteDatabase {
|
|||||||
.await
|
.await
|
||||||
.expect("Could not run migrations");
|
.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]
|
#[async_trait]
|
||||||
@@ -513,9 +530,12 @@ WHERE id=?
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(skip_all)]
|
async fn update_proofs(
|
||||||
async fn add_proofs(&self, proof_info: Vec<ProofInfo>) -> Result<(), Self::Err> {
|
&self,
|
||||||
for proof in proof_info {
|
added: Vec<ProofInfo>,
|
||||||
|
removed_ys: Vec<PublicKey>,
|
||||||
|
) -> Result<(), Self::Err> {
|
||||||
|
for proof in added {
|
||||||
sqlx::query(
|
sqlx::query(
|
||||||
r#"
|
r#"
|
||||||
INSERT OR REPLACE INTO proof
|
INSERT OR REPLACE INTO proof
|
||||||
@@ -547,6 +567,44 @@ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
|
|||||||
.map_err(Error::from)?;
|
.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(())
|
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))]
|
#[instrument(skip(self), fields(keyset_id = %keyset_id))]
|
||||||
async fn increment_keyset_counter(&self, keyset_id: &Id, count: u32) -> Result<(), Self::Err> {
|
async fn increment_keyset_counter(&self, keyset_id: &Id, count: u32) -> Result<(), Self::Err> {
|
||||||
sqlx::query(
|
sqlx::query(
|
||||||
|
|||||||
@@ -17,9 +17,9 @@ use crate::mint::MintQuote as MintMintQuote;
|
|||||||
#[cfg(feature = "wallet")]
|
#[cfg(feature = "wallet")]
|
||||||
use crate::mint_url::MintUrl;
|
use crate::mint_url::MintUrl;
|
||||||
#[cfg(feature = "mint")]
|
#[cfg(feature = "mint")]
|
||||||
use crate::nuts::{BlindSignature, MeltQuoteState, MintQuoteState, Proof};
|
use crate::nuts::{BlindSignature, MeltQuoteState, MintQuoteState, Proof, Proofs};
|
||||||
#[cfg(any(feature = "wallet", feature = "mint"))]
|
#[cfg(any(feature = "wallet", feature = "mint"))]
|
||||||
use crate::nuts::{CurrencyUnit, Id, Proofs, PublicKey, State};
|
use crate::nuts::{CurrencyUnit, Id, PublicKey, State};
|
||||||
#[cfg(feature = "wallet")]
|
#[cfg(feature = "wallet")]
|
||||||
use crate::nuts::{KeySetInfo, Keys, MintInfo, SpendingConditions};
|
use crate::nuts::{KeySetInfo, Keys, MintInfo, SpendingConditions};
|
||||||
#[cfg(feature = "wallet")]
|
#[cfg(feature = "wallet")]
|
||||||
@@ -124,8 +124,18 @@ pub trait WalletDatabase: Debug {
|
|||||||
/// Remove [`Keys`] from storage
|
/// Remove [`Keys`] from storage
|
||||||
async fn remove_keys(&self, id: &Id) -> Result<(), Self::Err>;
|
async fn remove_keys(&self, id: &Id) -> Result<(), Self::Err>;
|
||||||
|
|
||||||
/// Add [`Proofs`] to storage
|
/// Update the proofs in storage by adding new proofs or removing proofs by their Y value.
|
||||||
async fn add_proofs(&self, proof_info: Vec<ProofInfo>) -> Result<(), Self::Err>;
|
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
|
/// Get proofs from storage
|
||||||
async fn get_proofs(
|
async fn get_proofs(
|
||||||
&self,
|
&self,
|
||||||
@@ -134,11 +144,6 @@ pub trait WalletDatabase: Debug {
|
|||||||
state: Option<Vec<State>>,
|
state: Option<Vec<State>>,
|
||||||
spending_conditions: Option<Vec<SpendingConditions>>,
|
spending_conditions: Option<Vec<SpendingConditions>>,
|
||||||
) -> Result<Vec<ProofInfo>, Self::Err>;
|
) -> 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
|
/// Increment Keyset counter
|
||||||
async fn increment_keyset_counter(&self, keyset_id: &Id, count: u32) -> Result<(), Self::Err>;
|
async fn increment_keyset_counter(&self, keyset_id: &Id, count: u32) -> Result<(), Self::Err>;
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ use super::WalletDatabase;
|
|||||||
use crate::cdk_database::Error;
|
use crate::cdk_database::Error;
|
||||||
use crate::mint_url::MintUrl;
|
use crate::mint_url::MintUrl;
|
||||||
use crate::nuts::{
|
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::types::ProofInfo;
|
||||||
use crate::util::unix_time;
|
use crate::util::unix_time;
|
||||||
@@ -109,7 +109,7 @@ impl WalletDatabase for WalletMemoryDatabase {
|
|||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
self.add_proofs(updated_proofs).await?;
|
self.update_proofs(updated_proofs, vec![]).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update mint quotes
|
// Update mint quotes
|
||||||
@@ -238,13 +238,57 @@ impl WalletDatabase for WalletMemoryDatabase {
|
|||||||
Ok(())
|
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;
|
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);
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -272,34 +316,6 @@ impl WalletDatabase for WalletMemoryDatabase {
|
|||||||
Ok(proofs)
|
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> {
|
async fn increment_keyset_counter(&self, keyset_id: &Id, count: u32) -> Result<(), Error> {
|
||||||
let keyset_counter = self.keyset_counter.read().await;
|
let keyset_counter = self.keyset_counter.read().await;
|
||||||
let current_counter = keyset_counter.get(keyset_id).cloned().unwrap_or(0);
|
let current_counter = keyset_counter.get(keyset_id).cloned().unwrap_or(0);
|
||||||
|
|||||||
@@ -259,11 +259,7 @@ impl Wallet {
|
|||||||
/// Return proofs to unspent allowing them to be selected and spent
|
/// Return proofs to unspent allowing them to be selected and spent
|
||||||
#[instrument(skip(self))]
|
#[instrument(skip(self))]
|
||||||
pub async fn unreserve_proofs(&self, ys: Vec<PublicKey>) -> Result<(), Error> {
|
pub async fn unreserve_proofs(&self, ys: Vec<PublicKey>) -> Result<(), Error> {
|
||||||
for y in ys {
|
Ok(self.localstore.set_unspent_proofs(ys).await?)
|
||||||
self.localstore.set_proof_state(y, State::Unspent).await?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Qeury mint for current mint information
|
/// Qeury mint for current mint information
|
||||||
@@ -461,7 +457,10 @@ impl Wallet {
|
|||||||
let amount = pending_proofs.iter().map(|p| p.proof.amount).sum();
|
let amount = pending_proofs.iter().map(|p| p.proof.amount).sum();
|
||||||
|
|
||||||
self.localstore
|
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?;
|
.await?;
|
||||||
|
|
||||||
balance += amount;
|
balance += amount;
|
||||||
@@ -701,7 +700,7 @@ impl Wallet {
|
|||||||
.collect::<Result<Vec<ProofInfo>, _>>()?;
|
.collect::<Result<Vec<ProofInfo>, _>>()?;
|
||||||
|
|
||||||
// Add new proofs to store
|
// Add new proofs to store
|
||||||
self.localstore.add_proofs(proofs).await?;
|
self.localstore.update_proofs(proofs, vec![]).await?;
|
||||||
|
|
||||||
Ok(minted_amount)
|
Ok(minted_amount)
|
||||||
}
|
}
|
||||||
@@ -776,12 +775,8 @@ impl Wallet {
|
|||||||
// Desired amount is either amount passed or value of all proof
|
// Desired amount is either amount passed or value of all proof
|
||||||
let proofs_total: Amount = proofs.iter().map(|p| p.amount).sum();
|
let proofs_total: Amount = proofs.iter().map(|p| p.amount).sum();
|
||||||
|
|
||||||
for proof in proofs.iter() {
|
let ys: Vec<PublicKey> = proofs.iter().map(|p| p.y()).collect::<Result<_, _>>()?;
|
||||||
self.localstore
|
self.localstore.set_pending_proofs(ys).await?;
|
||||||
.set_proof_state(proof.y()?, State::Pending)
|
|
||||||
.await
|
|
||||||
.ok();
|
|
||||||
}
|
|
||||||
|
|
||||||
let fee = self.get_proofs_fee(&proofs).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)
|
.increment_keyset_counter(&active_keyset_id, pre_swap.derived_secret_count)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
let mut added_proofs = Vec::new();
|
||||||
let change_proofs;
|
let change_proofs;
|
||||||
let send_proofs;
|
let send_proofs;
|
||||||
|
|
||||||
match amount {
|
match amount {
|
||||||
Some(amount) => {
|
Some(amount) => {
|
||||||
let (proofs_with_condition, proofs_without_condition): (Proofs, Proofs) =
|
let (proofs_with_condition, proofs_without_condition): (Proofs, Proofs) =
|
||||||
@@ -982,8 +977,7 @@ impl Wallet {
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|proof| ProofInfo::new(proof, mint_url.clone(), State::Reserved, *unit))
|
.map(|proof| ProofInfo::new(proof, mint_url.clone(), State::Reserved, *unit))
|
||||||
.collect::<Result<Vec<ProofInfo>, _>>()?;
|
.collect::<Result<Vec<ProofInfo>, _>>()?;
|
||||||
|
added_proofs = send_proofs_info;
|
||||||
self.localstore.add_proofs(send_proofs_info).await?;
|
|
||||||
|
|
||||||
change_proofs = proofs_to_keep;
|
change_proofs = proofs_to_keep;
|
||||||
send_proofs = Some(proofs_to_send);
|
send_proofs = Some(proofs_to_send);
|
||||||
@@ -998,12 +992,17 @@ impl Wallet {
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|proof| ProofInfo::new(proof, mint_url.clone(), State::Unspent, *unit))
|
.map(|proof| ProofInfo::new(proof, mint_url.clone(), State::Unspent, *unit))
|
||||||
.collect::<Result<Vec<ProofInfo>, _>>()?;
|
.collect::<Result<Vec<ProofInfo>, _>>()?;
|
||||||
|
added_proofs.extend(keep_proofs);
|
||||||
self.localstore.add_proofs(keep_proofs).await?;
|
|
||||||
|
|
||||||
// Remove spent proofs used as inputs
|
// 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)
|
Ok(send_proofs)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1053,11 +1052,11 @@ impl Wallet {
|
|||||||
/// Send specific proofs
|
/// Send specific proofs
|
||||||
#[instrument(skip(self))]
|
#[instrument(skip(self))]
|
||||||
pub async fn send_proofs(&self, memo: Option<String>, proofs: Proofs) -> Result<Token, Error> {
|
pub async fn send_proofs(&self, memo: Option<String>, proofs: Proofs) -> Result<Token, Error> {
|
||||||
for proof in proofs.iter() {
|
let ys = proofs
|
||||||
self.localstore
|
.iter()
|
||||||
.set_proof_state(proof.y()?, State::Reserved)
|
.map(|p| p.y())
|
||||||
.await?;
|
.collect::<Result<Vec<PublicKey>, _>>()?;
|
||||||
}
|
self.localstore.reserve_proofs(ys).await?;
|
||||||
|
|
||||||
Ok(Token::new(
|
Ok(Token::new(
|
||||||
self.mint_url.clone(),
|
self.mint_url.clone(),
|
||||||
@@ -1358,11 +1357,11 @@ impl Wallet {
|
|||||||
return Err(Error::QuoteUnknown);
|
return Err(Error::QuoteUnknown);
|
||||||
};
|
};
|
||||||
|
|
||||||
for proof in proofs.iter() {
|
let ys = proofs
|
||||||
self.localstore
|
.iter()
|
||||||
.set_proof_state(proof.y()?, State::Pending)
|
.map(|p| p.y())
|
||||||
.await?;
|
.collect::<Result<Vec<PublicKey>, _>>()?;
|
||||||
}
|
self.localstore.set_pending_proofs(ys).await?;
|
||||||
|
|
||||||
let active_keyset_id = self.get_active_mint_keyset().await?.id;
|
let active_keyset_id = self.get_active_mint_keyset().await?.id;
|
||||||
|
|
||||||
@@ -1429,7 +1428,8 @@ impl Wallet {
|
|||||||
change: change_proofs.clone(),
|
change: change_proofs.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(change_proofs) = change_proofs {
|
let change_proof_infos = match change_proofs {
|
||||||
|
Some(change_proofs) => {
|
||||||
tracing::debug!(
|
tracing::debug!(
|
||||||
"Change amount returned from melt: {}",
|
"Change amount returned from melt: {}",
|
||||||
change_proofs.iter().map(|p| p.amount).sum::<Amount>()
|
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)
|
.increment_keyset_counter(&active_keyset_id, change_proofs.len() as u32)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let change_proofs_info = change_proofs
|
change_proofs
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|proof| {
|
.map(|proof| {
|
||||||
ProofInfo::new(
|
ProofInfo::new(
|
||||||
@@ -1450,14 +1450,20 @@ impl Wallet {
|
|||||||
quote_info.unit,
|
quote_info.unit,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<ProofInfo>, _>>()?;
|
.collect::<Result<Vec<ProofInfo>, _>>()?
|
||||||
|
|
||||||
self.localstore.add_proofs(change_proofs_info).await?;
|
|
||||||
}
|
}
|
||||||
|
None => Vec::new(),
|
||||||
|
};
|
||||||
|
|
||||||
self.localstore.remove_melt_quote("e_info.id).await?;
|
self.localstore.remove_melt_quote("e_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)
|
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
|
let mut pre_swap = self
|
||||||
.create_swap(None, amount_split_target, proofs, None, false)
|
.create_swap(None, amount_split_target, proofs, None, false)
|
||||||
.await?;
|
.await?;
|
||||||
@@ -1755,7 +1769,7 @@ impl Wallet {
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|proof| ProofInfo::new(proof, mint.clone(), State::Unspent, self.unit))
|
.map(|proof| ProofInfo::new(proof, mint.clone(), State::Unspent, self.unit))
|
||||||
.collect::<Result<Vec<ProofInfo>, _>>()?;
|
.collect::<Result<Vec<ProofInfo>, _>>()?;
|
||||||
self.localstore.add_proofs(proofs).await?;
|
self.localstore.update_proofs(proofs, vec![]).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(total_amount)
|
Ok(total_amount)
|
||||||
@@ -1919,7 +1933,9 @@ impl Wallet {
|
|||||||
})
|
})
|
||||||
.collect::<Result<Vec<ProofInfo>, _>>()?;
|
.collect::<Result<Vec<ProofInfo>, _>>()?;
|
||||||
|
|
||||||
self.localstore.add_proofs(unspent_proofs).await?;
|
self.localstore
|
||||||
|
.update_proofs(unspent_proofs, vec![])
|
||||||
|
.await?;
|
||||||
|
|
||||||
empty_batch = 0;
|
empty_batch = 0;
|
||||||
start_counter += 100;
|
start_counter += 100;
|
||||||
|
|||||||
Reference in New Issue
Block a user