|
@@ -0,0 +1,177 @@
|
|
|
|
|
+use std::sync::Arc;
|
|
|
|
|
+
|
|
|
|
|
+use cdk_common::{
|
|
|
|
|
+ database::{Error, WalletDatabase},
|
|
|
|
|
+ mint_url::MintUrl,
|
|
|
|
|
+ nuts::{CurrencyUnit, Id, KeySet, KeySetInfo, Keys},
|
|
|
|
|
+ wallet::TransactionId,
|
|
|
|
|
+ MintInfo, PublicKey, State,
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+use crate::nuts::SpendingConditions;
|
|
|
|
|
+use crate::types::ProofInfo;
|
|
|
|
|
+
|
|
|
|
|
+use super::Tx;
|
|
|
|
|
+
|
|
|
|
|
+/// Abstraction for all operations that can be executed in a database transaction and in a database
|
|
|
|
|
+/// trait, to avoid duplicating code for accesing data
|
|
|
|
|
+pub enum Storage<'a, 'b> {
|
|
|
|
|
+ Db(Arc<dyn WalletDatabase<Err = Error> + Send + Sync>),
|
|
|
|
|
+ Tx(&'a mut Tx<'a, 'b>),
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+impl<'a, 'b> From<Arc<dyn WalletDatabase<Err = Error> + Send + Sync>> for Storage<'a, 'b> {
|
|
|
|
|
+ fn from(value: Arc<dyn WalletDatabase<Err = Error> + Send + Sync>) -> Self {
|
|
|
|
|
+ Self::Db(value)
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+impl<'a, 'b> From<&'a mut Tx<'a, 'b>> for Storage<'a, 'b> {
|
|
|
|
|
+ fn from(value: &'a mut Tx<'a, 'b>) -> Self {
|
|
|
|
|
+ Self::Tx(value)
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+impl<'a, 'b> Storage<'a, 'b> {
|
|
|
|
|
+ /// Get mint from storage
|
|
|
|
|
+ pub async fn get_mint(&mut self, mint_url: MintUrl) -> Result<Option<MintInfo>, Error> {
|
|
|
|
|
+ match self {
|
|
|
|
|
+ Self::Db(db) => db.get_mint(mint_url).await,
|
|
|
|
|
+ Self::Tx(tx) => tx.get_mint(mint_url).await,
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /// Add mint - automatically uses transaction or connection
|
|
|
|
|
+ pub async fn add_mint(
|
|
|
|
|
+ &mut self,
|
|
|
|
|
+ mint_url: MintUrl,
|
|
|
|
|
+ mint_info: Option<MintInfo>,
|
|
|
|
|
+ ) -> Result<(), Error> {
|
|
|
|
|
+ match self {
|
|
|
|
|
+ Self::Db(db) => {
|
|
|
|
|
+ let mut new_tx = db.begin_db_transaction().await?;
|
|
|
|
|
+ new_tx.add_mint(mint_url, mint_info).await?;
|
|
|
|
|
+ new_tx.commit().await?;
|
|
|
|
|
+ Ok(())
|
|
|
|
|
+ }
|
|
|
|
|
+ Self::Tx(tx) => tx.add_mint(mint_url, mint_info).await,
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /// Get keys - automatically uses transaction or connection
|
|
|
|
|
+ pub async fn get_keys(&mut self, keyset_id: &Id) -> Result<Option<Keys>, Error> {
|
|
|
|
|
+ match self {
|
|
|
|
|
+ Self::Db(db) => db.get_keys(keyset_id).await,
|
|
|
|
|
+ Self::Tx(tx) => tx.get_keys(keyset_id).await,
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /// Add keys - automatically uses transaction or connection
|
|
|
|
|
+ pub async fn add_keys(&mut self, keys: KeySet) -> Result<(), Error> {
|
|
|
|
|
+ match self {
|
|
|
|
|
+ Self::Db(db) => {
|
|
|
|
|
+ // For non-transactional context, create and commit a transaction
|
|
|
|
|
+ let mut new_tx = db.begin_db_transaction().await?;
|
|
|
|
|
+ new_tx.add_keys(keys).await?;
|
|
|
|
|
+ new_tx.commit().await?;
|
|
|
|
|
+ Ok(())
|
|
|
|
|
+ }
|
|
|
|
|
+ Self::Tx(tx) => tx.add_keys(keys).await,
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /// Get mint keysets - automatically uses transaction or connection
|
|
|
|
|
+ pub async fn get_mint_keysets(
|
|
|
|
|
+ &mut self,
|
|
|
|
|
+ mint_url: MintUrl,
|
|
|
|
|
+ ) -> Result<Option<Vec<KeySetInfo>>, Error> {
|
|
|
|
|
+ match self {
|
|
|
|
|
+ Self::Db(db) => db.get_mint_keysets(mint_url).await,
|
|
|
|
|
+ Self::Tx(tx) => tx.get_mint_keysets(mint_url).await,
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /// Add mint keysets - automatically uses transaction or connection
|
|
|
|
|
+ pub async fn add_mint_keysets(
|
|
|
|
|
+ &mut self,
|
|
|
|
|
+ mint_url: MintUrl,
|
|
|
|
|
+ keysets: Vec<KeySetInfo>,
|
|
|
|
|
+ ) -> Result<(), Error> {
|
|
|
|
|
+ match self {
|
|
|
|
|
+ Self::Db(db) => {
|
|
|
|
|
+ let mut new_tx = db.begin_db_transaction().await?;
|
|
|
|
|
+ new_tx.add_mint_keysets(mint_url, keysets).await?;
|
|
|
|
|
+ new_tx.commit().await?;
|
|
|
|
|
+ Ok(())
|
|
|
|
|
+ }
|
|
|
|
|
+ Self::Tx(tx) => tx.add_mint_keysets(mint_url, keysets).await,
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /// Get proofs - automatically uses transaction or connection
|
|
|
|
|
+ pub async fn get_proofs(
|
|
|
|
|
+ &mut self,
|
|
|
|
|
+ mint_url: Option<MintUrl>,
|
|
|
|
|
+ unit: Option<CurrencyUnit>,
|
|
|
|
|
+ state: Option<Vec<State>>,
|
|
|
|
|
+ spending_conditions: Option<Vec<SpendingConditions>>,
|
|
|
|
|
+ ) -> Result<Vec<ProofInfo>, Error> {
|
|
|
|
|
+ match self {
|
|
|
|
|
+ Self::Db(db) => {
|
|
|
|
|
+ db.get_proofs(mint_url, unit, state, spending_conditions)
|
|
|
|
|
+ .await
|
|
|
|
|
+ }
|
|
|
|
|
+ Self::Tx(tx) => {
|
|
|
|
|
+ tx.get_proofs(mint_url, unit, state, spending_conditions)
|
|
|
|
|
+ .await
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /// Update proofs - automatically uses transaction or connection
|
|
|
|
|
+ pub async fn update_proofs(
|
|
|
|
|
+ &mut self,
|
|
|
|
|
+ proofs: Vec<ProofInfo>,
|
|
|
|
|
+ spent_proofs: Vec<PublicKey>,
|
|
|
|
|
+ ) -> Result<(), Error> {
|
|
|
|
|
+ match self {
|
|
|
|
|
+ Self::Db(db) => {
|
|
|
|
|
+ let mut new_tx = db.begin_db_transaction().await?;
|
|
|
|
|
+ new_tx.update_proofs(proofs, spent_proofs).await?;
|
|
|
|
|
+ new_tx.commit().await?;
|
|
|
|
|
+ Ok(())
|
|
|
|
|
+ }
|
|
|
|
|
+ Self::Tx(tx) => tx.update_proofs(proofs, spent_proofs).await,
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /// Update proofs state - automatically uses transaction or connection
|
|
|
|
|
+ pub async fn update_proofs_state(
|
|
|
|
|
+ &mut self,
|
|
|
|
|
+ ys: Vec<PublicKey>,
|
|
|
|
|
+ state: State,
|
|
|
|
|
+ ) -> Result<(), Error> {
|
|
|
|
|
+ match self {
|
|
|
|
|
+ Self::Db(db) => {
|
|
|
|
|
+ let mut new_tx = db.begin_db_transaction().await?;
|
|
|
|
|
+ new_tx.update_proofs_state(ys, state).await?;
|
|
|
|
|
+ new_tx.commit().await?;
|
|
|
|
|
+ Ok(())
|
|
|
|
|
+ }
|
|
|
|
|
+ Self::Tx(tx) => tx.update_proofs_state(ys, state).await,
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /// Remove transaction - automatically uses transaction or connection
|
|
|
|
|
+ pub async fn remove_transaction(&mut self, transaction_id: TransactionId) -> Result<(), Error> {
|
|
|
|
|
+ match self {
|
|
|
|
|
+ Self::Db(db) => {
|
|
|
|
|
+ let mut new_tx = db.begin_db_transaction().await?;
|
|
|
|
|
+ new_tx.remove_transaction(transaction_id).await?;
|
|
|
|
|
+ new_tx.commit().await?;
|
|
|
|
|
+ Ok(())
|
|
|
|
|
+ }
|
|
|
|
|
+ Self::Tx(tx) => tx.remove_transaction(transaction_id).await,
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|