rhaki_cw_multi_test/
app.rs

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