| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209 | 
							- use std::str::FromStr;
 
- use anyhow::{bail, Result};
 
- use cdk::mint_url::MintUrl;
 
- use cdk::wallet::multi_mint_wallet::TransferMode;
 
- use cdk::wallet::MultiMintWallet;
 
- use cdk::Amount;
 
- use clap::Args;
 
- use crate::utils::get_number_input;
 
- #[derive(Args)]
 
- pub struct TransferSubCommand {
 
-     /// Source mint URL to transfer from (optional - will prompt if not provided)
 
-     #[arg(long)]
 
-     source_mint: Option<String>,
 
-     /// Target mint URL to transfer to (optional - will prompt if not provided)
 
-     #[arg(long)]
 
-     target_mint: Option<String>,
 
-     /// Amount to transfer (optional - will prompt if not provided)
 
-     #[arg(short, long, conflicts_with = "full_balance")]
 
-     amount: Option<u64>,
 
-     /// Transfer all available balance from source mint
 
-     #[arg(long, conflicts_with = "amount")]
 
-     full_balance: bool,
 
- }
 
- /// Helper function to select a mint from available mints
 
- async fn select_mint(
 
-     multi_mint_wallet: &MultiMintWallet,
 
-     prompt: &str,
 
-     exclude_mint: Option<&MintUrl>,
 
- ) -> Result<MintUrl> {
 
-     let balances = multi_mint_wallet.get_balances().await?;
 
-     // Filter out excluded mint if provided
 
-     let available_mints: Vec<_> = balances
 
-         .iter()
 
-         .filter(|(url, _)| exclude_mint.is_none_or(|excluded| url != &excluded))
 
-         .collect();
 
-     if available_mints.is_empty() {
 
-         bail!("No available mints found");
 
-     }
 
-     println!("\nAvailable mints:");
 
-     for (i, (mint_url, balance)) in available_mints.iter().enumerate() {
 
-         println!(
 
-             "  {}: {} - {} {}",
 
-             i,
 
-             mint_url,
 
-             balance,
 
-             multi_mint_wallet.unit()
 
-         );
 
-     }
 
-     let mint_number: usize = get_number_input(prompt)?;
 
-     available_mints
 
-         .get(mint_number)
 
-         .map(|(url, _)| (*url).clone())
 
-         .ok_or_else(|| anyhow::anyhow!("Invalid mint number"))
 
- }
 
- pub async fn transfer(
 
-     multi_mint_wallet: &MultiMintWallet,
 
-     sub_command_args: &TransferSubCommand,
 
- ) -> Result<()> {
 
-     // Check total balance across all wallets
 
-     let total_balance = multi_mint_wallet.total_balance().await?;
 
-     if total_balance == Amount::ZERO {
 
-         bail!("No funds available");
 
-     }
 
-     // Get source mint URL either from args or by prompting user
 
-     let source_mint_url = if let Some(source_mint) = &sub_command_args.source_mint {
 
-         let url = MintUrl::from_str(source_mint)?;
 
-         // Verify the mint is in the wallet
 
-         if !multi_mint_wallet.has_mint(&url).await {
 
-             bail!(
 
-                 "Source mint {} is not in the wallet. Please add it first.",
 
-                 url
 
-             );
 
-         }
 
-         url
 
-     } else {
 
-         // Show available mints and let user select source
 
-         select_mint(
 
-             multi_mint_wallet,
 
-             "Enter source mint number to transfer from",
 
-             None,
 
-         )
 
-         .await?
 
-     };
 
-     // Get target mint URL either from args or by prompting user
 
-     let target_mint_url = if let Some(target_mint) = &sub_command_args.target_mint {
 
-         let url = MintUrl::from_str(target_mint)?;
 
-         // Verify the mint is in the wallet
 
-         if !multi_mint_wallet.has_mint(&url).await {
 
-             bail!(
 
-                 "Target mint {} is not in the wallet. Please add it first.",
 
-                 url
 
-             );
 
-         }
 
-         url
 
-     } else {
 
-         // Show available mints (excluding source) and let user select target
 
-         select_mint(
 
-             multi_mint_wallet,
 
-             "Enter target mint number to transfer to",
 
-             Some(&source_mint_url),
 
-         )
 
-         .await?
 
-     };
 
-     // Ensure source and target are different
 
-     if source_mint_url == target_mint_url {
 
-         bail!("Source and target mints must be different");
 
-     }
 
-     // Check source mint balance
 
-     let balances = multi_mint_wallet.get_balances().await?;
 
-     let source_balance = balances
 
-         .get(&source_mint_url)
 
-         .copied()
 
-         .unwrap_or(Amount::ZERO);
 
-     if source_balance == Amount::ZERO {
 
-         bail!("Source mint has no balance to transfer");
 
-     }
 
-     // Determine transfer mode based on user input
 
-     let transfer_mode = if sub_command_args.full_balance {
 
-         println!(
 
-             "\nTransferring full balance ({} {}) from {} to {}...",
 
-             source_balance,
 
-             multi_mint_wallet.unit(),
 
-             source_mint_url,
 
-             target_mint_url
 
-         );
 
-         TransferMode::FullBalance
 
-     } else {
 
-         let amount = match sub_command_args.amount {
 
-             Some(amt) => Amount::from(amt),
 
-             None => Amount::from(get_number_input::<u64>(&format!(
 
-                 "Enter amount to transfer in {}",
 
-                 multi_mint_wallet.unit()
 
-             ))?),
 
-         };
 
-         if source_balance < amount {
 
-             bail!(
 
-                 "Insufficient funds in source mint. Available: {} {}, Required: {} {}",
 
-                 source_balance,
 
-                 multi_mint_wallet.unit(),
 
-                 amount,
 
-                 multi_mint_wallet.unit()
 
-             );
 
-         }
 
-         println!(
 
-             "\nTransferring {} {} from {} to {}...",
 
-             amount,
 
-             multi_mint_wallet.unit(),
 
-             source_mint_url,
 
-             target_mint_url
 
-         );
 
-         TransferMode::ExactReceive(amount)
 
-     };
 
-     // Perform the transfer
 
-     let transfer_result = multi_mint_wallet
 
-         .transfer(&source_mint_url, &target_mint_url, transfer_mode)
 
-         .await?;
 
-     println!("\nTransfer completed successfully!");
 
-     println!(
 
-         "Amount sent: {} {}",
 
-         transfer_result.amount_sent,
 
-         multi_mint_wallet.unit()
 
-     );
 
-     println!(
 
-         "Amount received: {} {}",
 
-         transfer_result.amount_received,
 
-         multi_mint_wallet.unit()
 
-     );
 
-     if transfer_result.fees_paid > Amount::ZERO {
 
-         println!(
 
-             "Fees paid: {} {}",
 
-             transfer_result.fees_paid,
 
-             multi_mint_wallet.unit()
 
-         );
 
-     }
 
-     println!("\nUpdated balances:");
 
-     println!(
 
-         "  Source mint ({}): {} {}",
 
-         source_mint_url,
 
-         transfer_result.source_balance_after,
 
-         multi_mint_wallet.unit()
 
-     );
 
-     println!(
 
-         "  Target mint ({}): {} {}",
 
-         target_mint_url,
 
-         transfer_result.target_balance_after,
 
-         multi_mint_wallet.unit()
 
-     );
 
-     Ok(())
 
- }
 
 
  |