cw_multi_test/
app.rs

1use crate::bank::{Bank, BankKeeper, BankSudo};
2use crate::contracts::Contract;
3use crate::error::std_error_bail;
4use crate::executor::{AppResponse, Executor};
5use crate::featured::staking::{
6    Distribution, DistributionKeeper, StakeKeeper, Staking, StakingSudo,
7};
8use crate::gov::Gov;
9use crate::ibc::Ibc;
10use crate::module::{FailingModule, Module};
11use crate::prefixed_storage::{
12    prefixed, prefixed_multilevel, prefixed_multilevel_read, prefixed_read,
13};
14use crate::transactions::transactional;
15use crate::wasm::{ContractData, Wasm, WasmKeeper, WasmSudo};
16use crate::{AppBuilder, GovFailingModule, IbcFailingModule, Stargate, StargateFailing};
17use cosmwasm_std::testing::{MockApi, MockStorage};
18use cosmwasm_std::{
19    from_json, to_json_binary, Addr, Api, Binary, BlockInfo, ContractResult, CosmosMsg, CustomMsg,
20    CustomQuery, Empty, Querier, QuerierResult, QuerierWrapper, QueryRequest, Record, StdError,
21    StdResult, Storage, SystemError, SystemResult,
22};
23use serde::{de::DeserializeOwned, Serialize};
24use std::fmt::Debug;
25use std::marker::PhantomData;
26
27/// Advances the blockchain environment to the next block in tests, enabling developers to simulate
28/// time-dependent contract behaviors and block-related triggers efficiently.
29pub fn next_block(block: &mut BlockInfo) {
30    block.time = block.time.plus_seconds(5);
31    block.height += 1;
32}
33
34/// A type alias for the default-built App. It simplifies storage and handling in typical scenarios,
35/// streamlining the use of the App structure in standard test setups.
36pub type BasicApp<ExecC = Empty, QueryC = Empty> = App<
37    BankKeeper,
38    MockApi,
39    MockStorage,
40    FailingModule<ExecC, QueryC, Empty>,
41    WasmKeeper<ExecC, QueryC>,
42    StakeKeeper,
43    DistributionKeeper,
44    IbcFailingModule,
45    GovFailingModule,
46    StargateFailing,
47>;
48
49/// # Blockchain application simulator
50///
51/// This structure is the main component of the real-life blockchain simulator.
52#[derive(Clone)]
53pub struct App<
54    Bank = BankKeeper,
55    Api = MockApi,
56    Storage = MockStorage,
57    Custom = FailingModule<Empty, Empty, Empty>,
58    Wasm = WasmKeeper<Empty, Empty>,
59    Staking = StakeKeeper,
60    Distr = DistributionKeeper,
61    Ibc = IbcFailingModule,
62    Gov = GovFailingModule,
63    Stargate = StargateFailing,
64> {
65    pub(crate) router: Router<Bank, Custom, Wasm, Staking, Distr, Ibc, Gov, Stargate>,
66    pub(crate) api: Api,
67    pub(crate) storage: Storage,
68    pub(crate) block: BlockInfo,
69}
70
71/// No-op application initialization function.
72pub fn no_init<ApiT, BankT, CustomT, WasmT, StakingT, DistrT, IbcT, GovT, StargateT>(
73    router: &mut Router<BankT, CustomT, WasmT, StakingT, DistrT, IbcT, GovT, StargateT>,
74    api: &ApiT,
75    storage: &mut dyn Storage,
76) {
77    let _ = (router, api, storage);
78}
79
80impl Default for BasicApp {
81    fn default() -> Self {
82        Self::new(no_init)
83    }
84}
85
86impl BasicApp {
87    /// Creates new default `App` implementation working with Empty custom messages.
88    pub fn new<F>(init_fn: F) -> Self
89    where
90        F: FnOnce(
91            &mut Router<
92                BankKeeper,
93                FailingModule<Empty, Empty, Empty>,
94                WasmKeeper<Empty, Empty>,
95                StakeKeeper,
96                DistributionKeeper,
97                IbcFailingModule,
98                GovFailingModule,
99                StargateFailing,
100            >,
101            &MockApi,
102            &mut dyn Storage,
103        ),
104    {
105        AppBuilder::new().build(init_fn)
106    }
107}
108
109/// Creates new default `App` implementation working with customized exec and query messages.
110/// Outside the `App` implementation to make type elision better.
111pub fn custom_app<ExecC, QueryC, F>(init_fn: F) -> BasicApp<ExecC, QueryC>
112where
113    ExecC: CustomMsg + DeserializeOwned + 'static,
114    QueryC: Debug + CustomQuery + DeserializeOwned + 'static,
115    F: FnOnce(
116        &mut Router<
117            BankKeeper,
118            FailingModule<ExecC, QueryC, Empty>,
119            WasmKeeper<ExecC, QueryC>,
120            StakeKeeper,
121            DistributionKeeper,
122            IbcFailingModule,
123            GovFailingModule,
124            StargateFailing,
125        >,
126        &MockApi,
127        &mut dyn Storage,
128    ),
129{
130    AppBuilder::new_custom().build(init_fn)
131}
132
133impl<BankT, ApiT, StorageT, CustomT, WasmT, StakingT, DistrT, IbcT, GovT, StargateT> Querier
134    for App<BankT, ApiT, StorageT, CustomT, WasmT, StakingT, DistrT, IbcT, GovT, StargateT>
135where
136    CustomT::ExecT: CustomMsg + DeserializeOwned + 'static,
137    CustomT::QueryT: CustomQuery + DeserializeOwned + 'static,
138    WasmT: Wasm<CustomT::ExecT, CustomT::QueryT>,
139    BankT: Bank,
140    ApiT: Api,
141    StorageT: Storage,
142    CustomT: Module,
143    StakingT: Staking,
144    DistrT: Distribution,
145    IbcT: Ibc,
146    GovT: Gov,
147    StargateT: Stargate,
148{
149    fn raw_query(&self, bin_request: &[u8]) -> QuerierResult {
150        self.router
151            .querier(&self.api, &self.storage, &self.block)
152            .raw_query(bin_request)
153    }
154}
155
156impl<BankT, ApiT, StorageT, CustomT, WasmT, StakingT, DistrT, IbcT, GovT, StargateT>
157    Executor<CustomT::ExecT>
158    for App<BankT, ApiT, StorageT, CustomT, WasmT, StakingT, DistrT, IbcT, GovT, StargateT>
159where
160    CustomT::ExecT: CustomMsg + DeserializeOwned + 'static,
161    CustomT::QueryT: CustomQuery + DeserializeOwned + 'static,
162    WasmT: Wasm<CustomT::ExecT, CustomT::QueryT>,
163    BankT: Bank,
164    ApiT: Api,
165    StorageT: Storage,
166    CustomT: Module,
167    StakingT: Staking,
168    DistrT: Distribution,
169    IbcT: Ibc,
170    GovT: Gov,
171    StargateT: Stargate,
172{
173    fn execute(&mut self, sender: Addr, msg: CosmosMsg<CustomT::ExecT>) -> StdResult<AppResponse> {
174        let mut all = self.execute_multi(sender, vec![msg])?;
175        let res = all.pop().unwrap();
176        Ok(res)
177    }
178}
179
180impl<BankT, ApiT, StorageT, CustomT, WasmT, StakingT, DistrT, IbcT, GovT, StargateT>
181    App<BankT, ApiT, StorageT, CustomT, WasmT, StakingT, DistrT, IbcT, GovT, StargateT>
182where
183    WasmT: Wasm<CustomT::ExecT, CustomT::QueryT>,
184    BankT: Bank,
185    ApiT: Api,
186    StorageT: Storage,
187    CustomT: Module,
188    StakingT: Staking,
189    DistrT: Distribution,
190    IbcT: Ibc,
191    GovT: Gov,
192    StargateT: Stargate,
193{
194    /// Returns a shared reference to application's router.
195    pub fn router(
196        &self,
197    ) -> &Router<BankT, CustomT, WasmT, StakingT, DistrT, IbcT, GovT, StargateT> {
198        &self.router
199    }
200
201    /// Returns a shared reference to application's API.
202    pub fn api(&self) -> &ApiT {
203        &self.api
204    }
205
206    /// Returns a shared reference to application's storage.
207    pub fn storage(&self) -> &StorageT {
208        &self.storage
209    }
210
211    /// Returns a mutable reference to application's storage.
212    pub fn storage_mut(&mut self) -> &mut StorageT {
213        &mut self.storage
214    }
215
216    /// Initializes modules.
217    pub fn init_modules<F, T>(&mut self, init_fn: F) -> T
218    where
219        F: FnOnce(
220            &mut Router<BankT, CustomT, WasmT, StakingT, DistrT, IbcT, GovT, StargateT>,
221            &ApiT,
222            &mut dyn Storage,
223        ) -> T,
224    {
225        init_fn(&mut self.router, &self.api, &mut self.storage)
226    }
227
228    /// Queries a module.
229    pub fn read_module<F, T>(&self, query_fn: F) -> T
230    where
231        F: FnOnce(
232            &Router<BankT, CustomT, WasmT, StakingT, DistrT, IbcT, GovT, StargateT>,
233            &ApiT,
234            &dyn Storage,
235        ) -> T,
236    {
237        query_fn(&self.router, &self.api, &self.storage)
238    }
239}
240
241// Helper functions to call some custom WasmKeeper logic.
242// They show how we can easily add such calls to other custom keepers (CustomT, StakingT, etc)
243impl<BankT, ApiT, StorageT, CustomT, WasmT, StakingT, DistrT, IbcT, GovT, StargateT>
244    App<BankT, ApiT, StorageT, CustomT, WasmT, StakingT, DistrT, IbcT, GovT, StargateT>
245where
246    BankT: Bank,
247    ApiT: Api,
248    StorageT: Storage,
249    CustomT: Module,
250    WasmT: Wasm<CustomT::ExecT, CustomT::QueryT>,
251    StakingT: Staking,
252    DistrT: Distribution,
253    IbcT: Ibc,
254    GovT: Gov,
255    StargateT: Stargate,
256    CustomT::ExecT: CustomMsg + DeserializeOwned + 'static,
257    CustomT::QueryT: CustomQuery + DeserializeOwned + 'static,
258{
259    /// Registers contract code (like uploading wasm bytecode on a chain),
260    /// so it can later be used to instantiate a contract.
261    pub fn store_code(&mut self, code: Box<dyn Contract<CustomT::ExecT, CustomT::QueryT>>) -> u64 {
262        self.router
263            .wasm
264            .store_code(MockApi::default().addr_make("creator"), code)
265    }
266
267    /// Registers contract code (like [store_code](Self::store_code)),
268    /// but takes the address of the code creator as an additional argument.
269    pub fn store_code_with_creator(
270        &mut self,
271        creator: Addr,
272        code: Box<dyn Contract<CustomT::ExecT, CustomT::QueryT>>,
273    ) -> u64 {
274        self.router.wasm.store_code(creator, code)
275    }
276
277    /// Registers contract code (like [store_code_with_creator](Self::store_code_with_creator)),
278    /// but takes the code identifier as an additional argument.
279    pub fn store_code_with_id(
280        &mut self,
281        creator: Addr,
282        code_id: u64,
283        code: Box<dyn Contract<CustomT::ExecT, CustomT::QueryT>>,
284    ) -> StdResult<u64> {
285        self.router.wasm.store_code_with_id(creator, code_id, code)
286    }
287
288    /// Duplicates the contract code identified by `code_id` and returns
289    /// the identifier of the newly created copy of the contract code.
290    ///
291    /// # Examples
292    ///
293    /// ```
294    /// use cosmwasm_std::Addr;
295    /// use cw_multi_test::App;
296    ///
297    /// // contract implementation
298    /// mod echo {
299    ///   // contract entry points not shown here
300    /// #  use cosmwasm_std::{Binary, Deps, DepsMut, Empty, Env, MessageInfo, Response, StdError, SubMsg, WasmMsg};
301    /// #  use serde::{Deserialize, Serialize};
302    /// #  use cw_multi_test::{Contract, ContractWrapper};
303    /// #
304    /// #  fn instantiate(_: DepsMut, _: Env, _: MessageInfo, _: Empty) -> Result<Response, StdError> {
305    /// #    unimplemented!()
306    /// #  }
307    /// #
308    /// #  fn execute(_: DepsMut, _: Env, _info: MessageInfo, msg: WasmMsg) -> Result<Response, StdError> {
309    /// #    unimplemented!()
310    /// #  }
311    /// #
312    /// #  fn query(_deps: Deps, _env: Env, _msg: Empty) -> Result<Binary, StdError> {
313    /// #    unimplemented!()
314    /// #  }
315    /// #
316    ///   pub fn contract() -> Box<dyn Contract<Empty>> {
317    ///     // should return the contract
318    /// #   Box::new(ContractWrapper::new(execute, instantiate, query))
319    ///   }
320    /// }
321    ///
322    /// let mut app = App::default();
323    ///
324    /// // store a new contract, save the code id
325    /// let code_id = app.store_code(echo::contract());
326    ///
327    /// // duplicate the existing contract, duplicated contract has different code id
328    /// assert_ne!(code_id, app.duplicate_code(code_id).unwrap());
329    ///
330    /// // zero is an invalid identifier for contract code, returns an error
331    /// assert_eq!("kind: Other, error: code id: invalid", app.duplicate_code(0).unwrap_err().to_string());
332    ///
333    /// // there is no contract code with identifier 100 stored yet, returns an error
334    /// assert_eq!("kind: Other, error: code id 100: no such code", app.duplicate_code(100).unwrap_err().to_string());
335    /// ```
336    pub fn duplicate_code(&mut self, code_id: u64) -> StdResult<u64> {
337        self.router.wasm.duplicate_code(code_id)
338    }
339
340    /// Returns `ContractData` for the contract with specified address.
341    pub fn contract_data(&self, address: &Addr) -> StdResult<ContractData> {
342        self.router.wasm.contract_data(&self.storage, address)
343    }
344
345    /// Returns a raw state dump of all key-values held by a contract with specified address.
346    pub fn dump_wasm_raw(&self, address: &Addr) -> Vec<Record> {
347        self.router.wasm.dump_wasm_raw(&self.storage, address)
348    }
349
350    /// Returns **read-only** storage for a contract with specified address.
351    pub fn contract_storage<'a>(&'a self, contract_addr: &Addr) -> Box<dyn Storage + 'a> {
352        self.router
353            .wasm
354            .contract_storage(&self.storage, contract_addr)
355    }
356
357    /// Returns **read-write** storage for a contract with specified address.
358    pub fn contract_storage_mut<'a>(&'a mut self, contract_addr: &Addr) -> Box<dyn Storage + 'a> {
359        self.router
360            .wasm
361            .contract_storage_mut(&mut self.storage, contract_addr)
362    }
363
364    /// Returns **read-only** prefixed storage with specified namespace.
365    pub fn prefixed_storage<'a>(&'a self, namespace: &[u8]) -> Box<dyn Storage + 'a> {
366        Box::new(prefixed_read(&self.storage, namespace))
367    }
368
369    /// Returns **mutable** prefixed storage with specified namespace.
370    pub fn prefixed_storage_mut<'a>(&'a mut self, namespace: &[u8]) -> Box<dyn Storage + 'a> {
371        Box::new(prefixed(&mut self.storage, namespace))
372    }
373
374    /// Returns **read-only** prefixed, multilevel storage with specified namespaces.
375    pub fn prefixed_multilevel_storage<'a>(
376        &'a self,
377        namespaces: &[&[u8]],
378    ) -> Box<dyn Storage + 'a> {
379        Box::new(prefixed_multilevel_read(&self.storage, namespaces))
380    }
381
382    /// Returns **mutable** prefixed, multilevel storage with specified namespaces.
383    pub fn prefixed_multilevel_storage_mut<'a>(
384        &'a mut self,
385        namespaces: &[&[u8]],
386    ) -> Box<dyn Storage + 'a> {
387        Box::new(prefixed_multilevel(&mut self.storage, namespaces))
388    }
389}
390
391impl<BankT, ApiT, StorageT, CustomT, WasmT, StakingT, DistrT, IbcT, GovT, StargateT>
392    App<BankT, ApiT, StorageT, CustomT, WasmT, StakingT, DistrT, IbcT, GovT, StargateT>
393where
394    CustomT::ExecT: CustomMsg + DeserializeOwned + 'static,
395    CustomT::QueryT: CustomQuery + DeserializeOwned + 'static,
396    WasmT: Wasm<CustomT::ExecT, CustomT::QueryT>,
397    BankT: Bank,
398    ApiT: Api,
399    StorageT: Storage,
400    CustomT: Module,
401    StakingT: Staking,
402    DistrT: Distribution,
403    IbcT: Ibc,
404    GovT: Gov,
405    StargateT: Stargate,
406{
407    /// Sets the initial block properties.
408    pub fn set_block(&mut self, block: BlockInfo) {
409        self.block = block;
410        self.router
411            .staking
412            .process_queue(&self.api, &mut self.storage, &self.router, &self.block)
413            .unwrap();
414    }
415
416    /// Updates the current block applying the specified closure, usually [next_block].
417    pub fn update_block<F: Fn(&mut BlockInfo)>(&mut self, action: F) {
418        action(&mut self.block);
419        self.router
420            .staking
421            .process_queue(&self.api, &mut self.storage, &self.router, &self.block)
422            .unwrap();
423    }
424
425    /// Returns a copy of the current block info.
426    pub fn block_info(&self) -> BlockInfo {
427        self.block.clone()
428    }
429
430    /// Simple helper so we get access to all the QuerierWrapper helpers,
431    /// e.g. wrap().query_wasm_smart, query_all_balances, ...
432    pub fn wrap(&self) -> QuerierWrapper<CustomT::QueryT> {
433        QuerierWrapper::new(self)
434    }
435
436    /// Runs multiple CosmosMsg in one atomic operation.
437    /// This will create a cache before the execution, so no state changes are persisted if any of them
438    /// return an error. But all writes are persisted on success.
439    pub fn execute_multi(
440        &mut self,
441        sender: Addr,
442        msgs: Vec<CosmosMsg<CustomT::ExecT>>,
443    ) -> StdResult<Vec<AppResponse>> {
444        // we need to do some caching of storage here, once in the entry point:
445        // meaning, wrap current state, all writes go to a cache, only when execute
446        // returns a success do we flush it (otherwise drop it)
447
448        let Self {
449            block,
450            router,
451            api,
452            storage,
453        } = self;
454
455        transactional(&mut *storage, |write_cache, _| {
456            msgs.into_iter()
457                .map(|msg| router.execute(&*api, write_cache, block, sender.clone(), msg))
458                .collect()
459        })
460    }
461
462    /// Call a smart contract in "sudo" mode.
463    /// This will create a cache before the execution, so no state changes are persisted if this
464    /// returns an error, but all are persisted on success.
465    pub fn wasm_sudo<T: Serialize, U: Into<Addr>>(
466        &mut self,
467        contract_addr: U,
468        msg: &T,
469    ) -> StdResult<AppResponse> {
470        let msg = WasmSudo {
471            contract_addr: contract_addr.into(),
472            message: to_json_binary(msg)?,
473        };
474
475        let Self {
476            block,
477            router,
478            api,
479            storage,
480        } = self;
481
482        transactional(&mut *storage, |write_cache, _| {
483            router.wasm.sudo(&*api, write_cache, router, block, msg)
484        })
485    }
486
487    /// Runs arbitrary SudoMsg.
488    /// This will create a cache before the execution, so no state changes are persisted if this
489    /// returns an error, but all are persisted on success.
490    pub fn sudo(&mut self, msg: SudoMsg) -> StdResult<AppResponse> {
491        // we need to do some caching of storage here, once in the entry point:
492        // meaning, wrap current state, all writes go to a cache, only when execute
493        // returns a success do we flush it (otherwise drop it)
494        let Self {
495            block,
496            router,
497            api,
498            storage,
499        } = self;
500
501        transactional(&mut *storage, |write_cache, _| {
502            router.sudo(&*api, write_cache, block, msg)
503        })
504    }
505}
506/// The Router plays a critical role in managing and directing
507/// transactions within the Cosmos blockchain.
508#[derive(Clone)]
509pub struct Router<Bank, Custom, Wasm, Staking, Distr, Ibc, Gov, Stargate> {
510    /// Wasm module instance to be used in this [Router].
511    pub(crate) wasm: Wasm,
512    /// Bank module instance to be used in this [Router].
513    pub bank: Bank,
514    /// Custom module instance to be used in this [Router].
515    pub custom: Custom,
516    /// Staking module instance to be used in this [Router].
517    pub staking: Staking,
518    /// Distribution module instance to be used in this [Router].
519    pub distribution: Distr,
520    /// IBC module instance to be used in this [Router].
521    pub ibc: Ibc,
522    /// Governance module instance to be used in this [Router].
523    pub gov: Gov,
524    /// Stargate handler instance to be used in this [Router].
525    pub stargate: Stargate,
526}
527
528impl<BankT, CustomT, WasmT, StakingT, DistrT, IbcT, GovT, StargateT>
529    Router<BankT, CustomT, WasmT, StakingT, DistrT, IbcT, GovT, StargateT>
530where
531    CustomT::ExecT: CustomMsg + DeserializeOwned + 'static,
532    CustomT::QueryT: CustomQuery + DeserializeOwned + 'static,
533    CustomT: Module,
534    WasmT: Wasm<CustomT::ExecT, CustomT::QueryT>,
535    BankT: Bank,
536    StakingT: Staking,
537    DistrT: Distribution,
538    IbcT: Ibc,
539    GovT: Gov,
540    StargateT: Stargate,
541{
542    /// Returns a querier populated with the instance of this [Router].
543    pub fn querier<'a>(
544        &'a self,
545        api: &'a dyn Api,
546        storage: &'a dyn Storage,
547        block_info: &'a BlockInfo,
548    ) -> RouterQuerier<'a, CustomT::ExecT, CustomT::QueryT> {
549        RouterQuerier {
550            router: self,
551            api,
552            storage,
553            block_info,
554        }
555    }
556}
557
558/// We use it to allow calling into modules from another module in sudo mode.
559/// Things like gov proposals belong here.
560pub enum SudoMsg {
561    /// Bank privileged actions.
562    Bank(BankSudo),
563    /// Custom privileged actions.
564    Custom(Empty),
565    /// Staking privileged actions.
566    Staking(StakingSudo),
567    /// Wasm privileged actions.
568    Wasm(WasmSudo),
569}
570
571impl From<WasmSudo> for SudoMsg {
572    fn from(wasm: WasmSudo) -> Self {
573        SudoMsg::Wasm(wasm)
574    }
575}
576
577impl From<BankSudo> for SudoMsg {
578    fn from(bank: BankSudo) -> Self {
579        SudoMsg::Bank(bank)
580    }
581}
582
583impl From<StakingSudo> for SudoMsg {
584    fn from(staking: StakingSudo) -> Self {
585        SudoMsg::Staking(staking)
586    }
587}
588/// A trait representing the Cosmos based chain's router.
589///
590/// This trait is designed for routing messages within the Cosmos ecosystem.
591/// It is key to ensure that transactions and contract calls are directed to the
592/// correct destinations during testing, simulating real-world blockchain operations.
593pub trait CosmosRouter {
594    /// Type of the executed custom message.
595    type ExecC: CustomMsg;
596    /// Type of the query custom message.
597    type QueryC: CustomQuery;
598
599    /// Executes messages.
600    fn execute(
601        &self,
602        api: &dyn Api,
603        storage: &mut dyn Storage,
604        block: &BlockInfo,
605        sender: Addr,
606        msg: CosmosMsg<Self::ExecC>,
607    ) -> StdResult<AppResponse>;
608
609    /// Evaluates queries.
610    fn query(
611        &self,
612        api: &dyn Api,
613        storage: &dyn Storage,
614        block: &BlockInfo,
615        request: QueryRequest<Self::QueryC>,
616    ) -> StdResult<Binary>;
617
618    /// Evaluates privileged actions.
619    fn sudo(
620        &self,
621        api: &dyn Api,
622        storage: &mut dyn Storage,
623        block: &BlockInfo,
624        msg: SudoMsg,
625    ) -> StdResult<AppResponse>;
626}
627
628impl<BankT, CustomT, WasmT, StakingT, DistrT, IbcT, GovT, StargateT> CosmosRouter
629    for Router<BankT, CustomT, WasmT, StakingT, DistrT, IbcT, GovT, StargateT>
630where
631    CustomT::ExecT: CustomMsg + DeserializeOwned + 'static,
632    CustomT::QueryT: CustomQuery + DeserializeOwned + 'static,
633    CustomT: Module,
634    WasmT: Wasm<CustomT::ExecT, CustomT::QueryT>,
635    BankT: Bank,
636    StakingT: Staking,
637    DistrT: Distribution,
638    IbcT: Ibc,
639    GovT: Gov,
640    StargateT: Stargate,
641{
642    type ExecC = CustomT::ExecT;
643    type QueryC = CustomT::QueryT;
644
645    fn execute(
646        &self,
647        api: &dyn Api,
648        storage: &mut dyn Storage,
649        block: &BlockInfo,
650        sender: Addr,
651        msg: CosmosMsg<Self::ExecC>,
652    ) -> StdResult<AppResponse> {
653        match msg {
654            CosmosMsg::Wasm(msg) => self.wasm.execute(api, storage, self, block, sender, msg),
655            CosmosMsg::Bank(msg) => self.bank.execute(api, storage, self, block, sender, msg),
656            CosmosMsg::Custom(msg) => self.custom.execute(api, storage, self, block, sender, msg),
657            #[cfg(feature = "staking")]
658            CosmosMsg::Staking(msg) => self.staking.execute(api, storage, self, block, sender, msg),
659            #[cfg(feature = "staking")]
660            CosmosMsg::Distribution(msg) => self
661                .distribution
662                .execute(api, storage, self, block, sender, msg),
663            #[cfg(feature = "stargate")]
664            CosmosMsg::Ibc(msg) => self.ibc.execute(api, storage, self, block, sender, msg),
665            #[cfg(feature = "stargate")]
666            CosmosMsg::Gov(msg) => self.gov.execute(api, storage, self, block, sender, msg),
667            #[allow(deprecated)]
668            #[cfg(feature = "stargate")]
669            CosmosMsg::Stargate { type_url, value } => self
670                .stargate
671                .execute_stargate(api, storage, self, block, sender, type_url, value),
672            #[cfg(feature = "cosmwasm_2_0")]
673            CosmosMsg::Any(msg) => self
674                .stargate
675                .execute_any(api, storage, self, block, sender, msg),
676            _ => std_error_bail!("Cannot execute {:?}", msg),
677        }
678    }
679
680    /// This is used by `RouterQuerier` to actual implement the `Querier` interface.
681    /// you most likely want to use `router.querier(storage, block).wrap()` to get a
682    /// QuerierWrapper to interact with
683    fn query(
684        &self,
685        api: &dyn Api,
686        storage: &dyn Storage,
687        block: &BlockInfo,
688        request: QueryRequest<Self::QueryC>,
689    ) -> StdResult<Binary> {
690        let querier = self.querier(api, storage, block);
691        match request {
692            QueryRequest::Wasm(req) => self.wasm.query(api, storage, &querier, block, req),
693            QueryRequest::Bank(req) => self.bank.query(api, storage, &querier, block, req),
694            QueryRequest::Custom(req) => self.custom.query(api, storage, &querier, block, req),
695            #[cfg(feature = "staking")]
696            QueryRequest::Staking(req) => self.staking.query(api, storage, &querier, block, req),
697            #[cfg(all(feature = "cosmwasm_1_3", feature = "staking"))]
698            QueryRequest::Distribution(req) => {
699                self.distribution.query(api, storage, &querier, block, req)
700            }
701            #[cfg(feature = "stargate")]
702            QueryRequest::Ibc(req) => self.ibc.query(api, storage, &querier, block, req),
703            #[allow(deprecated)]
704            #[cfg(feature = "stargate")]
705            QueryRequest::Stargate { path, data } => self
706                .stargate
707                .query_stargate(api, storage, &querier, block, path, data),
708            #[cfg(feature = "cosmwasm_2_0")]
709            QueryRequest::Grpc(req) => self.stargate.query_grpc(api, storage, &querier, block, req),
710            _ => unimplemented!(),
711        }
712    }
713
714    fn sudo(
715        &self,
716        api: &dyn Api,
717        storage: &mut dyn Storage,
718        block: &BlockInfo,
719        msg: SudoMsg,
720    ) -> StdResult<AppResponse> {
721        match msg {
722            SudoMsg::Wasm(msg) => self.wasm.sudo(api, storage, self, block, msg),
723            SudoMsg::Bank(msg) => self.bank.sudo(api, storage, self, block, msg),
724            #[cfg(feature = "staking")]
725            SudoMsg::Staking(msg) => self.staking.sudo(api, storage, self, block, msg),
726            _ => unimplemented!(),
727        }
728    }
729}
730
731pub struct MockRouter<ExecC, QueryC>(PhantomData<(ExecC, QueryC)>);
732
733impl Default for MockRouter<Empty, Empty> {
734    fn default() -> Self {
735        Self::new()
736    }
737}
738
739impl<ExecC, QueryC> MockRouter<ExecC, QueryC> {
740    pub fn new() -> Self
741    where
742        QueryC: CustomQuery,
743    {
744        MockRouter(PhantomData)
745    }
746}
747
748impl<ExecC, QueryC> CosmosRouter for MockRouter<ExecC, QueryC>
749where
750    ExecC: CustomMsg,
751    QueryC: CustomQuery,
752{
753    type ExecC = ExecC;
754    type QueryC = QueryC;
755
756    fn execute(
757        &self,
758        _api: &dyn Api,
759        _storage: &mut dyn Storage,
760        _block: &BlockInfo,
761        _sender: Addr,
762        _msg: CosmosMsg<Self::ExecC>,
763    ) -> StdResult<AppResponse> {
764        panic!("Cannot execute MockRouters");
765    }
766
767    fn query(
768        &self,
769        _api: &dyn Api,
770        _storage: &dyn Storage,
771        _block: &BlockInfo,
772        _request: QueryRequest<Self::QueryC>,
773    ) -> StdResult<Binary> {
774        panic!("Cannot query MockRouters");
775    }
776
777    fn sudo(
778        &self,
779        _api: &dyn Api,
780        _storage: &mut dyn Storage,
781        _block: &BlockInfo,
782        _msg: SudoMsg,
783    ) -> StdResult<AppResponse> {
784        panic!("Cannot sudo MockRouters");
785    }
786}
787
788pub struct RouterQuerier<'a, ExecC, QueryC> {
789    router: &'a dyn CosmosRouter<ExecC = ExecC, QueryC = QueryC>,
790    api: &'a dyn Api,
791    storage: &'a dyn Storage,
792    block_info: &'a BlockInfo,
793}
794
795impl<'a, ExecC, QueryC> RouterQuerier<'a, ExecC, QueryC> {
796    pub fn new(
797        router: &'a dyn CosmosRouter<ExecC = ExecC, QueryC = QueryC>,
798        api: &'a dyn Api,
799        storage: &'a dyn Storage,
800        block_info: &'a BlockInfo,
801    ) -> Self {
802        Self {
803            router,
804            api,
805            storage,
806            block_info,
807        }
808    }
809}
810
811impl<ExecC, QueryC> Querier for RouterQuerier<'_, ExecC, QueryC>
812where
813    ExecC: CustomMsg + DeserializeOwned + 'static,
814    QueryC: CustomQuery + DeserializeOwned + 'static,
815{
816    fn raw_query(&self, bin_request: &[u8]) -> QuerierResult {
817        let request: QueryRequest<QueryC> = match from_json(bin_request) {
818            Ok(v) => v,
819            Err(e) => {
820                return SystemResult::Err(SystemError::InvalidRequest {
821                    error: format!("Parsing query request: {e}"),
822                    request: bin_request.into(),
823                })
824            }
825        };
826        let contract_result: ContractResult<Binary> = self
827            .router
828            .query(self.api, self.storage, self.block_info, request)
829            .into();
830        SystemResult::Ok(contract_result)
831    }
832}