cw_ica_controller/types/
state.rs

1//! This module defines the state storage of the Contract.
2
3use cosmwasm_schema::cw_serde;
4use cosmwasm_std::{Addr, IbcChannel};
5use cw_storage_plus::Item;
6
7use super::{msg::options::ChannelOpenInitOptions, ContractError};
8
9#[allow(clippy::module_name_repetitions)]
10pub use channel::{ChannelState, ChannelStatus};
11#[allow(clippy::module_name_repetitions)]
12pub use contract::State as ContractState;
13
14/// The item used to store the state of the IBC application.
15pub const STATE: Item<ContractState> = Item::new("state");
16
17/// The item used to store the state of the IBC application's channel.
18pub const CHANNEL_STATE: Item<ChannelState> = Item::new("ica_channel");
19
20/// The item used to store the channel open init options.
21pub const CHANNEL_OPEN_INIT_OPTIONS: Item<ChannelOpenInitOptions> =
22    Item::new("channel_open_init_options");
23
24/// The item used to store whether or not channel open init is allowed.
25/// Used to prevent relayers from opening channels. This right is reserved to the contract.
26pub const ALLOW_CHANNEL_OPEN_INIT: Item<bool> = Item::new("allow_channel_open_init");
27
28/// The item used to store whether or not channel close init is allowed.
29/// Used to prevent relayers from closing channels. This right is reserved to the contract.
30pub const ALLOW_CHANNEL_CLOSE_INIT: Item<bool> = Item::new("allow_channel_close_init");
31
32/// The item used to store the paths of an ICA query until its `SendPacket` response is received.
33/// Once the response is received, it is moved to the [`PENDING_QUERIES`] map and deleted from this item.
34/// This is used to ensure that the correct sequence is recorded for the response.
35#[cfg(feature = "query")]
36pub const QUERY: Item<Vec<(String, bool)>> = Item::new("pending_query");
37
38/// `PENDING_QUERIES` is the map of pending queries.
39/// It maps `channel_id`, and sequence to the query path.
40#[cfg(feature = "query")]
41pub const PENDING_QUERIES: cw_storage_plus::Map<(&str, u64), Vec<(String, bool)>> =
42    cw_storage_plus::Map::new("pending_queries");
43
44mod contract {
45    use crate::ibc::types::metadata::TxEncoding;
46
47    use cosmwasm_schema::schemars::JsonSchema;
48
49    use super::{cw_serde, Addr, ContractError};
50
51    /// State is the state of the contract.
52    #[derive(serde::Serialize, serde::Deserialize, Clone, Debug, PartialEq, JsonSchema)]
53    #[allow(clippy::derive_partial_eq_without_eq)]
54    pub struct State {
55        /// The Interchain Account (ICA) info needed to send packets.
56        /// This is set during the handshake.
57        #[serde(default)]
58        pub ica_info: Option<IcaInfo>,
59        /// The address of the callback contract.
60        #[serde(default)]
61        pub callback_address: Option<Addr>,
62    }
63
64    impl State {
65        /// Creates a new [`State`]
66        #[must_use]
67        pub const fn new(callback_address: Option<Addr>) -> Self {
68            Self {
69                ica_info: None,
70                // We always allow the first `MsgChannelOpenInit` message.
71                callback_address,
72            }
73        }
74
75        /// Gets the ICA info
76        ///
77        /// # Errors
78        ///
79        /// Returns an error if the ICA info is not set.
80        pub fn get_ica_info(&self) -> Result<IcaInfo, ContractError> {
81            self.ica_info
82                .as_ref()
83                .map_or(Err(ContractError::IcaInfoNotSet), |s| Ok(s.clone()))
84        }
85
86        /// Sets the ICA info
87        pub fn set_ica_info(
88            &mut self,
89            ica_address: impl Into<String>,
90            channel_id: impl Into<String>,
91            encoding: TxEncoding,
92        ) {
93            self.ica_info = Some(IcaInfo::new(ica_address, channel_id, encoding));
94        }
95
96        /// Deletes the ICA info
97        pub fn delete_ica_info(&mut self) {
98            self.ica_info = None;
99        }
100    }
101
102    /// IcaInfo is the ICA address and channel ID.
103    #[cw_serde]
104    pub struct IcaInfo {
105        pub ica_address: String,
106        pub channel_id: String,
107        pub encoding: TxEncoding,
108    }
109
110    impl IcaInfo {
111        /// Creates a new [`IcaInfo`]
112        pub fn new(
113            ica_address: impl Into<String>,
114            channel_id: impl Into<String>,
115            encoding: TxEncoding,
116        ) -> Self {
117            Self {
118                ica_address: ica_address.into(),
119                channel_id: channel_id.into(),
120                encoding,
121            }
122        }
123    }
124}
125
126#[allow(clippy::module_name_repetitions)]
127mod channel {
128    use cosmwasm_std::IbcOrder;
129
130    use super::{cw_serde, IbcChannel};
131
132    /// Status is the status of an IBC channel.
133    #[cw_serde]
134    pub enum ChannelStatus {
135        /// Uninitialized is the default state of the channel.
136        #[serde(rename = "STATE_UNINITIALIZED_UNSPECIFIED")]
137        Uninitialized,
138        /// Init is the state of the channel when it is created.
139        #[serde(rename = "STATE_INIT")]
140        Init,
141        /// TryOpen is the state of the channel when it is trying to open.
142        #[serde(rename = "STATE_TRYOPEN")]
143        TryOpen,
144        /// Open is the state of the channel when it is open.
145        #[serde(rename = "STATE_OPEN")]
146        Open,
147        /// Closed is the state of the channel when it is closed.
148        #[serde(rename = "STATE_CLOSED")]
149        Closed,
150        /// The channel has just accepted the upgrade handshake attempt and
151        /// is flushing in-flight packets. Added in `ibc-go` v8.1.0.
152        #[serde(rename = "STATE_FLUSHING")]
153        Flushing,
154        /// The channel has just completed flushing any in-flight packets.
155        /// Added in `ibc-go` v8.1.0.
156        #[serde(rename = "STATE_FLUSHCOMPLETE")]
157        FlushComplete,
158    }
159
160    /// State is the state of the IBC application's channel.
161    /// This application only supports one channel.
162    #[cw_serde]
163    pub struct ChannelState {
164        /// The IBC channel, as defined by cosmwasm.
165        pub channel: IbcChannel,
166        /// The status of the channel.
167        pub channel_status: ChannelStatus,
168    }
169
170    impl ChannelState {
171        /// Creates a new [`ChannelState`]
172        #[must_use]
173        pub const fn new_open_channel(channel: IbcChannel) -> Self {
174            Self {
175                channel,
176                channel_status: ChannelStatus::Open,
177            }
178        }
179
180        /// Checks if the channel is open
181        #[must_use]
182        pub const fn is_open(&self) -> bool {
183            matches!(self.channel_status, ChannelStatus::Open)
184        }
185
186        /// Closes the channel
187        pub fn close(&mut self) {
188            self.channel_status = ChannelStatus::Closed;
189        }
190
191        /// Checks if the channel is [`IbcOrder::Ordered`]
192        #[must_use]
193        pub const fn is_ordered(&self) -> bool {
194            matches!(self.channel.order, IbcOrder::Ordered)
195        }
196    }
197
198    impl std::fmt::Display for ChannelStatus {
199        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
200            match self {
201                Self::Uninitialized => write!(f, "STATE_UNINITIALIZED_UNSPECIFIED"),
202                Self::Init => write!(f, "STATE_INIT"),
203                Self::TryOpen => write!(f, "STATE_TRYOPEN"),
204                Self::Open => write!(f, "STATE_OPEN"),
205                Self::Closed => write!(f, "STATE_CLOSED"),
206                Self::Flushing => write!(f, "STATE_FLUSHING"),
207                Self::FlushComplete => write!(f, "STATE_FLUSHCOMPLETE"),
208            }
209        }
210    }
211}
212
213/// This module defines the types stored in the state for ICA queries.
214#[cfg(feature = "query")]
215pub mod ica_query {
216    use super::cw_serde;
217
218    /// PendingQuery is the query packet that is pending a response.
219    #[cw_serde]
220    pub struct PendingQuery {
221        /// The source channel ID of the query packet.
222        pub channel_id: String,
223        /// The sequence number of the query packet.
224        pub sequence: u64,
225        /// The gRPC query path.
226        pub path: String,
227        /// Whether the query was [`cosmwasm_std::QueryRequest::Stargate`] or not.
228        pub is_stargate: bool,
229    }
230}