integration_tests.rs
1 // Copyright (c) 2025 ADnet Contributors 2 // SPDX-License-Identifier: Apache-2.0 3 4 //! Integration tests for ADnet unified node 5 //! 6 //! These tests verify end-to-end functionality of the unified ALPHA/DELTA node, 7 //! including trading execution, attestation flow, and cross-chain operations. 8 9 use adnet::AdnetNode; 10 use alphavm::console::network::MainnetV0; 11 12 type CurrentNetwork = MainnetV0; 13 14 /// Test that a node can be created and initialized in dev mode 15 #[tokio::test] 16 async fn test_node_creation_and_init() { 17 // Create a dev node with 4 validators 18 let node = AdnetNode::<CurrentNetwork>::dev(4, 0); 19 20 // Verify configuration 21 assert_eq!(node.config().alpha.rest_port, 3030); 22 assert_eq!(node.config().delta.rest_port, 4030); 23 24 // Initialize the node 25 node.init().await.expect("Failed to initialize node"); 26 27 // Verify state after init 28 let state = node.state().await; 29 assert!(state.is_running); 30 assert_eq!(state.alpha_height, 0); 31 assert_eq!(state.delta_height, 0); 32 } 33 34 /// Test that multiple validator nodes can be created without port conflicts 35 #[tokio::test] 36 async fn test_multiple_validators_config() { 37 let node0 = AdnetNode::<CurrentNetwork>::dev(4, 0); 38 let node1 = AdnetNode::<CurrentNetwork>::dev(4, 1); 39 let node2 = AdnetNode::<CurrentNetwork>::dev(4, 2); 40 let node3 = AdnetNode::<CurrentNetwork>::dev(4, 3); 41 42 // Verify unique ports for each validator 43 assert_eq!(node0.config().alpha.rest_port, 3030); 44 assert_eq!(node1.config().alpha.rest_port, 3031); 45 assert_eq!(node2.config().alpha.rest_port, 3032); 46 assert_eq!(node3.config().alpha.rest_port, 3033); 47 48 assert_eq!(node0.config().delta.rest_port, 4030); 49 assert_eq!(node1.config().delta.rest_port, 4031); 50 assert_eq!(node2.config().delta.rest_port, 4032); 51 assert_eq!(node3.config().delta.rest_port, 4033); 52 53 // Verify unique P2P ports 54 assert_eq!(node0.config().alpha.p2p_port, 4130); 55 assert_eq!(node1.config().alpha.p2p_port, 4131); 56 assert_eq!(node2.config().alpha.p2p_port, 4132); 57 assert_eq!(node3.config().alpha.p2p_port, 4133); 58 } 59 60 /// Test trading execution via DeltaRuntime 61 #[tokio::test] 62 async fn test_trading_execution() { 63 use deltavm_console::Address; 64 use deltavm_execution::{ 65 DeltaRuntime, OrderSide, OrderType, TradingPair, TradingResult, TradingTx, 66 }; 67 68 let mut runtime = DeltaRuntime::new(); 69 70 // Create a test user 71 let user = Address::zero(); 72 73 // Fund the user first (in a real test, this would come from deposit) 74 // Note: Use "AX" for ALPHA token after rebranding 75 runtime 76 .ledger 77 .credit(&user, "AX", 1_000_000) 78 .expect("Failed to credit"); 79 80 // Place a limit buy order 81 let tx = TradingTx::PlaceOrder { 82 pair: TradingPair::DeltaAlpha, 83 side: OrderSide::Buy, 84 quantity: 100, 85 price: Some(1000), 86 order_type: OrderType::Limit, 87 }; 88 89 let result = runtime.execute_trading(user, tx); 90 assert!(result.is_ok()); 91 92 match result.unwrap() { 93 TradingResult::OrderPlaced { match_result, .. } => { 94 assert!(match_result.added_to_book); 95 assert!(match_result.trades.is_empty()); // No matching orders yet 96 } 97 _ => panic!("Expected OrderPlaced result"), 98 } 99 } 100 101 /// Test order matching between two users 102 #[tokio::test] 103 async fn test_order_matching() { 104 use alphavm::console::types::Group; 105 use deltavm_console::Address; 106 use deltavm_execution::{ 107 DeltaRuntime, OrderSide, OrderType, TradingPair, TradingResult, TradingTx, 108 }; 109 110 let mut runtime = DeltaRuntime::new(); 111 112 // Create two test users 113 let buyer = Address::zero(); 114 let generator = Group::<CurrentNetwork>::generator(); 115 let seller = Address::new(generator); 116 117 // Fund both users (AX = ALPHA token, DX = DELTA token) 118 runtime 119 .ledger 120 .credit(&buyer, "AX", 1_000_000) 121 .expect("Failed to credit buyer"); 122 runtime 123 .ledger 124 .credit(&seller, "DX", 1_000_000) 125 .expect("Failed to credit seller"); 126 127 // Seller places a limit sell order 128 let sell_tx = TradingTx::PlaceOrder { 129 pair: TradingPair::DeltaAlpha, 130 side: OrderSide::Sell, 131 quantity: 100, 132 price: Some(1000), 133 order_type: OrderType::Limit, 134 }; 135 136 let sell_result = runtime.execute_trading(seller, sell_tx).unwrap(); 137 assert!(matches!(sell_result, TradingResult::OrderPlaced { .. })); 138 139 // Buyer places a matching buy order 140 let buy_tx = TradingTx::PlaceOrder { 141 pair: TradingPair::DeltaAlpha, 142 side: OrderSide::Buy, 143 quantity: 100, 144 price: Some(1000), 145 order_type: OrderType::Limit, 146 }; 147 148 let buy_result = runtime.execute_trading(buyer, buy_tx).unwrap(); 149 150 match buy_result { 151 TradingResult::OrderPlaced { 152 match_result, 153 trades_executed, 154 } => { 155 assert_eq!(trades_executed, 1); 156 assert_eq!(match_result.trades.len(), 1); 157 158 let trade = &match_result.trades[0]; 159 assert_eq!(trade.quantity, 100); 160 assert_eq!(trade.price, 1000); 161 } 162 _ => panic!("Expected OrderPlaced with trades"), 163 } 164 } 165 166 /// Test bridge stats are tracked correctly 167 #[tokio::test] 168 async fn test_bridge_stats() { 169 let node = AdnetNode::<CurrentNetwork>::dev(4, 0); 170 node.init().await.expect("Failed to initialize node"); 171 172 let stats = node.bridge_stats().await; 173 assert_eq!(stats.attestations_sent, 0); 174 assert_eq!(stats.deposits_processed, 0); 175 assert_eq!(stats.withdrawals_processed, 0); 176 assert!(!stats.is_halted); 177 } 178 179 /// Test order book snapshot 180 #[tokio::test] 181 async fn test_orderbook_snapshot() { 182 use deltavm_console::Address; 183 use deltavm_execution::{DeltaRuntime, OrderSide, OrderType, TradingPair, TradingTx}; 184 185 let mut runtime = DeltaRuntime::new(); 186 let user = Address::zero(); 187 runtime 188 .ledger 189 .credit(&user, "AX", 1_000_000) 190 .expect("Failed to credit"); 191 192 // Place multiple orders at different prices 193 for price in [1000, 1010, 1020] { 194 let tx = TradingTx::PlaceOrder { 195 pair: TradingPair::DeltaAlpha, 196 side: OrderSide::Buy, 197 quantity: 100, 198 price: Some(price), 199 order_type: OrderType::Limit, 200 }; 201 runtime.execute_trading(user, tx).unwrap(); 202 } 203 204 // Get order book snapshot 205 let snapshot = runtime 206 .matching_engine 207 .get_order_book_snapshot(&TradingPair::DeltaAlpha); 208 209 // Verify we have 3 bid levels 210 assert_eq!(snapshot.bids.len(), 3); 211 212 // Verify all prices are present 213 let prices: Vec<u64> = snapshot.bids.iter().map(|l| l.price).collect(); 214 assert!(prices.contains(&1000)); 215 assert!(prices.contains(&1010)); 216 assert!(prices.contains(&1020)); 217 218 // Verify best bid is set 219 assert!(snapshot.best_bid.is_some()); 220 } 221 222 /// Test order cancellation 223 #[tokio::test] 224 async fn test_order_cancellation() { 225 use deltavm_console::Address; 226 use deltavm_execution::{ 227 DeltaRuntime, OrderSide, OrderType, TradingPair, TradingResult, TradingTx, 228 }; 229 230 let mut runtime = DeltaRuntime::new(); 231 let user = Address::zero(); 232 runtime 233 .ledger 234 .credit(&user, "AX", 1_000_000) 235 .expect("Failed to credit"); 236 237 // Place an order 238 let tx = TradingTx::PlaceOrder { 239 pair: TradingPair::DeltaAlpha, 240 side: OrderSide::Buy, 241 quantity: 100, 242 price: Some(1000), 243 order_type: OrderType::Limit, 244 }; 245 246 let place_result = runtime.execute_trading(user, tx).unwrap(); 247 let order_id = match place_result { 248 TradingResult::OrderPlaced { match_result, .. } => match_result.order.id, 249 _ => panic!("Expected OrderPlaced"), 250 }; 251 252 // Cancel the order 253 let cancel_tx = TradingTx::CancelOrder { 254 order_id: order_id.clone(), 255 }; 256 let cancel_result = runtime.execute_trading(user, cancel_tx); 257 258 assert!(cancel_result.is_ok()); 259 match cancel_result.unwrap() { 260 TradingResult::OrderCancelled { order } => { 261 assert_eq!(order.id.0, order_id.0); 262 } 263 TradingResult::Failed { reason } => { 264 panic!("Cancel failed: {}", reason); 265 } 266 _ => panic!("Expected OrderCancelled"), 267 } 268 } 269 270 /// Test ledger balance operations 271 #[tokio::test] 272 async fn test_ledger_balances() { 273 use deltavm_console::Address; 274 use deltavm_ledger::TradingLedger; 275 276 let mut ledger = TradingLedger::new(); 277 let user = Address::zero(); 278 279 // Credit some balance (AX = ALPHA token) 280 ledger.credit(&user, "AX", 1000).expect("Failed to credit"); 281 assert_eq!(ledger.balance(&user, "AX"), 1000); 282 283 // Debit some balance 284 ledger.debit(&user, "AX", 400).expect("Failed to debit"); 285 assert_eq!(ledger.balance(&user, "AX"), 600); 286 287 // Debit more than available should fail 288 let result = ledger.debit(&user, "AX", 1000); 289 assert!(result.is_err()); 290 } 291 292 /// Test withdrawal processor via DeltaRuntime.bridge 293 #[tokio::test] 294 async fn test_withdrawal_processor() { 295 use deltavm_execution::DeltaRuntime; 296 297 let runtime = DeltaRuntime::new(); 298 299 // Verify initial state 300 let stats = runtime.bridge_stats(); 301 assert_eq!(stats.total_fees, 0); 302 assert_eq!(stats.total_deposits, 0); 303 assert_eq!(stats.total_withdrawals, 0); 304 } 305 306 /// Test deposit processor (finalization) 307 #[tokio::test] 308 async fn test_deposit_finalization() { 309 use deltavm_ledger::DepositProcessor; 310 311 let processor = DepositProcessor::<CurrentNetwork>::new(10); 312 313 // Verify finalization depth 314 assert_eq!(processor.finalization_depth(), 10); 315 assert_eq!(processor.total_deposited(), 0); 316 }