mirror of
https://github.com/aljazceru/cdk.git
synced 2026-02-06 21:56:13 +01:00
fix: show ammounts (#1136)
This commit is contained in:
@@ -71,6 +71,50 @@ pub async fn pay(
|
||||
bail!("No funds available");
|
||||
}
|
||||
|
||||
// Determine which mint to use for melting BEFORE processing payment (unless using MPP)
|
||||
let selected_mint = if sub_command_args.mpp {
|
||||
None // MPP mode handles mint selection differently
|
||||
} else if let Some(mint_url) = &sub_command_args.mint_url {
|
||||
Some(MintUrl::from_str(mint_url)?)
|
||||
} else {
|
||||
// Display all mints with their balances and let user select
|
||||
let balances_map = multi_mint_wallet.get_balances().await?;
|
||||
if balances_map.is_empty() {
|
||||
bail!("No mints available in the wallet");
|
||||
}
|
||||
|
||||
let balances_vec: Vec<(MintUrl, Amount)> = balances_map.into_iter().collect();
|
||||
|
||||
println!("\nAvailable mints and balances:");
|
||||
for (index, (mint_url, balance)) in balances_vec.iter().enumerate() {
|
||||
println!(
|
||||
" {}: {} - {} {}",
|
||||
index,
|
||||
mint_url,
|
||||
balance,
|
||||
multi_mint_wallet.unit()
|
||||
);
|
||||
}
|
||||
println!(" {}: Any mint (auto-select best)", balances_vec.len());
|
||||
|
||||
let selection = loop {
|
||||
let selection: usize =
|
||||
get_number_input("Enter mint number to melt from (or select Any)")?;
|
||||
|
||||
if selection == balances_vec.len() {
|
||||
break None; // "Any" option selected
|
||||
}
|
||||
|
||||
if let Some((mint_url, _)) = balances_vec.get(selection) {
|
||||
break Some(mint_url.clone());
|
||||
}
|
||||
|
||||
println!("Invalid selection, please try again.");
|
||||
};
|
||||
|
||||
selection
|
||||
};
|
||||
|
||||
if sub_command_args.mpp {
|
||||
// Manual MPP - user specifies which mints and amounts to use
|
||||
if !matches!(sub_command_args.method, PaymentType::Bolt11) {
|
||||
@@ -180,12 +224,9 @@ pub async fn pay(
|
||||
let options =
|
||||
create_melt_options(available_funds, bolt11.amount_milli_satoshis(), &prompt)?;
|
||||
|
||||
// Use mint-specific functions or auto-select
|
||||
let melted = if let Some(mint_url) = &sub_command_args.mint_url {
|
||||
// User specified a mint - use the new mint-specific functions
|
||||
let mint_url = MintUrl::from_str(mint_url)?;
|
||||
|
||||
// Create a melt quote for the specific mint
|
||||
// Use selected mint or auto-select
|
||||
let melted = if let Some(mint_url) = selected_mint {
|
||||
// User selected a specific mint - use the new mint-specific functions
|
||||
let quote = multi_mint_wallet
|
||||
.melt_quote(&mint_url, bolt11_str.clone(), options)
|
||||
.await?;
|
||||
@@ -200,7 +241,7 @@ pub async fn pay(
|
||||
.melt_with_mint(&mint_url, "e.id)
|
||||
.await?
|
||||
} else {
|
||||
// Let the wallet automatically select the best mint
|
||||
// User selected "Any" - let the wallet auto-select the best mint
|
||||
multi_mint_wallet.melt(&bolt11_str, options, None).await?
|
||||
};
|
||||
|
||||
@@ -227,41 +268,25 @@ pub async fn pay(
|
||||
|
||||
let options = create_melt_options(available_funds, amount_msat, &prompt)?;
|
||||
|
||||
// Get wallet for BOLT12
|
||||
let wallet = if let Some(mint_url) = &sub_command_args.mint_url {
|
||||
// User specified a mint
|
||||
let mint_url = MintUrl::from_str(mint_url)?;
|
||||
multi_mint_wallet
|
||||
.get_wallet(&mint_url)
|
||||
.await
|
||||
.ok_or_else(|| anyhow::anyhow!("Mint {} not found", mint_url))?
|
||||
// Get wallet for BOLT12 using the selected mint
|
||||
let mint_url = if let Some(specific_mint) = selected_mint {
|
||||
specific_mint
|
||||
} else {
|
||||
// Show available mints and let user select
|
||||
// User selected "Any" - just pick the first mint with any balance
|
||||
let balances = multi_mint_wallet.get_balances().await?;
|
||||
println!("\nAvailable mints:");
|
||||
for (i, (mint_url, balance)) in balances.iter().enumerate() {
|
||||
println!(
|
||||
" {}: {} - {} {}",
|
||||
i,
|
||||
mint_url,
|
||||
balance,
|
||||
multi_mint_wallet.unit()
|
||||
);
|
||||
}
|
||||
|
||||
let mint_number: usize = get_number_input("Enter mint number to melt from")?;
|
||||
let selected_mint = balances
|
||||
.iter()
|
||||
.nth(mint_number)
|
||||
.map(|(url, _)| url)
|
||||
.ok_or_else(|| anyhow::anyhow!("Invalid mint number"))?;
|
||||
|
||||
multi_mint_wallet
|
||||
.get_wallet(selected_mint)
|
||||
.await
|
||||
.ok_or_else(|| anyhow::anyhow!("Mint {} not found", selected_mint))?
|
||||
balances
|
||||
.into_iter()
|
||||
.find(|(_, balance)| *balance > Amount::ZERO)
|
||||
.map(|(mint_url, _)| mint_url)
|
||||
.ok_or_else(|| anyhow::anyhow!("No mint available for BOLT12 payment"))?
|
||||
};
|
||||
|
||||
let wallet = multi_mint_wallet
|
||||
.get_wallet(&mint_url)
|
||||
.await
|
||||
.ok_or_else(|| anyhow::anyhow!("Mint {} not found", mint_url))?;
|
||||
|
||||
// Get melt quote for BOLT12
|
||||
let quote = wallet.melt_bolt12_quote(offer_str, options).await?;
|
||||
|
||||
@@ -293,41 +318,25 @@ pub async fn pay(
|
||||
// BIP353 payments are always amountless for now
|
||||
let options = create_melt_options(available_funds, None, &prompt)?;
|
||||
|
||||
// Get wallet for BIP353
|
||||
let wallet = if let Some(mint_url) = &sub_command_args.mint_url {
|
||||
// User specified a mint
|
||||
let mint_url = MintUrl::from_str(mint_url)?;
|
||||
multi_mint_wallet
|
||||
.get_wallet(&mint_url)
|
||||
.await
|
||||
.ok_or_else(|| anyhow::anyhow!("Mint {} not found", mint_url))?
|
||||
// Get wallet for BIP353 using the selected mint
|
||||
let mint_url = if let Some(specific_mint) = selected_mint {
|
||||
specific_mint
|
||||
} else {
|
||||
// Show available mints and let user select
|
||||
// User selected "Any" - just pick the first mint with any balance
|
||||
let balances = multi_mint_wallet.get_balances().await?;
|
||||
println!("\nAvailable mints:");
|
||||
for (i, (mint_url, balance)) in balances.iter().enumerate() {
|
||||
println!(
|
||||
" {}: {} - {} {}",
|
||||
i,
|
||||
mint_url,
|
||||
balance,
|
||||
multi_mint_wallet.unit()
|
||||
);
|
||||
}
|
||||
|
||||
let mint_number: usize = get_number_input("Enter mint number to melt from")?;
|
||||
let selected_mint = balances
|
||||
.iter()
|
||||
.nth(mint_number)
|
||||
.map(|(url, _)| url)
|
||||
.ok_or_else(|| anyhow::anyhow!("Invalid mint number"))?;
|
||||
|
||||
multi_mint_wallet
|
||||
.get_wallet(selected_mint)
|
||||
.await
|
||||
.ok_or_else(|| anyhow::anyhow!("Mint {} not found", selected_mint))?
|
||||
balances
|
||||
.into_iter()
|
||||
.find(|(_, balance)| *balance > Amount::ZERO)
|
||||
.map(|(mint_url, _)| mint_url)
|
||||
.ok_or_else(|| anyhow::anyhow!("No mint available for BIP353 payment"))?
|
||||
};
|
||||
|
||||
let wallet = multi_mint_wallet
|
||||
.get_wallet(&mint_url)
|
||||
.await
|
||||
.ok_or_else(|| anyhow::anyhow!("Mint {} not found", mint_url))?;
|
||||
|
||||
// Get melt quote for BIP353 address (internally resolves and gets BOLT12 quote)
|
||||
let quote = wallet
|
||||
.melt_bip353_quote(
|
||||
|
||||
@@ -54,9 +54,7 @@ pub struct SendSubCommand {
|
||||
/// Maximum amount to transfer from other mints
|
||||
#[arg(long)]
|
||||
max_transfer_amount: Option<u64>,
|
||||
/// Specific mints allowed for transfers (can be specified multiple times)
|
||||
#[arg(long, action = clap::ArgAction::Append)]
|
||||
allowed_mints: Vec<String>,
|
||||
|
||||
/// Specific mints to exclude from transfers (can be specified multiple times)
|
||||
#[arg(long, action = clap::ArgAction::Append)]
|
||||
excluded_mints: Vec<String>,
|
||||
@@ -66,6 +64,48 @@ pub async fn send(
|
||||
multi_mint_wallet: &MultiMintWallet,
|
||||
sub_command_args: &SendSubCommand,
|
||||
) -> Result<()> {
|
||||
// Determine which mint to use for sending BEFORE asking for amount
|
||||
let selected_mint = if let Some(mint_url) = &sub_command_args.mint_url {
|
||||
Some(MintUrl::from_str(mint_url)?)
|
||||
} else {
|
||||
// Display all mints with their balances and let user select
|
||||
let balances_map = multi_mint_wallet.get_balances().await?;
|
||||
if balances_map.is_empty() {
|
||||
return Err(anyhow!("No mints available in the wallet"));
|
||||
}
|
||||
|
||||
let balances_vec: Vec<(MintUrl, Amount)> = balances_map.into_iter().collect();
|
||||
|
||||
println!("\nAvailable mints and balances:");
|
||||
for (index, (mint_url, balance)) in balances_vec.iter().enumerate() {
|
||||
println!(
|
||||
" {}: {} - {} {}",
|
||||
index,
|
||||
mint_url,
|
||||
balance,
|
||||
multi_mint_wallet.unit()
|
||||
);
|
||||
}
|
||||
println!(" {}: Any mint (auto-select best)", balances_vec.len());
|
||||
|
||||
let selection = loop {
|
||||
let selection: usize =
|
||||
get_number_input("Enter mint number to send from (or select Any)")?;
|
||||
|
||||
if selection == balances_vec.len() {
|
||||
break None; // "Any" option selected
|
||||
}
|
||||
|
||||
if let Some((mint_url, _)) = balances_vec.get(selection) {
|
||||
break Some(mint_url.clone());
|
||||
}
|
||||
|
||||
println!("Invalid selection, please try again.");
|
||||
};
|
||||
|
||||
selection
|
||||
};
|
||||
|
||||
let token_amount = Amount::from(get_number_input::<u64>(&format!(
|
||||
"Enter value of token in {}",
|
||||
multi_mint_wallet.unit()
|
||||
@@ -214,14 +254,7 @@ pub async fn send(
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
// Parse allowed and excluded mints from CLI arguments
|
||||
let allowed_mints: Result<Vec<MintUrl>, _> = sub_command_args
|
||||
.allowed_mints
|
||||
.iter()
|
||||
.map(|url| MintUrl::from_str(url))
|
||||
.collect();
|
||||
let allowed_mints = allowed_mints?;
|
||||
|
||||
// Parse excluded mints from CLI arguments
|
||||
let excluded_mints: Result<Vec<MintUrl>, _> = sub_command_args
|
||||
.excluded_mints
|
||||
.iter()
|
||||
@@ -229,45 +262,44 @@ pub async fn send(
|
||||
.collect();
|
||||
let excluded_mints = excluded_mints?;
|
||||
|
||||
// Create MultiMintSendOptions from CLI arguments
|
||||
let multi_mint_options = cdk::wallet::multi_mint_wallet::MultiMintSendOptions {
|
||||
allow_transfer: sub_command_args.allow_transfer,
|
||||
max_transfer_amount: sub_command_args.max_transfer_amount.map(Amount::from),
|
||||
allowed_mints,
|
||||
excluded_mints,
|
||||
send_options: send_options.clone(),
|
||||
};
|
||||
// Prepare and confirm the send based on mint selection
|
||||
let token = if let Some(specific_mint) = selected_mint {
|
||||
// User selected a specific mint
|
||||
let multi_mint_options = cdk::wallet::multi_mint_wallet::MultiMintSendOptions {
|
||||
allow_transfer: sub_command_args.allow_transfer,
|
||||
max_transfer_amount: sub_command_args.max_transfer_amount.map(Amount::from),
|
||||
allowed_mints: vec![specific_mint.clone()], // Use selected mint as the only allowed mint
|
||||
excluded_mints,
|
||||
send_options: send_options.clone(),
|
||||
};
|
||||
|
||||
// Use the new unified interface
|
||||
let token = if let Some(mint_url) = &sub_command_args.mint_url {
|
||||
// User specified a mint, use that specific wallet
|
||||
let mint_url = cdk::mint_url::MintUrl::from_str(mint_url)?;
|
||||
let prepared = multi_mint_wallet
|
||||
.prepare_send(mint_url, token_amount, multi_mint_options)
|
||||
.prepare_send(specific_mint, token_amount, multi_mint_options)
|
||||
.await?;
|
||||
|
||||
// Confirm the prepared send (single mint)
|
||||
let memo = send_options.memo.clone();
|
||||
prepared.confirm(memo).await?
|
||||
} else {
|
||||
// Let the wallet automatically select the best mint
|
||||
// First, get balances to find a mint with sufficient funds
|
||||
// User selected "Any" - find the first mint with sufficient balance
|
||||
let balances = multi_mint_wallet.get_balances().await?;
|
||||
|
||||
// Find a mint with sufficient balance
|
||||
let mint_url = balances
|
||||
let best_mint = balances
|
||||
.into_iter()
|
||||
.find(|(_, balance)| *balance >= token_amount)
|
||||
.map(|(mint_url, _)| mint_url)
|
||||
.ok_or_else(|| {
|
||||
anyhow::anyhow!("No mint has sufficient balance for the requested amount")
|
||||
})?;
|
||||
.ok_or_else(|| anyhow!("No mint has sufficient balance for the requested amount"))?;
|
||||
|
||||
let multi_mint_options = cdk::wallet::multi_mint_wallet::MultiMintSendOptions {
|
||||
allow_transfer: sub_command_args.allow_transfer,
|
||||
max_transfer_amount: sub_command_args.max_transfer_amount.map(Amount::from),
|
||||
allowed_mints: vec![best_mint.clone()], // Use the best mint as the only allowed mint
|
||||
excluded_mints,
|
||||
send_options: send_options.clone(),
|
||||
};
|
||||
|
||||
let prepared = multi_mint_wallet
|
||||
.prepare_send(mint_url, token_amount, multi_mint_options)
|
||||
.prepare_send(best_mint, token_amount, multi_mint_options)
|
||||
.await?;
|
||||
|
||||
// Confirm the prepared send (multi mint)
|
||||
let memo = send_options.memo.clone();
|
||||
prepared.confirm(memo).await?
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user