From b2350b1b6f5f1166fcf0a954b6331a869f927e32 Mon Sep 17 00:00:00 2001 From: Christoph Otter Date: Mon, 3 Jun 2024 12:57:10 +0200 Subject: [PATCH 1/8] Implement initial version of TransferMsgBuilder --- packages/std/src/ibc.rs | 3 + packages/std/src/ibc/callbacks.rs | 4 +- packages/std/src/ibc/transfer_msg_builder.rs | 263 +++++++++++++++++++ packages/std/src/lib.rs | 1 + 4 files changed, 269 insertions(+), 2 deletions(-) create mode 100644 packages/std/src/ibc/transfer_msg_builder.rs diff --git a/packages/std/src/ibc.rs b/packages/std/src/ibc.rs index cec3b790d7..1b89c92a41 100644 --- a/packages/std/src/ibc.rs +++ b/packages/std/src/ibc.rs @@ -13,7 +13,10 @@ use crate::StdResult; use crate::{to_json_binary, Binary}; mod callbacks; +mod transfer_msg_builder; + pub use callbacks::*; +pub use transfer_msg_builder::*; /// These are messages in the IBC lifecycle. Only usable by IBC-enabled contracts /// (contracts that directly speak the IBC protocol via 6 entry points) diff --git a/packages/std/src/ibc/callbacks.rs b/packages/std/src/ibc/callbacks.rs index 86b59bcc0b..1457204398 100644 --- a/packages/std/src/ibc/callbacks.rs +++ b/packages/std/src/ibc/callbacks.rs @@ -39,9 +39,9 @@ use crate::{Addr, IbcAcknowledgement, IbcPacket, Uint64}; pub struct IbcCallbackRequest { // using private fields to force use of the constructors #[serde(skip_serializing_if = "Option::is_none")] - src_callback: Option, + pub(crate) src_callback: Option, #[serde(skip_serializing_if = "Option::is_none")] - dest_callback: Option, + pub(crate) dest_callback: Option, } impl IbcCallbackRequest { diff --git a/packages/std/src/ibc/transfer_msg_builder.rs b/packages/std/src/ibc/transfer_msg_builder.rs new file mode 100644 index 0000000000..798c219799 --- /dev/null +++ b/packages/std/src/ibc/transfer_msg_builder.rs @@ -0,0 +1,263 @@ +use std::marker::PhantomData; + +use crate::{ + to_json_string, Coin, IbcCallbackRequest, IbcDstCallback, IbcMsg, IbcSrcCallback, IbcTimeout, +}; + +// these are the different states the TransferMsgBuilder can be in +#[derive(Clone, Debug, PartialEq, Eq)] +struct EmptyMemo; +#[derive(Clone, Debug, PartialEq, Eq)] +struct WithMemo; +#[derive(Clone, Debug, PartialEq, Eq)] +struct WithSrcCallback; +#[derive(Clone, Debug, PartialEq, Eq)] +struct WithDstCallback; +#[derive(Clone, Debug, PartialEq, Eq)] +struct WithCallbacks; + +// TODO: use trait for MemoData and get rid of state? +#[derive(Clone, Debug, PartialEq, Eq)] +enum MemoData { + Empty, + Text(String), + IbcCallbacks(IbcCallbackRequest), +} + +impl From for Option { + fn from(memo: MemoData) -> Option { + match memo { + MemoData::Empty => None, + MemoData::Text(text) => Some(text), + MemoData::IbcCallbacks(callbacks) => Some(to_json_string(&callbacks).unwrap()), + } + } +} + +impl TransferMsgBuilder { + pub fn build(self) -> IbcMsg { + IbcMsg::Transfer { + channel_id: self.channel_id, + to_address: self.to_address, + amount: self.amount, + timeout: self.timeout, + memo: self.memo.into(), + } + } +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct TransferMsgBuilder { + channel_id: String, + to_address: String, + amount: Coin, + timeout: IbcTimeout, + memo: MemoData, + _state: PhantomData, +} + +impl TransferMsgBuilder { + pub fn new( + channel_id: impl Into, + to_address: impl Into, + amount: Coin, + timeout: impl Into, + ) -> Self { + Self { + channel_id: channel_id.into(), + to_address: to_address.into(), + amount, + timeout: timeout.into(), + memo: MemoData::Empty, + _state: PhantomData, + } + } + + pub fn with_memo(self, memo: impl Into) -> TransferMsgBuilder { + TransferMsgBuilder { + channel_id: self.channel_id, + to_address: self.to_address, + amount: self.amount, + timeout: self.timeout, + memo: MemoData::Text(memo.into()), + _state: PhantomData, + } + } + + pub fn with_src_callback( + self, + src_callback: IbcSrcCallback, + ) -> TransferMsgBuilder { + TransferMsgBuilder { + channel_id: self.channel_id, + to_address: self.to_address, + amount: self.amount, + timeout: self.timeout, + memo: MemoData::IbcCallbacks(IbcCallbackRequest::source(src_callback)), + _state: PhantomData, + } + } + + pub fn with_dst_callback( + self, + dst_callback: IbcDstCallback, + ) -> TransferMsgBuilder { + TransferMsgBuilder { + channel_id: self.channel_id, + to_address: self.to_address, + amount: self.amount, + timeout: self.timeout, + memo: MemoData::IbcCallbacks(IbcCallbackRequest::destination(dst_callback)), + _state: PhantomData, + } + } +} + +impl TransferMsgBuilder { + pub fn with_dst_callback( + self, + dst_callback: IbcDstCallback, + ) -> TransferMsgBuilder { + TransferMsgBuilder { + channel_id: self.channel_id, + to_address: self.to_address, + amount: self.amount, + timeout: self.timeout, + memo: match self.memo { + MemoData::IbcCallbacks(IbcCallbackRequest { + src_callback: Some(src_callback), + .. + }) => MemoData::IbcCallbacks(IbcCallbackRequest::both(src_callback, dst_callback)), + _ => unreachable!(), // we know this never happens because of the WithSrcCallback state + }, + _state: PhantomData, + } + } +} + +impl TransferMsgBuilder { + pub fn with_src_callback( + self, + src_callback: IbcSrcCallback, + ) -> TransferMsgBuilder { + TransferMsgBuilder { + channel_id: self.channel_id, + to_address: self.to_address, + amount: self.amount, + timeout: self.timeout, + memo: match self.memo { + MemoData::IbcCallbacks(IbcCallbackRequest { + dest_callback: Some(dst_callback), + .. + }) => MemoData::IbcCallbacks(IbcCallbackRequest::both(src_callback, dst_callback)), + _ => unreachable!(), // we know this never happens because of the WithDstCallback state + }, + _state: PhantomData, + } + } +} + +#[cfg(test)] +mod tests { + use crate::{coin, Addr, Timestamp, Uint64}; + + use super::*; + + #[test] + fn test_transfer_msg_builder() { + let src_callback = IbcSrcCallback { + address: Addr::unchecked("src"), + gas_limit: Some(Uint64::new(12345)), + }; + let dst_callback = IbcDstCallback { + address: "dst".to_string(), + gas_limit: None, + }; + + let empty_memo_builder = TransferMsgBuilder::new( + "channel-0", + "cosmos1example", + coin(10, "ucoin"), + Timestamp::from_seconds(12345), + ); + + let empty = empty_memo_builder.clone().build(); + let with_memo = empty_memo_builder.clone().with_memo("memo").build(); + + let with_src_callback_builder = empty_memo_builder + .clone() + .with_src_callback(src_callback.clone()); + let with_src_callback = with_src_callback_builder.clone().build(); + let with_dst_callback_builder = empty_memo_builder + .clone() + .with_dst_callback(dst_callback.clone()); + let with_dst_callback = with_dst_callback_builder.clone().build(); + + let with_both_callbacks1 = with_src_callback_builder + .with_dst_callback(dst_callback.clone()) + .build(); + + let with_both_callbacks2 = with_dst_callback_builder + .with_src_callback(src_callback.clone()) + .build(); + + // assert all the different messages + assert_eq!( + empty, + IbcMsg::Transfer { + channel_id: "channel-0".to_string(), + to_address: "cosmos1example".to_string(), + amount: coin(10, "ucoin"), + timeout: Timestamp::from_seconds(12345).into(), + memo: None, + } + ); + assert_eq!( + with_memo, + IbcMsg::Transfer { + channel_id: "channel-0".to_string(), + to_address: "cosmos1example".to_string(), + amount: coin(10, "ucoin"), + timeout: Timestamp::from_seconds(12345).into(), + memo: Some("memo".to_string()), + } + ); + assert_eq!( + with_src_callback, + IbcMsg::Transfer { + channel_id: "channel-0".to_string(), + to_address: "cosmos1example".to_string(), + amount: coin(10, "ucoin"), + timeout: Timestamp::from_seconds(12345).into(), + memo: Some( + to_json_string(&IbcCallbackRequest::source(src_callback.clone())).unwrap() + ), + } + ); + assert_eq!( + with_dst_callback, + IbcMsg::Transfer { + channel_id: "channel-0".to_string(), + to_address: "cosmos1example".to_string(), + amount: coin(10, "ucoin"), + timeout: Timestamp::from_seconds(12345).into(), + memo: Some( + to_json_string(&IbcCallbackRequest::destination(dst_callback.clone())).unwrap() + ), + } + ); + assert_eq!( + with_both_callbacks1, + IbcMsg::Transfer { + channel_id: "channel-0".to_string(), + to_address: "cosmos1example".to_string(), + amount: coin(10, "ucoin"), + timeout: Timestamp::from_seconds(12345).into(), + memo: Some( + to_json_string(&IbcCallbackRequest::both(src_callback, dst_callback)).unwrap() + ), + } + ); + assert_eq!(with_both_callbacks1, with_both_callbacks2); + } +} diff --git a/packages/std/src/lib.rs b/packages/std/src/lib.rs index d83774e750..e3d86c12de 100644 --- a/packages/std/src/lib.rs +++ b/packages/std/src/lib.rs @@ -45,6 +45,7 @@ pub use crate::ibc::{ IbcDestinationCallbackMsg, IbcDstCallback, IbcEndpoint, IbcMsg, IbcOrder, IbcPacket, IbcPacketAckMsg, IbcPacketReceiveMsg, IbcPacketTimeoutMsg, IbcReceiveResponse, IbcSourceCallbackMsg, IbcSrcCallback, IbcTimeout, IbcTimeoutBlock, IbcTimeoutCallbackMsg, + TransferMsgBuilder, }; #[cfg(feature = "iterator")] pub use crate::iterator::{Order, Record}; From 9e86d2d8f6fd9ba1a647a78e1bdf757d151353eb Mon Sep 17 00:00:00 2001 From: Christoph Otter Date: Mon, 3 Jun 2024 13:41:42 +0200 Subject: [PATCH 2/8] Refactor TransferMsgBuilder --- packages/std/src/ibc/transfer_msg_builder.rs | 99 +++++++++++--------- 1 file changed, 53 insertions(+), 46 deletions(-) diff --git a/packages/std/src/ibc/transfer_msg_builder.rs b/packages/std/src/ibc/transfer_msg_builder.rs index 798c219799..5a2c72ba6a 100644 --- a/packages/std/src/ibc/transfer_msg_builder.rs +++ b/packages/std/src/ibc/transfer_msg_builder.rs @@ -1,40 +1,60 @@ -use std::marker::PhantomData; - use crate::{ to_json_string, Coin, IbcCallbackRequest, IbcDstCallback, IbcMsg, IbcSrcCallback, IbcTimeout, }; -// these are the different states the TransferMsgBuilder can be in +// these are the different memo types and at the same time the states +// the TransferMsgBuilder can be in #[derive(Clone, Debug, PartialEq, Eq)] -struct EmptyMemo; +pub struct EmptyMemo; #[derive(Clone, Debug, PartialEq, Eq)] -struct WithMemo; +pub struct WithMemo { + memo: String, +} #[derive(Clone, Debug, PartialEq, Eq)] -struct WithSrcCallback; +pub struct WithSrcCallback { + src_callback: IbcSrcCallback, +} #[derive(Clone, Debug, PartialEq, Eq)] -struct WithDstCallback; +pub struct WithDstCallback { + dst_callback: IbcDstCallback, +} #[derive(Clone, Debug, PartialEq, Eq)] -struct WithCallbacks; +pub struct WithCallbacks { + src_callback: IbcSrcCallback, + dst_callback: IbcDstCallback, +} -// TODO: use trait for MemoData and get rid of state? -#[derive(Clone, Debug, PartialEq, Eq)] -enum MemoData { - Empty, - Text(String), - IbcCallbacks(IbcCallbackRequest), +impl From for Option { + fn from(_: EmptyMemo) -> Self { + None + } } -impl From for Option { - fn from(memo: MemoData) -> Option { - match memo { - MemoData::Empty => None, - MemoData::Text(text) => Some(text), - MemoData::IbcCallbacks(callbacks) => Some(to_json_string(&callbacks).unwrap()), - } +impl From for Option { + fn from(m: WithMemo) -> Self { + Some(m.memo) + } +} + +impl From for Option { + fn from(s: WithSrcCallback) -> Self { + Some(to_json_string(&IbcCallbackRequest::source(s.src_callback)).unwrap()) + } +} + +impl From for Option { + fn from(d: WithDstCallback) -> Self { + Some(to_json_string(&IbcCallbackRequest::destination(d.dst_callback)).unwrap()) + } +} + +impl From for Option { + fn from(c: WithCallbacks) -> Self { + Some(to_json_string(&IbcCallbackRequest::both(c.src_callback, c.dst_callback)).unwrap()) } } -impl TransferMsgBuilder { +impl>> TransferMsgBuilder { pub fn build(self) -> IbcMsg { IbcMsg::Transfer { channel_id: self.channel_id, @@ -47,13 +67,12 @@ impl TransferMsgBuilder { } #[derive(Clone, Debug, PartialEq, Eq)] -pub struct TransferMsgBuilder { +pub struct TransferMsgBuilder { channel_id: String, to_address: String, amount: Coin, timeout: IbcTimeout, memo: MemoData, - _state: PhantomData, } impl TransferMsgBuilder { @@ -68,8 +87,7 @@ impl TransferMsgBuilder { to_address: to_address.into(), amount, timeout: timeout.into(), - memo: MemoData::Empty, - _state: PhantomData, + memo: EmptyMemo, } } @@ -79,8 +97,7 @@ impl TransferMsgBuilder { to_address: self.to_address, amount: self.amount, timeout: self.timeout, - memo: MemoData::Text(memo.into()), - _state: PhantomData, + memo: WithMemo { memo: memo.into() }, } } @@ -93,8 +110,7 @@ impl TransferMsgBuilder { to_address: self.to_address, amount: self.amount, timeout: self.timeout, - memo: MemoData::IbcCallbacks(IbcCallbackRequest::source(src_callback)), - _state: PhantomData, + memo: WithSrcCallback { src_callback }, } } @@ -107,8 +123,7 @@ impl TransferMsgBuilder { to_address: self.to_address, amount: self.amount, timeout: self.timeout, - memo: MemoData::IbcCallbacks(IbcCallbackRequest::destination(dst_callback)), - _state: PhantomData, + memo: WithDstCallback { dst_callback }, } } } @@ -123,14 +138,10 @@ impl TransferMsgBuilder { to_address: self.to_address, amount: self.amount, timeout: self.timeout, - memo: match self.memo { - MemoData::IbcCallbacks(IbcCallbackRequest { - src_callback: Some(src_callback), - .. - }) => MemoData::IbcCallbacks(IbcCallbackRequest::both(src_callback, dst_callback)), - _ => unreachable!(), // we know this never happens because of the WithSrcCallback state + memo: WithCallbacks { + src_callback: self.memo.src_callback, + dst_callback, }, - _state: PhantomData, } } } @@ -145,14 +156,10 @@ impl TransferMsgBuilder { to_address: self.to_address, amount: self.amount, timeout: self.timeout, - memo: match self.memo { - MemoData::IbcCallbacks(IbcCallbackRequest { - dest_callback: Some(dst_callback), - .. - }) => MemoData::IbcCallbacks(IbcCallbackRequest::both(src_callback, dst_callback)), - _ => unreachable!(), // we know this never happens because of the WithDstCallback state + memo: WithCallbacks { + src_callback, + dst_callback: self.memo.dst_callback, }, - _state: PhantomData, } } } From 4ca8330c266d16d4b79c9260421e28559e714aaa Mon Sep 17 00:00:00 2001 From: Christoph Otter Date: Mon, 3 Jun 2024 13:52:55 +0200 Subject: [PATCH 3/8] Use TransferMsgBuilder in examples --- contracts/ibc-callbacks/src/contract.rs | 27 ++++++++++++++----------- packages/std/src/ibc/callbacks.rs | 24 +++++++++++++++++++++- 2 files changed, 38 insertions(+), 13 deletions(-) diff --git a/contracts/ibc-callbacks/src/contract.rs b/contracts/ibc-callbacks/src/contract.rs index a0f4223de5..cd2f269f26 100644 --- a/contracts/ibc-callbacks/src/contract.rs +++ b/contracts/ibc-callbacks/src/contract.rs @@ -1,7 +1,7 @@ use cosmwasm_std::{ - entry_point, to_json_binary, to_json_string, Binary, Deps, DepsMut, Empty, Env, - IbcBasicResponse, IbcCallbackRequest, IbcDestinationCallbackMsg, IbcDstCallback, IbcMsg, - IbcSourceCallbackMsg, IbcSrcCallback, IbcTimeout, MessageInfo, Response, StdError, StdResult, + entry_point, to_json_binary, Binary, Deps, DepsMut, Empty, Env, IbcBasicResponse, + IbcDestinationCallbackMsg, IbcDstCallback, IbcSourceCallbackMsg, IbcSrcCallback, IbcTimeout, + MessageInfo, Response, StdError, StdResult, TransferMsgBuilder, }; use crate::msg::{CallbackType, ExecuteMsg, QueryMsg}; @@ -71,16 +71,19 @@ fn execute_transfer( } }; - let transfer_msg = IbcMsg::Transfer { - to_address, - timeout: IbcTimeout::with_timestamp(env.block.time.plus_seconds(timeout_seconds as u64)), + let builder = TransferMsgBuilder::new( channel_id, - amount: coin.clone(), - memo: Some(to_json_string(&match callback_type { - CallbackType::Both => IbcCallbackRequest::both(src_callback, dst_callback), - CallbackType::Src => IbcCallbackRequest::source(src_callback), - CallbackType::Dst => IbcCallbackRequest::destination(dst_callback), - })?), + to_address.clone(), + coin.clone(), + IbcTimeout::with_timestamp(env.block.time.plus_seconds(timeout_seconds as u64)), + ); + let transfer_msg = match callback_type { + CallbackType::Both => builder + .with_src_callback(src_callback) + .with_dst_callback(dst_callback) + .build(), + CallbackType::Src => builder.with_src_callback(src_callback).build(), + CallbackType::Dst => builder.with_dst_callback(dst_callback).build(), }; Ok(Response::new() diff --git a/packages/std/src/ibc/callbacks.rs b/packages/std/src/ibc/callbacks.rs index 1457204398..3eeef3d54e 100644 --- a/packages/std/src/ibc/callbacks.rs +++ b/packages/std/src/ibc/callbacks.rs @@ -15,12 +15,34 @@ use crate::{Addr, IbcAcknowledgement, IbcPacket, Uint64}; /// /// # Example /// +/// Using [`TransferMsgBuilder`](crate::TransferMsgBuilder): /// ```rust /// use cosmwasm_std::{ -/// to_json_string, Coin, IbcCallbackRequest, IbcMsg, IbcSrcCallback, IbcTimeout, Response, +/// to_json_string, Coin, IbcCallbackRequest, TransferMsgBuilder, IbcSrcCallback, IbcTimeout, Response, /// Timestamp, /// }; +/// # use cosmwasm_std::testing::mock_env; +/// # let env = mock_env(); +/// +/// let _transfer = TransferMsgBuilder::new( +/// "channel-0".to_string(), +/// "cosmos1example".to_string(), +/// Coin::new(10u32, "ucoin"), +/// Timestamp::from_seconds(12345), +/// ) +/// .with_src_callback(IbcSrcCallback { +/// address: env.contract.address, +/// gas_limit: None, +/// }) +/// .build(); +/// ``` /// +/// Manual serialization: +/// ```rust +/// use cosmwasm_std::{ +/// to_json_string, Coin, IbcCallbackRequest, IbcMsg, IbcSrcCallback, IbcTimeout, Response, +/// Timestamp, +/// }; /// # use cosmwasm_std::testing::mock_env; /// # let env = mock_env(); /// From bbc86ce109be803e93550b19841680e2b887bd83 Mon Sep 17 00:00:00 2001 From: Christoph Otter Date: Mon, 3 Jun 2024 14:05:52 +0200 Subject: [PATCH 4/8] Undo pub(crate) --- packages/std/src/ibc/callbacks.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/std/src/ibc/callbacks.rs b/packages/std/src/ibc/callbacks.rs index 3eeef3d54e..f110eda639 100644 --- a/packages/std/src/ibc/callbacks.rs +++ b/packages/std/src/ibc/callbacks.rs @@ -61,9 +61,9 @@ use crate::{Addr, IbcAcknowledgement, IbcPacket, Uint64}; pub struct IbcCallbackRequest { // using private fields to force use of the constructors #[serde(skip_serializing_if = "Option::is_none")] - pub(crate) src_callback: Option, + src_callback: Option, #[serde(skip_serializing_if = "Option::is_none")] - pub(crate) dest_callback: Option, + dest_callback: Option, } impl IbcCallbackRequest { From 7f40a4fd82f698c367e17bfbf7a37a314189d681 Mon Sep 17 00:00:00 2001 From: Christoph Otter Date: Mon, 3 Jun 2024 14:22:23 +0200 Subject: [PATCH 5/8] Add docs to TransferMsgBuilder --- packages/std/src/ibc/transfer_msg_builder.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/packages/std/src/ibc/transfer_msg_builder.rs b/packages/std/src/ibc/transfer_msg_builder.rs index 5a2c72ba6a..8e04f34ed5 100644 --- a/packages/std/src/ibc/transfer_msg_builder.rs +++ b/packages/std/src/ibc/transfer_msg_builder.rs @@ -76,6 +76,7 @@ pub struct TransferMsgBuilder { } impl TransferMsgBuilder { + /// Creates a new transfer message with the given parameters and no memo. pub fn new( channel_id: impl Into, to_address: impl Into, @@ -91,6 +92,7 @@ impl TransferMsgBuilder { } } + /// Adds a memo text to the transfer message. pub fn with_memo(self, memo: impl Into) -> TransferMsgBuilder { TransferMsgBuilder { channel_id: self.channel_id, @@ -101,6 +103,10 @@ impl TransferMsgBuilder { } } + /// 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, @@ -114,6 +120,10 @@ impl TransferMsgBuilder { } } + /// 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, @@ -129,6 +139,10 @@ impl TransferMsgBuilder { } impl TransferMsgBuilder { + /// 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, @@ -147,6 +161,10 @@ impl TransferMsgBuilder { } impl TransferMsgBuilder { + /// 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, From d4e629eb32bbd5a79cb52316e1546582a8b3137f Mon Sep 17 00:00:00 2001 From: Christoph Otter Date: Tue, 4 Jun 2024 10:09:29 +0200 Subject: [PATCH 6/8] Update packages/std/src/ibc/callbacks.rs Co-authored-by: Simon Warta <2603011+webmaster128@users.noreply.github.com> --- packages/std/src/ibc/callbacks.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/std/src/ibc/callbacks.rs b/packages/std/src/ibc/callbacks.rs index f110eda639..d85c374a10 100644 --- a/packages/std/src/ibc/callbacks.rs +++ b/packages/std/src/ibc/callbacks.rs @@ -24,7 +24,7 @@ use crate::{Addr, IbcAcknowledgement, IbcPacket, Uint64}; /// # use cosmwasm_std::testing::mock_env; /// # let env = mock_env(); /// -/// let _transfer = TransferMsgBuilder::new( +/// let _msg = TransferMsgBuilder::new( /// "channel-0".to_string(), /// "cosmos1example".to_string(), /// Coin::new(10u32, "ucoin"), From eb4d6a2acaac79fe3440ae6fc2b260e49d1820c7 Mon Sep 17 00:00:00 2001 From: Christoph Otter Date: Tue, 4 Jun 2024 12:04:22 +0200 Subject: [PATCH 7/8] Add MemoSource trait --- packages/std/src/ibc/transfer_msg_builder.rs | 42 ++++++++++++-------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/packages/std/src/ibc/transfer_msg_builder.rs b/packages/std/src/ibc/transfer_msg_builder.rs index 8e04f34ed5..484ef4038b 100644 --- a/packages/std/src/ibc/transfer_msg_builder.rs +++ b/packages/std/src/ibc/transfer_msg_builder.rs @@ -24,44 +24,54 @@ pub struct WithCallbacks { dst_callback: IbcDstCallback, } -impl From for Option { - fn from(_: EmptyMemo) -> Self { +pub trait MemoSource { + fn into_memo(self) -> Option; +} + +impl MemoSource for EmptyMemo { + fn into_memo(self) -> Option { None } } -impl From for Option { - fn from(m: WithMemo) -> Self { - Some(m.memo) +impl MemoSource for WithMemo { + fn into_memo(self) -> Option { + Some(self.memo) } } -impl From for Option { - fn from(s: WithSrcCallback) -> Self { - Some(to_json_string(&IbcCallbackRequest::source(s.src_callback)).unwrap()) +impl MemoSource for WithSrcCallback { + fn into_memo(self) -> Option { + Some(to_json_string(&IbcCallbackRequest::source(self.src_callback)).unwrap()) } } -impl From for Option { - fn from(d: WithDstCallback) -> Self { - Some(to_json_string(&IbcCallbackRequest::destination(d.dst_callback)).unwrap()) +impl MemoSource for WithDstCallback { + fn into_memo(self) -> Option { + Some(to_json_string(&IbcCallbackRequest::destination(self.dst_callback)).unwrap()) } } -impl From for Option { - fn from(c: WithCallbacks) -> Self { - Some(to_json_string(&IbcCallbackRequest::both(c.src_callback, c.dst_callback)).unwrap()) +impl MemoSource for WithCallbacks { + fn into_memo(self) -> Option { + Some( + to_json_string(&IbcCallbackRequest::both( + self.src_callback, + self.dst_callback, + )) + .unwrap(), + ) } } -impl>> TransferMsgBuilder { +impl TransferMsgBuilder { pub fn build(self) -> IbcMsg { IbcMsg::Transfer { channel_id: self.channel_id, to_address: self.to_address, amount: self.amount, timeout: self.timeout, - memo: self.memo.into(), + memo: self.memo.into_memo(), } } } From d373f7815b958d22e7f90815fc751349465c0863 Mon Sep 17 00:00:00 2001 From: Christoph Otter Date: Wed, 5 Jun 2024 11:44:13 +0200 Subject: [PATCH 8/8] Add changelog entry --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b514818c2..362cdef46e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,6 +48,9 @@ and this project adheres to `ibc_source_callback` and `ibc_destination_callback`, as well as the `IbcCallbackRequest` type. ([#2025]) - cosmwasm-vm: Add support for the two new IBC Callbacks entrypoints. ([#2025]) +- cosmwasm-std: Add `TransferMsgBuilder` to more easily create an + `IbcMsg::Transfer` with different kinds of memo values, including IBC + Callbacks memo values. ([#2167]) [#1983]: https://github.com/CosmWasm/cosmwasm/pull/1983 [#2025]: https://github.com/CosmWasm/cosmwasm/pull/2025 @@ -64,6 +67,7 @@ and this project adheres to [#2124]: https://github.com/CosmWasm/cosmwasm/pull/2124 [#2129]: https://github.com/CosmWasm/cosmwasm/pull/2129 [#2166]: https://github.com/CosmWasm/cosmwasm/pull/2166 +[#2167]: https://github.com/CosmWasm/cosmwasm/pull/2167 ### Changed