-
Notifications
You must be signed in to change notification settings - Fork 3.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(bank/v2): Add MsgSend handler #21736
Changes from 5 commits
41f7632
1eb5c65
845510c
37cc625
f0187dc
f50fc0d
f1edd6e
1f005a4
f04ba3d
d0ff17c
5e5fb05
9bf855d
36d8752
f774b20
cadfdbe
2167d51
3e9a53d
29c9a8f
3778b6f
1645d00
44c3faa
76e89cc
3aafcb0
0b5d9f3
8e8297a
1fa11c9
829c03c
f9fe061
60485a0
d94ccad
b82b96c
6581309
2e312e7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,7 @@ import "cosmos/bank/v2/bank.proto"; | |
import "cosmos_proto/cosmos.proto"; | ||
import "cosmos/msg/v1/msg.proto"; | ||
import "amino/amino.proto"; | ||
import "cosmos/base/v1beta1/coin.proto"; | ||
|
||
option go_package = "cosmossdk.io/x/bank/v2/types"; | ||
|
||
|
@@ -23,4 +24,22 @@ message MsgUpdateParams { | |
} | ||
|
||
// MsgUpdateParamsResponse defines the response structure for executing a MsgUpdateParams message. | ||
message MsgUpdateParamsResponse {} | ||
message MsgUpdateParamsResponse {} | ||
|
||
// MsgSend represents a message to send coins from one account to another. | ||
message MsgSend { | ||
option (cosmos.msg.v1.signer) = "from_address"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To delete |
||
option (amino.name) = "cosmos-sdk/MsgSend"; | ||
|
||
option (gogoproto.equal) = false; | ||
option (gogoproto.goproto_getters) = false; | ||
|
||
string from_address = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; | ||
string to_address = 2 [(cosmos_proto.scalar) = "cosmos.AddressString"]; | ||
repeated cosmos.base.v1beta1.Coin amount = 3 [ | ||
(gogoproto.nullable) = false, | ||
(amino.dont_omitempty) = true, | ||
(amino.encoding) = "legacy_coins", | ||
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins" | ||
]; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
package cli | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/spf13/cobra" | ||
|
||
"cosmossdk.io/x/bank/v2/types" | ||
|
||
"github.com/cosmos/cosmos-sdk/client" | ||
"github.com/cosmos/cosmos-sdk/client/flags" | ||
"github.com/cosmos/cosmos-sdk/client/tx" | ||
sdk "github.com/cosmos/cosmos-sdk/types" | ||
) | ||
|
||
var FlagSplit = "split" | ||
|
||
// NewTxCmd returns a root CLI command handler for all x/bank transaction commands. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we add a TODO to remove and link the gRPC / AutoCLI issue ? |
||
func NewTxCmd() *cobra.Command { | ||
txCmd := &cobra.Command{ | ||
Use: types.ModuleName, | ||
Short: "Bank transaction subcommands", | ||
DisableFlagParsing: true, | ||
SuggestionsMinimumDistance: 2, | ||
RunE: client.ValidateCmd, | ||
} | ||
|
||
txCmd.AddCommand( | ||
NewSendTxCmd(), | ||
) | ||
|
||
return txCmd | ||
} | ||
|
||
// NewSendTxCmd returns a CLI command handler for creating a MsgSend transaction. | ||
func NewSendTxCmd() *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 { | ||
cmd.Flags().Set(flags.FlagFrom, args[0]) | ||
clientCtx, err := client.GetClientTxContext(cmd) | ||
fmt.Println("errs", err) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
coins, err := sdk.ParseCoinsNormalized(args[2]) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
msg := types.NewMsgSend(clientCtx.GetFromAddress().String(), args[1], coins) | ||
|
||
return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) | ||
}, | ||
} | ||
|
||
flags.AddTxFlagsToCmd(cmd) | ||
|
||
return cmd | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,9 +7,11 @@ import ( | |
"fmt" | ||
|
||
gogoproto "github.com/cosmos/gogoproto/proto" | ||
"github.com/spf13/cobra" | ||
|
||
appmodulev2 "cosmossdk.io/core/appmodule/v2" | ||
"cosmossdk.io/core/registry" | ||
"cosmossdk.io/x/bank/v2/client/cli" | ||
"cosmossdk.io/x/bank/v2/keeper" | ||
"cosmossdk.io/x/bank/v2/types" | ||
|
||
|
@@ -102,6 +104,12 @@ func (am AppModule) RegisterMsgHandlers(router appmodulev2.MsgRouter) { | |
errs = errors.Join(errs, err) | ||
} | ||
|
||
if err := appmodulev2.RegisterHandler( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @testinginprod, imho we should improve the API to register multiple messages and handlers in that method. Otherwise it is imho way too verbose. like
It will need to be a bit less type safe I think, but still a better UX. |
||
router, gogoproto.MessageName(&types.MsgSend{}), handlers.MsgSend, | ||
); err != nil { | ||
errs = errors.Join(errs, err) | ||
} | ||
|
||
if errs != nil { | ||
panic(errs) | ||
} | ||
|
@@ -122,3 +130,16 @@ func (am AppModule) RegisterQueryHandlers(router appmodulev2.QueryRouter) { | |
panic(errs) | ||
} | ||
} | ||
|
||
// GetTxCmd returns the root tx command for the bank module. | ||
hieuvubk marked this conversation as resolved.
Show resolved
Hide resolved
|
||
func (AppModule) GetTxCmd() *cobra.Command { | ||
return cli.NewTxCmd() | ||
} | ||
|
||
// // RegisterServices registers module services. | ||
hieuvubk marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// func (am AppModule) RegisterServices(registrar grpc.ServiceRegistrar) error { | ||
// am.RegisterMsgHandlers(registrar) | ||
|
||
// return nil | ||
// } | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
package types | ||
|
||
import ( | ||
coretransaction "cosmossdk.io/core/transaction" | ||
|
||
sdk "github.com/cosmos/cosmos-sdk/types" | ||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" | ||
errorsmod "cosmossdk.io/errors" | ||
) | ||
|
||
// bank message types | ||
const ( | ||
TypeMsgSend = "send" | ||
) | ||
|
||
var ( | ||
_ coretransaction.Msg = &MsgSend{} | ||
) | ||
|
||
// NewMsgSend constructs a msg to send coins from one account to another. | ||
func NewMsgSend(fromAddr, toAddr string, amount sdk.Coins) *MsgSend { | ||
return &MsgSend{FromAddress: fromAddr, ToAddress: toAddr, Amount: amount} | ||
} | ||
|
||
// ValidateBasic Implements Msg. | ||
hieuvubk marked this conversation as resolved.
Show resolved
Hide resolved
|
||
func (msg MsgSend) ValidateBasic() error { | ||
if _, err := sdk.AccAddressFromBech32(msg.FromAddress); err != nil { | ||
return sdkerrors.ErrInvalidAddress.Wrapf("invalid from address: %s", err) | ||
} | ||
|
||
if _, err := sdk.AccAddressFromBech32(msg.ToAddress); err != nil { | ||
return sdkerrors.ErrInvalidAddress.Wrapf("invalid to address: %s", err) | ||
} | ||
|
||
if !msg.Amount.IsValid() { | ||
return errorsmod.Wrap(sdkerrors.ErrInvalidCoins, msg.Amount.String()) | ||
} | ||
|
||
if !msg.Amount.IsAllPositive() { | ||
return errorsmod.Wrap(sdkerrors.ErrInvalidCoins, msg.Amount.String()) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// GetSigners Implements Msg. | ||
func (msg MsgSend) GetSigners() []sdk.AccAddress { | ||
hieuvubk marked this conversation as resolved.
Show resolved
Hide resolved
|
||
fromAddress, _ := sdk.AccAddressFromBech32(msg.FromAddress) | ||
return []sdk.AccAddress{fromAddress} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should add a check in registerService to avoid the double registration.