feat: check mint quotes

This commit is contained in:
thesimplekid
2024-05-19 00:34:18 +01:00
parent d21e99805c
commit 0cc5e153a8
7 changed files with 81 additions and 7 deletions

View File

@@ -231,6 +231,22 @@ impl WalletDatabase for RedbWalletDatabase {
Ok(None)
}
#[instrument(skip_all)]
async fn get_mint_quotes(&self) -> Result<Vec<MintQuote>, Self::Err> {
let db = self.db.lock().await;
let read_txn = db.begin_read().map_err(Into::<Error>::into)?;
let table = read_txn
.open_table(MINT_QUOTES_TABLE)
.map_err(Error::from)?;
Ok(table
.iter()
.map_err(Error::from)?
.flatten()
.flat_map(|(_id, quote)| serde_json::from_str(quote.value()))
.collect())
}
#[instrument(skip_all)]
async fn remove_mint_quote(&self, quote_id: &str) -> Result<(), Self::Err> {
let db = self.db.lock().await;

View File

@@ -265,14 +265,34 @@ impl WalletDatabase for RexieWalletDatabase {
let quotes_store = transaction.store(MINT_QUOTES).map_err(Error::from)?;
let quote_id = serde_wasm_bindgen::to_value(&quote_id).map_err(Error::from)?;
let keysets = quotes_store.get(&quote_id).await.map_err(Error::from)?;
let quote = quotes_store.get(&quote_id).await.map_err(Error::from)?;
let quote: Option<MintQuote> =
serde_wasm_bindgen::from_value(keysets).map_err(Error::from)?;
serde_wasm_bindgen::from_value(quote).map_err(Error::from)?;
Ok(quote)
}
async fn get_mint_quotes(&self) -> Result<Vec<MintQuote>, Self::Err> {
let rexie = self.db.lock().await;
let transaction = rexie
.transaction(&[MINT_QUOTES], TransactionMode::ReadOnly)
.map_err(Error::from)?;
let quotes_store = transaction.store(MINT_QUOTES).map_err(Error::from)?;
let quotes = quotes_store
.get_all(None, None, None, None)
.await
.map_err(Error::from)?;
Ok(quotes
.into_iter()
.flat_map(|(_id, q)| serde_wasm_bindgen::from_value(q))
.collect())
}
async fn remove_mint_quote(&self, quote_id: &str) -> Result<(), Self::Err> {
let rexie = self.db.lock().await;

View File

@@ -60,6 +60,7 @@ pub trait WalletDatabase {
) -> Result<Option<Vec<KeySetInfo>>, Self::Err>;
async fn add_mint_quote(&self, quote: MintQuote) -> Result<(), Self::Err>;
async fn get_mint_quote(&self, quote_id: &str) -> Result<Option<MintQuote>, Self::Err>;
async fn get_mint_quotes(&self) -> Result<Vec<MintQuote>, Self::Err>;
async fn remove_mint_quote(&self, quote_id: &str) -> Result<(), Self::Err>;
async fn add_melt_quote(&self, quote: MeltQuote) -> Result<(), Self::Err>;

View File

@@ -109,6 +109,11 @@ impl WalletDatabase for WalletMemoryDatabase {
Ok(self.mint_quotes.lock().await.get(quote_id).cloned())
}
async fn get_mint_quotes(&self) -> Result<Vec<MintQuote>, Error> {
let quotes = self.mint_quotes.lock().await;
Ok(quotes.values().cloned().collect())
}
async fn remove_mint_quote(&self, quote_id: &str) -> Result<(), Error> {
self.mint_quotes.lock().await.remove(quote_id);

View File

@@ -15,6 +15,7 @@ use crate::dhke::{hash_to_curve, sign_message, verify_message};
use crate::error::ErrorResponse;
use crate::nuts::*;
use crate::types::{MeltQuote, MintQuote};
use crate::url::UncheckedUrl;
use crate::util::unix_time;
use crate::Amount;
@@ -135,12 +136,13 @@ impl Mint {
pub async fn new_mint_quote(
&self,
mint_url: UncheckedUrl,
request: String,
unit: CurrencyUnit,
amount: Amount,
expiry: u64,
) -> Result<MintQuote, Error> {
let quote = MintQuote::new(request, unit, amount, expiry);
let quote = MintQuote::new(mint_url, request, unit, amount, expiry);
self.localstore.add_mint_quote(quote.clone()).await?;

View File

@@ -4,6 +4,7 @@ use serde::{Deserialize, Serialize};
use uuid::Uuid;
use crate::nuts::{CurrencyUnit, Proofs};
use crate::url::UncheckedUrl;
use crate::Amount;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
@@ -33,6 +34,7 @@ pub enum InvoiceStatus {
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
pub struct MintQuote {
pub id: String,
pub mint_url: UncheckedUrl,
pub amount: Amount,
pub unit: CurrencyUnit,
pub request: String,
@@ -41,10 +43,17 @@ pub struct MintQuote {
}
impl MintQuote {
pub fn new(request: String, unit: CurrencyUnit, amount: Amount, expiry: u64) -> Self {
pub fn new(
mint_url: UncheckedUrl,
request: String,
unit: CurrencyUnit,
amount: Amount,
expiry: u64,
) -> Self {
let id = Uuid::new_v4();
Self {
mint_url,
id: id.to_string(),
amount,
unit,

View File

@@ -364,10 +364,11 @@ impl Wallet {
) -> Result<MintQuote, Error> {
let quote_res = self
.client
.post_mint_quote(mint_url.try_into()?, amount, unit.clone())
.post_mint_quote(mint_url.clone().try_into()?, amount, unit.clone())
.await?;
let quote = MintQuote {
mint_url,
id: quote_res.quote.clone(),
amount,
unit: unit.clone(),
@@ -408,9 +409,29 @@ impl Wallet {
Ok(response)
}
/// Check status of pending mint quotes
pub async fn check_all_mint_quotes(&self) -> Result<Amount, Error> {
let mint_quotes = self.localstore.get_mint_quotes().await?;
let mut total_amount = Amount::ZERO;
for mint_quote in mint_quotes {
let mint_quote_response = self
.mint_quote_status(mint_quote.mint_url.clone(), &mint_quote.id)
.await?;
if mint_quote_response.paid {
let amount = self.mint(mint_quote.mint_url, &mint_quote.id).await?;
total_amount += amount;
} else if mint_quote.expiry.le(&unix_time()) {
self.localstore.remove_mint_quote(&mint_quote.id).await?;
}
}
Ok(total_amount)
}
#[instrument(skip(self), fields(mint_url = %mint_url))]
async fn active_mint_keyset(
&mut self,
&self,
mint_url: &UncheckedUrl,
unit: &CurrencyUnit,
) -> Result<Id, Error> {
@@ -466,7 +487,7 @@ impl Wallet {
/// Mint
#[instrument(skip(self, quote_id), fields(mint_url = %mint_url))]
pub async fn mint(&mut self, mint_url: UncheckedUrl, quote_id: &str) -> Result<Amount, Error> {
pub async fn mint(&self, mint_url: UncheckedUrl, quote_id: &str) -> Result<Amount, Error> {
// Check that mint is in store of mints
if self.localstore.get_mint(mint_url.clone()).await?.is_none() {
self.add_mint(mint_url.clone()).await?;