use crate::{
chain::client::QuantusClient,
cli::send::{
batch_transfer, get_batch_limits, load_transfers_from_file, validate_and_format_amount,
},
error::Result,
log_info, log_print, log_success,
};
use clap::Subcommand;
use colored::Colorize;
#[derive(Subcommand, Debug)]
pub enum BatchCommands {
Send {
#[arg(short, long)]
from: String,
#[arg(short, long)]
password: Option<String>,
#[arg(long)]
password_file: Option<String>,
#[arg(long)]
tip: Option<String>,
#[arg(long)]
batch_file: Option<String>,
#[arg(long)]
count: Option<u32>,
#[arg(long)]
to: Option<String>,
#[arg(long)]
amount: Option<String>,
},
Config {
#[arg(long)]
limits: bool,
#[arg(long)]
info: bool,
},
}
pub async fn handle_batch_command(
command: BatchCommands,
node_url: &str,
execution_mode: crate::cli::common::ExecutionMode,
) -> Result<()> {
match command {
BatchCommands::Send {
from,
password,
password_file,
tip,
batch_file,
count,
to,
amount,
} =>
handle_batch_send_command(
from,
node_url,
password,
password_file,
tip,
batch_file,
count,
to,
amount,
execution_mode,
)
.await,
BatchCommands::Config { limits, info } =>
handle_batch_config_command(node_url, limits, info).await,
}
}
async fn handle_batch_send_command(
from_wallet: String,
node_url: &str,
password: Option<String>,
password_file: Option<String>,
tip: Option<String>,
batch_file: Option<String>,
count: Option<u32>,
to: Option<String>,
amount: Option<String>,
execution_mode: crate::cli::common::ExecutionMode,
) -> Result<()> {
let quantus_client = QuantusClient::new(node_url).await?;
let transfers = if let Some(file_path) = batch_file {
load_transfers_from_file(&file_path).await?
} else if let (Some(count_val), Some(to_addr), Some(amount_str)) = (count, to, amount) {
let (parsed_amount, _) = validate_and_format_amount(&quantus_client, &amount_str).await?;
let mut transfers = Vec::new();
for _ in 0..count_val {
transfers.push((to_addr.clone(), parsed_amount));
}
transfers
} else {
return Err(crate::error::QuantusError::Generic(
"Either --batch-file or (--count + --to + --amount) must be provided".to_string(),
));
};
if transfers.is_empty() {
return Err(crate::error::QuantusError::Generic("No transfers to process".to_string()));
}
log_info!("🚀 Initiating batch transfer with {} transfers", transfers.len());
let tip_amount = if let Some(tip_str) = tip {
let (tip_val, _) = validate_and_format_amount(&quantus_client, &tip_str).await?;
Some(tip_val)
} else {
None
};
let keypair = crate::wallet::load_keypair_from_wallet(&from_wallet, password, password_file)?;
let from_account_id = keypair.to_account_id_ss58check();
let balance = crate::cli::send::get_balance(&quantus_client, &from_account_id).await?;
let total_amount: u128 = transfers.iter().map(|(_, amount)| amount).sum();
let estimated_fee = 50_000_000_000u128;
if balance < total_amount + estimated_fee {
let formatted_balance =
crate::cli::send::format_balance_with_symbol(&quantus_client, balance).await?;
let formatted_needed = crate::cli::send::format_balance_with_symbol(
&quantus_client,
total_amount + estimated_fee,
)
.await?;
return Err(crate::error::QuantusError::Generic(format!(
"Insufficient balance. Have: {formatted_balance}, Need: {formatted_needed} (including estimated fees)"
)));
}
let tx_hash =
batch_transfer(&quantus_client, &keypair, transfers, tip_amount, execution_mode).await?;
log_print!(
"✅ {} Batch transaction submitted! Hash: {:?}",
"SUCCESS".bright_green().bold(),
tx_hash
);
log_success!("🎉 {} Batch transaction confirmed!", "FINISHED".bright_green().bold());
let new_balance = crate::cli::send::get_balance(&quantus_client, &from_account_id).await?;
let formatted_new_balance =
crate::cli::send::format_balance_with_symbol(&quantus_client, new_balance).await?;
log_print!("💰 New balance: {}", formatted_new_balance.bright_yellow());
Ok(())
}
async fn handle_batch_config_command(
node_url: &str,
show_limits: bool,
show_info: bool,
) -> Result<()> {
let quantus_client = QuantusClient::new(node_url).await?;
if show_limits {
log_info!("🔍 Checking batch transfer limits for chain...");
let (safe_limit, recommended_limit) = get_batch_limits(&quantus_client).await?;
log_print!("📊 {} Batch Transfer Limits", "CHAIN".bright_cyan().bold());
log_print!(" • Safe batch size: {} transfers", safe_limit.to_string().bright_green());
log_print!(
" • Maximum batch size: {} transfers",
recommended_limit.to_string().bright_yellow()
);
log_print!(" • For larger batches, split into multiple transactions");
}
if show_info {
log_print!("ℹ️ {} Batch Transfer Information", "CONFIG".bright_cyan().bold());
log_print!(" • Batch transfers use utility.batch() pallet");
log_print!(" • All transfers in one transaction (atomic)");
log_print!(" • Single nonce used for all transfers");
log_print!(" • Lower fees compared to individual transfers");
log_print!(" • If one transfer fails, entire batch fails");
log_print!("");
log_print!("📝 {} Usage Examples", "EXAMPLES".bright_cyan().bold());
log_print!(" quantus batch send --from alice --count 100 --to bob --amount 1000");
log_print!(" quantus batch send --from alice --batch-file transfers.json");
log_print!(" quantus batch config --limits");
}
if !show_limits && !show_info {
let quantus_client = QuantusClient::new(node_url).await?;
log_info!("🔍 Checking batch transfer limits for chain...");
let (safe_limit, recommended_limit) = get_batch_limits(&quantus_client).await?;
log_print!("📊 {} Batch Transfer Limits", "CHAIN".bright_cyan().bold());
log_print!(" • Safe batch size: {} transfers", safe_limit.to_string().bright_green());
log_print!(
" • Maximum batch size: {} transfers",
recommended_limit.to_string().bright_yellow()
);
log_print!(" • For larger batches, split into multiple transactions");
log_print!("ℹ️ {} Batch Transfer Information", "CONFIG".bright_cyan().bold());
log_print!(" • Batch transfers use utility.batch() pallet");
log_print!(" • All transfers in one transaction (atomic)");
log_print!(" • Single nonce used for all transfers");
log_print!(" • Lower fees compared to individual transfers");
log_print!(" • If one transfer fails, entire batch fails");
log_print!("");
log_print!("📝 {} Usage Examples", "EXAMPLES".bright_cyan().bold());
log_print!(" quantus batch send --from alice --count 100 --to bob --amount 1000");
log_print!(" quantus batch send --from alice --batch-file transfers.json");
log_print!(" quantus batch config --limits");
}
Ok(())
}