1use cosmwasm_std::{Addr, Deps, QuerierWrapper};
2use thiserror::Error;
3
4use super::{
5 module::{Module, ModuleInfo},
6 module_reference::ModuleReference,
7 namespace::Namespace,
8 AccountId,
9};
10use crate::{
11 account::state::ACCOUNT_ID,
12 native_addrs,
13 registry::{
14 state::{
15 ACCOUNT_ADDRESSES, CONFIG, NAMESPACES, REGISTERED_MODULES, SERVICE_INFOS,
16 STANDALONE_INFOS,
17 },
18 Account, ModuleConfiguration, ModuleResponse, ModulesResponse, NamespaceResponse,
19 NamespacesResponse, QueryMsg,
20 },
21 AbstractResult,
22};
23
24#[derive(Error, Debug, PartialEq)]
25pub enum RegistryError {
26 #[error("Module {module} not found in version registry {registry_addr}.")]
28 ModuleNotFound { module: String, registry_addr: Addr },
29
30 #[error("Failed to query Account id on contract {contract_addr}. Please ensure that the contract is an Account contract.")]
32 FailedToQueryAccountId { contract_addr: Addr },
33
34 #[error("Standalone {code_id} not found in version registry {registry_addr}.")]
36 StandaloneNotFound { code_id: u64, registry_addr: Addr },
37
38 #[error("Unknown Account id {account_id} on registry {registry_addr}. Please ensure that you are using the correct Account id and registry address.")]
40 UnknownAccountId {
41 account_id: AccountId,
42 registry_addr: Addr,
43 },
44
45 #[error("Address {0} is not the valid account address of {1}.")]
47 NotAccount(Addr, AccountId),
48
49 #[error("Query during '{method_name}' failed: {error}")]
51 QueryFailed {
52 method_name: String,
53 error: cosmwasm_std::StdError,
54 },
55
56 #[error("Service {service_addr} not found in version registry {registry_addr}.")]
58 ServiceNotFound {
59 service_addr: Addr,
60 registry_addr: Addr,
61 },
62
63 #[error("The provided module {0} has an invalid module reference.")]
64 InvalidReference(ModuleInfo),
65}
66
67pub type RegistryResult<T> = Result<T, RegistryError>;
68
69#[allow(rustdoc::broken_intra_doc_links)]
71#[cosmwasm_schema::cw_serde]
73pub struct RegistryContract {
74 pub address: Addr,
76}
77
78impl RegistryContract {
79 pub fn new(deps: Deps, abstract_code_id: u64) -> AbstractResult<Self> {
81 let address = deps
82 .api
83 .addr_humanize(&native_addrs::registry_address(deps, abstract_code_id)?)?;
84 Ok(Self { address })
85 }
86
87 #[function_name::named]
91 pub fn query_module_reference_raw(
92 &self,
93 module_info: &ModuleInfo,
94 querier: &QuerierWrapper,
95 ) -> RegistryResult<ModuleReference> {
96 let module_reference = REGISTERED_MODULES
97 .query(querier, self.address.clone(), module_info)
98 .map_err(|error| RegistryError::QueryFailed {
99 method_name: function_name!().to_owned(),
100 error,
101 })?;
102
103 module_reference.ok_or_else(|| RegistryError::ModuleNotFound {
104 module: module_info.to_string(),
105 registry_addr: self.address.clone(),
106 })
107 }
108
109 pub fn query_module(
111 &self,
112 module_info: ModuleInfo,
113 querier: &QuerierWrapper,
114 ) -> RegistryResult<Module> {
115 Ok(self
116 .query_modules_configs(vec![module_info], querier)?
117 .swap_remove(0)
118 .module)
119 }
120
121 pub fn query_config(
123 &self,
124 module_info: ModuleInfo,
125 querier: &QuerierWrapper,
126 ) -> RegistryResult<ModuleConfiguration> {
127 Ok(self
128 .query_modules_configs(vec![module_info], querier)?
129 .swap_remove(0)
130 .config)
131 }
132
133 #[function_name::named]
135 pub fn query_modules_configs(
136 &self,
137 infos: Vec<ModuleInfo>,
138 querier: &QuerierWrapper,
139 ) -> RegistryResult<Vec<ModuleResponse>> {
140 let ModulesResponse { modules } = querier
141 .query_wasm_smart(self.address.to_string(), &QueryMsg::Modules { infos })
142 .map_err(|error| RegistryError::QueryFailed {
143 method_name: function_name!().to_owned(),
144 error,
145 })?;
146 Ok(modules)
147 }
148
149 #[function_name::named]
152 pub fn query_namespace(
153 &self,
154 namespace: Namespace,
155 querier: &QuerierWrapper,
156 ) -> RegistryResult<NamespaceResponse> {
157 let namespace_response: NamespaceResponse = querier
158 .query_wasm_smart(self.address.to_string(), &QueryMsg::Namespace { namespace })
159 .map_err(|error| RegistryError::QueryFailed {
160 method_name: function_name!().to_owned(),
161 error,
162 })?;
163 Ok(namespace_response)
164 }
165
166 #[function_name::named]
168 pub fn query_namespace_raw(
169 &self,
170 namespace: Namespace,
171 querier: &QuerierWrapper,
172 ) -> RegistryResult<Option<AccountId>> {
173 let namespace_response = NAMESPACES
174 .query(querier, self.address.clone(), &namespace)
175 .map_err(|error| RegistryError::QueryFailed {
176 method_name: function_name!().to_owned(),
177 error,
178 })?;
179 Ok(namespace_response)
180 }
181
182 #[function_name::named]
184 pub fn query_namespaces(
185 &self,
186 accounts: Vec<AccountId>,
187 querier: &QuerierWrapper,
188 ) -> RegistryResult<NamespacesResponse> {
189 let namespaces_response: NamespacesResponse = querier
190 .query_wasm_smart(self.address.to_string(), &QueryMsg::Namespaces { accounts })
191 .map_err(|error| RegistryError::QueryFailed {
192 method_name: function_name!().to_owned(),
193 error,
194 })?;
195 Ok(namespaces_response)
196 }
197
198 #[function_name::named]
200 pub fn query_standalone_info_raw(
201 &self,
202 code_id: u64,
203 querier: &QuerierWrapper,
204 ) -> RegistryResult<ModuleInfo> {
205 let module_info = STANDALONE_INFOS
206 .query(querier, self.address.clone(), code_id)
207 .map_err(|error| RegistryError::QueryFailed {
208 method_name: function_name!().to_owned(),
209 error,
210 })?;
211 module_info.ok_or_else(|| RegistryError::StandaloneNotFound {
212 code_id,
213 registry_addr: self.address.clone(),
214 })
215 }
216
217 #[function_name::named]
219 pub fn query_service_info_raw(
220 &self,
221 service_addr: &Addr,
222 querier: &QuerierWrapper,
223 ) -> RegistryResult<ModuleInfo> {
224 let module_info = SERVICE_INFOS
225 .query(querier, self.address.clone(), service_addr)
226 .map_err(|error| RegistryError::QueryFailed {
227 method_name: function_name!().to_owned(),
228 error,
229 })?;
230 module_info.ok_or_else(|| RegistryError::ServiceNotFound {
231 service_addr: service_addr.clone(),
232 registry_addr: self.address.clone(),
233 })
234 }
235
236 pub fn unchecked_account_id(
241 &self,
242 maybe_core_contract_addr: &Addr,
243 querier: &QuerierWrapper,
244 ) -> RegistryResult<AccountId> {
245 ACCOUNT_ID
246 .query(querier, maybe_core_contract_addr.clone())
247 .map_err(|_| RegistryError::FailedToQueryAccountId {
248 contract_addr: maybe_core_contract_addr.clone(),
249 })
250 }
251
252 pub fn account_id(
255 &self,
256 maybe_account_addr: &Addr,
257 querier: &QuerierWrapper,
258 ) -> RegistryResult<AccountId> {
259 let self_reported_account_id = self.unchecked_account_id(maybe_account_addr, querier)?;
260 let account = self.account(&self_reported_account_id, querier)?;
262 if account.addr().ne(maybe_account_addr) {
263 Err(RegistryError::FailedToQueryAccountId {
264 contract_addr: maybe_account_addr.clone(),
265 })
266 } else {
267 Ok(self_reported_account_id)
268 }
269 }
270
271 #[function_name::named]
273 pub fn account(
274 &self,
275 account_id: &AccountId,
276 querier: &QuerierWrapper,
277 ) -> RegistryResult<Account> {
278 let maybe_account = ACCOUNT_ADDRESSES
279 .query(querier, self.address.clone(), account_id)
280 .map_err(|error| RegistryError::QueryFailed {
281 method_name: function_name!().to_owned(),
282 error,
283 })?;
284 maybe_account.ok_or_else(|| RegistryError::UnknownAccountId {
285 account_id: account_id.clone(),
286 registry_addr: self.address.clone(),
287 })
288 }
289
290 #[function_name::named]
292 pub fn namespace_registration_fee(
293 &self,
294 querier: &QuerierWrapper,
295 ) -> RegistryResult<Option<cosmwasm_std::Coin>> {
296 let config = CONFIG
297 .query(querier, self.address.clone())
298 .map_err(|error| RegistryError::QueryFailed {
299 method_name: function_name!().to_owned(),
300 error,
301 })?;
302 Ok(config.namespace_registration_fee)
303 }
304
305 pub fn assert_account(
307 &self,
308 maybe_account: &Addr,
309 querier: &QuerierWrapper,
310 ) -> RegistryResult<Account> {
311 let account_id = self.unchecked_account_id(maybe_account, querier)?;
312 let account = self.account(&account_id, querier)?;
313 if account.addr().ne(maybe_account) {
314 Err(RegistryError::NotAccount(maybe_account.clone(), account_id))
315 } else {
316 Ok(account)
317 }
318 }
319}