mirror of
https://github.com/aljazceru/cdk.git
synced 2026-02-02 03:35:57 +01:00
Configure internal Wallets of a MultiMintWallet (#1177)
This commit is contained in:
@@ -29,19 +29,13 @@ pub async fn cat_device_login(
|
||||
) -> Result<()> {
|
||||
let mint_url = sub_command_args.mint_url.clone();
|
||||
|
||||
let wallet = match multi_mint_wallet.get_wallet(&mint_url).await {
|
||||
Some(wallet) => wallet.clone(),
|
||||
None => {
|
||||
multi_mint_wallet.add_mint(mint_url.clone(), None).await?;
|
||||
multi_mint_wallet
|
||||
.get_wallet(&mint_url)
|
||||
.await
|
||||
.expect("Wallet should exist after adding mint")
|
||||
}
|
||||
};
|
||||
// Ensure the mint exists
|
||||
if !multi_mint_wallet.has_mint(&mint_url).await {
|
||||
multi_mint_wallet.add_mint(mint_url.clone()).await?;
|
||||
}
|
||||
|
||||
let mint_info = wallet
|
||||
.fetch_mint_info()
|
||||
let mint_info = multi_mint_wallet
|
||||
.fetch_mint_info(&mint_url)
|
||||
.await?
|
||||
.ok_or(anyhow!("Mint info not found"))?;
|
||||
|
||||
|
||||
@@ -31,20 +31,13 @@ pub async fn cat_login(
|
||||
) -> Result<()> {
|
||||
let mint_url = sub_command_args.mint_url.clone();
|
||||
|
||||
let wallet = match multi_mint_wallet.get_wallet(&mint_url).await {
|
||||
Some(wallet) => wallet.clone(),
|
||||
None => {
|
||||
multi_mint_wallet.add_mint(mint_url.clone(), None).await?;
|
||||
multi_mint_wallet
|
||||
.get_wallet(&mint_url)
|
||||
.await
|
||||
.expect("Wallet should exist after adding mint")
|
||||
.clone()
|
||||
}
|
||||
};
|
||||
// Ensure the mint exists
|
||||
if !multi_mint_wallet.has_mint(&mint_url).await {
|
||||
multi_mint_wallet.add_mint(mint_url.clone()).await?;
|
||||
}
|
||||
|
||||
let mint_info = wallet
|
||||
.fetch_mint_info()
|
||||
let mint_info = multi_mint_wallet
|
||||
.fetch_mint_info(&mint_url)
|
||||
.await?
|
||||
.ok_or(anyhow!("Mint info not found"))?;
|
||||
|
||||
|
||||
@@ -28,19 +28,12 @@ pub async fn mint_blind_auth(
|
||||
) -> Result<()> {
|
||||
let mint_url = sub_command_args.mint_url.clone();
|
||||
|
||||
let wallet = match multi_mint_wallet.get_wallet(&mint_url).await {
|
||||
Some(wallet) => wallet.clone(),
|
||||
None => {
|
||||
multi_mint_wallet.add_mint(mint_url.clone(), None).await?;
|
||||
multi_mint_wallet
|
||||
.get_wallet(&mint_url)
|
||||
.await
|
||||
.expect("Wallet should exist after adding mint")
|
||||
.clone()
|
||||
}
|
||||
};
|
||||
// Ensure the mint exists
|
||||
if !multi_mint_wallet.has_mint(&mint_url).await {
|
||||
multi_mint_wallet.add_mint(mint_url.clone()).await?;
|
||||
}
|
||||
|
||||
wallet.fetch_mint_info().await?;
|
||||
multi_mint_wallet.fetch_mint_info(&mint_url).await?;
|
||||
|
||||
// Try to get the token from the provided argument or from the stored file
|
||||
let cat = match &sub_command_args.cat {
|
||||
@@ -68,7 +61,7 @@ pub async fn mint_blind_auth(
|
||||
};
|
||||
|
||||
// Try to set the access token
|
||||
if let Err(err) = wallet.set_cat(cat.clone()).await {
|
||||
if let Err(err) = multi_mint_wallet.set_cat(&mint_url, cat.clone()).await {
|
||||
tracing::error!("Could not set cat: {}", err);
|
||||
|
||||
// Try to refresh the token if we have a refresh token
|
||||
@@ -76,7 +69,7 @@ pub async fn mint_blind_auth(
|
||||
println!("Attempting to refresh the access token...");
|
||||
|
||||
// Get the mint info to access OIDC configuration
|
||||
if let Some(mint_info) = wallet.fetch_mint_info().await? {
|
||||
if let Some(mint_info) = multi_mint_wallet.fetch_mint_info(&mint_url).await? {
|
||||
match refresh_access_token(&mint_info, &token_data.refresh_token).await {
|
||||
Ok((new_access_token, new_refresh_token)) => {
|
||||
println!("Successfully refreshed access token");
|
||||
@@ -94,7 +87,9 @@ pub async fn mint_blind_auth(
|
||||
}
|
||||
|
||||
// Try setting the new access token
|
||||
if let Err(err) = wallet.set_cat(new_access_token).await {
|
||||
if let Err(err) =
|
||||
multi_mint_wallet.set_cat(&mint_url, new_access_token).await
|
||||
{
|
||||
tracing::error!("Could not set refreshed cat: {}", err);
|
||||
return Err(anyhow::anyhow!(
|
||||
"Authentication failed even after token refresh"
|
||||
@@ -102,7 +97,9 @@ pub async fn mint_blind_auth(
|
||||
}
|
||||
|
||||
// Set the refresh token
|
||||
wallet.set_refresh_token(new_refresh_token).await?;
|
||||
multi_mint_wallet
|
||||
.set_refresh_token(&mint_url, new_refresh_token)
|
||||
.await?;
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::error!("Failed to refresh token: {}", e);
|
||||
@@ -119,8 +116,10 @@ pub async fn mint_blind_auth(
|
||||
// If we have a refresh token, set it
|
||||
if let Ok(Some(token_data)) = token_storage::get_token_for_mint(work_dir, &mint_url).await {
|
||||
tracing::info!("Attempting to use refresh access token to refresh auth token");
|
||||
wallet.set_refresh_token(token_data.refresh_token).await?;
|
||||
wallet.refresh_access_token().await?;
|
||||
multi_mint_wallet
|
||||
.set_refresh_token(&mint_url, token_data.refresh_token)
|
||||
.await?;
|
||||
multi_mint_wallet.refresh_access_token(&mint_url).await?;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,8 +128,8 @@ pub async fn mint_blind_auth(
|
||||
let amount = match sub_command_args.amount {
|
||||
Some(amount) => amount,
|
||||
None => {
|
||||
let mint_info = wallet
|
||||
.fetch_mint_info()
|
||||
let mint_info = multi_mint_wallet
|
||||
.fetch_mint_info(&mint_url)
|
||||
.await?
|
||||
.ok_or(anyhow!("Unknown mint info"))?;
|
||||
mint_info
|
||||
@@ -139,7 +138,9 @@ pub async fn mint_blind_auth(
|
||||
}
|
||||
};
|
||||
|
||||
let proofs = wallet.mint_blind_auth(Amount::from(amount)).await?;
|
||||
let proofs = multi_mint_wallet
|
||||
.mint_blind_auth(&mint_url, Amount::from(amount))
|
||||
.await?;
|
||||
|
||||
println!("Received {} auth proofs for mint {mint_url}", proofs.len());
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ pub async fn restore(
|
||||
let wallet = match multi_mint_wallet.get_wallet(&mint_url).await {
|
||||
Some(wallet) => wallet.clone(),
|
||||
None => {
|
||||
multi_mint_wallet.add_mint(mint_url.clone(), None).await?;
|
||||
multi_mint_wallet.add_mint(mint_url.clone()).await?;
|
||||
multi_mint_wallet
|
||||
.get_wallet(&mint_url)
|
||||
.await
|
||||
|
||||
@@ -34,7 +34,7 @@ pub async fn get_or_create_wallet(
|
||||
Some(wallet) => Ok(wallet.clone()),
|
||||
None => {
|
||||
tracing::debug!("Wallet does not exist creating..");
|
||||
multi_mint_wallet.add_mint(mint_url.clone(), None).await?;
|
||||
multi_mint_wallet.add_mint(mint_url.clone()).await?;
|
||||
Ok(multi_mint_wallet
|
||||
.get_wallet(mint_url)
|
||||
.await
|
||||
|
||||
@@ -118,9 +118,16 @@ impl MultiMintWallet {
|
||||
target_proof_count: Option<u32>,
|
||||
) -> Result<(), FfiError> {
|
||||
let cdk_mint_url: cdk::mint_url::MintUrl = mint_url.try_into()?;
|
||||
self.inner
|
||||
.add_mint(cdk_mint_url, target_proof_count.map(|c| c as usize))
|
||||
.await?;
|
||||
|
||||
if let Some(count) = target_proof_count {
|
||||
let config = cdk::wallet::multi_mint_wallet::WalletConfig::new()
|
||||
.with_target_proof_count(count as usize);
|
||||
self.inner
|
||||
.add_mint_with_config(cdk_mint_url, config)
|
||||
.await?;
|
||||
} else {
|
||||
self.inner.add_mint(cdk_mint_url).await?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -380,6 +387,68 @@ impl MultiMintWallet {
|
||||
self.inner.verify_token_dleq(&cdk_token).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Query mint for current mint information
|
||||
pub async fn fetch_mint_info(&self, mint_url: MintUrl) -> Result<Option<MintInfo>, FfiError> {
|
||||
let cdk_mint_url: cdk::mint_url::MintUrl = mint_url.try_into()?;
|
||||
let mint_info = self.inner.fetch_mint_info(&cdk_mint_url).await?;
|
||||
Ok(mint_info.map(Into::into))
|
||||
}
|
||||
}
|
||||
|
||||
/// Auth methods for MultiMintWallet
|
||||
#[uniffi::export(async_runtime = "tokio")]
|
||||
impl MultiMintWallet {
|
||||
/// Set Clear Auth Token (CAT) for a specific mint
|
||||
pub async fn set_cat(&self, mint_url: MintUrl, cat: String) -> Result<(), FfiError> {
|
||||
let cdk_mint_url: cdk::mint_url::MintUrl = mint_url.try_into()?;
|
||||
self.inner.set_cat(&cdk_mint_url, cat).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Set refresh token for a specific mint
|
||||
pub async fn set_refresh_token(
|
||||
&self,
|
||||
mint_url: MintUrl,
|
||||
refresh_token: String,
|
||||
) -> Result<(), FfiError> {
|
||||
let cdk_mint_url: cdk::mint_url::MintUrl = mint_url.try_into()?;
|
||||
self.inner
|
||||
.set_refresh_token(&cdk_mint_url, refresh_token)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Refresh access token for a specific mint using the stored refresh token
|
||||
pub async fn refresh_access_token(&self, mint_url: MintUrl) -> Result<(), FfiError> {
|
||||
let cdk_mint_url: cdk::mint_url::MintUrl = mint_url.try_into()?;
|
||||
self.inner.refresh_access_token(&cdk_mint_url).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Mint blind auth tokens at a specific mint
|
||||
pub async fn mint_blind_auth(
|
||||
&self,
|
||||
mint_url: MintUrl,
|
||||
amount: Amount,
|
||||
) -> Result<Proofs, FfiError> {
|
||||
let cdk_mint_url: cdk::mint_url::MintUrl = mint_url.try_into()?;
|
||||
let proofs = self
|
||||
.inner
|
||||
.mint_blind_auth(&cdk_mint_url, amount.into())
|
||||
.await?;
|
||||
Ok(proofs.into_iter().map(|p| Arc::new(p.into())).collect())
|
||||
}
|
||||
|
||||
/// Get unspent auth proofs for a specific mint
|
||||
pub async fn get_unspent_auth_proofs(
|
||||
&self,
|
||||
mint_url: MintUrl,
|
||||
) -> Result<Vec<AuthProof>, FfiError> {
|
||||
let cdk_mint_url: cdk::mint_url::MintUrl = mint_url.try_into()?;
|
||||
let auth_proofs = self.inner.get_unspent_auth_proofs(&cdk_mint_url).await?;
|
||||
Ok(auth_proofs.into_iter().map(Into::into).collect())
|
||||
}
|
||||
}
|
||||
|
||||
/// Transfer mode for mint-to-mint transfers
|
||||
|
||||
@@ -65,4 +65,17 @@ impl Wallet {
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Set the auth client (AuthWallet) for this wallet
|
||||
///
|
||||
/// This allows updating the auth wallet without recreating the wallet.
|
||||
/// Also updates the client's auth wallet to keep them in sync.
|
||||
#[instrument(skip_all)]
|
||||
pub async fn set_auth_client(&self, auth_wallet: Option<AuthWallet>) {
|
||||
let mut auth_wallet_guard = self.auth_wallet.write().await;
|
||||
*auth_wallet_guard = auth_wallet.clone();
|
||||
|
||||
// Also update the client's auth wallet to keep them in sync
|
||||
self.client.set_auth_wallet(auth_wallet).await;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -673,6 +673,20 @@ impl Wallet {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Set the client (MintConnector) for this wallet
|
||||
///
|
||||
/// This allows updating the connector without recreating the wallet.
|
||||
pub fn set_client(&mut self, client: Arc<dyn MintConnector + Send + Sync>) {
|
||||
self.client = client;
|
||||
}
|
||||
|
||||
/// Set the target proof count for this wallet
|
||||
///
|
||||
/// This controls how many proofs of each denomination the wallet tries to maintain.
|
||||
pub fn set_target_proof_count(&mut self, count: usize) {
|
||||
self.target_proof_count = count;
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Wallet {
|
||||
|
||||
@@ -60,6 +60,50 @@ pub struct TransferResult {
|
||||
pub target_balance_after: Amount,
|
||||
}
|
||||
|
||||
/// Configuration for individual wallets within MultiMintWallet
|
||||
#[derive(Clone, Default, Debug)]
|
||||
pub struct WalletConfig {
|
||||
/// Custom mint connector implementation
|
||||
pub mint_connector: Option<Arc<dyn super::MintConnector + Send + Sync>>,
|
||||
/// Custom auth connector implementation
|
||||
#[cfg(feature = "auth")]
|
||||
pub auth_connector: Option<Arc<dyn super::auth::AuthMintConnector + Send + Sync>>,
|
||||
/// Target number of proofs to maintain at each denomination
|
||||
pub target_proof_count: Option<usize>,
|
||||
}
|
||||
|
||||
impl WalletConfig {
|
||||
/// Create a new empty WalletConfig
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
/// Set custom mint connector
|
||||
pub fn with_mint_connector(
|
||||
mut self,
|
||||
connector: Arc<dyn super::MintConnector + Send + Sync>,
|
||||
) -> Self {
|
||||
self.mint_connector = Some(connector);
|
||||
self
|
||||
}
|
||||
|
||||
/// Set custom auth connector
|
||||
#[cfg(feature = "auth")]
|
||||
pub fn with_auth_connector(
|
||||
mut self,
|
||||
connector: Arc<dyn super::auth::AuthMintConnector + Send + Sync>,
|
||||
) -> Self {
|
||||
self.auth_connector = Some(connector);
|
||||
self
|
||||
}
|
||||
|
||||
/// Set target proof count
|
||||
pub fn with_target_proof_count(mut self, count: usize) -> Self {
|
||||
self.target_proof_count = Some(count);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// Multi Mint Wallet
|
||||
///
|
||||
/// A wallet that manages multiple mints but supports only one currency unit.
|
||||
@@ -89,8 +133,8 @@ pub struct TransferResult {
|
||||
/// // Add mints to the wallet
|
||||
/// let mint_url1: MintUrl = "https://mint1.example.com".parse()?;
|
||||
/// let mint_url2: MintUrl = "https://mint2.example.com".parse()?;
|
||||
/// wallet.add_mint(mint_url1.clone(), None).await?;
|
||||
/// wallet.add_mint(mint_url2, None).await?;
|
||||
/// wallet.add_mint(mint_url1.clone()).await?;
|
||||
/// wallet.add_mint(mint_url2).await?;
|
||||
///
|
||||
/// // Check total balance across all mints
|
||||
/// let balance = wallet.total_balance().await?;
|
||||
@@ -199,12 +243,149 @@ impl MultiMintWallet {
|
||||
}
|
||||
|
||||
/// Adds a mint to this [MultiMintWallet]
|
||||
///
|
||||
/// Creates a wallet for the specified mint using default or global settings.
|
||||
/// For custom configuration, use `add_mint_with_config()`.
|
||||
#[instrument(skip(self))]
|
||||
pub async fn add_mint(
|
||||
pub async fn add_mint(&self, mint_url: MintUrl) -> Result<(), Error> {
|
||||
// Create wallet with default settings
|
||||
let wallet = self
|
||||
.create_wallet_with_config(mint_url.clone(), None)
|
||||
.await?;
|
||||
|
||||
// Insert into wallets map
|
||||
let mut wallets = self.wallets.write().await;
|
||||
wallets.insert(mint_url, wallet);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Adds a mint to this [MultiMintWallet] with custom configuration
|
||||
///
|
||||
/// The provided configuration is used to create the wallet with custom connectors
|
||||
/// and settings. Configuration is stored within the Wallet instance itself.
|
||||
#[instrument(skip(self))]
|
||||
pub async fn add_mint_with_config(
|
||||
&self,
|
||||
mint_url: MintUrl,
|
||||
target_proof_count: Option<usize>,
|
||||
config: WalletConfig,
|
||||
) -> Result<(), Error> {
|
||||
// Create wallet with the provided config
|
||||
let wallet = self
|
||||
.create_wallet_with_config(mint_url.clone(), Some(&config))
|
||||
.await?;
|
||||
|
||||
// Insert into wallets map
|
||||
let mut wallets = self.wallets.write().await;
|
||||
wallets.insert(mint_url, wallet);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Set or update configuration for a mint
|
||||
///
|
||||
/// If the wallet already exists, it will be updated with the new config.
|
||||
/// If the wallet doesn't exist, it will be created with the specified config.
|
||||
#[instrument(skip(self))]
|
||||
pub async fn set_mint_config(
|
||||
&self,
|
||||
mint_url: MintUrl,
|
||||
config: WalletConfig,
|
||||
) -> Result<(), Error> {
|
||||
// Check if wallet already exists
|
||||
if self.has_mint(&mint_url).await {
|
||||
// Update existing wallet in place
|
||||
let mut wallets = self.wallets.write().await;
|
||||
if let Some(wallet) = wallets.get_mut(&mint_url) {
|
||||
// Update target_proof_count if provided
|
||||
if let Some(count) = config.target_proof_count {
|
||||
wallet.set_target_proof_count(count);
|
||||
}
|
||||
|
||||
// Update connector if provided
|
||||
if let Some(connector) = config.mint_connector {
|
||||
wallet.set_client(connector);
|
||||
}
|
||||
|
||||
// TODO: Handle auth_connector if provided
|
||||
#[cfg(feature = "auth")]
|
||||
if let Some(_auth_connector) = config.auth_connector {
|
||||
// For now, we can't easily inject auth_connector into the wallet
|
||||
// This would require additional work on the Wallet API
|
||||
// We'll note this as a future enhancement
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
} else {
|
||||
// Wallet doesn't exist, create it with the provided config
|
||||
self.add_mint_with_config(mint_url, config).await
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the auth client (AuthWallet) for a specific mint
|
||||
///
|
||||
/// This allows updating the auth wallet for an existing mint wallet without recreating it.
|
||||
#[cfg(feature = "auth")]
|
||||
#[instrument(skip_all)]
|
||||
pub async fn set_auth_client(
|
||||
&self,
|
||||
mint_url: &MintUrl,
|
||||
auth_wallet: Option<super::auth::AuthWallet>,
|
||||
) -> Result<(), Error> {
|
||||
let wallets = self.wallets.read().await;
|
||||
let wallet = wallets.get(mint_url).ok_or(Error::UnknownMint {
|
||||
mint_url: mint_url.to_string(),
|
||||
})?;
|
||||
|
||||
wallet.set_auth_client(auth_wallet).await;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Remove mint from MultiMintWallet
|
||||
#[instrument(skip(self))]
|
||||
pub async fn remove_mint(&self, mint_url: &MintUrl) {
|
||||
let mut wallets = self.wallets.write().await;
|
||||
wallets.remove(mint_url);
|
||||
}
|
||||
|
||||
/// Internal: Create wallet with optional custom configuration
|
||||
///
|
||||
/// Priority order for configuration:
|
||||
/// 1. Custom connector from config (if provided)
|
||||
/// 2. Global settings (proxy/Tor)
|
||||
/// 3. Default HttpClient
|
||||
async fn create_wallet_with_config(
|
||||
&self,
|
||||
mint_url: MintUrl,
|
||||
config: Option<&WalletConfig>,
|
||||
) -> Result<Wallet, Error> {
|
||||
// Check if custom connector is provided in config
|
||||
if let Some(cfg) = config {
|
||||
if let Some(custom_connector) = &cfg.mint_connector {
|
||||
// Use custom connector with WalletBuilder
|
||||
let builder = WalletBuilder::new()
|
||||
.mint_url(mint_url.clone())
|
||||
.unit(self.unit.clone())
|
||||
.localstore(self.localstore.clone())
|
||||
.seed(self.seed)
|
||||
.target_proof_count(cfg.target_proof_count.unwrap_or(3))
|
||||
.shared_client(custom_connector.clone());
|
||||
|
||||
// TODO: Handle auth_connector if provided
|
||||
#[cfg(feature = "auth")]
|
||||
if let Some(_auth_connector) = &cfg.auth_connector {
|
||||
// For now, we can't easily inject auth_connector into the wallet
|
||||
// This would require additional work on the Wallet/WalletBuilder API
|
||||
// We'll note this as a future enhancement
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
}
|
||||
|
||||
// Fall back to existing logic: proxy/Tor/default
|
||||
let target_proof_count = config.and_then(|c| c.target_proof_count).unwrap_or(3);
|
||||
|
||||
let wallet = if let Some(proxy_url) = &self.proxy_config {
|
||||
// Create wallet with proxy-configured client
|
||||
let client = crate::wallet::HttpClient::with_proxy(
|
||||
@@ -228,7 +409,7 @@ impl MultiMintWallet {
|
||||
.unit(self.unit.clone())
|
||||
.localstore(self.localstore.clone())
|
||||
.seed(self.seed)
|
||||
.target_proof_count(target_proof_count.unwrap_or(3))
|
||||
.target_proof_count(target_proof_count)
|
||||
.client(client)
|
||||
.build()?
|
||||
} else {
|
||||
@@ -256,7 +437,7 @@ impl MultiMintWallet {
|
||||
.unit(self.unit.clone())
|
||||
.localstore(self.localstore.clone())
|
||||
.seed(self.seed)
|
||||
.target_proof_count(target_proof_count.unwrap_or(3))
|
||||
.target_proof_count(target_proof_count)
|
||||
.client(client)
|
||||
.build()?
|
||||
} else {
|
||||
@@ -266,7 +447,7 @@ impl MultiMintWallet {
|
||||
self.unit.clone(),
|
||||
self.localstore.clone(),
|
||||
self.seed,
|
||||
target_proof_count,
|
||||
Some(target_proof_count),
|
||||
)?
|
||||
}
|
||||
|
||||
@@ -278,22 +459,12 @@ impl MultiMintWallet {
|
||||
self.unit.clone(),
|
||||
self.localstore.clone(),
|
||||
self.seed,
|
||||
target_proof_count,
|
||||
Some(target_proof_count),
|
||||
)?
|
||||
}
|
||||
};
|
||||
|
||||
let mut wallets = self.wallets.write().await;
|
||||
wallets.insert(mint_url, wallet);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Remove mint from MultiMintWallet
|
||||
#[instrument(skip(self))]
|
||||
pub async fn remove_mint(&self, mint_url: &MintUrl) {
|
||||
let mut wallets = self.wallets.write().await;
|
||||
wallets.remove(mint_url);
|
||||
Ok(wallet)
|
||||
}
|
||||
|
||||
/// Load all wallets from database that have proofs for this currency unit
|
||||
@@ -317,7 +488,7 @@ impl MultiMintWallet {
|
||||
if mint_has_proofs_for_unit {
|
||||
// Add mint to the MultiMintWallet if not already present
|
||||
if !self.has_mint(&mint_url).await {
|
||||
self.add_mint(mint_url.clone(), None).await?
|
||||
self.add_mint(mint_url.clone()).await?
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -980,7 +1151,7 @@ impl MultiMintWallet {
|
||||
|
||||
// Add the untrusted mint temporarily if needed
|
||||
if !is_trusted {
|
||||
self.add_mint(mint_url.clone(), None).await?;
|
||||
self.add_mint(mint_url.clone()).await?;
|
||||
}
|
||||
|
||||
let wallets = self.wallets.read().await;
|
||||
@@ -1414,6 +1585,103 @@ impl MultiMintWallet {
|
||||
|
||||
Ok(total_consolidated)
|
||||
}
|
||||
|
||||
/// Mint blind auth tokens for a specific mint
|
||||
///
|
||||
/// This is a convenience method that calls the underlying wallet's mint_blind_auth.
|
||||
#[cfg(feature = "auth")]
|
||||
#[instrument(skip_all)]
|
||||
pub async fn mint_blind_auth(
|
||||
&self,
|
||||
mint_url: &MintUrl,
|
||||
amount: Amount,
|
||||
) -> Result<Proofs, Error> {
|
||||
let wallets = self.wallets.read().await;
|
||||
let wallet = wallets.get(mint_url).ok_or(Error::UnknownMint {
|
||||
mint_url: mint_url.to_string(),
|
||||
})?;
|
||||
|
||||
wallet.mint_blind_auth(amount).await
|
||||
}
|
||||
|
||||
/// Get unspent auth proofs for a specific mint
|
||||
///
|
||||
/// This is a convenience method that calls the underlying wallet's get_unspent_auth_proofs.
|
||||
#[cfg(feature = "auth")]
|
||||
#[instrument(skip_all)]
|
||||
pub async fn get_unspent_auth_proofs(
|
||||
&self,
|
||||
mint_url: &MintUrl,
|
||||
) -> Result<Vec<cdk_common::AuthProof>, Error> {
|
||||
let wallets = self.wallets.read().await;
|
||||
let wallet = wallets.get(mint_url).ok_or(Error::UnknownMint {
|
||||
mint_url: mint_url.to_string(),
|
||||
})?;
|
||||
|
||||
wallet.get_unspent_auth_proofs().await
|
||||
}
|
||||
|
||||
/// Set Clear Auth Token (CAT) for authentication at a specific mint
|
||||
///
|
||||
/// This is a convenience method that calls the underlying wallet's set_cat.
|
||||
#[cfg(feature = "auth")]
|
||||
#[instrument(skip_all)]
|
||||
pub async fn set_cat(&self, mint_url: &MintUrl, cat: String) -> Result<(), Error> {
|
||||
let wallets = self.wallets.read().await;
|
||||
let wallet = wallets.get(mint_url).ok_or(Error::UnknownMint {
|
||||
mint_url: mint_url.to_string(),
|
||||
})?;
|
||||
|
||||
wallet.set_cat(cat).await
|
||||
}
|
||||
|
||||
/// Set refresh token for authentication at a specific mint
|
||||
///
|
||||
/// This is a convenience method that calls the underlying wallet's set_refresh_token.
|
||||
#[cfg(feature = "auth")]
|
||||
#[instrument(skip_all)]
|
||||
pub async fn set_refresh_token(
|
||||
&self,
|
||||
mint_url: &MintUrl,
|
||||
refresh_token: String,
|
||||
) -> Result<(), Error> {
|
||||
let wallets = self.wallets.read().await;
|
||||
let wallet = wallets.get(mint_url).ok_or(Error::UnknownMint {
|
||||
mint_url: mint_url.to_string(),
|
||||
})?;
|
||||
|
||||
wallet.set_refresh_token(refresh_token).await
|
||||
}
|
||||
|
||||
/// Refresh CAT token for a specific mint
|
||||
///
|
||||
/// This is a convenience method that calls the underlying wallet's refresh_access_token.
|
||||
#[cfg(feature = "auth")]
|
||||
#[instrument(skip(self))]
|
||||
pub async fn refresh_access_token(&self, mint_url: &MintUrl) -> Result<(), Error> {
|
||||
let wallets = self.wallets.read().await;
|
||||
let wallet = wallets.get(mint_url).ok_or(Error::UnknownMint {
|
||||
mint_url: mint_url.to_string(),
|
||||
})?;
|
||||
|
||||
wallet.refresh_access_token().await
|
||||
}
|
||||
|
||||
/// Query mint for current mint information
|
||||
///
|
||||
/// This is a convenience method that calls the underlying wallet's fetch_mint_info.
|
||||
#[instrument(skip(self))]
|
||||
pub async fn fetch_mint_info(
|
||||
&self,
|
||||
mint_url: &MintUrl,
|
||||
) -> Result<Option<crate::nuts::MintInfo>, Error> {
|
||||
let wallets = self.wallets.read().await;
|
||||
let wallet = wallets.get(mint_url).ok_or(Error::UnknownMint {
|
||||
mint_url: mint_url.to_string(),
|
||||
})?;
|
||||
|
||||
wallet.fetch_mint_info().await
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for MultiMintWallet {
|
||||
|
||||
Reference in New Issue
Block a user