diff --git a/client/v2/autocli/flag/coin.go b/client/v2/autocli/flag/coin.go index d2b7a139571d5..41084c91bea27 100644 --- a/client/v2/autocli/flag/coin.go +++ b/client/v2/autocli/flag/coin.go @@ -2,6 +2,7 @@ package flag import ( "context" + "strings" "google.golang.org/protobuf/reflect/protoreflect" @@ -12,7 +13,7 @@ import ( type coinType struct{} type coinValue struct { - value *basev1beta1.Coin + value []*basev1beta1.Coin } func (c coinType) NewValue(_ context.Context, _ *Builder) Value { @@ -28,19 +29,28 @@ func (c *coinValue) Get(protoreflect.Value) (protoreflect.Value, error) { if c.value == nil { return protoreflect.Value{}, nil } - return protoreflect.ValueOfMessage(c.value.ProtoReflect()), nil + + return protoreflect.ValueOfMessage(c.value[0].ProtoReflect()), nil } func (c *coinValue) String() string { - return c.value.String() + stringCoin, _ := coins.FormatCoins(c.value, nil) + return stringCoin } func (c *coinValue) Set(stringValue string) error { - coin, err := coins.ParseCoin(stringValue) - if err != nil { - return err + coinsStr := strings.Split(stringValue, ",") + result := make([]*basev1beta1.Coin, len(coinsStr)) + + for i, coinStr := range coinsStr { + coin, err := coins.ParseCoin(coinStr) + if err != nil { + return err + } + result[i] = coin } - c.value = coin + + c.value = result return nil } diff --git a/client/v2/autocli/flag/message.go b/client/v2/autocli/flag/message.go index 5ea1943cd4def..166211b0d3f3e 100644 --- a/client/v2/autocli/flag/message.go +++ b/client/v2/autocli/flag/message.go @@ -89,12 +89,7 @@ func (f fieldBinding) bind(msg protoreflect.Message) error { if err != nil { return err } - kind := f.field.Kind() - if !(field.IsList() || - field.IsMap() || - kind == protoreflect.MessageKind || - kind == protoreflect.GroupKind) { - msg.Set(f.field, val) - } + + msg.Set(f.field, val) return nil } diff --git a/x/bank/autocli.go b/x/bank/autocli.go index 25d65feecb978..4adae35c3ec52 100644 --- a/x/bank/autocli.go +++ b/x/bank/autocli.go @@ -87,5 +87,17 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions { }, }, }, + Tx: &autocliv1.ServiceCommandDescriptor{ + Service: bankv1beta1.Msg_ServiceDesc.ServiceName, + RpcCommandOptions: []*autocliv1.RpcCommandOptions{ + { + RpcMethod: "Send", + Use: "send [from_key_or_address] [to_address] [amount]", + Short: "Send funds from one account to another.", + PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "from_address"}, {ProtoField: "to_address"}, {ProtoField: "amount"}}, + }, + }, + EnhanceCustomCommand: true, + }, } } diff --git a/x/bank/client/cli/tx.go b/x/bank/client/cli/tx.go index 11beeabd137e8..d45db2b248f19 100644 --- a/x/bank/client/cli/tx.go +++ b/x/bank/client/cli/tx.go @@ -29,57 +29,12 @@ func NewTxCmd(ac address.Codec) *cobra.Command { } txCmd.AddCommand( - NewSendTxCmd(ac), NewMultiSendTxCmd(ac), ) return txCmd } -// NewSendTxCmd returns a CLI command handler for creating a MsgSend transaction. -func NewSendTxCmd(ac address.Codec) *cobra.Command { - cmd := &cobra.Command{ - Use: "send [from_key_or_address] [to_address] [amount]", - Short: "Send funds from one account to another.", - Long: `Send funds from one account to another. -Note, the '--from' flag is ignored as it is implied from [from_key_or_address]. -When using '--dry-run' a key name cannot be used, only a bech32 address. -`, - Args: cobra.ExactArgs(3), - RunE: func(cmd *cobra.Command, args []string) error { - err := cmd.Flags().Set(flags.FlagFrom, args[0]) - if err != nil { - return err - } - clientCtx, err := client.GetClientTxContext(cmd) - if err != nil { - return err - } - toAddr, err := ac.StringToBytes(args[1]) - if err != nil { - return err - } - - coins, err := sdk.ParseCoinsNormalized(args[2]) - if err != nil { - return err - } - - if len(coins) == 0 { - return fmt.Errorf("invalid coins") - } - - msg := types.NewMsgSend(clientCtx.GetFromAddress(), toAddr, coins) - - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) - }, - } - - flags.AddTxFlagsToCmd(cmd) - - return cmd -} - // NewMultiSendTxCmd returns a CLI command handler for creating a MsgMultiSend transaction. // For a better UX this command is limited to send funds from one account to two or more accounts. func NewMultiSendTxCmd(ac address.Codec) *cobra.Command { diff --git a/x/bank/client/cli/tx_test.go b/x/bank/client/cli/tx_test.go index a9a5280f0bff7..b097be83444d7 100644 --- a/x/bank/client/cli/tx_test.go +++ b/x/bank/client/cli/tx_test.go @@ -48,91 +48,6 @@ func (s *CLITestSuite) SetupSuite() { WithOutput(io.Discard) } -func (s *CLITestSuite) TestSendTxCmd() { - accounts := testutil.CreateKeyringAccounts(s.T(), s.kr, 1) - cmd := cli.NewSendTxCmd(address.NewBech32Codec("cosmos")) - cmd.SetOutput(io.Discard) - - extraArgs := []string{ - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=true", flags.FlagSkipConfirmation), - fmt.Sprintf("--%s=%s", flags.FlagBroadcastMode, flags.BroadcastSync), - fmt.Sprintf("--%s=%s", flags.FlagFees, sdk.NewCoins(sdk.NewCoin("photon", sdkmath.NewInt(10))).String()), - fmt.Sprintf("--%s=test-chain", flags.FlagChainID), - } - - testCases := []struct { - name string - ctxGen func() client.Context - from, to sdk.AccAddress - amount sdk.Coins - extraArgs []string - expectErrMsg string - }{ - { - "valid transaction", - func() client.Context { - return s.baseCtx - }, - accounts[0].Address, - accounts[0].Address, - sdk.NewCoins( - sdk.NewCoin("stake", sdkmath.NewInt(10)), - sdk.NewCoin("photon", sdkmath.NewInt(40)), - ), - extraArgs, - "", - }, - { - "invalid to Address", - func() client.Context { - return s.baseCtx - }, - accounts[0].Address, - sdk.AccAddress{}, - sdk.NewCoins( - sdk.NewCoin("stake", sdkmath.NewInt(10)), - sdk.NewCoin("photon", sdkmath.NewInt(40)), - ), - extraArgs, - "empty address string is not allowed", - }, - { - "invalid coins", - func() client.Context { - return s.baseCtx - }, - accounts[0].Address, - accounts[0].Address, - nil, - extraArgs, - "invalid coins", - }, - } - - for _, tc := range testCases { - tc := tc - s.Run(tc.name, func() { - args := append([]string{tc.from.String(), tc.to.String(), tc.amount.String()}, tc.extraArgs...) - - ctx := svrcmd.CreateExecuteContext(context.Background()) - cmd.SetContext(ctx) - cmd.SetArgs(args) - s.Require().NoError(client.SetCmdClientContextHandler(tc.ctxGen(), cmd)) - - out, err := clitestutil.ExecTestCLICmd(tc.ctxGen(), cmd, args) - if tc.expectErrMsg != "" { - s.Require().Error(err) - s.Require().Contains(out.String(), tc.expectErrMsg) - } else { - s.Require().NoError(err) - msg := &sdk.TxResponse{} - s.Require().NoError(tc.ctxGen().Codec.UnmarshalJSON(out.Bytes(), msg), out.String()) - } - }) - } -} - func (s *CLITestSuite) TestMultiSendTxCmd() { accounts := testutil.CreateKeyringAccounts(s.T(), s.kr, 3)