|
@@ -1,751 +0,0 @@
|
|
|
-//! Rexie Browser Database
|
|
|
-
|
|
|
-use std::collections::{HashMap, HashSet};
|
|
|
-use std::rc::Rc;
|
|
|
-use std::result::Result;
|
|
|
-
|
|
|
-use async_trait::async_trait;
|
|
|
-use cdk::cdk_database::{self, WalletDatabase};
|
|
|
-use cdk::mint_url::MintUrl;
|
|
|
-use cdk::nuts::{
|
|
|
- CurrencyUnit, Id, KeySetInfo, Keys, MintInfo, PublicKey, SpendingConditions, State,
|
|
|
-};
|
|
|
-use cdk::types::ProofInfo;
|
|
|
-use cdk::util::unix_time;
|
|
|
-use cdk::wallet::{MeltQuote, MintQuote};
|
|
|
-use rexie::*;
|
|
|
-use thiserror::Error;
|
|
|
-use tokio::sync::Mutex;
|
|
|
-
|
|
|
-// Tables
|
|
|
-const MINTS: &str = "mints";
|
|
|
-const MINT_KEYSETS: &str = "keysets_by_mint";
|
|
|
-const KEYSETS: &str = "keysets";
|
|
|
-const MINT_KEYS: &str = "mint_keys";
|
|
|
-const MINT_QUOTES: &str = "mint_quotes";
|
|
|
-const MELT_QUOTES: &str = "melt_quotes";
|
|
|
-const PROOFS: &str = "proofs";
|
|
|
-const CONFIG: &str = "config";
|
|
|
-const KEYSET_COUNTER: &str = "keyset_counter";
|
|
|
-
|
|
|
-const DATABASE_VERSION: u32 = 4;
|
|
|
-
|
|
|
-/// Rexie Database Error
|
|
|
-#[derive(Debug, Error)]
|
|
|
-pub enum Error {
|
|
|
- /// CDK Database Error
|
|
|
- #[error(transparent)]
|
|
|
- CDKDatabase(#[from] cdk::cdk_database::Error),
|
|
|
- /// Rexie Error
|
|
|
- #[error(transparent)]
|
|
|
- Rexie(#[from] rexie::Error),
|
|
|
- /// Serde Wasm Error
|
|
|
- #[error(transparent)]
|
|
|
- SerdeBindgen(#[from] serde_wasm_bindgen::Error),
|
|
|
- /// NUT00 Error
|
|
|
- #[error(transparent)]
|
|
|
- NUT00(cdk::nuts::nut00::Error),
|
|
|
- #[error("Not found")]
|
|
|
- /// Not Found
|
|
|
- NotFound,
|
|
|
-}
|
|
|
-impl From<Error> for cdk::cdk_database::Error {
|
|
|
- fn from(e: Error) -> Self {
|
|
|
- Self::Database(Box::new(e))
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-// These are okay because we never actually send across threads in the browser
|
|
|
-unsafe impl Send for Error {}
|
|
|
-unsafe impl Sync for Error {}
|
|
|
-
|
|
|
-/// Wallet Rexie Database
|
|
|
-#[derive(Debug, Clone)]
|
|
|
-pub struct WalletRexieDatabase {
|
|
|
- db: Rc<Mutex<Rexie>>,
|
|
|
-}
|
|
|
-
|
|
|
-// These are okay because we never actually send across threads in the browser
|
|
|
-unsafe impl Send for WalletRexieDatabase {}
|
|
|
-unsafe impl Sync for WalletRexieDatabase {}
|
|
|
-
|
|
|
-impl WalletRexieDatabase {
|
|
|
- /// Create new [`WalletRexieDatabase`]
|
|
|
- pub async fn new() -> Result<Self, Error> {
|
|
|
- let rexie = Rexie::builder("cdk")
|
|
|
- .version(DATABASE_VERSION)
|
|
|
- .add_object_store(
|
|
|
- ObjectStore::new(PROOFS)
|
|
|
- .add_index(Index::new("y", "y").unique(true))
|
|
|
- .add_index(Index::new("mint_url", "mint_url"))
|
|
|
- .add_index(Index::new("state", "state"))
|
|
|
- .add_index(Index::new("unit", "unit")),
|
|
|
- )
|
|
|
- .add_object_store(
|
|
|
- ObjectStore::new(MINTS).add_index(Index::new("mint_url", "mint_url").unique(true)),
|
|
|
- )
|
|
|
- .add_object_store(ObjectStore::new(MINT_KEYSETS))
|
|
|
- .add_object_store(
|
|
|
- ObjectStore::new(KEYSETS)
|
|
|
- .add_index(Index::new("keyset_id", "keyset_id").unique(true)),
|
|
|
- )
|
|
|
- .add_object_store(
|
|
|
- ObjectStore::new(MINT_KEYS)
|
|
|
- .add_index(Index::new("keyset_id", "keyset_id").unique(true)),
|
|
|
- )
|
|
|
- .add_object_store(ObjectStore::new(MINT_QUOTES))
|
|
|
- .add_object_store(ObjectStore::new(MELT_QUOTES))
|
|
|
- .add_object_store(ObjectStore::new(CONFIG))
|
|
|
- .add_object_store(ObjectStore::new(KEYSET_COUNTER))
|
|
|
- // Build the database
|
|
|
- .build()
|
|
|
- .await
|
|
|
- .unwrap();
|
|
|
-
|
|
|
- Ok(Self {
|
|
|
- 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(not(target_arch = "wasm32"), async_trait)]
|
|
|
-impl WalletDatabase for WalletRexieDatabase {
|
|
|
- type Err = cdk::cdk_database::Error;
|
|
|
-
|
|
|
- async fn add_mint(
|
|
|
- &self,
|
|
|
- mint_url: MintUrl,
|
|
|
- mint_info: Option<MintInfo>,
|
|
|
- ) -> Result<(), Self::Err> {
|
|
|
- let rexie = self.db.lock().await;
|
|
|
-
|
|
|
- let transaction = rexie
|
|
|
- .transaction(&[MINTS], TransactionMode::ReadWrite)
|
|
|
- .map_err(Error::from)?;
|
|
|
-
|
|
|
- let mints_store = transaction.store(MINTS).map_err(Error::from)?;
|
|
|
-
|
|
|
- let mint_url = serde_wasm_bindgen::to_value(&mint_url).map_err(Error::from)?;
|
|
|
- let mint_info = serde_wasm_bindgen::to_value(&mint_info).map_err(Error::from)?;
|
|
|
-
|
|
|
- mints_store
|
|
|
- .put(&mint_info, Some(&mint_url))
|
|
|
- .await
|
|
|
- .map_err(Error::from)?;
|
|
|
-
|
|
|
- transaction.done().await.map_err(Error::from)?;
|
|
|
-
|
|
|
- Ok(())
|
|
|
- }
|
|
|
-
|
|
|
- async fn remove_mint(&self, mint_url: MintUrl) -> Result<(), Self::Err> {
|
|
|
- let rexie = self.db.lock().await;
|
|
|
-
|
|
|
- let transaction = rexie
|
|
|
- .transaction(&[MINTS], TransactionMode::ReadWrite)
|
|
|
- .map_err(Error::from)?;
|
|
|
-
|
|
|
- let mints_store = transaction.store(MINTS).map_err(Error::from)?;
|
|
|
-
|
|
|
- let mint_url = serde_wasm_bindgen::to_value(&mint_url).map_err(Error::from)?;
|
|
|
-
|
|
|
- mints_store.delete(mint_url).await.map_err(Error::from)?;
|
|
|
-
|
|
|
- transaction.done().await.map_err(Error::from)?;
|
|
|
-
|
|
|
- Ok(())
|
|
|
- }
|
|
|
-
|
|
|
- async fn get_mint(&self, mint_url: MintUrl) -> Result<Option<MintInfo>, Self::Err> {
|
|
|
- let rexie = self.db.lock().await;
|
|
|
-
|
|
|
- let transaction = rexie
|
|
|
- .transaction(&[MINTS], TransactionMode::ReadOnly)
|
|
|
- .map_err(Error::from)?;
|
|
|
-
|
|
|
- let mints_store = transaction.store(MINTS).map_err(Error::from)?;
|
|
|
-
|
|
|
- let mint_url = serde_wasm_bindgen::to_value(&mint_url).map_err(Error::from)?;
|
|
|
- let mint_info = mints_store
|
|
|
- .get(mint_url)
|
|
|
- .await
|
|
|
- .map_err(Error::from)?
|
|
|
- .and_then(|m| serde_wasm_bindgen::from_value(m).ok());
|
|
|
-
|
|
|
- Ok(mint_info)
|
|
|
- }
|
|
|
-
|
|
|
- async fn get_mints(&self) -> Result<HashMap<MintUrl, Option<MintInfo>>, Self::Err> {
|
|
|
- let rexie = self.db.lock().await;
|
|
|
-
|
|
|
- let transaction = rexie
|
|
|
- .transaction(&[MINTS], TransactionMode::ReadOnly)
|
|
|
- .map_err(Error::from)?;
|
|
|
-
|
|
|
- let mints_store = transaction.store(MINTS).map_err(Error::from)?;
|
|
|
-
|
|
|
- let mints = mints_store
|
|
|
- .scan(None, None, None, None)
|
|
|
- .await
|
|
|
- .map_err(Error::from)?;
|
|
|
-
|
|
|
- let mints: HashMap<MintUrl, Option<MintInfo>> = mints
|
|
|
- .into_iter()
|
|
|
- .map(|(url, info)| {
|
|
|
- (
|
|
|
- serde_wasm_bindgen::from_value(url).unwrap(),
|
|
|
- serde_wasm_bindgen::from_value(info).unwrap(),
|
|
|
- )
|
|
|
- })
|
|
|
- .collect();
|
|
|
-
|
|
|
- Ok(mints)
|
|
|
- }
|
|
|
-
|
|
|
- async fn update_mint_url(
|
|
|
- &self,
|
|
|
- old_mint_url: MintUrl,
|
|
|
- new_mint_url: MintUrl,
|
|
|
- ) -> Result<(), Self::Err> {
|
|
|
- let proofs = self
|
|
|
- .get_proofs(Some(old_mint_url), None, None, None)
|
|
|
- .await
|
|
|
- .map_err(Error::from)?;
|
|
|
-
|
|
|
- let updated_proofs: Vec<ProofInfo> = proofs
|
|
|
- .into_iter()
|
|
|
- .map(|mut p| {
|
|
|
- p.mint_url = new_mint_url.clone();
|
|
|
- p
|
|
|
- })
|
|
|
- .collect();
|
|
|
-
|
|
|
- if !updated_proofs.is_empty() {
|
|
|
- self.update_proofs(updated_proofs, vec![]).await?;
|
|
|
- }
|
|
|
-
|
|
|
- // Update mint quotes
|
|
|
- {
|
|
|
- let quotes = self.get_mint_quotes().await?;
|
|
|
-
|
|
|
- let unix_time = unix_time();
|
|
|
-
|
|
|
- let quotes: Vec<MintQuote> = quotes
|
|
|
- .into_iter()
|
|
|
- .filter_map(|mut q| {
|
|
|
- if q.expiry < unix_time {
|
|
|
- q.mint_url = new_mint_url.clone();
|
|
|
- Some(q)
|
|
|
- } else {
|
|
|
- None
|
|
|
- }
|
|
|
- })
|
|
|
- .collect();
|
|
|
-
|
|
|
- for quote in quotes {
|
|
|
- self.add_mint_quote(quote).await?;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- Ok(())
|
|
|
- }
|
|
|
-
|
|
|
- async fn add_mint_keysets(
|
|
|
- &self,
|
|
|
- mint_url: MintUrl,
|
|
|
- keysets: Vec<KeySetInfo>,
|
|
|
- ) -> Result<(), Self::Err> {
|
|
|
- let rexie = self.db.lock().await;
|
|
|
-
|
|
|
- let transaction = rexie
|
|
|
- .transaction(&[MINT_KEYSETS, KEYSETS], TransactionMode::ReadWrite)
|
|
|
- .map_err(Error::from)?;
|
|
|
-
|
|
|
- let mint_keysets_store = transaction.store(MINT_KEYSETS).map_err(Error::from)?;
|
|
|
- let keysets_store = transaction.store(KEYSETS).map_err(Error::from)?;
|
|
|
-
|
|
|
- let mint_url = serde_wasm_bindgen::to_value(&mint_url).map_err(Error::from)?;
|
|
|
-
|
|
|
- let mut mint_keysets = mint_keysets_store
|
|
|
- .get(mint_url.clone())
|
|
|
- .await
|
|
|
- .map_err(Error::from)?
|
|
|
- .and_then(|m| serde_wasm_bindgen::from_value(m).ok());
|
|
|
-
|
|
|
- let new_keyset_ids: Vec<Id> = keysets.iter().map(|k| k.id).collect();
|
|
|
-
|
|
|
- mint_keysets
|
|
|
- .as_mut()
|
|
|
- .unwrap_or(&mut HashSet::new())
|
|
|
- .extend(new_keyset_ids);
|
|
|
-
|
|
|
- let mint_keysets = serde_wasm_bindgen::to_value(&mint_keysets).map_err(Error::from)?;
|
|
|
-
|
|
|
- mint_keysets_store
|
|
|
- .put(&mint_keysets, Some(&mint_url))
|
|
|
- .await
|
|
|
- .map_err(Error::from)?;
|
|
|
-
|
|
|
- for keyset in keysets {
|
|
|
- let id = serde_wasm_bindgen::to_value(&keyset.id).map_err(Error::from)?;
|
|
|
- let keyset = serde_wasm_bindgen::to_value(&keyset).map_err(Error::from)?;
|
|
|
-
|
|
|
- keysets_store
|
|
|
- .put(&keyset, Some(&id))
|
|
|
- .await
|
|
|
- .map_err(Error::from)?;
|
|
|
- }
|
|
|
-
|
|
|
- transaction.done().await.map_err(Error::from)?;
|
|
|
-
|
|
|
- Ok(())
|
|
|
- }
|
|
|
-
|
|
|
- async fn get_mint_keysets(
|
|
|
- &self,
|
|
|
- mint_url: MintUrl,
|
|
|
- ) -> Result<Option<Vec<KeySetInfo>>, Self::Err> {
|
|
|
- let rexie = self.db.lock().await;
|
|
|
-
|
|
|
- let transaction = rexie
|
|
|
- .transaction(&[MINT_KEYSETS, KEYSETS], TransactionMode::ReadOnly)
|
|
|
- .map_err(Error::from)?;
|
|
|
-
|
|
|
- let mints_store = transaction.store(MINT_KEYSETS).map_err(Error::from)?;
|
|
|
-
|
|
|
- let mint_url = serde_wasm_bindgen::to_value(&mint_url).map_err(Error::from)?;
|
|
|
- let mint_keysets: Option<HashSet<Id>> = mints_store
|
|
|
- .get(mint_url)
|
|
|
- .await
|
|
|
- .map_err(Error::from)?
|
|
|
- .and_then(|m| serde_wasm_bindgen::from_value(m).ok());
|
|
|
-
|
|
|
- let keysets_store = transaction.store(KEYSETS).map_err(Error::from)?;
|
|
|
-
|
|
|
- let keysets = match mint_keysets {
|
|
|
- Some(mint_keysets) => {
|
|
|
- let mut keysets = vec![];
|
|
|
-
|
|
|
- for mint_keyset in mint_keysets {
|
|
|
- let id = serde_wasm_bindgen::to_value(&mint_keyset).map_err(Error::from)?;
|
|
|
-
|
|
|
- let keyset = keysets_store
|
|
|
- .get(id)
|
|
|
- .await
|
|
|
- .map_err(Error::from)?
|
|
|
- .and_then(|k| serde_wasm_bindgen::from_value(k).ok());
|
|
|
-
|
|
|
- keysets.push(keyset);
|
|
|
- }
|
|
|
-
|
|
|
- let keysets = keysets.iter().flatten().cloned().collect();
|
|
|
-
|
|
|
- Some(keysets)
|
|
|
- }
|
|
|
- None => None,
|
|
|
- };
|
|
|
-
|
|
|
- transaction.done().await.map_err(Error::from)?;
|
|
|
-
|
|
|
- Ok(keysets)
|
|
|
- }
|
|
|
-
|
|
|
- async fn get_keyset_by_id(&self, keyset_id: &Id) -> Result<Option<KeySetInfo>, Self::Err> {
|
|
|
- let rexie = self.db.lock().await;
|
|
|
-
|
|
|
- let transaction = rexie
|
|
|
- .transaction(&[KEYSETS], TransactionMode::ReadOnly)
|
|
|
- .map_err(Error::from)?;
|
|
|
- let keysets_store = transaction.store(KEYSETS).map_err(Error::from)?;
|
|
|
-
|
|
|
- let keyset_id = serde_wasm_bindgen::to_value(keyset_id).map_err(Error::from)?;
|
|
|
-
|
|
|
- let keyset = keysets_store
|
|
|
- .get(keyset_id)
|
|
|
- .await
|
|
|
- .map_err(Error::from)?
|
|
|
- .and_then(|k| serde_wasm_bindgen::from_value(k).ok());
|
|
|
-
|
|
|
- Ok(keyset)
|
|
|
- }
|
|
|
-
|
|
|
- async fn add_mint_quote(&self, quote: MintQuote) -> Result<(), Self::Err> {
|
|
|
- let rexie = self.db.lock().await;
|
|
|
-
|
|
|
- let transaction = rexie
|
|
|
- .transaction(&[MINT_QUOTES], TransactionMode::ReadWrite)
|
|
|
- .map_err(Error::from)?;
|
|
|
-
|
|
|
- let quotes_store = transaction.store(MINT_QUOTES).map_err(Error::from)?;
|
|
|
-
|
|
|
- let quote_id = serde_wasm_bindgen::to_value("e.id).map_err(Error::from)?;
|
|
|
- let quote = serde_wasm_bindgen::to_value("e).map_err(Error::from)?;
|
|
|
-
|
|
|
- quotes_store
|
|
|
- .put("e, Some("e_id))
|
|
|
- .await
|
|
|
- .map_err(Error::from)?;
|
|
|
-
|
|
|
- transaction.done().await.map_err(Error::from)?;
|
|
|
-
|
|
|
- Ok(())
|
|
|
- }
|
|
|
-
|
|
|
- async fn get_mint_quote(&self, quote_id: &str) -> Result<Option<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 quote_id = serde_wasm_bindgen::to_value("e_id).map_err(Error::from)?;
|
|
|
- let quote = quotes_store
|
|
|
- .get(quote_id)
|
|
|
- .await
|
|
|
- .map_err(Error::from)?
|
|
|
- .and_then(|q| serde_wasm_bindgen::from_value(q).ok());
|
|
|
-
|
|
|
- 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
|
|
|
- .scan(None, None, None, None)
|
|
|
- .await
|
|
|
- .map_err(Error::from)?;
|
|
|
-
|
|
|
- Ok(quotes
|
|
|
- .into_iter()
|
|
|
- .map(|(_id, q)| serde_wasm_bindgen::from_value(q))
|
|
|
- .collect::<Result<Vec<MintQuote>, serde_wasm_bindgen::Error>>()
|
|
|
- .map_err(<serde_wasm_bindgen::Error as Into<Error>>::into)?)
|
|
|
- }
|
|
|
-
|
|
|
- async fn remove_mint_quote(&self, quote_id: &str) -> Result<(), Self::Err> {
|
|
|
- let rexie = self.db.lock().await;
|
|
|
-
|
|
|
- let transaction = rexie
|
|
|
- .transaction(&[MINT_QUOTES], TransactionMode::ReadWrite)
|
|
|
- .map_err(Error::from)?;
|
|
|
-
|
|
|
- let quotes_store = transaction.store(MINT_QUOTES).map_err(Error::from)?;
|
|
|
-
|
|
|
- let quote_id = serde_wasm_bindgen::to_value("e_id).map_err(Error::from)?;
|
|
|
-
|
|
|
- quotes_store.delete(quote_id).await.map_err(Error::from)?;
|
|
|
-
|
|
|
- transaction.done().await.map_err(Error::from)?;
|
|
|
-
|
|
|
- Ok(())
|
|
|
- }
|
|
|
-
|
|
|
- async fn add_melt_quote(&self, quote: MeltQuote) -> Result<(), Self::Err> {
|
|
|
- let rexie = self.db.lock().await;
|
|
|
-
|
|
|
- let transaction = rexie
|
|
|
- .transaction(&[MELT_QUOTES], TransactionMode::ReadWrite)
|
|
|
- .map_err(Error::from)?;
|
|
|
-
|
|
|
- let quotes_store = transaction.store(MELT_QUOTES).map_err(Error::from)?;
|
|
|
-
|
|
|
- let quote_id = serde_wasm_bindgen::to_value("e.id).map_err(Error::from)?;
|
|
|
- let quote = serde_wasm_bindgen::to_value("e).map_err(Error::from)?;
|
|
|
-
|
|
|
- quotes_store
|
|
|
- .put("e, Some("e_id))
|
|
|
- .await
|
|
|
- .map_err(Error::from)?;
|
|
|
-
|
|
|
- transaction.done().await.map_err(Error::from)?;
|
|
|
-
|
|
|
- Ok(())
|
|
|
- }
|
|
|
-
|
|
|
- async fn get_melt_quote(&self, quote_id: &str) -> Result<Option<MeltQuote>, Self::Err> {
|
|
|
- let rexie = self.db.lock().await;
|
|
|
-
|
|
|
- let transaction = rexie
|
|
|
- .transaction(&[MELT_QUOTES], TransactionMode::ReadOnly)
|
|
|
- .map_err(Error::from)?;
|
|
|
-
|
|
|
- let quotes_store = transaction.store(MELT_QUOTES).map_err(Error::from)?;
|
|
|
-
|
|
|
- let quote_id = serde_wasm_bindgen::to_value("e_id).map_err(Error::from)?;
|
|
|
- let quote = quotes_store
|
|
|
- .get(quote_id)
|
|
|
- .await
|
|
|
- .map_err(Error::from)?
|
|
|
- .and_then(|q| serde_wasm_bindgen::from_value(q).ok());
|
|
|
-
|
|
|
- Ok(quote)
|
|
|
- }
|
|
|
-
|
|
|
- async fn remove_melt_quote(&self, quote_id: &str) -> Result<(), Self::Err> {
|
|
|
- let rexie = self.db.lock().await;
|
|
|
-
|
|
|
- let transaction = rexie
|
|
|
- .transaction(&[MELT_QUOTES], TransactionMode::ReadWrite)
|
|
|
- .map_err(Error::from)?;
|
|
|
-
|
|
|
- let quotes_store = transaction.store(MELT_QUOTES).map_err(Error::from)?;
|
|
|
-
|
|
|
- let quote_id = serde_wasm_bindgen::to_value("e_id).map_err(Error::from)?;
|
|
|
-
|
|
|
- quotes_store.delete(quote_id).await.map_err(Error::from)?;
|
|
|
-
|
|
|
- transaction.done().await.map_err(Error::from)?;
|
|
|
-
|
|
|
- Ok(())
|
|
|
- }
|
|
|
-
|
|
|
- async fn add_keys(&self, keyset: KeySet) -> Result<(), Self::Err> {
|
|
|
- // Verify ID by recomputing id
|
|
|
- keyset.verify_id()?;
|
|
|
-
|
|
|
- let rexie = self.db.lock().await;
|
|
|
-
|
|
|
- let transaction = rexie
|
|
|
- .transaction(&[MINT_KEYS], TransactionMode::ReadWrite)
|
|
|
- .map_err(Error::from)?;
|
|
|
-
|
|
|
- let keys_store = transaction.store(MINT_KEYS).map_err(Error::from)?;
|
|
|
-
|
|
|
- let keyset_id = serde_wasm_bindgen::to_value(&keyset.id).map_err(Error::from)?;
|
|
|
- let keys = serde_wasm_bindgen::to_value(&keys).map_err(Error::from)?;
|
|
|
-
|
|
|
- keys_store
|
|
|
- .put(&keys, Some(&keyset_id))
|
|
|
- .await
|
|
|
- .map_err(Error::from)?;
|
|
|
-
|
|
|
- transaction.done().await.map_err(Error::from)?;
|
|
|
-
|
|
|
- Ok(())
|
|
|
- }
|
|
|
-
|
|
|
- async fn get_keys(&self, id: &Id) -> Result<Option<Keys>, Self::Err> {
|
|
|
- let rexie = self.db.lock().await;
|
|
|
-
|
|
|
- let transaction = rexie
|
|
|
- .transaction(&[MINT_KEYS], TransactionMode::ReadOnly)
|
|
|
- .map_err(Error::from)?;
|
|
|
-
|
|
|
- let keys_store = transaction.store(MINT_KEYS).map_err(Error::from)?;
|
|
|
-
|
|
|
- let keyset_id = serde_wasm_bindgen::to_value(id).map_err(Error::from)?;
|
|
|
- let keys = keys_store
|
|
|
- .get(keyset_id)
|
|
|
- .await
|
|
|
- .map_err(Error::from)?
|
|
|
- .and_then(|k| serde_wasm_bindgen::from_value(k).ok());
|
|
|
-
|
|
|
- Ok(keys)
|
|
|
- }
|
|
|
-
|
|
|
- async fn remove_keys(&self, id: &Id) -> Result<(), Self::Err> {
|
|
|
- let rexie = self.db.lock().await;
|
|
|
-
|
|
|
- let transaction = rexie
|
|
|
- .transaction(&[MINT_KEYS], TransactionMode::ReadWrite)
|
|
|
- .map_err(Error::from)?;
|
|
|
-
|
|
|
- let keys_store = transaction.store(MINT_KEYS).map_err(Error::from)?;
|
|
|
-
|
|
|
- let keyset_id = serde_wasm_bindgen::to_value(id).map_err(Error::from)?;
|
|
|
- keys_store.delete(keyset_id).await.map_err(Error::from)?;
|
|
|
-
|
|
|
- Ok(())
|
|
|
- }
|
|
|
-
|
|
|
- async fn update_proofs(
|
|
|
- &self,
|
|
|
- added: Vec<ProofInfo>,
|
|
|
- removed_ys: Vec<PublicKey>,
|
|
|
- ) -> 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 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
|
|
|
- .put(&proof, Some(&y))
|
|
|
- .await
|
|
|
- .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>,
|
|
|
- unit: Option<CurrencyUnit>,
|
|
|
- state: Option<Vec<State>>,
|
|
|
- spending_conditions: Option<Vec<SpendingConditions>>,
|
|
|
- ) -> Result<Vec<ProofInfo>, Self::Err> {
|
|
|
- let rexie = self.db.lock().await;
|
|
|
-
|
|
|
- let transaction = rexie
|
|
|
- .transaction(&[PROOFS], TransactionMode::ReadOnly)
|
|
|
- .map_err(Error::from)?;
|
|
|
-
|
|
|
- let proofs_store = transaction.store(PROOFS).map_err(Error::from)?;
|
|
|
-
|
|
|
- let proofs = proofs_store
|
|
|
- .scan(None, None, None, None)
|
|
|
- .await
|
|
|
- .map_err(Error::from)?;
|
|
|
-
|
|
|
- let proofs: Vec<ProofInfo> = proofs
|
|
|
- .into_iter()
|
|
|
- .filter_map(|(_k, v)| {
|
|
|
- let mut proof = None;
|
|
|
-
|
|
|
- if let Ok(proof_info) = serde_wasm_bindgen::from_value::<ProofInfo>(v) {
|
|
|
- proof = match proof_info.matches_conditions(
|
|
|
- &mint_url,
|
|
|
- &unit,
|
|
|
- &state,
|
|
|
- &spending_conditions,
|
|
|
- ) {
|
|
|
- true => Some(proof_info),
|
|
|
- false => None,
|
|
|
- };
|
|
|
- }
|
|
|
-
|
|
|
- proof
|
|
|
- })
|
|
|
- .collect();
|
|
|
-
|
|
|
- transaction.done().await.map_err(Error::from)?;
|
|
|
-
|
|
|
- Ok(proofs)
|
|
|
- }
|
|
|
-
|
|
|
- async fn increment_keyset_counter(&self, keyset_id: &Id, count: u32) -> Result<(), Self::Err> {
|
|
|
- let rexie = self.db.lock().await;
|
|
|
-
|
|
|
- let transaction = rexie
|
|
|
- .transaction(&[KEYSET_COUNTER], TransactionMode::ReadWrite)
|
|
|
- .map_err(Error::from)?;
|
|
|
-
|
|
|
- let counter_store = transaction.store(KEYSET_COUNTER).map_err(Error::from)?;
|
|
|
-
|
|
|
- let keyset_id = serde_wasm_bindgen::to_value(keyset_id).map_err(Error::from)?;
|
|
|
-
|
|
|
- let current_count: Option<u32> = counter_store
|
|
|
- .get(keyset_id.clone())
|
|
|
- .await
|
|
|
- .map_err(Error::from)?
|
|
|
- .and_then(|c| serde_wasm_bindgen::from_value(c).ok());
|
|
|
-
|
|
|
- let new_count = current_count.unwrap_or_default() + count;
|
|
|
-
|
|
|
- let new_count = serde_wasm_bindgen::to_value(&new_count).map_err(Error::from)?;
|
|
|
-
|
|
|
- counter_store
|
|
|
- .put(&new_count, Some(&keyset_id))
|
|
|
- .await
|
|
|
- .map_err(Error::from)?;
|
|
|
-
|
|
|
- transaction.done().await.map_err(Error::from)?;
|
|
|
-
|
|
|
- Ok(())
|
|
|
- }
|
|
|
-
|
|
|
- async fn get_keyset_counter(&self, keyset_id: &Id) -> Result<Option<u32>, Self::Err> {
|
|
|
- let rexie = self.db.lock().await;
|
|
|
-
|
|
|
- let transaction = rexie
|
|
|
- .transaction(&[KEYSET_COUNTER], TransactionMode::ReadWrite)
|
|
|
- .map_err(Error::from)?;
|
|
|
-
|
|
|
- let counter_store = transaction.store(KEYSET_COUNTER).map_err(Error::from)?;
|
|
|
-
|
|
|
- let keyset_id = serde_wasm_bindgen::to_value(keyset_id).map_err(Error::from)?;
|
|
|
-
|
|
|
- let current_count = counter_store
|
|
|
- .get(keyset_id)
|
|
|
- .await
|
|
|
- .map_err(Error::from)?
|
|
|
- .and_then(|c| serde_wasm_bindgen::from_value(c).ok());
|
|
|
-
|
|
|
- Ok(current_count)
|
|
|
- }
|
|
|
-}
|