use crate::cli::*; use crate::client::nac_lens::NrpcClient; use crate::config::Config; use crate::error::{CliError, Result}; use crate::utils::*; use colored::Colorize; use dialoguer::Password; use std::fs; pub async fn execute(cmd: &ContractCommands, _cli: &Cli) -> Result<()> { match cmd { ContractCommands::Deploy { wasm_file, from, init_args } => { deploy_contract(wasm_file, from, init_args.as_deref()).await } ContractCommands::Call { address, method, args, from } => { call_contract(address, method, args.as_deref(), from).await } ContractCommands::Query { address, method, args } => { query_contract(address, method, args.as_deref()).await } ContractCommands::Code { address } => { show_contract_code(address).await } } } /// 部署Charter合约 async fn deploy_contract( wasm_file: &str, from: &str, init_args: Option<&str>, ) -> Result<()> { // 验证地址格式 validate_address(from)?; // 读取WASM文件(或字节码) print_info(&format!("读取合约文件: {}", wasm_file)); let bytecode = fs::read_to_string(wasm_file) .map_err(|e| CliError::Io(format!("读取合约文件失败: {}", e)))?; let bytecode = bytecode.trim(); // 验证字节码格式 if !bytecode.starts_with("0x") { return Err(CliError::InvalidInput("字节码必须以0x开头".to_string())); } println!(); println!("{}", "部署Charter合约".bold()); println!("{}", "=".repeat(80)); println!(); println!("{:12} {}", "部署者:".bold(), from.green()); println!("{:12} {} 字节", "字节码:".bold(), bytecode.len() / 2 - 1); if let Some(args) = init_args { println!("{:12} {}", "初始化参数:".bold(), args); } println!(); // 获取密码 let password = Password::new() .with_prompt("请输入账户密码") .interact() .map_err(|e| CliError::Io(format!("读取密码失败: {}", e)))?; // 验证密码 let manager = KeystoreManager::default()?; if !manager.verify_password(from, &password)? { return Err(CliError::Crypto("密码错误".to_string())); } // 加载配置 let config = Config::load() .map_err(|_| CliError::Config("未找到配置文件,请先运行 'nac config init'".to_string()))?; // 创建RPC客户端 let client = NrpcClient::new(config.get_current_rpc_url()); // 解析参数 let args_json: Vec = if let Some(args_str) = init_args { serde_json::from_str(args_str) .map_err(|e| CliError::InvalidInput(format!("解析参数失败: {}", e)))? } else { Vec::new() }; // 部署合约 print_info("部署合约到网络..."); let contract_address = client.deploy_contract(bytecode, args_json).await?; print_success("合约部署成功!"); println!(); println!("{}", "合约地址:".bold()); println!(" {}", contract_address.green()); println!(); println!("提示: 使用 'nac contract code {}' 查询合约信息", contract_address); println!(); Ok(()) } /// 调用合约方法(状态变更) async fn call_contract( address: &str, method: &str, args: Option<&str>, from: &str, ) -> Result<()> { // 验证地址格式 validate_address(address)?; validate_address(from)?; println!(); println!("{}", "调用合约方法".bold()); println!("{}", "=".repeat(80)); println!(); println!("{:12} {}", "合约:".bold(), address.green()); println!("{:12} {}", "方法:".bold(), method.cyan()); println!("{:12} {}", "调用者:".bold(), from.green()); if let Some(a) = args { println!("{:12} {}", "参数:".bold(), a); } println!(); // 获取密码 let password = Password::new() .with_prompt("请输入账户密码") .interact() .map_err(|e| CliError::Io(format!("读取密码失败: {}", e)))?; // 验证密码 let manager = KeystoreManager::default()?; if !manager.verify_password(from, &password)? { return Err(CliError::Crypto("密码错误".to_string())); } // 加载配置 let config = Config::load() .map_err(|_| CliError::Config("未找到配置文件,请先运行 'nac config init'".to_string()))?; // 创建RPC客户端 let client = NrpcClient::new(config.get_current_rpc_url()); // 解析参数 let args_json: Vec = if let Some(args_str) = args { serde_json::from_str(args_str) .map_err(|e| CliError::InvalidInput(format!("解析参数失败: {}", e)))? } else { Vec::new() }; // 发送交易 print_info("发送合约交易到网络..."); let tx_hash = client.send_contract_tx(address, method, args_json).await?; print_success("交易已发送!"); println!(); println!("{}", "交易哈希:".bold()); println!(" {}", tx_hash.cyan()); println!(); println!("提示: 使用 'nac tx show {}' 查询交易状态", tx_hash); println!(); Ok(()) } /// 查询合约状态(只读) async fn query_contract( address: &str, method: &str, args: Option<&str>, ) -> Result<()> { // 验证地址格式 validate_address(address)?; // 加载配置 let config = Config::load() .map_err(|_| CliError::Config("未找到配置文件,请先运行 'nac config init'".to_string()))?; // 创建RPC客户端 let client = NrpcClient::new(config.get_current_rpc_url()); // 解析参数 let args_json: Vec = if let Some(args_str) = args { serde_json::from_str(args_str) .map_err(|e| CliError::InvalidInput(format!("解析参数失败: {}", e)))? } else { Vec::new() }; print_info(&format!("查询合约方法: {}...", method)); // 调用合约 let result = client.call_contract(address, method, args_json).await?; println!(); println!("{}", "查询结果".bold()); println!("{}", "=".repeat(80)); println!(); println!("{}", serde_json::to_string_pretty(&result).unwrap_or_default()); println!(); Ok(()) } /// 查看合约代码 async fn show_contract_code(address: &str) -> Result<()> { // 验证地址格式 validate_address(address)?; // 加载配置 let config = Config::load() .map_err(|_| CliError::Config("未找到配置文件,请先运行 'nac config init'".to_string()))?; // 创建RPC客户端 let client = NrpcClient::new(config.get_current_rpc_url()); print_info(&format!("查询合约: {}...", address)); println!(); println!("{}", "合约信息".bold()); println!("{}", "=".repeat(80)); println!(); println!("{:12} {}", "地址:".bold(), address.green()); // 查询字节码 match client.get_contract_code(address).await { Ok(code) => { let code_size = if code.starts_with("0x") { (code.len() - 2) / 2 } else { code.len() / 2 }; println!("{:12} {} 字节", "字节码:".bold(), code_size); if code_size > 0 { println!("{:12} {}", "类型:".bold(), "Charter智能合约".cyan()); println!(); println!("{}", "字节码:".bold()); println!("{}", code); } else { println!("{:12} {}", "类型:".bold(), "普通账户".yellow()); } } Err(e) => { print_warning(&format!("查询字节码失败: {}", e)); } } // 查询余额 match client.get_balance(address).await { Ok(balance) => { println!(); println!("{:12} {} NAC", "余额:".bold(), balance.cyan()); } Err(e) => { print_warning(&format!("查询余额失败: {}", e)); } } println!(); Ok(()) }