apollo_cw_multi_test/
custom_handler.rs

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