Co-authored-by: Julien Robert <julien@rbrt.fr>
This commit is contained in:
co-authored by
Julien Robert
parent
3fee9db359
commit
c8a49b35cd
@@ -0,0 +1,91 @@
|
||||
package bank
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
autocliv1 "cosmossdk.io/api/cosmos/autocli/v1"
|
||||
bankv1beta1 "cosmossdk.io/api/cosmos/bank/v1beta1"
|
||||
)
|
||||
|
||||
// AutoCLIOptions implements the autocli.HasAutoCLIConfig interface.
|
||||
func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions {
|
||||
return &autocliv1.ModuleOptions{
|
||||
Query: &autocliv1.ServiceCommandDescriptor{
|
||||
Service: bankv1beta1.Query_ServiceDesc.ServiceName,
|
||||
RpcCommandOptions: []*autocliv1.RpcCommandOptions{
|
||||
{
|
||||
RpcMethod: "Balance",
|
||||
Use: "balance [address] [denom]",
|
||||
Short: "Query an account balance by address and denom",
|
||||
PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "address"}, {ProtoField: "denom"}},
|
||||
},
|
||||
{
|
||||
RpcMethod: "AllBalances",
|
||||
Use: "balances [address]",
|
||||
Short: "Query for account balances by address",
|
||||
Long: "Query the total balance of an account or of a specific denomination.",
|
||||
PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "address"}},
|
||||
},
|
||||
{
|
||||
RpcMethod: "SpendableBalances",
|
||||
Use: "spendable-balances [address]",
|
||||
Short: "Query for account spendable balances by address",
|
||||
PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "address"}},
|
||||
},
|
||||
{
|
||||
RpcMethod: "SpendableBalanceByDenom",
|
||||
Use: "spendable-balances [address] [denom]",
|
||||
Short: "Query the spendable balance of a single denom for a single account.",
|
||||
PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "address"}, {ProtoField: "denom"}},
|
||||
},
|
||||
{
|
||||
RpcMethod: "TotalSupply",
|
||||
Use: "total-supply",
|
||||
Alias: []string{"total"},
|
||||
Short: "Query the total supply of coins of the chain",
|
||||
Long: "Query total supply of coins that are held by accounts in the chain. To query for the total supply of a specific coin denomination use --denom flag.",
|
||||
},
|
||||
{
|
||||
RpcMethod: "SupplyOf",
|
||||
Use: "total-supply-of [denom]",
|
||||
Short: "Query the supply of a single coin denom",
|
||||
PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "denom"}},
|
||||
},
|
||||
{
|
||||
RpcMethod: "Params",
|
||||
Use: "params",
|
||||
Short: "Query the current bank parameters",
|
||||
},
|
||||
{
|
||||
RpcMethod: "DenomMetadata",
|
||||
Use: "denom-metadata [denom]",
|
||||
Short: "Query the client metadata of a given coin denomination",
|
||||
PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "denom"}},
|
||||
},
|
||||
{
|
||||
RpcMethod: "DenomsMetadata",
|
||||
Use: "denoms-metadata",
|
||||
Short: "Query the client metadata for all registered coin denominations",
|
||||
},
|
||||
{
|
||||
RpcMethod: "DenomOwners",
|
||||
Use: "denom-owners [denom]",
|
||||
Short: "Query for all account addresses that own a particular token denomination.",
|
||||
PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "denom"}},
|
||||
},
|
||||
{
|
||||
RpcMethod: "SendEnabled",
|
||||
Use: "send-enabled [denom1 ...]",
|
||||
Short: "Query for send enabled entries",
|
||||
Long: strings.TrimSpace(`Query for send enabled entries that have been specifically set.
|
||||
|
||||
To look up one or more specific denoms, supply them as arguments to this command.
|
||||
To look up all denoms, do not provide any arguments.
|
||||
`,
|
||||
),
|
||||
PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "denoms"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -1,350 +0,0 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"cosmossdk.io/core/address"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/version"
|
||||
"github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
)
|
||||
|
||||
const (
|
||||
FlagDenom = "denom"
|
||||
FlagResolveDenom = "resolve-denom"
|
||||
)
|
||||
|
||||
// GetQueryCmd returns the parent command for all x/bank CLi query commands. The
|
||||
// provided clientCtx should have, at a minimum, a verifier, CometBFT RPC client,
|
||||
// and marshaler set.
|
||||
func GetQueryCmd(ac address.Codec) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: types.ModuleName,
|
||||
Short: "Querying commands for the bank module",
|
||||
DisableFlagParsing: true,
|
||||
SuggestionsMinimumDistance: 2,
|
||||
RunE: client.ValidateCmd,
|
||||
}
|
||||
|
||||
cmd.AddCommand(
|
||||
GetBalancesCmd(ac),
|
||||
GetSpendableBalancesCmd(ac),
|
||||
GetCmdQueryTotalSupply(),
|
||||
GetCmdDenomsMetadata(),
|
||||
GetCmdQuerySendEnabled(),
|
||||
)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func GetBalancesCmd(ac address.Codec) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "balances [address]",
|
||||
Short: "Query for account balances by address",
|
||||
Long: strings.TrimSpace(
|
||||
fmt.Sprintf(`Query the total balance of an account or of a specific denomination.
|
||||
|
||||
Example:
|
||||
$ %s query %s balances [address]
|
||||
$ %s query %s balances [address] --denom=[denom]
|
||||
$ %s query %s balances [address] --resolve-denom
|
||||
`,
|
||||
version.AppName, types.ModuleName, version.AppName, types.ModuleName, version.AppName, types.ModuleName,
|
||||
),
|
||||
),
|
||||
Args: cobra.ExactArgs(1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
clientCtx, err := client.GetClientQueryContext(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
denom, err := cmd.Flags().GetString(FlagDenom)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
queryClient := types.NewQueryClient(clientCtx)
|
||||
|
||||
addr, err := ac.StringToBytes(args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pageReq, err := client.ReadPageRequest(cmd.Flags())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctx := cmd.Context()
|
||||
|
||||
if denom == "" {
|
||||
resolveDenom, err := cmd.Flags().GetBool(FlagResolveDenom)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
params := types.NewQueryAllBalancesRequest(addr, pageReq, resolveDenom)
|
||||
|
||||
res, err := queryClient.AllBalances(ctx, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return clientCtx.PrintProto(res)
|
||||
}
|
||||
|
||||
params := types.NewQueryBalanceRequest(addr, denom)
|
||||
|
||||
res, err := queryClient.Balance(ctx, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return clientCtx.PrintProto(res.Balance)
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Flags().String(FlagDenom, "", "The specific balance denomination to query for")
|
||||
cmd.Flags().Bool(FlagResolveDenom, false, "Resolve denom to human-readable denom from metadata")
|
||||
flags.AddQueryFlagsToCmd(cmd)
|
||||
flags.AddPaginationFlagsToCmd(cmd, "all balances")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func GetSpendableBalancesCmd(ac address.Codec) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "spendable-balances [address]",
|
||||
Short: "Query for account spendable balances by address",
|
||||
Example: fmt.Sprintf("$ %s query %s spendable-balances [address]", version.AppName, types.ModuleName),
|
||||
Args: cobra.ExactArgs(1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
clientCtx, err := client.GetClientQueryContext(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
denom, err := cmd.Flags().GetString(FlagDenom)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
queryClient := types.NewQueryClient(clientCtx)
|
||||
|
||||
addr, err := ac.StringToBytes(args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pageReq, err := client.ReadPageRequest(cmd.Flags())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctx := cmd.Context()
|
||||
|
||||
if denom == "" {
|
||||
params := types.NewQuerySpendableBalancesRequest(addr, pageReq)
|
||||
|
||||
res, err := queryClient.SpendableBalances(ctx, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return clientCtx.PrintProto(res)
|
||||
}
|
||||
|
||||
params := types.NewQuerySpendableBalanceByDenomRequest(addr, denom)
|
||||
|
||||
res, err := queryClient.SpendableBalanceByDenom(ctx, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return clientCtx.PrintProto(res)
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Flags().String(FlagDenom, "", "The specific balance denomination to query for")
|
||||
flags.AddQueryFlagsToCmd(cmd)
|
||||
flags.AddPaginationFlagsToCmd(cmd, "spendable balances")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
// GetCmdDenomsMetadata defines the cobra command to query client denomination metadata.
|
||||
func GetCmdDenomsMetadata() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "denom-metadata",
|
||||
Short: "Query the client metadata for coin denominations",
|
||||
Long: strings.TrimSpace(
|
||||
fmt.Sprintf(`Query the client metadata for all the registered coin denominations
|
||||
|
||||
Example:
|
||||
To query for the client metadata of all coin denominations use:
|
||||
$ %s query %s denom-metadata
|
||||
|
||||
To query for the client metadata of a specific coin denomination use:
|
||||
$ %s query %s denom-metadata --denom=[denom]
|
||||
`,
|
||||
version.AppName, types.ModuleName, version.AppName, types.ModuleName,
|
||||
),
|
||||
),
|
||||
RunE: func(cmd *cobra.Command, _ []string) error {
|
||||
clientCtx, err := client.GetClientQueryContext(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
denom, err := cmd.Flags().GetString(FlagDenom)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
queryClient := types.NewQueryClient(clientCtx)
|
||||
|
||||
if denom == "" {
|
||||
res, err := queryClient.DenomsMetadata(cmd.Context(), &types.QueryDenomsMetadataRequest{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return clientCtx.PrintProto(res)
|
||||
}
|
||||
|
||||
res, err := queryClient.DenomMetadata(cmd.Context(), &types.QueryDenomMetadataRequest{Denom: denom})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return clientCtx.PrintProto(res)
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Flags().String(FlagDenom, "", "The specific denomination to query client metadata for")
|
||||
flags.AddQueryFlagsToCmd(cmd)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func GetCmdQueryTotalSupply() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "total",
|
||||
Short: "Query the total supply of coins of the chain",
|
||||
Args: cobra.NoArgs,
|
||||
Long: strings.TrimSpace(
|
||||
fmt.Sprintf(`Query total supply of coins that are held by accounts in the chain.
|
||||
|
||||
Example:
|
||||
$ %s query %s total
|
||||
|
||||
To query for the total supply of a specific coin denomination use:
|
||||
$ %s query %s total --denom=[denom]
|
||||
`,
|
||||
version.AppName, types.ModuleName, version.AppName, types.ModuleName,
|
||||
),
|
||||
),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
clientCtx, err := client.GetClientQueryContext(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
denom, err := cmd.Flags().GetString(FlagDenom)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
queryClient := types.NewQueryClient(clientCtx)
|
||||
ctx := cmd.Context()
|
||||
|
||||
pageReq, err := client.ReadPageRequest(cmd.Flags())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if denom == "" {
|
||||
res, err := queryClient.TotalSupply(ctx, &types.QueryTotalSupplyRequest{Pagination: pageReq})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return clientCtx.PrintProto(res)
|
||||
}
|
||||
|
||||
res, err := queryClient.SupplyOf(ctx, &types.QuerySupplyOfRequest{Denom: denom})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return clientCtx.PrintProto(&res.Amount)
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Flags().String(FlagDenom, "", "The specific balance denomination to query for")
|
||||
flags.AddQueryFlagsToCmd(cmd)
|
||||
flags.AddPaginationFlagsToCmd(cmd, "all supply totals")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func GetCmdQuerySendEnabled() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "send-enabled [denom1 ...]",
|
||||
Short: "Query for send enabled entries",
|
||||
Long: strings.TrimSpace(`Query for send enabled entries that have been specifically set.
|
||||
|
||||
To look up one or more specific denoms, supply them as arguments to this command.
|
||||
To look up all denoms, do not provide any arguments.
|
||||
`,
|
||||
),
|
||||
Example: strings.TrimSpace(
|
||||
fmt.Sprintf(`Getting one specific entry:
|
||||
$ %[1]s query %[2]s send-enabled foocoin
|
||||
|
||||
Getting two specific entries:
|
||||
$ %[1]s query %[2]s send-enabled foocoin barcoin
|
||||
|
||||
Getting all entries:
|
||||
$ %[1]s query %[2]s send-enabled
|
||||
`,
|
||||
version.AppName, types.ModuleName,
|
||||
),
|
||||
),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
reqPag, err := client.ReadPageRequest(client.MustFlagSetWithPageKeyDecoded(cmd.Flags()))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
clientCtx, err := client.GetClientQueryContext(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
queryClient := types.NewQueryClient(clientCtx)
|
||||
req := &types.QuerySendEnabledRequest{
|
||||
Denoms: args,
|
||||
Pagination: reqPag,
|
||||
}
|
||||
|
||||
res, err := queryClient.SendEnabled(cmd.Context(), req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return clientCtx.PrintProto(res)
|
||||
},
|
||||
}
|
||||
|
||||
flags.AddQueryFlagsToCmd(cmd)
|
||||
flags.AddPaginationFlagsToCmd(cmd, "send enabled entries")
|
||||
|
||||
return cmd
|
||||
}
|
||||
@@ -1,428 +0,0 @@
|
||||
package cli_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
abci "github.com/cometbft/cometbft/abci/types"
|
||||
"github.com/cosmos/gogoproto/proto"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/codec/address"
|
||||
svrcmd "github.com/cosmos/cosmos-sdk/server/cmd"
|
||||
"github.com/cosmos/cosmos-sdk/testutil"
|
||||
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/bank/client/cli"
|
||||
"github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
)
|
||||
|
||||
func (s *CLITestSuite) TestGetBalancesCmd() {
|
||||
accounts := testutil.CreateKeyringAccounts(s.T(), s.kr, 1)
|
||||
cmd := cli.GetBalancesCmd(address.NewBech32Codec("cosmos"))
|
||||
cmd.SetOutput(io.Discard)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
ctxGen func() client.Context
|
||||
args []string
|
||||
expectResult proto.Message
|
||||
expectErr bool
|
||||
}{
|
||||
{
|
||||
"valid query",
|
||||
func() client.Context {
|
||||
bz, _ := s.encCfg.Codec.Marshal(&types.QueryAllBalancesResponse{})
|
||||
c := clitestutil.NewMockCometRPC(abci.ResponseQuery{
|
||||
Value: bz,
|
||||
})
|
||||
return s.baseCtx.WithClient(c)
|
||||
},
|
||||
[]string{
|
||||
accounts[0].Address.String(),
|
||||
fmt.Sprintf("--%s=json", flags.FlagOutput),
|
||||
},
|
||||
&types.QueryAllBalancesResponse{},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"valid query with denom",
|
||||
func() client.Context {
|
||||
bz, _ := s.encCfg.Codec.Marshal(&types.QueryBalanceResponse{
|
||||
Balance: &sdk.Coin{},
|
||||
})
|
||||
c := clitestutil.NewMockCometRPC(abci.ResponseQuery{
|
||||
Value: bz,
|
||||
})
|
||||
return s.baseCtx.WithClient(c)
|
||||
},
|
||||
[]string{
|
||||
accounts[0].Address.String(),
|
||||
fmt.Sprintf("--%s=photon", cli.FlagDenom),
|
||||
fmt.Sprintf("--%s=json", flags.FlagOutput),
|
||||
},
|
||||
&sdk.Coin{},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"invalid Address",
|
||||
func() client.Context {
|
||||
return s.baseCtx
|
||||
},
|
||||
[]string{
|
||||
"foo",
|
||||
},
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"invalid denom",
|
||||
func() client.Context {
|
||||
c := clitestutil.NewMockCometRPC(abci.ResponseQuery{
|
||||
Code: 1,
|
||||
})
|
||||
return s.baseCtx.WithClient(c)
|
||||
},
|
||||
[]string{
|
||||
accounts[0].Address.String(),
|
||||
fmt.Sprintf("--%s=foo", cli.FlagDenom),
|
||||
},
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
|
||||
s.Run(tc.name, func() {
|
||||
ctx := svrcmd.CreateExecuteContext(context.Background())
|
||||
|
||||
cmd.SetContext(ctx)
|
||||
cmd.SetArgs(tc.args)
|
||||
|
||||
s.Require().NoError(client.SetCmdClientContextHandler(tc.ctxGen(), cmd))
|
||||
|
||||
out, err := clitestutil.ExecTestCLICmd(tc.ctxGen(), cmd, tc.args)
|
||||
if tc.expectErr {
|
||||
s.Require().Error(err)
|
||||
} else {
|
||||
s.Require().NoError(s.encCfg.Codec.UnmarshalJSON(out.Bytes(), tc.expectResult))
|
||||
s.Require().NoError(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (s *CLITestSuite) TestGetSpendableBalancesCmd() {
|
||||
accounts := testutil.CreateKeyringAccounts(s.T(), s.kr, 1)
|
||||
|
||||
cmd := cli.GetSpendableBalancesCmd(address.NewBech32Codec("cosmos"))
|
||||
cmd.SetOutput(io.Discard)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
ctxGen func() client.Context
|
||||
args []string
|
||||
expectResult proto.Message
|
||||
expectErr bool
|
||||
}{
|
||||
{
|
||||
"valid query",
|
||||
func() client.Context {
|
||||
bz, _ := s.encCfg.Codec.Marshal(&types.QuerySpendableBalancesResponse{})
|
||||
c := clitestutil.NewMockCometRPC(abci.ResponseQuery{
|
||||
Value: bz,
|
||||
})
|
||||
return s.baseCtx.WithClient(c)
|
||||
},
|
||||
[]string{
|
||||
accounts[0].Address.String(),
|
||||
fmt.Sprintf("--%s=json", flags.FlagOutput),
|
||||
},
|
||||
&types.QuerySpendableBalancesResponse{},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"valid query with denom flag",
|
||||
func() client.Context {
|
||||
bz, _ := s.encCfg.Codec.Marshal(&types.QuerySpendableBalanceByDenomRequest{})
|
||||
c := clitestutil.NewMockCometRPC(abci.ResponseQuery{
|
||||
Value: bz,
|
||||
})
|
||||
return s.baseCtx.WithClient(c)
|
||||
},
|
||||
[]string{
|
||||
accounts[0].Address.String(),
|
||||
fmt.Sprintf("--%s=json", flags.FlagOutput),
|
||||
fmt.Sprintf("--%s=photon", cli.FlagDenom),
|
||||
},
|
||||
&types.QuerySpendableBalanceByDenomResponse{},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"invalid Address",
|
||||
func() client.Context {
|
||||
return s.baseCtx
|
||||
},
|
||||
[]string{
|
||||
"foo",
|
||||
},
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
|
||||
s.Run(tc.name, func() {
|
||||
ctx := svrcmd.CreateExecuteContext(context.Background())
|
||||
cmd.SetContext(ctx)
|
||||
cmd.SetArgs(tc.args)
|
||||
s.Require().NoError(client.SetCmdClientContextHandler(tc.ctxGen(), cmd))
|
||||
|
||||
out, err := clitestutil.ExecTestCLICmd(tc.ctxGen(), cmd, tc.args)
|
||||
if tc.expectErr {
|
||||
s.Require().Error(err)
|
||||
} else {
|
||||
s.Require().NoError(s.encCfg.Codec.UnmarshalJSON(out.Bytes(), tc.expectResult))
|
||||
s.Require().NoError(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (s *CLITestSuite) TestGetCmdDenomsMetadata() {
|
||||
cmd := cli.GetCmdDenomsMetadata()
|
||||
cmd.SetOutput(io.Discard)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
ctxGen func() client.Context
|
||||
args []string
|
||||
expectResult proto.Message
|
||||
expectErr bool
|
||||
}{
|
||||
{
|
||||
"valid query",
|
||||
func() client.Context {
|
||||
bz, _ := s.encCfg.Codec.Marshal(&types.QueryDenomsMetadataResponse{})
|
||||
c := clitestutil.NewMockCometRPC(abci.ResponseQuery{
|
||||
Value: bz,
|
||||
})
|
||||
return s.baseCtx.WithClient(c)
|
||||
},
|
||||
[]string{
|
||||
fmt.Sprintf("--%s=json", flags.FlagOutput),
|
||||
},
|
||||
&types.QueryDenomsMetadataResponse{},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"valid query with denom",
|
||||
func() client.Context {
|
||||
bz, _ := s.encCfg.Codec.Marshal(&types.QueryDenomMetadataResponse{})
|
||||
c := clitestutil.NewMockCometRPC(abci.ResponseQuery{
|
||||
Value: bz,
|
||||
})
|
||||
return s.baseCtx.WithClient(c)
|
||||
},
|
||||
[]string{
|
||||
fmt.Sprintf("--%s=photon", cli.FlagDenom),
|
||||
fmt.Sprintf("--%s=json", flags.FlagOutput),
|
||||
},
|
||||
&types.QueryDenomMetadataResponse{},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"invalid query with denom",
|
||||
func() client.Context {
|
||||
c := clitestutil.NewMockCometRPC(abci.ResponseQuery{
|
||||
Code: 1,
|
||||
})
|
||||
return s.baseCtx.WithClient(c)
|
||||
},
|
||||
[]string{
|
||||
fmt.Sprintf("--%s=foo", cli.FlagDenom),
|
||||
},
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
|
||||
s.Run(tc.name, func() {
|
||||
ctx := svrcmd.CreateExecuteContext(context.Background())
|
||||
|
||||
cmd.SetContext(ctx)
|
||||
cmd.SetArgs(tc.args)
|
||||
|
||||
s.Require().NoError(client.SetCmdClientContextHandler(tc.ctxGen(), cmd))
|
||||
|
||||
out, err := clitestutil.ExecTestCLICmd(tc.ctxGen(), cmd, tc.args)
|
||||
if tc.expectErr {
|
||||
s.Require().Error(err)
|
||||
} else {
|
||||
s.Require().NoError(s.encCfg.Codec.UnmarshalJSON(out.Bytes(), tc.expectResult))
|
||||
s.Require().NoError(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (s *CLITestSuite) TestGetCmdQueryTotalSupply() {
|
||||
cmd := cli.GetCmdQueryTotalSupply()
|
||||
cmd.SetOutput(io.Discard)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
ctxGen func() client.Context
|
||||
args []string
|
||||
expectResult proto.Message
|
||||
expectErr bool
|
||||
}{
|
||||
{
|
||||
"valid query",
|
||||
func() client.Context {
|
||||
bz, _ := s.encCfg.Codec.Marshal(&types.QueryTotalSupplyResponse{})
|
||||
c := clitestutil.NewMockCometRPC(abci.ResponseQuery{
|
||||
Value: bz,
|
||||
})
|
||||
return s.baseCtx.WithClient(c)
|
||||
},
|
||||
[]string{
|
||||
fmt.Sprintf("--%s=json", flags.FlagOutput),
|
||||
},
|
||||
&types.QueryTotalSupplyResponse{},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"valid query with denom",
|
||||
func() client.Context {
|
||||
bz, _ := s.encCfg.Codec.Marshal(&types.QuerySupplyOfResponse{
|
||||
Amount: sdk.Coin{},
|
||||
})
|
||||
c := clitestutil.NewMockCometRPC(abci.ResponseQuery{
|
||||
Value: bz,
|
||||
})
|
||||
return s.baseCtx.WithClient(c)
|
||||
},
|
||||
[]string{
|
||||
fmt.Sprintf("--%s=photon", cli.FlagDenom),
|
||||
fmt.Sprintf("--%s=json", flags.FlagOutput),
|
||||
},
|
||||
&sdk.Coin{},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"invalid query with denom",
|
||||
func() client.Context {
|
||||
c := clitestutil.NewMockCometRPC(abci.ResponseQuery{
|
||||
Code: 1,
|
||||
})
|
||||
return s.baseCtx.WithClient(c)
|
||||
},
|
||||
[]string{
|
||||
fmt.Sprintf("--%s=foo", cli.FlagDenom),
|
||||
fmt.Sprintf("--%s=json", flags.FlagOutput),
|
||||
},
|
||||
nil,
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
|
||||
s.Run(tc.name, func() {
|
||||
ctx := svrcmd.CreateExecuteContext(context.Background())
|
||||
cmd.SetContext(ctx)
|
||||
cmd.SetArgs(tc.args)
|
||||
s.Require().NoError(client.SetCmdClientContextHandler(tc.ctxGen(), cmd))
|
||||
|
||||
out, err := clitestutil.ExecTestCLICmd(tc.ctxGen(), cmd, tc.args)
|
||||
if tc.expectErr {
|
||||
s.Require().Error(err)
|
||||
} else {
|
||||
s.Require().NoError(s.encCfg.Codec.UnmarshalJSON(out.Bytes(), tc.expectResult))
|
||||
s.Require().NoError(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (s *CLITestSuite) TestGetCmdQuerySendEnabled() {
|
||||
cmd := cli.GetCmdQuerySendEnabled()
|
||||
cmd.SetOutput(io.Discard)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
ctxGen func() client.Context
|
||||
args []string
|
||||
expectResult proto.Message
|
||||
expectErr bool
|
||||
}{
|
||||
{
|
||||
"valid query",
|
||||
func() client.Context {
|
||||
bz, _ := s.encCfg.Codec.Marshal(&types.QuerySendEnabledResponse{
|
||||
SendEnabled: []*types.SendEnabled{},
|
||||
})
|
||||
c := clitestutil.NewMockCometRPC(abci.ResponseQuery{
|
||||
Value: bz,
|
||||
})
|
||||
return s.baseCtx.WithClient(c)
|
||||
},
|
||||
[]string{
|
||||
fmt.Sprintf("--%s=json", flags.FlagOutput),
|
||||
},
|
||||
&types.QuerySendEnabledResponse{},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"valid query with denoms",
|
||||
func() client.Context {
|
||||
bz, _ := s.encCfg.Codec.Marshal(&types.QuerySendEnabledResponse{
|
||||
SendEnabled: []*types.SendEnabled{},
|
||||
})
|
||||
c := clitestutil.NewMockCometRPC(abci.ResponseQuery{
|
||||
Value: bz,
|
||||
})
|
||||
return s.baseCtx.WithClient(c)
|
||||
},
|
||||
[]string{
|
||||
"photon",
|
||||
"stake",
|
||||
fmt.Sprintf("--%s=json", flags.FlagOutput),
|
||||
},
|
||||
&types.QuerySendEnabledResponse{},
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
|
||||
s.Run(tc.name, func() {
|
||||
ctx := svrcmd.CreateExecuteContext(context.Background())
|
||||
|
||||
cmd.SetContext(ctx)
|
||||
cmd.SetArgs(tc.args)
|
||||
|
||||
s.Require().NoError(client.SetCmdClientContextHandler(tc.ctxGen(), cmd))
|
||||
|
||||
out, err := clitestutil.ExecTestCLICmd(tc.ctxGen(), cmd, tc.args)
|
||||
if tc.expectErr {
|
||||
s.Require().Error(err)
|
||||
} else {
|
||||
s.Require().NoError(s.encCfg.Codec.UnmarshalJSON(out.Bytes(), tc.expectResult))
|
||||
s.Require().NoError(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
package cli_test
|
||||
|
||||
import (
|
||||
"io"
|
||||
"testing"
|
||||
|
||||
rpcclientmock "github.com/cometbft/cometbft/rpc/client/mock"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
|
||||
testutilmod "github.com/cosmos/cosmos-sdk/types/module/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/x/bank"
|
||||
)
|
||||
|
||||
type CLITestSuite struct {
|
||||
suite.Suite
|
||||
|
||||
kr keyring.Keyring
|
||||
encCfg testutilmod.TestEncodingConfig
|
||||
baseCtx client.Context
|
||||
}
|
||||
|
||||
func TestCLITestSuite(t *testing.T) {
|
||||
suite.Run(t, new(CLITestSuite))
|
||||
}
|
||||
|
||||
func (s *CLITestSuite) SetupSuite() {
|
||||
s.encCfg = testutilmod.MakeTestEncodingConfig(bank.AppModuleBasic{})
|
||||
s.kr = keyring.NewInMemory(s.encCfg.Codec)
|
||||
s.baseCtx = client.Context{}.
|
||||
WithKeyring(s.kr).
|
||||
WithTxConfig(s.encCfg.TxConfig).
|
||||
WithCodec(s.encCfg.Codec).
|
||||
WithClient(clitestutil.MockCometRPC{Client: rpcclientmock.Client{}}).
|
||||
WithAccountRetriever(client.MockAccountRetriever{}).
|
||||
WithOutput(io.Discard)
|
||||
}
|
||||
@@ -4,19 +4,50 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"testing"
|
||||
|
||||
rpcclientmock "github.com/cometbft/cometbft/rpc/client/mock"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
sdkmath "cosmossdk.io/math"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/codec/address"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
svrcmd "github.com/cosmos/cosmos-sdk/server/cmd"
|
||||
"github.com/cosmos/cosmos-sdk/testutil"
|
||||
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
testutilmod "github.com/cosmos/cosmos-sdk/types/module/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/x/bank"
|
||||
"github.com/cosmos/cosmos-sdk/x/bank/client/cli"
|
||||
)
|
||||
|
||||
type CLITestSuite struct {
|
||||
suite.Suite
|
||||
|
||||
kr keyring.Keyring
|
||||
encCfg testutilmod.TestEncodingConfig
|
||||
baseCtx client.Context
|
||||
}
|
||||
|
||||
func TestCLITestSuite(t *testing.T) {
|
||||
suite.Run(t, new(CLITestSuite))
|
||||
}
|
||||
|
||||
func (s *CLITestSuite) SetupSuite() {
|
||||
s.encCfg = testutilmod.MakeTestEncodingConfig(bank.AppModuleBasic{})
|
||||
s.kr = keyring.NewInMemory(s.encCfg.Codec)
|
||||
s.baseCtx = client.Context{}.
|
||||
WithKeyring(s.kr).
|
||||
WithTxConfig(s.encCfg.TxConfig).
|
||||
WithCodec(s.encCfg.Codec).
|
||||
WithClient(clitestutil.MockCometRPC{Client: rpcclientmock.Client{}}).
|
||||
WithAccountRetriever(client.MockAccountRetriever{}).
|
||||
WithOutput(io.Discard)
|
||||
}
|
||||
|
||||
func (s *CLITestSuite) TestSendTxCmd() {
|
||||
accounts := testutil.CreateKeyringAccounts(s.T(), s.kr, 1)
|
||||
cmd := cli.NewSendTxCmd(address.NewBech32Codec("cosmos"))
|
||||
|
||||
@@ -19,31 +19,81 @@ func (suite *KeeperTestSuite) TestQueryBalance() {
|
||||
ctx, queryClient := suite.ctx, suite.queryClient
|
||||
_, _, addr := testdata.KeyTestPubAddr()
|
||||
|
||||
_, err := queryClient.Balance(gocontext.Background(), &types.QueryBalanceRequest{})
|
||||
suite.Require().Error(err)
|
||||
|
||||
_, err = queryClient.Balance(gocontext.Background(), &types.QueryBalanceRequest{Address: addr.String()})
|
||||
suite.Require().Error(err)
|
||||
|
||||
req := types.NewQueryBalanceRequest(addr, "0000")
|
||||
_, err = queryClient.Balance(gocontext.Background(), req)
|
||||
suite.Require().Error(err)
|
||||
|
||||
req = types.NewQueryBalanceRequest(addr, fooDenom)
|
||||
res, err := queryClient.Balance(gocontext.Background(), req)
|
||||
suite.Require().NoError(err)
|
||||
suite.Require().NotNil(res)
|
||||
suite.True(res.Balance.IsZero())
|
||||
|
||||
origCoins := sdk.NewCoins(newFooCoin(50), newBarCoin(30))
|
||||
|
||||
origCoins := sdk.NewCoins(newBarCoin(30))
|
||||
suite.mockFundAccount(addr)
|
||||
suite.Require().NoError(testutil.FundAccount(ctx, suite.bankKeeper, addr, origCoins))
|
||||
|
||||
res, err = queryClient.Balance(gocontext.Background(), req)
|
||||
suite.Require().NoError(err)
|
||||
suite.Require().NotNil(res)
|
||||
suite.True(res.Balance.IsEqual(newFooCoin(50)))
|
||||
testCases := []struct {
|
||||
name string
|
||||
req *types.QueryBalanceRequest
|
||||
expectErrMsg string
|
||||
postFn func(res *types.QueryBalanceResponse)
|
||||
}{
|
||||
{
|
||||
"empty request",
|
||||
&types.QueryBalanceRequest{},
|
||||
"invalid denom",
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"invalid denom",
|
||||
types.NewQueryBalanceRequest(addr, "0000"),
|
||||
"invalid denom",
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"empty address",
|
||||
types.NewQueryBalanceRequest(sdk.AccAddress{}, barDenom),
|
||||
"empty address string is not allowed",
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"invalid address",
|
||||
&types.QueryBalanceRequest{Address: "foo", Denom: barDenom},
|
||||
"invalid address",
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"query missing denom",
|
||||
&types.QueryBalanceRequest{Address: addr.String()},
|
||||
"invalid denom",
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"valid query empty result",
|
||||
types.NewQueryBalanceRequest(addr, fooDenom),
|
||||
"",
|
||||
func(res *types.QueryBalanceResponse) {
|
||||
suite.True(res.Balance.IsZero())
|
||||
},
|
||||
},
|
||||
{
|
||||
"valid query",
|
||||
types.NewQueryBalanceRequest(addr, barDenom),
|
||||
"",
|
||||
func(res *types.QueryBalanceResponse) {
|
||||
suite.True(res.Balance.IsEqual(newBarCoin(30)))
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
|
||||
suite.Run(tc.name, func() {
|
||||
res, err := queryClient.Balance(gocontext.Background(), tc.req)
|
||||
if tc.expectErrMsg == "" {
|
||||
suite.Require().NoError(err)
|
||||
suite.Require().NotNil(res)
|
||||
} else {
|
||||
suite.Require().ErrorContains(err, tc.expectErrMsg)
|
||||
}
|
||||
|
||||
if tc.postFn != nil {
|
||||
tc.postFn(res)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestQueryAllBalances() {
|
||||
@@ -231,13 +281,12 @@ func (suite *KeeperTestSuite) TestQueryTotalSupply() {
|
||||
ctx, queryClient := suite.ctx, suite.queryClient
|
||||
res, err := queryClient.TotalSupply(gocontext.Background(), &types.QueryTotalSupplyRequest{})
|
||||
suite.Require().NoError(err)
|
||||
suite.Require().NotNil(res)
|
||||
genesisSupply := res.Supply
|
||||
testCoins := sdk.NewCoins(sdk.NewInt64Coin("test", 400000000))
|
||||
|
||||
suite.mockMintCoins(mintAcc)
|
||||
suite.
|
||||
Require().
|
||||
NoError(suite.bankKeeper.MintCoins(ctx, minttypes.ModuleName, testCoins))
|
||||
suite.Require().NoError(suite.bankKeeper.MintCoins(ctx, minttypes.ModuleName, testCoins))
|
||||
|
||||
res, err = queryClient.TotalSupply(gocontext.Background(), &types.QueryTotalSupplyRequest{})
|
||||
suite.Require().NoError(err)
|
||||
@@ -256,9 +305,7 @@ func (suite *KeeperTestSuite) TestQueryTotalSupplyOf() {
|
||||
expectedTotalSupply := sdk.NewCoins(test1Supply, test2Supply)
|
||||
|
||||
suite.mockMintCoins(mintAcc)
|
||||
suite.
|
||||
Require().
|
||||
NoError(suite.bankKeeper.MintCoins(ctx, minttypes.ModuleName, expectedTotalSupply))
|
||||
suite.Require().NoError(suite.bankKeeper.MintCoins(ctx, minttypes.ModuleName, expectedTotalSupply))
|
||||
|
||||
_, err := queryClient.SupplyOf(gocontext.Background(), &types.QuerySupplyOfRequest{})
|
||||
suite.Require().Error(err)
|
||||
@@ -266,8 +313,13 @@ func (suite *KeeperTestSuite) TestQueryTotalSupplyOf() {
|
||||
res, err := queryClient.SupplyOf(gocontext.Background(), &types.QuerySupplyOfRequest{Denom: test1Supply.Denom})
|
||||
suite.Require().NoError(err)
|
||||
suite.Require().NotNil(res)
|
||||
|
||||
suite.Require().Equal(test1Supply, res.Amount)
|
||||
|
||||
// total supply bogus denom
|
||||
res, err = queryClient.SupplyOf(gocontext.Background(), &types.QuerySupplyOfRequest{Denom: "bogus"})
|
||||
suite.Require().NoError(err)
|
||||
suite.Require().NotNil(res)
|
||||
suite.Require().Equal(sdk.NewInt64Coin("bogus", 0), res.Amount)
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestQueryParams() {
|
||||
@@ -277,7 +329,7 @@ func (suite *KeeperTestSuite) TestQueryParams() {
|
||||
suite.Require().Equal(suite.bankKeeper.GetParams(suite.ctx), res.GetParams())
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestQueryDenomsMetadataRequest() {
|
||||
func (suite *KeeperTestSuite) TestQueryDenomsMetadata() {
|
||||
var (
|
||||
req *types.QueryDenomsMetadataRequest
|
||||
expMetadata = []types.Metadata(nil)
|
||||
@@ -379,7 +431,7 @@ func (suite *KeeperTestSuite) TestQueryDenomsMetadataRequest() {
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestQueryDenomMetadataRequest() {
|
||||
func (suite *KeeperTestSuite) TestQueryDenomMetadata() {
|
||||
var (
|
||||
req *types.QueryDenomMetadataRequest
|
||||
expMetadata = types.Metadata{}
|
||||
@@ -456,7 +508,7 @@ func (suite *KeeperTestSuite) TestQueryDenomMetadataRequest() {
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestGRPCDenomOwners() {
|
||||
func (suite *KeeperTestSuite) TestQueryDenomOwners() {
|
||||
ctx := suite.ctx
|
||||
|
||||
keeper := suite.bankKeeper
|
||||
|
||||
+1
-1
@@ -87,7 +87,7 @@ func (ab AppModuleBasic) GetTxCmd() *cobra.Command {
|
||||
|
||||
// GetQueryCmd returns no root query command for the bank module.
|
||||
func (ab AppModuleBasic) GetQueryCmd() *cobra.Command {
|
||||
return cli.GetQueryCmd(ab.ac)
|
||||
return nil
|
||||
}
|
||||
|
||||
// RegisterInterfaces registers interfaces and implementations of the bank module.
|
||||
|
||||
Reference in New Issue
Block a user