From b0ed43f930a60019f1c4728dac45d3f3ead3c960 Mon Sep 17 00:00:00 2001 From: cyberhoward Date: Wed, 1 Feb 2023 16:53:10 +0100 Subject: [PATCH 1/9] Add `TransferFee` struct and `Chargeable` trait --- packages/abstract-os/src/modules/apis/dex.rs | 15 +++- packages/abstract-os/src/objects/fee.rs | 77 +++++++++++++++++++- packages/abstract-sdk/src/helpers/fees.rs | 26 +++++++ packages/abstract-sdk/src/helpers/mod.rs | 1 + 4 files changed, 114 insertions(+), 5 deletions(-) create mode 100644 packages/abstract-sdk/src/helpers/fees.rs diff --git a/packages/abstract-os/src/modules/apis/dex.rs b/packages/abstract-os/src/modules/apis/dex.rs index 5eb1c3030..effcf7076 100644 --- a/packages/abstract-os/src/modules/apis/dex.rs +++ b/packages/abstract-os/src/modules/apis/dex.rs @@ -14,15 +14,28 @@ pub type DexName = String; pub type OfferAsset = AnsAsset; pub type AskAsset = AnsAsset; +pub mod state { + use cw_storage_plus::Item; + + use crate::objects::fee::Fee; + + pub const SWAP_FEE: Item = Item::new("swap_fee"); +} + pub const IBC_DEX_ID: u32 = 11335; pub type ExecuteMsg = api::ExecuteMsg; pub type QueryMsg = api::QueryMsg; impl api::ApiExecuteMsg for DexExecuteMsg {} - impl api::ApiQueryMsg for DexQueryMsg {} +#[cosmwasm_schema::cw_serde] +// Struct messages not yet supported by BOOT +pub struct DexInstantiateMsg { + pub swap_fee: Decimal, +} + /// Dex Execute msg #[cosmwasm_schema::cw_serde] // Struct messages not yet supported by BOOT diff --git a/packages/abstract-os/src/objects/fee.rs b/packages/abstract-os/src/objects/fee.rs index a51161cb9..d3ccfcedf 100644 --- a/packages/abstract-os/src/objects/fee.rs +++ b/packages/abstract-os/src/objects/fee.rs @@ -1,10 +1,33 @@ -use cosmwasm_std::{Addr, CosmosMsg, Decimal, StdError, StdResult, Uint128}; +use cosmwasm_std::{Addr, CosmosMsg, Decimal, StdError, StdResult, Uint128, Api}; use cw_asset::Asset; -use schemars::JsonSchema; -use serde::{Deserialize, Serialize}; + +/// A wrapper around Fee to help handle fee logic. +/// Use this with `Chargeable` trait in the SDK to charge fees on asset structs. +#[cosmwasm_schema::cw_serde] +pub struct TransferFee { + fee: Fee, + recipient: Addr, +} + +impl TransferFee { + pub fn new(api: &dyn Api,share: Decimal, recipient: impl Into) -> StdResult { + let recipient = api.addr_validate(&recipient.into())?; + let fee = Fee::new(share)?; + Ok(TransferFee { fee, recipient }) + } + pub fn share(&self) -> Decimal { + self.fee.share() + } + pub fn compute(&self, amount: Uint128) -> Uint128 { + amount * self.share() + } + pub fn recipient(&self) -> Addr { + self.recipient.clone() + } +} /// A wrapper around Decimal to help handle fractional fees. -#[derive(Deserialize, Serialize, Clone, Debug, PartialEq, Eq, JsonSchema)] +#[cosmwasm_schema::cw_serde] pub struct Fee { /// fraction of asset to take as fee. share: Decimal, @@ -33,6 +56,9 @@ impl Fee { mod tests { use super::*; + mod fee { + use super::*; + #[test] fn test_fee_manual_construction() { let fee = Fee { @@ -76,3 +102,46 @@ mod tests { assert_eq!(msg, asset.transfer_msg(recipient).unwrap(),); } } +mod transfer_fee { + use cosmwasm_std::testing::MockApi; + + use super::*; + + #[test] + fn test_transfer_fee_new() { + let api = MockApi::default(); + let fee = TransferFee::new(&api, Decimal::percent(20u64), "recipient").unwrap(); + let deposit = Uint128::from(1000000u64); + let deposit_fee = fee.compute(deposit); + assert_eq!(deposit_fee, Uint128::from(200000u64)); + } + + #[test] + fn test_transfer_fee_share() { + let api = MockApi::default(); + let expected_percent = 20u64; + let fee = TransferFee::new(&api, Decimal::percent(expected_percent), "recipient").unwrap(); + assert_eq!(fee.share(), Decimal::percent(expected_percent)); + } + + #[test] + fn test_transfer_fee_msg() { + let api = MockApi::default(); + let fee = TransferFee::new(&api, Decimal::percent(20u64), "recipient").unwrap(); + let asset = Asset::native("uusd", Uint128::from(1000000u64)); + + let recipient = Addr::unchecked("recipient"); + let msg = fee.fee.msg(asset.clone(), recipient.clone()).unwrap(); + assert_eq!(msg, asset.transfer_msg(recipient).unwrap(),); + } + + #[test] + fn test_transfer_fee_new_gte_100() { + let api = MockApi::default(); + let fee = TransferFee::new(&api, Decimal::percent(100u64), "recipient"); + assert!(fee.is_err()); + let fee = TransferFee::new(&api, Decimal::percent(101u64), "recipient"); + assert!(fee.is_err()); + } +} +} diff --git a/packages/abstract-sdk/src/helpers/fees.rs b/packages/abstract-sdk/src/helpers/fees.rs new file mode 100644 index 000000000..885f26c05 --- /dev/null +++ b/packages/abstract-sdk/src/helpers/fees.rs @@ -0,0 +1,26 @@ +//! # Fee helpers +//! Helper trait that lets you easily charge fees on assets + +use cosmwasm_std::{StdResult, CosmosMsg}; +use cw_asset::Asset; +use os::objects::fee::{TransferFee, Fee}; + +/// Indicates that the implementing type can be charged fees. +pub trait Chargeable { + fn charge_fee(&mut self, fee: Fee) -> StdResult<()>; + fn charge_transfer_fee(&mut self, fee: TransferFee) -> StdResult; +} + +impl Chargeable for Asset { + fn charge_fee(&mut self, fee: Fee) -> StdResult<()> { + let fee_amount = fee.compute(self.amount); + self.amount -= fee_amount; + Ok(()) + } + + fn charge_transfer_fee(&mut self, fee: TransferFee) -> StdResult { + let fee_amount = fee.compute(self.amount); + self.amount -= fee_amount; + Asset::new(self.info.clone(), fee_amount).transfer_msg(fee.recipient()) + } +} \ No newline at end of file diff --git a/packages/abstract-sdk/src/helpers/mod.rs b/packages/abstract-sdk/src/helpers/mod.rs index fd3f491e6..b1ff5a30f 100644 --- a/packages/abstract-sdk/src/helpers/mod.rs +++ b/packages/abstract-sdk/src/helpers/mod.rs @@ -1 +1,2 @@ pub mod cosmwasm_std; +pub mod fees; From 9c7cd3b17c136c2b69ea53517dc6feaac39c23d5 Mon Sep 17 00:00:00 2001 From: cyberhoward Date: Wed, 1 Feb 2023 17:06:03 +0100 Subject: [PATCH 2/9] add tests to fee --- packages/abstract-os/src/modules/apis/dex.rs | 4 +- packages/abstract-os/src/objects/fee.rs | 158 +++++++++---------- packages/abstract-sdk/src/helpers/fees.rs | 57 ++++++- 3 files changed, 130 insertions(+), 89 deletions(-) diff --git a/packages/abstract-os/src/modules/apis/dex.rs b/packages/abstract-os/src/modules/apis/dex.rs index effcf7076..5122c0f07 100644 --- a/packages/abstract-os/src/modules/apis/dex.rs +++ b/packages/abstract-os/src/modules/apis/dex.rs @@ -17,9 +17,9 @@ pub type AskAsset = AnsAsset; pub mod state { use cw_storage_plus::Item; - use crate::objects::fee::Fee; + use crate::objects::fee::UsageFee; - pub const SWAP_FEE: Item = Item::new("swap_fee"); + pub const SWAP_FEE: Item = Item::new("swap_fee"); } pub const IBC_DEX_ID: u32 = 11335; diff --git a/packages/abstract-os/src/objects/fee.rs b/packages/abstract-os/src/objects/fee.rs index d3ccfcedf..af2633ca3 100644 --- a/packages/abstract-os/src/objects/fee.rs +++ b/packages/abstract-os/src/objects/fee.rs @@ -1,19 +1,19 @@ -use cosmwasm_std::{Addr, CosmosMsg, Decimal, StdError, StdResult, Uint128, Api}; +use cosmwasm_std::{Addr, Api, CosmosMsg, Decimal, StdError, StdResult, Uint128}; use cw_asset::Asset; /// A wrapper around Fee to help handle fee logic. /// Use this with `Chargeable` trait in the SDK to charge fees on asset structs. #[cosmwasm_schema::cw_serde] -pub struct TransferFee { +pub struct UsageFee { fee: Fee, recipient: Addr, } -impl TransferFee { - pub fn new(api: &dyn Api,share: Decimal, recipient: impl Into) -> StdResult { +impl UsageFee { + pub fn new(api: &dyn Api, share: Decimal, recipient: impl Into) -> StdResult { let recipient = api.addr_validate(&recipient.into())?; let fee = Fee::new(share)?; - Ok(TransferFee { fee, recipient }) + Ok(UsageFee { fee, recipient }) } pub fn share(&self) -> Decimal { self.fee.share() @@ -57,91 +57,91 @@ mod tests { use super::*; mod fee { - use super::*; - - #[test] - fn test_fee_manual_construction() { - let fee = Fee { - share: Decimal::percent(20u64), - }; - let deposit = Uint128::from(1000000u64); - let deposit_fee = fee.compute(deposit); - assert_eq!(deposit_fee, Uint128::from(200000u64)); - } + use super::*; + + #[test] + fn test_fee_manual_construction() { + let fee = Fee { + share: Decimal::percent(20u64), + }; + let deposit = Uint128::from(1000000u64); + let deposit_fee = fee.compute(deposit); + assert_eq!(deposit_fee, Uint128::from(200000u64)); + } - #[test] - fn test_fee_new() { - let fee = Fee::new(Decimal::percent(20u64)).unwrap(); - let deposit = Uint128::from(1000000u64); - let deposit_fee = fee.compute(deposit); - assert_eq!(deposit_fee, Uint128::from(200000u64)); - } + #[test] + fn test_fee_new() { + let fee = Fee::new(Decimal::percent(20u64)).unwrap(); + let deposit = Uint128::from(1000000u64); + let deposit_fee = fee.compute(deposit); + assert_eq!(deposit_fee, Uint128::from(200000u64)); + } - #[test] - fn test_fee_new_gte_100() { - let fee = Fee::new(Decimal::percent(100u64)); - assert!(fee.is_err()); - let fee = Fee::new(Decimal::percent(101u64)); - assert!(fee.is_err()); - } + #[test] + fn test_fee_new_gte_100() { + let fee = Fee::new(Decimal::percent(100u64)); + assert!(fee.is_err()); + let fee = Fee::new(Decimal::percent(101u64)); + assert!(fee.is_err()); + } - #[test] - fn test_fee_share() { - let expected_percent = 20u64; - let fee = Fee::new(Decimal::percent(expected_percent)).unwrap(); - assert_eq!(fee.share(), Decimal::percent(expected_percent)); - } + #[test] + fn test_fee_share() { + let expected_percent = 20u64; + let fee = Fee::new(Decimal::percent(expected_percent)).unwrap(); + assert_eq!(fee.share(), Decimal::percent(expected_percent)); + } - #[test] - fn test_fee_msg() { - let fee = Fee::new(Decimal::percent(20u64)).unwrap(); - let asset = Asset::native("uusd", Uint128::from(1000000u64)); + #[test] + fn test_fee_msg() { + let fee = Fee::new(Decimal::percent(20u64)).unwrap(); + let asset = Asset::native("uusd", Uint128::from(1000000u64)); - let recipient = Addr::unchecked("recipient"); - let msg = fee.msg(asset.clone(), recipient.clone()).unwrap(); - assert_eq!(msg, asset.transfer_msg(recipient).unwrap(),); + let recipient = Addr::unchecked("recipient"); + let msg = fee.msg(asset.clone(), recipient.clone()).unwrap(); + assert_eq!(msg, asset.transfer_msg(recipient).unwrap(),); + } } -} -mod transfer_fee { - use cosmwasm_std::testing::MockApi; + mod transfer_fee { + use cosmwasm_std::testing::MockApi; - use super::*; + use super::*; - #[test] - fn test_transfer_fee_new() { - let api = MockApi::default(); - let fee = TransferFee::new(&api, Decimal::percent(20u64), "recipient").unwrap(); - let deposit = Uint128::from(1000000u64); - let deposit_fee = fee.compute(deposit); - assert_eq!(deposit_fee, Uint128::from(200000u64)); - } + #[test] + fn test_transfer_fee_new() { + let api = MockApi::default(); + let fee = UsageFee::new(&api, Decimal::percent(20u64), "recipient").unwrap(); + let deposit = Uint128::from(1000000u64); + let deposit_fee = fee.compute(deposit); + assert_eq!(deposit_fee, Uint128::from(200000u64)); + } - #[test] - fn test_transfer_fee_share() { - let api = MockApi::default(); - let expected_percent = 20u64; - let fee = TransferFee::new(&api, Decimal::percent(expected_percent), "recipient").unwrap(); - assert_eq!(fee.share(), Decimal::percent(expected_percent)); - } + #[test] + fn test_transfer_fee_share() { + let api = MockApi::default(); + let expected_percent = 20u64; + let fee = UsageFee::new(&api, Decimal::percent(expected_percent), "recipient").unwrap(); + assert_eq!(fee.share(), Decimal::percent(expected_percent)); + } - #[test] - fn test_transfer_fee_msg() { - let api = MockApi::default(); - let fee = TransferFee::new(&api, Decimal::percent(20u64), "recipient").unwrap(); - let asset = Asset::native("uusd", Uint128::from(1000000u64)); + #[test] + fn test_transfer_fee_msg() { + let api = MockApi::default(); + let fee = UsageFee::new(&api, Decimal::percent(20u64), "recipient").unwrap(); + let asset = Asset::native("uusd", Uint128::from(1000000u64)); - let recipient = Addr::unchecked("recipient"); - let msg = fee.fee.msg(asset.clone(), recipient.clone()).unwrap(); - assert_eq!(msg, asset.transfer_msg(recipient).unwrap(),); - } + let recipient = Addr::unchecked("recipient"); + let msg = fee.fee.msg(asset.clone(), recipient.clone()).unwrap(); + assert_eq!(msg, asset.transfer_msg(recipient).unwrap(),); + } - #[test] - fn test_transfer_fee_new_gte_100() { - let api = MockApi::default(); - let fee = TransferFee::new(&api, Decimal::percent(100u64), "recipient"); - assert!(fee.is_err()); - let fee = TransferFee::new(&api, Decimal::percent(101u64), "recipient"); - assert!(fee.is_err()); + #[test] + fn test_transfer_fee_new_gte_100() { + let api = MockApi::default(); + let fee = UsageFee::new(&api, Decimal::percent(100u64), "recipient"); + assert!(fee.is_err()); + let fee = UsageFee::new(&api, Decimal::percent(101u64), "recipient"); + assert!(fee.is_err()); + } } } -} diff --git a/packages/abstract-sdk/src/helpers/fees.rs b/packages/abstract-sdk/src/helpers/fees.rs index 885f26c05..5e5797c95 100644 --- a/packages/abstract-sdk/src/helpers/fees.rs +++ b/packages/abstract-sdk/src/helpers/fees.rs @@ -1,26 +1,67 @@ //! # Fee helpers //! Helper trait that lets you easily charge fees on assets -use cosmwasm_std::{StdResult, CosmosMsg}; +use cosmwasm_std::{CosmosMsg, StdResult, Uint128}; use cw_asset::Asset; -use os::objects::fee::{TransferFee, Fee}; +use os::objects::fee::{Fee, UsageFee}; /// Indicates that the implementing type can be charged fees. pub trait Chargeable { - fn charge_fee(&mut self, fee: Fee) -> StdResult<()>; - fn charge_transfer_fee(&mut self, fee: TransferFee) -> StdResult; + /// Charge a fee on the asset and returns the amount charged. + fn charge_fee(&mut self, fee: Fee) -> StdResult; + /// Charge a fee on the asset and returns the fee transfer message. + fn charge_usage_fee(&mut self, fee: UsageFee) -> StdResult; } impl Chargeable for Asset { - fn charge_fee(&mut self, fee: Fee) -> StdResult<()> { + fn charge_fee(&mut self, fee: Fee) -> StdResult { let fee_amount = fee.compute(self.amount); self.amount -= fee_amount; - Ok(()) + Ok(fee_amount) } - fn charge_transfer_fee(&mut self, fee: TransferFee) -> StdResult { + fn charge_usage_fee(&mut self, fee: UsageFee) -> StdResult { let fee_amount = fee.compute(self.amount); self.amount -= fee_amount; Asset::new(self.info.clone(), fee_amount).transfer_msg(fee.recipient()) } -} \ No newline at end of file +} + +#[cfg(test)] +mod tests { + use super::*; + use cosmwasm_std::{testing::MockApi, Addr, Decimal}; + use cw_asset::AssetInfo; + + // test that we can charge fees on assets + + #[test] + fn test_charge_fee() { + let info = AssetInfo::native("uusd"); + let mut asset = Asset::new(info, 1000u128); + let fee = Fee::new(Decimal::percent(10)).unwrap(); + let charged = asset.charge_fee(fee).unwrap(); + assert_eq!(asset.amount.u128(), 900); + assert_eq!(charged.u128(), 100); + } + // test transfer fee + #[test] + fn test_charge_transfer_fee() { + let info = AssetInfo::native("uusd"); + let mut asset: Asset = Asset::new(info.clone(), 1000u128); + let fee = UsageFee::new( + &MockApi::default(), + Decimal::percent(10), + Addr::unchecked("recipient"), + ) + .unwrap(); + let msg = asset.charge_usage_fee(fee).unwrap(); + assert_eq!(asset.amount.u128(), 900); + assert_eq!( + msg, + Asset::new(info, 100u128) + .transfer_msg(Addr::unchecked("recipient")) + .unwrap() + ); + } +} From 296ba8cc2fad5de90f192bfb68f60b8493fe1a64 Mon Sep 17 00:00:00 2001 From: cyberhoward Date: Wed, 1 Feb 2023 17:25:49 +0100 Subject: [PATCH 3/9] update OsRegister --- packages/abstract-sdk/src/apis/verify.rs | 53 +++++++++++++----------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/packages/abstract-sdk/src/apis/verify.rs b/packages/abstract-sdk/src/apis/verify.rs index 677899a31..ccc38291e 100644 --- a/packages/abstract-sdk/src/apis/verify.rs +++ b/packages/abstract-sdk/src/apis/verify.rs @@ -30,21 +30,13 @@ impl<'a, T: Verification> OsRegister<'a, T> { let os_id = OS_ID .query(&self.deps.querier, maybe_manager.clone()) .map_err(|_| StdError::generic_err("Caller must be an OS manager."))?; - let maybe_os = - OS_ADDRESSES.query(&self.deps.querier, self.base.registry(self.deps)?, os_id)?; - match maybe_os { - None => Err(StdError::generic_err(format!( - "OS with id {os_id} is not active." - ))), - Some(core) => { - if &core.manager != maybe_manager { - Err(StdError::generic_err( - "Proposed manager is not the manager of this OS.", - )) - } else { - Ok(core) - } - } + let core = self.core(os_id)?; + if &core.manager != maybe_manager { + Err(StdError::generic_err( + "Proposed manager is not the manager of this OS.", + )) + } else { + Ok(core) } } @@ -53,21 +45,32 @@ impl<'a, T: Verification> OsRegister<'a, T> { let os_id = OS_ID .query(&self.deps.querier, maybe_proxy.clone()) .map_err(|_| StdError::generic_err("Caller must be an OS proxy."))?; + let core = self.core(os_id)?; + if &core.proxy != maybe_proxy { + Err(StdError::generic_err( + "Proposed proxy is not the proxy of this OS.", + )) + } else { + Ok(core) + } + } + + pub fn proxy_address(&self, os_id: u32) -> StdResult { + self.core(os_id).map(|core| core.proxy) + } + + pub fn manager_address(&self, os_id: u32) -> StdResult { + self.core(os_id).map(|core| core.manager) + } + + pub fn core(&self, os_id: u32) -> StdResult { let maybe_os = OS_ADDRESSES.query(&self.deps.querier, self.base.registry(self.deps)?, os_id)?; match maybe_os { None => Err(StdError::generic_err(format!( - "OS with id {os_id} is not active." + "OS with id {os_id} is not registered." ))), - Some(core) => { - if &core.proxy != maybe_proxy { - Err(StdError::generic_err( - "Proposed proxy is not the proxy of this OS.", - )) - } else { - Ok(core) - } - } + Some(core) => Ok(core), } } } From b4cc26eb96ba3a3678922a74cb20e9c4dd5fd4db Mon Sep 17 00:00:00 2001 From: cyberhoward Date: Wed, 1 Feb 2023 18:06:51 +0100 Subject: [PATCH 4/9] format and fix --- contracts/modules/apis/dex/src/commands.rs | 14 +++++++---- contracts/modules/apis/dex/src/contract.rs | 6 +++-- .../dex/src/exchanges/exchange_resolver.rs | 5 +++- .../apis/dex/src/handlers/instantiate.rs | 23 +++++++++++++++++++ .../modules/apis/dex/src/handlers/mod.rs | 3 ++- .../modules/apis/dex/src/handlers/query.rs | 8 +++++++ .../native/ans-host/src/tests/mock_querier.rs | 4 ++-- contracts/native/ibc-client/src/commands.rs | 1 - contracts/native/ibc-client/src/ibc.rs | 5 +--- .../native/module-factory/src/commands.rs | 4 +--- contracts/native/os-factory/src/commands.rs | 2 +- .../abstract-api/src/endpoints/execute.rs | 6 ++--- packages/abstract-app/src/endpoints.rs | 4 ++-- .../abstract-app/src/endpoints/execute.rs | 2 +- .../abstract-app/src/endpoints/instantiate.rs | 8 ++----- packages/abstract-app/src/endpoints/query.rs | 10 ++++---- packages/abstract-app/src/features.rs | 2 +- packages/abstract-app/src/lib.rs | 2 +- packages/abstract-os/src/modules/apis/dex.rs | 4 +++- .../abstract-os/src/objects/proxy_asset.rs | 4 +--- 20 files changed, 74 insertions(+), 43 deletions(-) create mode 100644 contracts/modules/apis/dex/src/handlers/instantiate.rs diff --git a/contracts/modules/apis/dex/src/commands.rs b/contracts/modules/apis/dex/src/commands.rs index 79693f986..2306b80a4 100644 --- a/contracts/modules/apis/dex/src/commands.rs +++ b/contracts/modules/apis/dex/src/commands.rs @@ -1,6 +1,8 @@ use crate::{error::DexError, DEX}; +use abstract_os::dex::state::SWAP_FEE; use abstract_os::objects::{DexAssetPairing, PoolReference}; use abstract_sdk::base::features::AbstractNameService; +use abstract_sdk::helpers::fees::Chargeable; use abstract_sdk::os::dex::AskAsset; use abstract_sdk::os::objects::AnsAsset; use abstract_sdk::os::{ @@ -128,16 +130,20 @@ pub trait LocalDex: AbstractNameService + Execution { let pair_address = exchange.pair_address(deps, ans.host(), (offer_asset.clone(), ask_asset))?; - let offer_asset: Asset = Asset::new(offer_asset_info, offer_amount); - - exchange.swap( + let mut offer_asset: Asset = Asset::new(offer_asset_info, offer_amount); + // account for fee + let fee = SWAP_FEE.load(deps.storage)?; + let fee_msg = offer_asset.charge_usage_fee(fee)?; + let mut swap_msgs = exchange.swap( deps, pair_address, offer_asset, ask_asset_info, belief_price, max_spread, - ) + )?; + swap_msgs.push(fee_msg.clone()); + Ok(swap_msgs) } #[allow(clippy::too_many_arguments)] diff --git a/contracts/modules/apis/dex/src/contract.rs b/contracts/modules/apis/dex/src/contract.rs index e82ab3d22..2259439c3 100644 --- a/contracts/modules/apis/dex/src/contract.rs +++ b/contracts/modules/apis/dex/src/contract.rs @@ -1,17 +1,19 @@ use crate::{error::DexError, handlers}; use abstract_api::ApiContract; +use abstract_os::dex::DexInstantiateMsg; use abstract_sdk::os::{ dex::{DexExecuteMsg, DexQueryMsg}, EXCHANGE, }; -use cosmwasm_std::{Empty, Response}; +use cosmwasm_std::Response; const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); -pub type DexApi = ApiContract; +pub type DexApi = ApiContract; pub type DexResult = Result; pub const DEX_API: DexApi = DexApi::new(EXCHANGE, CONTRACT_VERSION, None) + .with_instantiate(handlers::instantiate_handler) .with_execute(handlers::execute_handler) .with_query(handlers::query_handler); diff --git a/contracts/modules/apis/dex/src/exchanges/exchange_resolver.rs b/contracts/modules/apis/dex/src/exchanges/exchange_resolver.rs index aa94f160e..8824d1c85 100644 --- a/contracts/modules/apis/dex/src/exchanges/exchange_resolver.rs +++ b/contracts/modules/apis/dex/src/exchanges/exchange_resolver.rs @@ -4,7 +4,10 @@ use crate::DEX; // Supported exchanges on Juno #[cfg(feature = "juno")] -pub use crate::exchanges::{junoswap::{JunoSwap, JUNOSWAP}, wyndex::{WynDex, WYNDEX}}; +pub use crate::exchanges::{ + junoswap::{JunoSwap, JUNOSWAP}, + wyndex::{WynDex, WYNDEX}, +}; #[cfg(any(feature = "juno", feature = "terra"))] pub use crate::exchanges::loop_dex::{Loop, LOOP}; diff --git a/contracts/modules/apis/dex/src/handlers/instantiate.rs b/contracts/modules/apis/dex/src/handlers/instantiate.rs new file mode 100644 index 000000000..30e34ad87 --- /dev/null +++ b/contracts/modules/apis/dex/src/handlers/instantiate.rs @@ -0,0 +1,23 @@ +use abstract_os::{ + dex::{state::SWAP_FEE, DexInstantiateMsg}, + objects::fee::UsageFee, +}; +use abstract_sdk::Verification; +use cosmwasm_std::{DepsMut, Env, MessageInfo, Response}; + +use crate::contract::{DexApi, DexResult}; + +pub fn instantiate_handler( + deps: DepsMut, + _env: Env, + _info: MessageInfo, + api: DexApi, + msg: DexInstantiateMsg, +) -> DexResult { + let recipient = api + .os_register(deps.as_ref()) + .proxy_address(msg.recipient_os)?; + let fee = UsageFee::new(deps.api, msg.swap_fee, recipient)?; + SWAP_FEE.save(deps.storage, &fee)?; + Ok(Response::default()) +} diff --git a/contracts/modules/apis/dex/src/handlers/mod.rs b/contracts/modules/apis/dex/src/handlers/mod.rs index bf8dd129f..d67297e4b 100644 --- a/contracts/modules/apis/dex/src/handlers/mod.rs +++ b/contracts/modules/apis/dex/src/handlers/mod.rs @@ -1,4 +1,5 @@ mod execute; +mod instantiate; mod query; -pub use {execute::execute_handler, query::query_handler}; +pub use {execute::execute_handler, instantiate::instantiate_handler, query::query_handler}; diff --git a/contracts/modules/apis/dex/src/handlers/query.rs b/contracts/modules/apis/dex/src/handlers/query.rs index 0c9d3c3cd..b07e1950e 100644 --- a/contracts/modules/apis/dex/src/handlers/query.rs +++ b/contracts/modules/apis/dex/src/handlers/query.rs @@ -1,5 +1,6 @@ use crate::contract::DexApi; use crate::exchanges::exchange_resolver::resolve_exchange; +use abstract_os::dex::state::SWAP_FEE; use abstract_os::dex::{DexQueryMsg, OfferAsset, SimulateSwapResponse}; use abstract_os::objects::{AssetEntry, DexAssetPairing}; use abstract_sdk::base::features::AbstractNameService; @@ -27,6 +28,8 @@ pub fn simulate_swap( ) -> StdResult { let exchange = resolve_exchange(&dex).map_err(|e| StdError::generic_err(e.to_string()))?; let ans = api.name_service(deps); + let fee = SWAP_FEE.load(deps.storage)?; + // format input offer_asset.name.format(); ask_asset.format(); @@ -47,6 +50,10 @@ pub fn simulate_swap( let pool_info = DexAssetPairing::new(offer_asset.name.clone(), ask_asset.clone(), exchange.name()); + // compute api fee + let api_fee = fee.compute(offer_asset.amount); + offer_asset.amount -= api_fee; + let (return_amount, spread_amount, commission_amount, fee_on_input) = exchange .simulate_swap(deps, pair_address, swap_offer_asset, ask_asset_info) .map_err(|e| StdError::generic_err(e.to_string()))?; @@ -60,6 +67,7 @@ pub fn simulate_swap( return_amount, spread_amount, commission: (commission_asset, commission_amount), + api_fee, }; to_binary(&resp).map_err(From::from) } diff --git a/contracts/native/ans-host/src/tests/mock_querier.rs b/contracts/native/ans-host/src/tests/mock_querier.rs index 51c05270e..4ad7f5b51 100644 --- a/contracts/native/ans-host/src/tests/mock_querier.rs +++ b/contracts/native/ans-host/src/tests/mock_querier.rs @@ -86,8 +86,8 @@ impl WasmMockQuerier { None => { return SystemResult::Err(SystemError::InvalidRequest { error: format!( - "No balance info exists for the contract {contract_addr}" - ), + "No balance info exists for the contract {contract_addr}" + ), request: msg.as_slice().into(), }) } diff --git a/contracts/native/ibc-client/src/commands.rs b/contracts/native/ibc-client/src/commands.rs index aa6773cb6..1defc11d2 100644 --- a/contracts/native/ibc-client/src/commands.rs +++ b/contracts/native/ibc-client/src/commands.rs @@ -220,7 +220,6 @@ mod test { use super::*; use crate::contract; - use abstract_os::ibc_client::state::*; use abstract_os::ibc_client::*; use abstract_testing::{TEST_ADMIN, TEST_ANS_HOST, TEST_VERSION_CONTROL}; use cosmwasm_std::testing::{mock_dependencies, mock_env, mock_info}; diff --git a/contracts/native/ibc-client/src/ibc.rs b/contracts/native/ibc-client/src/ibc.rs index 6efee3392..cfa8f20fe 100644 --- a/contracts/native/ibc-client/src/ibc.rs +++ b/contracts/native/ibc-client/src/ibc.rs @@ -312,7 +312,6 @@ mod tests { use crate::contract::{execute, instantiate, query, IbcClientResult}; use abstract_sdk::os::ibc_client::{ExecuteMsg, InstantiateMsg, QueryMsg}; - use abstract_sdk::os::abstract_ica::{APP_ORDER, BAD_APP_ORDER, IBC_APP_VERSION}; use abstract_testing::{TEST_ADMIN, TEST_ANS_HOST, TEST_VERSION_CONTROL}; use cosmwasm_std::testing::{ @@ -320,9 +319,7 @@ mod tests { mock_ibc_channel_open_try, mock_ibc_packet_ack, mock_info, MockApi, MockQuerier, MockStorage, }; - use cosmwasm_std::{ - CosmosMsg, Deps, IbcAcknowledgement, OwnedDeps, QueryResponse, - }; + use cosmwasm_std::{CosmosMsg, Deps, IbcAcknowledgement, OwnedDeps, QueryResponse}; type IbcClientTestResult = Result<(), IbcClientError>; diff --git a/contracts/native/module-factory/src/commands.rs b/contracts/native/module-factory/src/commands.rs index 464fa142a..e389c1cc7 100644 --- a/contracts/native/module-factory/src/commands.rs +++ b/contracts/native/module-factory/src/commands.rs @@ -292,9 +292,7 @@ mod test { code_id: expected_code_id, funds: vec![], admin: None, - label: format!( - "Module: {expected_module_info}, Height {some_block_height}" - ), + label: format!("Module: {expected_module_info}, Height {some_block_height}"), msg: expected_module_init_msg, }; diff --git a/contracts/native/os-factory/src/commands.rs b/contracts/native/os-factory/src/commands.rs index a1fc8d8da..50e46a82f 100644 --- a/contracts/native/os-factory/src/commands.rs +++ b/contracts/native/os-factory/src/commands.rs @@ -3,7 +3,7 @@ use crate::state::*; use crate::{error::OsFactoryError, response::MsgInstantiateContractResponse}; use abstract_macros::abstract_response; use abstract_os::objects::module::Module; -use abstract_os::version_control::{ModulesResponse}; +use abstract_os::version_control::ModulesResponse; use abstract_os::{app, OS_FACTORY}; use abstract_sdk::helpers::cosmwasm_std::wasm_smart_query; use abstract_sdk::os::version_control::{ExecuteMsg as VCExecuteMsg, QueryMsg as VCQuery}; diff --git a/packages/abstract-api/src/endpoints/execute.rs b/packages/abstract-api/src/endpoints/execute.rs index eb8b6b4b7..f746b120c 100644 --- a/packages/abstract-api/src/endpoints/execute.rs +++ b/packages/abstract-api/src/endpoints/execute.rs @@ -179,16 +179,14 @@ impl< #[cfg(test)] mod tests { use super::*; - use abstract_os::{ - api::{BaseInstantiateMsg, InstantiateMsg}, - }; + use abstract_os::api::{BaseInstantiateMsg, InstantiateMsg}; use abstract_sdk::base::InstantiateEndpoint; use abstract_testing::*; use cosmwasm_std::{ testing::{mock_dependencies, mock_env, mock_info}, Addr, Empty, StdError, }; - + use speculoos::prelude::*; use thiserror::Error; diff --git a/packages/abstract-app/src/endpoints.rs b/packages/abstract-app/src/endpoints.rs index 586a580ba..c4f2c4725 100644 --- a/packages/abstract-app/src/endpoints.rs +++ b/packages/abstract-app/src/endpoints.rs @@ -72,9 +72,9 @@ macro_rules! export_endpoints { #[cfg(test)] mod test { - + use cosmwasm_std::testing::{mock_dependencies, mock_env, mock_info}; - use cosmwasm_std::{SubMsgResult}; + use cosmwasm_std::SubMsgResult; use abstract_sdk::base::{ ExecuteEndpoint, InstantiateEndpoint, MigrateEndpoint, QueryEndpoint, ReplyEndpoint, diff --git a/packages/abstract-app/src/endpoints/execute.rs b/packages/abstract-app/src/endpoints/execute.rs index ecec3f0d6..700ce20ed 100644 --- a/packages/abstract-app/src/endpoints/execute.rs +++ b/packages/abstract-app/src/endpoints/execute.rs @@ -99,7 +99,7 @@ impl< mod test { use super::*; use crate::test_common::*; - use abstract_testing::{TEST_ADMIN, TEST_MANAGER}; + use abstract_testing::TEST_MANAGER; use cosmwasm_std::Addr; use cw_controllers::AdminError; diff --git a/packages/abstract-app/src/endpoints/instantiate.rs b/packages/abstract-app/src/endpoints/instantiate.rs index bdd19ff97..1747a7b4c 100644 --- a/packages/abstract-app/src/endpoints/instantiate.rs +++ b/packages/abstract-app/src/endpoints/instantiate.rs @@ -81,12 +81,8 @@ impl< mod test { use super::*; use crate::test_common::*; - - use abstract_testing::{ - TEST_ANS_HOST, TEST_MODULE_FACTORY, - }; - - + + use abstract_testing::{TEST_ANS_HOST, TEST_MODULE_FACTORY}; #[test] fn test_instantiate() { diff --git a/packages/abstract-app/src/endpoints/query.rs b/packages/abstract-app/src/endpoints/query.rs index f296c7342..74726fef8 100644 --- a/packages/abstract-app/src/endpoints/query.rs +++ b/packages/abstract-app/src/endpoints/query.rs @@ -81,7 +81,7 @@ mod test { #[test] fn without_handler() { - let mut deps = mock_init(); + let deps = mock_init(); let msg = AppQueryMsg::App(MockQueryMsg); let res = query_helper(deps.as_ref(), msg); @@ -92,7 +92,7 @@ mod test { } fn mock_query_handler( - deps: Deps, + _deps: Deps, _env: Env, _contract: &MockAppContract, msg: MockQueryMsg, @@ -103,7 +103,7 @@ mod test { #[test] fn with_handler() { - let mut deps = mock_init(); + let deps = mock_init(); let msg = AppQueryMsg::App(MockQueryMsg); let with_mocked_query = MOCK_APP.with_query(mock_query_handler); @@ -121,7 +121,7 @@ mod test { #[test] fn config() -> AppTestResult { - let mut deps = mock_init(); + let deps = mock_init(); let config_query = QueryMsg::Base(BaseQueryMsg::Config {}); let res = query_helper(deps.as_ref(), config_query)?; @@ -137,7 +137,7 @@ mod test { #[test] fn admin() -> AppTestResult { - let mut deps = mock_init(); + let deps = mock_init(); let admin_query = QueryMsg::Base(BaseQueryMsg::Admin {}); let res = query_helper(deps.as_ref(), admin_query)?; diff --git a/packages/abstract-app/src/features.rs b/packages/abstract-app/src/features.rs index faf898adb..42d9c47dd 100644 --- a/packages/abstract-app/src/features.rs +++ b/packages/abstract-app/src/features.rs @@ -76,7 +76,7 @@ impl< #[cfg(test)] mod test { use super::*; - use abstract_testing::{TEST_ANS_HOST, TEST_MODULE_FACTORY, TEST_MODULE_ID, TEST_PROXY}; + use abstract_testing::{TEST_ANS_HOST, TEST_MODULE_ID, TEST_PROXY}; use crate::test_common::*; diff --git a/packages/abstract-app/src/lib.rs b/packages/abstract-app/src/lib.rs index 9459b2c1b..14ab76d4a 100644 --- a/packages/abstract-app/src/lib.rs +++ b/packages/abstract-app/src/lib.rs @@ -52,7 +52,7 @@ mod test_common { use abstract_os::version_control::Core; use abstract_sdk::base::InstantiateEndpoint; use abstract_testing::{ - MockDeps, MockQuerierBuilder, TEST_ADMIN, TEST_ANS_HOST, TEST_MANAGER, TEST_MODULE_FACTORY, + MockDeps, MockQuerierBuilder, TEST_ANS_HOST, TEST_MANAGER, TEST_MODULE_FACTORY, TEST_MODULE_ID, TEST_PROXY, TEST_VERSION, }; use thiserror::Error; diff --git a/packages/abstract-os/src/modules/apis/dex.rs b/packages/abstract-os/src/modules/apis/dex.rs index 5122c0f07..9e3ab85dc 100644 --- a/packages/abstract-os/src/modules/apis/dex.rs +++ b/packages/abstract-os/src/modules/apis/dex.rs @@ -31,9 +31,9 @@ impl api::ApiExecuteMsg for DexExecuteMsg {} impl api::ApiQueryMsg for DexQueryMsg {} #[cosmwasm_schema::cw_serde] -// Struct messages not yet supported by BOOT pub struct DexInstantiateMsg { pub swap_fee: Decimal, + pub recipient_os: u32, } /// Dex Execute msg @@ -114,4 +114,6 @@ pub struct SimulateSwapResponse { pub spread_amount: Uint128, /// Commission charged for the swap pub commission: (AssetEntry, Uint128), + /// API fee charged for the swap (paid in offer asset) + pub api_fee: Uint128, } diff --git a/packages/abstract-os/src/objects/proxy_asset.rs b/packages/abstract-os/src/objects/proxy_asset.rs index ddf9ee917..a1a6bee98 100644 --- a/packages/abstract-os/src/objects/proxy_asset.rs +++ b/packages/abstract-os/src/objects/proxy_asset.rs @@ -335,9 +335,7 @@ pub fn other_asset_name<'a>(asset: &'a str, composite: &'a str) -> StdResult<&'a .split('_') .find(|component| *component != asset) .ok_or_else(|| { - StdError::generic_err(format!( - "composite {composite} is not structured correctly" - )) + StdError::generic_err(format!("composite {composite} is not structured correctly")) }) } From 4b24d8acbf1365bb7f9fff74b6d0e020b20175e4 Mon Sep 17 00:00:00 2001 From: cyberhoward Date: Wed, 1 Feb 2023 18:07:51 +0100 Subject: [PATCH 5/9] clippy --- contracts/modules/apis/dex/src/commands.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/modules/apis/dex/src/commands.rs b/contracts/modules/apis/dex/src/commands.rs index 2306b80a4..7b7e7f596 100644 --- a/contracts/modules/apis/dex/src/commands.rs +++ b/contracts/modules/apis/dex/src/commands.rs @@ -142,7 +142,7 @@ pub trait LocalDex: AbstractNameService + Execution { belief_price, max_spread, )?; - swap_msgs.push(fee_msg.clone()); + swap_msgs.push(fee_msg); Ok(swap_msgs) } From c7b59ff8cab19a7d60b5613c6c9fac4a5a4e92c8 Mon Sep 17 00:00:00 2001 From: cyberhoward Date: Wed, 1 Feb 2023 18:48:49 +0100 Subject: [PATCH 6/9] fix tests --- contracts/modules/apis/dex/src/contract.rs | 9 ++-- .../modules/apis/dex/src/handlers/execute.rs | 54 ++++++++++++++----- packages/abstract-os/src/modules/apis/dex.rs | 22 +++++++- packages/abstract-os/src/objects/fee.rs | 25 +++++++++ packages/abstract-sdk/src/apis/dex.rs | 12 ++--- 5 files changed, 94 insertions(+), 28 deletions(-) diff --git a/contracts/modules/apis/dex/src/contract.rs b/contracts/modules/apis/dex/src/contract.rs index 2259439c3..563facb32 100644 --- a/contracts/modules/apis/dex/src/contract.rs +++ b/contracts/modules/apis/dex/src/contract.rs @@ -1,15 +1,12 @@ use crate::{error::DexError, handlers}; use abstract_api::ApiContract; -use abstract_os::dex::DexInstantiateMsg; -use abstract_sdk::os::{ - dex::{DexExecuteMsg, DexQueryMsg}, - EXCHANGE, -}; +use abstract_os::dex::{DexApiExecuteMsg, DexInstantiateMsg, DexQueryMsg}; +use abstract_sdk::os::EXCHANGE; use cosmwasm_std::Response; const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); -pub type DexApi = ApiContract; +pub type DexApi = ApiContract; pub type DexResult = Result; pub const DEX_API: DexApi = DexApi::new(EXCHANGE, CONTRACT_VERSION, None) diff --git a/contracts/modules/apis/dex/src/handlers/execute.rs b/contracts/modules/apis/dex/src/handlers/execute.rs index ff653b17c..47d7838c0 100644 --- a/contracts/modules/apis/dex/src/handlers/execute.rs +++ b/contracts/modules/apis/dex/src/handlers/execute.rs @@ -1,12 +1,14 @@ use crate::contract::{DexApi, DexResult}; use crate::exchanges::exchange_resolver; use crate::LocalDex; -use abstract_os::dex::{DexAction, DexExecuteMsg, DexName, IBC_DEX_ID}; +use abstract_os::dex::state::SWAP_FEE; +use abstract_os::dex::{DexAction, DexApiExecuteMsg, DexExecuteMsg, DexName, IBC_DEX_ID}; use abstract_os::ibc_client::CallbackInfo; use abstract_os::objects::ans_host::AnsHost; use abstract_os::objects::AnsAsset; + use abstract_sdk::base::features::AbstractNameService; -use abstract_sdk::{IbcInterface, Resolve}; +use abstract_sdk::{IbcInterface, Resolve, Verification}; use cosmwasm_std::{ to_binary, Coin, Deps, DepsMut, Env, MessageInfo, Response, StdError, StdResult, }; @@ -18,19 +20,43 @@ pub fn execute_handler( env: Env, info: MessageInfo, api: DexApi, - msg: DexExecuteMsg, + msg: DexApiExecuteMsg, ) -> DexResult { - let DexExecuteMsg { - dex: dex_name, - action, - } = msg; - let exchange = exchange_resolver::identify_exchange(&dex_name)?; - // if exchange is on an app-chain, execute the action on the app-chain - if exchange.over_ibc() { - handle_ibc_api_request(&deps, info, &api, dex_name, &action) - } else { - // the action can be executed on the local chain - handle_local_api_request(deps, env, info, api, action, dex_name) + match msg { + DexApiExecuteMsg::Action(msg) => { + let DexExecuteMsg { + dex: dex_name, + action, + } = msg; + let exchange = exchange_resolver::identify_exchange(&dex_name)?; + // if exchange is on an app-chain, execute the action on the app-chain + if exchange.over_ibc() { + handle_ibc_api_request(&deps, info, &api, dex_name, &action) + } else { + // the action can be executed on the local chain + handle_local_api_request(deps, env, info, api, action, dex_name) + } + } + DexApiExecuteMsg::UpdateFee { + swap_fee, + recipient_os_id, + } => { + // only previous OS can change the owner + api.os_register(deps.as_ref()).assert_proxy(&info.sender)?; + if let Some(swap_fee) = swap_fee { + let mut fee = SWAP_FEE.load(deps.storage)?; + fee.set_share(swap_fee)?; + SWAP_FEE.save(deps.storage, &fee)?; + } + + if let Some(os_id) = recipient_os_id { + let mut fee = SWAP_FEE.load(deps.storage)?; + let recipient = api.os_register(deps.as_ref()).proxy_address(os_id)?; + fee.set_recipient(deps.api, recipient)?; + SWAP_FEE.save(deps.storage, &fee)?; + } + Ok(Response::default()) + } } } diff --git a/packages/abstract-os/src/modules/apis/dex.rs b/packages/abstract-os/src/modules/apis/dex.rs index 9e3ab85dc..c8ae516a4 100644 --- a/packages/abstract-os/src/modules/apis/dex.rs +++ b/packages/abstract-os/src/modules/apis/dex.rs @@ -24,10 +24,11 @@ pub mod state { pub const IBC_DEX_ID: u32 = 11335; -pub type ExecuteMsg = api::ExecuteMsg; +pub type ExecuteMsg = api::ExecuteMsg; pub type QueryMsg = api::QueryMsg; +pub type InstantiateMsg = api::InstantiateMsg; -impl api::ApiExecuteMsg for DexExecuteMsg {} +impl api::ApiExecuteMsg for DexApiExecuteMsg {} impl api::ApiQueryMsg for DexQueryMsg {} #[cosmwasm_schema::cw_serde] @@ -36,6 +37,23 @@ pub struct DexInstantiateMsg { pub recipient_os: u32, } +/// Dex Execute msg +#[cosmwasm_schema::cw_serde] +// Struct messages not yet supported by BOOT +pub enum DexApiExecuteMsg { + Action(DexExecuteMsg), + UpdateFee { + swap_fee: Option, + recipient_os_id: Option, + }, +} + +impl From for DexApiExecuteMsg { + fn from(action: DexExecuteMsg) -> Self { + DexApiExecuteMsg::Action(action) + } +} + /// Dex Execute msg #[cosmwasm_schema::cw_serde] // Struct messages not yet supported by BOOT diff --git a/packages/abstract-os/src/objects/fee.rs b/packages/abstract-os/src/objects/fee.rs index af2633ca3..ce1f55a2c 100644 --- a/packages/abstract-os/src/objects/fee.rs +++ b/packages/abstract-os/src/objects/fee.rs @@ -15,6 +15,10 @@ impl UsageFee { let fee = Fee::new(share)?; Ok(UsageFee { fee, recipient }) } + pub fn set_share(&mut self, share: Decimal) -> StdResult<()> { + self.fee = Fee::new(share)?; + Ok(()) + } pub fn share(&self) -> Decimal { self.fee.share() } @@ -24,6 +28,10 @@ impl UsageFee { pub fn recipient(&self) -> Addr { self.recipient.clone() } + pub fn set_recipient(&mut self, api: &dyn Api, recipient: impl Into) -> StdResult<()> { + self.recipient = api.addr_validate(&recipient.into())?; + Ok(()) + } } /// A wrapper around Decimal to help handle fractional fees. @@ -143,5 +151,22 @@ mod tests { let fee = UsageFee::new(&api, Decimal::percent(101u64), "recipient"); assert!(fee.is_err()); } + + #[test] + fn test_transfer_fee_set_recipient() { + let api = MockApi::default(); + let mut fee = UsageFee::new(&api, Decimal::percent(20u64), "recipient").unwrap(); + let new_recipient = "new_recipient"; + fee.set_recipient(&api, new_recipient).unwrap(); + assert_eq!(fee.recipient(), Addr::unchecked(new_recipient)); + } + #[test] + fn test_transfer_fee_set_share() { + let api = MockApi::default(); + let mut fee = UsageFee::new(&api, Decimal::percent(20u64), "recipient").unwrap(); + let new_share = Decimal::percent(10u64); + fee.set_share(new_share).unwrap(); + assert_eq!(fee.share(), new_share); + } } } diff --git a/packages/abstract-sdk/src/apis/dex.rs b/packages/abstract-sdk/src/apis/dex.rs index 1941c4bd6..e3d56effa 100644 --- a/packages/abstract-sdk/src/apis/dex.rs +++ b/packages/abstract-sdk/src/apis/dex.rs @@ -9,6 +9,7 @@ use abstract_os::dex::{ use abstract_os::objects::AssetEntry; use abstract_os::EXCHANGE; use cosmwasm_std::{CosmosMsg, Decimal, Deps, StdResult, Uint128}; +use os::dex::DexApiExecuteMsg; use os::manager::state::ModuleId; use serde::de::DeserializeOwned; @@ -57,10 +58,10 @@ impl<'a, T: DexInterface> Dex<'a, T> { modules.api_request( self.dex_module_id(), - DexExecuteMsg { + DexApiExecuteMsg::from(DexExecuteMsg { dex: self.dex_name(), action, - }, + }), ) } @@ -146,14 +147,13 @@ mod test { use super::*; use crate::apis::test_common::*; - - use os::api; use os::api::ApiRequestMsg; + use os::dex::ExecuteMsg; - fn expected_request_with_test_proxy(request: DexExecuteMsg) -> api::ExecuteMsg { + fn expected_request_with_test_proxy(request: DexExecuteMsg) -> ExecuteMsg { ApiRequestMsg { proxy_address: Some(abstract_testing::TEST_PROXY.to_string()), - request, + request: request.into(), } .into() } From d8c6804481cfbc3bac5150962ef4fc689d75bae9 Mon Sep 17 00:00:00 2001 From: cyberhoward Date: Wed, 15 Feb 2023 14:40:18 +0100 Subject: [PATCH 7/9] formatting --- packages/abstract-sdk/src/apis/dex.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/abstract-sdk/src/apis/dex.rs b/packages/abstract-sdk/src/apis/dex.rs index c9dda95fd..1cbf9e9e6 100644 --- a/packages/abstract-sdk/src/apis/dex.rs +++ b/packages/abstract-sdk/src/apis/dex.rs @@ -150,8 +150,8 @@ mod test { use super::*; use crate::apis::test_common::*; - use os::dex::ExecuteMsg; use os::api::ApiRequestMsg; + use os::dex::ExecuteMsg; fn expected_request_with_test_proxy(request: DexExecuteMsg) -> ExecuteMsg { ApiRequestMsg { From 627310a834189f3af2bd4465f22d4886ccfc783b Mon Sep 17 00:00:00 2001 From: cyberhoward Date: Wed, 15 Feb 2023 14:42:13 +0100 Subject: [PATCH 8/9] fix comment --- packages/abstract-os/src/modules/apis/dex.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/abstract-os/src/modules/apis/dex.rs b/packages/abstract-os/src/modules/apis/dex.rs index 51888ca20..a3caafaa1 100644 --- a/packages/abstract-os/src/modules/apis/dex.rs +++ b/packages/abstract-os/src/modules/apis/dex.rs @@ -38,7 +38,6 @@ pub struct DexInstantiateMsg { /// Dex Execute msg #[cosmwasm_schema::cw_serde] -// Struct messages not yet supported by BOOT pub enum DexApiExecuteMsg { Action(DexExecuteMsg), UpdateFee { @@ -55,7 +54,6 @@ impl From for DexApiExecuteMsg { /// Dex Execute msg #[cosmwasm_schema::cw_serde] -// Struct messages not yet supported by BOOT pub struct DexExecuteMsg { pub dex: DexName, pub action: DexAction, From d95b055dfa726f86eaf6adf0c27b27aa20e41168 Mon Sep 17 00:00:00 2001 From: cyberhoward Date: Wed, 15 Feb 2023 15:37:24 +0100 Subject: [PATCH 9/9] fix pool test --- packages/abstract-os/src/objects/pool/pool_id.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/abstract-os/src/objects/pool/pool_id.rs b/packages/abstract-os/src/objects/pool/pool_id.rs index 34a5dea0f..b470303f2 100644 --- a/packages/abstract-os/src/objects/pool/pool_id.rs +++ b/packages/abstract-os/src/objects/pool/pool_id.rs @@ -118,9 +118,9 @@ impl UncheckedPoolAddress { /// * For Contract addresses, assert its address is valid /// /// - /// ```rust - /// use cosmwasm_std::{Addr, Api, AbstractResult}; - /// use abstract_os::objects::pool_id::UncheckedPoolAddress; + /// ```rust,no_run + /// use cosmwasm_std::{Addr, Api}; + /// use abstract_os::{objects::pool_id::UncheckedPoolAddress, AbstractResult}; /// /// fn validate_pool_id(api: &dyn Api, pool_id_unchecked: &UncheckedPoolAddress) { /// match pool_id_unchecked.check(api) {