From 00f346bc83ad941f508f8d39d333974ee14c528e Mon Sep 17 00:00:00 2001 From: Kerber0x <94062656+kerber0x@users.noreply.github.com> Date: Tue, 2 Jul 2024 16:19:37 +0100 Subject: [PATCH] feat(pool_manager): pools query improvement (#372) --- Cargo.lock | 2 +- .../schema/bonding-manager.json | 2 +- .../schema/raw/response_to_config.json | 2 +- .../bonding-manager/src/contract.rs | 4 +- .../bonding-manager/src/helpers.rs | 52 +++++--- .../pool-manager/schema/pool-manager.json | 20 +-- .../pool-manager/schema/raw/query.json | 8 +- .../schema/raw/response_to_pools.json | 12 +- .../pool-manager/src/contract.rs | 13 +- .../pool-manager/src/manager/commands.rs | 1 + .../liquidity_hub/pool-manager/src/queries.rs | 50 ++++++- .../src/tests/integration_tests.rs | 125 ++++++++++++++---- .../pool-manager/src/tests/suite.rs | 34 +++-- integration-tests/tests/common/suite.rs | 20 ++- packages/white-whale-std/Cargo.toml | 3 +- packages/white-whale-std/src/pool_manager.rs | 25 +++- 16 files changed, 266 insertions(+), 107 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 550f53ea..6b151ea2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1799,7 +1799,7 @@ dependencies = [ [[package]] name = "white-whale-std" -version = "1.1.3" +version = "1.1.6" dependencies = [ "anybuf", "anyhow", diff --git a/contracts/liquidity_hub/bonding-manager/schema/bonding-manager.json b/contracts/liquidity_hub/bonding-manager/schema/bonding-manager.json index 01fed86a..d799b1d0 100644 --- a/contracts/liquidity_hub/bonding-manager/schema/bonding-manager.json +++ b/contracts/liquidity_hub/bonding-manager/schema/bonding-manager.json @@ -852,7 +852,7 @@ ] }, "unbonding_period": { - "description": "Unbonding period in nanoseconds. The time that needs to pass before an unbonded position can be withdrawn", + "description": "Unbonding period in epochs. The time (in epochs) that needs to pass before an unbonded position can be withdrawn", "type": "integer", "format": "uint64", "minimum": 0.0 diff --git a/contracts/liquidity_hub/bonding-manager/schema/raw/response_to_config.json b/contracts/liquidity_hub/bonding-manager/schema/raw/response_to_config.json index 498ca242..4f2e9575 100644 --- a/contracts/liquidity_hub/bonding-manager/schema/raw/response_to_config.json +++ b/contracts/liquidity_hub/bonding-manager/schema/raw/response_to_config.json @@ -54,7 +54,7 @@ ] }, "unbonding_period": { - "description": "Unbonding period in nanoseconds. The time that needs to pass before an unbonded position can be withdrawn", + "description": "Unbonding period in epochs. The time (in epochs) that needs to pass before an unbonded position can be withdrawn", "type": "integer", "format": "uint64", "minimum": 0.0 diff --git a/contracts/liquidity_hub/bonding-manager/src/contract.rs b/contracts/liquidity_hub/bonding-manager/src/contract.rs index cc1c5b72..8c628cd9 100644 --- a/contracts/liquidity_hub/bonding-manager/src/contract.rs +++ b/contracts/liquidity_hub/bonding-manager/src/contract.rs @@ -19,7 +19,7 @@ const CONTRACT_NAME: &str = "white_whale-bonding_manager"; const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); pub const LP_WITHDRAWAL_REPLY_ID: u64 = 0; -pub const NEW_EPOCH_CREATION_REPLY_ID: u64 = 1; +pub const TEMPORAL_BOND_ACTION_REPLY_ID: u64 = 1; #[entry_point] pub fn instantiate( @@ -68,7 +68,7 @@ pub fn instantiate( pub fn reply(deps: DepsMut, env: Env, msg: Reply) -> Result { match msg.id { LP_WITHDRAWAL_REPLY_ID => rewards::commands::handle_lp_withdrawal_reply(deps, msg), - NEW_EPOCH_CREATION_REPLY_ID => { + TEMPORAL_BOND_ACTION_REPLY_ID => { let TemporalBondAction { sender, coin, diff --git a/contracts/liquidity_hub/bonding-manager/src/helpers.rs b/contracts/liquidity_hub/bonding-manager/src/helpers.rs index 75a56337..3d1704e0 100644 --- a/contracts/liquidity_hub/bonding-manager/src/helpers.rs +++ b/contracts/liquidity_hub/bonding-manager/src/helpers.rs @@ -15,12 +15,12 @@ use white_whale_std::bonding_manager::{ use white_whale_std::constants::LP_SYMBOL; use white_whale_std::epoch_manager::epoch_manager::EpochResponse; use white_whale_std::pool_manager::{ - PoolInfoResponse, SimulateSwapOperationsResponse, SwapRouteResponse, + PoolsResponse, SimulateSwapOperationsResponse, SwapRouteResponse, }; use white_whale_std::pool_network::asset; use white_whale_std::pool_network::asset::aggregate_coins; -use crate::contract::{LP_WITHDRAWAL_REPLY_ID, NEW_EPOCH_CREATION_REPLY_ID}; +use crate::contract::{LP_WITHDRAWAL_REPLY_ID, TEMPORAL_BOND_ACTION_REPLY_ID}; use crate::error::ContractError; use crate::queries::query_claimable; use crate::state::{ @@ -128,14 +128,16 @@ pub fn handle_lp_tokens_rewards( extract_pool_identifier(&lp_token.denom).ok_or(ContractError::AssetMismatch)?; // make sure a pool with the given identifier exists - let pool: StdResult = deps.querier.query_wasm_smart( + let pools_response: StdResult = deps.querier.query_wasm_smart( config.pool_manager_addr.to_string(), - &white_whale_std::pool_manager::QueryMsg::Pool { - pool_identifier: pool_identifier.to_string(), + &white_whale_std::pool_manager::QueryMsg::Pools { + pool_identifier: Some(pool_identifier.to_string()), + start_after: None, + limit: None, }, ); - if pool.is_err() { + if pools_response.is_err() || pools_response?.pools.is_empty() { continue; } @@ -221,25 +223,33 @@ pub fn swap_coins_to_main_token( // check if the pool has any assets, if not skip the swap // Note we are only checking the first operation here. // Might be better to another loop to check all operations - let pool_query = white_whale_std::pool_manager::QueryMsg::Pool { - pool_identifier: swap_routes - .swap_route - .swap_operations - .first() - .unwrap() - .get_pool_identifer(), + let pools_query = white_whale_std::pool_manager::QueryMsg::Pools { + pool_identifier: Some( + swap_routes + .swap_route + .swap_operations + .first() + .unwrap() + .get_pool_identifer(), + ), + start_after: None, + limit: None, }; let mut skip_swap = false; // Query for the pool to check if it has any assets - let resp: PoolInfoResponse = deps + let pools_response: PoolsResponse = deps .querier - .query_wasm_smart(config.pool_manager_addr.to_string(), &pool_query)?; + .query_wasm_smart(config.pool_manager_addr.to_string(), &pools_query)?; // Check pair 'assets' and if either one has 0 amount then don't do swaps - resp.pool_info.assets.iter().for_each(|asset| { - if asset.amount.is_zero() { - skip_swap = true; - } - }); + pools_response.pools[0] + .pool_info + .assets + .iter() + .for_each(|asset| { + if asset.amount.is_zero() { + skip_swap = true; + } + }); let simulate_swap_operations_response: SimulateSwapOperationsResponse = deps.querier.query_wasm_smart( @@ -537,6 +547,6 @@ fn create_temporal_bond_action_submsg( ) -> Result { Ok(SubMsg::reply_on_success( wasm_execute(contract_addr, msg, vec![])?, - NEW_EPOCH_CREATION_REPLY_ID, + TEMPORAL_BOND_ACTION_REPLY_ID, )) } diff --git a/contracts/liquidity_hub/pool-manager/schema/pool-manager.json b/contracts/liquidity_hub/pool-manager/schema/pool-manager.json index 157b38c8..e6d2a39f 100644 --- a/contracts/liquidity_hub/pool-manager/schema/pool-manager.json +++ b/contracts/liquidity_hub/pool-manager/schema/pool-manager.json @@ -965,7 +965,7 @@ "additionalProperties": false }, { - "description": "Retrieves the pools information.", + "description": "Retrieves the pool information for the given pool identifier.", "type": "object", "required": [ "pools" @@ -975,7 +975,7 @@ "type": "object", "properties": { "limit": { - "description": "An optional parameter specifying the maximum number of pools to return.", + "description": "The amount of pools to return. If unspecified, will default to a value specified by the contract.", "type": [ "integer", "null" @@ -984,14 +984,14 @@ "minimum": 0.0 }, "pool_identifier": { - "description": "If provided, the query will return the pool with the given identifier, otherwise, it will return all pools.", + "description": "An optional parameter specifying the pool identifier to do the query for. If not provided, it will return all pools based on the pagination parameters.", "type": [ "string", "null" ] }, "start_after": { - "description": "An optional parameter specifying what pool identifier to start searching after.", + "description": "An optional parameter specifying what pool (identifier) to start searching after.", "type": [ "string", "null" @@ -1356,7 +1356,7 @@ ], "properties": { "pools": { - "description": "The pools on the contract.", + "description": "The pools information responses.", "type": "array", "items": { "$ref": "#/definitions/PoolInfoResponse" @@ -1447,9 +1447,9 @@ "asset_decimals", "asset_denoms", "assets", - "identifier", "lp_denom", "pool_fees", + "pool_identifier", "pool_type" ], "properties": { @@ -1476,9 +1476,6 @@ "$ref": "#/definitions/Coin" } }, - "identifier": { - "type": "string" - }, "lp_denom": { "description": "The LP denom of the pool.", "type": "string" @@ -1491,6 +1488,10 @@ } ] }, + "pool_identifier": { + "description": "The identifier for the pool.", + "type": "string" + }, "pool_type": { "description": "The type of pool to create.", "allOf": [ @@ -1503,7 +1504,6 @@ "additionalProperties": false }, "PoolInfoResponse": { - "description": "The response for the `Pool` query.", "type": "object", "required": [ "pool_info", diff --git a/contracts/liquidity_hub/pool-manager/schema/raw/query.json b/contracts/liquidity_hub/pool-manager/schema/raw/query.json index e750cc46..7e4990da 100644 --- a/contracts/liquidity_hub/pool-manager/schema/raw/query.json +++ b/contracts/liquidity_hub/pool-manager/schema/raw/query.json @@ -217,7 +217,7 @@ "additionalProperties": false }, { - "description": "Retrieves the pools information.", + "description": "Retrieves the pool information for the given pool identifier.", "type": "object", "required": [ "pools" @@ -227,7 +227,7 @@ "type": "object", "properties": { "limit": { - "description": "An optional parameter specifying the maximum number of pools to return.", + "description": "The amount of pools to return. If unspecified, will default to a value specified by the contract.", "type": [ "integer", "null" @@ -236,14 +236,14 @@ "minimum": 0.0 }, "pool_identifier": { - "description": "If provided, the query will return the pool with the given identifier, otherwise, it will return all pools.", + "description": "An optional parameter specifying the pool identifier to do the query for. If not provided, it will return all pools based on the pagination parameters.", "type": [ "string", "null" ] }, "start_after": { - "description": "An optional parameter specifying what pool identifier to start searching after.", + "description": "An optional parameter specifying what pool (identifier) to start searching after.", "type": [ "string", "null" diff --git a/contracts/liquidity_hub/pool-manager/schema/raw/response_to_pools.json b/contracts/liquidity_hub/pool-manager/schema/raw/response_to_pools.json index 32fdddf6..c0a94cfd 100644 --- a/contracts/liquidity_hub/pool-manager/schema/raw/response_to_pools.json +++ b/contracts/liquidity_hub/pool-manager/schema/raw/response_to_pools.json @@ -8,7 +8,7 @@ ], "properties": { "pools": { - "description": "The pools on the contract.", + "description": "The pools information responses.", "type": "array", "items": { "$ref": "#/definitions/PoolInfoResponse" @@ -99,9 +99,9 @@ "asset_decimals", "asset_denoms", "assets", - "identifier", "lp_denom", "pool_fees", + "pool_identifier", "pool_type" ], "properties": { @@ -128,9 +128,6 @@ "$ref": "#/definitions/Coin" } }, - "identifier": { - "type": "string" - }, "lp_denom": { "description": "The LP denom of the pool.", "type": "string" @@ -143,6 +140,10 @@ } ] }, + "pool_identifier": { + "description": "The identifier for the pool.", + "type": "string" + }, "pool_type": { "description": "The type of pool to create.", "allOf": [ @@ -155,7 +156,6 @@ "additionalProperties": false }, "PoolInfoResponse": { - "description": "The response for the `Pool` query.", "type": "object", "required": [ "pool_info", diff --git a/contracts/liquidity_hub/pool-manager/src/contract.rs b/contracts/liquidity_hub/pool-manager/src/contract.rs index bb5e7c61..56c4fa58 100644 --- a/contracts/liquidity_hub/pool-manager/src/contract.rs +++ b/contracts/liquidity_hub/pool-manager/src/contract.rs @@ -244,9 +244,16 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> Result Ok(to_json_binary(&queries::get_swap_routes(deps)?)?), QueryMsg::Ownership {} => Ok(to_json_binary(&cw_ownable::get_ownership(deps.storage)?)?), - QueryMsg::Pool { pool_identifier } => { - Ok(to_json_binary(&queries::get_pool(deps, pool_identifier)?)?) - } + QueryMsg::Pools { + pool_identifier, + start_after, + limit, + } => Ok(to_json_binary(&queries::get_pools( + deps, + pool_identifier, + start_after, + limit, + )?)?), QueryMsg::SwapRouteCreator { offer_asset_denom, ask_asset_denom, diff --git a/contracts/liquidity_hub/pool-manager/src/manager/commands.rs b/contracts/liquidity_hub/pool-manager/src/manager/commands.rs index bf7d2824..13247ab2 100644 --- a/contracts/liquidity_hub/pool-manager/src/manager/commands.rs +++ b/contracts/liquidity_hub/pool-manager/src/manager/commands.rs @@ -164,6 +164,7 @@ pub fn create_pool( deps.storage, &identifier, &PoolInfo { + pool_identifier: identifier.clone(), asset_denoms, pool_type: pool_type.clone(), lp_denom: lp_asset.clone(), diff --git a/contracts/liquidity_hub/pool-manager/src/queries.rs b/contracts/liquidity_hub/pool-manager/src/queries.rs index a02e4f3a..2e8afa80 100644 --- a/contracts/liquidity_hub/pool-manager/src/queries.rs +++ b/contracts/liquidity_hub/pool-manager/src/queries.rs @@ -3,11 +3,12 @@ use std::cmp::Ordering; use cosmwasm_std::{ coin, ensure, Coin, Decimal256, Deps, Fraction, Order, StdResult, Uint128, Uint256, }; +use cw_storage_plus::Bound; use white_whale_std::pool_manager::{ - AssetDecimalsResponse, Config, PoolInfoResponse, PoolType, ReverseSimulationResponse, - SimulateSwapOperationsResponse, SimulationResponse, SwapOperation, SwapRoute, - SwapRouteCreatorResponse, SwapRouteResponse, SwapRoutesResponse, + AssetDecimalsResponse, Config, PoolInfoResponse, PoolType, PoolsResponse, + ReverseSimulationResponse, SimulateSwapOperationsResponse, SimulationResponse, SwapOperation, + SwapRoute, SwapRouteCreatorResponse, SwapRouteResponse, SwapRoutesResponse, }; use crate::helpers::get_asset_indexes_in_pool; @@ -287,13 +288,48 @@ pub fn get_swap_route_creator( }) } +// settings for pagination +pub(crate) const MAX_LIMIT: u32 = 100; +const DEFAULT_LIMIT: u32 = 10; + +/// Gets the pools in the contract. Returns a [PoolsResponse]. +pub fn get_pools( + deps: Deps, + pool_identifier: Option, + start_after: Option, + limit: Option, +) -> Result { + let pools = if let Some(pool_identifier) = pool_identifier { + vec![get_pool(deps, pool_identifier)?] + } else { + let limit = limit.unwrap_or(DEFAULT_LIMIT).min(MAX_LIMIT) as usize; + let start = cw_utils::calc_range_start_string(start_after).map(Bound::ExclusiveRaw); + + POOLS + .range(deps.storage, start, None, Order::Ascending) + .take(limit) + .map(|item| { + let (_, pool) = item?; + let total_share = deps.querier.query_supply(&pool.lp_denom)?; + + Ok(PoolInfoResponse { + pool_info: pool, + total_share, + }) + }) + .collect::>>()? + }; + + Ok(PoolsResponse { pools }) +} + /// Gets the pool info for a given pool identifier. Returns a [PoolInfoResponse]. -pub fn get_pool(deps: Deps, pool_identifier: String) -> Result { - let pool = POOLS.load(deps.storage, &pool_identifier)?; - let total_share = deps.querier.query_supply(pool.lp_denom)?; +fn get_pool(deps: Deps, pool_identifier: String) -> Result { + let pool_info = POOLS.load(deps.storage, &pool_identifier)?; + let total_share = deps.querier.query_supply(&pool_info.lp_denom)?; Ok(PoolInfoResponse { - pool_info: POOLS.load(deps.storage, &pool_identifier)?, + pool_info, total_share, }) } diff --git a/contracts/liquidity_hub/pool-manager/src/tests/integration_tests.rs b/contracts/liquidity_hub/pool-manager/src/tests/integration_tests.rs index 1ada98dd..07047706 100644 --- a/contracts/liquidity_hub/pool-manager/src/tests/integration_tests.rs +++ b/contracts/liquidity_hub/pool-manager/src/tests/integration_tests.rs @@ -1918,8 +1918,11 @@ mod swapping { ); // Query pool info to ensure the query is working fine - suite.query_pool_info("whale-uluna".to_string(), |result| { - assert_eq!(result.unwrap().pool_info.asset_decimals, vec![6u8, 6u8]); + suite.query_pools(Some("whale-uluna".to_string()), None, None, |result| { + assert_eq!( + result.unwrap().pools[0].pool_info.asset_decimals, + vec![6u8, 6u8] + ); }); // Lets try to add liquidity @@ -1953,12 +1956,12 @@ mod swapping { })); }, ) - .query_pool_info("whale-uluna".to_string(), |result| { + .query_pools(Some("whale-uluna".to_string()), None, None, |result| { let response = result.unwrap(); assert_eq!( - response.total_share, + response.pools[0].total_share, Coin { - denom: response.pool_info.lp_denom, + denom: response.pools[0].pool_info.lp_denom.clone(), amount: Uint128::from(1_000_000u128), } ); @@ -3235,16 +3238,16 @@ mod provide_liquidity { // 1_000 to the contract, and 1_000_000 to the second, single-side LP assert_eq!(res.unwrap().amount, Uint128::from(2_000_000u128)); }) - .query_pool_info("whale-uluna".to_string(), |res| { + .query_pools(Some("whale-uluna".to_string()), None, None, |res| { let response = res.unwrap(); - let whale = response + let whale = response.pools[0] .pool_info .assets .iter() .find(|coin| coin.denom == "uwhale".to_string()) .unwrap(); - let luna = response + let luna = response.pools[0] .pool_info .assets .iter() @@ -4319,9 +4322,9 @@ mod multiple_pools { result.unwrap(); }, ) - .query_pool_info("whale-uluna-pool-1".to_string(), |result| { + .query_pools(Some("whale-uluna-pool-1".to_string()), None, None, |result| { let response = result.unwrap(); - let pool_info = response.pool_info; + let pool_info = response.pools[0].pool_info.clone(); // swapped 1000 uwhale // fees: @@ -4332,6 +4335,7 @@ mod multiple_pools { // Going out of the pool is 99 (bonding manager) + 29 (burned) assert_eq!(pool_info, PoolInfo { + pool_identifier: "whale-uluna-pool-1".to_string(), asset_denoms: vec!["uwhale".to_string(), "uluna".to_string()], lp_denom: "factory/migaloo1zwv6feuzhy6a9wekh96cd57lsarmqlwxdypdsplw6zhfncqw6ftqqhavvl/uwhale-uluna.pool.whale-uluna-pool-1.uLP".to_string(), asset_decimals: vec![6u8, 6u8], @@ -4362,9 +4366,9 @@ mod multiple_pools { result.unwrap(); }, ) - .query_pool_info("whale-uluna-pool-1".to_string(), |result| { + .query_pools(Some("whale-uluna-pool-1".to_string()), None, None, |result| { let response = result.unwrap(); - let pool_info = response.pool_info; + let pool_info = response.pools[0].pool_info.clone(); // swapped 2000 uluna // fees: @@ -4375,6 +4379,7 @@ mod multiple_pools { // Going out of the pool is 199 (bonding manager) + 59 (burned) assert_eq!(pool_info, PoolInfo { + pool_identifier: "whale-uluna-pool-1".to_string(), asset_denoms: vec!["uwhale".to_string(), "uluna".to_string()], lp_denom: "factory/migaloo1zwv6feuzhy6a9wekh96cd57lsarmqlwxdypdsplw6zhfncqw6ftqqhavvl/uwhale-uluna.pool.whale-uluna-pool-1.uLP".to_string(), asset_decimals: vec![6u8, 6u8], @@ -4415,9 +4420,9 @@ mod multiple_pools { result.unwrap(); }, ) - .query_pool_info("whale-uluna-pool-2".to_string(), |result| { + .query_pools(Some("whale-uluna-pool-2".to_string()), None, None, |result| { let response = result.unwrap(); - let pool_info = response.pool_info; + let pool_info = response.pools[0].pool_info.clone(); // swapped 1000 uwhale // fees: @@ -4428,6 +4433,7 @@ mod multiple_pools { // Going out of the pool is 49 (burned) assert_eq!(pool_info, PoolInfo { + pool_identifier: "whale-uluna-pool-2".to_string(), asset_denoms: vec!["uwhale".to_string(), "uluna".to_string()], lp_denom: "factory/migaloo1zwv6feuzhy6a9wekh96cd57lsarmqlwxdypdsplw6zhfncqw6ftqqhavvl/uwhale-uluna.pool.whale-uluna-pool-2.uLP".to_string(), asset_decimals: vec![6u8, 6u8], @@ -4451,9 +4457,9 @@ mod multiple_pools { result.unwrap(); }, ) - .query_pool_info("whale-uluna-pool-2".to_string(), |result| { + .query_pools(Some("whale-uluna-pool-2".to_string()), None, None, |result| { let response = result.unwrap(); - let pool_info = response.pool_info; + let pool_info = response.pools[0].pool_info.clone(); // swapped 2000 uluna // fees: @@ -4464,6 +4470,7 @@ mod multiple_pools { // Going out of the pool is 99 (burned) assert_eq!(pool_info, PoolInfo { + pool_identifier: "whale-uluna-pool-2".to_string(), asset_denoms: vec!["uwhale".to_string(), "uluna".to_string()], lp_denom: "factory/migaloo1zwv6feuzhy6a9wekh96cd57lsarmqlwxdypdsplw6zhfncqw6ftqqhavvl/uwhale-uluna.pool.whale-uluna-pool-2.uLP".to_string(), asset_decimals: vec![6u8, 6u8], @@ -4505,9 +4512,9 @@ mod multiple_pools { result.unwrap(); }, ) - .query_pool_info("uluna-uusd-pool-1".to_string(), |result| { + .query_pools(Some("uluna-uusd-pool-1".to_string()), None, None, |result| { let response = result.unwrap(); - let pool_info = response.pool_info; + let pool_info = response.pools[0].pool_info.clone(); // swapped 3000 uluna // fees: @@ -4518,6 +4525,7 @@ mod multiple_pools { // Going out of the pool is 299 (bonding manager) + 89 (burned) assert_eq!(pool_info, PoolInfo { + pool_identifier: "uluna-uusd-pool-1".to_string(), asset_denoms: vec!["uluna".to_string(), "uusd".to_string()], lp_denom: "factory/migaloo1zwv6feuzhy6a9wekh96cd57lsarmqlwxdypdsplw6zhfncqw6ftqqhavvl/uluna-uusd.pool.uluna-uusd-pool-1.uLP".to_string(), asset_decimals: vec![6u8, 6u8], @@ -4546,9 +4554,9 @@ mod multiple_pools { result.unwrap(); }, ) - .query_pool_info("uluna-uusd-pool-1".to_string(), |result| { + .query_pools(Some("uluna-uusd-pool-1".to_string()), None, None, |result| { let response = result.unwrap(); - let pool_info = response.pool_info; + let pool_info = response.pools[0].pool_info.clone(); // swapped 1500 uusd // fees: @@ -4559,6 +4567,7 @@ mod multiple_pools { // Going out of the pool is 150 (bonding manager) + 45 (burned) assert_eq!(pool_info, PoolInfo { + pool_identifier: "uluna-uusd-pool-1".to_string(), asset_denoms: vec!["uluna".to_string(), "uusd".to_string()], lp_denom: "factory/migaloo1zwv6feuzhy6a9wekh96cd57lsarmqlwxdypdsplw6zhfncqw6ftqqhavvl/uluna-uusd.pool.uluna-uusd-pool-1.uLP".to_string(), asset_decimals: vec![6u8, 6u8], @@ -4650,12 +4659,13 @@ mod multiple_pools { |result| { result.unwrap(); }, - ).query_pool_info("whale-uluna-pool-1".to_string(), |result| { + ).query_pools(Some("whale-uluna-pool-1".to_string()), None, None, |result| { let response = result.unwrap(); - let pool_info = response.pool_info; + let pool_info = response.pools[0].pool_info.clone(); // this should have not changed since last time, since we didn't touch this pool assert_eq!(pool_info, PoolInfo { + pool_identifier: "whale-uluna-pool-1".to_string(), asset_denoms: vec!["uwhale".to_string(), "uluna".to_string()], lp_denom: "factory/migaloo1zwv6feuzhy6a9wekh96cd57lsarmqlwxdypdsplw6zhfncqw6ftqqhavvl/uwhale-uluna.pool.whale-uluna-pool-1.uLP".to_string(), asset_decimals: vec![6u8, 6u8], @@ -4664,9 +4674,9 @@ mod multiple_pools { pool_fees: pool_fees_1.clone(), }); }) - .query_pool_info("whale-uluna-pool-2".to_string(), |result| { + .query_pools(Some("whale-uluna-pool-2".to_string()), None, None, |result| { let response = result.unwrap(); - let pool_info = response.pool_info; + let pool_info = response.pools[0].pool_info.clone(); // the swap above was: // SwapComputation { return_amount: Uint128(3988), @@ -4674,6 +4684,7 @@ mod multiple_pools { // protocol_fee_amount: Uint128(0), burn_fee_amount: Uint128(249) } assert_eq!(pool_info, PoolInfo { + pool_identifier: "whale-uluna-pool-2".to_string(), asset_denoms: vec!["uwhale".to_string(), "uluna".to_string()], lp_denom: "factory/migaloo1zwv6feuzhy6a9wekh96cd57lsarmqlwxdypdsplw6zhfncqw6ftqqhavvl/uwhale-uluna.pool.whale-uluna-pool-2.uLP".to_string(), asset_decimals: vec![6u8, 6u8], @@ -4681,9 +4692,9 @@ mod multiple_pools { pool_type: PoolType::ConstantProduct, pool_fees: pool_fees_2.clone(), }); - }).query_pool_info("uluna-uusd-pool-1".to_string(), |result| { + }).query_pools(Some("uluna-uusd-pool-1".to_string()),None, None, |result| { let response = result.unwrap(); - let pool_info = response.pool_info; + let pool_info = response.pools[0].pool_info.clone(); // the swap above was: // SwapComputation { return_amount: Uint128(3169), @@ -4691,6 +4702,7 @@ mod multiple_pools { // protocol_fee_amount: Uint128(396), burn_fee_amount: Uint128(118) } assert_eq!(pool_info, PoolInfo { + pool_identifier: "uluna-uusd-pool-1".to_string(), asset_denoms: vec!["uluna".to_string(), "uusd".to_string()], lp_denom: "factory/migaloo1zwv6feuzhy6a9wekh96cd57lsarmqlwxdypdsplw6zhfncqw6ftqqhavvl/uluna-uusd.pool.uluna-uusd-pool-1.uLP".to_string(), asset_decimals: vec![6u8, 6u8], @@ -4753,5 +4765,66 @@ mod multiple_pools { ]); }, ); + + // query pools with pagination + suite + .query_pools(None, None, None, |result| { + let response = result.unwrap(); + assert_eq!(response.pools.len(), 3); + assert_eq!( + response.pools[0].pool_info.pool_identifier, + "uluna-uusd-pool-1" + ); + assert_eq!( + response.pools[1].pool_info.pool_identifier, + "whale-uluna-pool-1" + ); + assert_eq!( + response.pools[2].pool_info.pool_identifier, + "whale-uluna-pool-2" + ); + }) + .query_pools(None, None, Some(2), |result| { + let response = result.unwrap(); + assert_eq!(response.pools.len(), 2); + assert_eq!( + response.pools[0].pool_info.pool_identifier, + "uluna-uusd-pool-1" + ); + assert_eq!( + response.pools[1].pool_info.pool_identifier, + "whale-uluna-pool-1" + ); + }) + .query_pools( + None, + Some("uluna-uusd-pool-1".to_string()), + None, + |result| { + let response = result.unwrap(); + assert_eq!(response.pools.len(), 2); + assert_eq!( + response.pools[0].pool_info.pool_identifier, + "whale-uluna-pool-1" + ); + assert_eq!( + response.pools[1].pool_info.pool_identifier, + "whale-uluna-pool-2" + ); + }, + ) + .query_pools( + None, + Some("whale-uluna-pool-1".to_string()), + None, + |result| { + let response = result.unwrap(); + assert_eq!(response.pools.len(), 1); + assert_eq!( + response.pools[0].pool_info.pool_identifier, + "whale-uluna-pool-2" + ); + }, + ); } } diff --git a/contracts/liquidity_hub/pool-manager/src/tests/suite.rs b/contracts/liquidity_hub/pool-manager/src/tests/suite.rs index 11880bb8..54034f0a 100644 --- a/contracts/liquidity_hub/pool-manager/src/tests/suite.rs +++ b/contracts/liquidity_hub/pool-manager/src/tests/suite.rs @@ -1,7 +1,7 @@ use cosmwasm_std::testing::MockStorage; use std::cell::RefCell; use white_whale_std::pool_manager::{ - Config, FeatureToggle, PoolInfoResponse, ReverseSimulateSwapOperationsResponse, + Config, FeatureToggle, PoolsResponse, ReverseSimulateSwapOperationsResponse, ReverseSimulationResponse, SimulateSwapOperationsResponse, SimulationResponse, SwapOperation, SwapRoute, SwapRouteCreatorResponse, SwapRouteResponse, SwapRoutesResponse, }; @@ -610,17 +610,23 @@ impl TestingSuite { self } - pub(crate) fn query_pool_info( + pub(crate) fn query_pools( &self, - pool_identifier: String, - result: impl Fn(StdResult), + pool_identifier: Option, + start_after: Option, + limit: Option, + result: impl Fn(StdResult), ) -> &Self { - let pool_info_response: StdResult = self.app.wrap().query_wasm_smart( + let pools_response: StdResult = self.app.wrap().query_wasm_smart( &self.pool_manager_addr, - &white_whale_std::pool_manager::QueryMsg::Pool { pool_identifier }, + &white_whale_std::pool_manager::QueryMsg::Pools { + pool_identifier, + start_after, + limit, + }, ); - result(pool_info_response); + result(pools_response); self } @@ -715,13 +721,15 @@ impl TestingSuite { result: impl Fn(StdResult), ) -> &mut Self { // Get the LP token from Config - let lp_token_response: PoolInfoResponse = self + let lp_token_response: PoolsResponse = self .app .wrap() .query_wasm_smart( &self.pool_manager_addr, - &white_whale_std::pool_manager::QueryMsg::Pool { - pool_identifier: identifier, + &white_whale_std::pool_manager::QueryMsg::Pools { + pool_identifier: Some(identifier), + start_after: None, + limit: None, }, ) .unwrap(); @@ -731,7 +739,7 @@ impl TestingSuite { let balance: Uint128 = self .app .wrap() - .query_balance(sender, lp_token_response.pool_info.lp_denom) + .query_balance(sender, &lp_token_response.pools[0].pool_info.lp_denom) .unwrap() .amount; @@ -834,9 +842,9 @@ impl TestingSuite { ) -> &mut Self { let lp_denom = RefCell::new("".to_string()); - self.query_pool_info(identifier.clone(), |res| { + self.query_pools(Some(identifier.clone()), None, None, |res| { let response = res.unwrap(); - *lp_denom.borrow_mut() = response.pool_info.lp_denom.clone(); + *lp_denom.borrow_mut() = response.pools[0].pool_info.lp_denom.clone(); }); let supply_response = self.app.wrap().query_supply(lp_denom.into_inner()); diff --git a/integration-tests/tests/common/suite.rs b/integration-tests/tests/common/suite.rs index 0c7f88c4..e3d5388a 100644 --- a/integration-tests/tests/common/suite.rs +++ b/integration-tests/tests/common/suite.rs @@ -19,7 +19,7 @@ use white_whale_std::incentive_manager::{ PositionsResponse, }; use white_whale_std::pool_manager::{ - PoolInfoResponse, PoolType, ReverseSimulateSwapOperationsResponse, ReverseSimulationResponse, + PoolType, PoolsResponse, ReverseSimulateSwapOperationsResponse, ReverseSimulationResponse, SimulateSwapOperationsResponse, SimulationResponse, SwapOperation, SwapRoute, SwapRoutesResponse, }; @@ -1015,17 +1015,23 @@ impl TestingSuite { self } - pub(crate) fn _query_pool( + pub(crate) fn _query_pools( &self, - pool_identifier: String, - result: impl Fn(StdResult), + pool_identifier: Option, + start_after: Option, + limit: Option, + result: impl Fn(StdResult), ) -> &Self { - let pool_info_response: StdResult = self.app.wrap().query_wasm_smart( + let pools_response: StdResult = self.app.wrap().query_wasm_smart( &self.pool_manager_addr, - &white_whale_std::pool_manager::QueryMsg::Pool { pool_identifier }, + &white_whale_std::pool_manager::QueryMsg::Pools { + pool_identifier, + start_after, + limit, + }, ); - result(pool_info_response); + result(pools_response); self } diff --git a/packages/white-whale-std/Cargo.toml b/packages/white-whale-std/Cargo.toml index bbbcf61a..e529d88c 100644 --- a/packages/white-whale-std/Cargo.toml +++ b/packages/white-whale-std/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "white-whale-std" -version = "1.1.3" +version = "1.1.6" edition.workspace = true authors = [ "Kerber0x ", @@ -13,6 +13,7 @@ license.workspace = true repository.workspace = true homepage.workspace = true documentation.workspace = true +keywords = ["cosmos", "cosmwasm", "whitewhale", "migaloo"] [features] default = ["osmosis_token_factory"] diff --git a/packages/white-whale-std/src/pool_manager.rs b/packages/white-whale-std/src/pool_manager.rs index 8823750c..389730a8 100644 --- a/packages/white-whale-std/src/pool_manager.rs +++ b/packages/white-whale-std/src/pool_manager.rs @@ -116,6 +116,8 @@ pub struct StableSwapParams { /// Contains the pool information #[cw_serde] pub struct PoolInfo { + /// The identifier for the pool. + pub pool_identifier: String, /// The asset denoms for the pool. pub asset_denoms: Vec, /// The LP denom of the pool. @@ -333,8 +335,17 @@ pub enum QueryMsg { operations: Vec, }, /// Retrieves the pool information for the given pool identifier. - #[returns(PoolInfoResponse)] - Pool { pool_identifier: String }, + #[returns(PoolsResponse)] + Pools { + /// An optional parameter specifying the pool identifier to do the query for. If not + /// provided, it will return all pools based on the pagination parameters. + pool_identifier: Option, + /// An optional parameter specifying what pool (identifier) to start searching after. + start_after: Option, + /// The amount of pools to return. If unspecified, will default to a value specified by + /// the contract. + limit: Option, + }, /// Retrieves the creator of the swap route to get from offer to ask asset. The creator of /// the swap route can remove it. #[returns(SwapRouteCreatorResponse)] @@ -360,7 +371,13 @@ pub struct SwapRoutesResponse { pub swap_routes: Vec, } -/// The response for the `Pool` query. +/// The response for the `Pools` query. +#[cw_serde] +pub struct PoolsResponse { + /// The pools information responses. + pub pools: Vec, +} + #[cw_serde] pub struct PoolInfoResponse { /// The pool information for the given pool identifier. @@ -448,4 +465,4 @@ pub struct ReverseSimulateSwapOperationsResponse { pub struct SwapRouteCreatorResponse { /// The creator of the swap route. pub creator: String, -} \ No newline at end of file +}