-
Notifications
You must be signed in to change notification settings - Fork 750
Expand file tree
/
Copy pathtx.go
More file actions
157 lines (131 loc) · 4.87 KB
/
tx.go
File metadata and controls
157 lines (131 loc) · 4.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
package cli
import (
"encoding/json"
"errors"
"fmt"
"github.com/cosmos/gogoproto/proto"
"github.com/spf13/cobra"
"golang.org/x/exp/slices"
"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/cosmos/ibc-go/v7/modules/apps/27-interchain-accounts/types"
icatypes "github.com/cosmos/ibc-go/v7/modules/apps/27-interchain-accounts/types"
)
const (
memoFlag string = "memo"
)
func generatePacketDataCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "generate-packet-data [encoding] [message]",
Short: "Generates protobuf or proto3 JSON encoded ICA packet data.",
Long: `generate-packet-data accepts a message string and serializes it (depending on the
encoding parameter) using protobuf or proto3 JSON 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: fmt.Sprintf(`%s tx interchain-accounts host generate-packet-data proto3 '{
"@type":"/cosmos.bank.v1beta1.MsgSend",
"from_address":"cosmos15ccshhmp0gsx29qpqq6g4zmltnnvgmyu9ueuadh9y2nc5zj0szls5gtddz",
"to_address":"cosmos10h9stc5v6ntgeygf5xf945njqq5h32r53uquvw",
"amount": [
{
"denom": "stake",
"amount": "1000"
}
]
}' --memo memo
%s tx interchain-accounts host generate-packet-data proto3 '[{
"@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"
}
}]'`, version.AppName, 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
}
encoding := args[0]
if !slices.Contains([]string{types.EncodingProtobuf, types.EncodingProto3JSON}, encoding) {
return errors.New(fmt.Sprintf("unsupported encoding type: %s", encoding))
}
packetDataBytes, err := generatePacketData(cdc, []byte(args[0]), memo, encoding)
if err != nil {
return err
}
cmd.Println(string(packetDataBytes))
return nil
},
}
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, encoding string) ([]byte, error) {
protoMessages, err := convertBytesIntoProtoMessages(cdc, msgBytes)
if err != nil {
return nil, err
}
return generateIcaPacketDataFromProtoMessages(cdc, protoMessages, memo, encoding)
}
// convertBytesIntoProtoMessages returns a list of proto messages from bytes. The bytes can be in the form of a single
// message, or a json array of messages.
func convertBytesIntoProtoMessages(cdc *codec.ProtoCodec, msgBytes []byte) ([]proto.Message, 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 []proto.Message{msg}, nil
}
sdkMessages := make([]proto.Message, 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
}
// generateIcaPacketDataFromProtoMessages generates ica packet data as bytes from a given set of proto encoded sdk messages and a memo.
func generateIcaPacketDataFromProtoMessages(cdc *codec.ProtoCodec, sdkMessages []proto.Message, memo string, encoding string) ([]byte, error) {
icaPacketDataBytes, err := icatypes.SerializeCosmosTx(cdc, sdkMessages, encoding)
if err != nil {
return nil, err
}
icaPacketData := icatypes.InterchainAccountPacketData{
Type: icatypes.EXECUTE_TX,
Data: icaPacketDataBytes,
Memo: memo,
}
if err := icaPacketData.ValidateBasic(); err != nil {
return nil, err
}
return cdc.MarshalJSON(&icaPacketData)
}