cw_multi_test/lib.rs
1//! # CosmWasm MultiTest
2//!
3//! **CosmWasm MultiTest** is designed to simulate a blockchain environment in pure Rust.
4//! This allows you to run unit tests that involve **contract 🡘 contract**,
5//! and **contract 🡘 module** interactions.
6//!
7//! **CosmWasm MultiTest** is not intended to be a full blockchain application, but to simulate
8//! the Cosmos SDK modules close enough to gain confidence in multi-contract deployments,
9//! before testing them on a live blockchain.
10//!
11//! The following sections explains some of the design for those who want to use the API,
12//! as well as those who want to take a look under the hood of **CosmWasm MultiTest**.
13//!
14//! ## Key APIs
15//!
16//! ### App
17//!
18//! The main entry point to the system is called [App], which represents a blockchain application.
19//! It maintains an idea of block height and time, which can be updated to simulate multiple
20//! blocks. You can use application's [update_block](App::update_block) method to increment
21//! the timestamp by 5 seconds and the height by 1 (simulating a new block) or you can write
22//! any other mutator of [BlockInfo](cosmwasm_std::BlockInfo) to advance more.
23//!
24//! [App] exposes an entry point [execute](App::execute) that allows to execute
25//! any [CosmosMsg](cosmwasm_std::CosmosMsg) and wraps it in an atomic transaction.
26//! That is, only if [execute](App::execute) returns a success, then the state will be committed.
27//! It returns the data and a list of [Event](cosmwasm_std::Event)s on successful execution
28//! or an `Err(String)` on error. There are some helper methods tied to the [Executor] trait
29//! that create the [CosmosMsg](cosmwasm_std::CosmosMsg) for you to provide a less verbose API.
30//! [App]'s methods like [instantiate_contract](App::instantiate_contract),
31//! [execute_contract](App::execute_contract), and [send_tokens](App::send_tokens) are exposed
32//! for your convenience in writing tests.
33//! Each method executes one [CosmosMsg](cosmwasm_std::CosmosMsg) atomically, as if it was submitted by a user.
34//! You can also use [execute_multi](App::execute_multi) if you wish to execute multiple messages together
35//! that revert the state as a whole in case of any failure.
36//!
37//! The other key entry point to [App] is the [Querier](cosmwasm_std::Querier) interface that it implements.
38//! In particular, you can use [wrap](App::wrap) to get a [QuerierWrapper](cosmwasm_std::QuerierWrapper),
39//! which provides all kinds of interesting APIs to query the blockchain, like
40//! [query_balance](cosmwasm_std::QuerierWrapper::query_balance) and
41//! [query_wasm_smart](cosmwasm_std::QuerierWrapper::query_wasm_smart).
42//! Putting this all together, you have one [Storage](cosmwasm_std::Storage) wrapped into an application,
43//! where you can execute contracts and bank, query them easily, and update the current
44//! [BlockInfo](cosmwasm_std::BlockInfo), in an API that is not very verbose or cumbersome.
45//! Under the hood it will process all messages returned from contracts, move _bank_ tokens
46//! and call into other contracts.
47//!
48//! You can easily create an [App] for use in your testcode like shown below.
49//! Having a single utility function for creating and configuring the [App] is the common
50//! pattern while testing contracts with **MultiTest**.
51//!
52//! ```
53//! use cw_multi_test::App;
54//!
55//! fn mock_app() -> App {
56//! App::default()
57//! }
58//! ```
59//!
60//! The [App] maintains the root [Storage](cosmwasm_std::Storage), and the [BlockInfo](cosmwasm_std::BlockInfo)
61//! for the current block. It also contains a [Router] (discussed below), which can process
62//! any [CosmosMsg](cosmwasm_std::CosmosMsg) variant by passing it to the proper keeper.
63//!
64//! > **Note**: [App] properly handles submessages and reply blocks.
65//!
66//! > **Note**: While the API currently supports custom messages, we don't currently have an implementation
67//! > of the default keeper, except of experimental [CachingCustomHandler](custom_handler::CachingCustomHandler).
68//!
69//! ### Contracts
70//!
71//! Before you can call contracts, you must **instantiate** them. And to instantiate them,
72//! you need a `code_id`. In `wasmd`, this `code_id` points to some stored Wasm code that is then run.
73//! In **MultiTest**, we use it to point to a `Box<dyn Contract>` that should be run.
74//! That is, you need to implement the [Contract] trait and then add the contract
75//! to the [App] via [store_code](App::store_code) function.
76//!
77//! The [Contract] trait defines the major entry points to any CosmWasm contract:
78//! [instantiate](Contract::instantiate), [execute](Contract::execute), [query](Contract::query),
79//! [sudo](Contract::sudo), [reply](Contract::reply) (for submessages) and [migrate](Contract::migrate).
80//!
81//! In order to easily implement [Contract] from some existing contract code, we use the [ContractWrapper] struct,
82//! which takes some function pointers and combines them. You can take a look at **test_helpers** module
83//! for some examples or how to do so (and useful mocks for some test cases).
84//! Here is an example of wrapping a CosmWasm contract into a [Contract] trait to be added to an [App]:
85//!
86//! ```
87//! use cosmwasm_std::Empty;
88//! use cw_multi_test::{App, Contract, ContractWrapper};
89//!
90//! // Contract definition.
91//! mod my_contract {
92//! use cosmwasm_std::{Binary, Deps, DepsMut, Empty, Env, MessageInfo, Response, StdResult};
93//!
94//! pub fn instantiate(
95//! deps: DepsMut,
96//! env: Env,
97//! info: MessageInfo,
98//! msg: Empty,
99//! ) -> StdResult<Response> {
100//! Ok(Response::default())
101//! }
102//!
103//! pub fn execute(
104//! deps: DepsMut,
105//! env: Env,
106//! info: MessageInfo,
107//! msg: Empty,
108//! ) -> StdResult<Response> {
109//! Ok(Response::default())
110//! }
111//!
112//! pub fn query(deps: Deps, env: Env, msg: Empty) -> StdResult<Binary> {
113//! Ok(Binary::default())
114//! }
115//! }
116//!
117//! // Wrapped contract.
118//! pub fn contract() -> Box<dyn Contract<Empty>> {
119//! Box::new(ContractWrapper::new(
120//! my_contract::execute,
121//! my_contract::instantiate,
122//! my_contract::query,
123//! ))
124//! }
125//!
126//! // Chain initialization.
127//! let mut app = App::default();
128//!
129//! // Storing contract code on chain.
130//! let code_id = app.store_code(contract());
131//!
132//! assert_eq!(1, code_id);
133//!
134//! // Use this `code_id` to instantiate the contract.
135//! // ...
136//! ```
137//!
138//! ### Modules
139//!
140//! There is only one root [Storage](cosmwasm_std::Storage), stored inside [App].
141//! This is wrapped into a transaction, and then passed down to other functions to work with.
142//! The code that modifies the Storage is divided into modules much like the CosmosSDK.
143//! Currently, the message processing logic is divided into one module for every [CosmosMsg](cosmwasm_std) variant:
144//! - [Bank] module handles [BankMsg](cosmwasm_std::BankMsg) and [BankQuery](cosmwasm_std::BankQuery) messages,
145//! - [Wasm] module handles [WasmMsg](cosmwasm_std::WasmMsg) and [WasmQuery](cosmwasm_std::WasmQuery), etc.
146//!
147//! ### Router
148//!
149//! The [Router] groups all modules in the system into one "macro-module" that can handle
150//! any [CosmosMsg](cosmwasm_std::CosmosMsg). While [Bank] handles [BankMsg](cosmwasm_std::BankMsg),
151//! and [Wasm] handles [WasmMsg](cosmwasm_std::WasmMsg), we need to combine them into a larger composite
152//! to let them process messages from [App]. This is the whole concept of the [Router].
153//! If you take a look at the [execute](Router::execute) method, you will see it is quite straightforward.
154//!
155//! Note that the only way one module can call or query another module is by dispatching messages via the [Router].
156//! This allows us to implement an independent [Wasm] in a way that it can process [SubMsg](cosmwasm_std::SubMsg)
157//! that call into [Bank]. You can see an example of that in `send` method of the [WasmKeeper],
158//! where it moves bank tokens from one account to another.
159
160#![deny(missing_docs)]
161#![deny(rustdoc::broken_intra_doc_links)]
162#![deny(rustdoc::missing_crate_level_docs)]
163
164mod addresses;
165mod api;
166mod app;
167mod app_builder;
168mod bank;
169mod checksums;
170mod contracts;
171pub mod custom_handler;
172pub mod error;
173mod executor;
174mod featured;
175mod gov;
176mod ibc;
177mod module;
178mod prefixed_storage;
179#[cfg(feature = "staking")]
180mod staking;
181mod stargate;
182mod test_helpers;
183mod tests;
184mod transactions;
185mod wasm;
186
187pub use crate::addresses::{
188 AddressGenerator, IntoAddr, IntoBech32, IntoBech32m, SimpleAddressGenerator,
189};
190pub use crate::api::{MockApiBech32, MockApiBech32m};
191pub use crate::app::{
192 custom_app, next_block, no_init, App, BasicApp, CosmosRouter, Router, SudoMsg,
193};
194pub use crate::app_builder::{AppBuilder, BasicAppBuilder};
195pub use crate::bank::{Bank, BankKeeper, BankSudo};
196pub use crate::checksums::ChecksumGenerator;
197pub use crate::contracts::{Contract, ContractWrapper};
198pub use crate::executor::{AppResponse, Executor};
199pub use crate::featured::staking::{
200 Distribution, DistributionKeeper, StakeKeeper, Staking, StakingInfo, StakingSudo,
201};
202pub use crate::gov::{Gov, GovAcceptingModule, GovFailingModule};
203pub use crate::ibc::{Ibc, IbcAcceptingModule, IbcFailingModule};
204pub use crate::module::{AcceptingModule, FailingModule, Module};
205pub use crate::stargate::{Stargate, StargateAccepting, StargateFailing};
206pub use crate::wasm::{ContractData, Wasm, WasmKeeper, WasmSudo};