From 8260e3aabef6d5f20f54db0cfdac364c5ede6bb5 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Thu, 8 Feb 2024 17:31:20 +0100 Subject: [PATCH 01/10] First impl of Mock and MockBech32 --- cw-orch-daemon/src/queriers/cosmwasm.rs | 2 +- cw-orch/src/osmosis_test_tube/core.rs | 2 +- .../src/osmosis_test_tube/queriers/wasm.rs | 2 +- .../src/environment/queriers/wasm.rs | 2 +- packages/cw-orch-core/src/error.rs | 3 + packages/cw-orch-mock/src/core.rs | 387 ++++++++++++------ packages/cw-orch-mock/src/lib.rs | 3 +- packages/cw-orch-mock/src/queriers/bank.rs | 21 +- packages/cw-orch-mock/src/queriers/env.rs | 19 +- packages/cw-orch-mock/src/queriers/mod.rs | 44 +- packages/cw-orch-mock/src/queriers/node.rs | 22 +- packages/cw-orch-mock/src/queriers/wasm.rs | 223 +++++++--- packages/cw-orch-mock/tests/instantiate2.rs | 41 +- 13 files changed, 556 insertions(+), 215 deletions(-) diff --git a/cw-orch-daemon/src/queriers/cosmwasm.rs b/cw-orch-daemon/src/queriers/cosmwasm.rs index 80849fbe9..77f3bae51 100644 --- a/cw-orch-daemon/src/queriers/cosmwasm.rs +++ b/cw-orch-daemon/src/queriers/cosmwasm.rs @@ -276,7 +276,7 @@ impl WasmQuerier for CosmWasm { Ok(c) } - fn instantiate2_addr( + fn instantiate2_addr( &self, code_id: u64, creator: impl Into, diff --git a/cw-orch/src/osmosis_test_tube/core.rs b/cw-orch/src/osmosis_test_tube/core.rs index 8fb5fa320..4b8610685 100644 --- a/cw-orch/src/osmosis_test_tube/core.rs +++ b/cw-orch/src/osmosis_test_tube/core.rs @@ -284,7 +284,7 @@ impl TxHandler for OsmosisTestTube { impl BankSetter for OsmosisTestTube { type T = OsmosisTestTubeBankQuerier; - /// It's impossible to set the balance of an address directly in OsmosisTestTub + /// It's impossible to set the balance of an address directly in OsmosisTestTube /// So for this implementation, we use a weird algorithm fn set_balance( &mut self, diff --git a/cw-orch/src/osmosis_test_tube/queriers/wasm.rs b/cw-orch/src/osmosis_test_tube/queriers/wasm.rs index 731e992de..c2bf27a66 100644 --- a/cw-orch/src/osmosis_test_tube/queriers/wasm.rs +++ b/cw-orch/src/osmosis_test_tube/queriers/wasm.rs @@ -157,7 +157,7 @@ impl WasmQuerier for OsmosisTestTubeWasmQuerier { Ok(c) } - fn instantiate2_addr( + fn instantiate2_addr( &self, code_id: u64, creator: impl Into, diff --git a/packages/cw-orch-core/src/environment/queriers/wasm.rs b/packages/cw-orch-core/src/environment/queriers/wasm.rs index ac8622442..2bebba247 100644 --- a/packages/cw-orch-core/src/environment/queriers/wasm.rs +++ b/packages/cw-orch-core/src/environment/queriers/wasm.rs @@ -42,7 +42,7 @@ pub trait WasmQuerier: Querier { contract.wasm().checksum() } - fn instantiate2_addr( + fn instantiate2_addr( &self, code_id: u64, creator: impl Into, diff --git a/packages/cw-orch-core/src/error.rs b/packages/cw-orch-core/src/error.rs index b5db6b014..c1bd9c74a 100644 --- a/packages/cw-orch-core/src/error.rs +++ b/packages/cw-orch-core/src/error.rs @@ -6,6 +6,7 @@ use std::{ str::ParseBoolError, }; +use cosmwasm_std::Instantiate2AddressError; use thiserror::Error; /// cw-orchestrator error wrapper using thiserror. @@ -29,6 +30,8 @@ pub enum CwEnvError { ParseIntError(#[from] ParseIntError), #[error(transparent)] ParseBoolError(#[from] ParseBoolError), + #[error(transparent)] + Instantiate2AddressError(#[from] Instantiate2AddressError), #[error("File must be a wasm file")] NotWasm, #[error("Could not find wasm file with name {0} in artifacts:{1} dir")] diff --git a/packages/cw-orch-mock/src/core.rs b/packages/cw-orch-mock/src/core.rs index d92dd623f..d6184bd0b 100644 --- a/packages/cw-orch-mock/src/core.rs +++ b/packages/cw-orch-mock/src/core.rs @@ -2,11 +2,13 @@ use std::{cell::RefCell, fmt::Debug, rc::Rc}; use cosmwasm_std::{ testing::{MockApi, MockStorage}, - to_json_binary, Addr, Binary, Coin, CosmosMsg, Empty, Event, Uint128, WasmMsg, + to_json_binary, Addr, Api, Binary, Coin, CosmosMsg, Empty, Event, Uint128, WasmMsg, }; use cw_multi_test::{ - ibc::IbcSimpleModule, App, AppBuilder, AppResponse, BankKeeper, Contract, DistributionKeeper, - Executor, FailingModule, GovFailingModule, StakeKeeper, StargateFailing, WasmKeeper, + addons::{MockAddressGenerator, MockApiBech32}, + ibc::IbcSimpleModule, + App, AppBuilder, AppResponse, BankKeeper, Contract, DistributionKeeper, Executor, + FailingModule, GovFailingModule, StakeKeeper, StargateFailing, WasmKeeper, }; use cw_utils::NativeBalance; use serde::Serialize; @@ -14,18 +16,15 @@ use serde::Serialize; use super::state::MockState; use cw_orch_core::{ contract::interface_traits::Uploadable, - environment::TxHandler, - environment::{ - BankQuerier, BankSetter, ChainState, DefaultQueriers, IndexResponse, StateInterface, - }, + environment::{BankQuerier, BankSetter, ChainState, IndexResponse, StateInterface, TxHandler}, CwEnvError, }; use crate::queriers::bank::MockBankQuerier; -pub type MockApp = App< +pub type MockApp = App< BankKeeper, - MockApi, + A, MockStorage, FailingModule, WasmKeeper, @@ -43,7 +42,7 @@ pub type MockApp = App< /// The state is customizable by implementing the [`StateInterface`] trait on a custom struct and providing it on the custom constructor. /// /// The addresses used inside this environment are bech32 addresses. For instance, when creating a mock environment -/// let chain = Mock::new("sender"); +/// let chain = MockBase::new("sender"); /// the actual sender address can be generated using /// let sender_addr = chain.addr_make("sender") /// @@ -53,7 +52,7 @@ pub type MockApp = App< /// use cw_orch_mock::Mock; /// use cw_orch_core::environment::TxHandler; /// -/// let mock: Mock = Mock::new("sender"); +/// let mock: Mock = MockBase::new("sender"); /// /// // set a balance /// mock.set_balance("sender", vec![coin(100u128, "token")]).unwrap(); @@ -71,113 +70,268 @@ pub type MockApp = App< /// // We just use the MockState as an example here, but you can implement your own state struct. /// use cw_orch_mock::MockState as CustomState; /// -/// let mock: Mock = Mock::new_custom("sender", CustomState::new()); +/// let mock: Mock = MockBase::new_custom("sender", CustomState::new()); /// ``` -#[derive(Clone)] -pub struct Mock { +pub struct MockBase { /// Address used for the operations. pub sender: Addr, /// Inner mutable state storage for contract addresses and code-ids pub state: Rc>, /// Inner mutable cw-multi-test app backend - pub app: Rc>, + pub app: Rc>>, } -impl Mock { - /// Set the bank balance of an address. - pub fn set_balance( - &self, - address: impl Into, - amount: Vec, - ) -> Result<(), CwEnvError> { - self.app - .borrow_mut() - .init_modules(|router, _, storage| { - router - .bank - .init_balance(storage, &Addr::unchecked(address.into()), amount) - }) - .map_err(Into::into) +pub type Mock = MockBase; +pub type MockBech32 = MockBase; + +impl Clone for MockBase { + fn clone(&self) -> Self { + Self { + sender: self.sender.clone(), + state: self.state.clone(), + app: self.app.clone(), + } } +} - /// Adds the bank balance of an address. - pub fn add_balance( - &self, - address: impl Into, - amount: Vec, - ) -> Result<(), CwEnvError> { - let addr = &Addr::unchecked(address.into()); - let b = self.query_all_balances(addr.clone())?; - let new_amount = NativeBalance(b) + NativeBalance(amount); - self.app - .borrow_mut() - .init_modules(|router, _, storage| { - router - .bank - .init_balance(storage, addr, new_amount.into_vec()) - }) - .map_err(Into::into) +mod mock_api { + use super::*; + + impl MockBase { + /// Create a mock environment with the default mock state. + pub fn new(sender: impl Into) -> Self { + MockBase::::new_custom(sender, MockState::new()) + } + + pub fn new_with_chain_id(sender: impl Into, chain_id: &str) -> Self { + let chain = MockBase::::new_custom(sender, MockState::new()); + chain + .app + .borrow_mut() + .update_block(|b| b.chain_id = chain_id.to_string()); + + chain + } + } + impl MockBase { + /// Create a mock environment with a custom mock state. + /// The state is customizable by implementing the `StateInterface` trait on a custom struct and providing it on the custom constructor. + pub fn new_custom(sender: impl Into, custom_state: S) -> Self { + let state = Rc::new(RefCell::new(custom_state)); + let app = Rc::new(RefCell::new(AppBuilder::new_custom().build(|_, _, _| {}))); + + Self { + sender: Addr::unchecked(sender), + state, + app, + } + } } +} - /// Set the balance for multiple coins at once. - pub fn set_balances( - &self, - balances: &[(impl Into + Clone, &[cosmwasm_std::Coin])], - ) -> Result<(), CwEnvError> { - self.app - .borrow_mut() - .init_modules(|router, _, storage| -> Result<(), CwEnvError> { - for (addr, coins) in balances { - router.bank.init_balance( - storage, - &Addr::unchecked(addr.clone()), - coins.to_vec(), - )?; - } - Ok(()) - }) +mod bech32 { + use cw_orch_core::environment::DefaultQueriers; + + use super::*; + + impl MockBase { + /// Create a mock environment with the default mock state. + pub fn new_bech32(prefix: &'static str) -> Self { + MockBech32::new_custom_bech32(prefix, MockState::new()) + } + + pub fn new_bech32_with_chain_id(prefix: &'static str, chain_id: &str) -> Self { + let chain = MockBech32::new_custom_bech32(prefix, MockState::new()); + chain + .app + .borrow_mut() + .update_block(|b| b.chain_id = chain_id.to_string()); + + chain + } } - /// Query the (bank) balance of a native token for and address. - /// Returns the amount of the native token. - pub fn query_balance( - &self, - address: impl Into, - denom: &str, - ) -> Result { - Ok(self - .bank_querier() - .balance(address, Some(denom.to_string()))? - .first() - .map(|c| c.amount) - .unwrap_or_default()) + impl MockBase { + /// Set the bank balance of an address. + pub fn set_balance( + &self, + address: impl Into, + amount: Vec, + ) -> Result<(), CwEnvError> { + self.app + .borrow_mut() + .init_modules(|router, _, storage| { + router + .bank + .init_balance(storage, &Addr::unchecked(address.into()), amount) + }) + .map_err(Into::into) + } + + /// Adds the bank balance of an address. + pub fn add_balance( + &self, + address: impl Into, + amount: Vec, + ) -> Result<(), CwEnvError> { + let addr = &Addr::unchecked(address.into()); + let b = self.query_all_balances(addr.clone())?; + let new_amount = NativeBalance(b) + NativeBalance(amount); + self.app + .borrow_mut() + .init_modules(|router, _, storage| { + router + .bank + .init_balance(storage, addr, new_amount.into_vec()) + }) + .map_err(Into::into) + } + + /// Set the balance for multiple coins at once. + pub fn set_balances( + &self, + balances: &[(impl Into + Clone, &[cosmwasm_std::Coin])], + ) -> Result<(), CwEnvError> { + self.app + .borrow_mut() + .init_modules(|router, _, storage| -> Result<(), CwEnvError> { + for (addr, coins) in balances { + router.bank.init_balance( + storage, + &Addr::unchecked(addr.clone()), + coins.to_vec(), + )?; + } + Ok(()) + }) + } + + /// Query the (bank) balance of a native token for and address. + /// Returns the amount of the native token. + pub fn query_balance( + &self, + address: impl Into, + denom: &str, + ) -> Result { + Ok(self + .bank_querier() + .balance(address, Some(denom.to_string()))? + .first() + .map(|c| c.amount) + .unwrap_or_default()) + } + + /// Fetch all the balances of an address. + pub fn query_all_balances( + &self, + address: impl Into, + ) -> Result, CwEnvError> { + self.bank_querier().balance(address, None) + } } - /// Fetch all the balances of an address. - pub fn query_all_balances( - &self, - address: impl Into, - ) -> Result, CwEnvError> { - self.bank_querier().balance(address, None) + impl MockBase { + pub fn create_account(&self, account_name: impl Into) -> Addr { + self.app.borrow().api().addr_make(&account_name.into()) + } } -} -impl Mock { - /// Create a mock environment with the default mock state. - pub fn new(sender: impl Into) -> Self { - Mock::new_custom(sender, MockState::new()) + impl Default for MockBase { + fn default() -> Self { + MockBase::::new_custom_bech32("mock", MockState::new()) + } } - pub fn new_with_chain_id(sender: impl Into, chain_id: &str) -> Self { - let chain = Mock::new_custom(sender, MockState::new()); - chain - .app - .borrow_mut() - .update_block(|b| b.chain_id = chain_id.to_string()); + impl MockBase { + /// Create a mock environment with a custom mock state. + /// The state is customizable by implementing the `StateInterface` trait on a custom struct and providing it on the custom constructor. + pub fn new_custom_bech32(prefix: &'static str, custom_state: S) -> Self { + let state = Rc::new(RefCell::new(custom_state)); + let app = Rc::new(RefCell::new( + AppBuilder::new_custom() + .with_api(MockApiBech32::new(prefix)) + .with_wasm(WasmKeeper::default().with_address_generator(MockAddressGenerator)) + .build(|_, _, _| {}), + )); + + // We create an address internally + let sender = app.borrow().api().addr_make("sender"); + + Self { sender, state, app } + } + } - chain + impl MockBech32 { + /// Set the bank balance of an address. + pub fn set_balance( + &self, + address: &Addr, + amount: Vec, + ) -> Result<(), CwEnvError> { + self.app + .borrow_mut() + .init_modules(|router, _, storage| { + router.bank.init_balance(storage, address, amount) + }) + .map_err(Into::into) + } + + /// Adds the bank balance of an address. + pub fn add_balance( + &self, + address: &Addr, + amount: Vec, + ) -> Result<(), CwEnvError> { + let addr = &address; + let b = self.query_all_balances(addr)?; + let new_amount = NativeBalance(b) + NativeBalance(amount); + self.app + .borrow_mut() + .init_modules(|router, _, storage| { + router + .bank + .init_balance(storage, addr, new_amount.into_vec()) + }) + .map_err(Into::into) + } + + /// Set the balance for multiple coins at once. + pub fn set_balances( + &self, + balances: &[(&Addr, &[cosmwasm_std::Coin])], + ) -> Result<(), CwEnvError> { + self.app + .borrow_mut() + .init_modules(|router, _, storage| -> Result<(), CwEnvError> { + for (addr, coins) in balances { + router.bank.init_balance(storage, addr, coins.to_vec())?; + } + Ok(()) + }) + } + + /// Query the (bank) balance of a native token for and address. + /// Returns the amount of the native token. + pub fn query_balance(&self, address: &Addr, denom: &str) -> Result { + Ok(self + .bank_querier() + .balance(address, Some(denom.to_string()))? + .first() + .map(|c| c.amount) + .unwrap_or_default()) + } + + /// Fetch all the balances of an address. + pub fn query_all_balances( + &self, + address: &Addr, + ) -> Result, CwEnvError> { + self.bank_querier().balance(address, None) + } } +} +impl MockBase { pub fn with_chain_id(&mut self, chain_id: &str) { self.state.borrow_mut().set_chain_id(chain_id); self.app @@ -186,20 +340,7 @@ impl Mock { } } -impl Mock { - /// Create a mock environment with a custom mock state. - /// The state is customizable by implementing the `StateInterface` trait on a custom struct and providing it on the custom constructor. - pub fn new_custom(sender: impl Into, custom_state: S) -> Self { - let state = Rc::new(RefCell::new(custom_state)); - let app = Rc::new(RefCell::new(AppBuilder::new_custom().build(|_, _, _| {}))); - - Self { - sender: Addr::unchecked(sender), - state, - app, - } - } - +impl MockBase { /// Upload a custom contract wrapper. /// Support for this is limited. pub fn upload_custom( @@ -220,8 +361,7 @@ impl Mock { Ok(resp) } } - -impl ChainState for Mock { +impl ChainState for MockBase { type Out = Rc>; fn state(&self) -> Self::Out { @@ -230,7 +370,7 @@ impl ChainState for Mock { } // Execute on the test chain, returns test response type -impl TxHandler for Mock { +impl TxHandler for MockBase { type Response = AppResponse; type Error = CwEnvError; type ContractSource = Box>; @@ -349,7 +489,7 @@ impl TxHandler for Mock { } impl BankSetter for Mock { - type T = MockBankQuerier; + type T = MockBankQuerier; fn set_balance( &mut self, @@ -359,6 +499,17 @@ impl BankSetter for Mock { (*self).set_balance(address, amount) } } +impl BankSetter for MockBech32 { + type T = MockBankQuerier; + + fn set_balance( + &mut self, + address: impl Into, + amount: Vec, + ) -> Result<(), ::Error> { + (*self).set_balance(&Addr::unchecked(address), amount) + } +} #[cfg(test)] mod test { @@ -368,7 +519,7 @@ mod test { StdResult, Uint128, }; use cw_multi_test::ContractWrapper; - use cw_orch_core::environment::QueryHandler; + use cw_orch_core::environment::{DefaultQueriers, QueryHandler}; use serde::Serialize; use speculoos::prelude::*; @@ -411,7 +562,7 @@ mod test { fn mock() { let recipient = BALANCE_ADDR; let sender = SENDER; - let chain = Mock::new(sender); + let chain = MockBase::new(sender); let amount = 1000000u128; let denom = "uosmo"; @@ -489,7 +640,7 @@ mod test { #[test] fn custom_mock_env() { let mock_state = MockState::new(); - let chain = Mock::<_>::new_custom(SENDER, mock_state); + let chain = MockBase::<_>::new_custom(SENDER, mock_state); let recipient = BALANCE_ADDR; let amount = 1000000u128; @@ -533,7 +684,7 @@ mod test { #[test] fn add_balance() { - let chain = Mock::new(SENDER); + let chain = MockBase::new(SENDER); let recipient = BALANCE_ADDR; let amount = 1000000u128; let denom_1 = "uosmo"; @@ -557,7 +708,7 @@ mod test { let denom = "urandom"; let init_coins = coins(45, denom); let sender = "sender"; - let app = Mock::new(sender); + let app = MockBase::new(sender); app.set_balance(sender, init_coins.clone())?; let sender = app.sender.clone(); assert_eq!( diff --git a/packages/cw-orch-mock/src/lib.rs b/packages/cw-orch-mock/src/lib.rs index e1a3c9711..db21b4895 100644 --- a/packages/cw-orch-mock/src/lib.rs +++ b/packages/cw-orch-mock/src/lib.rs @@ -8,5 +8,6 @@ mod core; pub mod queriers; mod state; -pub use self::core::Mock; +pub(crate) use self::core::MockBase; +pub use self::core::{Mock, MockBech32}; pub use state::MockState; diff --git a/packages/cw-orch-mock/src/queriers/bank.rs b/packages/cw-orch-mock/src/queriers/bank.rs index 21caafd85..0cb8382d6 100644 --- a/packages/cw-orch-mock/src/queriers/bank.rs +++ b/packages/cw-orch-mock/src/queriers/bank.rs @@ -1,7 +1,6 @@ use std::{cell::RefCell, rc::Rc}; -use cosmwasm_std::{Coin, Empty}; -use cw_multi_test::BasicApp; +use cosmwasm_std::{Api, Coin}; use cw_orch_core::{ environment::{ QuerierGetter, StateInterface, {BankQuerier, Querier}, @@ -9,31 +8,31 @@ use cw_orch_core::{ CwEnvError, }; -use crate::Mock; +use crate::{core::MockApp, MockBase}; -pub struct MockBankQuerier { - app: Rc>>, +pub struct MockBankQuerier { + app: Rc>>, } -impl MockBankQuerier { - fn new(mock: &Mock) -> Self { +impl MockBankQuerier { + fn new(mock: &MockBase) -> Self { Self { app: mock.app.clone(), } } } -impl QuerierGetter for Mock { - fn querier(&self) -> MockBankQuerier { +impl QuerierGetter> for MockBase { + fn querier(&self) -> MockBankQuerier { MockBankQuerier::new(self) } } -impl Querier for MockBankQuerier { +impl Querier for MockBankQuerier { type Error = CwEnvError; } -impl BankQuerier for MockBankQuerier { +impl BankQuerier for MockBankQuerier { fn balance( &self, address: impl Into, diff --git a/packages/cw-orch-mock/src/queriers/env.rs b/packages/cw-orch-mock/src/queriers/env.rs index 6da6cad70..60793693c 100644 --- a/packages/cw-orch-mock/src/queriers/env.rs +++ b/packages/cw-orch-mock/src/queriers/env.rs @@ -1,10 +1,25 @@ +use cosmwasm_std::testing::MockApi; +use cw_multi_test::addons::MockApiBech32; use cw_orch_core::environment::{ EnvironmentInfo, EnvironmentQuerier, QueryHandler, StateInterface, }; -use crate::Mock; +use crate::MockBase; -impl EnvironmentQuerier for Mock { +impl EnvironmentQuerier for MockBase { + fn env_info(&self) -> EnvironmentInfo { + let block_info = self.block_info().unwrap(); + let chain_id = block_info.chain_id.clone(); + let chain_name = chain_id.rsplitn(2, '-').collect::>()[1].to_string(); + EnvironmentInfo { + chain_id, + chain_name, + deployment_id: "default".to_string(), + } + } +} + +impl EnvironmentQuerier for MockBase { fn env_info(&self) -> EnvironmentInfo { let block_info = self.block_info().unwrap(); let chain_id = block_info.chain_id.clone(); diff --git a/packages/cw-orch-mock/src/queriers/mod.rs b/packages/cw-orch-mock/src/queriers/mod.rs index 4d1497701..dd2afbae5 100644 --- a/packages/cw-orch-mock/src/queriers/mod.rs +++ b/packages/cw-orch-mock/src/queriers/mod.rs @@ -1,6 +1,7 @@ -use crate::Mock; +use crate::MockBase; -use cw_multi_test::next_block; +use cosmwasm_std::testing::MockApi; +use cw_multi_test::{addons::MockApiBech32, next_block}; use cw_orch_core::{ environment::{DefaultQueriers, QueryHandler, StateInterface}, CwEnvError, @@ -11,7 +12,31 @@ mod env; pub mod node; pub mod wasm; -impl QueryHandler for Mock { +impl QueryHandler for MockBase { + type Error = CwEnvError; + + fn wait_blocks(&self, amount: u64) -> Result<(), CwEnvError> { + self.app.borrow_mut().update_block(|b| { + b.height += amount; + b.time = b.time.plus_seconds(5 * amount); + }); + Ok(()) + } + + fn wait_seconds(&self, secs: u64) -> Result<(), CwEnvError> { + self.app.borrow_mut().update_block(|b| { + b.time = b.time.plus_seconds(secs); + b.height += secs / 5; + }); + Ok(()) + } + + fn next_block(&self) -> Result<(), CwEnvError> { + self.app.borrow_mut().update_block(next_block); + Ok(()) + } +} +impl QueryHandler for MockBase { type Error = CwEnvError; fn wait_blocks(&self, amount: u64) -> Result<(), CwEnvError> { @@ -36,8 +61,13 @@ impl QueryHandler for Mock { } } -impl DefaultQueriers for Mock { - type Bank = bank::MockBankQuerier; - type Wasm = wasm::MockWasmQuerier; - type Node = node::MockNodeQuerier; +impl DefaultQueriers for MockBase { + type Bank = bank::MockBankQuerier; + type Wasm = wasm::MockWasmQuerier; + type Node = node::MockNodeQuerier; +} +impl DefaultQueriers for MockBase { + type Bank = bank::MockBankQuerier; + type Wasm = wasm::MockWasmQuerier; + type Node = node::MockNodeQuerier; } diff --git a/packages/cw-orch-mock/src/queriers/node.rs b/packages/cw-orch-mock/src/queriers/node.rs index f4152bf7a..f8c5d8af4 100644 --- a/packages/cw-orch-mock/src/queriers/node.rs +++ b/packages/cw-orch-mock/src/queriers/node.rs @@ -1,37 +1,37 @@ use std::{cell::RefCell, rc::Rc}; -use cosmwasm_std::Empty; -use cw_multi_test::{AppResponse, BasicApp}; +use cosmwasm_std::Api; +use cw_multi_test::AppResponse; use cw_orch_core::{ environment::{NodeQuerier, Querier, QuerierGetter, StateInterface}, CwEnvError, }; -use crate::Mock; +use crate::{core::MockApp, MockBase}; -pub struct MockNodeQuerier { - app: Rc>>, +pub struct MockNodeQuerier { + app: Rc>>, } -impl MockNodeQuerier { - fn new(mock: &Mock) -> Self { +impl MockNodeQuerier { + fn new(mock: &MockBase) -> Self { Self { app: mock.app.clone(), } } } -impl Querier for MockNodeQuerier { +impl Querier for MockNodeQuerier { type Error = CwEnvError; } -impl QuerierGetter for Mock { - fn querier(&self) -> MockNodeQuerier { +impl QuerierGetter> for MockBase { + fn querier(&self) -> MockNodeQuerier { MockNodeQuerier::new(self) } } -impl NodeQuerier for MockNodeQuerier { +impl NodeQuerier for MockNodeQuerier { type Response = AppResponse; fn latest_block(&self) -> Result { diff --git a/packages/cw-orch-mock/src/queriers/wasm.rs b/packages/cw-orch-mock/src/queriers/wasm.rs index 4d42a043f..d94bfc582 100644 --- a/packages/cw-orch-mock/src/queriers/wasm.rs +++ b/packages/cw-orch-mock/src/queriers/wasm.rs @@ -1,7 +1,9 @@ use std::{cell::RefCell, rc::Rc}; -use cosmwasm_std::{to_json_binary, ContractInfoResponse, Empty, HexBinary}; -use cw_multi_test::{AddressGenerator, BasicApp}; +use cosmwasm_std::testing::MockApi; +use cosmwasm_std::{instantiate2_address, Api}; +use cosmwasm_std::{to_json_binary, ContractInfoResponse, HexBinary}; +use cw_multi_test::addons::MockApiBech32; use cw_orch_core::{ contract::interface_traits::{ContractInstance, Uploadable}, environment::{Querier, QuerierGetter, QueryHandler, StateInterface, TxHandler, WasmQuerier}, @@ -9,34 +11,111 @@ use cw_orch_core::{ }; use serde::{de::DeserializeOwned, Serialize}; -use crate::Mock; +use crate::{core::MockApp, MockBase}; -pub struct MockWasmQuerier { - app: Rc>>, +pub struct MockWasmQuerier { + app: Rc>>, } -impl MockWasmQuerier { - fn new(mock: &Mock) -> Self { +impl MockWasmQuerier { + fn new(mock: &MockBase) -> Self { Self { app: mock.app.clone(), } } } -impl Querier for MockWasmQuerier { +impl Querier for MockWasmQuerier { type Error = CwEnvError; } -impl QuerierGetter for Mock { - fn querier(&self) -> MockWasmQuerier { +impl QuerierGetter> for MockBase { + fn querier(&self) -> MockWasmQuerier { MockWasmQuerier::new(self) } } -impl WasmQuerier for MockWasmQuerier { +fn code_id_hash(querier: &MockWasmQuerier, code_id: u64) -> Result { + let code_info = querier.app.borrow().wrap().query_wasm_code_info(code_id)?; + Ok(code_info.checksum.to_hex()) +} + +fn contract_info( + querier: &MockWasmQuerier, + address: impl Into, +) -> Result { + let info = querier + .app + .borrow() + .wrap() + .query_wasm_contract_info(address)?; + Ok(info) +} + +fn local_hash>( + _querier: &MockWasmQuerier, + contract: &T, +) -> Result { + // We return the hashed contract-id. + // This will cause the logic to never re-upload a contract if it has the same contract-id. + Ok(sha256::digest(contract.id().as_bytes())) +} + +fn raw_query( + querier: &MockWasmQuerier, + address: impl Into, + query_data: Vec, +) -> Result, CwEnvError> { + Ok(querier + .app + .borrow() + .wrap() + .query(&cosmwasm_std::QueryRequest::Wasm( + cosmwasm_std::WasmQuery::Raw { + contract_addr: address.into(), + key: query_data.into(), + }, + ))?) +} + +fn smart_query( + querier: &MockWasmQuerier, + address: impl Into, + query_data: &Q, +) -> Result +where + T: DeserializeOwned, + Q: Serialize, +{ + Ok(querier + .app + .borrow() + .wrap() + .query(&cosmwasm_std::QueryRequest::Wasm( + cosmwasm_std::WasmQuery::Smart { + contract_addr: address.into(), + msg: to_json_binary(query_data)?, + }, + ))?) +} + +fn code( + querier: &MockWasmQuerier, + code_id: u64, +) -> Result { + Ok(querier + .app + .borrow() + .wrap() + .query(&cosmwasm_std::QueryRequest::Wasm( + cosmwasm_std::WasmQuery::CodeInfo { code_id }, + ))?) +} + +impl WasmQuerier for MockWasmQuerier { + /// Returns the hex-encoded checksum of the code. fn code_id_hash(&self, code_id: u64) -> Result { - let code_info = self.app.borrow().wrap().query_wasm_code_info(code_id)?; - Ok(code_info.checksum.to_hex()) + code_id_hash(self, code_id) } /// Returns the code_info structure of the provided contract @@ -44,75 +123,105 @@ impl WasmQuerier for MockWasmQuerier { &self, address: impl Into, ) -> Result { - let info = self.app.borrow().wrap().query_wasm_contract_info(address)?; - Ok(info) + contract_info(self, address) } fn local_hash>( &self, contract: &T, ) -> Result { - // We return the hashed contract-id. - // This will cause the logic to never re-upload a contract if it has the same contract-id. - Ok(sha256::digest(contract.id().as_bytes())) + local_hash(self, contract) } fn raw_query( &self, address: impl Into, query_data: Vec, - ) -> Result, Self::Error> { - Ok(self - .app - .borrow() - .wrap() - .query(&cosmwasm_std::QueryRequest::Wasm( - cosmwasm_std::WasmQuery::Raw { - contract_addr: address.into(), - key: query_data.into(), - }, - ))?) + ) -> Result, CwEnvError> { + raw_query(self, address, query_data) } - fn smart_query( - &self, - address: impl Into, - query_data: &Q, - ) -> Result + fn smart_query(&self, address: impl Into, query_data: &Q) -> Result where T: DeserializeOwned, Q: Serialize, { - Ok(self - .app - .borrow() - .wrap() - .query(&cosmwasm_std::QueryRequest::Wasm( - cosmwasm_std::WasmQuery::Smart { - contract_addr: address.into(), - msg: to_json_binary(query_data)?, - }, - ))?) + smart_query(self, address, query_data) } - fn code(&self, code_id: u64) -> Result { - Ok(self - .app - .borrow() - .wrap() - .query(&cosmwasm_std::QueryRequest::Wasm( - cosmwasm_std::WasmQuery::CodeInfo { code_id }, - ))?) + fn code(&self, code_id: u64) -> Result { + code(self, code_id) } - fn instantiate2_addr( + fn instantiate2_addr( &self, _code_id: u64, - _creator: impl Into, + creator: impl Into, salt: cosmwasm_std::Binary, - ) -> Result { - Ok(format!("contract{}", HexBinary::from(salt).to_hex())) + ) -> Result { + Ok(format!( + "contract/{}/{}", + creator.into(), + HexBinary::from(salt).to_hex() + )) } } -impl AddressGenerator for MockWasmQuerier {} +impl WasmQuerier for MockWasmQuerier { + /// Returns the hex-encoded checksum of the code. + fn code_id_hash(&self, code_id: u64) -> Result { + code_id_hash(self, code_id) + } + + /// Returns the code_info structure of the provided contract + fn contract_info( + &self, + address: impl Into, + ) -> Result { + contract_info(self, address) + } + + fn local_hash>( + &self, + contract: &T, + ) -> Result { + local_hash(self, contract) + } + + fn raw_query( + &self, + address: impl Into, + query_data: Vec, + ) -> Result, CwEnvError> { + raw_query(self, address, query_data) + } + + fn smart_query(&self, address: impl Into, query_data: &Q) -> Result + where + T: DeserializeOwned, + Q: Serialize, + { + smart_query(self, address, query_data) + } + + fn code(&self, code_id: u64) -> Result { + code(self, code_id) + } + + fn instantiate2_addr( + &self, + code_id: u64, + creator: impl Into, + salt: cosmwasm_std::Binary, + ) -> Result { + let checksum = HexBinary::from_hex(&self.code_id_hash(code_id)?)?; + let canon_creator = self.app.borrow().api().addr_canonicalize(&creator.into())?; + let canonical_addr = instantiate2_address(checksum.as_slice(), &canon_creator, &salt)?; + Ok(self + .app + .borrow() + .api() + .addr_humanize(&canonical_addr)? + .to_string()) + } +} diff --git a/packages/cw-orch-mock/tests/instantiate2.rs b/packages/cw-orch-mock/tests/instantiate2.rs index fc210bd38..b226b76f8 100644 --- a/packages/cw-orch-mock/tests/instantiate2.rs +++ b/packages/cw-orch-mock/tests/instantiate2.rs @@ -1,28 +1,61 @@ +use cosmwasm_std::instantiate2_address; +use cosmwasm_std::Api; use cosmwasm_std::Binary; -use cosmwasm_std::HexBinary; use cw_orch_core::contract::interface_traits::ContractInstance; use cw_orch_core::contract::interface_traits::CwOrchInstantiate; use cw_orch_core::contract::interface_traits::CwOrchUpload; -use cw_orch_mock::Mock; +use cw_orch_core::environment::DefaultQueriers; +use cw_orch_core::environment::TxHandler; +use cw_orch_core::environment::WasmQuerier; +use cw_orch_mock::MockBech32; use mock_contract::InstantiateMsg; use mock_contract::MockContract; #[test] fn instantiate2() -> anyhow::Result<()> { - let app = Mock::new("sender"); + let app = MockBech32::new_bech32("mock"); let salt = Binary(vec![12, 89, 156, 63]); let mock_contract = MockContract::new("mock-contract", app.clone()); mock_contract.upload()?; + let expected_address = app.wasm_querier().instantiate2_addr( + mock_contract.code_id()?, + app.sender(), + salt.clone(), + )?; + mock_contract.instantiate2(&InstantiateMsg {}, None, None, salt.clone())?; let addr = mock_contract.address()?; + assert_eq!(addr.to_string(), expected_address); + + // Finally we need to make sure that the instantiate2 function also works inside contracts + let canon_sender = app + .app + .borrow() + .api() + .addr_canonicalize(app.sender().as_str())?; + + // If there is a `Invalid input: canonical address length not correct` error, that means this env doesn't work with instantiate2 correctly assert_eq!( addr.to_string(), - format!("contract/sender/{}", HexBinary::from(salt).to_hex()) + app.app + .borrow() + .api() + .addr_humanize(&instantiate2_address( + app.app + .borrow() + .wrap() + .query_wasm_code_info(mock_contract.code_id()?)? + .checksum + .as_slice(), + &canon_sender, + &salt + )?)? + .to_string() ); Ok(()) From fa36593c23d8035a66fc489a7df6f7783bb3c494 Mon Sep 17 00:00:00 2001 From: cyberhoward Date: Fri, 9 Feb 2024 12:47:47 +0100 Subject: [PATCH 02/10] Refactor querier impl to be API generic --- packages/cw-orch-mock/src/queriers/env.rs | 18 +--- packages/cw-orch-mock/src/queriers/mod.rs | 41 ++------- packages/cw-orch-mock/src/queriers/wasm.rs | 98 ++++++++-------------- 3 files changed, 41 insertions(+), 116 deletions(-) diff --git a/packages/cw-orch-mock/src/queriers/env.rs b/packages/cw-orch-mock/src/queriers/env.rs index 60793693c..47cce5486 100644 --- a/packages/cw-orch-mock/src/queriers/env.rs +++ b/packages/cw-orch-mock/src/queriers/env.rs @@ -1,25 +1,11 @@ -use cosmwasm_std::testing::MockApi; -use cw_multi_test::addons::MockApiBech32; +use cosmwasm_std::{testing::MockApi, Api}; use cw_orch_core::environment::{ EnvironmentInfo, EnvironmentQuerier, QueryHandler, StateInterface, }; use crate::MockBase; -impl EnvironmentQuerier for MockBase { - fn env_info(&self) -> EnvironmentInfo { - let block_info = self.block_info().unwrap(); - let chain_id = block_info.chain_id.clone(); - let chain_name = chain_id.rsplitn(2, '-').collect::>()[1].to_string(); - EnvironmentInfo { - chain_id, - chain_name, - deployment_id: "default".to_string(), - } - } -} - -impl EnvironmentQuerier for MockBase { +impl EnvironmentQuerier for MockBase { fn env_info(&self) -> EnvironmentInfo { let block_info = self.block_info().unwrap(); let chain_id = block_info.chain_id.clone(); diff --git a/packages/cw-orch-mock/src/queriers/mod.rs b/packages/cw-orch-mock/src/queriers/mod.rs index dd2afbae5..d940a62cf 100644 --- a/packages/cw-orch-mock/src/queriers/mod.rs +++ b/packages/cw-orch-mock/src/queriers/mod.rs @@ -1,6 +1,6 @@ use crate::MockBase; -use cosmwasm_std::testing::MockApi; +use cosmwasm_std::{testing::MockApi, Api}; use cw_multi_test::{addons::MockApiBech32, next_block}; use cw_orch_core::{ environment::{DefaultQueriers, QueryHandler, StateInterface}, @@ -12,31 +12,7 @@ mod env; pub mod node; pub mod wasm; -impl QueryHandler for MockBase { - type Error = CwEnvError; - - fn wait_blocks(&self, amount: u64) -> Result<(), CwEnvError> { - self.app.borrow_mut().update_block(|b| { - b.height += amount; - b.time = b.time.plus_seconds(5 * amount); - }); - Ok(()) - } - - fn wait_seconds(&self, secs: u64) -> Result<(), CwEnvError> { - self.app.borrow_mut().update_block(|b| { - b.time = b.time.plus_seconds(secs); - b.height += secs / 5; - }); - Ok(()) - } - - fn next_block(&self) -> Result<(), CwEnvError> { - self.app.borrow_mut().update_block(next_block); - Ok(()) - } -} -impl QueryHandler for MockBase { +impl QueryHandler for MockBase { type Error = CwEnvError; fn wait_blocks(&self, amount: u64) -> Result<(), CwEnvError> { @@ -61,13 +37,8 @@ impl QueryHandler for MockBase { } } -impl DefaultQueriers for MockBase { - type Bank = bank::MockBankQuerier; - type Wasm = wasm::MockWasmQuerier; - type Node = node::MockNodeQuerier; -} -impl DefaultQueriers for MockBase { - type Bank = bank::MockBankQuerier; - type Wasm = wasm::MockWasmQuerier; - type Node = node::MockNodeQuerier; +impl DefaultQueriers for MockBase { + type Bank = bank::MockBankQuerier; + type Wasm = wasm::MockWasmQuerier; + type Node = node::MockNodeQuerier; } diff --git a/packages/cw-orch-mock/src/queriers/wasm.rs b/packages/cw-orch-mock/src/queriers/wasm.rs index d94bfc582..d9fa0146c 100644 --- a/packages/cw-orch-mock/src/queriers/wasm.rs +++ b/packages/cw-orch-mock/src/queriers/wasm.rs @@ -112,62 +112,7 @@ fn code( ))?) } -impl WasmQuerier for MockWasmQuerier { - /// Returns the hex-encoded checksum of the code. - fn code_id_hash(&self, code_id: u64) -> Result { - code_id_hash(self, code_id) - } - - /// Returns the code_info structure of the provided contract - fn contract_info( - &self, - address: impl Into, - ) -> Result { - contract_info(self, address) - } - - fn local_hash>( - &self, - contract: &T, - ) -> Result { - local_hash(self, contract) - } - - fn raw_query( - &self, - address: impl Into, - query_data: Vec, - ) -> Result, CwEnvError> { - raw_query(self, address, query_data) - } - - fn smart_query(&self, address: impl Into, query_data: &Q) -> Result - where - T: DeserializeOwned, - Q: Serialize, - { - smart_query(self, address, query_data) - } - - fn code(&self, code_id: u64) -> Result { - code(self, code_id) - } - - fn instantiate2_addr( - &self, - _code_id: u64, - creator: impl Into, - salt: cosmwasm_std::Binary, - ) -> Result { - Ok(format!( - "contract/{}/{}", - creator.into(), - HexBinary::from(salt).to_hex() - )) - } -} - -impl WasmQuerier for MockWasmQuerier { +impl WasmQuerier for MockWasmQuerier { /// Returns the hex-encoded checksum of the code. fn code_id_hash(&self, code_id: u64) -> Result { code_id_hash(self, code_id) @@ -214,14 +159,37 @@ impl WasmQuerier for MockWasmQuerier { creator: impl Into, salt: cosmwasm_std::Binary, ) -> Result { - let checksum = HexBinary::from_hex(&self.code_id_hash(code_id)?)?; - let canon_creator = self.app.borrow().api().addr_canonicalize(&creator.into())?; - let canonical_addr = instantiate2_address(checksum.as_slice(), &canon_creator, &salt)?; - Ok(self - .app - .borrow() - .api() - .addr_humanize(&canonical_addr)? - .to_string()) + // little hack to figure out which instantiate2 generator to use. + // Without this hack the querier methods can't be implemented on a generic "MockApi" + const MOCK_ADDR: &str = "cosmos1g0pzl69nr8j7wyxxkzurj808svnrrrxtfl8qqm"; + + let mock_canonical = MockApi::default().addr_canonicalize(MOCK_ADDR)?; + let mock_canonical_bech32 = MockApiBech32::new("cosmos").addr_canonicalize(MOCK_ADDR)?; + + let self_canonical = self.app.borrow().api().addr_canonicalize(MOCK_ADDR)?; + + if self_canonical == mock_canonical { + // if regular mock + Ok(format!( + "contract/{}/{}", + creator.into(), + HexBinary::from(salt).to_hex() + )) + } else if self_canonical == mock_canonical_bech32 { + // if bech32 mock + let checksum = HexBinary::from_hex(&self.code_id_hash(code_id)?)?; + let canon_creator = self.app.borrow().api().addr_canonicalize(&creator.into())?; + let canonical_addr = instantiate2_address(checksum.as_slice(), &canon_creator, &salt)?; + Ok(self + .app + .borrow() + .api() + .addr_humanize(&canonical_addr)? + .to_string()) + } else { + Err(CwEnvError::StdErr( + "Unsupported mock API for instantiate2_addr".to_string(), + )) + } } } From b662913706060b1e8018ce86b76321ce9c697a83 Mon Sep 17 00:00:00 2001 From: cyberhoward Date: Fri, 9 Feb 2024 12:52:32 +0100 Subject: [PATCH 03/10] clippy and fmt --- packages/cw-orch-mock/src/queriers/env.rs | 2 +- packages/cw-orch-mock/src/queriers/mod.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/cw-orch-mock/src/queriers/env.rs b/packages/cw-orch-mock/src/queriers/env.rs index 47cce5486..e2c3157a3 100644 --- a/packages/cw-orch-mock/src/queriers/env.rs +++ b/packages/cw-orch-mock/src/queriers/env.rs @@ -1,4 +1,4 @@ -use cosmwasm_std::{testing::MockApi, Api}; +use cosmwasm_std::Api; use cw_orch_core::environment::{ EnvironmentInfo, EnvironmentQuerier, QueryHandler, StateInterface, }; diff --git a/packages/cw-orch-mock/src/queriers/mod.rs b/packages/cw-orch-mock/src/queriers/mod.rs index d940a62cf..37b46a2a6 100644 --- a/packages/cw-orch-mock/src/queriers/mod.rs +++ b/packages/cw-orch-mock/src/queriers/mod.rs @@ -1,7 +1,7 @@ use crate::MockBase; -use cosmwasm_std::{testing::MockApi, Api}; -use cw_multi_test::{addons::MockApiBech32, next_block}; +use cosmwasm_std::Api; +use cw_multi_test::next_block; use cw_orch_core::{ environment::{DefaultQueriers, QueryHandler, StateInterface}, CwEnvError, From 1eedaa1ad2e85b1077a2811e3725c46cb6f62ad6 Mon Sep 17 00:00:00 2001 From: cyberhoward Date: Fri, 9 Feb 2024 15:49:44 +0100 Subject: [PATCH 04/10] add bech32 mock to prelude --- cw-orch/src/prelude.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cw-orch/src/prelude.rs b/cw-orch/src/prelude.rs index fde2a0a9d..650b15e0a 100644 --- a/cw-orch/src/prelude.rs +++ b/cw-orch/src/prelude.rs @@ -31,7 +31,7 @@ pub use crate::environment::{ }; // Mock for testing -pub use crate::mock::Mock; +pub use crate::mock::{Mock, MockBech32}; // OsmosisTestTube for testing #[cfg(feature = "osmosis-test-tube")] From ba09e512104748e8126cdc4686e9eeee38f9aad0 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Mon, 12 Feb 2024 09:31:16 +0100 Subject: [PATCH 05/10] Refactored file structure slightly --- packages/cw-orch-mock/src/bech32.rs | 141 ++++++++++++++ packages/cw-orch-mock/src/core.rs | 276 +--------------------------- packages/cw-orch-mock/src/lib.rs | 2 + packages/cw-orch-mock/src/simple.rs | 137 ++++++++++++++ 4 files changed, 286 insertions(+), 270 deletions(-) create mode 100644 packages/cw-orch-mock/src/bech32.rs create mode 100644 packages/cw-orch-mock/src/simple.rs diff --git a/packages/cw-orch-mock/src/bech32.rs b/packages/cw-orch-mock/src/bech32.rs new file mode 100644 index 000000000..e60165f6e --- /dev/null +++ b/packages/cw-orch-mock/src/bech32.rs @@ -0,0 +1,141 @@ +use std::{cell::RefCell, rc::Rc}; + +use cosmwasm_std::{Addr, Coin, Uint128}; +use cw_multi_test::{ + addons::{MockAddressGenerator, MockApiBech32}, + AppBuilder, WasmKeeper, +}; +use cw_orch_core::{ + environment::{BankQuerier, BankSetter, DefaultQueriers, StateInterface, TxHandler}, + CwEnvError, +}; +use cw_utils::NativeBalance; + +use crate::{queriers::bank::MockBankQuerier, MockBase, MockBech32, MockState}; + +impl MockBase { + /// Create a mock environment with the default mock state. + pub fn new_bech32(prefix: &'static str) -> Self { + MockBech32::new_custom_bech32(prefix, MockState::new()) + } + + pub fn new_bech32_with_chain_id(prefix: &'static str, chain_id: &str) -> Self { + let chain = MockBech32::new_custom_bech32(prefix, MockState::new()); + chain + .app + .borrow_mut() + .update_block(|b| b.chain_id = chain_id.to_string()); + + chain + } +} + +impl MockBase { + pub fn create_account(&self, account_name: impl Into) -> Addr { + self.app.borrow().api().addr_make(&account_name.into()) + } +} + +impl Default for MockBase { + fn default() -> Self { + MockBase::::new_custom_bech32("mock", MockState::new()) + } +} + +impl MockBase { + /// Create a mock environment with a custom mock state. + /// The state is customizable by implementing the `StateInterface` trait on a custom struct and providing it on the custom constructor. + pub fn new_custom_bech32(prefix: &'static str, custom_state: S) -> Self { + let state = Rc::new(RefCell::new(custom_state)); + let app = Rc::new(RefCell::new( + AppBuilder::new_custom() + .with_api(MockApiBech32::new(prefix)) + .with_wasm(WasmKeeper::default().with_address_generator(MockAddressGenerator)) + .build(|_, _, _| {}), + )); + + // We create an address internally + let sender = app.borrow().api().addr_make("sender"); + + Self { sender, state, app } + } +} + +impl MockBech32 { + /// Set the bank balance of an address. + pub fn set_balance( + &self, + address: &Addr, + amount: Vec, + ) -> Result<(), CwEnvError> { + self.app + .borrow_mut() + .init_modules(|router, _, storage| router.bank.init_balance(storage, address, amount)) + .map_err(Into::into) + } + + /// Adds the bank balance of an address. + pub fn add_balance( + &self, + address: &Addr, + amount: Vec, + ) -> Result<(), CwEnvError> { + let addr = &address; + let b = self.query_all_balances(addr)?; + let new_amount = NativeBalance(b) + NativeBalance(amount); + self.app + .borrow_mut() + .init_modules(|router, _, storage| { + router + .bank + .init_balance(storage, addr, new_amount.into_vec()) + }) + .map_err(Into::into) + } + + /// Set the balance for multiple coins at once. + pub fn set_balances( + &self, + balances: &[(&Addr, &[cosmwasm_std::Coin])], + ) -> Result<(), CwEnvError> { + self.app + .borrow_mut() + .init_modules(|router, _, storage| -> Result<(), CwEnvError> { + for (addr, coins) in balances { + router.bank.init_balance(storage, addr, coins.to_vec())?; + } + Ok(()) + }) + } + + /// Query the (bank) balance of a native token for and address. + /// Returns the amount of the native token. + pub fn query_balance(&self, address: &Addr, denom: &str) -> Result { + Ok(self + .bank_querier() + .balance(address, Some(denom.to_string()))? + .first() + .map(|c| c.amount) + .unwrap_or_default()) + } + + /// Fetch all the balances of an address. + pub fn query_all_balances( + &self, + address: &Addr, + ) -> Result, CwEnvError> { + self.bank_querier().balance(address, None) + } +} + +impl BankSetter for MockBech32 { + type T = MockBankQuerier; + + fn set_balance( + &mut self, + address: impl Into, + amount: Vec, + ) -> Result<(), ::Error> { + (*self).set_balance(&Addr::unchecked(address), amount) + } +} diff --git a/packages/cw-orch-mock/src/core.rs b/packages/cw-orch-mock/src/core.rs index d6184bd0b..c82adf294 100644 --- a/packages/cw-orch-mock/src/core.rs +++ b/packages/cw-orch-mock/src/core.rs @@ -2,26 +2,22 @@ use std::{cell::RefCell, fmt::Debug, rc::Rc}; use cosmwasm_std::{ testing::{MockApi, MockStorage}, - to_json_binary, Addr, Api, Binary, Coin, CosmosMsg, Empty, Event, Uint128, WasmMsg, + to_json_binary, Addr, Api, Binary, CosmosMsg, Empty, Event, WasmMsg, }; use cw_multi_test::{ - addons::{MockAddressGenerator, MockApiBech32}, - ibc::IbcSimpleModule, - App, AppBuilder, AppResponse, BankKeeper, Contract, DistributionKeeper, Executor, - FailingModule, GovFailingModule, StakeKeeper, StargateFailing, WasmKeeper, + addons::MockApiBech32, ibc::IbcSimpleModule, App, AppResponse, BankKeeper, Contract, + DistributionKeeper, Executor, FailingModule, GovFailingModule, StakeKeeper, StargateFailing, + WasmKeeper, }; -use cw_utils::NativeBalance; use serde::Serialize; use super::state::MockState; use cw_orch_core::{ contract::interface_traits::Uploadable, - environment::{BankQuerier, BankSetter, ChainState, IndexResponse, StateInterface, TxHandler}, + environment::{ChainState, IndexResponse, StateInterface, TxHandler}, CwEnvError, }; -use crate::queriers::bank::MockBankQuerier; - pub type MockApp = App< BankKeeper, A, @@ -94,243 +90,6 @@ impl Clone for MockBase { } } -mod mock_api { - use super::*; - - impl MockBase { - /// Create a mock environment with the default mock state. - pub fn new(sender: impl Into) -> Self { - MockBase::::new_custom(sender, MockState::new()) - } - - pub fn new_with_chain_id(sender: impl Into, chain_id: &str) -> Self { - let chain = MockBase::::new_custom(sender, MockState::new()); - chain - .app - .borrow_mut() - .update_block(|b| b.chain_id = chain_id.to_string()); - - chain - } - } - impl MockBase { - /// Create a mock environment with a custom mock state. - /// The state is customizable by implementing the `StateInterface` trait on a custom struct and providing it on the custom constructor. - pub fn new_custom(sender: impl Into, custom_state: S) -> Self { - let state = Rc::new(RefCell::new(custom_state)); - let app = Rc::new(RefCell::new(AppBuilder::new_custom().build(|_, _, _| {}))); - - Self { - sender: Addr::unchecked(sender), - state, - app, - } - } - } -} - -mod bech32 { - use cw_orch_core::environment::DefaultQueriers; - - use super::*; - - impl MockBase { - /// Create a mock environment with the default mock state. - pub fn new_bech32(prefix: &'static str) -> Self { - MockBech32::new_custom_bech32(prefix, MockState::new()) - } - - pub fn new_bech32_with_chain_id(prefix: &'static str, chain_id: &str) -> Self { - let chain = MockBech32::new_custom_bech32(prefix, MockState::new()); - chain - .app - .borrow_mut() - .update_block(|b| b.chain_id = chain_id.to_string()); - - chain - } - } - - impl MockBase { - /// Set the bank balance of an address. - pub fn set_balance( - &self, - address: impl Into, - amount: Vec, - ) -> Result<(), CwEnvError> { - self.app - .borrow_mut() - .init_modules(|router, _, storage| { - router - .bank - .init_balance(storage, &Addr::unchecked(address.into()), amount) - }) - .map_err(Into::into) - } - - /// Adds the bank balance of an address. - pub fn add_balance( - &self, - address: impl Into, - amount: Vec, - ) -> Result<(), CwEnvError> { - let addr = &Addr::unchecked(address.into()); - let b = self.query_all_balances(addr.clone())?; - let new_amount = NativeBalance(b) + NativeBalance(amount); - self.app - .borrow_mut() - .init_modules(|router, _, storage| { - router - .bank - .init_balance(storage, addr, new_amount.into_vec()) - }) - .map_err(Into::into) - } - - /// Set the balance for multiple coins at once. - pub fn set_balances( - &self, - balances: &[(impl Into + Clone, &[cosmwasm_std::Coin])], - ) -> Result<(), CwEnvError> { - self.app - .borrow_mut() - .init_modules(|router, _, storage| -> Result<(), CwEnvError> { - for (addr, coins) in balances { - router.bank.init_balance( - storage, - &Addr::unchecked(addr.clone()), - coins.to_vec(), - )?; - } - Ok(()) - }) - } - - /// Query the (bank) balance of a native token for and address. - /// Returns the amount of the native token. - pub fn query_balance( - &self, - address: impl Into, - denom: &str, - ) -> Result { - Ok(self - .bank_querier() - .balance(address, Some(denom.to_string()))? - .first() - .map(|c| c.amount) - .unwrap_or_default()) - } - - /// Fetch all the balances of an address. - pub fn query_all_balances( - &self, - address: impl Into, - ) -> Result, CwEnvError> { - self.bank_querier().balance(address, None) - } - } - - impl MockBase { - pub fn create_account(&self, account_name: impl Into) -> Addr { - self.app.borrow().api().addr_make(&account_name.into()) - } - } - - impl Default for MockBase { - fn default() -> Self { - MockBase::::new_custom_bech32("mock", MockState::new()) - } - } - - impl MockBase { - /// Create a mock environment with a custom mock state. - /// The state is customizable by implementing the `StateInterface` trait on a custom struct and providing it on the custom constructor. - pub fn new_custom_bech32(prefix: &'static str, custom_state: S) -> Self { - let state = Rc::new(RefCell::new(custom_state)); - let app = Rc::new(RefCell::new( - AppBuilder::new_custom() - .with_api(MockApiBech32::new(prefix)) - .with_wasm(WasmKeeper::default().with_address_generator(MockAddressGenerator)) - .build(|_, _, _| {}), - )); - - // We create an address internally - let sender = app.borrow().api().addr_make("sender"); - - Self { sender, state, app } - } - } - - impl MockBech32 { - /// Set the bank balance of an address. - pub fn set_balance( - &self, - address: &Addr, - amount: Vec, - ) -> Result<(), CwEnvError> { - self.app - .borrow_mut() - .init_modules(|router, _, storage| { - router.bank.init_balance(storage, address, amount) - }) - .map_err(Into::into) - } - - /// Adds the bank balance of an address. - pub fn add_balance( - &self, - address: &Addr, - amount: Vec, - ) -> Result<(), CwEnvError> { - let addr = &address; - let b = self.query_all_balances(addr)?; - let new_amount = NativeBalance(b) + NativeBalance(amount); - self.app - .borrow_mut() - .init_modules(|router, _, storage| { - router - .bank - .init_balance(storage, addr, new_amount.into_vec()) - }) - .map_err(Into::into) - } - - /// Set the balance for multiple coins at once. - pub fn set_balances( - &self, - balances: &[(&Addr, &[cosmwasm_std::Coin])], - ) -> Result<(), CwEnvError> { - self.app - .borrow_mut() - .init_modules(|router, _, storage| -> Result<(), CwEnvError> { - for (addr, coins) in balances { - router.bank.init_balance(storage, addr, coins.to_vec())?; - } - Ok(()) - }) - } - - /// Query the (bank) balance of a native token for and address. - /// Returns the amount of the native token. - pub fn query_balance(&self, address: &Addr, denom: &str) -> Result { - Ok(self - .bank_querier() - .balance(address, Some(denom.to_string()))? - .first() - .map(|c| c.amount) - .unwrap_or_default()) - } - - /// Fetch all the balances of an address. - pub fn query_all_balances( - &self, - address: &Addr, - ) -> Result, CwEnvError> { - self.bank_querier().balance(address, None) - } - } -} - impl MockBase { pub fn with_chain_id(&mut self, chain_id: &str) { self.state.borrow_mut().set_chain_id(chain_id); @@ -488,29 +247,6 @@ impl TxHandler for MockBase { } } -impl BankSetter for Mock { - type T = MockBankQuerier; - - fn set_balance( - &mut self, - address: impl Into, - amount: Vec, - ) -> Result<(), ::Error> { - (*self).set_balance(address, amount) - } -} -impl BankSetter for MockBech32 { - type T = MockBankQuerier; - - fn set_balance( - &mut self, - address: impl Into, - amount: Vec, - ) -> Result<(), ::Error> { - (*self).set_balance(&Addr::unchecked(address), amount) - } -} - #[cfg(test)] mod test { @@ -519,7 +255,7 @@ mod test { StdResult, Uint128, }; use cw_multi_test::ContractWrapper; - use cw_orch_core::environment::{DefaultQueriers, QueryHandler}; + use cw_orch_core::environment::{BankQuerier, DefaultQueriers, QueryHandler}; use serde::Serialize; use speculoos::prelude::*; diff --git a/packages/cw-orch-mock/src/lib.rs b/packages/cw-orch-mock/src/lib.rs index db21b4895..17af99875 100644 --- a/packages/cw-orch-mock/src/lib.rs +++ b/packages/cw-orch-mock/src/lib.rs @@ -4,8 +4,10 @@ // Export our fork pub extern crate cw_multi_test; +mod bech32; mod core; pub mod queriers; +mod simple; mod state; pub(crate) use self::core::MockBase; diff --git a/packages/cw-orch-mock/src/simple.rs b/packages/cw-orch-mock/src/simple.rs new file mode 100644 index 000000000..9fde27960 --- /dev/null +++ b/packages/cw-orch-mock/src/simple.rs @@ -0,0 +1,137 @@ +use std::cell::RefCell; +use std::rc::Rc; + +use cosmwasm_std::testing::MockApi; +use cosmwasm_std::{Addr, Coin, Uint128}; +use cw_multi_test::AppBuilder; +use cw_orch_core::environment::{BankQuerier, BankSetter, TxHandler}; +use cw_orch_core::{ + environment::{DefaultQueriers, StateInterface}, + CwEnvError, +}; +use cw_utils::NativeBalance; + +use crate::queriers::bank::MockBankQuerier; +use crate::{Mock, MockState}; + +impl Mock { + /// Set the bank balance of an address. + pub fn set_balance( + &self, + address: impl Into, + amount: Vec, + ) -> Result<(), CwEnvError> { + self.app + .borrow_mut() + .init_modules(|router, _, storage| { + router + .bank + .init_balance(storage, &Addr::unchecked(address.into()), amount) + }) + .map_err(Into::into) + } + + /// Adds the bank balance of an address. + pub fn add_balance( + &self, + address: impl Into, + amount: Vec, + ) -> Result<(), CwEnvError> { + let addr = &Addr::unchecked(address.into()); + let b = self.query_all_balances(addr.clone())?; + let new_amount = NativeBalance(b) + NativeBalance(amount); + self.app + .borrow_mut() + .init_modules(|router, _, storage| { + router + .bank + .init_balance(storage, addr, new_amount.into_vec()) + }) + .map_err(Into::into) + } + + /// Set the balance for multiple coins at once. + pub fn set_balances( + &self, + balances: &[(impl Into + Clone, &[cosmwasm_std::Coin])], + ) -> Result<(), CwEnvError> { + self.app + .borrow_mut() + .init_modules(|router, _, storage| -> Result<(), CwEnvError> { + for (addr, coins) in balances { + router.bank.init_balance( + storage, + &Addr::unchecked(addr.clone()), + coins.to_vec(), + )?; + } + Ok(()) + }) + } + + /// Query the (bank) balance of a native token for and address. + /// Returns the amount of the native token. + pub fn query_balance( + &self, + address: impl Into, + denom: &str, + ) -> Result { + Ok(self + .bank_querier() + .balance(address, Some(denom.to_string()))? + .first() + .map(|c| c.amount) + .unwrap_or_default()) + } + + /// Fetch all the balances of an address. + pub fn query_all_balances( + &self, + address: impl Into, + ) -> Result, CwEnvError> { + self.bank_querier().balance(address, None) + } +} + +impl Mock { + /// Create a mock environment with the default mock state. + pub fn new(sender: impl Into) -> Self { + Mock::new_custom(sender, MockState::new()) + } + + pub fn new_with_chain_id(sender: impl Into, chain_id: &str) -> Self { + let chain = Mock::new_custom(sender, MockState::new()); + chain + .app + .borrow_mut() + .update_block(|b| b.chain_id = chain_id.to_string()); + + chain + } +} +impl Mock { + /// Create a mock environment with a custom mock state. + /// The state is customizable by implementing the `StateInterface` trait on a custom struct and providing it on the custom constructor. + pub fn new_custom(sender: impl Into, custom_state: S) -> Self { + let state = Rc::new(RefCell::new(custom_state)); + let app = Rc::new(RefCell::new(AppBuilder::new_custom().build(|_, _, _| {}))); + + Self { + sender: Addr::unchecked(sender), + state, + app, + } + } +} + +impl BankSetter for Mock { + type T = MockBankQuerier; + + fn set_balance( + &mut self, + address: impl Into, + amount: Vec, + ) -> Result<(), ::Error> { + (*self).set_balance(address, amount) + } +} From f15de10020c2f1d80daf41025b1576915cfa13bf Mon Sep 17 00:00:00 2001 From: Kayanski Date: Mon, 12 Feb 2024 09:54:56 +0100 Subject: [PATCH 06/10] Fixed tests and instantiate2 hack --- packages/cw-orch-mock/src/core.rs | 4 +- packages/cw-orch-mock/src/queriers/wasm.rs | 59 ++++++++++++++++++---- 2 files changed, 51 insertions(+), 12 deletions(-) diff --git a/packages/cw-orch-mock/src/core.rs b/packages/cw-orch-mock/src/core.rs index c82adf294..7b0b9f7e9 100644 --- a/packages/cw-orch-mock/src/core.rs +++ b/packages/cw-orch-mock/src/core.rs @@ -48,7 +48,7 @@ pub type MockApp = App< /// use cw_orch_mock::Mock; /// use cw_orch_core::environment::TxHandler; /// -/// let mock: Mock = MockBase::new("sender"); +/// let mock: Mock = Mock::new("sender"); /// /// // set a balance /// mock.set_balance("sender", vec![coin(100u128, "token")]).unwrap(); @@ -66,7 +66,7 @@ pub type MockApp = App< /// // We just use the MockState as an example here, but you can implement your own state struct. /// use cw_orch_mock::MockState as CustomState; /// -/// let mock: Mock = MockBase::new_custom("sender", CustomState::new()); +/// let mock: Mock = Mock::new_custom("sender", CustomState::new()); /// ``` pub struct MockBase { /// Address used for the operations. diff --git a/packages/cw-orch-mock/src/queriers/wasm.rs b/packages/cw-orch-mock/src/queriers/wasm.rs index d9fa0146c..8dedf77f9 100644 --- a/packages/cw-orch-mock/src/queriers/wasm.rs +++ b/packages/cw-orch-mock/src/queriers/wasm.rs @@ -3,7 +3,6 @@ use std::{cell::RefCell, rc::Rc}; use cosmwasm_std::testing::MockApi; use cosmwasm_std::{instantiate2_address, Api}; use cosmwasm_std::{to_json_binary, ContractInfoResponse, HexBinary}; -use cw_multi_test::addons::MockApiBech32; use cw_orch_core::{ contract::interface_traits::{ContractInstance, Uploadable}, environment::{Querier, QuerierGetter, QueryHandler, StateInterface, TxHandler, WasmQuerier}, @@ -164,18 +163,16 @@ impl WasmQuerier for MockWasmQuerier { const MOCK_ADDR: &str = "cosmos1g0pzl69nr8j7wyxxkzurj808svnrrrxtfl8qqm"; let mock_canonical = MockApi::default().addr_canonicalize(MOCK_ADDR)?; - let mock_canonical_bech32 = MockApiBech32::new("cosmos").addr_canonicalize(MOCK_ADDR)?; + let mock_humanized = self.app.borrow().api().addr_humanize(&mock_canonical); - let self_canonical = self.app.borrow().api().addr_canonicalize(MOCK_ADDR)?; - - if self_canonical == mock_canonical { + if mock_humanized.is_ok() && mock_humanized.unwrap() == MOCK_ADDR { // if regular mock Ok(format!( "contract/{}/{}", creator.into(), HexBinary::from(salt).to_hex() )) - } else if self_canonical == mock_canonical_bech32 { + } else { // if bech32 mock let checksum = HexBinary::from_hex(&self.code_id_hash(code_id)?)?; let canon_creator = self.app.borrow().api().addr_canonicalize(&creator.into())?; @@ -186,10 +183,52 @@ impl WasmQuerier for MockWasmQuerier { .api() .addr_humanize(&canonical_addr)? .to_string()) - } else { - Err(CwEnvError::StdErr( - "Unsupported mock API for instantiate2_addr".to_string(), - )) } } } + +#[cfg(test)] +mod tests { + use cosmwasm_std::{Binary, Empty, HexBinary, Response, StdError}; + use cw_multi_test::ContractWrapper; + use cw_orch_core::environment::{DefaultQueriers, TxHandler, WasmQuerier}; + + use crate::{Mock, MockBech32}; + + #[test] + fn bech32_instantiate2() -> anyhow::Result<()> { + let mock = MockBech32::new_bech32("mock"); + + // For this instantiate 2, we need a registered code id + mock.upload_custom( + "test-contract", + Box::new(ContractWrapper::new_with_empty( + |_, _, _, _: Empty| Ok::<_, StdError>(Response::new()), + |_, _, _, _: Empty| Ok::<_, StdError>(Response::new()), + |_, _, _: Empty| Ok::<_, StdError>(Binary(b"dummy-response".to_vec())), + )), + )?; + + mock.wasm_querier() + .instantiate2_addr(1, mock.sender(), Binary(b"salt-test".to_vec()))?; + + Ok(()) + } + #[test] + fn normal_instantiate2() -> anyhow::Result<()> { + let mock = Mock::new("sender"); + + let addr = mock.wasm_querier().instantiate2_addr( + 0, + mock.sender(), + Binary(b"salt-test".to_vec()), + )?; + + assert_eq!( + addr, + format!("contract/sender/{}", HexBinary::from(b"salt-test").to_hex()) + ); + + Ok(()) + } +} From 503048783a53ef5262418a588e9c5792b334329e Mon Sep 17 00:00:00 2001 From: Kayanski Date: Mon, 12 Feb 2024 10:05:23 +0100 Subject: [PATCH 07/10] New instead of new_bech32 --- packages/cw-orch-mock/src/bech32.rs | 12 ++++++------ packages/cw-orch-mock/src/core.rs | 10 +++++----- packages/cw-orch-mock/src/queriers/wasm.rs | 2 +- packages/cw-orch-mock/tests/instantiate2.rs | 2 +- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/packages/cw-orch-mock/src/bech32.rs b/packages/cw-orch-mock/src/bech32.rs index e60165f6e..a9761fb41 100644 --- a/packages/cw-orch-mock/src/bech32.rs +++ b/packages/cw-orch-mock/src/bech32.rs @@ -15,12 +15,12 @@ use crate::{queriers::bank::MockBankQuerier, MockBase, MockBech32, MockState}; impl MockBase { /// Create a mock environment with the default mock state. - pub fn new_bech32(prefix: &'static str) -> Self { - MockBech32::new_custom_bech32(prefix, MockState::new()) + pub fn new(prefix: &'static str) -> Self { + MockBech32::new_custom(prefix, MockState::new()) } - pub fn new_bech32_with_chain_id(prefix: &'static str, chain_id: &str) -> Self { - let chain = MockBech32::new_custom_bech32(prefix, MockState::new()); + pub fn new_with_chain_id(prefix: &'static str, chain_id: &str) -> Self { + let chain = MockBech32::new_custom(prefix, MockState::new()); chain .app .borrow_mut() @@ -38,14 +38,14 @@ impl MockBase { impl Default for MockBase { fn default() -> Self { - MockBase::::new_custom_bech32("mock", MockState::new()) + MockBase::::new_custom("mock", MockState::new()) } } impl MockBase { /// Create a mock environment with a custom mock state. /// The state is customizable by implementing the `StateInterface` trait on a custom struct and providing it on the custom constructor. - pub fn new_custom_bech32(prefix: &'static str, custom_state: S) -> Self { + pub fn new_custom(prefix: &'static str, custom_state: S) -> Self { let state = Rc::new(RefCell::new(custom_state)); let app = Rc::new(RefCell::new( AppBuilder::new_custom() diff --git a/packages/cw-orch-mock/src/core.rs b/packages/cw-orch-mock/src/core.rs index 7b0b9f7e9..4cd84eeb1 100644 --- a/packages/cw-orch-mock/src/core.rs +++ b/packages/cw-orch-mock/src/core.rs @@ -38,7 +38,7 @@ pub type MockApp = App< /// The state is customizable by implementing the [`StateInterface`] trait on a custom struct and providing it on the custom constructor. /// /// The addresses used inside this environment are bech32 addresses. For instance, when creating a mock environment -/// let chain = MockBase::new("sender"); +/// let chain = Mock::new("sender"); /// the actual sender address can be generated using /// let sender_addr = chain.addr_make("sender") /// @@ -298,7 +298,7 @@ mod test { fn mock() { let recipient = BALANCE_ADDR; let sender = SENDER; - let chain = MockBase::new(sender); + let chain = Mock::new(sender); let amount = 1000000u128; let denom = "uosmo"; @@ -376,7 +376,7 @@ mod test { #[test] fn custom_mock_env() { let mock_state = MockState::new(); - let chain = MockBase::<_>::new_custom(SENDER, mock_state); + let chain = Mock::new_custom(SENDER, mock_state); let recipient = BALANCE_ADDR; let amount = 1000000u128; @@ -420,7 +420,7 @@ mod test { #[test] fn add_balance() { - let chain = MockBase::new(SENDER); + let chain = Mock::new(SENDER); let recipient = BALANCE_ADDR; let amount = 1000000u128; let denom_1 = "uosmo"; @@ -444,7 +444,7 @@ mod test { let denom = "urandom"; let init_coins = coins(45, denom); let sender = "sender"; - let app = MockBase::new(sender); + let app = Mock::new(sender); app.set_balance(sender, init_coins.clone())?; let sender = app.sender.clone(); assert_eq!( diff --git a/packages/cw-orch-mock/src/queriers/wasm.rs b/packages/cw-orch-mock/src/queriers/wasm.rs index 8dedf77f9..f7841ed84 100644 --- a/packages/cw-orch-mock/src/queriers/wasm.rs +++ b/packages/cw-orch-mock/src/queriers/wasm.rs @@ -197,7 +197,7 @@ mod tests { #[test] fn bech32_instantiate2() -> anyhow::Result<()> { - let mock = MockBech32::new_bech32("mock"); + let mock = MockBech32::new("mock"); // For this instantiate 2, we need a registered code id mock.upload_custom( diff --git a/packages/cw-orch-mock/tests/instantiate2.rs b/packages/cw-orch-mock/tests/instantiate2.rs index b226b76f8..056b77359 100644 --- a/packages/cw-orch-mock/tests/instantiate2.rs +++ b/packages/cw-orch-mock/tests/instantiate2.rs @@ -13,7 +13,7 @@ use mock_contract::MockContract; #[test] fn instantiate2() -> anyhow::Result<()> { - let app = MockBech32::new_bech32("mock"); + let app = MockBech32::new("mock"); let salt = Binary(vec![12, 89, 156, 63]); let mock_contract = MockContract::new("mock-contract", app.clone()); From 7ad4d6fe566e5a39fce9a4c9d81e69cd21ef2d90 Mon Sep 17 00:00:00 2001 From: Kayanski Date: Mon, 12 Feb 2024 11:49:35 +0100 Subject: [PATCH 08/10] Added mock app exports --- packages/cw-orch-mock/src/lib.rs | 6 +++++ packages/cw-orch-mock/src/queriers/wasm.rs | 26 +++++++++++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/packages/cw-orch-mock/src/lib.rs b/packages/cw-orch-mock/src/lib.rs index 17af99875..c1d40761e 100644 --- a/packages/cw-orch-mock/src/lib.rs +++ b/packages/cw-orch-mock/src/lib.rs @@ -12,4 +12,10 @@ mod state; pub(crate) use self::core::MockBase; pub use self::core::{Mock, MockBech32}; + +pub type MockApp = self::core::MockApp; +pub type MockAppBech32 = self::core::MockApp; + +use cosmwasm_std::testing::MockApi; +use cw_multi_test::addons::MockApiBech32; pub use state::MockState; diff --git a/packages/cw-orch-mock/src/queriers/wasm.rs b/packages/cw-orch-mock/src/queriers/wasm.rs index f7841ed84..e0007ad86 100644 --- a/packages/cw-orch-mock/src/queriers/wasm.rs +++ b/packages/cw-orch-mock/src/queriers/wasm.rs @@ -189,7 +189,7 @@ impl WasmQuerier for MockWasmQuerier { #[cfg(test)] mod tests { - use cosmwasm_std::{Binary, Empty, HexBinary, Response, StdError}; + use cosmwasm_std::{Addr, Binary, Empty, HexBinary, Response, StdError}; use cw_multi_test::ContractWrapper; use cw_orch_core::environment::{DefaultQueriers, TxHandler, WasmQuerier}; @@ -214,6 +214,30 @@ mod tests { Ok(()) } + + #[test] + fn bech32_instantiate2_contract() -> anyhow::Result<()> { + let mut mock = MockBech32::new("mock"); + mock.set_sender(Addr::unchecked( + "mock1pgm8hyk0pvphmlvfjc8wsvk4daluz5tgrw6pu5mfpemk74uxnx9qwrtv4f", + )); + + // For this instantiate 2, we need a registered code id + mock.upload_custom( + "test-contract", + Box::new(ContractWrapper::new_with_empty( + |_, _, _, _: Empty| Ok::<_, StdError>(Response::new()), + |_, _, _, _: Empty| Ok::<_, StdError>(Response::new()), + |_, _, _: Empty| Ok::<_, StdError>(Binary(b"dummy-response".to_vec())), + )), + )?; + + mock.wasm_querier() + .instantiate2_addr(1, mock.sender(), Binary(b"salt-test".to_vec()))?; + + Ok(()) + } + #[test] fn normal_instantiate2() -> anyhow::Result<()> { let mock = Mock::new("sender"); From 65c222457ee948b8c6d0e7dfd4896ca986c04c7b Mon Sep 17 00:00:00 2001 From: Kayanski Date: Tue, 13 Feb 2024 09:08:58 +0100 Subject: [PATCH 09/10] Re-export MockBase --- packages/cw-orch-mock/src/lib.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/cw-orch-mock/src/lib.rs b/packages/cw-orch-mock/src/lib.rs index c1d40761e..e7be3830e 100644 --- a/packages/cw-orch-mock/src/lib.rs +++ b/packages/cw-orch-mock/src/lib.rs @@ -16,6 +16,10 @@ pub use self::core::{Mock, MockBech32}; pub type MockApp = self::core::MockApp; pub type MockAppBech32 = self::core::MockApp; +pub mod base { + pub use super::core::MockBase; +} + use cosmwasm_std::testing::MockApi; use cw_multi_test::addons::MockApiBech32; pub use state::MockState; From 1d8c7e2807d2a66295ebcbb5121a32298685c766 Mon Sep 17 00:00:00 2001 From: cyberhoward Date: Tue, 13 Feb 2024 09:50:09 -0800 Subject: [PATCH 10/10] remove unused `self` from `WasmQuerier::local_hash` fn --- cw-orch/src/osmosis_test_tube/core.rs | 1 - packages/cw-orch-core/src/contract/interface_traits.rs | 2 +- packages/cw-orch-core/src/environment/queriers/wasm.rs | 1 - packages/cw-orch-mock/src/queriers/wasm.rs | 6 ++---- 4 files changed, 3 insertions(+), 7 deletions(-) diff --git a/cw-orch/src/osmosis_test_tube/core.rs b/cw-orch/src/osmosis_test_tube/core.rs index 4b8610685..e539626ac 100644 --- a/cw-orch/src/osmosis_test_tube/core.rs +++ b/cw-orch/src/osmosis_test_tube/core.rs @@ -285,7 +285,6 @@ impl BankSetter for OsmosisTestTube { type T = OsmosisTestTubeBankQuerier; /// It's impossible to set the balance of an address directly in OsmosisTestTube - /// So for this implementation, we use a weird algorithm fn set_balance( &mut self, _address: impl Into, diff --git a/packages/cw-orch-core/src/contract/interface_traits.rs b/packages/cw-orch-core/src/contract/interface_traits.rs index 292604401..dabd08dca 100644 --- a/packages/cw-orch-core/src/contract/interface_traits.rs +++ b/packages/cw-orch-core/src/contract/interface_traits.rs @@ -230,7 +230,7 @@ pub trait ConditionalUpload: CwOrchUpload { .wasm_querier() .code_id_hash(latest_uploaded_code_id) .map_err(Into::into)?; - let local_hash = chain.wasm_querier().local_hash(self)?; + let local_hash = Chain::Wasm::local_hash(self)?; Ok(local_hash == on_chain_hash) } diff --git a/packages/cw-orch-core/src/environment/queriers/wasm.rs b/packages/cw-orch-core/src/environment/queriers/wasm.rs index 2bebba247..de593d23e 100644 --- a/packages/cw-orch-core/src/environment/queriers/wasm.rs +++ b/packages/cw-orch-core/src/environment/queriers/wasm.rs @@ -36,7 +36,6 @@ pub trait WasmQuerier: Querier { /// Returns the checksum of the WASM file if the env supports it. Will re-upload every time if not supported. fn local_hash>( - &self, contract: &T, ) -> Result { contract.wasm().checksum() diff --git a/packages/cw-orch-mock/src/queriers/wasm.rs b/packages/cw-orch-mock/src/queriers/wasm.rs index e0007ad86..7c105dbf0 100644 --- a/packages/cw-orch-mock/src/queriers/wasm.rs +++ b/packages/cw-orch-mock/src/queriers/wasm.rs @@ -51,8 +51,7 @@ fn contract_info( Ok(info) } -fn local_hash>( - _querier: &MockWasmQuerier, +fn local_hash>( contract: &T, ) -> Result { // We return the hashed contract-id. @@ -126,10 +125,9 @@ impl WasmQuerier for MockWasmQuerier { } fn local_hash>( - &self, contract: &T, ) -> Result { - local_hash(self, contract) + local_hash(contract) } fn raw_query(