1use ibc_app_transfer_types::error::TokenTransferError;
2use ibc_app_transfer_types::events::{AckEvent, AckStatusEvent, RecvEvent, TimeoutEvent};
3use ibc_app_transfer_types::packet::PacketData;
4use ibc_app_transfer_types::{ack_success_b64, VERSION};
5use ibc_core::channel::types::acknowledgement::{Acknowledgement, AcknowledgementStatus};
6use ibc_core::channel::types::channel::{Counterparty, Order};
7use ibc_core::channel::types::packet::Packet;
8use ibc_core::channel::types::Version;
9use ibc_core::host::types::identifiers::{ChannelId, ConnectionId, PortId};
10use ibc_core::primitives::prelude::*;
11use ibc_core::primitives::Signer;
12use ibc_core::router::types::module::ModuleExtras;
13
14use crate::context::{TokenTransferExecutionContext, TokenTransferValidationContext};
15use crate::handler::{
16 process_recv_packet_execute, refund_packet_token_execute, refund_packet_token_validate,
17};
18
19pub fn on_chan_open_init_validate(
20 ctx: &impl TokenTransferValidationContext,
21 order: Order,
22 _connection_hops: &[ConnectionId],
23 port_id: &PortId,
24 _channel_id: &ChannelId,
25 _counterparty: &Counterparty,
26 version: &Version,
27) -> Result<(), TokenTransferError> {
28 if order != Order::Unordered {
29 return Err(TokenTransferError::MismatchedChannelOrders {
30 expected: Order::Unordered,
31 actual: order,
32 });
33 }
34 let bound_port = ctx.get_port()?;
35 if port_id != &bound_port {
36 return Err(TokenTransferError::MismatchedPortIds {
37 actual: port_id.clone(),
38 expected: bound_port,
39 });
40 }
41
42 if !version.is_empty() {
43 version.verify_is_expected(Version::new(VERSION.to_string()))?;
44 }
45
46 Ok(())
47}
48
49pub fn on_chan_open_init_execute(
50 _ctx: &mut impl TokenTransferExecutionContext,
51 _order: Order,
52 _connection_hops: &[ConnectionId],
53 _port_id: &PortId,
54 _channel_id: &ChannelId,
55 _counterparty: &Counterparty,
56 _version: &Version,
57) -> Result<(ModuleExtras, Version), TokenTransferError> {
58 Ok((ModuleExtras::empty(), Version::new(VERSION.to_string())))
59}
60
61pub fn on_chan_open_try_validate(
62 _ctx: &impl TokenTransferValidationContext,
63 order: Order,
64 _connection_hops: &[ConnectionId],
65 _port_id: &PortId,
66 _channel_id: &ChannelId,
67 _counterparty: &Counterparty,
68 counterparty_version: &Version,
69) -> Result<(), TokenTransferError> {
70 if order != Order::Unordered {
71 return Err(TokenTransferError::MismatchedChannelOrders {
72 expected: Order::Unordered,
73 actual: order,
74 });
75 }
76
77 counterparty_version.verify_is_expected(Version::new(VERSION.to_string()))?;
78
79 Ok(())
80}
81
82pub fn on_chan_open_try_execute(
83 _ctx: &mut impl TokenTransferExecutionContext,
84 _order: Order,
85 _connection_hops: &[ConnectionId],
86 _port_id: &PortId,
87 _channel_id: &ChannelId,
88 _counterparty: &Counterparty,
89 _counterparty_version: &Version,
90) -> Result<(ModuleExtras, Version), TokenTransferError> {
91 Ok((ModuleExtras::empty(), Version::new(VERSION.to_string())))
92}
93
94pub fn on_chan_open_ack_validate(
95 _ctx: &impl TokenTransferValidationContext,
96 _port_id: &PortId,
97 _channel_id: &ChannelId,
98 counterparty_version: &Version,
99) -> Result<(), TokenTransferError> {
100 counterparty_version.verify_is_expected(Version::new(VERSION.to_string()))?;
101
102 Ok(())
103}
104
105pub fn on_chan_open_ack_execute(
106 _ctx: &mut impl TokenTransferExecutionContext,
107 _port_id: &PortId,
108 _channel_id: &ChannelId,
109 _counterparty_version: &Version,
110) -> Result<ModuleExtras, TokenTransferError> {
111 Ok(ModuleExtras::empty())
112}
113
114pub fn on_chan_open_confirm_validate(
115 _ctx: &impl TokenTransferValidationContext,
116 _port_id: &PortId,
117 _channel_id: &ChannelId,
118) -> Result<(), TokenTransferError> {
119 Ok(())
120}
121
122pub fn on_chan_open_confirm_execute(
123 _ctx: &mut impl TokenTransferExecutionContext,
124 _port_id: &PortId,
125 _channel_id: &ChannelId,
126) -> Result<ModuleExtras, TokenTransferError> {
127 Ok(ModuleExtras::empty())
128}
129
130pub fn on_chan_close_init_validate(
131 _ctx: &impl TokenTransferValidationContext,
132 _port_id: &PortId,
133 _channel_id: &ChannelId,
134) -> Result<(), TokenTransferError> {
135 Err(TokenTransferError::InvalidClosedChannel)
136}
137
138pub fn on_chan_close_init_execute(
139 _ctx: &mut impl TokenTransferExecutionContext,
140 _port_id: &PortId,
141 _channel_id: &ChannelId,
142) -> Result<ModuleExtras, TokenTransferError> {
143 Err(TokenTransferError::InvalidClosedChannel)
144}
145
146pub fn on_chan_close_confirm_validate(
147 _ctx: &impl TokenTransferValidationContext,
148 _port_id: &PortId,
149 _channel_id: &ChannelId,
150) -> Result<(), TokenTransferError> {
151 Ok(())
152}
153
154pub fn on_chan_close_confirm_execute(
155 _ctx: &mut impl TokenTransferExecutionContext,
156 _port_id: &PortId,
157 _channel_id: &ChannelId,
158) -> Result<ModuleExtras, TokenTransferError> {
159 Ok(ModuleExtras::empty())
160}
161
162pub fn on_recv_packet_execute(
163 ctx_b: &mut impl TokenTransferExecutionContext,
164 packet: &Packet,
165) -> (ModuleExtras, Acknowledgement) {
166 let Ok(data) = serde_json::from_slice::<PacketData>(&packet.data) else {
167 let ack =
168 AcknowledgementStatus::error(TokenTransferError::FailedToDeserializePacketData.into());
169 return (ModuleExtras::empty(), ack.into());
170 };
171
172 let (mut extras, ack) = match process_recv_packet_execute(ctx_b, packet, data.clone()) {
173 Ok(extras) => (extras, AcknowledgementStatus::success(ack_success_b64())),
174 Err((extras, error)) => (extras, AcknowledgementStatus::error(error.into())),
175 };
176
177 let recv_event = RecvEvent {
178 sender: data.sender,
179 receiver: data.receiver,
180 denom: data.token.denom,
181 amount: data.token.amount,
182 memo: data.memo,
183 success: ack.is_successful(),
184 };
185 extras.events.push(recv_event.into());
186
187 (extras, ack.into())
188}
189
190pub fn on_acknowledgement_packet_validate<Ctx>(
191 ctx: &Ctx,
192 packet: &Packet,
193 acknowledgement: &Acknowledgement,
194 _relayer: &Signer,
195) -> Result<(), TokenTransferError>
196where
197 Ctx: TokenTransferValidationContext,
198{
199 let data = serde_json::from_slice::<PacketData>(&packet.data)
200 .map_err(|_| TokenTransferError::FailedToDeserializePacketData)?;
201
202 let acknowledgement = serde_json::from_slice::<AcknowledgementStatus>(acknowledgement.as_ref())
203 .map_err(|_| TokenTransferError::FailedToDeserializeAck)?;
204
205 if !acknowledgement.is_successful() {
206 refund_packet_token_validate(ctx, packet, &data)?;
207 }
208
209 Ok(())
210}
211
212pub fn on_acknowledgement_packet_execute(
213 ctx: &mut impl TokenTransferExecutionContext,
214 packet: &Packet,
215 acknowledgement: &Acknowledgement,
216 _relayer: &Signer,
217) -> (ModuleExtras, Result<(), TokenTransferError>) {
218 let Ok(data) = serde_json::from_slice::<PacketData>(&packet.data) else {
219 return (
220 ModuleExtras::empty(),
221 Err(TokenTransferError::FailedToDeserializePacketData),
222 );
223 };
224
225 let Ok(acknowledgement) =
226 serde_json::from_slice::<AcknowledgementStatus>(acknowledgement.as_ref())
227 else {
228 return (
229 ModuleExtras::empty(),
230 Err(TokenTransferError::FailedToDeserializeAck),
231 );
232 };
233
234 if !acknowledgement.is_successful() {
235 if let Err(err) = refund_packet_token_execute(ctx, packet, &data) {
236 return (ModuleExtras::empty(), Err(err));
237 }
238 }
239
240 let ack_event = AckEvent {
241 sender: data.sender,
242 receiver: data.receiver,
243 denom: data.token.denom,
244 amount: data.token.amount,
245 memo: data.memo,
246 acknowledgement: acknowledgement.clone(),
247 };
248
249 let extras = ModuleExtras {
250 events: vec![ack_event.into(), AckStatusEvent { acknowledgement }.into()],
251 log: Vec::new(),
252 };
253
254 (extras, Ok(()))
255}
256
257pub fn on_timeout_packet_validate<Ctx>(
258 ctx: &Ctx,
259 packet: &Packet,
260 _relayer: &Signer,
261) -> Result<(), TokenTransferError>
262where
263 Ctx: TokenTransferValidationContext,
264{
265 let data = serde_json::from_slice::<PacketData>(&packet.data)
266 .map_err(|_| TokenTransferError::FailedToDeserializePacketData)?;
267
268 refund_packet_token_validate(ctx, packet, &data)?;
269
270 Ok(())
271}
272
273pub fn on_timeout_packet_execute(
274 ctx: &mut impl TokenTransferExecutionContext,
275 packet: &Packet,
276 _relayer: &Signer,
277) -> (ModuleExtras, Result<(), TokenTransferError>) {
278 let Ok(data) = serde_json::from_slice::<PacketData>(&packet.data) else {
279 return (
280 ModuleExtras::empty(),
281 Err(TokenTransferError::FailedToDeserializePacketData),
282 );
283 };
284
285 if let Err(err) = refund_packet_token_execute(ctx, packet, &data) {
286 return (ModuleExtras::empty(), Err(err));
287 }
288
289 let timeout_event = TimeoutEvent {
290 refund_receiver: data.sender,
291 refund_denom: data.token.denom,
292 refund_amount: data.token.amount,
293 memo: data.memo,
294 };
295
296 let extras = ModuleExtras {
297 events: vec![timeout_event.into()],
298 log: Vec::new(),
299 };
300
301 (extras, Ok(()))
302}
303
304#[cfg(test)]
305mod test {
306 use super::*;
307
308 #[test]
309 fn test_ack_ser() {
310 fn ser_json_assert_eq(ack: AcknowledgementStatus, json_str: &str) {
311 let ser = serde_json::to_string(&ack).unwrap();
312 assert_eq!(ser, json_str)
313 }
314
315 ser_json_assert_eq(
316 AcknowledgementStatus::success(ack_success_b64()),
317 r#"{"result":"AQ=="}"#,
318 );
319 ser_json_assert_eq(
320 AcknowledgementStatus::error(TokenTransferError::FailedToDeserializePacketData.into()),
321 r#"{"error":"failed to deserialize packet data"}"#,
322 );
323 }
324
325 #[test]
326 fn test_ack_success_to_vec() {
327 let ack_success: Vec<u8> = AcknowledgementStatus::success(ack_success_b64()).into();
328
329 assert_eq!(ack_success, br#"{"result":"AQ=="}"#);
333 }
334
335 #[test]
336 fn test_ack_error_to_vec() {
337 let ack_error: Vec<u8> =
338 AcknowledgementStatus::error(TokenTransferError::FailedToDeserializePacketData.into())
339 .into();
340
341 assert_eq!(
345 ack_error,
346 br#"{"error":"failed to deserialize packet data"}"#
347 );
348 }
349
350 #[test]
351 fn test_ack_de() {
352 fn de_json_assert_eq(json_str: &str, ack: AcknowledgementStatus) {
353 let de = serde_json::from_str::<AcknowledgementStatus>(json_str).unwrap();
354 assert_eq!(de, ack)
355 }
356
357 de_json_assert_eq(
358 r#"{"result":"AQ=="}"#,
359 AcknowledgementStatus::success(ack_success_b64()),
360 );
361 de_json_assert_eq(
362 r#"{"error":"failed to deserialize packet data"}"#,
363 AcknowledgementStatus::error(TokenTransferError::FailedToDeserializePacketData.into()),
364 );
365
366 assert!(serde_json::from_str::<AcknowledgementStatus>(r#"{"success":"AQ=="}"#).is_err());
367 }
368}