NAC_Blockchain/_archive/wallet_legacy_v1/nac-wallet-cli/src/main.rs

214 lines
6.1 KiB
Rust
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// NAC钱包CLI工具 - 简化版
// 提供基本的命令行钱包功能
use clap::{Parser, Subcommand};
use nac_wallet_core::{
key_manager::{KeyPair, SignatureAlgorithm},
address::{StructuredAddress, AccountType, WalletKYCLevel},
storage::KeyStore,
nac_lens_wrapper::NacLensWrapper,
};
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<dyn std::error::Error>> {
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<dyn std::error::Error>> {
println!("💰 正在查询余额...");
// 读取钱包文件
let keystore = KeyStore::load_from_file(wallet_path)?;
let address_bytes = keystore.address;
// 创建NAC Lens客户端
let client = NacLensWrapper::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<dyn std::error::Error>> {
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<dyn std::error::Error>> {
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(())
}