#[cfg(test)] mod tests { use threefold_marketplace::services::farmer::FarmerService; use threefold_marketplace::services::user_persistence::UserPersistence; use threefold_marketplace::models::user::NodeStakingOptions; use rust_decimal::Decimal; #[test] fn test_staking_end_to_end_flow() { // Test the complete staking flow for user1 let user_email = "user1@example.com"; let farmer_service = FarmerService::builder().build().unwrap(); // Clean up any existing staking data first let user_data = UserPersistence::load_user_data(user_email); assert!(user_data.is_some(), "User1 data should exist"); let user_data = user_data.unwrap(); // Unstake from all nodes to start with a clean state for node in &user_data.nodes { if let Some(staking_options) = &node.staking_options { if staking_options.staking_enabled { let _ = farmer_service.unstake_from_node(user_email, &node.id); } } } // Reload user data after cleanup let user_data = UserPersistence::load_user_data(user_email).unwrap(); println!("Initial wallet balance: {}", user_data.wallet_balance_usd); println!("Number of nodes: {}", user_data.nodes.len()); // Verify user has sufficient balance (should be 11000 TFP) assert!(user_data.wallet_balance_usd >= Decimal::from(100), "User should have at least 100 TFP"); // Verify user has nodes to stake on assert!(!user_data.nodes.is_empty(), "User should have nodes"); let first_node = &user_data.nodes[0]; println!("First node ID: {}", first_node.id); println!("First node name: {}", first_node.name); // Test staking 100 TFP on the first node let staking_options = NodeStakingOptions { staking_enabled: true, staked_amount: Decimal::from(100), staking_start_date: None, // Will be set by the service staking_period_months: 12, early_withdrawal_allowed: true, early_withdrawal_penalty_percent: 5.0, }; // Perform staking let stake_result = farmer_service.stake_on_node(user_email, &first_node.id, staking_options); match stake_result { Ok(()) => { println!("✅ Staking successful!"); // Verify the staking was applied let updated_data = UserPersistence::load_user_data(user_email).unwrap(); // Check wallet balance decreased let expected_balance = user_data.wallet_balance_usd - Decimal::from(100); assert_eq!(updated_data.wallet_balance_usd, expected_balance, "Wallet balance should decrease by staked amount"); // Check node has staking options let updated_node = updated_data.nodes.iter() .find(|n| n.id == first_node.id) .expect("Node should still exist"); assert!(updated_node.staking_options.is_some(), "Node should have staking options"); let node_staking = updated_node.staking_options.as_ref().unwrap(); assert!(node_staking.staking_enabled, "Staking should be enabled"); assert_eq!(node_staking.staked_amount, Decimal::from(100), "Staked amount should be 100"); println!("✅ All staking verifications passed!"); // Test getting staking statistics let stats = farmer_service.get_staking_statistics(user_email); assert_eq!(stats.total_staked_amount, Decimal::from(100), "Total staked should be 100"); assert_eq!(stats.staked_nodes_count, 1, "Should have 1 staked node"); println!("✅ Staking statistics correct!"); // Test unstaking let unstake_result = farmer_service.unstake_from_node(user_email, &first_node.id); match unstake_result { Ok(returned_amount) => { println!("✅ Unstaking successful! Returned: {} TFP", returned_amount); // Verify unstaking let final_data = UserPersistence::load_user_data(user_email).unwrap(); let final_node = final_data.nodes.iter() .find(|n| n.id == first_node.id) .expect("Node should still exist"); assert!(final_node.staking_options.is_none(), "Node should not have staking options after unstaking"); println!("✅ Complete staking flow test passed!"); } Err(e) => { println!("❌ Unstaking failed: {}", e); panic!("Unstaking should succeed"); } } } Err(e) => { println!("❌ Staking failed: {}", e); panic!("Staking should succeed with sufficient balance"); } } } #[test] fn test_insufficient_balance_staking() { let user_email = "user1@example.com"; let farmer_service = FarmerService::builder().build().unwrap(); let user_data = UserPersistence::load_user_data(user_email).unwrap(); let first_node = &user_data.nodes[0]; // Try to stake more than available balance let excessive_amount = user_data.wallet_balance_usd + Decimal::from(1000); let staking_options = NodeStakingOptions { staking_enabled: true, staked_amount: excessive_amount, staking_start_date: None, staking_period_months: 12, early_withdrawal_allowed: true, early_withdrawal_penalty_percent: 5.0, }; let result = farmer_service.stake_on_node(user_email, &first_node.id, staking_options); assert!(result.is_err(), "Staking should fail with insufficient balance"); let error_msg = result.unwrap_err(); assert!(error_msg.contains("Insufficient balance"), "Error should mention insufficient balance"); println!("✅ Insufficient balance test passed!"); } }