abstract_adapter/
endpoints.rs

1mod execute;
2mod ibc_callback;
3mod instantiate;
4mod module_ibc;
5mod query;
6mod reply;
7mod sudo;
8
9#[macro_export]
10macro_rules! export_endpoints {
11    ($api_const:expr, $api_type:ty) => {
12        $crate::__endpoints_without_custom__!($api_const, $api_type);
13        /// Execute entrypoint
14        #[::cosmwasm_std::entry_point]
15        pub fn execute(
16            deps: ::cosmwasm_std::DepsMut,
17            env: ::cosmwasm_std::Env,
18            info: ::cosmwasm_std::MessageInfo,
19            msg: <$api_type as $crate::sdk::base::ExecuteEndpoint>::ExecuteMsg,
20        ) -> Result<::cosmwasm_std::Response, <$api_type as $crate::sdk::base::Handler>::Error> {
21            use $crate::sdk::base::ExecuteEndpoint;
22            $api_const.execute(deps, env, info, msg)
23        }
24    };
25    ($api_const:expr, $api_type:ty, $custom_exec:ty) => {
26        $crate::__endpoints_without_custom__!($api_const, $api_type);
27        /// Execute entrypoint
28        #[::cosmwasm_std::entry_point]
29        pub fn execute(
30            deps: ::cosmwasm_std::DepsMut,
31            env: ::cosmwasm_std::Env,
32            info: ::cosmwasm_std::MessageInfo,
33            msg: $custom_exec,
34        ) -> Result<::cosmwasm_std::Response, <$api_type as $crate::sdk::base::Handler>::Error> {
35            use $crate::sdk::base::{CustomExecuteHandler, ExecuteEndpoint};
36            match CustomExecuteHandler::try_into_base(msg) {
37                Ok(default) => $api_const.execute(deps, env, info, default),
38                Err(custom) => custom.custom_execute(deps, env, info, $api_const),
39            }
40        }
41    };
42}
43
44#[macro_export]
45#[doc(hidden)]
46macro_rules! __endpoints_without_custom__ {
47    ($api_const:expr, $api_type:ty) => {
48        /// Instantiate entrypoint
49        #[::cosmwasm_std::entry_point]
50        pub fn instantiate(
51            deps: ::cosmwasm_std::DepsMut,
52            env: ::cosmwasm_std::Env,
53            info: ::cosmwasm_std::MessageInfo,
54            msg: <$api_type as $crate::sdk::base::InstantiateEndpoint>::InstantiateMsg,
55        ) -> Result<::cosmwasm_std::Response, <$api_type as $crate::sdk::base::Handler>::Error> {
56            use $crate::sdk::base::InstantiateEndpoint;
57            $api_const.instantiate(deps, env, info, msg)
58        }
59
60        /// Query entrypoint
61        #[::cosmwasm_std::entry_point]
62        pub fn query(
63            deps: ::cosmwasm_std::Deps,
64            env: ::cosmwasm_std::Env,
65            msg: <$api_type as $crate::sdk::base::QueryEndpoint>::QueryMsg,
66        ) -> Result<::cosmwasm_std::Binary, <$api_type as $crate::sdk::base::Handler>::Error> {
67            use $crate::sdk::base::QueryEndpoint;
68            $api_const.query(deps, env, msg)
69        }
70
71        // Reply entrypoint
72        #[::cosmwasm_std::entry_point]
73        pub fn reply(
74            deps: ::cosmwasm_std::DepsMut,
75            env: ::cosmwasm_std::Env,
76            msg: ::cosmwasm_std::Reply,
77        ) -> Result<::cosmwasm_std::Response, <$api_type as $crate::sdk::base::Handler>::Error> {
78            use $crate::sdk::base::ReplyEndpoint;
79            $api_const.reply(deps, env, msg)
80        }
81
82        // Sudo entrypoint
83        #[::cosmwasm_std::entry_point]
84        pub fn sudo(
85            deps: ::cosmwasm_std::DepsMut,
86            env: ::cosmwasm_std::Env,
87            msg: <$api_type as $crate::sdk::base::Handler>::SudoMsg,
88        ) -> Result<::cosmwasm_std::Response, <$api_type as $crate::sdk::base::Handler>::Error> {
89            use $crate::sdk::base::SudoEndpoint;
90            $api_const.sudo(deps, env, msg)
91        }
92    };
93}
94
95#[cfg(test)]
96mod test {
97    #![allow(clippy::needless_borrows_for_generic_args)]
98    use abstract_sdk::base::{
99        CustomExecuteHandler, ExecuteEndpoint, InstantiateEndpoint, QueryEndpoint, ReplyEndpoint,
100        SudoEndpoint,
101    };
102    use abstract_std::adapter::{self, AdapterRequestMsg};
103    use abstract_testing::prelude::*;
104    use cosmwasm_std::{
105        testing::{message_info, mock_dependencies},
106        Binary, SubMsgResult,
107    };
108
109    use crate::mock::*;
110
111    #[coverage_helper::test]
112    fn exports_endpoints() {
113        export_endpoints!(MOCK_ADAPTER, MockAdapterContract);
114
115        let mut deps = mock_dependencies();
116        let env = mock_env_validated(deps.api);
117        let abstr = AbstractMockAddrs::new(deps.api);
118        let owner = abstr.owner;
119
120        // init
121        let init_msg = adapter::InstantiateMsg {
122            base: adapter::BaseInstantiateMsg {
123                registry_address: abstr.registry.to_string(),
124            },
125            module: MockInitMsg {},
126        };
127        let actual_init = instantiate(
128            deps.as_mut(),
129            env.clone(),
130            message_info(&owner, &[]),
131            init_msg.clone(),
132        );
133        let expected_init = MOCK_ADAPTER.instantiate(
134            deps.as_mut(),
135            env.clone(),
136            message_info(&owner, &[]),
137            init_msg,
138        );
139        assert_eq!(actual_init, expected_init);
140
141        // exec
142        let exec_msg = adapter::ExecuteMsg::Module(AdapterRequestMsg::new(None, MockExecMsg {}));
143        let actual_exec = execute(
144            deps.as_mut(),
145            env.clone(),
146            message_info(&owner, &[]),
147            exec_msg.clone(),
148        );
149        let expected_exec = MOCK_ADAPTER.execute(
150            deps.as_mut(),
151            env.clone(),
152            message_info(&owner, &[]),
153            exec_msg,
154        );
155        assert_eq!(actual_exec, expected_exec);
156
157        // query
158        let query_msg = adapter::QueryMsg::Module(MockQueryMsg::GetSomething {});
159        let actual_query = query(deps.as_ref(), env.clone(), query_msg.clone());
160        let expected_query = MOCK_ADAPTER.query(deps.as_ref(), env.clone(), query_msg);
161        assert_eq!(actual_query, expected_query);
162
163        // sudo
164        let sudo_msg = MockSudoMsg {};
165        let actual_sudo = sudo(deps.as_mut(), env.clone(), sudo_msg.clone());
166        let expected_sudo = MOCK_ADAPTER.sudo(deps.as_mut(), env.clone(), sudo_msg);
167        assert_eq!(actual_sudo, expected_sudo);
168
169        // reply
170        let reply_msg = ::cosmwasm_std::Reply {
171            id: 0,
172            result: SubMsgResult::Err("test".into()),
173            payload: Binary::default(),
174            gas_used: 0,
175        };
176        let actual_reply = reply(deps.as_mut(), env.clone(), reply_msg.clone());
177        let expected_reply = MOCK_ADAPTER.reply(deps.as_mut(), env, reply_msg);
178        assert_eq!(actual_reply, expected_reply);
179    }
180
181    #[coverage_helper::test]
182    fn export_endpoints_custom() {
183        #[cosmwasm_schema::cw_serde]
184        #[derive(cw_orch::ExecuteFns)]
185        pub enum CustomExecMsg {
186            Base(abstract_std::adapter::BaseExecuteMsg),
187            Module(AdapterRequestMsg<crate::mock::MockExecMsg>),
188            IbcCallback(abstract_std::ibc::IbcResponseMsg),
189            ModuleIbc(abstract_std::ibc::ModuleIbcMsg),
190            Foo {},
191        }
192
193        impl From<crate::mock::MockExecMsg> for CustomExecMsg {
194            fn from(request: crate::mock::MockExecMsg) -> Self {
195                Self::Module(AdapterRequestMsg {
196                    account_address: None,
197                    request,
198                })
199            }
200        }
201
202        impl CustomExecuteHandler<MockAdapterContract> for CustomExecMsg {
203            type ExecuteMsg = crate::mock::ExecuteMsg;
204
205            fn try_into_base(self) -> Result<Self::ExecuteMsg, Self> {
206                match self {
207                    CustomExecMsg::Base(msg) => Ok(Self::ExecuteMsg::Base(msg)),
208                    CustomExecMsg::Module(msg) => Ok(Self::ExecuteMsg::Module(msg)),
209                    CustomExecMsg::IbcCallback(msg) => Ok(Self::ExecuteMsg::IbcCallback(msg)),
210                    CustomExecMsg::ModuleIbc(msg) => Ok(Self::ExecuteMsg::ModuleIbc(msg)),
211                    _ => Err(self),
212                }
213            }
214
215            fn custom_execute(
216                self,
217                _deps: cosmwasm_std::DepsMut,
218                _env: cosmwasm_std::Env,
219                _info: cosmwasm_std::MessageInfo,
220                _module: MockAdapterContract,
221            ) -> Result<cosmwasm_std::Response, crate::mock::MockError> {
222                Ok(cosmwasm_std::Response::new().set_data(b"foo"))
223            }
224        }
225        export_endpoints!(MOCK_ADAPTER, MockAdapterContract, CustomExecMsg);
226
227        let mut deps = mock_dependencies();
228        let env = mock_env_validated(deps.api);
229
230        let abstr = AbstractMockAddrs::new(deps.api);
231        // custom
232        let actual_custom_exec = execute(
233            deps.as_mut(),
234            env.clone(),
235            message_info(&abstr.owner, &[]),
236            CustomExecMsg::Foo {},
237        )
238        .unwrap();
239        let expected_custom_exec =
240            cosmwasm_std::Response::<cosmwasm_std::Empty>::new().set_data(b"foo");
241        assert_eq!(actual_custom_exec, expected_custom_exec);
242
243        // ensure nothing got broken
244
245        // init
246        let init_msg = adapter::InstantiateMsg {
247            base: adapter::BaseInstantiateMsg {
248                registry_address: abstr.registry.to_string(),
249            },
250            module: MockInitMsg {},
251        };
252        let actual_init = instantiate(
253            deps.as_mut(),
254            env.clone(),
255            message_info(&abstr.owner, &[]),
256            init_msg.clone(),
257        );
258        let expected_init = MOCK_ADAPTER.instantiate(
259            deps.as_mut(),
260            env.clone(),
261            message_info(&abstr.owner, &[]),
262            init_msg,
263        );
264        assert_eq!(actual_init, expected_init);
265
266        // exec
267        let exec_msg = MockExecMsg {};
268        let actual_exec = execute(
269            deps.as_mut(),
270            env.clone(),
271            message_info(&abstr.owner, &[]),
272            exec_msg.clone().into(),
273        );
274        let expected_exec = MOCK_ADAPTER.execute(
275            deps.as_mut(),
276            env.clone(),
277            message_info(&abstr.owner, &[]),
278            exec_msg.into(),
279        );
280        assert_eq!(actual_exec, expected_exec);
281
282        // query
283        let query_msg = adapter::QueryMsg::Module(MockQueryMsg::GetSomething {});
284        let actual_query = query(deps.as_ref(), env.clone(), query_msg.clone());
285        let expected_query = MOCK_ADAPTER.query(deps.as_ref(), env.clone(), query_msg);
286        assert_eq!(actual_query, expected_query);
287
288        // sudo
289        let sudo_msg = MockSudoMsg {};
290        let actual_sudo = sudo(deps.as_mut(), env.clone(), sudo_msg.clone());
291        let expected_sudo = MOCK_ADAPTER.sudo(deps.as_mut(), env.clone(), sudo_msg);
292        assert_eq!(actual_sudo, expected_sudo);
293
294        // reply
295        let reply_msg = ::cosmwasm_std::Reply {
296            id: 0,
297            result: SubMsgResult::Err("test".into()),
298            payload: Binary::default(),
299            gas_used: 0,
300        };
301        let actual_reply = reply(deps.as_mut(), env.clone(), reply_msg.clone());
302        let expected_reply = MOCK_ADAPTER.reply(deps.as_mut(), env, reply_msg);
303        assert_eq!(actual_reply, expected_reply);
304    }
305}