use nac_cross_chain_bridge::{ init_logger, manager::{BridgeManager, BridgeManagerImpl}, eth_listener::EthereumListener, ChainId, VERSION, }; use std::sync::Arc; use tokio::signal; /// 中继节点配置 #[derive(Debug, Clone)] struct RelayConfig { /// 数据库路径 db_path: String, /// NAC RPC URL nac_rpc_url: String, /// 以太坊 RPC URL eth_rpc_url: String, /// BSC RPC URL bsc_rpc_url: Option, /// NAC桥接合约地址 nac_bridge_address: [u8; 32], /// 以太坊桥接合约地址 eth_bridge_address: [u8; 32], } impl Default for RelayConfig { fn default() -> Self { Self { db_path: "./bridge_data".to_string(), nac_rpc_url: "http://localhost:8545".to_string(), eth_rpc_url: "http://localhost:8546".to_string(), bsc_rpc_url: None, nac_bridge_address: [0u8; 32], eth_bridge_address: [0u8; 32], } } } /// 从环境变量加载配置 fn load_config_from_env() -> RelayConfig { let mut config = RelayConfig::default(); if let Ok(db_path) = std::env::var("BRIDGE_DB_PATH") { config.db_path = db_path; } if let Ok(nac_rpc) = std::env::var("NAC_RPC_URL") { config.nac_rpc_url = nac_rpc; } if let Ok(eth_rpc) = std::env::var("ETH_RPC_URL") { config.eth_rpc_url = eth_rpc; } if let Ok(bsc_rpc) = std::env::var("BSC_RPC_URL") { config.bsc_rpc_url = Some(bsc_rpc); } // TODO: 从环境变量加载合约地址 config } /// 初始化桥接管理器 async fn initialize_bridge(config: &RelayConfig) -> anyhow::Result> { log::info!("Initializing bridge manager..."); log::info!("Database path: {}", config.db_path); log::info!("NAC RPC: {}", config.nac_rpc_url); log::info!("Ethereum RPC: {}", config.eth_rpc_url); // 创建桥接管理器 let manager = Arc::new(BridgeManagerImpl::new(&config.db_path)?); // 初始化 manager.initialize().await?; // 注册以太坊监听器 let eth_listener = Arc::new(EthereumListener::new( ChainId::Ethereum, config.eth_rpc_url.clone(), config.eth_bridge_address, )); manager.register_listener(ChainId::Ethereum, eth_listener).await?; // 如果配置了BSC,也注册BSC监听器 if let Some(bsc_rpc) = &config.bsc_rpc_url { let bsc_listener = Arc::new(EthereumListener::new( ChainId::BSC, bsc_rpc.clone(), config.eth_bridge_address, // TODO: 使用独立的BSC合约地址 )); manager.register_listener(ChainId::BSC, bsc_listener).await?; } log::info!("Bridge manager initialized successfully"); Ok(manager) } /// 启动中继节点 async fn start_relay(manager: Arc) -> anyhow::Result<()> { log::info!("Starting relay node..."); // 启动桥接 manager.start().await?; log::info!("Relay node started successfully"); log::info!("Press Ctrl+C to stop"); // 等待退出信号 signal::ctrl_c().await?; log::info!("Received shutdown signal, stopping relay node..."); // 停止桥接 manager.stop().await?; log::info!("Relay node stopped"); Ok(()) } /// 显示状态 async fn show_status(manager: &BridgeManagerImpl) -> anyhow::Result<()> { let status = manager.get_status().await?; println!("=== NAC Bridge Relay Status ==="); println!("Running: {}", status.is_running); println!("Paused: {}", status.is_paused); println!("Total Locked: {}", status.total_locked); println!("Total Unlocked: {}", status.total_unlocked); println!("Active Validators: {}", status.active_validators); println!("Active Relayers: {}", status.active_relayers); println!("=============================="); Ok(()) } #[tokio::main] async fn main() -> anyhow::Result<()> { // 初始化日志 init_logger(); log::info!("NAC Bridge Relay v{}", VERSION); log::info!("================================="); // 加载配置 let config = load_config_from_env(); // 解析命令行参数 let args: Vec = std::env::args().collect(); let command = args.get(1).map(|s| s.as_str()).unwrap_or("start"); match command { "start" => { // 初始化桥接 let manager = initialize_bridge(&config).await?; // 启动中继节点 start_relay(manager).await?; } "status" => { // 创建桥接管理器(只读模式) let manager = BridgeManagerImpl::new(&config.db_path)?; manager.initialize().await?; // 显示状态 show_status(&manager).await?; } "pause" => { let manager = BridgeManagerImpl::new(&config.db_path)?; manager.initialize().await?; manager.pause().await?; log::info!("Bridge paused"); } "resume" => { let manager = BridgeManagerImpl::new(&config.db_path)?; manager.initialize().await?; manager.resume().await?; log::info!("Bridge resumed"); } "version" => { println!("NAC Bridge Relay v{}", VERSION); } "help" | "--help" | "-h" => { println!("NAC Bridge Relay v{}", VERSION); println!("\nUsage: nac-bridge-relay [COMMAND]"); println!("\nCommands:"); println!(" start Start the relay node (default)"); println!(" status Show bridge status"); println!(" pause Pause the bridge"); println!(" resume Resume the bridge"); println!(" version Show version"); println!(" help Show this help message"); println!("\nEnvironment Variables:"); println!(" BRIDGE_DB_PATH Database path (default: ./bridge_data)"); println!(" NAC_RPC_URL NAC RPC URL (default: http://localhost:8545)"); println!(" ETH_RPC_URL Ethereum RPC URL (default: http://localhost:8546)"); println!(" BSC_RPC_URL BSC RPC URL (optional)"); } _ => { eprintln!("Unknown command: {}", command); eprintln!("Run 'nac-bridge-relay help' for usage"); std::process::exit(1); } } Ok(()) } #[cfg(test)] mod tests { use super::*; #[test] fn test_default_config() { let config = RelayConfig::default(); assert_eq!(config.db_path, "./bridge_data"); assert_eq!(config.nac_rpc_url, "http://localhost:8545"); } #[test] fn test_load_config_from_env() { std::env::set_var("BRIDGE_DB_PATH", "/tmp/test_bridge"); std::env::set_var("NAC_RPC_URL", "http://test:8545"); let config = load_config_from_env(); assert_eq!(config.db_path, "/tmp/test_bridge"); assert_eq!(config.nac_rpc_url, "http://test:8545"); std::env::remove_var("BRIDGE_DB_PATH"); std::env::remove_var("NAC_RPC_URL"); } }