Explorar o código

Add get_keys from the transaction

Cesar Rodas hai 1 mes
pai
achega
c7d00238cb

+ 3 - 0
crates/cdk-common/src/database/wallet.rs

@@ -22,6 +22,9 @@ use crate::wallet::{
 #[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
 #[cfg_attr(not(target_arch = "wasm32"), async_trait)]
 pub trait DatabaseTransaction<'a, Error>: DbTransactionFinalizer<Err = Error> {
+    /// Get [`Keys`] from storage
+    async fn get_keys(&mut self, id: &Id) -> Result<Option<Keys>, Self::Err>;
+
     /// Add Mint to storage
     async fn add_mint(
         &mut self,

+ 25 - 1
crates/cdk-ffi/src/database.rs

@@ -177,6 +177,27 @@ struct WalletDatabaseTransactionBridge {
 impl<'a> cdk::cdk_database::WalletDatabaseTransaction<'a, cdk::cdk_database::Error>
     for WalletDatabaseTransactionBridge
 {
+    async fn get_keys(
+        &mut self,
+        id: &cdk::nuts::Id,
+    ) -> Result<Option<cdk::nuts::Keys>, cdk::cdk_database::Error> {
+        let ffi_id: Id = (*id).into();
+        let result = self
+            .ffi_db
+            .get_keys(ffi_id)
+            .await
+            .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))?;
+
+        // Convert FFI Keys back to CDK Keys using TryFrom
+        result
+            .map(|ffi_keys| {
+                ffi_keys
+                    .try_into()
+                    .map_err(|e: FfiError| cdk::cdk_database::Error::Database(e.to_string().into()))
+            })
+            .transpose()
+    }
+
     async fn add_mint(
         &mut self,
         mint_url: cdk::mint_url::MintUrl,
@@ -289,7 +310,10 @@ impl<'a> cdk::cdk_database::WalletDatabaseTransaction<'a, cdk::cdk_database::Err
             .map_err(|e| cdk::cdk_database::Error::Database(e.to_string().into()))
     }
 
-    async fn add_keys(&mut self, keyset: cdk::nuts::KeySet) -> Result<(), cdk::cdk_database::Error> {
+    async fn add_keys(
+        &mut self,
+        keyset: cdk::nuts::KeySet,
+    ) -> Result<(), cdk::cdk_database::Error> {
         let ffi_keyset = keyset.into();
         self.ffi_db
             .add_keys(ffi_keyset)

+ 15 - 0
crates/cdk-redb/src/wallet/mod.rs

@@ -485,6 +485,21 @@ impl WalletDatabase for WalletRedbDatabase {
 impl<'a> cdk_common::database::WalletDatabaseTransaction<'a, database::Error>
     for RedbWalletTransaction
 {
+    #[instrument(skip(self), fields(keyset_id = %keyset_id))]
+    async fn get_keys(&mut self, keyset_id: &Id) -> Result<Option<Keys>, Self::Err> {
+        let txn = self.txn().map_err(Into::<database::Error>::into)?;
+        let table = txn.open_table(MINT_KEYS_TABLE).map_err(Error::from)?;
+
+        if let Some(mint_info) = table
+            .get(keyset_id.to_string().as_str())
+            .map_err(Error::from)?
+        {
+            return Ok(serde_json::from_str(mint_info.value()).map_err(Error::from)?);
+        }
+
+        Ok(None)
+    }
+
     #[instrument(skip(self, mint_info))]
     async fn add_mint(
         &mut self,

+ 21 - 0
crates/cdk-sql-common/src/wallet/mod.rs

@@ -152,6 +152,27 @@ impl<'a, RM> WalletDatabaseTransaction<'a, Error> for SQLWalletTransaction<RM>
 where
     RM: DatabasePool + 'static,
 {
+    /// Read the key from a transaction but it will not lock it
+    #[instrument(skip(self), fields(keyset_id = %keyset_id))]
+    async fn get_keys(&mut self, keyset_id: &Id) -> Result<Option<Keys>, Error> {
+        Ok(query(
+            r#"
+            SELECT
+                keys
+            FROM key
+            WHERE id = :id
+            "#,
+        )?
+        .bind("id", keyset_id.to_string())
+        .pluck(&self.inner)
+        .await?
+        .map(|keys| {
+            let keys = column_as_string!(keys);
+            serde_json::from_str(&keys).map_err(Error::from)
+        })
+        .transpose()?)
+    }
+
     #[instrument(skip(self, mint_info))]
     async fn add_mint(
         &mut self,

+ 35 - 16
crates/cdk/src/wallet/keysets.rs

@@ -20,28 +20,40 @@ impl Wallet {
         keyset_id: Id,
         tx: Option<&mut Tx<'_, '_>>,
     ) -> Result<Keys, Error> {
-        let keys = if let Some(keys) = self.localstore.get_keys(&keyset_id).await? {
-            keys
-        } else {
-            tracing::debug!(
-                "Keyset {} not in db fetching from mint {}",
-                keyset_id,
-                self.mint_url
-            );
-
-            let keys = self.client.get_mint_keyset(keyset_id).await?;
+        let keys = if let Some(tx) = tx {
+            if let Some(keys) = tx.get_keys(&keyset_id).await? {
+                keys
+            } else {
+                tracing::debug!(
+                    "Keyset {} not in db fetching from mint {}",
+                    keyset_id,
+                    self.mint_url
+                );
 
-            keys.verify_id()?;
+                let keys = self.client.get_mint_keyset(keyset_id).await?;
 
-            if let Some(tx) = tx {
+                keys.verify_id()?;
                 tx.add_keys(keys.clone()).await?;
+                keys.keys
+            }
+        } else {
+            if let Some(keys) = self.localstore.get_keys(&keyset_id).await? {
+                keys
             } else {
+                tracing::debug!(
+                    "Keyset {} not in db fetching from mint {}",
+                    keyset_id,
+                    self.mint_url
+                );
+
+                let keys = self.client.get_mint_keyset(keyset_id).await?;
+
+                keys.verify_id()?;
                 let mut tx = self.localstore.begin_db_transaction().await?;
                 tx.add_keys(keys.clone()).await?;
                 tx.commit().await?;
+                keys.keys
             }
-
-            keys.keys
         };
 
         Ok(keys)
@@ -95,14 +107,21 @@ impl Wallet {
     #[instrument(skip(self, tx))]
     pub async fn refresh_keysets(&self, tx: Option<&mut Tx<'_, '_>>) -> Result<KeySetInfos, Error> {
         tracing::debug!("Refreshing keysets and ensuring we have keys");
-        let _ = self.fetch_mint_info(None).await?;
+
+        let mut tx = tx;
+        let _ = self
+            .fetch_mint_info(if let Some(tx) = tx.as_mut() {
+                Some(*tx)
+            } else {
+                None
+            })
+            .await?;
 
         // Fetch all current keysets from mint
         let keysets_response = self.client.get_mint_keysets().await?;
         let all_keysets = keysets_response.keysets;
 
         // Update local storage with keyset info
-        let mut tx = tx;
         if let Some(tx) = tx.as_mut() {
             tx.add_mint_keysets(self.mint_url.clone(), all_keysets.clone())
                 .await?;