Overview
Querying user state across multiple farming pools requires one RPC call per pool. For a user staking in 5 pools, that is 5 sequential simulation calls. A read-only view contract that aggregates data across pools reduces this to a single call.
Design
MultiPoolViewer (deployed once, no admin, pure view functions)
├── user_summary(factory, user) -> Vec<UserPoolSummary>
├── pool_overview(factory, start_id, limit) -> Vec<PoolOverview>
└── global_stats(factory) -> GlobalStats
UserPoolSummary
#[contracttype]
pub struct UserPoolSummary {
pub pool_id: u32,
pub pool_address: Address,
pub staked_amount: i128,
pub locked_amount: i128,
pub total_credits: i128,
pub has_boost: bool,
pub boost_allocation_pct: u32,
pub is_pool_paused: bool,
}
user_summary Implementation
pub fn user_summary(env: Env, factory: Address, user: Address) -> Vec<UserPoolSummary> {
let factory_client = FactoryClient::new(&env, &factory);
let count = factory_client.pool_count();
let mut summaries = Vec::new(&env);
for id in 0..count.min(50) { // cap at 50 pools per call
let record = factory_client.get_pool(&id);
let pool = FarmingPoolClient::new(&env, &record.address);
let stake = pool.get_stake(&user);
let position = pool.get_user_position(&user);
let credits = pool.get_credits(&user) + pool.calculate_credits(&user);
let boost = pool.get_boost_config(&user);
summaries.push_back(UserPoolSummary { ... });
}
summaries
}
Acceptance Criteria
Overview
Querying user state across multiple farming pools requires one RPC call per pool. For a user staking in 5 pools, that is 5 sequential simulation calls. A read-only view contract that aggregates data across pools reduces this to a single call.
Design
UserPoolSummaryuser_summaryImplementationAcceptance Criteria
contracts/multi-pool-viewer/created with noAdminstorageuser_summaryreturns correct aggregated data for each poolpool_overviewreturns basic info for paginated pool listbump_instance, no events)