Skip to main content

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