From d32f725e9c9a1bfe60a988b5ba99f959337fad07 Mon Sep 17 00:00:00 2001 From: Tu Pham Date: Mon, 25 May 2026 18:25:59 +0700 Subject: [PATCH] feat: add round history query --- contracts/sorosave/src/lib.rs | 10 ++++++ contracts/sorosave/src/payout.rs | 36 ++++++++++++++++++++++ contracts/sorosave/src/test.rs | 53 ++++++++++++++++++++++++++++++++ 3 files changed, 99 insertions(+) diff --git a/contracts/sorosave/src/lib.rs b/contracts/sorosave/src/lib.rs index 454a6ca..f6d52db 100644 --- a/contracts/sorosave/src/lib.rs +++ b/contracts/sorosave/src/lib.rs @@ -118,6 +118,16 @@ impl SoroSaveContract { payout::get_current_recipient(&env, group_id) } + /// Get completed round history for a group, paginated by completed-round index. + pub fn get_round_history( + env: Env, + group_id: u64, + offset: u32, + limit: u32, + ) -> Result, ContractError> { + payout::get_round_history(&env, group_id, offset, limit) + } + // ─── Admin / Governance ───────────────────────────────────────── /// Pause an active group. diff --git a/contracts/sorosave/src/payout.rs b/contracts/sorosave/src/payout.rs index 76ed389..2a95d6c 100644 --- a/contracts/sorosave/src/payout.rs +++ b/contracts/sorosave/src/payout.rs @@ -84,3 +84,39 @@ pub fn get_current_recipient(env: &Env, group_id: u64) -> Result Result, ContractError> { + let group = storage::get_group(env, group_id).ok_or(ContractError::GroupNotFound)?; + let mut history = Vec::new(env); + + if limit == 0 { + return Ok(history); + } + + let mut skipped = 0; + let mut round_number = 1; + + while round_number <= group.current_round { + if let Some(round_info) = storage::get_round(env, group_id, round_number) { + if round_info.is_complete { + if skipped < offset { + skipped += 1; + } else { + history.push_back(round_info); + if history.len() >= limit { + break; + } + } + } + } + + round_number += 1; + } + + Ok(history) +} diff --git a/contracts/sorosave/src/test.rs b/contracts/sorosave/src/test.rs index f1ac1ef..c578395 100644 --- a/contracts/sorosave/src/test.rs +++ b/contracts/sorosave/src/test.rs @@ -151,6 +151,59 @@ fn test_full_cycle() { assert_eq!(group.status, GroupStatus::Completed); } +#[test] +fn test_round_history_pagination() { + let (env, admin, client, _token) = setup_env(); + let member1 = Address::generate(&env); + let member2 = Address::generate(&env); + let mint_admin = Address::generate(&env); + let token_id = env.register_stellar_asset_contract_v2(mint_admin); + let token_sac = StellarAssetClient::new(&env, &token_id.address()); + token_sac.mint(&admin, &10_000_000); + token_sac.mint(&member1, &10_000_000); + token_sac.mint(&member2, &10_000_000); + + let group_id = client.create_group( + &admin, + &String::from_str(&env, "Round History Test"), + &token_id.address(), + &1_000_000, + &86400, + &5, + ); + client.join_group(&member1, &group_id); + client.join_group(&member2, &group_id); + client.start_group(&admin, &group_id); + + client.contribute(&admin, &group_id); + client.contribute(&member1, &group_id); + client.contribute(&member2, &group_id); + + let first_page = client.get_round_history(&group_id, &0, &10); + assert_eq!(first_page.len(), 1); + assert_eq!(first_page.get(0).unwrap().round_number, 1); + assert_eq!(first_page.get(0).unwrap().recipient, admin); + assert_eq!(first_page.get(0).unwrap().total_contributed, 3_000_000); + assert!(first_page.get(0).unwrap().is_complete); + + client.distribute_payout(&group_id); + client.contribute(&admin, &group_id); + + let history_before_second_complete = client.get_round_history(&group_id, &0, &10); + assert_eq!(history_before_second_complete.len(), 1); + + client.contribute(&member1, &group_id); + client.contribute(&member2, &group_id); + + let second_page = client.get_round_history(&group_id, &1, &1); + assert_eq!(second_page.len(), 1); + assert_eq!(second_page.get(0).unwrap().round_number, 2); + assert_eq!(second_page.get(0).unwrap().recipient, member1); + + assert_eq!(client.get_round_history(&group_id, &0, &0).len(), 0); + assert_eq!(client.get_round_history(&group_id, &5, &2).len(), 0); +} + #[test] fn test_member_groups() { let (env, admin, client, token) = setup_env();