1#![allow(unused)]
2use abstract_std::{app as msg, objects::module::ModuleId};
3use cosmwasm_std::{wasm_execute, CosmosMsg, Deps, Empty};
4use serde::{de::DeserializeOwned, Serialize};
5
6use super::AbstractApi;
7use crate::{
8 cw_helpers::ApiQuery, features::ModuleIdentification, AbstractSdkResult, AccountAction,
9 ModuleInterface,
10};
11
12pub trait AppInterface: ModuleInterface + ModuleIdentification {
14 fn apps<'a>(&'a self, deps: Deps<'a>) -> Apps<'a, Self> {
31 Apps { base: self, deps }
32 }
33}
34
35impl<T> AppInterface for T where T: ModuleInterface + ModuleIdentification {}
36
37impl<T: AppInterface> AbstractApi<T> for Apps<'_, T> {
38 const API_ID: &'static str = "Apps";
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 Apps<'a, T: AppInterface> {
66 base: &'a T,
67 deps: Deps<'a>,
68}
69
70impl<T: AppInterface> Apps<'_, T> {
71 pub fn execute<M: Serialize>(
73 &self,
74 app_id: ModuleId,
75 message: impl Into<msg::ExecuteMsg<M>>,
76 ) -> AbstractSdkResult<CosmosMsg> {
77 let modules = self.base.modules(self.deps);
78 modules.assert_module_dependency(app_id)?;
79 let app_msg: msg::ExecuteMsg<M> = message.into();
80 let app_address = modules.module_address(app_id)?;
81 Ok(wasm_execute(app_address, &app_msg, vec![])?.into())
82 }
83
84 pub fn query<Q: Serialize, R: DeserializeOwned>(
86 &self,
87 app_id: ModuleId,
88 query: impl Into<msg::QueryMsg<Q>>,
89 ) -> AbstractSdkResult<R> {
90 let modules = self.base.modules(self.deps);
91 let app_query: msg::QueryMsg<Q> = query.into();
92 let app_address = modules.module_address(app_id)?;
93 self.smart_query(app_address, &app_query)
94 }
95}
96
97#[cfg(test)]
98mod tests {
99 use abstract_std::registry::Account;
100 use abstract_testing::{abstract_mock_querier_builder, prelude::*};
101 use cosmwasm_std::{testing::*, *};
102
103 pub use super::*;
104 use crate::{apis::traits::test::abstract_api_test, mock_module::*};
105
106 fn fail_when_not_dependency_test<T: std::fmt::Debug>(
108 modules_fn: impl FnOnce(&MockModule, Deps) -> AbstractSdkResult<T>,
109 fake_module: ModuleId,
110 ) {
111 let (deps, _, app) = mock_module_setup();
112
113 let _mods = app.apps(deps.as_ref());
114
115 let res = modules_fn(&app, deps.as_ref());
116
117 assert!(res
118 .unwrap_err()
119 .to_string()
120 .contains(&fake_module.to_string()));
121 }
122
123 mod app_request {
124 use super::*;
125 use crate::{mock_module::MockModuleExecuteMsg, std::app};
126
127 #[coverage_helper::test]
128 fn should_return_err_if_not_dependency() {
129 fail_when_not_dependency_test(
130 |app, deps| {
131 let mods = app.apps(deps);
132 mods.execute(FAKE_MODULE_ID, MockModuleExecuteMsg {})
133 },
134 FAKE_MODULE_ID,
135 );
136 }
137
138 #[coverage_helper::test]
139 fn expected_app_request() {
140 let (deps, _, app) = mock_module_setup();
141
142 let abstr = AbstractMockAddrs::new(deps.api);
143
144 let mods = app.apps(deps.as_ref());
145
146 let res = mods.execute(TEST_MODULE_ID, MockModuleExecuteMsg {});
147
148 let expected_msg: app::ExecuteMsg<_> = app::ExecuteMsg::Module(MockModuleExecuteMsg {});
149
150 assert_eq!(
151 res,
152 Ok(CosmosMsg::Wasm(WasmMsg::Execute {
153 contract_addr: abstr.module_address.into(),
154 msg: to_json_binary(&expected_msg).unwrap(),
155 funds: vec![],
156 }))
157 );
158 }
159 }
160
161 mod query_app {
162 use super::*;
163
164 #[coverage_helper::test]
165 fn should_return_err_if_not_dependency() {
166 fail_when_not_dependency_test(
167 |app, deps| {
168 let mods = app.apps(deps);
169 mods.query::<_, Empty>(FAKE_MODULE_ID, Empty {})
170 },
171 FAKE_MODULE_ID,
172 );
173 }
174
175 #[coverage_helper::test]
176 fn expected_app_query() {
177 let (deps, _, app) = mock_module_setup();
178
179 let mods = app.apps(deps.as_ref());
180
181 let res = mods.query::<_, String>(TEST_MODULE_ID, Empty {});
182
183 assert_eq!(res, Ok(TEST_MODULE_RESPONSE.to_string()));
184 }
185 }
186
187 #[coverage_helper::test]
188 fn abstract_api() {
189 let (deps, _, app) = mock_module_setup();
190 let apps = app.apps(deps.as_ref());
191
192 abstract_api_test(apps);
193 }
194}