|
|
@@ -13,30 +13,36 @@ impl Wallet {
|
|
|
///
|
|
|
/// Returns keys from local database if they are already stored.
|
|
|
/// If keys are not found locally, goes online to query the mint for the keyset and stores the [`Keys`] in local database.
|
|
|
+ #[instrument(skip(self))]
|
|
|
+ pub async fn load_keyset_keys(&self, keyset_id: Id) -> Result<Keys, Error> {
|
|
|
+ if let Some(keys) = self.localstore.get_keys(&keyset_id).await? {
|
|
|
+ Ok(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?;
|
|
|
+ Ok(keys.keys)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// Load keyset keys with transaction
|
|
|
#[instrument(skip(self, tx))]
|
|
|
- pub async fn load_keyset_keys(
|
|
|
+ pub async fn load_keyset_keys_with_tx(
|
|
|
&self,
|
|
|
+ tx: &mut Tx<'_, '_>,
|
|
|
keyset_id: Id,
|
|
|
- tx: Option<&mut Tx<'_, '_>>,
|
|
|
) -> Result<Keys, Error> {
|
|
|
- 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
|
|
|
- );
|
|
|
-
|
|
|
- let keys = self.client.get_mint_keyset(keyset_id).await?;
|
|
|
-
|
|
|
- keys.verify_id()?;
|
|
|
- tx.add_keys(keys.clone()).await?;
|
|
|
- keys.keys
|
|
|
- }
|
|
|
- } else if let Some(keys) = self.localstore.get_keys(&keyset_id).await? {
|
|
|
- keys
|
|
|
+ if let Some(keys) = tx.get_keys(&keyset_id).await? {
|
|
|
+ Ok(keys)
|
|
|
} else {
|
|
|
tracing::debug!(
|
|
|
"Keyset {} not in db fetching from mint {}",
|
|
|
@@ -47,13 +53,9 @@ impl Wallet {
|
|
|
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
|
|
|
- };
|
|
|
-
|
|
|
- Ok(keys)
|
|
|
+ Ok(keys.keys)
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/// Get keysets from local database or go online if missing
|
|
|
@@ -72,7 +74,7 @@ impl Wallet {
|
|
|
Some(keysets_info) => Ok(keysets_info),
|
|
|
None => {
|
|
|
// If we don't have any keysets, fetch them from the mint
|
|
|
- let keysets = self.refresh_keysets(None).await?;
|
|
|
+ let keysets = self.refresh_keysets().await?;
|
|
|
Ok(keysets)
|
|
|
}
|
|
|
}
|
|
|
@@ -97,48 +99,41 @@ impl Wallet {
|
|
|
|
|
|
/// Refresh keysets by fetching the latest from mint - always goes online
|
|
|
///
|
|
|
+ /// Refresh keysets from mint
|
|
|
+ ///
|
|
|
/// This method always goes online to fetch the latest keyset information from the mint.
|
|
|
/// It updates the local database with the fetched keysets and ensures we have keys
|
|
|
/// for all active keysets. This is used when operations need the most up-to-date
|
|
|
/// keyset information and are willing to go online.
|
|
|
+ #[instrument(skip(self))]
|
|
|
+ pub async fn refresh_keysets(&self) -> Result<KeySetInfos, Error> {
|
|
|
+ let mut tx = self.localstore.begin_db_transaction().await?;
|
|
|
+ let result = self.refresh_keysets_with_tx(&mut tx).await?;
|
|
|
+ tx.commit().await?;
|
|
|
+ Ok(result)
|
|
|
+ }
|
|
|
+
|
|
|
+ /// Refresh keysets from mint with transaction
|
|
|
#[instrument(skip(self, tx))]
|
|
|
- pub async fn refresh_keysets(&self, tx: Option<&mut Tx<'_, '_>>) -> Result<KeySetInfos, Error> {
|
|
|
+ pub async fn refresh_keysets_with_tx(&self, tx: &mut Tx<'_, '_>) -> Result<KeySetInfos, Error> {
|
|
|
tracing::debug!("Refreshing keysets and ensuring we have keys");
|
|
|
|
|
|
- let mut tx = tx;
|
|
|
- let _ = self
|
|
|
- .fetch_mint_info(if let Some(tx) = tx.as_mut() {
|
|
|
- Some(*tx)
|
|
|
- } else {
|
|
|
- None
|
|
|
- })
|
|
|
- .await?;
|
|
|
+ let _ = self.fetch_mint_info_with_tx(tx).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
|
|
|
- if let Some(tx) = tx.as_mut() {
|
|
|
- tx.add_mint_keysets(self.mint_url.clone(), all_keysets.clone())
|
|
|
- .await?;
|
|
|
- } else {
|
|
|
- let mut tx = self.localstore.begin_db_transaction().await?;
|
|
|
- tx.add_mint_keysets(self.mint_url.clone(), all_keysets.clone())
|
|
|
- .await?;
|
|
|
- tx.commit().await?;
|
|
|
- }
|
|
|
+ tx.add_mint_keysets(self.mint_url.clone(), all_keysets.clone())
|
|
|
+ .await?;
|
|
|
|
|
|
// Filter for active keysets matching our unit
|
|
|
let keysets: KeySetInfos = all_keysets.unit(self.unit.clone()).cloned().collect();
|
|
|
|
|
|
// Ensure we have keys for all active keysets
|
|
|
for keyset in &keysets {
|
|
|
- if let Some(tx) = tx.as_mut() {
|
|
|
- self.load_keyset_keys(keyset.id, Some(*tx)).await?;
|
|
|
- } else {
|
|
|
- self.load_keyset_keys(keyset.id, None).await?;
|
|
|
- }
|
|
|
+ self.load_keyset_keys_with_tx(tx, keyset.id).await?;
|
|
|
}
|
|
|
|
|
|
Ok(keysets)
|
|
|
@@ -149,12 +144,23 @@ impl Wallet {
|
|
|
/// This method always goes online to refresh keysets from the mint and then returns
|
|
|
/// the active keyset with the minimum input fees. Use this when you need the most
|
|
|
/// up-to-date keyset information for operations.
|
|
|
+ #[instrument(skip(self))]
|
|
|
+ pub async fn fetch_active_keyset(&self) -> Result<KeySetInfo, Error> {
|
|
|
+ self.refresh_keysets()
|
|
|
+ .await?
|
|
|
+ .active()
|
|
|
+ .min_by_key(|k| k.input_fee_ppk)
|
|
|
+ .cloned()
|
|
|
+ .ok_or(Error::NoActiveKeyset)
|
|
|
+ }
|
|
|
+
|
|
|
+ /// Get the active keyset with the lowest fees with transaction - always goes online
|
|
|
#[instrument(skip(self, tx))]
|
|
|
- pub async fn fetch_active_keyset(
|
|
|
+ pub async fn fetch_active_keyset_with_tx(
|
|
|
&self,
|
|
|
- tx: Option<&mut Tx<'_, '_>>,
|
|
|
+ tx: &mut Tx<'_, '_>,
|
|
|
) -> Result<KeySetInfo, Error> {
|
|
|
- self.refresh_keysets(tx)
|
|
|
+ self.refresh_keysets_with_tx(tx)
|
|
|
.await?
|
|
|
.active()
|
|
|
.min_by_key(|k| k.input_fee_ppk)
|
|
|
@@ -187,21 +193,41 @@ impl Wallet {
|
|
|
/// Returns a HashMap of keyset IDs to their input fee rates (per-proof-per-thousand)
|
|
|
/// from cached keysets in the local database. This is an offline operation that does
|
|
|
/// not contact the mint. If no keysets are found locally, returns an error.
|
|
|
- pub async fn get_keyset_fees_and_amounts(
|
|
|
+ pub async fn get_keyset_fees_and_amounts(&self) -> Result<KeysetFeeAndAmounts, Error> {
|
|
|
+ let keysets = self
|
|
|
+ .localstore
|
|
|
+ .get_mint_keysets(self.mint_url.clone())
|
|
|
+ .await?
|
|
|
+ .ok_or(Error::UnknownKeySet)?;
|
|
|
+
|
|
|
+ let mut fees = HashMap::new();
|
|
|
+ for keyset in keysets {
|
|
|
+ fees.insert(
|
|
|
+ keyset.id,
|
|
|
+ (
|
|
|
+ keyset.input_fee_ppk,
|
|
|
+ self.load_keyset_keys(keyset.id)
|
|
|
+ .await?
|
|
|
+ .iter()
|
|
|
+ .map(|(amount, _)| amount.to_u64())
|
|
|
+ .collect::<Vec<_>>(),
|
|
|
+ )
|
|
|
+ .into(),
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ Ok(fees)
|
|
|
+ }
|
|
|
+
|
|
|
+ /// Get keyset fees and amounts for mint with transaction
|
|
|
+ pub async fn get_keyset_fees_and_amounts_with_tx(
|
|
|
&self,
|
|
|
- tx: Option<&mut Tx<'_, '_>>,
|
|
|
+ tx: &mut Tx<'_, '_>,
|
|
|
) -> Result<KeysetFeeAndAmounts, Error> {
|
|
|
- let mut tx = tx;
|
|
|
- let keysets = if let Some(tx) = tx.as_mut() {
|
|
|
- tx.get_mint_keysets(self.mint_url.clone())
|
|
|
- .await?
|
|
|
- .ok_or(Error::UnknownKeySet)?
|
|
|
- } else {
|
|
|
- self.localstore
|
|
|
- .get_mint_keysets(self.mint_url.clone())
|
|
|
- .await?
|
|
|
- .ok_or(Error::UnknownKeySet)?
|
|
|
- };
|
|
|
+ let keysets = tx
|
|
|
+ .get_mint_keysets(self.mint_url.clone())
|
|
|
+ .await?
|
|
|
+ .ok_or(Error::UnknownKeySet)?;
|
|
|
|
|
|
let mut fees = HashMap::new();
|
|
|
for keyset in keysets {
|
|
|
@@ -209,18 +235,11 @@ impl Wallet {
|
|
|
keyset.id,
|
|
|
(
|
|
|
keyset.input_fee_ppk,
|
|
|
- self.load_keyset_keys(
|
|
|
- keyset.id,
|
|
|
- if let Some(tx) = tx.as_mut() {
|
|
|
- Some(*tx)
|
|
|
- } else {
|
|
|
- None
|
|
|
- },
|
|
|
- )
|
|
|
- .await?
|
|
|
- .iter()
|
|
|
- .map(|(amount, _)| amount.to_u64())
|
|
|
- .collect::<Vec<_>>(),
|
|
|
+ self.load_keyset_keys_with_tx(tx, keyset.id)
|
|
|
+ .await?
|
|
|
+ .iter()
|
|
|
+ .map(|(amount, _)| amount.to_u64())
|
|
|
+ .collect::<Vec<_>>(),
|
|
|
)
|
|
|
.into(),
|
|
|
);
|
|
|
@@ -237,9 +256,21 @@ impl Wallet {
|
|
|
pub async fn get_keyset_fees_and_amounts_by_id(
|
|
|
&self,
|
|
|
keyset_id: Id,
|
|
|
- tx: Option<&mut Tx<'_, '_>>,
|
|
|
) -> Result<FeeAndAmounts, Error> {
|
|
|
- self.get_keyset_fees_and_amounts(tx)
|
|
|
+ self.get_keyset_fees_and_amounts()
|
|
|
+ .await?
|
|
|
+ .get(&keyset_id)
|
|
|
+ .cloned()
|
|
|
+ .ok_or(Error::UnknownKeySet)
|
|
|
+ }
|
|
|
+
|
|
|
+ /// Get keyset fees and amounts for mint by keyset id with transaction
|
|
|
+ pub async fn get_keyset_fees_and_amounts_by_id_with_tx(
|
|
|
+ &self,
|
|
|
+ tx: &mut Tx<'_, '_>,
|
|
|
+ keyset_id: Id,
|
|
|
+ ) -> Result<FeeAndAmounts, Error> {
|
|
|
+ self.get_keyset_fees_and_amounts_with_tx(tx)
|
|
|
.await?
|
|
|
.get(&keyset_id)
|
|
|
.cloned()
|