diff --git a/.circleci/config.yml b/.circleci/config.yml index 2b9f83afd9..2d2ac008d4 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -96,15 +96,15 @@ jobs: - run: name: Build library for native target (all features) working_directory: ~/project/packages/std - command: cargo build --locked --features iterator,staking + command: cargo build --locked --features iterator,staking,stargate - run: name: Build library for wasm target (all features) working_directory: ~/project/packages/std - command: cargo wasm --locked --features iterator,staking + command: cargo wasm --locked --features iterator,staking,stargate - run: name: Run unit tests (all features) working_directory: ~/project/packages/std - command: cargo test --locked --features iterator,staking + command: cargo test --locked --features iterator,staking,stargate - run: name: Build and run schema generator working_directory: ~/project/packages/std diff --git a/Cargo.lock b/Cargo.lock index 51e9d040f6..32a6a42d9b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1071,9 +1071,9 @@ dependencies = [ [[package]] name = "serde-json-wasm" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7294d94d390f1d2334697c065ea591d7074c676e2d20aa6f1df752fced29823f" +checksum = "0584333eb679085166085b536f2aa378297647618c99f27fd9e9066e9b80c752" dependencies = [ "serde", ] diff --git a/contracts/burner/Cargo.lock b/contracts/burner/Cargo.lock index e25cce5cc6..56e3864e5d 100644 --- a/contracts/burner/Cargo.lock +++ b/contracts/burner/Cargo.lock @@ -857,9 +857,9 @@ dependencies = [ [[package]] name = "serde-json-wasm" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7294d94d390f1d2334697c065ea591d7074c676e2d20aa6f1df752fced29823f" +checksum = "0584333eb679085166085b536f2aa378297647618c99f27fd9e9066e9b80c752" dependencies = [ "serde", ] diff --git a/contracts/hackatom/Cargo.lock b/contracts/hackatom/Cargo.lock index fd391b2fb1..a3d787230e 100644 --- a/contracts/hackatom/Cargo.lock +++ b/contracts/hackatom/Cargo.lock @@ -868,9 +868,9 @@ dependencies = [ [[package]] name = "serde-json-wasm" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7294d94d390f1d2334697c065ea591d7074c676e2d20aa6f1df752fced29823f" +checksum = "0584333eb679085166085b536f2aa378297647618c99f27fd9e9066e9b80c752" dependencies = [ "serde", ] diff --git a/contracts/queue/Cargo.lock b/contracts/queue/Cargo.lock index a29f189e61..bf6e57e8f1 100644 --- a/contracts/queue/Cargo.lock +++ b/contracts/queue/Cargo.lock @@ -857,9 +857,9 @@ dependencies = [ [[package]] name = "serde-json-wasm" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7294d94d390f1d2334697c065ea591d7074c676e2d20aa6f1df752fced29823f" +checksum = "0584333eb679085166085b536f2aa378297647618c99f27fd9e9066e9b80c752" dependencies = [ "serde", ] diff --git a/contracts/reflect/Cargo.lock b/contracts/reflect/Cargo.lock index e21612f855..8f970b364e 100644 --- a/contracts/reflect/Cargo.lock +++ b/contracts/reflect/Cargo.lock @@ -867,9 +867,9 @@ dependencies = [ [[package]] name = "serde-json-wasm" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7294d94d390f1d2334697c065ea591d7074c676e2d20aa6f1df752fced29823f" +checksum = "0584333eb679085166085b536f2aa378297647618c99f27fd9e9066e9b80c752" dependencies = [ "serde", ] diff --git a/contracts/staking/Cargo.lock b/contracts/staking/Cargo.lock index 80bb1bff58..261f69d009 100644 --- a/contracts/staking/Cargo.lock +++ b/contracts/staking/Cargo.lock @@ -860,9 +860,9 @@ dependencies = [ [[package]] name = "serde-json-wasm" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7294d94d390f1d2334697c065ea591d7074c676e2d20aa6f1df752fced29823f" +checksum = "0584333eb679085166085b536f2aa378297647618c99f27fd9e9066e9b80c752" dependencies = [ "serde", ] diff --git a/packages/std/Cargo.toml b/packages/std/Cargo.toml index 55935699a4..c588fc8008 100644 --- a/packages/std/Cargo.toml +++ b/packages/std/Cargo.toml @@ -34,7 +34,7 @@ stargate = [] [dependencies] base64 = "0.13.0" cosmwasm-derive = { path = "../derive", version = "0.13.1" } -serde-json-wasm = { version = "0.2.1" } +serde-json-wasm = { version = "0.2.2" } schemars = "0.7" serde = { version = "1.0.103", default-features = false, features = ["derive", "alloc"] } thiserror = "1.0" diff --git a/packages/std/src/exports.rs b/packages/std/src/exports.rs index e9ec2fd5f4..34106a0c0b 100644 --- a/packages/std/src/exports.rs +++ b/packages/std/src/exports.rs @@ -251,7 +251,7 @@ where } /// Makes all bridges to external dependencies (i.e. Wasm imports) that are injected by the VM -fn make_dependencies() -> OwnedDeps { +pub(crate) fn make_dependencies() -> OwnedDeps { OwnedDeps { storage: ExternalStorage::new(), api: ExternalApi::new(), diff --git a/packages/std/src/ibc.rs b/packages/std/src/ibc.rs new file mode 100644 index 0000000000..c150cdae2d --- /dev/null +++ b/packages/std/src/ibc.rs @@ -0,0 +1,220 @@ +#![cfg(feature = "stargate")] +// The CosmosMsg variants are defined in results/cosmos_msg.rs +// The rest of the IBC related functionality is defined here + +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; +use std::fmt; + +use crate::addresses::HumanAddr; +use crate::binary::Binary; +use crate::coins::Coin; +use crate::results::{Attribute, CosmosMsg}; +use crate::types::Empty; + +/// These are messages in the IBC lifecycle. Only usable by IBC-enabled contracts +/// (contracts that directly speak the IBC protocol via 6 entry points) +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub enum IbcMsg { + /// Sends bank tokens owned by the contract to the given address on another chain. + /// The channel must already be established between the ibctransfer module on this chain + /// and a matching module on the remote chain. + /// We cannot select the port_id, this is whatever the local chain has bound the ibctransfer + /// module to. + Ics20Transfer { + /// exisiting channel to send the tokens over + channel_id: String, + /// address on the remote chain to receive these tokens + to_address: HumanAddr, + /// packet data only supports one coin + /// https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/ibc/applications/transfer/v1/transfer.proto#L11-L20 + amount: Coin, + }, + /// Sends an IBC packet with given data over the existing channel. + /// Data should be encoded in a format defined by the channel version, + /// and the module on the other side should know how to parse this. + SendPacket { + channel_id: String, + data: Binary, + timeout_height: IbcTimeoutHeight, + timeout_timestamp: u64, + version: u64, + }, + /// This will close an existing channel that is owned by this contract. + /// Port is auto-assigned to the contracts' ibc port + CloseChannel { channel_id: String }, +} + +/// These are queries to the various IBC modules to see the state of the contract's +/// IBC connection. These will return errors if the contract is not "ibc enabled" +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub enum IbcQuery { + /// Gets the Port ID the current contract is bound to. + /// Returns PortIdResponse + PortId {}, + /// Lists all (portID, channelID) pairs that are bound to a given port + /// If port_id is omitted, list all channels bound to the contract's port. + /// Returns ListChannelsResponse. + ListChannels { port_id: Option }, + /// Lists all information for a (portID, channelID) pair. + /// If port_id is omitted, it will default to the contract's own channel. + /// (To save a PortId{} call) + /// Returns ChannelResponse. + Channel { + channel_id: String, + port_id: Option, + }, + // TODO: Add more +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct PortIdResponse { + pub port_id: String, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct ListChannelsResponse { + pub channels: Vec, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct ChannelResponse { + pub channel: IbcChannel, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct IbcEndpoint { + pub port_id: String, + pub channel_id: String, +} + +// These are various messages used in the callbacks + +/// IbcChannel defines all information on a channel. +/// This is generally used in the hand-shake process, but can be queried directly. +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct IbcChannel { + pub endpoint: IbcEndpoint, + pub counterparty_endpoint: IbcEndpoint, + pub order: IbcOrder, + pub version: String, + /// CounterpartyVersion can be None when not known this context, yet + pub counterparty_version: Option, + /// The connection upon which this channel was created. If this is a multi-hop + /// channel, we only expose the first hop. + pub connection_id: String, +} + +// TODO: check what representation we want here for encoding - string or number +/// IbcOrder defines if a channel is ORDERED or UNORDERED +/// Values come from https://github.com/cosmos/cosmos-sdk/blob/v0.40.0/proto/ibc/core/channel/v1/channel.proto#L69-L80 +/// Naming comes from the protobuf files and go translations. +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub enum IbcOrder { + #[serde(rename = "ORDER_UNORDERED")] + Unordered, + #[serde(rename = "ORDER_ORDERED")] + Ordered, +} + +// IBCTimeoutHeight Height is a monotonically increasing data type +// that can be compared against another Height for the purposes of updating and +// freezing clients. +// Ordering is (revision_number, timeout_height) +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct IbcTimeoutHeight { + /// the version that the client is currently on + /// (eg. after reseting the chain this could increment 1 as height drops to 0) + pub revision_number: u64, + /// block height after which the packet times out. + /// the height within the given revision + pub timeout_height: u64, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct IbcPacket { + /// The raw data send from the other side in the packet + pub data: Binary, + /// identifies the channel and port on the sending chain. + pub src: IbcEndpoint, + /// identifies the channel and port on the receiving chain. + pub dest: IbcEndpoint, + /// The sequence number of the packet on the given channel + pub sequence: u64, + /// block height after which the packet times out + pub timeout_height: IbcTimeoutHeight, + /// block timestamp (in nanoseconds) after which the packet times out + pub timeout_timestamp: u64, + // the version that the client is currently on + pub version: u64, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct IbcAcknowledgement { + pub acknowledgement: Binary, + pub original_packet: IbcPacket, +} + +/// This is the return value for the majority of the ibc handlers. +/// That are able to dispatch messages / events on their own, +/// but have no meaningful return value to the calling code. +/// +/// Callbacks that have return values (like receive_packet) +/// or that cannot redispatch messages (like the handshake callbacks) +/// will use other Response types +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct IbcBasicResponse +where + T: Clone + fmt::Debug + PartialEq + JsonSchema, +{ + pub messages: Vec>, + /// The attributes that will be emitted as part of a "wasm" event + pub attributes: Vec, +} + +impl Default for IbcBasicResponse +where + T: Clone + fmt::Debug + PartialEq + JsonSchema, +{ + fn default() -> Self { + IbcBasicResponse { + messages: vec![], + attributes: vec![], + } + } +} + +/// This is the return value for the majority of the ibc handlers. +/// That are able to dispatch messages / events on their own, +/// but have no meaningful return value to the calling code. +/// +/// Callbacks that have return values (like receive_packet) +/// or that cannot redispatch messages (like the handshake callbacks) +/// will use other Response types +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct IbcReceiveResponse +where + T: Clone + fmt::Debug + PartialEq + JsonSchema, +{ + /// The bytes we return to the contract that sent the packet. + /// This may represent a success or error of exection + pub acknowledgement: Binary, + pub messages: Vec>, + /// The attributes that will be emitted as part of a "wasm" event + pub attributes: Vec, +} + +impl Default for IbcReceiveResponse +where + T: Clone + fmt::Debug + PartialEq + JsonSchema, +{ + fn default() -> Self { + IbcReceiveResponse { + acknowledgement: Binary(vec![]), + messages: vec![], + attributes: vec![], + } + } +} diff --git a/packages/std/src/ibc_exports.rs b/packages/std/src/ibc_exports.rs new file mode 100644 index 0000000000..611588aa64 --- /dev/null +++ b/packages/std/src/ibc_exports.rs @@ -0,0 +1,248 @@ +#![cfg(all(feature = "stargate", target_arch = "wasm32"))] +use std::fmt; +use std::vec::Vec; + +use schemars::JsonSchema; +use serde::Serialize; + +use crate::deps::DepsMut; +use crate::exports::make_dependencies; +use crate::ibc::{IbcBasicResponse, IbcChannel}; +use crate::memory::{consume_region, release_buffer, Region}; +use crate::results::ContractResult; +use crate::serde::{from_slice, to_vec}; +use crate::types::Env; +use crate::{IbcAcknowledgement, IbcPacket, IbcReceiveResponse}; + +// TODO: replace with https://doc.rust-lang.org/std/ops/trait.Try.html once stabilized +macro_rules! r#try_into_contract_result { + ($expr:expr) => { + match $expr { + Ok(val) => val, + Err(err) => { + return ContractResult::Err(err.to_string()); + } + } + }; + ($expr:expr,) => { + $crate::try_into_contract_result!($expr) + }; +} + +/// do_ibc_channel_open is designed for use with #[entry_point] to make a "C" extern +/// +/// contract_fn does the protocol version negotiation during channel handshake phase +pub fn do_ibc_channel_open( + contract_fn: &dyn Fn(DepsMut, Env, IbcChannel) -> Result<(), E>, + env_ptr: u32, + msg_ptr: u32, +) -> u32 +where + E: ToString, +{ + let res = _do_ibc_channel_open(contract_fn, env_ptr as *mut Region, msg_ptr as *mut Region); + let v = to_vec(&res).unwrap(); + release_buffer(v) as u32 +} + +fn _do_ibc_channel_open( + contract_fn: &dyn Fn(DepsMut, Env, IbcChannel) -> Result<(), E>, + env_ptr: *mut Region, + msg_ptr: *mut Region, +) -> ContractResult<()> +where + E: ToString, +{ + let env: Vec = unsafe { consume_region(env_ptr) }; + let msg: Vec = unsafe { consume_region(msg_ptr) }; + + let env: Env = try_into_contract_result!(from_slice(&env)); + let msg: IbcChannel = try_into_contract_result!(from_slice(&msg)); + + let mut deps = make_dependencies(); + contract_fn(deps.as_mut(), env, msg).into() +} + +/// do_ibc_channel_connect is designed for use with #[entry_point] to make a "C" extern +/// +/// contract_fn is a callback when a IBC channel is established (after both sides agree in open) +pub fn do_ibc_channel_connect( + contract_fn: &dyn Fn(DepsMut, Env, IbcChannel) -> Result, E>, + env_ptr: u32, + msg_ptr: u32, +) -> u32 +where + C: Serialize + Clone + fmt::Debug + PartialEq + JsonSchema, + E: ToString, +{ + let res = _do_ibc_channel_connect(contract_fn, env_ptr as *mut Region, msg_ptr as *mut Region); + let v = to_vec(&res).unwrap(); + release_buffer(v) as u32 +} + +fn _do_ibc_channel_connect( + contract_fn: &dyn Fn(DepsMut, Env, IbcChannel) -> Result, E>, + env_ptr: *mut Region, + msg_ptr: *mut Region, +) -> ContractResult> +where + C: Serialize + Clone + fmt::Debug + PartialEq + JsonSchema, + E: ToString, +{ + let env: Vec = unsafe { consume_region(env_ptr) }; + let msg: Vec = unsafe { consume_region(msg_ptr) }; + + let env: Env = try_into_contract_result!(from_slice(&env)); + let msg: IbcChannel = try_into_contract_result!(from_slice(&msg)); + + let mut deps = make_dependencies(); + contract_fn(deps.as_mut(), env, msg).into() +} + +/// do_ibc_channel_close is designed for use with #[entry_point] to make a "C" extern +/// +/// contract_fn is a callback when a IBC channel belonging to this contract is closed +pub fn do_ibc_channel_close( + contract_fn: &dyn Fn(DepsMut, Env, IbcChannel) -> Result, E>, + env_ptr: u32, + msg_ptr: u32, +) -> u32 +where + C: Serialize + Clone + fmt::Debug + PartialEq + JsonSchema, + E: ToString, +{ + let res = _do_ibc_channel_close(contract_fn, env_ptr as *mut Region, msg_ptr as *mut Region); + let v = to_vec(&res).unwrap(); + release_buffer(v) as u32 +} + +fn _do_ibc_channel_close( + contract_fn: &dyn Fn(DepsMut, Env, IbcChannel) -> Result, E>, + env_ptr: *mut Region, + msg_ptr: *mut Region, +) -> ContractResult> +where + C: Serialize + Clone + fmt::Debug + PartialEq + JsonSchema, + E: ToString, +{ + let env: Vec = unsafe { consume_region(env_ptr) }; + let msg: Vec = unsafe { consume_region(msg_ptr) }; + + let env: Env = try_into_contract_result!(from_slice(&env)); + let msg: IbcChannel = try_into_contract_result!(from_slice(&msg)); + + let mut deps = make_dependencies(); + contract_fn(deps.as_mut(), env, msg).into() +} + +/// do_ibc_packet_receive is designed for use with #[entry_point] to make a "C" extern +/// +/// contract_fn is called when this chain receives an IBC Packet on a channel belonging +/// to this contract +pub fn do_ibc_packet_receive( + contract_fn: &dyn Fn(DepsMut, Env, IbcPacket) -> Result, E>, + env_ptr: u32, + msg_ptr: u32, +) -> u32 +where + C: Serialize + Clone + fmt::Debug + PartialEq + JsonSchema, + E: ToString, +{ + let res = _do_ibc_packet_receive(contract_fn, env_ptr as *mut Region, msg_ptr as *mut Region); + let v = to_vec(&res).unwrap(); + release_buffer(v) as u32 +} + +fn _do_ibc_packet_receive( + contract_fn: &dyn Fn(DepsMut, Env, IbcPacket) -> Result, E>, + env_ptr: *mut Region, + msg_ptr: *mut Region, +) -> ContractResult> +where + C: Serialize + Clone + fmt::Debug + PartialEq + JsonSchema, + E: ToString, +{ + let env: Vec = unsafe { consume_region(env_ptr) }; + let msg: Vec = unsafe { consume_region(msg_ptr) }; + + let env: Env = try_into_contract_result!(from_slice(&env)); + let msg: IbcPacket = try_into_contract_result!(from_slice(&msg)); + + let mut deps = make_dependencies(); + contract_fn(deps.as_mut(), env, msg).into() +} + +/// do_ibc_packet_ack is designed for use with #[entry_point] to make a "C" extern +/// +/// contract_fn is called when this chain receives an IBC Acknowledgement for a packet +/// that this contract previously sent +pub fn do_ibc_packet_ack( + contract_fn: &dyn Fn(DepsMut, Env, IbcAcknowledgement) -> Result, E>, + env_ptr: u32, + msg_ptr: u32, +) -> u32 +where + C: Serialize + Clone + fmt::Debug + PartialEq + JsonSchema, + E: ToString, +{ + let res = _do_ibc_packet_ack(contract_fn, env_ptr as *mut Region, msg_ptr as *mut Region); + let v = to_vec(&res).unwrap(); + release_buffer(v) as u32 +} + +fn _do_ibc_packet_ack( + contract_fn: &dyn Fn(DepsMut, Env, IbcAcknowledgement) -> Result, E>, + env_ptr: *mut Region, + msg_ptr: *mut Region, +) -> ContractResult> +where + C: Serialize + Clone + fmt::Debug + PartialEq + JsonSchema, + E: ToString, +{ + let env: Vec = unsafe { consume_region(env_ptr) }; + let msg: Vec = unsafe { consume_region(msg_ptr) }; + + let env: Env = try_into_contract_result!(from_slice(&env)); + let msg: IbcAcknowledgement = try_into_contract_result!(from_slice(&msg)); + + let mut deps = make_dependencies(); + contract_fn(deps.as_mut(), env, msg).into() +} + +/// do_ibc_packet_timeout is designed for use with #[entry_point] to make a "C" extern +/// +/// contract_fn is called when a packet that this contract previously sent has provably +/// timedout and will never be relayed to the calling chain. This generally behaves +/// like ick_ack_fn upon an acknowledgement containing an error. +pub fn do_ibc_packet_timeout( + contract_fn: &dyn Fn(DepsMut, Env, IbcPacket) -> Result, E>, + env_ptr: u32, + msg_ptr: u32, +) -> u32 +where + C: Serialize + Clone + fmt::Debug + PartialEq + JsonSchema, + E: ToString, +{ + let res = _do_ibc_packet_timeout(contract_fn, env_ptr as *mut Region, msg_ptr as *mut Region); + let v = to_vec(&res).unwrap(); + release_buffer(v) as u32 +} + +fn _do_ibc_packet_timeout( + contract_fn: &dyn Fn(DepsMut, Env, IbcPacket) -> Result, E>, + env_ptr: *mut Region, + msg_ptr: *mut Region, +) -> ContractResult> +where + C: Serialize + Clone + fmt::Debug + PartialEq + JsonSchema, + E: ToString, +{ + let env: Vec = unsafe { consume_region(env_ptr) }; + let msg: Vec = unsafe { consume_region(msg_ptr) }; + + let env: Env = try_into_contract_result!(from_slice(&env)); + let msg: IbcPacket = try_into_contract_result!(from_slice(&msg)); + + let mut deps = make_dependencies(); + contract_fn(deps.as_mut(), env, msg).into() +} diff --git a/packages/std/src/lib.rs b/packages/std/src/lib.rs index 530c97af43..6a4b627e45 100644 --- a/packages/std/src/lib.rs +++ b/packages/std/src/lib.rs @@ -9,6 +9,7 @@ mod coins; mod deps; mod entry_points; mod errors; +mod ibc; #[cfg(feature = "iterator")] mod iterator; mod math; @@ -24,6 +25,12 @@ pub use crate::binary::{Binary, ByteArray}; pub use crate::coins::{coin, coins, has_coins, Coin}; pub use crate::deps::{Deps, DepsMut, OwnedDeps}; pub use crate::errors::{StdError, StdResult, SystemError}; +#[cfg(feature = "stargate")] +pub use crate::ibc::{ + ChannelResponse, IbcAcknowledgement, IbcBasicResponse, IbcChannel, IbcEndpoint, IbcMsg, + IbcOrder, IbcPacket, IbcQuery, IbcReceiveResponse, IbcTimeoutHeight, ListChannelsResponse, + PortIdResponse, +}; #[cfg(feature = "iterator")] pub use crate::iterator::{Order, KV}; pub use crate::math::{Decimal, Uint128}; @@ -57,6 +64,14 @@ pub use crate::exports::{do_handle, do_init, do_migrate, do_query}; #[cfg(target_arch = "wasm32")] pub use crate::imports::{ExternalApi, ExternalQuerier, ExternalStorage}; +#[cfg(all(feature = "stargate", target_arch = "wasm32"))] +mod ibc_exports; +#[cfg(all(feature = "stargate", target_arch = "wasm32"))] +pub use crate::ibc_exports::{ + do_ibc_channel_close, do_ibc_channel_connect, do_ibc_channel_open, do_ibc_packet_ack, + do_ibc_packet_receive, do_ibc_packet_timeout, +}; + // Exposed for testing only // Both unit tests and integration tests are compiled to native code, so everything in here does not need to compile to Wasm. diff --git a/packages/std/src/mock.rs b/packages/std/src/mock.rs index 4e3c55e9b3..0c62a84f5c 100644 --- a/packages/std/src/mock.rs +++ b/packages/std/src/mock.rs @@ -232,6 +232,14 @@ impl MockQuerier { QueryRequest::Custom(custom_query) => (*self.custom_handler)(custom_query), QueryRequest::Staking(staking_query) => self.staking.query(staking_query), QueryRequest::Wasm(msg) => self.wasm.query(msg), + #[cfg(feature = "stargate")] + QueryRequest::Stargate { .. } => SystemResult::Err(SystemError::UnsupportedRequest { + kind: "Stargate".to_string(), + }), + #[cfg(feature = "stargate")] + QueryRequest::Ibc(_) => SystemResult::Err(SystemError::UnsupportedRequest { + kind: "Ibc".to_string(), + }), } } } diff --git a/packages/std/src/query.rs b/packages/std/src/query.rs index 4bbeab1f4f..43a1f727cf 100644 --- a/packages/std/src/query.rs +++ b/packages/std/src/query.rs @@ -4,6 +4,8 @@ use serde::{Deserialize, Serialize}; use crate::addresses::HumanAddr; use crate::binary::Binary; use crate::coins::Coin; +#[cfg(feature = "stargate")] +use crate::ibc::IbcQuery; use crate::math::Decimal; use crate::types::Empty; @@ -24,6 +26,8 @@ pub enum QueryRequest { /// this is the expected protobuf message type (not any), binary encoded data: Binary, }, + #[cfg(feature = "stargate")] + Ibc(IbcQuery), Wasm(WasmQuery), } @@ -106,6 +110,13 @@ impl From for QueryRequest { } } +#[cfg(feature = "stargate")] +impl From for QueryRequest { + fn from(msg: IbcQuery) -> Self { + QueryRequest::Ibc(msg) + } +} + #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] pub struct BalanceResponse { diff --git a/packages/std/src/results/cosmos_msg.rs b/packages/std/src/results/cosmos_msg.rs index ce941f6090..d3958ef876 100644 --- a/packages/std/src/results/cosmos_msg.rs +++ b/packages/std/src/results/cosmos_msg.rs @@ -5,6 +5,8 @@ use std::fmt; use crate::addresses::HumanAddr; use crate::binary::Binary; use crate::coins::Coin; +#[cfg(feature = "stargate")] +use crate::ibc::IbcMsg; use crate::types::Empty; #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] @@ -26,6 +28,8 @@ where type_url: String, data: Binary, }, + #[cfg(feature = "stargate")] + Ibc(IbcMsg), Wasm(WasmMsg), } @@ -124,6 +128,13 @@ impl From for CosmosMsg } } +#[cfg(feature = "stargate")] +impl From for CosmosMsg { + fn from(msg: IbcMsg) -> Self { + CosmosMsg::Ibc(msg) + } +} + #[cfg(test)] mod tests { use super::*;