diff --git a/contracts/payment-vault-contract/src/contract.rs b/contracts/payment-vault-contract/src/contract.rs index 7c2cc2a..919db0f 100644 --- a/contracts/payment-vault-contract/src/contract.rs +++ b/contracts/payment-vault-contract/src/contract.rs @@ -68,6 +68,10 @@ pub fn book_session( // Save booking storage::save_booking(env, &booking); + // Add booking to user and expert lists + storage::add_booking_to_user_list(env, user, booking_id); + storage::add_booking_to_expert_list(env, expert, booking_id); + // Emit event for booking creation events::booking_created(env, booking_id, user, expert, total_deposit); diff --git a/contracts/payment-vault-contract/src/lib.rs b/contracts/payment-vault-contract/src/lib.rs index def4262..86fab6a 100644 --- a/contracts/payment-vault-contract/src/lib.rs +++ b/contracts/payment-vault-contract/src/lib.rs @@ -8,8 +8,9 @@ mod types; #[cfg(test)] mod test; -use soroban_sdk::{contract, contractimpl, Address, Env}; +use soroban_sdk::{contract, contractimpl, Address, Env, Vec}; use crate::error::VaultError; +use crate::types::BookingRecord; #[contract] pub struct PaymentVaultContract; @@ -47,4 +48,19 @@ impl PaymentVaultContract { ) -> Result<(), VaultError> { contract::finalize_session(&env, booking_id, actual_duration) } + + /// Get all booking IDs for a specific user + pub fn get_user_bookings(env: Env, user: Address) -> Vec { + storage::get_user_bookings(&env, &user) + } + + /// Get all booking IDs for a specific expert + pub fn get_expert_bookings(env: Env, expert: Address) -> Vec { + storage::get_expert_bookings(&env, &expert) + } + + /// Get booking details by booking ID (read-only) + pub fn get_booking(env: Env, booking_id: u64) -> Option { + storage::get_booking(&env, booking_id) + } } \ No newline at end of file diff --git a/contracts/payment-vault-contract/src/storage.rs b/contracts/payment-vault-contract/src/storage.rs index b12d145..5c6caa9 100644 --- a/contracts/payment-vault-contract/src/storage.rs +++ b/contracts/payment-vault-contract/src/storage.rs @@ -9,6 +9,8 @@ pub enum DataKey { Oracle, Booking(u64), // Booking ID -> BookingRecord BookingCounter, // Counter for generating unique booking IDs + UserBookings(Address), // User Address -> Vec of booking IDs + ExpertBookings(Address), // Expert Address -> Vec of booking IDs } // --- Admin --- @@ -72,4 +74,47 @@ pub fn update_booking_status(env: &Env, booking_id: u64, status: BookingStatus) booking.status = status; save_booking(env, &booking); } +} + +// --- User and Expert Booking Lists --- +pub fn add_booking_to_user_list(env: &Env, user: &Address, booking_id: u64) { + let mut user_bookings: soroban_sdk::Vec = env + .storage() + .persistent() + .get(&DataKey::UserBookings(user.clone())) + .unwrap_or(soroban_sdk::Vec::new(env)); + + user_bookings.push_back(booking_id); + + env.storage() + .persistent() + .set(&DataKey::UserBookings(user.clone()), &user_bookings); +} + +pub fn add_booking_to_expert_list(env: &Env, expert: &Address, booking_id: u64) { + let mut expert_bookings: soroban_sdk::Vec = env + .storage() + .persistent() + .get(&DataKey::ExpertBookings(expert.clone())) + .unwrap_or(soroban_sdk::Vec::new(env)); + + expert_bookings.push_back(booking_id); + + env.storage() + .persistent() + .set(&DataKey::ExpertBookings(expert.clone()), &expert_bookings); +} + +pub fn get_user_bookings(env: &Env, user: &Address) -> soroban_sdk::Vec { + env.storage() + .persistent() + .get(&DataKey::UserBookings(user.clone())) + .unwrap_or(soroban_sdk::Vec::new(env)) +} + +pub fn get_expert_bookings(env: &Env, expert: &Address) -> soroban_sdk::Vec { + env.storage() + .persistent() + .get(&DataKey::ExpertBookings(expert.clone())) + .unwrap_or(soroban_sdk::Vec::new(env)) } \ No newline at end of file diff --git a/contracts/payment-vault-contract/src/test.rs b/contracts/payment-vault-contract/src/test.rs index a50f661..2fc4503 100644 --- a/contracts/payment-vault-contract/src/test.rs +++ b/contracts/payment-vault-contract/src/test.rs @@ -237,7 +237,7 @@ fn test_book_session_balance_transfer() { let token_admin = Address::generate(&env); let token = create_token_contract(&env, &token_admin); - + // Initial balance let initial_balance = 5_000_i128; token.mint(&user, &initial_balance); @@ -269,8 +269,62 @@ fn test_book_session_balance_transfer() { // Create another booking to verify uniqueness token.mint(&user, &expected_deposit); // Mint more tokens for second booking let booking_id_2 = client.book_session(&user, &expert, &rate_per_second, &max_duration); - + // Second booking should have different ID assert_eq!(booking_id_2, 2); assert_ne!(booking_id, booking_id_2); +} + +#[test] +fn test_get_user_and_expert_bookings() { + let env = Env::default(); + env.mock_all_auths(); + + let admin = Address::generate(&env); + let user = Address::generate(&env); + let expert1 = Address::generate(&env); + let expert2 = Address::generate(&env); + let oracle = Address::generate(&env); + + let token_admin = Address::generate(&env); + let token = create_token_contract(&env, &token_admin); + token.mint(&user, &100_000); + + let client = create_client(&env); + client.init(&admin, &token.address, &oracle); + + // Create 2 bookings for the same user with different experts + let rate_per_second = 10_i128; + let max_duration = 100_u64; + let booking_id_1 = client.book_session(&user, &expert1, &rate_per_second, &max_duration); + let booking_id_2 = client.book_session(&user, &expert2, &rate_per_second, &max_duration); + + // Test get_user_bookings - should return 2 bookings + let user_bookings = client.get_user_bookings(&user); + assert_eq!(user_bookings.len(), 2); + assert_eq!(user_bookings.get(0).unwrap(), booking_id_1); + assert_eq!(user_bookings.get(1).unwrap(), booking_id_2); + + // Test get_expert_bookings - expert1 should have 1 booking + let expert1_bookings = client.get_expert_bookings(&expert1); + assert_eq!(expert1_bookings.len(), 1); + assert_eq!(expert1_bookings.get(0).unwrap(), booking_id_1); + + // Test get_expert_bookings - expert2 should have 1 booking + let expert2_bookings = client.get_expert_bookings(&expert2); + assert_eq!(expert2_bookings.len(), 1); + assert_eq!(expert2_bookings.get(0).unwrap(), booking_id_2); + + // Test get_booking - verify we can retrieve booking details + let booking_1 = client.get_booking(&booking_id_1); + assert!(booking_1.is_some()); + let booking_1 = booking_1.unwrap(); + assert_eq!(booking_1.id, booking_id_1); + assert_eq!(booking_1.user, user); + assert_eq!(booking_1.expert, expert1); + assert_eq!(booking_1.rate_per_second, rate_per_second); + + // Test get_booking for non-existent booking + let non_existent = client.get_booking(&999); + assert!(non_existent.is_none()); } \ No newline at end of file