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        /// Sequence number of the packet that was received
64        packet_sequence: u64,
65        /// The acknowledgement to send back
66        ack: IbcAcknowledgement,
67    },
68}
69
70/// IBC2PacketReceiveMsg represents a message received via the IBC2 protocol.
71/// The message that is passed into `ibc2_packet_receive`.
72/// It contains the payload data along with metadata about the source and relayer.
73#[derive(
74    Serialize, Deserialize, Clone, Debug, PartialEq, Eq, cw_schema::Schemaifier, JsonSchema,
75)]
76#[non_exhaustive]
77pub struct Ibc2PacketReceiveMsg {
78    /// The actual data being transmitted via IBC2.
79    pub payload: Ibc2Payload,
80    /// The address of the entity that relayed the packet.
81    pub relayer: Addr,
82    /// The identifier of the source IBC client.
83    pub source_client: String,
84    /// The unique sequence number of the received packet.
85    pub packet_sequence: u64,
86}
87
88impl Ibc2PacketReceiveMsg {
89    pub fn new(
90        payload: Ibc2Payload,
91        relayer: Addr,
92        source_client: String,
93        packet_sequence: u64,
94    ) -> Self {
95        Self {
96            payload,
97            relayer,
98            source_client,
99            packet_sequence,
100        }
101    }
102}
103
104/// IBC2PacketTimeoutMsg represents a timeout event for a packet that was not
105/// successfully delivered within the expected timeframe in the IBC2 protocol.
106/// It includes details about the source and destination clients, and the sequence
107/// number of the timed-out packet.
108#[derive(
109    Serialize, Deserialize, Clone, Debug, PartialEq, Eq, cw_schema::Schemaifier, JsonSchema,
110)]
111#[non_exhaustive]
112pub struct Ibc2PacketTimeoutMsg {
113    /// The data associated with the timed-out packet.
114    pub payload: Ibc2Payload,
115    /// The identifier of the client that originally sent the packet.
116    pub source_client: String,
117    /// The identifier of the client that was the intended recipient.
118    pub destination_client: String,
119    /// The sequence number of the timed-out packet.
120    pub packet_sequence: u64,
121    /// The address of the relayer responsible for the packet.
122    pub relayer: Addr,
123}
124
125impl Ibc2PacketTimeoutMsg {
126    pub fn new(
127        payload: Ibc2Payload,
128        source_client: String,
129        destination_client: String,
130        packet_sequence: u64,
131        relayer: Addr,
132    ) -> Self {
133        Self {
134            payload,
135            source_client,
136            destination_client,
137            packet_sequence,
138            relayer,
139        }
140    }
141}
142
143/// Message sent to the IBCv2 app upon receiving an acknowledgement packet
144#[derive(
145    Serialize, Deserialize, Clone, Debug, PartialEq, Eq, cw_schema::Schemaifier, JsonSchema,
146)]
147#[non_exhaustive]
148pub struct Ibc2PacketAckMsg {
149    pub source_client: String,
150    pub destination_client: String,
151    pub data: Ibc2Payload,
152    pub acknowledgement: Binary,
153    pub relayer: Addr,
154}
155
156impl Ibc2PacketAckMsg {
157    pub fn new(
158        source_client: String,
159        destination_client: String,
160        data: Ibc2Payload,
161        acknowledgement: Binary,
162        relayer: Addr,
163    ) -> Self {
164        Self {
165            source_client,
166            destination_client,
167            data,
168            acknowledgement,
169            relayer,
170        }
171    }
172}
173
174/// Ibc2PacketSendMsg represents a payload sent event in the IBC2 protocol.
175/// Since sending IBCv2 packet is permissionless, the IBC protocol introduces
176/// an extra entry point, in which the application can verify the message sent from
177/// a port ID belonging to the contract.
178///
179/// It includes details about the source and destination clients, the sequence
180/// number of the packet and the signer that sent the message.
181#[derive(
182    Serialize, Deserialize, Clone, Debug, PartialEq, Eq, cw_schema::Schemaifier, JsonSchema,
183)]
184#[non_exhaustive]
185pub struct Ibc2PacketSendMsg {
186    /// The payload to be sent.
187    pub payload: Ibc2Payload,
188    /// The identifier of the client that originally sent the packet.
189    pub source_client: String,
190    /// The identifier of the client that was the intended recipient.
191    pub destination_client: String,
192    /// The sequence number of the sent packet.
193    pub packet_sequence: u64,
194    /// The address of the signer that sent the packet.
195    pub signer: Addr,
196}
197
198impl Ibc2PacketSendMsg {
199    pub fn new(
200        payload: Ibc2Payload,
201        source_client: String,
202        destination_client: String,
203        packet_sequence: u64,
204        signer: Addr,
205    ) -> Self {
206        Self {
207            payload,
208            source_client,
209            destination_client,
210            packet_sequence,
211            signer,
212        }
213    }
214}
215
216#[cfg(test)]
217mod tests {
218    use serde_json::to_string;
219
220    use crate::Ibc2Payload;
221
222    #[test]
223    fn ibc2_payload_serialize() {
224        let packet = Ibc2Payload {
225            source_port: "sending-contractr-port".to_string(),
226            destination_port: "receiving-contract-port".to_string(),
227            version: "v1".to_string(),
228            encoding: "json".to_string(),
229            value: b"foo".into(),
230        };
231        let expected = r#"{"source_port":"sending-contractr-port","destination_port":"receiving-contract-port","version":"v1","encoding":"json","value":"Zm9v"}"#;
232        assert_eq!(to_string(&packet).unwrap(), expected);
233    }
234}