clone_cw_multi_test/
custom_handler.rs

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