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