abstract_sdk/apis/
adapter.rs1#![allow(dead_code)]
2
3use abstract_std::{adapter::AdapterRequestMsg, objects::module::ModuleId};
4use cosmwasm_std::{wasm_execute, CosmosMsg, Deps};
5use serde::{de::DeserializeOwned, Serialize};
6
7use super::AbstractApi;
8use crate::{
9 cw_helpers::ApiQuery, features::ModuleIdentification, AbstractSdkResult, ModuleInterface,
10};
11
12pub trait AdapterInterface: ModuleInterface + ModuleIdentification {
14 fn adapters<'a>(&'a self, deps: Deps<'a>) -> Adapters<'a, Self> {
31 Adapters { base: self, deps }
32 }
33}
34
35impl<T> AdapterInterface for T where T: ModuleInterface + ModuleIdentification {}
36
37impl<T: AdapterInterface> AbstractApi<T> for Adapters<'_, T> {
38 const API_ID: &'static str = "Adapters";
39
40 fn base(&self) -> &T {
41 self.base
42 }
43 fn deps(&self) -> Deps {
44 self.deps
45 }
46}
47
48#[derive(Clone)]
65pub struct Adapters<'a, T: AdapterInterface> {
66 base: &'a T,
67 deps: Deps<'a>,
68}
69
70impl<T: AdapterInterface> Adapters<'_, T> {
71 pub fn execute<M: Serialize + Into<abstract_std::adapter::ExecuteMsg<M>>>(
74 &self,
75 adapter_id: ModuleId,
76 message: M,
77 ) -> AbstractSdkResult<CosmosMsg> {
78 let modules = self.base.modules(self.deps);
79 modules.assert_module_dependency(adapter_id)?;
80 let adapter_msg = abstract_std::adapter::ExecuteMsg::<_>::Module(AdapterRequestMsg::new(
81 Some(self.base.account(self.deps)?.into_addr().into_string()),
82 message,
83 ));
84 let adapter_address = modules.module_address(adapter_id)?;
85 Ok(wasm_execute(adapter_address, &adapter_msg, vec![])?.into())
86 }
87
88 pub fn query<Q: Serialize, R: DeserializeOwned>(
90 &self,
91 adapter_id: ModuleId,
92 query: impl Into<abstract_std::adapter::QueryMsg<Q>>,
93 ) -> AbstractSdkResult<R> {
94 let adapter_query: abstract_std::adapter::QueryMsg<Q> = query.into();
95 let modules = self.base.modules(self.deps);
96 let adapter_address = modules.module_address(adapter_id)?;
97 self.smart_query(adapter_address, &adapter_query)
98 }
99}
100
101#[cfg(test)]
102mod tests {
103
104 use abstract_testing::prelude::*;
105 use cosmwasm_std::*;
106
107 use super::*;
108 use crate::{apis::traits::test::abstract_api_test, mock_module::*};
109
110 pub fn fail_when_not_dependency_test<T: std::fmt::Debug>(
111 modules_fn: impl FnOnce(&MockModule, Deps) -> AbstractSdkResult<T>,
112 fake_module: ModuleId,
113 ) {
114 let (deps, _, app) = mock_module_setup();
115
116 let _mods = app.adapters(deps.as_ref());
117
118 let res = modules_fn(&app, deps.as_ref());
119
120 assert!(res
121 .unwrap_err()
122 .to_string()
123 .contains(&fake_module.to_string()));
124 }
125 mod adapter_request {
126 use super::*;
127
128 use crate::std::adapter;
129
130 #[coverage_helper::test]
131 fn should_return_err_if_not_dependency() {
132 fail_when_not_dependency_test(
133 |app, deps| {
134 let mods = app.adapters(deps);
135 mods.execute(FAKE_MODULE_ID, MockModuleExecuteMsg {})
136 },
137 FAKE_MODULE_ID,
138 );
139 }
140
141 #[coverage_helper::test]
142 fn expected_adapter_request() {
143 let (deps, account, app) = mock_module_setup();
144 let abstr = AbstractMockAddrs::new(deps.api);
145
146 let mods = app.adapters(deps.as_ref());
147
148 let res = mods.execute(TEST_MODULE_ID, MockModuleExecuteMsg {});
149
150 let expected_msg: adapter::ExecuteMsg<_> =
151 adapter::ExecuteMsg::Module(AdapterRequestMsg {
152 account_address: Some(account.addr().to_string()),
153 request: MockModuleExecuteMsg {},
154 });
155
156 assert_eq!(
157 res,
158 Ok(CosmosMsg::Wasm(WasmMsg::Execute {
159 contract_addr: abstr.module_address.to_string(),
160 msg: to_json_binary(&expected_msg).unwrap(),
161 funds: vec![],
162 }))
163 );
164 }
165 }
166
167 mod query_api {
168 use super::*;
169
170 #[coverage_helper::test]
171 fn should_return_err_if_not_dependency() {
172 fail_when_not_dependency_test(
173 |app, deps| {
174 let mods = app.adapters(deps);
175 mods.query::<_, Empty>(FAKE_MODULE_ID, Empty {})
176 },
177 FAKE_MODULE_ID,
178 );
179 }
180
181 #[coverage_helper::test]
182 fn expected_adapter_query() {
183 let (deps, _, app) = mock_module_setup();
184
185 let mods = app.adapters(deps.as_ref());
186
187 let inner_msg = Empty {};
188
189 let res = mods.query::<_, String>(TEST_MODULE_ID, inner_msg);
190
191 assert_eq!(res, Ok(TEST_MODULE_RESPONSE.to_string()));
192 }
193 }
194
195 #[coverage_helper::test]
196 fn abstract_api() {
197 let (deps, _, app) = mock_module_setup();
198 let adapters = app.adapters(deps.as_ref());
199
200 abstract_api_test(adapters);
201 }
202}