abstract_ibc_host/endpoints/
packet.rs1use abstract_sdk::feature_objects::RegistryContract;
2use abstract_std::{
3 base::ExecuteMsg as MiddlewareExecMsg,
4 ibc::{ModuleIbcInfo, ModuleIbcMsg},
5 ibc_client::InstalledModuleIdentification,
6 ibc_host::{
7 state::{ActionAfterCreationCache, TEMP_ACTION_AFTER_CREATION},
8 HelperAction, HostAction, InternalAction,
9 },
10 native_addrs,
11 objects::{
12 account::AccountTrace, module::ModuleInfo, module_reference::ModuleReference, AccountId,
13 TruncatedChainId,
14 },
15};
16use cosmwasm_std::{
17 to_json_vec, wasm_execute, Binary, ContractResult, Deps, DepsMut, Empty, Env, QueryRequest,
18 Response, StdError, SystemResult, WasmQuery,
19};
20
21use crate::{
22 account_commands::{self, receive_dispatch, receive_register, receive_send_all_back},
23 contract::HostResult,
24 HostError,
25};
26
27pub fn handle_host_action(
31 deps: DepsMut,
32 env: Env,
33 src_chain: TruncatedChainId,
34 account_address: String,
35 received_account_id: AccountId,
36 host_action: HostAction,
37) -> HostResult {
38 let account_id = {
40 let mut account_id = received_account_id.clone();
41 account_id.push_chain(src_chain.clone());
42 account_id
43 };
44
45 match host_action {
47 HostAction::Internal(InternalAction::Register {
48 description,
49 link,
50 name,
51 namespace,
52 install_modules,
53 }) => receive_register(
54 deps,
55 env,
56 account_id,
57 name,
58 description,
59 link,
60 namespace,
61 install_modules,
62 false,
63 vec![],
64 ),
65
66 action => {
67 if let Ok(account) = account_commands::get_account(deps.as_ref(), &env, &account_id) {
69 match action {
70 HostAction::Dispatch { account_msgs } => {
71 receive_dispatch(deps, account, account_msgs)
72 }
73 HostAction::Helpers(helper_action) => match helper_action {
74 HelperAction::SendAllBack => {
75 receive_send_all_back(deps, env, account, account_address, src_chain)
76 }
77 _ => unimplemented!(""),
78 },
79 HostAction::Internal(InternalAction::Register { .. }) => {
80 unreachable!("This action is handled above")
81 }
82 _ => unimplemented!(""),
83 }
84 } else {
85 let name = format!(
89 "Remote Abstract Account for {}/{}",
90 src_chain.as_str(),
91 account_id
92 );
93
94 TEMP_ACTION_AFTER_CREATION.save(
96 deps.storage,
97 &ActionAfterCreationCache {
98 action,
99 client_account_address: account_address,
100 account_id: received_account_id,
101 chain_name: src_chain,
102 },
103 )?;
104 receive_register(
105 deps,
106 env,
107 account_id,
108 Some(name),
109 None,
110 None,
111 None,
112 vec![],
113 true,
114 vec![],
115 )
116 }
117 }
118 }
119 .map_err(Into::into)
120}
121
122pub fn handle_module_execute(
124 deps: DepsMut,
125 env: Env,
126 src_chain: TruncatedChainId,
127 source_module: InstalledModuleIdentification,
128 target_module: ModuleInfo,
129 msg: Binary,
130) -> HostResult {
131 let abstract_code_id =
133 native_addrs::abstract_code_id(&deps.querier, env.contract.address.clone())?;
134
135 let registry = RegistryContract::new(deps.as_ref(), abstract_code_id)?;
136
137 let target_module = InstalledModuleIdentification {
138 module_info: target_module,
139 account_id: source_module
142 .account_id
143 .map(|a| client_to_host_module_account_id(&env, src_chain.clone(), a)),
144 };
145
146 let target_module_resolved = target_module.addr(deps.as_ref(), registry)?;
147
148 match target_module_resolved.reference {
149 ModuleReference::Account(_) | ModuleReference::Native(_) | ModuleReference::Service(_) => {
150 return Err(HostError::WrongModuleAction(
151 "Can't send module-to-module message to an account, service or a native module"
152 .to_string(),
153 ))
154 }
155 _ => {}
156 }
157
158 let response = Response::new().add_attribute("action", "module-ibc-call");
159 let msg = wasm_execute(
161 target_module_resolved.address,
162 &MiddlewareExecMsg::ModuleIbc::<Empty, Empty>(ModuleIbcMsg {
163 src_module_info: ModuleIbcInfo {
164 chain: src_chain,
165 module: source_module.module_info,
166 },
167 msg,
168 }),
169 vec![],
170 )?;
171
172 Ok(response.add_message(msg))
173}
174
175pub fn handle_host_module_query(
177 deps: Deps,
178 env: Env,
179 target_module: InstalledModuleIdentification,
180 msg: Binary,
181) -> HostResult<Binary> {
182 let abstract_code_id =
184 native_addrs::abstract_code_id(&deps.querier, env.contract.address.clone())?;
185
186 let registry = RegistryContract::new(deps, abstract_code_id)?;
187
188 let target_module_resolved = target_module.addr(deps, registry)?;
189
190 let query = QueryRequest::<Empty>::from(WasmQuery::Smart {
191 contract_addr: target_module_resolved.address.into_string(),
192 msg,
193 });
194 let bin = match deps.querier.raw_query(&to_json_vec(&query)?) {
195 SystemResult::Err(system_err) => Err(StdError::generic_err(format!(
196 "Querier system error: {system_err}"
197 ))),
198 SystemResult::Ok(ContractResult::Err(contract_err)) => Err(StdError::generic_err(format!(
199 "Querier contract error: {contract_err}"
200 ))),
201 SystemResult::Ok(ContractResult::Ok(value)) => Ok(value),
202 }?;
203 Ok(bin)
204}
205
206pub fn client_to_host_module_account_id(
208 env: &Env,
209 remote_chain: TruncatedChainId,
210 mut account_id: AccountId,
211) -> AccountId {
212 let account_trace = account_id.trace_mut();
213 match account_trace {
214 AccountTrace::Local => account_trace.push_chain(remote_chain),
215 AccountTrace::Remote(trace) => {
216 let current_chain_name = TruncatedChainId::from_chain_id(&env.block.chain_id);
217 if current_chain_name.eq(trace.last().unwrap()) {
219 trace.pop();
220 if trace.is_empty() {
221 *account_trace = AccountTrace::Local;
222 }
223 } else {
224 trace.push(remote_chain);
225 }
226 }
227 };
228 account_id
229}