cw_multi_test/
module.rs

1use crate::app::CosmosRouter;
2use crate::error::{bail, AnyResult};
3use crate::AppResponse;
4use cosmwasm_std::{Addr, Api, Binary, BlockInfo, CustomMsg, CustomQuery, Querier, Storage};
5use serde::de::DeserializeOwned;
6use std::fmt::Debug;
7use std::marker::PhantomData;
8
9/// # General module
10///
11/// Provides a generic interface for modules within the test environment.
12/// It is essential for creating modular and extensible testing setups,
13/// allowing developers to integrate custom functionalities
14/// or test specific scenarios.
15pub trait Module {
16    /// Type of messages processed by the module instance.
17    type ExecT;
18    /// Type of queries processed by the module instance.
19    type QueryT;
20    /// Type of privileged messages used by the module instance.
21    type SudoT;
22
23    /// Runs any [ExecT](Self::ExecT) message,
24    /// which can be called by any external actor or smart contract.
25    fn execute<ExecC, QueryC>(
26        &self,
27        api: &dyn Api,
28        storage: &mut dyn Storage,
29        router: &dyn CosmosRouter<ExecC = ExecC, QueryC = QueryC>,
30        block: &BlockInfo,
31        sender: Addr,
32        msg: Self::ExecT,
33    ) -> AnyResult<AppResponse>
34    where
35        ExecC: CustomMsg + DeserializeOwned + 'static,
36        QueryC: CustomQuery + DeserializeOwned + 'static;
37
38    /// Runs any [QueryT](Self::QueryT) message,
39    /// which can be called by any external actor or smart contract.
40    fn query(
41        &self,
42        api: &dyn Api,
43        storage: &dyn Storage,
44        querier: &dyn Querier,
45        block: &BlockInfo,
46        request: Self::QueryT,
47    ) -> AnyResult<Binary>;
48
49    /// Runs privileged actions, like minting tokens, or governance proposals.
50    /// This allows modules to have full access to these privileged actions,
51    /// that cannot be triggered by smart contracts.
52    ///
53    /// There is no sender, as this must be previously authorized before calling.
54    fn sudo<ExecC, QueryC>(
55        &self,
56        api: &dyn Api,
57        storage: &mut dyn Storage,
58        router: &dyn CosmosRouter<ExecC = ExecC, QueryC = QueryC>,
59        block: &BlockInfo,
60        msg: Self::SudoT,
61    ) -> AnyResult<AppResponse>
62    where
63        ExecC: CustomMsg + DeserializeOwned + 'static,
64        QueryC: CustomQuery + DeserializeOwned + 'static;
65}
66/// # Always failing module
67///
68/// This could be a diagnostic or testing tool within the Cosmos ecosystem,
69/// designed to intentionally fail during processing any message, query or privileged action.
70pub struct FailingModule<ExecT, QueryT, SudoT>(PhantomData<(ExecT, QueryT, SudoT)>);
71
72impl<ExecT, QueryT, SudoT> FailingModule<ExecT, QueryT, SudoT> {
73    /// Creates an instance of a failing module.
74    pub fn new() -> Self {
75        Self(PhantomData)
76    }
77}
78
79impl<ExecT, QueryT, SudoT> Default for FailingModule<ExecT, QueryT, SudoT> {
80    /// Creates a default instance of a failing module.
81    fn default() -> Self {
82        Self::new()
83    }
84}
85
86impl<ExecT, QueryT, SudoT> Module for FailingModule<ExecT, QueryT, SudoT>
87where
88    ExecT: Debug,
89    QueryT: Debug,
90    SudoT: Debug,
91{
92    type ExecT = ExecT;
93    type QueryT = QueryT;
94    type SudoT = SudoT;
95
96    /// Runs any [ExecT](Self::ExecT) message, always returns an error.
97    fn execute<ExecC, QueryC>(
98        &self,
99        _api: &dyn Api,
100        _storage: &mut dyn Storage,
101        _router: &dyn CosmosRouter<ExecC = ExecC, QueryC = QueryC>,
102        _block: &BlockInfo,
103        sender: Addr,
104        msg: Self::ExecT,
105    ) -> AnyResult<AppResponse> {
106        bail!("Unexpected exec msg {:?} from {:?}", msg, sender)
107    }
108
109    /// Runs any [QueryT](Self::QueryT) message, always returns an error.
110    fn query(
111        &self,
112        _api: &dyn Api,
113        _storage: &dyn Storage,
114        _querier: &dyn Querier,
115        _block: &BlockInfo,
116        request: Self::QueryT,
117    ) -> AnyResult<Binary> {
118        bail!("Unexpected custom query {:?}", request)
119    }
120
121    /// Runs any [SudoT](Self::SudoT) privileged action, always returns an error.
122    fn sudo<ExecC, QueryC>(
123        &self,
124        _api: &dyn Api,
125        _storage: &mut dyn Storage,
126        _router: &dyn CosmosRouter<ExecC = ExecC, QueryC = QueryC>,
127        _block: &BlockInfo,
128        msg: Self::SudoT,
129    ) -> AnyResult<AppResponse> {
130        bail!("Unexpected sudo msg {:?}", msg)
131    }
132}
133/// # Always accepting module
134///
135/// This struct represents a module in the Cosmos ecosystem designed to
136/// always accept all processed messages, queries and privileged actions.
137pub struct AcceptingModule<ExecT, QueryT, SudoT>(PhantomData<(ExecT, QueryT, SudoT)>);
138
139impl<ExecT, QueryT, SudoT> AcceptingModule<ExecT, QueryT, SudoT> {
140    /// Creates an instance of an accepting module.
141    pub fn new() -> Self {
142        Self(PhantomData)
143    }
144}
145
146impl<ExecT, QueryT, SudoT> Default for AcceptingModule<ExecT, QueryT, SudoT> {
147    /// Creates an instance of an accepting module with default settings.
148    fn default() -> Self {
149        Self::new()
150    }
151}
152
153impl<ExecT, QueryT, SudoT> Module for AcceptingModule<ExecT, QueryT, SudoT>
154where
155    ExecT: Debug,
156    QueryT: Debug,
157    SudoT: Debug,
158{
159    type ExecT = ExecT;
160    type QueryT = QueryT;
161    type SudoT = SudoT;
162
163    /// Runs any [ExecT](Self::ExecT) message, always returns a default response.
164    fn execute<ExecC, QueryC>(
165        &self,
166        _api: &dyn Api,
167        _storage: &mut dyn Storage,
168        _router: &dyn CosmosRouter<ExecC = ExecC, QueryC = QueryC>,
169        _block: &BlockInfo,
170        _sender: Addr,
171        _msg: Self::ExecT,
172    ) -> AnyResult<AppResponse> {
173        Ok(AppResponse::default())
174    }
175
176    /// Runs any [QueryT](Self::QueryT) message, always returns a default (empty) binary.
177    fn query(
178        &self,
179        _api: &dyn Api,
180        _storage: &dyn Storage,
181        _querier: &dyn Querier,
182        _block: &BlockInfo,
183        _request: Self::QueryT,
184    ) -> AnyResult<Binary> {
185        Ok(Binary::default())
186    }
187
188    /// Runs any [SudoT](Self::SudoT) privileged action, always returns a default response.
189    fn sudo<ExecC, QueryC>(
190        &self,
191        _api: &dyn Api,
192        _storage: &mut dyn Storage,
193        _router: &dyn CosmosRouter<ExecC = ExecC, QueryC = QueryC>,
194        _block: &BlockInfo,
195        _msg: Self::SudoT,
196    ) -> AnyResult<AppResponse> {
197        Ok(AppResponse::default())
198    }
199}