From 0244ce03f8fa6554ae89a50c5926a6512406f668 Mon Sep 17 00:00:00 2001 From: Jakub Date: Mon, 27 Nov 2023 11:00:23 +0100 Subject: [PATCH 1/7] Multitest bindings: Create Coreum multitest App type --- packages/bindings-test/Cargo.toml | 16 +++++++++++++ packages/bindings-test/src/lib.rs | 1 + packages/bindings-test/src/multitest.rs | 32 +++++++++++++++++++++++++ 3 files changed, 49 insertions(+) create mode 100644 packages/bindings-test/Cargo.toml create mode 100644 packages/bindings-test/src/lib.rs create mode 100644 packages/bindings-test/src/multitest.rs diff --git a/packages/bindings-test/Cargo.toml b/packages/bindings-test/Cargo.toml new file mode 100644 index 0000000..a2953fc --- /dev/null +++ b/packages/bindings-test/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "bindings-test" +version.workspace = true +authors = ["Jakub "] +description = "Multitest app for Coreum-specific contracts" +edition.workspace = true +license.workspace = true +repository.workspace = true + +[dependencies] +anyhow = { workspace = true } +coreum-wasm-sdk = { workspace = true } +cosmwasm-std = { workspace = true } +cw-multi-test = { workspace = true } + + diff --git a/packages/bindings-test/src/lib.rs b/packages/bindings-test/src/lib.rs new file mode 100644 index 0000000..b2b7912 --- /dev/null +++ b/packages/bindings-test/src/lib.rs @@ -0,0 +1 @@ +mod multitest; diff --git a/packages/bindings-test/src/multitest.rs b/packages/bindings-test/src/multitest.rs new file mode 100644 index 0000000..85c292f --- /dev/null +++ b/packages/bindings-test/src/multitest.rs @@ -0,0 +1,32 @@ +use std::marker::PhantomData; + +use coreum_wasm_sdk::core::{CoreumMsg, CoreumQueries}; +use cosmwasm_std::{ + testing::{MockApi, MockQuerier, MockStorage}, + Addr, Api, Binary, BlockInfo, Coin, CustomQuery, Empty, Order, OwnedDeps, Querier, + QuerierResult, StdError, StdResult, Storage, Timestamp, +}; +use cw_multi_test::{ + App, AppResponse, BankKeeper, BankSudo, BasicAppBuilder, CosmosRouter, Executor, Module, + WasmKeeper, +}; + +pub struct CoreumModule {} + +/// How many seconds per block +/// (when we increment block.height, use this multiplier for block.time) +pub const BLOCK_TIME: u64 = 5; + +pub type CoreumDeps = OwnedDeps; + +pub fn mock_coreum_deps() -> CoreumDeps { + CoreumDeps { + storage: MockStorage::default(), + api: MockApi::default(), + querier: MockQuerier::default(), + custom_query_type: PhantomData, + } +} + +pub type CoreumAppWrapped = + App>; From 01d2a0f2a8b0ac4276d91f030164964d1ddccda0 Mon Sep 17 00:00:00 2001 From: Jakub Date: Mon, 27 Nov 2023 11:38:01 +0100 Subject: [PATCH 2/7] Multitest bindings: Implement base for coreum module --- Cargo.lock | 12 ++++ Cargo.toml | 1 + packages/bindings-test/Cargo.toml | 2 + packages/bindings-test/src/multitest.rs | 87 +++++++++++++++++++++++-- 4 files changed, 98 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0b54e9e..3b4e710 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -140,6 +140,18 @@ dependencies = [ "which", ] +[[package]] +name = "bindings-test" +version = "0.1.0" +dependencies = [ + "anyhow", + "coreum-wasm-sdk 0.1.4", + "cosmwasm-std", + "cw-multi-test", + "schemars", + "serde", +] + [[package]] name = "bip32" version = "0.5.1" diff --git a/Cargo.toml b/Cargo.toml index 7efdbd2..33ea911 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,7 @@ derivative = "2.2" dex = { path = "./packages/dex", default-features = false } itertools = "0.10" proptest = "1.0" +schemars = "0.8" serde = { version = "1", default-features = false, features = ["derive"] } thiserror = "1" test-case = "2.2.1" diff --git a/packages/bindings-test/Cargo.toml b/packages/bindings-test/Cargo.toml index a2953fc..b80f292 100644 --- a/packages/bindings-test/Cargo.toml +++ b/packages/bindings-test/Cargo.toml @@ -12,5 +12,7 @@ anyhow = { workspace = true } coreum-wasm-sdk = { workspace = true } cosmwasm-std = { workspace = true } cw-multi-test = { workspace = true } +schemars = { workspace = true } +serde = { workspace = true } diff --git a/packages/bindings-test/src/multitest.rs b/packages/bindings-test/src/multitest.rs index 85c292f..ef12ffd 100644 --- a/packages/bindings-test/src/multitest.rs +++ b/packages/bindings-test/src/multitest.rs @@ -1,4 +1,15 @@ -use std::marker::PhantomData; +use std::{ + fmt::Debug, + marker::PhantomData, + ops::{Deref, DerefMut}, +}; + +use anyhow::{bail, Result as AnyResult}; +use schemars::JsonSchema; +use serde::{ + de::DeserializeOwned, + {Deserialize, Serialize}, +}; use coreum_wasm_sdk::core::{CoreumMsg, CoreumQueries}; use cosmwasm_std::{ @@ -11,8 +22,6 @@ use cw_multi_test::{ WasmKeeper, }; -pub struct CoreumModule {} - /// How many seconds per block /// (when we increment block.height, use this multiplier for block.time) pub const BLOCK_TIME: u64 = 5; @@ -28,5 +37,75 @@ pub fn mock_coreum_deps() -> CoreumDeps { } } +pub struct CoreumModule {} + +impl Module for CoreumModule { + type ExecT = CoreumMsg; + type QueryT = CoreumQueries; + type SudoT = Empty; + + fn execute( + &self, + api: &dyn Api, + storage: &mut dyn Storage, + router: &dyn CosmosRouter, + block: &BlockInfo, + sender: Addr, + msg: CoreumMsg, + ) -> AnyResult + where + ExecC: Debug + Clone + PartialEq + JsonSchema + DeserializeOwned + 'static, + QueryC: CustomQuery + DeserializeOwned + 'static, + { + bail!("You have reached the coreum app execute module!") + } + + fn query( + &self, + _api: &dyn Api, + _storage: &dyn Storage, + _querier: &dyn Querier, + _block: &BlockInfo, + msg: CoreumQueries, + ) -> AnyResult { + bail!("You have reached the coreum app query module!") + } + + fn sudo( + &self, + _api: &dyn Api, + _storage: &mut dyn Storage, + _router: &dyn CosmosRouter, + _block: &BlockInfo, + _msg: Self::SudoT, + ) -> AnyResult + where + ExecC: Debug + Clone + PartialEq + JsonSchema + DeserializeOwned + 'static, + QueryC: CustomQuery + DeserializeOwned + 'static, + { + bail!("sudo not implemented for CoreumModule") + } +} + pub type CoreumAppWrapped = - App>; + App>; + +pub struct CoreumApp(CoreumAppWrapped); + +impl Deref for CoreumApp { + type Target = CoreumAppWrapped; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl CoreumApp { + pub fn new() -> Self { + Self( + BasicAppBuilder::::new_custom() + .with_custom(CoreumModule {}) + .build(|_router, _, _storage| ()), + ) + } +} From 2a7f6a233dcbbbf1d6c9e181bf9d250f93f11368 Mon Sep 17 00:00:00 2001 From: Jakub Date: Mon, 27 Nov 2023 12:00:56 +0100 Subject: [PATCH 3/7] Multitest bindings: Implement first message Issue for coreum ft token --- packages/bindings-test/src/multitest.rs | 43 +++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/packages/bindings-test/src/multitest.rs b/packages/bindings-test/src/multitest.rs index ef12ffd..e00a9aa 100644 --- a/packages/bindings-test/src/multitest.rs +++ b/packages/bindings-test/src/multitest.rs @@ -1,4 +1,5 @@ use std::{ + cmp::max, fmt::Debug, marker::PhantomData, ops::{Deref, DerefMut}, @@ -11,7 +12,10 @@ use serde::{ {Deserialize, Serialize}, }; -use coreum_wasm_sdk::core::{CoreumMsg, CoreumQueries}; +use coreum_wasm_sdk::{ + assetft, + core::{CoreumMsg, CoreumQueries}, +}; use cosmwasm_std::{ testing::{MockApi, MockQuerier, MockStorage}, Addr, Api, Binary, BlockInfo, Coin, CustomQuery, Empty, Order, OwnedDeps, Querier, @@ -57,7 +61,14 @@ impl Module for CoreumModule { ExecC: Debug + Clone + PartialEq + JsonSchema + DeserializeOwned + 'static, QueryC: CustomQuery + DeserializeOwned + 'static, { - bail!("You have reached the coreum app execute module!") + match msg { + CoreumMsg::AssetFT(msg) => match msg { + // Just return empty response for now, issue does nothing in mock + assetft::Msg::Issue { .. } => Ok(AppResponse::default()), + _ => bail!("Unsupported assetft message!"), + }, + _ => bail!("You have reached the coreum app execute module!"), + } } fn query( @@ -100,6 +111,12 @@ impl Deref for CoreumApp { } } +impl DerefMut for CoreumApp { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + impl CoreumApp { pub fn new() -> Self { Self( @@ -108,4 +125,26 @@ impl CoreumApp { .build(|_router, _, _storage| ()), ) } + + pub fn block_info(&self) -> BlockInfo { + self.0.block_info() + } + + /// This advances BlockInfo by given number of blocks. + /// It does not do any callbacks, but keeps the ratio of seconds/blokc + pub fn advance_blocks(&mut self, blocks: u64) { + self.update_block(|block| { + block.time = block.time.plus_seconds(BLOCK_TIME * blocks); + block.height += blocks; + }); + } + + /// This advances BlockInfo by given number of seconds. + /// It does not do any callbacks, but keeps the ratio of seconds/blokc + pub fn advance_seconds(&mut self, seconds: u64) { + self.update_block(|block| { + block.time = block.time.plus_seconds(seconds); + block.height += max(1, seconds / BLOCK_TIME); + }); + } } From b55971b3e346db758383ad52346d19ed24b33d26 Mon Sep 17 00:00:00 2001 From: Jakub Date: Mon, 27 Nov 2023 12:13:08 +0100 Subject: [PATCH 4/7] Multitest bindings: Implement mint smart token message --- packages/bindings-test/src/multitest.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packages/bindings-test/src/multitest.rs b/packages/bindings-test/src/multitest.rs index e00a9aa..d1297e0 100644 --- a/packages/bindings-test/src/multitest.rs +++ b/packages/bindings-test/src/multitest.rs @@ -65,6 +65,15 @@ impl Module for CoreumModule { CoreumMsg::AssetFT(msg) => match msg { // Just return empty response for now, issue does nothing in mock assetft::Msg::Issue { .. } => Ok(AppResponse::default()), + assetft::Msg::Mint { + coin, + } => { + let mint_msg = BankSudo::Mint { + to_address: sender.to_string(), + amount: vec![coin], + }; + router.sudo(api, storage, block, mint_msg.into()) + } _ => bail!("Unsupported assetft message!"), }, _ => bail!("You have reached the coreum app execute module!"), From aa44f268cd6b37b1e50a890bf65cf7a70973398a Mon Sep 17 00:00:00 2001 From: Jakub Date: Mon, 27 Nov 2023 19:17:39 +0100 Subject: [PATCH 5/7] Multitest bindings: Implement burn message and first queries --- packages/bindings-test/src/multitest.rs | 46 +++++++++++++++++++------ 1 file changed, 35 insertions(+), 11 deletions(-) diff --git a/packages/bindings-test/src/multitest.rs b/packages/bindings-test/src/multitest.rs index d1297e0..e80543c 100644 --- a/packages/bindings-test/src/multitest.rs +++ b/packages/bindings-test/src/multitest.rs @@ -18,8 +18,9 @@ use coreum_wasm_sdk::{ }; use cosmwasm_std::{ testing::{MockApi, MockQuerier, MockStorage}, - Addr, Api, Binary, BlockInfo, Coin, CustomQuery, Empty, Order, OwnedDeps, Querier, - QuerierResult, StdError, StdResult, Storage, Timestamp, + to_json_binary, Addr, Api, BankMsg, BankQuery, Binary, BlockInfo, Coin, CustomQuery, Empty, + Order, OwnedDeps, Querier, QuerierResult, QuerierWrapper, QueryRequest, StdError, StdResult, + Storage, Timestamp, }; use cw_multi_test::{ App, AppResponse, BankKeeper, BankSudo, BasicAppBuilder, CosmosRouter, Executor, Module, @@ -65,15 +66,18 @@ impl Module for CoreumModule { CoreumMsg::AssetFT(msg) => match msg { // Just return empty response for now, issue does nothing in mock assetft::Msg::Issue { .. } => Ok(AppResponse::default()), - assetft::Msg::Mint { - coin, - } => { + assetft::Msg::Mint { coin } => { let mint_msg = BankSudo::Mint { to_address: sender.to_string(), amount: vec![coin], }; router.sudo(api, storage, block, mint_msg.into()) } + // Also do nothing for now + assetft::Msg::Burn { coin } => { + let burn_msg = BankMsg::Burn { amount: vec![coin] }; + router.execute(api, storage, block, sender, burn_msg.into()) + } _ => bail!("Unsupported assetft message!"), }, _ => bail!("You have reached the coreum app execute module!"), @@ -82,13 +86,33 @@ impl Module for CoreumModule { fn query( &self, - _api: &dyn Api, - _storage: &dyn Storage, - _querier: &dyn Querier, - _block: &BlockInfo, - msg: CoreumQueries, + api: &dyn Api, + storage: &dyn Storage, + querier: &dyn Querier, + block: &BlockInfo, + request: CoreumQueries, ) -> AnyResult { - bail!("You have reached the coreum app query module!") + match request { + CoreumQueries::AssetFT(r) => match r { + assetft::Query::Balance { account, denom } => { + let bank_query = QueryRequest::Bank(BankQuery::Balance { + address: account, + denom, + }); + // TODO! + let res: assetft::BalanceResponse = + querier.raw_query(api, storage, querier, block, bank_query.into()); + Ok(to_json_binary(&assetft::BalanceResponse { + balance: res.amount.amount.to_string(), + whitelisted: "".to_owned(), + frozen: "".to_owned(), + locked: "".to_owned(), + })?) + } + _ => bail!("Unsupported assetft query!"), + }, + _ => bail!("Unsupported CoreumQueries query!"), + } } fn sudo( From 26838cff15746c916fb2b5209643e6b64e57760f Mon Sep 17 00:00:00 2001 From: Jakub Date: Wed, 29 Nov 2023 13:52:00 +0100 Subject: [PATCH 6/7] Multitest-bindings: Parse bank query into coreum query result --- packages/bindings-test/src/multitest.rs | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/packages/bindings-test/src/multitest.rs b/packages/bindings-test/src/multitest.rs index e80543c..b7d60cc 100644 --- a/packages/bindings-test/src/multitest.rs +++ b/packages/bindings-test/src/multitest.rs @@ -18,9 +18,9 @@ use coreum_wasm_sdk::{ }; use cosmwasm_std::{ testing::{MockApi, MockQuerier, MockStorage}, - to_json_binary, Addr, Api, BankMsg, BankQuery, Binary, BlockInfo, Coin, CustomQuery, Empty, - Order, OwnedDeps, Querier, QuerierResult, QuerierWrapper, QueryRequest, StdError, StdResult, - Storage, Timestamp, + to_json_binary, Addr, Api, BalanceResponse, BankMsg, BankQuery, Binary, BlockInfo, Coin, + CustomQuery, Empty, Order, OwnedDeps, Querier, QuerierResult, QuerierWrapper, QueryRequest, + StdError, StdResult, Storage, Timestamp, }; use cw_multi_test::{ App, AppResponse, BankKeeper, BankSudo, BasicAppBuilder, CosmosRouter, Executor, Module, @@ -95,13 +95,12 @@ impl Module for CoreumModule { match request { CoreumQueries::AssetFT(r) => match r { assetft::Query::Balance { account, denom } => { - let bank_query = QueryRequest::Bank(BankQuery::Balance { - address: account, - denom, - }); - // TODO! - let res: assetft::BalanceResponse = - querier.raw_query(api, storage, querier, block, bank_query.into()); + let bank_query: QueryRequest = + QueryRequest::Bank(BankQuery::Balance { + address: account, + denom, + }); + let res: BalanceResponse = QuerierWrapper::new(querier).query(&bank_query)?; Ok(to_json_binary(&assetft::BalanceResponse { balance: res.amount.amount.to_string(), whitelisted: "".to_owned(), From 1b4582fd2d27be2f35f1d23d8a7eb69678978525 Mon Sep 17 00:00:00 2001 From: Jakub Date: Wed, 29 Nov 2023 15:21:16 +0100 Subject: [PATCH 7/7] Multitest-bindings: Refactor code and fix clippy lints --- packages/bindings-test/src/lib.rs | 4 ++++ packages/bindings-test/src/multitest.rs | 27 +++++++++++++------------ 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/packages/bindings-test/src/lib.rs b/packages/bindings-test/src/lib.rs index b2b7912..9ea7c7b 100644 --- a/packages/bindings-test/src/lib.rs +++ b/packages/bindings-test/src/lib.rs @@ -1 +1,5 @@ mod multitest; + +pub use multitest::{ + mock_coreum_deps, CoreumApp, CoreumAppWrapped, CoreumDeps, CoreumModule, BLOCK_TIME, +}; diff --git a/packages/bindings-test/src/multitest.rs b/packages/bindings-test/src/multitest.rs index b7d60cc..9881c44 100644 --- a/packages/bindings-test/src/multitest.rs +++ b/packages/bindings-test/src/multitest.rs @@ -7,10 +7,7 @@ use std::{ use anyhow::{bail, Result as AnyResult}; use schemars::JsonSchema; -use serde::{ - de::DeserializeOwned, - {Deserialize, Serialize}, -}; +use serde::de::DeserializeOwned; use coreum_wasm_sdk::{ assetft, @@ -18,13 +15,11 @@ use coreum_wasm_sdk::{ }; use cosmwasm_std::{ testing::{MockApi, MockQuerier, MockStorage}, - to_json_binary, Addr, Api, BalanceResponse, BankMsg, BankQuery, Binary, BlockInfo, Coin, - CustomQuery, Empty, Order, OwnedDeps, Querier, QuerierResult, QuerierWrapper, QueryRequest, - StdError, StdResult, Storage, Timestamp, + to_json_binary, Addr, Api, BalanceResponse, BankMsg, BankQuery, Binary, BlockInfo, CustomQuery, + Empty, OwnedDeps, Querier, QuerierWrapper, QueryRequest, Storage, }; use cw_multi_test::{ - App, AppResponse, BankKeeper, BankSudo, BasicAppBuilder, CosmosRouter, Executor, Module, - WasmKeeper, + App, AppResponse, BankKeeper, BankSudo, BasicAppBuilder, CosmosRouter, Module, WasmKeeper, }; /// How many seconds per block @@ -80,16 +75,16 @@ impl Module for CoreumModule { } _ => bail!("Unsupported assetft message!"), }, - _ => bail!("You have reached the coreum app execute module!"), + _ => bail!("Unsupported CoreumMsg execute!"), } } fn query( &self, - api: &dyn Api, - storage: &dyn Storage, + _api: &dyn Api, + _storage: &dyn Storage, querier: &dyn Querier, - block: &BlockInfo, + _block: &BlockInfo, request: CoreumQueries, ) -> AnyResult { match request { @@ -149,6 +144,12 @@ impl DerefMut for CoreumApp { } } +impl Default for CoreumApp { + fn default() -> Self { + Self::new() + } +} + impl CoreumApp { pub fn new() -> Self { Self(