Skip to content

Commit

Permalink
chore: Update after review
Browse files Browse the repository at this point in the history
  • Loading branch information
kulikthebird committed Feb 3, 2025
1 parent 39179ac commit a1b922e
Show file tree
Hide file tree
Showing 8 changed files with 99 additions and 49 deletions.
13 changes: 12 additions & 1 deletion contracts/ibc-callbacks/schema/ibc-callbacks.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,11 @@
},
"channel_version": {
"description": "IBC channel version",
"type": "string"
"allOf": [
{
"$ref": "#/definitions/ChannelVersion"
}
]
},
"timeout_seconds": {
"description": "The amount of seconds from now the transfer should timeout at",
Expand Down Expand Up @@ -87,6 +91,13 @@
]
}
]
},
"ChannelVersion": {
"type": "string",
"enum": [
"v1",
"v2"
]
}
}
},
Expand Down
13 changes: 12 additions & 1 deletion contracts/ibc-callbacks/schema/raw/execute.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,11 @@
},
"channel_version": {
"description": "IBC channel version",
"type": "string"
"allOf": [
{
"$ref": "#/definitions/ChannelVersion"
}
]
},
"timeout_seconds": {
"description": "The amount of seconds from now the transfer should timeout at",
Expand Down Expand Up @@ -76,6 +80,13 @@
]
}
]
},
"ChannelVersion": {
"type": "string",
"enum": [
"v1",
"v2"
]
}
}
}
15 changes: 5 additions & 10 deletions contracts/ibc-callbacks/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use cosmwasm_std::{
MessageInfo, Response, StdError, StdResult, TransferMsgBuilder, TransferMsgBuilderV2,
};

use crate::msg::{CallbackType, ExecuteMsg, QueryMsg};
use crate::msg::{CallbackType, ChannelVersion, ExecuteMsg, QueryMsg};
use crate::state::{load_stats, save_stats, CallbackStats};

#[entry_point]
Expand Down Expand Up @@ -55,7 +55,7 @@ fn execute_transfer(
channel_id: String,
timeout_seconds: u32,
callback_type: CallbackType,
channel_version: String,
channel_version: ChannelVersion,
) -> StdResult<Response> {
let src_callback = IbcSrcCallback {
address: env.contract.address,
Expand All @@ -66,8 +66,8 @@ fn execute_transfer(
gas_limit: None,
};

let transfer_msg = match channel_version.as_str() {
"V1" => {
let transfer_msg = match channel_version {
ChannelVersion::V1 => {
let coin = match &*info.funds {
[coin] if !coin.amount.is_zero() => coin,
_ => {
Expand All @@ -91,7 +91,7 @@ fn execute_transfer(
CallbackType::Dst => builder.with_dst_callback(dst_callback).build(),
}
}
"V2" => {
ChannelVersion::V2 => {
let builder = TransferMsgBuilderV2::new(
channel_id,
to_address.clone(),
Expand All @@ -107,11 +107,6 @@ fn execute_transfer(
CallbackType::Dst => builder.with_dst_callback(dst_callback).build(),
}
}
_ => {
return Err(StdError::generic_err(
"Must specify \"V1\" or \"V2\" channel version",
))
}
};

Ok(Response::new()
Expand Down
8 changes: 7 additions & 1 deletion contracts/ibc-callbacks/src/msg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ pub enum QueryMsg {
CallbackStats {},
}

#[cw_serde]
pub enum ChannelVersion {
V1,
V2,
}

#[cw_serde]
pub enum ExecuteMsg {
Transfer {
Expand All @@ -21,7 +27,7 @@ pub enum ExecuteMsg {
#[serde(default)]
callback_type: CallbackType,
/// IBC channel version
channel_version: String,
channel_version: ChannelVersion,
},
}

Expand Down
2 changes: 0 additions & 2 deletions packages/go-gen/tests/cosmwasm_std__IbcMsg.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ type TransferV2Msg struct {
// An optional memo. See the blog post ["Moving Beyond Simple Token Transfers"](https://medium.com/the-interchain-foundation/moving-beyond-simple-token-transfers-d42b2b1dc29b) for more information.
//
// There is no difference between setting this to `None` or an empty string.
//
// This field is only supported on chains with CosmWasm >= 2.0 and silently ignored on older chains. If you need support for both 1.x and 2.x chain with the same codebase, it is recommended to use `CosmosMsg::Stargate` with a custom MsgTransfer protobuf encoder instead.
Memo string `json:"memo,omitempty"`
// when packet times out, measured on remote chain
Timeout IBCTimeout `json:"timeout"`
Expand Down
7 changes: 0 additions & 7 deletions packages/std/src/ibc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
use core::cmp::{Ord, Ordering, PartialOrd};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use std::vec;

use crate::coin::Coin;
use crate::prelude::*;
Expand Down Expand Up @@ -84,12 +83,6 @@ pub enum IbcMsg {
/// for more information.
///
/// There is no difference between setting this to `None` or an empty string.
///
/// This field is only supported on chains with CosmWasm >= 2.0 and silently
/// ignored on older chains.
/// If you need support for both 1.x and 2.x chain with the same codebase,
/// it is recommended to use `CosmosMsg::Stargate` with a custom MsgTransfer
/// protobuf encoder instead.
memo: Option<String>,
// A struct containing the list of next hops,
// determining where the tokens must be forwarded next.
Expand Down
10 changes: 5 additions & 5 deletions packages/std/src/ibc/transfer_msg_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,23 @@ pub struct EmptyMemo;
#[derive(Clone, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub struct WithMemo {
pub memo: String,
pub(crate) memo: String,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub struct WithSrcCallback {
pub src_callback: IbcSrcCallback,
pub(crate) src_callback: IbcSrcCallback,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub struct WithDstCallback {
pub dst_callback: IbcDstCallback,
pub(crate) dst_callback: IbcDstCallback,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub struct WithCallbacks {
pub src_callback: IbcSrcCallback,
pub dst_callback: IbcDstCallback,
pub(crate) src_callback: IbcSrcCallback,
pub(crate) dst_callback: IbcDstCallback,
}

pub trait MemoSource {
Expand Down
80 changes: 58 additions & 22 deletions packages/std/src/ibc/transfer_msg_builder_v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,40 +4,52 @@ use super::{
EmptyMemo, Hop, MemoSource, WithCallbacks, WithDstCallback, WithMemo, WithSrcCallback,
};

impl<M: MemoSource> TransferMsgBuilderV2<M> {
impl<M: MemoSource, F: Into<Vec<Hop>>> TransferMsgBuilderV2<M, F> {
pub fn build(self) -> IbcMsg {
IbcMsg::TransferV2 {
channel_id: self.channel_id,
to_address: self.to_address,
tokens: self.tokens,
timeout: self.timeout,
memo: self.memo.into_memo(),
forwarding: self.forwarding,
forwarding: self.forwarding.into(),
}
}
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct TransferMsgBuilderV2<MemoData> {
pub struct TransferMsgBuilderV2<MemoData, ForwardingData> {
channel_id: String,
to_address: String,
tokens: Vec<Coin>,
timeout: IbcTimeout,
memo: MemoData,
forwarding: Vec<Hop>,
forwarding: ForwardingData,
}

#[derive(Clone, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub struct WithForwarding;
pub struct WithoutForwarding;

#[derive(Clone, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub struct WithForwarding {
pub(crate) forwarding: Vec<Hop>,
}

impl MemoSource for WithForwarding {
fn into_memo(self) -> Option<String> {
None
impl From<WithoutForwarding> for Vec<Hop> {
fn from(_val: WithoutForwarding) -> Self {
vec![]
}
}

impl TransferMsgBuilderV2<EmptyMemo> {
impl From<WithForwarding> for Vec<Hop> {
fn from(val: WithForwarding) -> Self {
val.forwarding
}
}

impl TransferMsgBuilderV2<EmptyMemo, WithoutForwarding> {
/// Creates a new transfer message with the given parameters and no memo.
pub fn new(
channel_id: impl Into<String>,
Expand All @@ -51,12 +63,15 @@ impl TransferMsgBuilderV2<EmptyMemo> {
tokens,
timeout: timeout.into(),
memo: EmptyMemo,
forwarding: vec![],
forwarding: WithoutForwarding,
}
}

/// Adds a memo text to the transfer message.
pub fn with_memo(self, memo: impl Into<String>) -> TransferMsgBuilderV2<WithMemo> {
pub fn with_memo(
self,
memo: impl Into<String>,
) -> TransferMsgBuilderV2<WithMemo, WithoutForwarding> {
TransferMsgBuilderV2 {
channel_id: self.channel_id,
to_address: self.to_address,
Expand All @@ -74,7 +89,7 @@ impl TransferMsgBuilderV2<EmptyMemo> {
pub fn with_src_callback(
self,
src_callback: IbcSrcCallback,
) -> TransferMsgBuilderV2<WithSrcCallback> {
) -> TransferMsgBuilderV2<WithSrcCallback, WithoutForwarding> {
TransferMsgBuilderV2 {
channel_id: self.channel_id,
to_address: self.to_address,
Expand All @@ -92,7 +107,7 @@ impl TransferMsgBuilderV2<EmptyMemo> {
pub fn with_dst_callback(
self,
dst_callback: IbcDstCallback,
) -> TransferMsgBuilderV2<WithDstCallback> {
) -> TransferMsgBuilderV2<WithDstCallback, WithoutForwarding> {
TransferMsgBuilderV2 {
channel_id: self.channel_id,
to_address: self.to_address,
Expand All @@ -105,29 +120,32 @@ impl TransferMsgBuilderV2<EmptyMemo> {

/// Adds forwarding data.
/// It is worth to notice that the builder does not allow to add forwarding data along with
/// callbacks. It is discouraged in the IBC docs:
/// https://github.com/cosmos/ibc-go/blob/main/docs/docs/04-middleware/02-callbacks/01-overview.md#known-limitations
pub fn with_forwarding(self, forwarding: Vec<Hop>) -> TransferMsgBuilderV2<WithForwarding> {
/// source callback. It is discouraged in the IBC docs:
/// https://ibc.cosmos.network/v9/middleware/callbacks/overview/#known-limitations
pub fn with_forwarding(
self,
forwarding: Vec<Hop>,
) -> TransferMsgBuilderV2<EmptyMemo, WithForwarding> {
TransferMsgBuilderV2 {
channel_id: self.channel_id,
to_address: self.to_address,
tokens: self.tokens,
timeout: self.timeout,
memo: WithForwarding,
forwarding,
memo: self.memo,
forwarding: WithForwarding { forwarding },
}
}
}

impl TransferMsgBuilderV2<WithSrcCallback> {
impl TransferMsgBuilderV2<WithSrcCallback, WithoutForwarding> {
/// Adds an IBC destination callback entry to the memo field.
/// Use this if you want to receive IBC callbacks on the destination chain.
///
/// For more info check out [`crate::IbcDestinationCallbackMsg`].
pub fn with_dst_callback(
self,
dst_callback: IbcDstCallback,
) -> TransferMsgBuilderV2<WithCallbacks> {
) -> TransferMsgBuilderV2<WithCallbacks, WithoutForwarding> {
TransferMsgBuilderV2 {
channel_id: self.channel_id,
to_address: self.to_address,
Expand All @@ -142,15 +160,15 @@ impl TransferMsgBuilderV2<WithSrcCallback> {
}
}

impl TransferMsgBuilderV2<WithDstCallback> {
impl TransferMsgBuilderV2<WithDstCallback, WithoutForwarding> {
/// Adds an IBC source callback entry to the memo field.
/// Use this if you want to receive IBC callbacks on the source chain.
///
/// For more info check out [`crate::IbcSourceCallbackMsg`].
pub fn with_src_callback(
self,
src_callback: IbcSrcCallback,
) -> TransferMsgBuilderV2<WithCallbacks> {
) -> TransferMsgBuilderV2<WithCallbacks, WithoutForwarding> {
TransferMsgBuilderV2 {
channel_id: self.channel_id,
to_address: self.to_address,
Expand All @@ -163,6 +181,24 @@ impl TransferMsgBuilderV2<WithDstCallback> {
forwarding: self.forwarding,
}
}

/// Adds forwarding data.
/// It is worth to notice that the builder does not allow to add forwarding data along with
/// source callback. It is discouraged in the IBC docs:
/// https://ibc.cosmos.network/v9/middleware/callbacks/overview/#known-limitations
pub fn with_forwarding(
self,
forwarding: Vec<Hop>,
) -> TransferMsgBuilderV2<WithDstCallback, WithForwarding> {
TransferMsgBuilderV2 {
channel_id: self.channel_id,
to_address: self.to_address,
tokens: self.tokens,
timeout: self.timeout,
memo: self.memo,
forwarding: WithForwarding { forwarding },
}
}
}

#[cfg(test)]
Expand Down

0 comments on commit a1b922e

Please sign in to comment.