Skip to content
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

Merged
merged 33 commits into from
Sep 23, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
41f7632
add send msgs
hieuvubk Sep 15, 2024
1eb5c65
handler
hieuvubk Sep 15, 2024
845510c
send cmd
hieuvubk Sep 15, 2024
37cc625
regist msg & query handler
hieuvubk Sep 15, 2024
f0187dc
Merge branch 'main' into hieu/bankv2/handlers
hieuvubk Sep 15, 2024
f50fc0d
Merge branch 'main' into hieu/bankv2/handlers
hieuvubk Sep 16, 2024
f1edd6e
feedback
hieuvubk Sep 16, 2024
1f005a4
Merge branch 'hieu/bankv2/handlers' of https://github.com/cosmos/cosm…
hieuvubk Sep 16, 2024
f04ba3d
tx signer
hieuvubk Sep 16, 2024
d0ff17c
bankv2 genesis with balances and supply
hieuvubk Sep 16, 2024
5e5fb05
update comments
hieuvubk Sep 16, 2024
9bf855d
init bankv2 in testnet for systemtest
hieuvubk Sep 16, 2024
36d8752
test valid case
hieuvubk Sep 16, 2024
f774b20
msg mint & query balance
hieuvubk Sep 17, 2024
cadfdbe
balance cmd
hieuvubk Sep 18, 2024
2167d51
type
hieuvubk Sep 18, 2024
3e9a53d
re add to grpcQueryDecoders
hieuvubk Sep 18, 2024
29c9a8f
update
hieuvubk Sep 18, 2024
3778b6f
Merge branch 'main' into hieu/bankv2/handlers
hieuvubk Sep 19, 2024
1645d00
format response
hieuvubk Sep 19, 2024
44c3faa
systemtest
hieuvubk Sep 19, 2024
76e89cc
Merge branch 'hieu/bankv2/handlers' of https://github.com/cosmos/cosm…
hieuvubk Sep 19, 2024
3aafcb0
Merge branch 'main' into hieu/bankv2/handlers
hieuvubk Sep 19, 2024
0b5d9f3
lint
hieuvubk Sep 19, 2024
8e8297a
update tests
hieuvubk Sep 23, 2024
1fa11c9
no need
hieuvubk Sep 23, 2024
829c03c
feedback
hieuvubk Sep 23, 2024
f9fe061
err check
hieuvubk Sep 23, 2024
60485a0
lintttt
hieuvubk Sep 23, 2024
d94ccad
Merge branch 'main' into hieu/bankv2/handlers
hieuvubk Sep 23, 2024
b82b96c
resolve conflict
hieuvubk Sep 23, 2024
6581309
Merge branch 'hieu/bankv2/handlers' of https://github.com/cosmos/cosm…
hieuvubk Sep 23, 2024
2e312e7
Merge branch 'main' into hieu/bankv2/handlers
hieuvubk Sep 23, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions runtime/v2/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,14 @@ func (m *MM[T]) RegisterServices(app *App[T]) error {
if module, ok := module.(appmodulev2.HasPostMsgHandlers); ok {
module.RegisterPostMsgHandlers(app.msgRouterBuilder)
}

if module, ok := module.(appmodulev2.HasMsgHandlers); ok {
Copy link
Member

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.

module.RegisterMsgHandlers(app.msgRouterBuilder)
}

if module, ok := module.(appmodulev2.HasQueryHandlers); ok {
module.RegisterQueryHandlers(app.queryRouterBuilder)
}
}

return nil
Expand Down
21 changes: 20 additions & 1 deletion x/bank/proto/cosmos/bank/v2/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -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";

Expand All @@ -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";
Copy link
Member

Choose a reason for hiding this comment

The 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"
];
}
67 changes: 67 additions & 0 deletions x/bank/v2/client/cli/tx.go
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.
Copy link
Member

Choose a reason for hiding this comment

The 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
}
50 changes: 50 additions & 0 deletions x/bank/v2/keeper/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ import (
"errors"
"fmt"

errorsmod "cosmossdk.io/errors"
"cosmossdk.io/x/bank/v2/types"
"github.com/cosmos/cosmos-sdk/telemetry"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/hashicorp/go-metrics"
)

type handlers struct {
Expand Down Expand Up @@ -45,6 +49,52 @@ func (h handlers) MsgUpdateParams(ctx context.Context, msg *types.MsgUpdateParam
return &types.MsgUpdateParamsResponse{}, nil
}

func (h handlers) MsgSend(ctx context.Context, msg *types.MsgSend) (*types.MsgSendResponse, error) {
var (
from, to []byte
err error
)

from, err = h.addressCodec.StringToBytes(msg.FromAddress)
if err != nil {
return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid from address: %s", err)
}

to, err = h.addressCodec.StringToBytes(msg.ToAddress)
if err != nil {
return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid to address: %s", err)
}

if !msg.Amount.IsValid() {
return nil, errorsmod.Wrap(sdkerrors.ErrInvalidCoins, msg.Amount.String())
}

if !msg.Amount.IsAllPositive() {
return nil, errorsmod.Wrap(sdkerrors.ErrInvalidCoins, msg.Amount.String())
}

// TODO: Check denom enable

err = h.SendCoins(ctx, from, to, msg.Amount)
if err != nil {
return nil, err
}

defer func() {
for _, a := range msg.Amount {
if a.Amount.IsInt64() {
telemetry.SetGaugeWithLabels(
[]string{"tx", "msg", "send"},
float32(a.Amount.Int64()),
[]metrics.Label{telemetry.NewLabel("denom", a.Denom)},
)
}
}
}()

return &types.MsgSendResponse{}, nil
}

// QueryParams queries the parameters of the bank/v2 module.
func (h handlers) QueryParams(ctx context.Context, req *types.QueryParamsRequest) (*types.QueryParamsResponse, error) {
if req == nil {
Expand Down
21 changes: 21 additions & 0 deletions x/bank/v2/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -102,6 +104,12 @@ func (am AppModule) RegisterMsgHandlers(router appmodulev2.MsgRouter) {
errs = errors.Join(errs, err)
}

if err := appmodulev2.RegisterHandler(
Copy link
Member

Choose a reason for hiding this comment

The 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

appmodulev2.RegisterHandlers(router, "cosmos.bank.v2.MsgSend": handlers.SendHandler, "cosmos.bank.v2.MsgUpdateParams": handlers.ParamsHandler)

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)
}
Expand All @@ -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
// }

1 change: 1 addition & 0 deletions x/bank/v2/types/codec.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ import (
func RegisterInterfaces(registrar registry.InterfaceRegistrar) {
registrar.RegisterImplementations((*transaction.Msg)(nil),
&MsgUpdateParams{},
&MsgSend{},
)
}
50 changes: 50 additions & 0 deletions x/bank/v2/types/msgs.go
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}
}
Loading
Loading