rhaki_cw_multi_test/
custom_handler.rs

1//! # Custom message and query handler
2
3use crate::app::CosmosRouter;
4use crate::error::{bail, AnyResult};
5use crate::{AppResponse, Module};
6use cosmwasm_std::{Addr, Api, Binary, BlockInfo, Empty, Querier, Storage};
7use derivative::Derivative;
8use std::cell::{Ref, RefCell};
9use std::ops::Deref;
10use std::rc::Rc;
11
12/// A cache for messages and queries processes by the custom module.
13#[derive(Derivative)]
14#[derivative(Default(bound = "", new = "true"), Clone(bound = ""))]
15pub struct CachingCustomHandlerState<ExecC, QueryC> {
16    /// Cache for processes custom messages.
17    execs: Rc<RefCell<Vec<ExecC>>>,
18    /// Cache for processed custom queries.
19    queries: Rc<RefCell<Vec<QueryC>>>,
20}
21
22impl<ExecC, QueryC> CachingCustomHandlerState<ExecC, QueryC> {
23    /// Returns a slice of processed custom messages.
24    pub fn execs(&self) -> impl Deref<Target = [ExecC]> + '_ {
25        Ref::map(self.execs.borrow(), Vec::as_slice)
26    }
27
28    /// Returns a slice of processed custom queries.
29    pub fn queries(&self) -> impl Deref<Target = [QueryC]> + '_ {
30        Ref::map(self.queries.borrow(), Vec::as_slice)
31    }
32
33    /// Clears the cache.
34    pub fn reset(&self) {
35        self.execs.borrow_mut().clear();
36        self.queries.borrow_mut().clear();
37    }
38}
39
40/// Custom handler that stores all received messages and queries.
41///
42/// State is thin shared state, so it can be held after mock is passed to [App](crate::App) to read state.
43#[derive(Clone, Derivative)]
44#[derivative(Default(bound = "", new = "true"))]
45pub struct CachingCustomHandler<ExecC, QueryC> {
46    /// Cached state.
47    state: CachingCustomHandlerState<ExecC, QueryC>,
48}
49
50impl<ExecC, QueryC> CachingCustomHandler<ExecC, QueryC> {
51    /// Returns the cached state.
52    pub fn state(&self) -> CachingCustomHandlerState<ExecC, QueryC> {
53        self.state.clone()
54    }
55}
56
57impl<Exec, Query> Module for CachingCustomHandler<Exec, Query> {
58    type ExecT = Exec;
59    type QueryT = Query;
60    type SudoT = Empty;
61
62    // TODO: how to assert like `where ExecC: Exec, QueryC: Query`
63    fn execute<ExecC, QueryC>(
64        &self,
65        _api: &dyn Api,
66        _storage: &mut dyn Storage,
67        _router: &dyn CosmosRouter<ExecC = ExecC, QueryC = QueryC>,
68        _block: &BlockInfo,
69        _sender: Addr,
70        msg: Self::ExecT,
71    ) -> AnyResult<AppResponse> {
72        self.state.execs.borrow_mut().push(msg);
73        Ok(AppResponse::default())
74    }
75
76    fn query(
77        &self,
78        _api: &dyn Api,
79        _storage: &dyn Storage,
80        _querier: &dyn Querier,
81        _block: &BlockInfo,
82        request: Self::QueryT,
83    ) -> AnyResult<Binary> {
84        self.state.queries.borrow_mut().push(request);
85        Ok(Binary::default())
86    }
87
88    fn sudo<ExecC, QueryC>(
89        &self,
90        _api: &dyn Api,
91        _storage: &mut dyn Storage,
92        _router: &dyn CosmosRouter<ExecC = ExecC, QueryC = QueryC>,
93        _block: &BlockInfo,
94        msg: Self::SudoT,
95    ) -> AnyResult<AppResponse> {
96        bail!("Unexpected custom sudo message {:?}", msg)
97    }
98}