From 0e0550889ac936fea2e3dda3f7f967addc7385b7 Mon Sep 17 00:00:00 2001 From: samuel Date: Sat, 21 Feb 2026 12:20:13 +0100 Subject: [PATCH] feat: implement get_campaigns_by_creator function - Add get_campaigns_by_creator function to retrieve all campaigns by creator address - Add CreatorCampaigns storage key to track creator-to-campaigns mapping - Update create_campaign to maintain creator mapping - Add test with 2 campaigns from one user and 1 from another --- contract/contract/src/base/types.rs | 1 + contract/contract/src/crowdfunding.rs | 20 +++++ .../contract/src/interfaces/crowdfunding.rs | 2 + .../test/get_campaigns_by_creator_test.rs | 74 +++++++++++++++++++ contract/contract/test/mod.rs | 1 + 5 files changed, 98 insertions(+) create mode 100644 contract/contract/test/get_campaigns_by_creator_test.rs diff --git a/contract/contract/src/base/types.rs b/contract/contract/src/base/types.rs index 44140c9..a8d4216 100644 --- a/contract/contract/src/base/types.rs +++ b/contract/contract/src/base/types.rs @@ -191,6 +191,7 @@ pub enum StorageKey { VerifiedCause(Address), PlatformFees, GlobalTotalRaised, + CreatorCampaigns(Address), } #[cfg(test)] diff --git a/contract/contract/src/crowdfunding.rs b/contract/contract/src/crowdfunding.rs index 78120df..1281545 100644 --- a/contract/contract/src/crowdfunding.rs +++ b/contract/contract/src/crowdfunding.rs @@ -112,6 +112,18 @@ impl CrowdfundingTrait for CrowdfundingContract { .instance() .set(&StorageKey::AllCampaigns, &all_campaigns); + // Track campaigns by creator + let creator_key = StorageKey::CreatorCampaigns(creator.clone()); + let mut creator_campaigns = env + .storage() + .instance() + .get(&creator_key) + .unwrap_or(Vec::new(&env)); + creator_campaigns.push_back(id.clone()); + env.storage() + .instance() + .set(&creator_key, &creator_campaigns); + events::campaign_created(&env, id, title, creator, goal, deadline); Ok(()) @@ -1089,4 +1101,12 @@ impl CrowdfundingTrait for CrowdfundingContract { Ok(()) } + + fn get_campaigns_by_creator(env: Env, creator: Address) -> Vec> { + let creator_key = StorageKey::CreatorCampaigns(creator); + env.storage() + .instance() + .get(&creator_key) + .unwrap_or(Vec::new(&env)) + } } diff --git a/contract/contract/src/interfaces/crowdfunding.rs b/contract/contract/src/interfaces/crowdfunding.rs index 0accbcc..007bc80 100644 --- a/contract/contract/src/interfaces/crowdfunding.rs +++ b/contract/contract/src/interfaces/crowdfunding.rs @@ -127,4 +127,6 @@ pub trait CrowdfundingTrait { admin: Address, amount: i128, ) -> Result<(), CrowdfundingError>; + + fn get_campaigns_by_creator(env: Env, creator: Address) -> Vec>; } diff --git a/contract/contract/test/get_campaigns_by_creator_test.rs b/contract/contract/test/get_campaigns_by_creator_test.rs new file mode 100644 index 0000000..7be26d1 --- /dev/null +++ b/contract/contract/test/get_campaigns_by_creator_test.rs @@ -0,0 +1,74 @@ +#![cfg(test)] + +use crate::{ + crowdfunding::{CrowdfundingContract, CrowdfundingContractClient}, +}; +use soroban_sdk::{testutils::Address as _, Address, BytesN, Env, String}; + +#[test] +fn test_get_campaigns_by_creator_multiple_users() { + let env = Env::default(); + env.mock_all_auths(); + + let contract_id = env.register(CrowdfundingContract, ()); + let client = CrowdfundingContractClient::new(&env, &contract_id); + + // Initialize contract + let admin = Address::generate(&env); + let token_admin = Address::generate(&env); + let token_contract = env.register_stellar_asset_contract_v2(token_admin.clone()); + let token_address = token_contract.address(); + + client.initialize(&admin, &token_address, &0); + + // Create campaigns with two different creators + let creator1 = Address::generate(&env); + let creator2 = Address::generate(&env); + + let campaign_id1 = BytesN::from_array(&env, &[1u8; 32]); + let campaign_id2 = BytesN::from_array(&env, &[2u8; 32]); + let campaign_id3 = BytesN::from_array(&env, &[3u8; 32]); + + let title1 = String::from_str(&env, "Campaign 1"); + let title2 = String::from_str(&env, "Campaign 2"); + let title3 = String::from_str(&env, "Campaign 3"); + let goal = 1_000_000i128; + let deadline = env.ledger().timestamp() + 86400; + + // Creator 1 creates 2 campaigns + client.create_campaign( + &campaign_id1, + &title1, + &creator1, + &goal, + &deadline, + &token_address, + ); + + client.create_campaign( + &campaign_id2, + &title2, + &creator1, + &goal, + &deadline, + &token_address, + ); + + // Creator 2 creates 1 campaign + client.create_campaign( + &campaign_id3, + &title3, + &creator2, + &goal, + &deadline, + &token_address, + ); + + // Verify creator1 has 2 campaigns + let campaigns1 = client.get_campaigns_by_creator(&creator1); + assert_eq!(campaigns1.len(), 2); + + // Verify creator2 has 1 campaign + let campaigns2 = client.get_campaigns_by_creator(&creator2); + assert_eq!(campaigns2.len(), 1); +} diff --git a/contract/contract/test/mod.rs b/contract/contract/test/mod.rs index 1eb7cf3..67817e2 100644 --- a/contract/contract/test/mod.rs +++ b/contract/contract/test/mod.rs @@ -1,4 +1,5 @@ mod close_pool_test; mod create_pool; mod crowdfunding_test; +mod get_campaigns_by_creator_test; mod verify_cause;