cw_ica_controller/ibc/
relay.rs1use cosmwasm_std::entry_point;
7use cosmwasm_std::{
8 from_json, DepsMut, Env, IbcBasicResponse, IbcPacketAckMsg, IbcPacketReceiveMsg,
9 IbcPacketTimeoutMsg, IbcReceiveResponse, Never,
10};
11
12use crate::types::{query_msg, state, ContractError};
13
14use super::types::{events, packet::acknowledgement::Data as AcknowledgementData};
15
16#[entry_point]
25#[allow(clippy::needless_pass_by_value)]
26pub fn ibc_packet_ack(
27 deps: DepsMut,
28 _env: Env,
29 ack: IbcPacketAckMsg,
30) -> Result<IbcBasicResponse, ContractError> {
31 match from_json(&ack.acknowledgement.data)? {
33 AcknowledgementData::Result(res) => {
34 ibc_packet_ack::success(deps, ack.original_packet, ack.relayer, res)
35 }
36 AcknowledgementData::Error(err) => {
37 ibc_packet_ack::error(deps, ack.original_packet, ack.relayer, err)
38 }
39 }
40}
41
42#[entry_point]
51#[allow(clippy::needless_pass_by_value)]
52pub fn ibc_packet_timeout(
53 deps: DepsMut,
54 _env: Env,
55 msg: IbcPacketTimeoutMsg,
56) -> Result<IbcBasicResponse, ContractError> {
57 let mut channel_state = state::CHANNEL_STATE.load(deps.storage)?;
59 if channel_state.is_ordered() {
60 channel_state.close();
61 state::CHANNEL_STATE.save(deps.storage, &channel_state)?;
62 }
63
64 ibc_packet_timeout::callback(deps, msg.packet, msg.relayer)
65}
66
67#[entry_point]
72#[allow(clippy::needless_pass_by_value, clippy::missing_errors_doc)]
73pub fn ibc_packet_receive(
74 _deps: DepsMut,
75 _env: Env,
76 _msg: IbcPacketReceiveMsg,
77) -> Result<IbcReceiveResponse, Never> {
78 unreachable!("ICA controller cannot receive packets")
81}
82
83mod ibc_packet_ack {
84 use cosmwasm_std::{Addr, Binary, IbcPacket};
85
86 use crate::types::callbacks::IcaControllerCallbackMsg;
87
88 use super::{
89 events, query_msg, state, AcknowledgementData, ContractError, DepsMut, IbcBasicResponse,
90 };
91
92 #[allow(clippy::needless_pass_by_value)]
95 pub fn success(
96 deps: DepsMut,
97 packet: IbcPacket,
98 relayer: Addr,
99 res: Binary,
100 ) -> Result<IbcBasicResponse, ContractError> {
101 let success_event = events::packet_ack::success(&packet, &res);
102 let ica_acknowledgement = AcknowledgementData::Result(res);
103 let query_result = state::PENDING_QUERIES
104 .may_load(deps.storage, (&packet.src.channel_id, packet.sequence))?
105 .map(
106 |paths| -> Result<query_msg::IcaQueryResult, ContractError> {
107 let resp_msg =
108 ica_acknowledgement.decode_module_query_safe_resp_last_index()?;
109 Ok(query_msg::result_from_response(paths, &resp_msg))
110 },
111 )
112 .transpose()?;
113
114 state::PENDING_QUERIES.remove(deps.storage, (&packet.src.channel_id, packet.sequence));
115
116 if let Some(contract_addr) = state::STATE.load(deps.storage)?.callback_address {
117 let callback_msg = IcaControllerCallbackMsg::OnAcknowledgementPacketCallback {
118 ica_acknowledgement,
119 original_packet: packet,
120 relayer,
121 query_result,
122 }
123 .into_cosmos_msg(contract_addr)?;
124
125 Ok(IbcBasicResponse::default()
126 .add_message(callback_msg)
127 .add_event(success_event))
128 } else {
129 Ok(IbcBasicResponse::default().add_event(success_event))
130 }
131 }
132
133 #[allow(clippy::needless_pass_by_value)]
136 pub fn error(
137 deps: DepsMut,
138 packet: IbcPacket,
139 relayer: Addr,
140 err: String,
141 ) -> Result<IbcBasicResponse, ContractError> {
142 let state = state::STATE.load(deps.storage)?;
143 let error_event = events::packet_ack::error(&packet, &err);
144
145 if let Some(contract_addr) = state.callback_address {
146 let callback_msg = IcaControllerCallbackMsg::OnAcknowledgementPacketCallback {
147 ica_acknowledgement: AcknowledgementData::Error(err.clone()),
148 original_packet: packet,
149 relayer,
150 query_result: Some(query_msg::IcaQueryResult::Error(err)),
151 }
152 .into_cosmos_msg(contract_addr)?;
153
154 Ok(IbcBasicResponse::default()
155 .add_message(callback_msg)
156 .add_event(error_event))
157 } else {
158 Ok(IbcBasicResponse::default().add_event(error_event))
159 }
160 }
161}
162
163mod ibc_packet_timeout {
164 use cosmwasm_std::{Addr, IbcPacket};
165
166 use crate::types::{callbacks::IcaControllerCallbackMsg, state};
167
168 use super::{ContractError, DepsMut, IbcBasicResponse};
169
170 #[allow(clippy::needless_pass_by_value)]
172 pub fn callback(
173 deps: DepsMut,
174 packet: IbcPacket,
175 relayer: Addr,
176 ) -> Result<IbcBasicResponse, ContractError> {
177 let state = state::STATE.load(deps.storage)?;
178
179 state::PENDING_QUERIES.remove(deps.storage, (&packet.src.channel_id, packet.sequence));
180
181 if let Some(contract_addr) = state.callback_address {
182 let callback_msg = IcaControllerCallbackMsg::OnTimeoutPacketCallback {
183 original_packet: packet,
184 relayer,
185 }
186 .into_cosmos_msg(contract_addr)?;
187
188 Ok(IbcBasicResponse::default().add_message(callback_msg))
189 } else {
190 Ok(IbcBasicResponse::default())
191 }
192 }
193}