1use abstract_sdk::feature_objects::{AnsHost, RegistryContract};
2use abstract_std::{
3 app::{AppConfigResponse, AppQueryMsg, BaseQueryMsg, QueryMsg},
4 native_addrs,
5 objects::{
6 gov_type::TopLevelOwnerResponse,
7 module_version::{ModuleDataResponse, MODULE},
8 ownership::nested_admin::query_top_level_owner_addr,
9 },
10};
11use cosmwasm_std::{to_json_binary, Binary, Deps, Env, StdError, StdResult};
12use cw_controllers::AdminResponse;
13
14use crate::{
15 state::{AppContract, ContractError},
16 Handler, QueryEndpoint,
17};
18
19impl<
20 Error: ContractError,
21 CustomInitMsg,
22 CustomExecMsg,
23 CustomQueryMsg: AppQueryMsg,
24 CustomMigrateMsg,
25 SudoMsg,
26 > QueryEndpoint
27 for AppContract<Error, CustomInitMsg, CustomExecMsg, CustomQueryMsg, CustomMigrateMsg, SudoMsg>
28{
29 type QueryMsg = QueryMsg<CustomQueryMsg>;
30
31 fn query(&self, deps: Deps, env: Env, msg: Self::QueryMsg) -> Result<Binary, Error> {
32 match msg {
33 QueryMsg::Base(msg) => self.base_query(deps, msg).map_err(Into::into),
34 QueryMsg::Module(msg) => self.query_handler()?(deps, env, self, msg),
35 }
36 }
37}
38impl<
41 Error: ContractError,
42 CustomInitMsg,
43 CustomExecMsg,
44 CustomQueryMsg,
45 CustomMigrateMsg,
46 SudoMsg,
47 > AppContract<Error, CustomInitMsg, CustomExecMsg, CustomQueryMsg, CustomMigrateMsg, SudoMsg>
48{
49 pub fn base_query(&self, deps: Deps, query: BaseQueryMsg) -> StdResult<Binary> {
50 match query {
51 BaseQueryMsg::BaseConfig {} => to_json_binary(&self.dapp_config(deps)?),
52 BaseQueryMsg::BaseAdmin {} => to_json_binary(&self.admin(deps)?),
53 BaseQueryMsg::ModuleData {} => to_json_binary(&self.module_data(deps)?),
54 BaseQueryMsg::TopLevelOwner {} => to_json_binary(&self.top_level_owner(deps)?),
55 }
56 }
57
58 fn dapp_config(&self, deps: Deps) -> StdResult<AppConfigResponse> {
59 let state = self.base_state.load(deps.storage)?;
60 let abstract_code_id = native_addrs::abstract_code_id(&deps.querier, state.account.addr())?;
61 Ok(AppConfigResponse {
62 account: state.account.into_addr(),
63 ans_host_address: AnsHost::new(deps, abstract_code_id)
64 .map_err(|e| StdError::generic_err(e.to_string()))?
65 .address,
66 registry_address: RegistryContract::new(deps, abstract_code_id)
67 .map_err(|e| StdError::generic_err(e.to_string()))?
68 .address,
69 })
70 }
71
72 fn admin(&self, deps: Deps) -> StdResult<AdminResponse> {
73 self.admin.query_admin(deps)
74 }
75
76 fn module_data(&self, deps: Deps) -> StdResult<ModuleDataResponse> {
77 let module_data = MODULE.load(deps.storage)?;
78 Ok(ModuleDataResponse {
79 module_id: module_data.module,
80 version: module_data.version,
81 dependencies: module_data
82 .dependencies
83 .into_iter()
84 .map(Into::into)
85 .collect(),
86 metadata: module_data.metadata,
87 })
88 }
89
90 fn top_level_owner(&self, deps: Deps) -> StdResult<TopLevelOwnerResponse> {
91 let account = self.admin.get(deps)?.unwrap();
92 let addr = query_top_level_owner_addr(&deps.querier, account)?;
93 Ok(TopLevelOwnerResponse { address: addr })
94 }
95}
96
97#[cfg(test)]
98mod test {
99 #![allow(clippy::needless_borrows_for_generic_args)]
100 use abstract_sdk::base::QueryEndpoint;
101 use cosmwasm_std::{Binary, Deps, Env};
102
103 use super::QueryMsg as SuperQueryMsg;
104 use crate::mock::*;
105
106 type AppQueryMsg = SuperQueryMsg<MockQueryMsg>;
107
108 fn query_helper(deps: Deps, env: Env, msg: AppQueryMsg) -> Result<Binary, MockError> {
109 BASIC_MOCK_APP.query(deps, env, msg)
110 }
111
112 mod app_query {
113 use abstract_sdk::AbstractSdkError;
114 use abstract_testing::mock_env_validated;
115 use cosmwasm_std::{to_json_binary, Env};
116
117 use super::*;
118
119 #[coverage_helper::test]
120 fn without_handler() {
121 let deps = mock_init();
122 let msg = AppQueryMsg::Module(MockQueryMsg::GetSomething {});
123
124 let res = query_helper(deps.as_ref(), mock_env_validated(deps.api), msg);
125
126 assert!(matches!(
127 res,
128 Err(MockError::AbstractSdk(
129 AbstractSdkError::MissingHandler { .. }
130 ))
131 ));
132 }
133
134 fn mock_query_handler(
135 _deps: Deps,
136 _env: Env,
137 _contract: &MockAppContract,
138 msg: MockQueryMsg,
139 ) -> Result<Binary, MockError> {
140 to_json_binary(&msg).map_err(Into::into)
142 }
143
144 #[coverage_helper::test]
145 fn with_handler() {
146 let deps = mock_init();
147 let msg = AppQueryMsg::Module(MockQueryMsg::GetSomething {});
148
149 let with_mocked_query = BASIC_MOCK_APP.with_query(mock_query_handler);
150 let res = with_mocked_query.query(deps.as_ref(), mock_env_validated(deps.api), msg);
151
152 let expected = to_json_binary(&MockQueryMsg::GetSomething {}).unwrap();
153 assert_eq!(res, Ok(expected));
154 }
155 }
156
157 mod base_query {
158 use super::*;
159
160 use abstract_std::{
161 app::{AppConfigResponse, BaseQueryMsg},
162 objects::module_version::ModuleDataResponse,
163 };
164 use abstract_testing::prelude::*;
165 use cw_controllers::AdminResponse;
166
167 #[coverage_helper::test]
168 fn config() -> AppTestResult {
169 let deps = mock_init();
170 let abstr = AbstractMockAddrs::new(deps.api);
171 let account = test_account(deps.api);
172
173 let config_query = QueryMsg::Base(BaseQueryMsg::BaseConfig {});
174 let res = query_helper(deps.as_ref(), mock_env_validated(deps.api), config_query)?;
175
176 assert_eq!(
177 AppConfigResponse {
178 account: account.into_addr(),
179 ans_host_address: abstr.ans_host,
180 registry_address: abstr.registry,
181 },
182 from_json(res).unwrap()
183 );
184
185 Ok(())
186 }
187
188 #[coverage_helper::test]
189 fn admin() -> AppTestResult {
190 let deps = mock_init();
191 let account = test_account(deps.api);
192
193 let admin_query = QueryMsg::Base(BaseQueryMsg::BaseAdmin {});
194 let res = query_helper(deps.as_ref(), mock_env_validated(deps.api), admin_query)?;
195
196 assert_eq!(
197 AdminResponse {
198 admin: Some(account.addr().to_string()),
199 },
200 from_json(res).unwrap()
201 );
202
203 Ok(())
204 }
205
206 #[coverage_helper::test]
207 fn module_data() -> AppTestResult {
208 let deps = mock_init();
209
210 let module_data_query = QueryMsg::Base(BaseQueryMsg::ModuleData {});
211 let res = query_helper(
212 deps.as_ref(),
213 mock_env_validated(deps.api),
214 module_data_query,
215 )?;
216
217 assert_eq!(
218 ModuleDataResponse {
219 module_id: TEST_MODULE_ID.to_string(),
220 version: TEST_VERSION.to_string(),
221 dependencies: vec![],
222 metadata: None
223 },
224 from_json(res).unwrap()
225 );
226
227 Ok(())
228 }
229 }
230}