// NAC钱包CLI工具 - 简化版 // 提供基本的命令行钱包功能 use clap::{Parser, Subcommand}; use nac_wallet_core::{ key_manager::{KeyPair, SignatureAlgorithm}, address::{StructuredAddress, AccountType, WalletKYCLevel}, storage::KeyStore, nrpc_wrapper::NRPCWrapper, }; use std::path::PathBuf; #[derive(Parser)] #[command(name = "nac-wallet")] #[command(about = "NAC公链命令行钱包", long_about = None)] struct Cli { #[command(subcommand)] command: Commands, } #[derive(Subcommand)] enum Commands { /// 创建新钱包 Create { /// 密码 #[arg(long)] password: String, /// 钱包文件路径 #[arg(long, default_value = "./wallet.json")] output: PathBuf, }, /// 查询余额 Balance { /// 钱包文件路径 #[arg(long, default_value = "./wallet.json")] wallet: PathBuf, /// RPC端点 #[arg(long, default_value = "https://rpc.newassetchain.io")] rpc: String, }, /// 查看钱包信息 Info { /// 钱包文件路径 #[arg(long, default_value = "./wallet.json")] wallet: PathBuf, }, /// 列出所有钱包 List { /// 钱包目录 #[arg(long, default_value = ".")] dir: PathBuf, }, } #[tokio::main] async fn main() { let cli = Cli::parse(); match cli.command { Commands::Create { password, output } => { if let Err(e) = create_wallet(&password, &output).await { eprintln!("❌ 创建钱包失败: {}", e); std::process::exit(1); } } Commands::Balance { wallet, rpc } => { if let Err(e) = query_balance(&wallet, &rpc).await { eprintln!("❌ 查询余额失败: {}", e); std::process::exit(1); } } Commands::Info { wallet } => { if let Err(e) = show_wallet_info(&wallet).await { eprintln!("❌ 查看钱包信息失败: {}", e); std::process::exit(1); } } Commands::List { dir } => { if let Err(e) = list_wallets(&dir).await { eprintln!("❌ 列出钱包失败: {}", e); std::process::exit(1); } } } } async fn create_wallet( password: &str, output: &PathBuf, ) -> Result<(), Box> { println!("🔐 正在创建NAC钱包..."); // 生成密钥对 let keypair = KeyPair::generate(SignatureAlgorithm::Ed25519) .map_err(|e| format!("Failed to generate keypair: {}", e))?; // 计算公钥哈希 let pubkey_hash = keypair.public_key_hash(); // 创建结构化地址 let address = StructuredAddress::new( AccountType::Personal, WalletKYCLevel::None, 156, // 中国 pubkey_hash, ); println!("✅ 地址: {}", hex::encode(address.to_bytes())); println!("📝 账户类型: Personal"); println!("🔒 KYC等级: None"); println!("🌍 区域代码: 156 (中国)"); println!("🔑 签名算法: Ed25519"); // 保存密钥库 let keystore = KeyStore::encrypt(&keypair, password)?; keystore.save_to_file(output)?; println!("💾 钱包已保存到: {}", output.display()); println!("\n⚠️ 请妥善保管密码,密码丢失将无法恢复钱包!"); Ok(()) } async fn query_balance( wallet_path: &PathBuf, rpc_url: &str, ) -> Result<(), Box> { println!("💰 正在查询余额..."); // 读取钱包文件 let keystore = KeyStore::load_from_file(wallet_path)?; let address_bytes = keystore.address; // 创建NRPC客户端 let client = NRPCWrapper::new(rpc_url); // 查询XTZH余额 match client.get_balance(&address_bytes, Some("xtzh")).await { Ok(balance) => { println!("✅ 地址: {}", hex::encode(address_bytes)); println!("💵 XTZH余额: {}", balance); } Err(e) => { println!("⚠️ 无法连接到RPC节点: {}", e); println!("💡 请确保RPC端点正确且节点正在运行"); } } Ok(()) } async fn show_wallet_info( wallet_path: &PathBuf, ) -> Result<(), Box> { println!("ℹ️ 正在查看钱包信息..."); // 读取钱包文件 let keystore = KeyStore::load_from_file(wallet_path)?; println!("\n💼 钱包信息"); println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"); println!("📁 文件路径: {}", wallet_path.display()); println!("📍 地址: {}", hex::encode(keystore.address)); println!("🔐 加密算法: AES-256-GCM"); println!("🔑 密钥派生: PBKDF2-SHA256 (100,000次迭代)"); Ok(()) } async fn list_wallets( dir: &PathBuf, ) -> Result<(), Box> { println!("📂 正在列出钱包..."); let mut count = 0; // 遍历目录查找.json文件 if let Ok(entries) = std::fs::read_dir(dir) { for entry in entries.flatten() { if let Ok(file_type) = entry.file_type() { if file_type.is_file() { if let Some(ext) = entry.path().extension() { if ext == "json" { // 尝试读取为KeyStore if let Ok(keystore) = KeyStore::load_from_file(&entry.path()) { count += 1; println!("\n💼 钱包 #{}", count); println!(" 文件: {}", entry.path().display()); println!(" 地址: {}", hex::encode(keystore.address)); } } } } } } } if count == 0 { println!("❌ 未找到钱包文件"); } else { println!("\n✅ 共找到 {} 个钱包", count); } Ok(()) }