cosmwasm_std/
ibc2.rs

1use schemars::JsonSchema;
2use serde::{Deserialize, Serialize};
3
4use crate::{Addr, Binary, IbcAcknowledgement, Timestamp};
5
6/// Payload value should be encoded in a format defined by the channel version,
7/// and the module on the other side should know how to parse this.
8#[non_exhaustive]
9#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
10#[serde(rename_all = "snake_case")]
11pub struct Ibc2Payload {
12    /// The port id on the chain where the packet is sent from.
13    pub source_port: String,
14    /// The port id on the chain where the packet is sent to.
15    pub destination_port: String,
16    /// Version of the receiving contract.
17    pub version: String,
18    /// Encoding used to serialize the [Ibc2Payload::value].
19    pub encoding: String,
20    /// Encoded payload data.
21    pub value: Binary,
22}
23
24impl Ibc2Payload {
25    pub fn new(
26        source_port: String,
27        destination_port: String,
28        version: String,
29        encoding: String,
30        value: Binary,
31    ) -> Self {
32        Self {
33            source_port,
34            destination_port,
35            version,
36            encoding,
37            value,
38        }
39    }
40}
41
42/// These are messages in the IBC lifecycle using the new Ibc2 approach.
43/// Only usable by Ibc2-enabled contracts
44#[non_exhaustive]
45#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
46#[serde(rename_all = "snake_case")]
47pub enum Ibc2Msg {
48    /// Sends an Ibc2 packet with given payloads over the existing channel.
49    SendPacket {
50        source_client: String,
51        timeout: Timestamp,
52        payloads: Vec<Ibc2Payload>,
53    },
54    /// Acknowledges a packet that this contract received over IBC.
55    /// This allows acknowledging a packet that was not acknowledged yet in the `ibc2_packet_receive` call.
56    WriteAcknowledgement {
57        /// Existing channel where the packet was received
58        source_client: String,
59        /// Sequence number of the packet that was received
60        packet_sequence: u64,
61        /// The acknowledgement to send back
62        ack: IbcAcknowledgement,
63    },
64}
65
66/// IBC2PacketReceiveMsg represents a message received via the IBC2 protocol.
67/// The message that is passed into `ibc2_packet_receive`.
68/// It contains the payload data along with metadata about the source and relayer.
69#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
70#[non_exhaustive]
71pub struct Ibc2PacketReceiveMsg {
72    /// The actual data being transmitted via IBC2.
73    pub payload: Ibc2Payload,
74    /// The address of the entity that relayed the packet.
75    pub relayer: Addr,
76    /// The identifier of the source IBC client.
77    pub source_client: String,
78    /// The unique sequence number of the received packet.
79    pub packet_sequence: u64,
80}
81
82impl Ibc2PacketReceiveMsg {
83    pub fn new(
84        payload: Ibc2Payload,
85        relayer: Addr,
86        source_client: String,
87        packet_sequence: u64,
88    ) -> Self {
89        Self {
90            payload,
91            relayer,
92            source_client,
93            packet_sequence,
94        }
95    }
96}
97
98/// IBC2PacketTimeoutMsg represents a timeout event for a packet that was not
99/// successfully delivered within the expected timeframe in the IBC2 protocol.
100/// It includes details about the source and destination clients, and the sequence
101/// number of the timed-out packet.
102#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
103#[non_exhaustive]
104pub struct Ibc2PacketTimeoutMsg {
105    /// The data associated with the timed-out packet.
106    pub payload: Ibc2Payload,
107    /// The identifier of the client that originally sent the packet.
108    pub source_client: String,
109    /// The identifier of the client that was the intended recipient.
110    pub destination_client: String,
111    /// The sequence number of the timed-out packet.
112    pub packet_sequence: u64,
113    /// The address of the relayer responsible for the packet.
114    pub relayer: Addr,
115}
116
117impl Ibc2PacketTimeoutMsg {
118    pub fn new(
119        payload: Ibc2Payload,
120        source_client: String,
121        destination_client: String,
122        packet_sequence: u64,
123        relayer: Addr,
124    ) -> Self {
125        Self {
126            payload,
127            source_client,
128            destination_client,
129            packet_sequence,
130            relayer,
131        }
132    }
133}
134
135/// Message sent to the IBCv2 app upon receiving an acknowledgement packet
136#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
137#[non_exhaustive]
138pub struct Ibc2PacketAckMsg {
139    pub source_client: String,
140    pub destination_client: String,
141    pub data: Ibc2Payload,
142    pub acknowledgement: Binary,
143    pub relayer: Addr,
144}
145
146impl Ibc2PacketAckMsg {
147    pub fn new(
148        source_client: String,
149        destination_client: String,
150        data: Ibc2Payload,
151        acknowledgement: Binary,
152        relayer: Addr,
153    ) -> Self {
154        Self {
155            source_client,
156            destination_client,
157            data,
158            acknowledgement,
159            relayer,
160        }
161    }
162}
163
164/// Ibc2PacketSendMsg represents a payload sent event in the IBC2 protocol.
165/// Since sending IBCv2 packet is permissionless, the IBC protocol introduces
166/// an extra entry point, in which the application can verify the message sent from
167/// a port ID belonging to the contract.
168///
169/// It includes details about the source and destination clients, the sequence
170/// number of the packet and the signer that sent the message.
171#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
172#[non_exhaustive]
173pub struct Ibc2PacketSendMsg {
174    /// The payload to be sent.
175    pub payload: Ibc2Payload,
176    /// The identifier of the client that originally sent the packet.
177    pub source_client: String,
178    /// The identifier of the client that was the intended recipient.
179    pub destination_client: String,
180    /// The sequence number of the sent packet.
181    pub packet_sequence: u64,
182    /// The address of the signer that sent the packet.
183    pub signer: Addr,
184}
185
186impl Ibc2PacketSendMsg {
187    pub fn new(
188        payload: Ibc2Payload,
189        source_client: String,
190        destination_client: String,
191        packet_sequence: u64,
192        signer: Addr,
193    ) -> Self {
194        Self {
195            payload,
196            source_client,
197            destination_client,
198            packet_sequence,
199            signer,
200        }
201    }
202}
203
204#[cfg(test)]
205mod tests {
206    use serde_json::to_string;
207
208    use crate::Ibc2Payload;
209
210    #[test]
211    fn ibc2_payload_serialize() {
212        let packet = Ibc2Payload {
213            source_port: "sending-contractr-port".to_string(),
214            destination_port: "receiving-contract-port".to_string(),
215            version: "v1".to_string(),
216            encoding: "json".to_string(),
217            value: b"foo".into(),
218        };
219        let expected = r#"{"source_port":"sending-contractr-port","destination_port":"receiving-contract-port","version":"v1","encoding":"json","value":"Zm9v"}"#;
220        assert_eq!(to_string(&packet).unwrap(), expected);
221    }
222}