mod blockchain; mod cli; mod wallet; mod network; mod api; use blockchain::{Blockchain, Transaction}; use clap::Parser; use cli::{Cli, Commands}; use std::fs; use wallet::Wallet; const BLOCKCHAIN_FILE: &str = "blockchain.json"; #[tokio::main] async fn main() { let cli = Cli::parse(); let mut blockchain = load_blockchain(); match cli.command { Commands::Wallet { atproto_did, export } => { let wallet = Wallet::new(atproto_did); println!("New wallet created!"); println!("Address: {}", wallet.address); if let Some(private_key) = wallet.get_private_key_hex() { println!("Private key: {}", private_key); println!("IMPORTANT: Save this private key securely!"); } if let Some(ref did) = wallet.atproto_did { println!("ATProto DID: {}", did); } if let Some(path) = export { match wallet.export_to_file(&path) { Ok(()) => println!("Wallet exported to: {}", path), Err(e) => println!("Failed to export wallet: {}", e), } } } Commands::Import { path } => { match Wallet::import_from_file(&path) { Ok(wallet) => { println!("Wallet imported successfully!"); println!("Address: {}", wallet.address); if let Some(ref did) = wallet.atproto_did { println!("ATProto DID: {}", did); } } Err(e) => println!("Failed to import wallet: {}", e), } } Commands::Balance { address } => { let balance = blockchain.get_balance(&address); println!("Balance for {}: {} AIC", address, balance); } Commands::Send { to, amount, private_key, atproto_did } => { match Wallet::from_private_key(&private_key, atproto_did) { Ok(wallet) => { let mut transaction = Transaction::new( wallet.address.clone(), to.clone(), amount, wallet.atproto_did.clone(), ); if let Some(ref signing_key) = wallet.private_key { transaction.sign(signing_key); match blockchain.add_transaction(transaction) { Ok(()) => { save_blockchain(&blockchain); println!("Transaction added to pending transactions"); println!("From: {}", wallet.address); println!("To: {}", to); println!("Amount: {} AIC", amount); } Err(e) => println!("Error: {}", e), } } } Err(e) => println!("Error loading wallet: {}", e), } } Commands::Mine { address } => { if blockchain.pending_transactions.is_empty() { println!("No pending transactions to mine"); } else { println!("Mining block..."); let pending_count = blockchain.pending_transactions.len(); blockchain.mine_pending_transactions(address.clone()); save_blockchain(&blockchain); println!("Block mined successfully!"); println!("Transactions included: {}", pending_count); println!("Mining reward sent to: {}", address); } } Commands::Info => { println!("Blockchain Info:"); println!("Total blocks: {}", blockchain.chain.len()); println!("Difficulty: {}", blockchain.difficulty); println!("Mining reward: {} AIC", blockchain.mining_reward); println!("Pending transactions: {}", blockchain.pending_transactions.len()); if let Some(latest) = blockchain.chain.last() { println!("\nLatest block:"); println!(" Index: {}", latest.index); println!(" Hash: {}", latest.hash); println!(" Timestamp: {}", latest.timestamp); println!(" Transactions: {}", latest.transactions.len()); } } Commands::Validate => { if blockchain.is_valid() { println!("Blockchain is valid ✓"); } else { println!("Blockchain is invalid ✗"); } } Commands::Server { port } => { println!("Starting API server on port {}", port); api::run_api_server(blockchain, port).await; } Commands::Node { port } => { println!("Starting P2P node on port {}", port); let (tx, mut rx) = tokio::sync::mpsc::channel(100); let p2p_network = network::P2PNetwork::new(tx, port).await .expect("Failed to create P2P network"); tokio::spawn(async move { p2p_network.run().await; }); // Handle incoming messages while let Some(msg) = rx.recv().await { match msg { network::MessageType::NewTransaction(tx) => { println!("Received new transaction"); if let Err(e) = blockchain.add_transaction(tx) { eprintln!("Failed to add transaction: {}", e); } save_blockchain(&blockchain); } network::MessageType::NewBlock(block) => { println!("Received new block"); // TODO: Validate and add block } _ => {} } } } } } fn load_blockchain() -> Blockchain { if let Ok(data) = fs::read_to_string(BLOCKCHAIN_FILE) { if let Ok(blockchain) = serde_json::from_str(&data) { return blockchain; } } Blockchain::new() } fn save_blockchain(blockchain: &Blockchain) { if let Ok(data) = serde_json::to_string_pretty(blockchain) { let _ = fs::write(BLOCKCHAIN_FILE, data); } }