abstract_ibc_host/endpoints/
query.rs

1use std::str::FromStr;
2
3use abstract_sdk::{
4    feature_objects::{AnsHost, RegistryContract},
5    std::ibc_host::QueryMsg,
6};
7use abstract_std::{
8    ibc_host::{state::CHAIN_PROXIES, ClientProxiesResponse, ClientProxyResponse, ConfigResponse},
9    native_addrs,
10    objects::{module_factory::ModuleFactoryContract, TruncatedChainId},
11};
12use cosmwasm_std::{to_json_binary, Binary, Deps, Env};
13use cw_storage_plus::Bound;
14
15use crate::{contract::HostResult, HostError};
16
17use super::packet;
18
19pub fn query(deps: Deps, env: Env, query: QueryMsg) -> HostResult<Binary> {
20    match query {
21        QueryMsg::Config {} => to_json_binary(&config(deps, &env)?),
22        QueryMsg::ClientProxies { start_after, limit } => {
23            to_json_binary(&registered_chains(deps, start_after, limit)?)
24        }
25        QueryMsg::ClientProxy { chain } => to_json_binary(&associated_client(deps, chain)?),
26        QueryMsg::Ownership {} => to_json_binary(&cw_ownable::get_ownership(deps.storage)?),
27        QueryMsg::ModuleQuery { target_module, msg } => {
28            return packet::handle_host_module_query(deps, env, target_module, msg);
29        }
30    }
31    .map_err(Into::into)
32}
33
34fn config(deps: Deps, env: &Env) -> HostResult<ConfigResponse> {
35    let abstract_code_id =
36        native_addrs::abstract_code_id(&deps.querier, env.contract.address.clone())?;
37
38    Ok(ConfigResponse {
39        ans_host_address: AnsHost::new(deps, abstract_code_id)?.address,
40        module_factory_address: ModuleFactoryContract::new(deps, abstract_code_id)?.address,
41        registry_address: RegistryContract::new(deps, abstract_code_id)?.address,
42    })
43}
44
45fn registered_chains(
46    deps: Deps,
47    start_after: Option<String>,
48    limit: Option<u32>,
49) -> HostResult<ClientProxiesResponse> {
50    let start = start_after.map(TruncatedChainId::from_string).transpose()?;
51
52    let chains = cw_paginate::paginate_map(
53        &CHAIN_PROXIES,
54        deps.storage,
55        start.as_ref().map(Bound::exclusive),
56        limit,
57        |name, proxy| Ok::<_, HostError>((name, proxy)),
58    )?;
59
60    Ok(ClientProxiesResponse { chains })
61}
62
63fn associated_client(deps: Deps, chain: String) -> HostResult<ClientProxyResponse> {
64    let proxy = CHAIN_PROXIES.load(deps.storage, &TruncatedChainId::from_str(&chain)?)?;
65    Ok(ClientProxyResponse { proxy })
66}
67
68#[cfg(test)]
69mod test {
70    #![allow(clippy::needless_borrows_for_generic_args)]
71
72    use abstract_testing::mock_env_validated;
73
74    #[coverage_helper::test]
75    fn test_registered_client() {
76        use abstract_std::ibc_host::{ClientProxyResponse, InstantiateMsg, QueryMsg};
77        use cosmwasm_std::{from_json, testing::*};
78
79        use crate::contract::{execute, instantiate, query};
80        // Instantiate
81        let mut deps = mock_dependencies();
82        let info = message_info(&deps.api.addr_make("admin"), &[]);
83        let env = mock_env_validated(deps.api);
84        instantiate(deps.as_mut(), env.clone(), info.clone(), InstantiateMsg {}).unwrap();
85
86        // Register
87        let proxy = deps.api.addr_make("juno-proxy");
88        execute(
89            deps.as_mut(),
90            env.clone(),
91            info,
92            abstract_std::ibc_host::ExecuteMsg::RegisterChainProxy {
93                chain: "juno".parse().unwrap(),
94                proxy: proxy.to_string(),
95            },
96        )
97        .unwrap();
98
99        // Query
100        let client_name = query(
101            deps.as_ref(),
102            env,
103            QueryMsg::ClientProxy {
104                chain: "juno".to_string(),
105            },
106        )
107        .unwrap();
108        let queried_client_name: ClientProxyResponse = from_json(client_name).unwrap();
109        assert_eq!(queried_client_name.proxy, proxy);
110    }
111}