1use cosmwasm_std::{Addr, Deps, QuerierWrapper};
2use cw_asset::AssetInfo;
3use thiserror::Error;
4
5use super::{AssetEntry, ChannelEntry, ContractEntry};
6use crate::{
7 ans_host::{
8 state::{
9 ASSET_ADDRESSES, ASSET_PAIRINGS, CHANNELS, CONTRACT_ADDRESSES, POOL_METADATA,
10 REGISTERED_DEXES, REV_ASSET_ADDRESSES,
11 },
12 RegisteredDexesResponse,
13 },
14 native_addrs,
15 objects::{DexAssetPairing, PoolMetadata, PoolReference, UniquePoolId},
16 AbstractResult,
17};
18
19#[derive(Error, Debug, PartialEq)]
20pub enum AnsHostError {
21 #[error("Contract {contract} not found in ans_host {ans_host}.")]
23 ContractNotFound {
24 contract: ContractEntry,
25 ans_host: Addr,
26 },
27
28 #[error("Asset {asset} not found in ans_host {ans_host}.")]
30 AssetNotFound { asset: AssetEntry, ans_host: Addr },
31
32 #[error("CW Asset {asset} not found in ans_host {ans_host}.")]
34 CwAssetNotFound { asset: AssetInfo, ans_host: Addr },
35
36 #[error("Channel {channel} not found in ans_host {ans_host}.")]
38 ChannelNotFound {
39 channel: ChannelEntry,
40 ans_host: Addr,
41 },
42
43 #[error("Asset pairing {pairing} not found in ans_host {ans_host}.")]
45 DexPairingNotFound {
46 pairing: DexAssetPairing,
47 ans_host: Addr,
48 },
49
50 #[error("Pool metadata for pool {pool} not found in ans_host {ans_host}.")]
52 PoolMetadataNotFound { pool: UniquePoolId, ans_host: Addr },
53
54 #[error("Object {object} should be formatted {expected} but is {actual}")]
55 FormattingError {
56 object: String,
57 expected: String,
58 actual: String,
59 },
60
61 #[error("Query during '{method_name}' failed: {error}")]
63 QueryFailed {
64 method_name: String,
65 error: cosmwasm_std::StdError,
66 },
67}
68
69pub type AnsHostResult<T> = Result<T, AnsHostError>;
70
71#[cosmwasm_schema::cw_serde]
74pub struct AnsHost {
75 pub address: Addr,
77}
78
79impl AnsHost {
80 pub fn new(deps: Deps, abstract_code_id: u64) -> AbstractResult<Self> {
82 let address = deps
83 .api
84 .addr_humanize(&native_addrs::ans_address(deps, abstract_code_id)?)?;
85 Ok(Self { address })
86 }
87 pub fn query_contracts(
89 &self,
90 querier: &QuerierWrapper,
91 contracts: &[ContractEntry],
92 ) -> AnsHostResult<Vec<Addr>> {
93 let mut resolved_contracts: Vec<Addr> = Vec::new();
94 for key in contracts.iter() {
96 let result = self.query_contract(querier, key)?;
97 resolved_contracts.push(result);
98 }
99 Ok(resolved_contracts)
100 }
101
102 #[function_name::named]
104 pub fn query_contract(
105 &self,
106 querier: &QuerierWrapper,
107 contract: &ContractEntry,
108 ) -> AnsHostResult<Addr> {
109 let result: Addr = CONTRACT_ADDRESSES
110 .query(querier, self.address.clone(), contract)
111 .map_err(|error| AnsHostError::QueryFailed {
112 method_name: function_name!().to_owned(),
113 error,
114 })?
115 .ok_or_else(|| AnsHostError::ContractNotFound {
116 contract: contract.clone(),
117 ans_host: self.address.clone(),
118 })?;
119 Ok(result)
120 }
121
122 pub fn query_assets(
124 &self,
125 querier: &QuerierWrapper,
126 assets: &[AssetEntry],
127 ) -> AnsHostResult<Vec<AssetInfo>> {
128 let mut resolved_assets = Vec::new();
129
130 for asset in assets.iter() {
131 let result = self.query_asset(querier, asset)?;
132 resolved_assets.push(result);
133 }
134 Ok(resolved_assets)
135 }
136
137 #[function_name::named]
139 pub fn query_asset(
140 &self,
141 querier: &QuerierWrapper,
142 asset: &AssetEntry,
143 ) -> AnsHostResult<AssetInfo> {
144 let result = ASSET_ADDRESSES
145 .query(querier, self.address.clone(), asset)
146 .map_err(|error| AnsHostError::QueryFailed {
147 method_name: function_name!().to_owned(),
148 error,
149 })?
150 .ok_or_else(|| AnsHostError::AssetNotFound {
151 asset: asset.clone(),
152 ans_host: self.address.clone(),
153 })?;
154 Ok(result)
155 }
156
157 pub fn query_assets_reverse(
159 &self,
160 querier: &QuerierWrapper,
161 assets: &[AssetInfo],
162 ) -> AnsHostResult<Vec<AssetEntry>> {
163 let mut resolved_assets = vec![];
165
166 for asset in assets.iter() {
167 let result = self.query_asset_reverse(querier, asset)?;
168 resolved_assets.push(result);
169 }
170 Ok(resolved_assets)
171 }
172
173 #[function_name::named]
175 pub fn query_asset_reverse(
176 &self,
177 querier: &QuerierWrapper,
178 asset: &AssetInfo,
179 ) -> AnsHostResult<AssetEntry> {
180 let result = REV_ASSET_ADDRESSES
181 .query(querier, self.address.clone(), asset)
182 .map_err(|error| AnsHostError::QueryFailed {
183 method_name: function_name!().to_owned(),
184 error,
185 })?
186 .ok_or_else(|| AnsHostError::CwAssetNotFound {
187 asset: asset.clone(),
188 ans_host: self.address.clone(),
189 })?;
190 Ok(result)
191 }
192
193 #[function_name::named]
195 pub fn query_channel(
196 &self,
197 querier: &QuerierWrapper,
198 channel: &ChannelEntry,
199 ) -> AnsHostResult<String> {
200 let result: String = CHANNELS
201 .query(querier, self.address.clone(), channel)
202 .map_err(|error| AnsHostError::QueryFailed {
203 method_name: function_name!().to_owned(),
204 error,
205 })?
206 .ok_or_else(|| AnsHostError::ChannelNotFound {
207 channel: channel.clone(),
208 ans_host: self.address.clone(),
209 })?;
210 Ok(result)
212 }
213
214 #[function_name::named]
216 pub fn query_asset_pairing(
217 &self,
218 querier: &QuerierWrapper,
219 dex_asset_pairing: &DexAssetPairing,
220 ) -> AnsHostResult<Vec<PoolReference>> {
221 let result: Vec<PoolReference> = ASSET_PAIRINGS
222 .query(querier, self.address.clone(), dex_asset_pairing)
223 .map_err(|error| AnsHostError::QueryFailed {
224 method_name: function_name!().to_owned(),
225 error,
226 })?
227 .ok_or_else(|| AnsHostError::DexPairingNotFound {
228 pairing: dex_asset_pairing.clone(),
229 ans_host: self.address.clone(),
230 })?;
231 Ok(result)
232 }
233
234 #[function_name::named]
235 pub fn query_pool_metadata(
236 &self,
237 querier: &QuerierWrapper,
238 pool_id: UniquePoolId,
239 ) -> AnsHostResult<PoolMetadata> {
240 let result: PoolMetadata = POOL_METADATA
241 .query(querier, self.address.clone(), pool_id)
242 .map_err(|error| AnsHostError::QueryFailed {
243 method_name: function_name!().to_owned(),
244 error,
245 })?
246 .ok_or_else(|| AnsHostError::PoolMetadataNotFound {
247 pool: pool_id,
248 ans_host: self.address.clone(),
249 })?;
250 Ok(result)
251 }
252
253 #[function_name::named]
254 pub fn query_registered_dexes(
255 &self,
256 querier: &QuerierWrapper,
257 ) -> AnsHostResult<RegisteredDexesResponse> {
258 let dexes = REGISTERED_DEXES
259 .query(querier, self.address.clone())
260 .map_err(|error| AnsHostError::QueryFailed {
261 method_name: function_name!().to_owned(),
262 error,
263 })?;
264 Ok(RegisteredDexesResponse { dexes })
265 }
266}