Files
coin/src/main.rs
2025-06-12 07:36:25 +09:00

178 lines
6.5 KiB
Rust

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);
}
}