Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions contracts/payment-vault-contract/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
18 changes: 17 additions & 1 deletion contracts/payment-vault-contract/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<u64> {
storage::get_user_bookings(&env, &user)
}

/// Get all booking IDs for a specific expert
pub fn get_expert_bookings(env: Env, expert: Address) -> Vec<u64> {
storage::get_expert_bookings(&env, &expert)
}

/// Get booking details by booking ID (read-only)
pub fn get_booking(env: Env, booking_id: u64) -> Option<BookingRecord> {
storage::get_booking(&env, booking_id)
}
}
45 changes: 45 additions & 0 deletions contracts/payment-vault-contract/src/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<u64> of booking IDs
ExpertBookings(Address), // Expert Address -> Vec<u64> of booking IDs
}

// --- Admin ---
Expand Down Expand Up @@ -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<u64> = 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<u64> = 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<u64> {
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<u64> {
env.storage()
.persistent()
.get(&DataKey::ExpertBookings(expert.clone()))
.unwrap_or(soroban_sdk::Vec::new(env))
}
58 changes: 56 additions & 2 deletions contracts/payment-vault-contract/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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());
}