Skip to content

Commit 5caa7d5

Browse files
authored
Configure internal Wallets of a MultiMintWallet (#1177)
1 parent f173b2d commit 5caa7d5

9 files changed

Lines changed: 425 additions & 73 deletions

File tree

crates/cdk-cli/src/sub_commands/cat_device_login.rs

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,19 +29,13 @@ pub async fn cat_device_login(
2929
) -> Result<()> {
3030
let mint_url = sub_command_args.mint_url.clone();
3131

32-
let wallet = match multi_mint_wallet.get_wallet(&mint_url).await {
33-
Some(wallet) => wallet.clone(),
34-
None => {
35-
multi_mint_wallet.add_mint(mint_url.clone(), None).await?;
36-
multi_mint_wallet
37-
.get_wallet(&mint_url)
38-
.await
39-
.expect("Wallet should exist after adding mint")
40-
}
41-
};
32+
// Ensure the mint exists
33+
if !multi_mint_wallet.has_mint(&mint_url).await {
34+
multi_mint_wallet.add_mint(mint_url.clone()).await?;
35+
}
4236

43-
let mint_info = wallet
44-
.fetch_mint_info()
37+
let mint_info = multi_mint_wallet
38+
.fetch_mint_info(&mint_url)
4539
.await?
4640
.ok_or(anyhow!("Mint info not found"))?;
4741

crates/cdk-cli/src/sub_commands/cat_login.rs

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -31,20 +31,13 @@ pub async fn cat_login(
3131
) -> Result<()> {
3232
let mint_url = sub_command_args.mint_url.clone();
3333

34-
let wallet = match multi_mint_wallet.get_wallet(&mint_url).await {
35-
Some(wallet) => wallet.clone(),
36-
None => {
37-
multi_mint_wallet.add_mint(mint_url.clone(), None).await?;
38-
multi_mint_wallet
39-
.get_wallet(&mint_url)
40-
.await
41-
.expect("Wallet should exist after adding mint")
42-
.clone()
43-
}
44-
};
45-
46-
let mint_info = wallet
47-
.fetch_mint_info()
34+
// Ensure the mint exists
35+
if !multi_mint_wallet.has_mint(&mint_url).await {
36+
multi_mint_wallet.add_mint(mint_url.clone()).await?;
37+
}
38+
39+
let mint_info = multi_mint_wallet
40+
.fetch_mint_info(&mint_url)
4841
.await?
4942
.ok_or(anyhow!("Mint info not found"))?;
5043

crates/cdk-cli/src/sub_commands/mint_blind_auth.rs

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,12 @@ pub async fn mint_blind_auth(
2828
) -> Result<()> {
2929
let mint_url = sub_command_args.mint_url.clone();
3030

31-
let wallet = match multi_mint_wallet.get_wallet(&mint_url).await {
32-
Some(wallet) => wallet.clone(),
33-
None => {
34-
multi_mint_wallet.add_mint(mint_url.clone(), None).await?;
35-
multi_mint_wallet
36-
.get_wallet(&mint_url)
37-
.await
38-
.expect("Wallet should exist after adding mint")
39-
.clone()
40-
}
41-
};
31+
// Ensure the mint exists
32+
if !multi_mint_wallet.has_mint(&mint_url).await {
33+
multi_mint_wallet.add_mint(mint_url.clone()).await?;
34+
}
4235

43-
wallet.fetch_mint_info().await?;
36+
multi_mint_wallet.fetch_mint_info(&mint_url).await?;
4437

4538
// Try to get the token from the provided argument or from the stored file
4639
let cat = match &sub_command_args.cat {
@@ -68,15 +61,15 @@ pub async fn mint_blind_auth(
6861
};
6962

7063
// Try to set the access token
71-
if let Err(err) = wallet.set_cat(cat.clone()).await {
64+
if let Err(err) = multi_mint_wallet.set_cat(&mint_url, cat.clone()).await {
7265
tracing::error!("Could not set cat: {}", err);
7366

7467
// Try to refresh the token if we have a refresh token
7568
if let Ok(Some(token_data)) = token_storage::get_token_for_mint(work_dir, &mint_url).await {
7669
println!("Attempting to refresh the access token...");
7770

7871
// Get the mint info to access OIDC configuration
79-
if let Some(mint_info) = wallet.fetch_mint_info().await? {
72+
if let Some(mint_info) = multi_mint_wallet.fetch_mint_info(&mint_url).await? {
8073
match refresh_access_token(&mint_info, &token_data.refresh_token).await {
8174
Ok((new_access_token, new_refresh_token)) => {
8275
println!("Successfully refreshed access token");
@@ -94,15 +87,19 @@ pub async fn mint_blind_auth(
9487
}
9588

9689
// Try setting the new access token
97-
if let Err(err) = wallet.set_cat(new_access_token).await {
90+
if let Err(err) =
91+
multi_mint_wallet.set_cat(&mint_url, new_access_token).await
92+
{
9893
tracing::error!("Could not set refreshed cat: {}", err);
9994
return Err(anyhow::anyhow!(
10095
"Authentication failed even after token refresh"
10196
));
10297
}
10398

10499
// Set the refresh token
105-
wallet.set_refresh_token(new_refresh_token).await?;
100+
multi_mint_wallet
101+
.set_refresh_token(&mint_url, new_refresh_token)
102+
.await?;
106103
}
107104
Err(e) => {
108105
tracing::error!("Failed to refresh token: {}", e);
@@ -119,8 +116,10 @@ pub async fn mint_blind_auth(
119116
// If we have a refresh token, set it
120117
if let Ok(Some(token_data)) = token_storage::get_token_for_mint(work_dir, &mint_url).await {
121118
tracing::info!("Attempting to use refresh access token to refresh auth token");
122-
wallet.set_refresh_token(token_data.refresh_token).await?;
123-
wallet.refresh_access_token().await?;
119+
multi_mint_wallet
120+
.set_refresh_token(&mint_url, token_data.refresh_token)
121+
.await?;
122+
multi_mint_wallet.refresh_access_token(&mint_url).await?;
124123
}
125124
}
126125

@@ -129,8 +128,8 @@ pub async fn mint_blind_auth(
129128
let amount = match sub_command_args.amount {
130129
Some(amount) => amount,
131130
None => {
132-
let mint_info = wallet
133-
.fetch_mint_info()
131+
let mint_info = multi_mint_wallet
132+
.fetch_mint_info(&mint_url)
134133
.await?
135134
.ok_or(anyhow!("Unknown mint info"))?;
136135
mint_info
@@ -139,7 +138,9 @@ pub async fn mint_blind_auth(
139138
}
140139
};
141140

142-
let proofs = wallet.mint_blind_auth(Amount::from(amount)).await?;
141+
let proofs = multi_mint_wallet
142+
.mint_blind_auth(&mint_url, Amount::from(amount))
143+
.await?;
143144

144145
println!("Received {} auth proofs for mint {mint_url}", proofs.len());
145146

crates/cdk-cli/src/sub_commands/restore.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ pub async fn restore(
1818
let wallet = match multi_mint_wallet.get_wallet(&mint_url).await {
1919
Some(wallet) => wallet.clone(),
2020
None => {
21-
multi_mint_wallet.add_mint(mint_url.clone(), None).await?;
21+
multi_mint_wallet.add_mint(mint_url.clone()).await?;
2222
multi_mint_wallet
2323
.get_wallet(&mint_url)
2424
.await

crates/cdk-cli/src/utils.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ pub async fn get_or_create_wallet(
3434
Some(wallet) => Ok(wallet.clone()),
3535
None => {
3636
tracing::debug!("Wallet does not exist creating..");
37-
multi_mint_wallet.add_mint(mint_url.clone(), None).await?;
37+
multi_mint_wallet.add_mint(mint_url.clone()).await?;
3838
Ok(multi_mint_wallet
3939
.get_wallet(mint_url)
4040
.await

crates/cdk-ffi/src/multi_mint_wallet.rs

Lines changed: 72 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,16 @@ impl MultiMintWallet {
118118
target_proof_count: Option<u32>,
119119
) -> Result<(), FfiError> {
120120
let cdk_mint_url: cdk::mint_url::MintUrl = mint_url.try_into()?;
121-
self.inner
122-
.add_mint(cdk_mint_url, target_proof_count.map(|c| c as usize))
123-
.await?;
121+
122+
if let Some(count) = target_proof_count {
123+
let config = cdk::wallet::multi_mint_wallet::WalletConfig::new()
124+
.with_target_proof_count(count as usize);
125+
self.inner
126+
.add_mint_with_config(cdk_mint_url, config)
127+
.await?;
128+
} else {
129+
self.inner.add_mint(cdk_mint_url).await?;
130+
}
124131
Ok(())
125132
}
126133

@@ -380,6 +387,68 @@ impl MultiMintWallet {
380387
self.inner.verify_token_dleq(&cdk_token).await?;
381388
Ok(())
382389
}
390+
391+
/// Query mint for current mint information
392+
pub async fn fetch_mint_info(&self, mint_url: MintUrl) -> Result<Option<MintInfo>, FfiError> {
393+
let cdk_mint_url: cdk::mint_url::MintUrl = mint_url.try_into()?;
394+
let mint_info = self.inner.fetch_mint_info(&cdk_mint_url).await?;
395+
Ok(mint_info.map(Into::into))
396+
}
397+
}
398+
399+
/// Auth methods for MultiMintWallet
400+
#[uniffi::export(async_runtime = "tokio")]
401+
impl MultiMintWallet {
402+
/// Set Clear Auth Token (CAT) for a specific mint
403+
pub async fn set_cat(&self, mint_url: MintUrl, cat: String) -> Result<(), FfiError> {
404+
let cdk_mint_url: cdk::mint_url::MintUrl = mint_url.try_into()?;
405+
self.inner.set_cat(&cdk_mint_url, cat).await?;
406+
Ok(())
407+
}
408+
409+
/// Set refresh token for a specific mint
410+
pub async fn set_refresh_token(
411+
&self,
412+
mint_url: MintUrl,
413+
refresh_token: String,
414+
) -> Result<(), FfiError> {
415+
let cdk_mint_url: cdk::mint_url::MintUrl = mint_url.try_into()?;
416+
self.inner
417+
.set_refresh_token(&cdk_mint_url, refresh_token)
418+
.await?;
419+
Ok(())
420+
}
421+
422+
/// Refresh access token for a specific mint using the stored refresh token
423+
pub async fn refresh_access_token(&self, mint_url: MintUrl) -> Result<(), FfiError> {
424+
let cdk_mint_url: cdk::mint_url::MintUrl = mint_url.try_into()?;
425+
self.inner.refresh_access_token(&cdk_mint_url).await?;
426+
Ok(())
427+
}
428+
429+
/// Mint blind auth tokens at a specific mint
430+
pub async fn mint_blind_auth(
431+
&self,
432+
mint_url: MintUrl,
433+
amount: Amount,
434+
) -> Result<Proofs, FfiError> {
435+
let cdk_mint_url: cdk::mint_url::MintUrl = mint_url.try_into()?;
436+
let proofs = self
437+
.inner
438+
.mint_blind_auth(&cdk_mint_url, amount.into())
439+
.await?;
440+
Ok(proofs.into_iter().map(|p| Arc::new(p.into())).collect())
441+
}
442+
443+
/// Get unspent auth proofs for a specific mint
444+
pub async fn get_unspent_auth_proofs(
445+
&self,
446+
mint_url: MintUrl,
447+
) -> Result<Vec<AuthProof>, FfiError> {
448+
let cdk_mint_url: cdk::mint_url::MintUrl = mint_url.try_into()?;
449+
let auth_proofs = self.inner.get_unspent_auth_proofs(&cdk_mint_url).await?;
450+
Ok(auth_proofs.into_iter().map(Into::into).collect())
451+
}
383452
}
384453

385454
/// Transfer mode for mint-to-mint transfers

crates/cdk/src/wallet/auth/mod.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,4 +65,17 @@ impl Wallet {
6565
}
6666
Ok(())
6767
}
68+
69+
/// Set the auth client (AuthWallet) for this wallet
70+
///
71+
/// This allows updating the auth wallet without recreating the wallet.
72+
/// Also updates the client's auth wallet to keep them in sync.
73+
#[instrument(skip_all)]
74+
pub async fn set_auth_client(&self, auth_wallet: Option<AuthWallet>) {
75+
let mut auth_wallet_guard = self.auth_wallet.write().await;
76+
*auth_wallet_guard = auth_wallet.clone();
77+
78+
// Also update the client's auth wallet to keep them in sync
79+
self.client.set_auth_wallet(auth_wallet).await;
80+
}
6881
}

crates/cdk/src/wallet/mod.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -673,6 +673,20 @@ impl Wallet {
673673

674674
Ok(())
675675
}
676+
677+
/// Set the client (MintConnector) for this wallet
678+
///
679+
/// This allows updating the connector without recreating the wallet.
680+
pub fn set_client(&mut self, client: Arc<dyn MintConnector + Send + Sync>) {
681+
self.client = client;
682+
}
683+
684+
/// Set the target proof count for this wallet
685+
///
686+
/// This controls how many proofs of each denomination the wallet tries to maintain.
687+
pub fn set_target_proof_count(&mut self, count: usize) {
688+
self.target_proof_count = count;
689+
}
676690
}
677691

678692
impl Drop for Wallet {

0 commit comments

Comments
 (0)