From a09f6dd36288f46868efbaed6c582214d1381312 Mon Sep 17 00:00:00 2001 From: Josue19-08 Date: Tue, 24 Mar 2026 20:04:46 -0600 Subject: [PATCH] feat(identity-registry): implement expert directory pagination Add get_experts_paginated function to efficiently fetch experts in batches. This addresses the performance issue of fetching large expert lists. - Implement get_experts_paginated in contract.rs with start_index and limit - Expose function in public API (lib.rs) - Add comprehensive test with 15 experts, validating pagination behavior --- .../src/contract.rs | 22 ++++++++++ .../identity-registry-contract/src/lib.rs | 6 +++ .../identity-registry-contract/src/test.rs | 42 +++++++++++++++++++ 3 files changed, 70 insertions(+) diff --git a/contracts/identity-registry-contract/src/contract.rs b/contracts/identity-registry-contract/src/contract.rs index 051493f..f19d671 100644 --- a/contracts/identity-registry-contract/src/contract.rs +++ b/contracts/identity-registry-contract/src/contract.rs @@ -157,3 +157,25 @@ pub fn update_profile(env: &Env, expert: &Address, new_uri: String) -> Result<() events::emit_profile_updated(env, expert.clone(), new_uri); Ok(()) } + +/// Get a paginated list of experts +/// Returns a vector of expert addresses from start_index to start_index + limit +pub fn get_experts_paginated(env: &Env, start_index: u64, limit: u64) -> Vec
{ + let total = storage::get_total_experts(env); + let mut experts = Vec::new(env); + + // Calculate the actual end index (don't exceed total) + let end_index = if start_index + limit > total { + total + } else { + start_index + limit + }; + + // Fetch experts from start_index to end_index + for i in start_index..end_index { + let expert = storage::get_expert_by_index(env, i); + experts.push_back(expert); + } + + experts +} diff --git a/contracts/identity-registry-contract/src/lib.rs b/contracts/identity-registry-contract/src/lib.rs index b226d4b..ae4e86d 100644 --- a/contracts/identity-registry-contract/src/lib.rs +++ b/contracts/identity-registry-contract/src/lib.rs @@ -68,4 +68,10 @@ impl IdentityRegistryContract { pub fn update_profile(env: Env, expert: Address, new_uri: String) -> Result<(), RegistryError> { contract::update_profile(&env, &expert, new_uri) } + + /// Get a paginated list of experts + /// Returns a vector of expert addresses from start_index to start_index + limit + pub fn get_experts_paginated(env: Env, start_index: u64, limit: u64) -> Vec
{ + contract::get_experts_paginated(&env, start_index, limit) + } } diff --git a/contracts/identity-registry-contract/src/test.rs b/contracts/identity-registry-contract/src/test.rs index 41c7195..5c03da1 100644 --- a/contracts/identity-registry-contract/src/test.rs +++ b/contracts/identity-registry-contract/src/test.rs @@ -581,3 +581,45 @@ fn test_expert_directory_via_batch_add() { assert_eq!(client.get_expert_by_index(&1u64), expert2); assert_eq!(client.get_expert_by_index(&2u64), expert3); } + +#[test] +fn test_expert_pagination() { + let env = Env::default(); + env.mock_all_auths(); + + let contract_id = env.register(IdentityRegistryContract, ()); + let client = IdentityRegistryContractClient::new(&env, &contract_id); + + let admin = Address::generate(&env); + client.init(&admin); + + // Add 15 experts + let mut experts = vec![&env]; + for _ in 0..15 { + let expert = Address::generate(&env); + let uri = String::from_str(&env, "ipfs://expert"); + client.add_expert(&expert, &uri); + experts.push_back(expert); + } + + // Verify total count + assert_eq!(client.get_total_experts(), 15u64); + + // Fetch start: 0, limit: 10 (should return 10) + let page1 = client.get_experts_paginated(&0u64, &10u64); + assert_eq!(page1.len(), 10); + + // Verify the first 10 experts match + for i in 0..10 { + assert_eq!(page1.get(i as u32).unwrap(), experts.get(i as u32).unwrap()); + } + + // Fetch start: 10, limit: 10 (should return 5) + let page2 = client.get_experts_paginated(&10u64, &10u64); + assert_eq!(page2.len(), 5); + + // Verify the last 5 experts match + for i in 0..5 { + assert_eq!(page2.get(i as u32).unwrap(), experts.get((i + 10) as u32).unwrap()); + } +}