From 22d9e1b341b79b131893cd1ad85f1dfe8362fc02 Mon Sep 17 00:00:00 2001 From: Cian Hatton Date: Wed, 14 Sep 2022 15:19:39 +0100 Subject: [PATCH 01/11] wip: adding command to display json value for interchain packet data --- .../27-interchain-accounts/client/cli/cli.go | 1 + .../host/client/cli/cli.go | 18 ++++++ .../host/client/cli/tx.go | 61 +++++++++++++++++++ 3 files changed, 80 insertions(+) create mode 100644 modules/apps/27-interchain-accounts/host/client/cli/tx.go diff --git a/modules/apps/27-interchain-accounts/client/cli/cli.go b/modules/apps/27-interchain-accounts/client/cli/cli.go index d9df3024e2e..9163141608a 100644 --- a/modules/apps/27-interchain-accounts/client/cli/cli.go +++ b/modules/apps/27-interchain-accounts/client/cli/cli.go @@ -37,6 +37,7 @@ func NewTxCmd() *cobra.Command { icaTxCmd.AddCommand( controllercli.NewTxCmd(), + hostcli.NewTxCmd(), ) return icaTxCmd diff --git a/modules/apps/27-interchain-accounts/host/client/cli/cli.go b/modules/apps/27-interchain-accounts/host/client/cli/cli.go index 2ae88a48b70..fda6cea1577 100644 --- a/modules/apps/27-interchain-accounts/host/client/cli/cli.go +++ b/modules/apps/27-interchain-accounts/host/client/cli/cli.go @@ -1,6 +1,7 @@ package cli import ( + "github.com/cosmos/cosmos-sdk/client" "github.com/spf13/cobra" ) @@ -20,3 +21,20 @@ func GetQueryCmd() *cobra.Command { return queryCmd } + +// NewTxCmd creates and returns the tx command +func NewTxCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "host", + Short: "interchain-accounts host subcommands", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + + cmd.AddCommand( + generatePacketData(), + ) + + return cmd +} diff --git a/modules/apps/27-interchain-accounts/host/client/cli/tx.go b/modules/apps/27-interchain-accounts/host/client/cli/tx.go new file mode 100644 index 00000000000..4c9de61047f --- /dev/null +++ b/modules/apps/27-interchain-accounts/host/client/cli/tx.go @@ -0,0 +1,61 @@ +package cli + +import ( + "strings" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/spf13/cobra" + + icatypes "github.com/cosmos/ibc-go/v5/modules/apps/27-interchain-accounts/types" +) + +func generatePacketData() *cobra.Command { + cmd := &cobra.Command{ + Use: "generate-packet-data [message]", + Short: "Generate ICA packet data.", + Long: strings.TrimSpace(`Generate ICA packet data.`), // TODO write more here + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + cdc := codec.NewProtoCodec(clientCtx.InterfaceRegistry) + + var msg sdk.Msg + if err := cdc.UnmarshalInterfaceJSON([]byte(args[0]), &msg); err != nil { + return err + } + + icaPacketDataBytes, err := icatypes.SerializeCosmosTx(cdc, []sdk.Msg{msg}) + if err != nil { + return err + } + + memo, err := cmd.Flags().GetString("memo") + if err != nil { + return err + } + + icaPacketData := icatypes.InterchainAccountPacketData{ + Type: icatypes.EXECUTE_TX, + Data: icaPacketDataBytes, + Memo: memo, + } + + if err := icaPacketData.ValidateBasic(); err != nil { + return err + } + + jsonBytes := cdc.MustMarshalJSON(&icaPacketData) + cmd.Println(string(jsonBytes)) + return nil + }, + } + + cmd.Flags().String("memo", "", "") + return cmd +} From 3ecdc1d3ed4bf1b5cb88715dc0d6b2e0ba7d0875 Mon Sep 17 00:00:00 2001 From: Cian Hatton Date: Thu, 15 Sep 2022 15:45:30 +0100 Subject: [PATCH 02/11] tests: adding tests for generatePacketData --- .../host/client/cli/cli.go | 2 +- .../host/client/cli/tx.go | 59 ++++---- .../host/client/cli/tx_test.go | 132 ++++++++++++++++++ 3 files changed, 165 insertions(+), 28 deletions(-) create mode 100644 modules/apps/27-interchain-accounts/host/client/cli/tx_test.go diff --git a/modules/apps/27-interchain-accounts/host/client/cli/cli.go b/modules/apps/27-interchain-accounts/host/client/cli/cli.go index fda6cea1577..d426a1993eb 100644 --- a/modules/apps/27-interchain-accounts/host/client/cli/cli.go +++ b/modules/apps/27-interchain-accounts/host/client/cli/cli.go @@ -33,7 +33,7 @@ func NewTxCmd() *cobra.Command { } cmd.AddCommand( - generatePacketData(), + generatePacketDataCmd(), ) return cmd diff --git a/modules/apps/27-interchain-accounts/host/client/cli/tx.go b/modules/apps/27-interchain-accounts/host/client/cli/tx.go index 4c9de61047f..9b9c38dfa62 100644 --- a/modules/apps/27-interchain-accounts/host/client/cli/tx.go +++ b/modules/apps/27-interchain-accounts/host/client/cli/tx.go @@ -11,7 +11,11 @@ import ( icatypes "github.com/cosmos/ibc-go/v5/modules/apps/27-interchain-accounts/types" ) -func generatePacketData() *cobra.Command { +const ( + memoFlag string = "memo" +) + +func generatePacketDataCmd() *cobra.Command { cmd := &cobra.Command{ Use: "generate-packet-data [message]", Short: "Generate ICA packet data.", @@ -22,40 +26,41 @@ func generatePacketData() *cobra.Command { if err != nil { return err } - cdc := codec.NewProtoCodec(clientCtx.InterfaceRegistry) - - var msg sdk.Msg - if err := cdc.UnmarshalInterfaceJSON([]byte(args[0]), &msg); err != nil { - return err - } - - icaPacketDataBytes, err := icatypes.SerializeCosmosTx(cdc, []sdk.Msg{msg}) + memo, err := cmd.Flags().GetString(memoFlag) if err != nil { return err } + packetDataBytes, err := generatePacketData(cdc, []byte(args[0]), memo) + cmd.Println(string(packetDataBytes)) + return nil + }, + } - memo, err := cmd.Flags().GetString("memo") - if err != nil { - return err - } + cmd.Flags().String(memoFlag, "", "") + return cmd +} - icaPacketData := icatypes.InterchainAccountPacketData{ - Type: icatypes.EXECUTE_TX, - Data: icaPacketDataBytes, - Memo: memo, - } +func generatePacketData(cdc *codec.ProtoCodec, msgBytes []byte, memo string) ([]byte, error) { + var msg sdk.Msg + if err := cdc.UnmarshalInterfaceJSON(msgBytes, &msg); err != nil { + return nil, err + } - if err := icaPacketData.ValidateBasic(); err != nil { - return err - } + icaPacketDataBytes, err := icatypes.SerializeCosmosTx(cdc, []sdk.Msg{msg}) + if err != nil { + return nil, err + } - jsonBytes := cdc.MustMarshalJSON(&icaPacketData) - cmd.Println(string(jsonBytes)) - return nil - }, + icaPacketData := icatypes.InterchainAccountPacketData{ + Type: icatypes.EXECUTE_TX, + Data: icaPacketDataBytes, + Memo: memo, } - cmd.Flags().String("memo", "", "") - return cmd + if err := icaPacketData.ValidateBasic(); err != nil { + return nil, err + } + + return cdc.MarshalJSON(&icaPacketData) } diff --git a/modules/apps/27-interchain-accounts/host/client/cli/tx_test.go b/modules/apps/27-interchain-accounts/host/client/cli/tx_test.go new file mode 100644 index 00000000000..c13ae55271b --- /dev/null +++ b/modules/apps/27-interchain-accounts/host/client/cli/tx_test.go @@ -0,0 +1,132 @@ +package cli + +import ( + "testing" + + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + "github.com/stretchr/testify/require" + + icatypes "github.com/cosmos/ibc-go/v5/modules/apps/27-interchain-accounts/types" +) + +const msgDelegateMessage = `{ + "@type": "/cosmos.staking.v1beta1.MsgDelegate", + "delegator_address": "cosmos15ccshhmp0gsx29qpqq6g4zmltnnvgmyu9ueuadh9y2nc5zj0szls5gtddz", + "validator_address": "cosmosvaloper1qnk2n4nlkpw9xfqntladh74w6ujtulwnmxnh3k", + "amount": { + "denom": "stake", + "amount": "1000" + } +}` + +const bankSendMessage = `{ + "@type":"/cosmos.bank.v1beta1.MsgSend", + "from_address":"cosmos15ccshhmp0gsx29qpqq6g4zmltnnvgmyu9ueuadh9y2nc5zj0szls5gtddz", + "to_address":"cosmos10h9stc5v6ntgeygf5xf945njqq5h32r53uquvw", + "amount": [ + { + "denom": "stake", + "amount": "1000" + } + ] +}` + +func TestGeneratePacketData(t *testing.T) { + tests := []struct { + name string + memo string + expectedPass bool + message string + registerInterfaceFn func(registry codectypes.InterfaceRegistry) + assertionFn func(msg sdk.Msg) + }{ + { + name: "packet data generation succeeds (MsgDelegate)", + memo: "non-empty-memo", + expectedPass: true, + message: msgDelegateMessage, + registerInterfaceFn: stakingtypes.RegisterInterfaces, + assertionFn: func(msg sdk.Msg) { + msgDelegate := msg.(*stakingtypes.MsgDelegate) + require.Equal(t, "cosmos15ccshhmp0gsx29qpqq6g4zmltnnvgmyu9ueuadh9y2nc5zj0szls5gtddz", msgDelegate.DelegatorAddress) + require.Equal(t, "cosmosvaloper1qnk2n4nlkpw9xfqntladh74w6ujtulwnmxnh3k", msgDelegate.ValidatorAddress) + require.Equal(t, "stake", msgDelegate.Amount.Denom) + require.Equal(t, uint64(1000), msgDelegate.Amount.Amount.Uint64()) + }, + }, + { + name: "packet data generation succeeds (MsgSend)", + memo: "non-empty-memo", + expectedPass: true, + message: bankSendMessage, + registerInterfaceFn: banktypes.RegisterInterfaces, + assertionFn: func(msg sdk.Msg) { + bankSendMsg := msg.(*banktypes.MsgSend) + require.Equal(t, "cosmos15ccshhmp0gsx29qpqq6g4zmltnnvgmyu9ueuadh9y2nc5zj0szls5gtddz", bankSendMsg.FromAddress) + require.Equal(t, "cosmos10h9stc5v6ntgeygf5xf945njqq5h32r53uquvw", bankSendMsg.ToAddress) + require.Equal(t, "stake", bankSendMsg.Amount.GetDenomByIndex(0)) + require.Equal(t, uint64(1000), bankSendMsg.Amount[0].Amount.Uint64()) + }, + }, + { + name: "empty memo is valid", + memo: "", + expectedPass: true, + message: msgDelegateMessage, + registerInterfaceFn: stakingtypes.RegisterInterfaces, + assertionFn: func(msg sdk.Msg) { + msgDelegate := msg.(*stakingtypes.MsgDelegate) + require.Equal(t, "cosmos15ccshhmp0gsx29qpqq6g4zmltnnvgmyu9ueuadh9y2nc5zj0szls5gtddz", msgDelegate.DelegatorAddress) + require.Equal(t, "cosmosvaloper1qnk2n4nlkpw9xfqntladh74w6ujtulwnmxnh3k", msgDelegate.ValidatorAddress) + require.Equal(t, "stake", msgDelegate.Amount.Denom) + require.Equal(t, uint64(1000), msgDelegate.Amount.Amount.Uint64()) + }, + }, + { + name: "invalid message string", + memo: "", + expectedPass: false, + message: "{}", + registerInterfaceFn: func(codectypes.InterfaceRegistry) {}, + assertionFn: func(sdk.Msg) {}, + }, + } + + for _, tt := range tests { + tt := tt + ir := codectypes.NewInterfaceRegistry() + tt.registerInterfaceFn(ir) + + cdc := codec.NewProtoCodec(ir) + t.Run(tt.name, func(t *testing.T) { + bz, err := generatePacketData(cdc, []byte(tt.message), tt.memo) + if !tt.expectedPass { + require.Error(t, err) + require.Nil(t, bz) + return + } + require.NoError(t, err) + require.NotNil(t, bz) + + packetData := icatypes.InterchainAccountPacketData{} + err = cdc.UnmarshalJSON(bz, &packetData) + require.NoError(t, err) + + require.NoError(t, err) + require.Equal(t, icatypes.EXECUTE_TX, packetData.Type) + require.Equal(t, tt.memo, packetData.Memo) + + data := packetData.Data + messages, err := icatypes.DeserializeCosmosTx(cdc, data) + + require.NoError(t, err) + require.NotNil(t, messages) + + tt.assertionFn(messages[0]) + }) + } +} From fe4880a8454e310de7b0cb17e52f408c4d079c7d Mon Sep 17 00:00:00 2001 From: Cian Hatton Date: Thu, 15 Sep 2022 16:14:58 +0100 Subject: [PATCH 03/11] chore: adding changelog entry --- CHANGELOG.md | 1 + .../host/client/cli/tx.go | 16 ++++-- .../host/client/cli/tx_test.go | 49 +++++++++---------- 3 files changed, 34 insertions(+), 32 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c555e6e586..9348e328d8d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -96,6 +96,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (apps/27-interchain-accounts) [\#2157](https://github.com/cosmos/ibc-go/pull/2157) Adding `IsMiddlewareEnabled` functionality to enforce calls to ICS27 msg server to *not* route to the underlying application. * (apps/27-interchain-accounts) [\#2177](https://github.com/cosmos/ibc-go/pull/2177) Adding `IsMiddlewareEnabled` flag to interchain accounts `ActiveChannel` genesis type. * (apps/27-interchain-accounts) [\#2140](https://github.com/cosmos/ibc-go/pull/2140) Adding migration handler to ICS27 `controller` submodule to assert ownership of channel capabilities and set middleware enabled flag for existing channels. The ICS27 module consensus version has been bumped from 1 to 2. +* (apps/27-interchain-accounts) [\#2297](https://github.com/cosmos/ibc-go/pull/2297) Adding cli command to generate ICS27 packet data. ### Features diff --git a/modules/apps/27-interchain-accounts/host/client/cli/tx.go b/modules/apps/27-interchain-accounts/host/client/cli/tx.go index 9b9c38dfa62..1f884d1a4d5 100644 --- a/modules/apps/27-interchain-accounts/host/client/cli/tx.go +++ b/modules/apps/27-interchain-accounts/host/client/cli/tx.go @@ -1,11 +1,12 @@ package cli import ( - "strings" + "fmt" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/version" "github.com/spf13/cobra" icatypes "github.com/cosmos/ibc-go/v5/modules/apps/27-interchain-accounts/types" @@ -18,9 +19,12 @@ const ( func generatePacketDataCmd() *cobra.Command { cmd := &cobra.Command{ Use: "generate-packet-data [message]", - Short: "Generate ICA packet data.", - Long: strings.TrimSpace(`Generate ICA packet data.`), // TODO write more here - Args: cobra.ExactArgs(1), + Short: "Generates ICA packet data.", + Long: fmt.Sprintf(`generate-packet-data accepts a message string and serializes it +into packet data which is outputted to stdout. It can be used in conjuction with "%s ica controller send-tx" +which submits pre-built packet data containing messages to be executed on the host chain. +`, version.AppName), + Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { clientCtx, err := client.GetClientTxContext(cmd) if err != nil { @@ -37,10 +41,12 @@ func generatePacketDataCmd() *cobra.Command { }, } - cmd.Flags().String(memoFlag, "", "") + cmd.Flags().String(memoFlag, "", "an optional memo to be included in the interchain account packet data") return cmd } +// generatePacketData takes in message bytes and a memo and serializes the message into an +// instance of InterchainAccountPacketData which is returned as bytes. func generatePacketData(cdc *codec.ProtoCodec, msgBytes []byte, memo string) ([]byte, error) { var msg sdk.Msg if err := cdc.UnmarshalInterfaceJSON(msgBytes, &msg); err != nil { diff --git a/modules/apps/27-interchain-accounts/host/client/cli/tx_test.go b/modules/apps/27-interchain-accounts/host/client/cli/tx_test.go index c13ae55271b..9099c4b6c9a 100644 --- a/modules/apps/27-interchain-accounts/host/client/cli/tx_test.go +++ b/modules/apps/27-interchain-accounts/host/client/cli/tx_test.go @@ -14,25 +14,25 @@ import ( ) const msgDelegateMessage = `{ - "@type": "/cosmos.staking.v1beta1.MsgDelegate", - "delegator_address": "cosmos15ccshhmp0gsx29qpqq6g4zmltnnvgmyu9ueuadh9y2nc5zj0szls5gtddz", - "validator_address": "cosmosvaloper1qnk2n4nlkpw9xfqntladh74w6ujtulwnmxnh3k", - "amount": { - "denom": "stake", - "amount": "1000" - } + "@type": "/cosmos.staking.v1beta1.MsgDelegate", + "delegator_address": "cosmos15ccshhmp0gsx29qpqq6g4zmltnnvgmyu9ueuadh9y2nc5zj0szls5gtddz", + "validator_address": "cosmosvaloper1qnk2n4nlkpw9xfqntladh74w6ujtulwnmxnh3k", + "amount": { + "denom": "stake", + "amount": "1000" + } }` const bankSendMessage = `{ - "@type":"/cosmos.bank.v1beta1.MsgSend", - "from_address":"cosmos15ccshhmp0gsx29qpqq6g4zmltnnvgmyu9ueuadh9y2nc5zj0szls5gtddz", - "to_address":"cosmos10h9stc5v6ntgeygf5xf945njqq5h32r53uquvw", - "amount": [ - { - "denom": "stake", - "amount": "1000" - } - ] + "@type":"/cosmos.bank.v1beta1.MsgSend", + "from_address":"cosmos15ccshhmp0gsx29qpqq6g4zmltnnvgmyu9ueuadh9y2nc5zj0szls5gtddz", + "to_address":"cosmos10h9stc5v6ntgeygf5xf945njqq5h32r53uquvw", + "amount": [ + { + "denom": "stake", + "amount": "1000" + } + ] }` func TestGeneratePacketData(t *testing.T) { @@ -51,7 +51,8 @@ func TestGeneratePacketData(t *testing.T) { message: msgDelegateMessage, registerInterfaceFn: stakingtypes.RegisterInterfaces, assertionFn: func(msg sdk.Msg) { - msgDelegate := msg.(*stakingtypes.MsgDelegate) + msgDelegate, ok := msg.(*stakingtypes.MsgDelegate) + require.True(t, ok) require.Equal(t, "cosmos15ccshhmp0gsx29qpqq6g4zmltnnvgmyu9ueuadh9y2nc5zj0szls5gtddz", msgDelegate.DelegatorAddress) require.Equal(t, "cosmosvaloper1qnk2n4nlkpw9xfqntladh74w6ujtulwnmxnh3k", msgDelegate.ValidatorAddress) require.Equal(t, "stake", msgDelegate.Amount.Denom) @@ -65,7 +66,8 @@ func TestGeneratePacketData(t *testing.T) { message: bankSendMessage, registerInterfaceFn: banktypes.RegisterInterfaces, assertionFn: func(msg sdk.Msg) { - bankSendMsg := msg.(*banktypes.MsgSend) + bankSendMsg, ok := msg.(*banktypes.MsgSend) + require.True(t, ok) require.Equal(t, "cosmos15ccshhmp0gsx29qpqq6g4zmltnnvgmyu9ueuadh9y2nc5zj0szls5gtddz", bankSendMsg.FromAddress) require.Equal(t, "cosmos10h9stc5v6ntgeygf5xf945njqq5h32r53uquvw", bankSendMsg.ToAddress) require.Equal(t, "stake", bankSendMsg.Amount.GetDenomByIndex(0)) @@ -78,19 +80,12 @@ func TestGeneratePacketData(t *testing.T) { expectedPass: true, message: msgDelegateMessage, registerInterfaceFn: stakingtypes.RegisterInterfaces, - assertionFn: func(msg sdk.Msg) { - msgDelegate := msg.(*stakingtypes.MsgDelegate) - require.Equal(t, "cosmos15ccshhmp0gsx29qpqq6g4zmltnnvgmyu9ueuadh9y2nc5zj0szls5gtddz", msgDelegate.DelegatorAddress) - require.Equal(t, "cosmosvaloper1qnk2n4nlkpw9xfqntladh74w6ujtulwnmxnh3k", msgDelegate.ValidatorAddress) - require.Equal(t, "stake", msgDelegate.Amount.Denom) - require.Equal(t, uint64(1000), msgDelegate.Amount.Amount.Uint64()) - }, + assertionFn: func(msg sdk.Msg) {}, }, { name: "invalid message string", - memo: "", expectedPass: false, - message: "{}", + message: "", registerInterfaceFn: func(codectypes.InterfaceRegistry) {}, assertionFn: func(sdk.Msg) {}, }, From 4f3ef3097df5acb41f729e1d82a8f44e8d47ef46 Mon Sep 17 00:00:00 2001 From: Cian Hatton Date: Thu, 15 Sep 2022 16:15:59 +0100 Subject: [PATCH 04/11] chore: fix useless assignment to local var --- modules/apps/27-interchain-accounts/host/client/cli/tx.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/apps/27-interchain-accounts/host/client/cli/tx.go b/modules/apps/27-interchain-accounts/host/client/cli/tx.go index 1f884d1a4d5..ee76bdf895e 100644 --- a/modules/apps/27-interchain-accounts/host/client/cli/tx.go +++ b/modules/apps/27-interchain-accounts/host/client/cli/tx.go @@ -36,6 +36,9 @@ which submits pre-built packet data containing messages to be executed on the ho return err } packetDataBytes, err := generatePacketData(cdc, []byte(args[0]), memo) + if err != nil { + return err + } cmd.Println(string(packetDataBytes)) return nil }, From 4e6ed4ebcb8422db13d1a305f9cd26a22bb99664 Mon Sep 17 00:00:00 2001 From: Cian Hatton Date: Thu, 15 Sep 2022 16:17:25 +0100 Subject: [PATCH 05/11] chore: fix typo --- modules/apps/27-interchain-accounts/host/client/cli/tx.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/apps/27-interchain-accounts/host/client/cli/tx.go b/modules/apps/27-interchain-accounts/host/client/cli/tx.go index ee76bdf895e..0fbbc9840ad 100644 --- a/modules/apps/27-interchain-accounts/host/client/cli/tx.go +++ b/modules/apps/27-interchain-accounts/host/client/cli/tx.go @@ -21,7 +21,7 @@ func generatePacketDataCmd() *cobra.Command { Use: "generate-packet-data [message]", Short: "Generates ICA packet data.", Long: fmt.Sprintf(`generate-packet-data accepts a message string and serializes it -into packet data which is outputted to stdout. It can be used in conjuction with "%s ica controller send-tx" +into packet data which is outputted to stdout. It can be used in conjunction with "%s ica controller send-tx" which submits pre-built packet data containing messages to be executed on the host chain. `, version.AppName), Args: cobra.ExactArgs(1), From 8645a8b62672e222046d6c3047bda9d06b482700 Mon Sep 17 00:00:00 2001 From: Cian Hatton Date: Wed, 21 Sep 2022 09:40:25 +0100 Subject: [PATCH 06/11] chore: addressing PR feedback --- .../host/client/cli/tx.go | 14 +++--- .../host/client/cli/tx_test.go | 47 ++++++++++--------- 2 files changed, 32 insertions(+), 29 deletions(-) diff --git a/modules/apps/27-interchain-accounts/host/client/cli/tx.go b/modules/apps/27-interchain-accounts/host/client/cli/tx.go index 0fbbc9840ad..6f4e80abcf7 100644 --- a/modules/apps/27-interchain-accounts/host/client/cli/tx.go +++ b/modules/apps/27-interchain-accounts/host/client/cli/tx.go @@ -1,12 +1,9 @@ package cli import ( - "fmt" - "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/version" "github.com/spf13/cobra" icatypes "github.com/cosmos/ibc-go/v5/modules/apps/27-interchain-accounts/types" @@ -20,26 +17,31 @@ func generatePacketDataCmd() *cobra.Command { cmd := &cobra.Command{ Use: "generate-packet-data [message]", Short: "Generates ICA packet data.", - Long: fmt.Sprintf(`generate-packet-data accepts a message string and serializes it -into packet data which is outputted to stdout. It can be used in conjunction with "%s ica controller send-tx" + Long: `generate-packet-data accepts a message string and serializes it +into packet data which is outputted to stdout. It can be used in conjunction with send-tx" which submits pre-built packet data containing messages to be executed on the host chain. -`, version.AppName), +`, Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { clientCtx, err := client.GetClientTxContext(cmd) if err != nil { return err } + cdc := codec.NewProtoCodec(clientCtx.InterfaceRegistry) + memo, err := cmd.Flags().GetString(memoFlag) if err != nil { return err } + packetDataBytes, err := generatePacketData(cdc, []byte(args[0]), memo) if err != nil { return err } + cmd.Println(string(packetDataBytes)) + return nil }, } diff --git a/modules/apps/27-interchain-accounts/host/client/cli/tx_test.go b/modules/apps/27-interchain-accounts/host/client/cli/tx_test.go index 9099c4b6c9a..a95ebc012bb 100644 --- a/modules/apps/27-interchain-accounts/host/client/cli/tx_test.go +++ b/modules/apps/27-interchain-accounts/host/client/cli/tx_test.go @@ -91,37 +91,38 @@ func TestGeneratePacketData(t *testing.T) { }, } - for _, tt := range tests { - tt := tt + for _, tc := range tests { + tc := tc ir := codectypes.NewInterfaceRegistry() - tt.registerInterfaceFn(ir) + tc.registerInterfaceFn(ir) cdc := codec.NewProtoCodec(ir) - t.Run(tt.name, func(t *testing.T) { - bz, err := generatePacketData(cdc, []byte(tt.message), tt.memo) - if !tt.expectedPass { - require.Error(t, err) - require.Nil(t, bz) - return - } - require.NoError(t, err) - require.NotNil(t, bz) - packetData := icatypes.InterchainAccountPacketData{} - err = cdc.UnmarshalJSON(bz, &packetData) - require.NoError(t, err) + t.Run(tc.name, func(t *testing.T) { + bz, err := generatePacketData(cdc, []byte(tc.message), tc.memo) + + if tc.expectedPass { + require.NoError(t, err) + require.NotNil(t, bz) - require.NoError(t, err) - require.Equal(t, icatypes.EXECUTE_TX, packetData.Type) - require.Equal(t, tt.memo, packetData.Memo) + packetData := icatypes.InterchainAccountPacketData{} + err = cdc.UnmarshalJSON(bz, &packetData) + require.NoError(t, err) - data := packetData.Data - messages, err := icatypes.DeserializeCosmosTx(cdc, data) + require.Equal(t, icatypes.EXECUTE_TX, packetData.Type) + require.Equal(t, tc.memo, packetData.Memo) - require.NoError(t, err) - require.NotNil(t, messages) + data := packetData.Data + messages, err := icatypes.DeserializeCosmosTx(cdc, data) - tt.assertionFn(messages[0]) + require.NoError(t, err) + require.NotNil(t, messages) + + tc.assertionFn(messages[0]) + } else { + require.Error(t, err) + require.Nil(t, bz) + } }) } } From cf2179f75e537b06d331c8a8fc951e4b95a5b74b Mon Sep 17 00:00:00 2001 From: Cian Hatton Date: Thu, 22 Sep 2022 16:39:36 +0100 Subject: [PATCH 07/11] chore: bumping imports --- modules/apps/27-interchain-accounts/host/client/cli/tx.go | 2 +- modules/apps/27-interchain-accounts/host/client/cli/tx_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/apps/27-interchain-accounts/host/client/cli/tx.go b/modules/apps/27-interchain-accounts/host/client/cli/tx.go index 6f4e80abcf7..c67e57914ab 100644 --- a/modules/apps/27-interchain-accounts/host/client/cli/tx.go +++ b/modules/apps/27-interchain-accounts/host/client/cli/tx.go @@ -6,7 +6,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/spf13/cobra" - icatypes "github.com/cosmos/ibc-go/v5/modules/apps/27-interchain-accounts/types" + icatypes "github.com/cosmos/ibc-go/v6/modules/apps/27-interchain-accounts/types" ) const ( diff --git a/modules/apps/27-interchain-accounts/host/client/cli/tx_test.go b/modules/apps/27-interchain-accounts/host/client/cli/tx_test.go index a95ebc012bb..ae6a9c2b76b 100644 --- a/modules/apps/27-interchain-accounts/host/client/cli/tx_test.go +++ b/modules/apps/27-interchain-accounts/host/client/cli/tx_test.go @@ -10,7 +10,7 @@ import ( stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/stretchr/testify/require" - icatypes "github.com/cosmos/ibc-go/v5/modules/apps/27-interchain-accounts/types" + icatypes "github.com/cosmos/ibc-go/v6/modules/apps/27-interchain-accounts/types" ) const msgDelegateMessage = `{ From 5ae13d38999cf8f5239d22bba6a96f1c6d4ca6b9 Mon Sep 17 00:00:00 2001 From: Cian Hatton Date: Fri, 23 Sep 2022 10:18:28 +0100 Subject: [PATCH 08/11] feat: adding support for both single and multiple messages --- .../host/client/cli/tx.go | 41 ++++++++++- .../host/client/cli/tx_test.go | 73 +++++++++++++------ 2 files changed, 88 insertions(+), 26 deletions(-) diff --git a/modules/apps/27-interchain-accounts/host/client/cli/tx.go b/modules/apps/27-interchain-accounts/host/client/cli/tx.go index c67e57914ab..afe6da691e2 100644 --- a/modules/apps/27-interchain-accounts/host/client/cli/tx.go +++ b/modules/apps/27-interchain-accounts/host/client/cli/tx.go @@ -1,6 +1,8 @@ package cli import ( + "encoding/json" + "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" @@ -53,12 +55,45 @@ which submits pre-built packet data containing messages to be executed on the ho // generatePacketData takes in message bytes and a memo and serializes the message into an // instance of InterchainAccountPacketData which is returned as bytes. func generatePacketData(cdc *codec.ProtoCodec, msgBytes []byte, memo string) ([]byte, error) { - var msg sdk.Msg - if err := cdc.UnmarshalInterfaceJSON(msgBytes, &msg); err != nil { + sdkMessages, err := convertBytesIntoSdkMessages(cdc, msgBytes) + if err != nil { return nil, err } - icaPacketDataBytes, err := icatypes.SerializeCosmosTx(cdc, []sdk.Msg{msg}) + return generateIcaPacketDataFromSdkMessages(cdc, sdkMessages, memo) +} + +// convertBytesIntoSdkMessages returns a list of sdk messages from bytes. The bytes can be in the form of a single +// message, or a json array of messages. +func convertBytesIntoSdkMessages(cdc *codec.ProtoCodec, msgBytes []byte) ([]sdk.Msg, error) { + var rawMessages []json.RawMessage + if err := json.Unmarshal(msgBytes, &rawMessages); err != nil { + // if we fail to unmarshal a list of messages, we assume we are just dealing with a single message. + // in this case we return a list of a single item. + var msg sdk.Msg + if err := cdc.UnmarshalInterfaceJSON(msgBytes, &msg); err != nil { + return nil, err + } + + return []sdk.Msg{msg}, nil + } + + sdkMessages := make([]sdk.Msg, len(rawMessages)) + for i, anyJSON := range rawMessages { + var msg sdk.Msg + if err := cdc.UnmarshalInterfaceJSON(anyJSON, &msg); err != nil { + return nil, err + } + + sdkMessages[i] = msg + } + + return sdkMessages, nil +} + +// generateIcaPacketDataFromSdkMessages generates ica packet data as bytes from a given set of sdk messages and a memo. +func generateIcaPacketDataFromSdkMessages(cdc *codec.ProtoCodec, sdkMessages []sdk.Msg, memo string) ([]byte, error) { + icaPacketDataBytes, err := icatypes.SerializeCosmosTx(cdc, sdkMessages) if err != nil { return nil, err } diff --git a/modules/apps/27-interchain-accounts/host/client/cli/tx_test.go b/modules/apps/27-interchain-accounts/host/client/cli/tx_test.go index ae6a9c2b76b..7c4461921ee 100644 --- a/modules/apps/27-interchain-accounts/host/client/cli/tx_test.go +++ b/modules/apps/27-interchain-accounts/host/client/cli/tx_test.go @@ -1,6 +1,7 @@ package cli import ( + "fmt" "testing" "github.com/cosmos/cosmos-sdk/codec" @@ -35,6 +36,8 @@ const bankSendMessage = `{ ] }` +var multiMsg = fmt.Sprintf("[ %s, %s ]", msgDelegateMessage, bankSendMessage) + func TestGeneratePacketData(t *testing.T) { tests := []struct { name string @@ -42,21 +45,30 @@ func TestGeneratePacketData(t *testing.T) { expectedPass bool message string registerInterfaceFn func(registry codectypes.InterfaceRegistry) - assertionFn func(msg sdk.Msg) + assertionFn func(t *testing.T, msgs []sdk.Msg) }{ + { + name: "multi message", + memo: "", + expectedPass: true, + message: multiMsg, + registerInterfaceFn: func(registry codectypes.InterfaceRegistry) { + stakingtypes.RegisterInterfaces(registry) + banktypes.RegisterInterfaces(registry) + }, + assertionFn: func(t *testing.T, msgs []sdk.Msg) { + assertMsgDelegate(t, msgs, 0) + assertMsgBankSend(t, msgs, 1) + }, + }, { name: "packet data generation succeeds (MsgDelegate)", memo: "non-empty-memo", expectedPass: true, message: msgDelegateMessage, registerInterfaceFn: stakingtypes.RegisterInterfaces, - assertionFn: func(msg sdk.Msg) { - msgDelegate, ok := msg.(*stakingtypes.MsgDelegate) - require.True(t, ok) - require.Equal(t, "cosmos15ccshhmp0gsx29qpqq6g4zmltnnvgmyu9ueuadh9y2nc5zj0szls5gtddz", msgDelegate.DelegatorAddress) - require.Equal(t, "cosmosvaloper1qnk2n4nlkpw9xfqntladh74w6ujtulwnmxnh3k", msgDelegate.ValidatorAddress) - require.Equal(t, "stake", msgDelegate.Amount.Denom) - require.Equal(t, uint64(1000), msgDelegate.Amount.Amount.Uint64()) + assertionFn: func(t *testing.T, msgs []sdk.Msg) { + assertMsgDelegate(t, msgs, 0) }, }, { @@ -65,13 +77,8 @@ func TestGeneratePacketData(t *testing.T) { expectedPass: true, message: bankSendMessage, registerInterfaceFn: banktypes.RegisterInterfaces, - assertionFn: func(msg sdk.Msg) { - bankSendMsg, ok := msg.(*banktypes.MsgSend) - require.True(t, ok) - require.Equal(t, "cosmos15ccshhmp0gsx29qpqq6g4zmltnnvgmyu9ueuadh9y2nc5zj0szls5gtddz", bankSendMsg.FromAddress) - require.Equal(t, "cosmos10h9stc5v6ntgeygf5xf945njqq5h32r53uquvw", bankSendMsg.ToAddress) - require.Equal(t, "stake", bankSendMsg.Amount.GetDenomByIndex(0)) - require.Equal(t, uint64(1000), bankSendMsg.Amount[0].Amount.Uint64()) + assertionFn: func(t *testing.T, msgs []sdk.Msg) { + assertMsgBankSend(t, msgs, 0) }, }, { @@ -80,21 +87,21 @@ func TestGeneratePacketData(t *testing.T) { expectedPass: true, message: msgDelegateMessage, registerInterfaceFn: stakingtypes.RegisterInterfaces, - assertionFn: func(msg sdk.Msg) {}, + assertionFn: nil, }, { - name: "invalid message string", - expectedPass: false, - message: "", - registerInterfaceFn: func(codectypes.InterfaceRegistry) {}, - assertionFn: func(sdk.Msg) {}, + name: "invalid message string", + expectedPass: false, + message: "", }, } for _, tc := range tests { tc := tc ir := codectypes.NewInterfaceRegistry() - tc.registerInterfaceFn(ir) + if tc.registerInterfaceFn != nil { + tc.registerInterfaceFn(ir) + } cdc := codec.NewProtoCodec(ir) @@ -118,7 +125,9 @@ func TestGeneratePacketData(t *testing.T) { require.NoError(t, err) require.NotNil(t, messages) - tc.assertionFn(messages[0]) + if tc.assertionFn != nil { + tc.assertionFn(t, messages) + } } else { require.Error(t, err) require.Nil(t, bz) @@ -126,3 +135,21 @@ func TestGeneratePacketData(t *testing.T) { }) } } + +func assertMsgBankSend(t *testing.T, msgs []sdk.Msg, idx int) { + bankSendMsg, ok := msgs[idx].(*banktypes.MsgSend) + require.True(t, ok) + require.Equal(t, "cosmos15ccshhmp0gsx29qpqq6g4zmltnnvgmyu9ueuadh9y2nc5zj0szls5gtddz", bankSendMsg.FromAddress) + require.Equal(t, "cosmos10h9stc5v6ntgeygf5xf945njqq5h32r53uquvw", bankSendMsg.ToAddress) + require.Equal(t, "stake", bankSendMsg.Amount.GetDenomByIndex(0)) + require.Equal(t, uint64(1000), bankSendMsg.Amount[0].Amount.Uint64()) +} + +func assertMsgDelegate(t *testing.T, msgs []sdk.Msg, idx int) { + msgDelegate, ok := msgs[idx].(*stakingtypes.MsgDelegate) + require.True(t, ok) + require.Equal(t, "cosmos15ccshhmp0gsx29qpqq6g4zmltnnvgmyu9ueuadh9y2nc5zj0szls5gtddz", msgDelegate.DelegatorAddress) + require.Equal(t, "cosmosvaloper1qnk2n4nlkpw9xfqntladh74w6ujtulwnmxnh3k", msgDelegate.ValidatorAddress) + require.Equal(t, "stake", msgDelegate.Amount.Denom) + require.Equal(t, uint64(1000), msgDelegate.Amount.Amount.Uint64()) +} From e3066370fed7bb85ed385a578dc8a6dc772f2663 Mon Sep 17 00:00:00 2001 From: Cian Hatton Date: Mon, 26 Sep 2022 12:53:32 +0100 Subject: [PATCH 09/11] chore: addressing PR feedback --- .../host/client/cli/cli.go | 2 +- .../host/client/cli/tx.go | 33 +++++++++++++++++++ .../host/client/cli/tx_test.go | 18 +++++----- 3 files changed, 43 insertions(+), 10 deletions(-) diff --git a/modules/apps/27-interchain-accounts/host/client/cli/cli.go b/modules/apps/27-interchain-accounts/host/client/cli/cli.go index d426a1993eb..4a7ed942c5b 100644 --- a/modules/apps/27-interchain-accounts/host/client/cli/cli.go +++ b/modules/apps/27-interchain-accounts/host/client/cli/cli.go @@ -26,7 +26,7 @@ func GetQueryCmd() *cobra.Command { func NewTxCmd() *cobra.Command { cmd := &cobra.Command{ Use: "host", - Short: "interchain-accounts host subcommands", + Short: "IBC interchain accounts host transaction", DisableFlagParsing: true, SuggestionsMinimumDistance: 2, RunE: client.ValidateCmd, diff --git a/modules/apps/27-interchain-accounts/host/client/cli/tx.go b/modules/apps/27-interchain-accounts/host/client/cli/tx.go index afe6da691e2..cd5eee798c9 100644 --- a/modules/apps/27-interchain-accounts/host/client/cli/tx.go +++ b/modules/apps/27-interchain-accounts/host/client/cli/tx.go @@ -23,6 +23,39 @@ func generatePacketDataCmd() *cobra.Command { into packet data which is outputted to stdout. It can be used in conjunction with send-tx" which submits pre-built packet data containing messages to be executed on the host chain. `, + Example: ` tx interchain-accounts host generate-packet-data '{ + "@type":"/cosmos.bank.v1beta1.MsgSend", + "from_address":"cosmos15ccshhmp0gsx29qpqq6g4zmltnnvgmyu9ueuadh9y2nc5zj0szls5gtddz", + "to_address":"cosmos10h9stc5v6ntgeygf5xf945njqq5h32r53uquvw", + "amount": [ + { + "denom": "stake", + "amount": "1000" + } + ] +}' --memo memo + + + tx interchain-accounts host generate-packet-data '[{ + "@type":"/cosmos.bank.v1beta1.MsgSend", + "from_address":"cosmos15ccshhmp0gsx29qpqq6g4zmltnnvgmyu9ueuadh9y2nc5zj0szls5gtddz", + "to_address":"cosmos10h9stc5v6ntgeygf5xf945njqq5h32r53uquvw", + "amount": [ + { + "denom": "stake", + "amount": "1000" + } + ] +}, +{ + "@type": "/cosmos.staking.v1beta1.MsgDelegate", + "delegator_address": "cosmos15ccshhmp0gsx29qpqq6g4zmltnnvgmyu9ueuadh9y2nc5zj0szls5gtddz", + "validator_address": "cosmosvaloper1qnk2n4nlkpw9xfqntladh74w6ujtulwnmxnh3k", + "amount": { + "denom": "stake", + "amount": "1000" + } +}]'`, Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { clientCtx, err := client.GetClientTxContext(cmd) diff --git a/modules/apps/27-interchain-accounts/host/client/cli/tx_test.go b/modules/apps/27-interchain-accounts/host/client/cli/tx_test.go index 7c4461921ee..127e89fd784 100644 --- a/modules/apps/27-interchain-accounts/host/client/cli/tx_test.go +++ b/modules/apps/27-interchain-accounts/host/client/cli/tx_test.go @@ -48,7 +48,7 @@ func TestGeneratePacketData(t *testing.T) { assertionFn func(t *testing.T, msgs []sdk.Msg) }{ { - name: "multi message", + name: "packet data generation succeeds (MsgDelegate & MsgSend)", memo: "", expectedPass: true, message: multiMsg, @@ -57,8 +57,8 @@ func TestGeneratePacketData(t *testing.T) { banktypes.RegisterInterfaces(registry) }, assertionFn: func(t *testing.T, msgs []sdk.Msg) { - assertMsgDelegate(t, msgs, 0) - assertMsgBankSend(t, msgs, 1) + assertMsgDelegate(t, msgs[0]) + assertMsgBankSend(t, msgs[1]) }, }, { @@ -68,7 +68,7 @@ func TestGeneratePacketData(t *testing.T) { message: msgDelegateMessage, registerInterfaceFn: stakingtypes.RegisterInterfaces, assertionFn: func(t *testing.T, msgs []sdk.Msg) { - assertMsgDelegate(t, msgs, 0) + assertMsgDelegate(t, msgs[0]) }, }, { @@ -78,7 +78,7 @@ func TestGeneratePacketData(t *testing.T) { message: bankSendMessage, registerInterfaceFn: banktypes.RegisterInterfaces, assertionFn: func(t *testing.T, msgs []sdk.Msg) { - assertMsgBankSend(t, msgs, 0) + assertMsgBankSend(t, msgs[0]) }, }, { @@ -136,8 +136,8 @@ func TestGeneratePacketData(t *testing.T) { } } -func assertMsgBankSend(t *testing.T, msgs []sdk.Msg, idx int) { - bankSendMsg, ok := msgs[idx].(*banktypes.MsgSend) +func assertMsgBankSend(t *testing.T, msg sdk.Msg) { + bankSendMsg, ok := msg.(*banktypes.MsgSend) require.True(t, ok) require.Equal(t, "cosmos15ccshhmp0gsx29qpqq6g4zmltnnvgmyu9ueuadh9y2nc5zj0szls5gtddz", bankSendMsg.FromAddress) require.Equal(t, "cosmos10h9stc5v6ntgeygf5xf945njqq5h32r53uquvw", bankSendMsg.ToAddress) @@ -145,8 +145,8 @@ func assertMsgBankSend(t *testing.T, msgs []sdk.Msg, idx int) { require.Equal(t, uint64(1000), bankSendMsg.Amount[0].Amount.Uint64()) } -func assertMsgDelegate(t *testing.T, msgs []sdk.Msg, idx int) { - msgDelegate, ok := msgs[idx].(*stakingtypes.MsgDelegate) +func assertMsgDelegate(t *testing.T, msg sdk.Msg) { + msgDelegate, ok := msg.(*stakingtypes.MsgDelegate) require.True(t, ok) require.Equal(t, "cosmos15ccshhmp0gsx29qpqq6g4zmltnnvgmyu9ueuadh9y2nc5zj0szls5gtddz", msgDelegate.DelegatorAddress) require.Equal(t, "cosmosvaloper1qnk2n4nlkpw9xfqntladh74w6ujtulwnmxnh3k", msgDelegate.ValidatorAddress) From 7411b537f536e178961cd6c4fc08e7e40a4205f3 Mon Sep 17 00:00:00 2001 From: Cian Hatton Date: Mon, 26 Sep 2022 13:05:13 +0100 Subject: [PATCH 10/11] Update modules/apps/27-interchain-accounts/host/client/cli/cli.go Co-authored-by: Carlos Rodriguez --- modules/apps/27-interchain-accounts/host/client/cli/cli.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/apps/27-interchain-accounts/host/client/cli/cli.go b/modules/apps/27-interchain-accounts/host/client/cli/cli.go index 4a7ed942c5b..8f1f0f7fa7e 100644 --- a/modules/apps/27-interchain-accounts/host/client/cli/cli.go +++ b/modules/apps/27-interchain-accounts/host/client/cli/cli.go @@ -26,7 +26,7 @@ func GetQueryCmd() *cobra.Command { func NewTxCmd() *cobra.Command { cmd := &cobra.Command{ Use: "host", - Short: "IBC interchain accounts host transaction", + Short: "IBC interchain accounts host transaction subcommands", DisableFlagParsing: true, SuggestionsMinimumDistance: 2, RunE: client.ValidateCmd, From 30b790750a8d3e765e981e6c3039debd59db1e97 Mon Sep 17 00:00:00 2001 From: Cian Hatton Date: Tue, 27 Sep 2022 12:53:53 +0100 Subject: [PATCH 11/11] chore: use version AppName variable --- modules/apps/27-interchain-accounts/host/client/cli/tx.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/modules/apps/27-interchain-accounts/host/client/cli/tx.go b/modules/apps/27-interchain-accounts/host/client/cli/tx.go index cd5eee798c9..b72769bcda1 100644 --- a/modules/apps/27-interchain-accounts/host/client/cli/tx.go +++ b/modules/apps/27-interchain-accounts/host/client/cli/tx.go @@ -2,10 +2,12 @@ package cli import ( "encoding/json" + "fmt" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/version" "github.com/spf13/cobra" icatypes "github.com/cosmos/ibc-go/v6/modules/apps/27-interchain-accounts/types" @@ -23,7 +25,7 @@ func generatePacketDataCmd() *cobra.Command { into packet data which is outputted to stdout. It can be used in conjunction with send-tx" which submits pre-built packet data containing messages to be executed on the host chain. `, - Example: ` tx interchain-accounts host generate-packet-data '{ + Example: fmt.Sprintf(`%s tx interchain-accounts host generate-packet-data '{ "@type":"/cosmos.bank.v1beta1.MsgSend", "from_address":"cosmos15ccshhmp0gsx29qpqq6g4zmltnnvgmyu9ueuadh9y2nc5zj0szls5gtddz", "to_address":"cosmos10h9stc5v6ntgeygf5xf945njqq5h32r53uquvw", @@ -36,7 +38,7 @@ which submits pre-built packet data containing messages to be executed on the ho }' --memo memo - tx interchain-accounts host generate-packet-data '[{ +%s tx interchain-accounts host generate-packet-data '[{ "@type":"/cosmos.bank.v1beta1.MsgSend", "from_address":"cosmos15ccshhmp0gsx29qpqq6g4zmltnnvgmyu9ueuadh9y2nc5zj0szls5gtddz", "to_address":"cosmos10h9stc5v6ntgeygf5xf945njqq5h32r53uquvw", @@ -55,7 +57,7 @@ which submits pre-built packet data containing messages to be executed on the ho "denom": "stake", "amount": "1000" } -}]'`, +}]'`, version.AppName, version.AppName), Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { clientCtx, err := client.GetClientTxContext(cmd)