diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ea3bb8a400c..ff654f363b12 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -49,10 +49,17 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### API Breaking Changes -* (x/auth) [#16650](https://github.com/cosmos/cosmos-sdk/pull/16650) The testutil `QueryAccountExec` has been removed from auth as it was using the CLI. +* (testutil) [#16899](https://github.com/cosmos/cosmos-sdk/pull/16899) The *cli testutil* `QueryBalancesExec` has been removed. Use the gRPC or REST query instead. +* (x/auth) [#16650](https://github.com/cosmos/cosmos-sdk/pull/16650) The *cli testutil* `QueryAccountExec` has been removed. Use the gRPC or REST query instead. * (types/math) [#16040](https://github.com/cosmos/cosmos-sdk/pull/16798) Remove aliases in `types/math.go` (part 2). * (x/staking) [#16795](https://github.com/cosmos/cosmos-sdk/pull/16795) `DelegationToDelegationResponse`, `DelegationsToDelegationResponses`, `RedelegationsToRedelegationResponses` are no longer exported. +## CLI Breaking Changes + +* (x/bank) [#16899](https://github.com/cosmos/cosmos-sdk/pull/16899) With the migration to AutoCLI some bank commands have been split in two: + * Use `denoms-metadata` for querying all denom metadata and `denom-metadata` for querying a specific denom metadata. + * Use `total-supply` (or `total`) for querying the total supply and `total-supply-of` for querying the supply of a specific denom. + ## [v0.50.0-alpha.1](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.50.0-alpha.1) - 2023-06-30 ### Features diff --git a/tests/e2e/auth/suite.go b/tests/e2e/auth/suite.go index 81df6f4b1e87..8209a6fd4a49 100644 --- a/tests/e2e/auth/suite.go +++ b/tests/e2e/auth/suite.go @@ -612,11 +612,11 @@ func (s *E2ETestSuite) TestCLISendGenerateSignAndBroadcast() { s.Require().NoError(err) s.Require().Equal(0, len(sigs)) - resp, err := clitestutil.QueryBalancesExec(val1.ClientCtx, val1.Address, addresscodec.NewBech32Codec("cosmos")) + resp, err := testutil.GetRequest(fmt.Sprintf("%s/cosmos/bank/v1beta1/balances/%s", val1.APIAddress, val1.Address)) s.Require().NoError(err) var balRes banktypes.QueryAllBalancesResponse - err = val1.ClientCtx.Codec.UnmarshalJSON(resp.Bytes(), &balRes) + err = val1.ClientCtx.Codec.UnmarshalJSON(resp, &balRes) s.Require().NoError(err) startTokens := balRes.Balances.AmountOf(s.cfg.BondDenom) @@ -679,10 +679,9 @@ func (s *E2ETestSuite) TestCLISendGenerateSignAndBroadcast() { s.Require().NoError(s.network.WaitForNextBlock()) // Ensure foo has right amount of funds - resp, err = clitestutil.QueryBalancesExec(val1.ClientCtx, val1.Address, addresscodec.NewBech32Codec("cosmos")) + resp, err = testutil.GetRequest(fmt.Sprintf("%s/cosmos/bank/v1beta1/balances/%s", val1.APIAddress, val1.Address)) s.Require().NoError(err) - - err = val1.ClientCtx.Codec.UnmarshalJSON(resp.Bytes(), &balRes) + err = val1.ClientCtx.Codec.UnmarshalJSON(resp, &balRes) s.Require().NoError(err) s.Require().Equal(startTokens, balRes.Balances.AmountOf(s.cfg.BondDenom)) @@ -701,20 +700,20 @@ func (s *E2ETestSuite) TestCLISendGenerateSignAndBroadcast() { // Ensure destiny account state err = s.network.RetryForBlocks(func() error { - resp, err = clitestutil.QueryBalancesExec(val1.ClientCtx, addr, addresscodec.NewBech32Codec("cosmos")) + resp, err = testutil.GetRequest(fmt.Sprintf("%s/cosmos/bank/v1beta1/balances/%s", val1.APIAddress, addr)) + s.Require().NoError(err) return err }, 3) s.Require().NoError(err) - err = val1.ClientCtx.Codec.UnmarshalJSON(resp.Bytes(), &balRes) + err = val1.ClientCtx.Codec.UnmarshalJSON(resp, &balRes) s.Require().NoError(err) s.Require().Equal(sendTokens.Amount, balRes.Balances.AmountOf(s.cfg.BondDenom)) // Ensure origin account state - resp, err = clitestutil.QueryBalancesExec(val1.ClientCtx, val1.Address, addresscodec.NewBech32Codec("cosmos")) + resp, err = testutil.GetRequest(fmt.Sprintf("%s/cosmos/bank/v1beta1/balances/%s", val1.APIAddress, val1.Address)) s.Require().NoError(err) - - err = val1.ClientCtx.Codec.UnmarshalJSON(resp.Bytes(), &balRes) + err = val1.ClientCtx.Codec.UnmarshalJSON(resp, &balRes) s.Require().NoError(err) } @@ -833,11 +832,11 @@ func (s *E2ETestSuite) TestCLIMultisignSortSignatures() { addr, err := multisigRecord.GetAddress() s.Require().NoError(err) - resp, err := clitestutil.QueryBalancesExec(val1.ClientCtx, addr, addresscodec.NewBech32Codec("cosmos")) + resp, err := testutil.GetRequest(fmt.Sprintf("%s/cosmos/bank/v1beta1/balances/%s", val1.APIAddress, addr)) s.Require().NoError(err) var balRes banktypes.QueryAllBalancesResponse - err = val1.ClientCtx.Codec.UnmarshalJSON(resp.Bytes(), &balRes) + err = val1.ClientCtx.Codec.UnmarshalJSON(resp, &balRes) s.Require().NoError(err) intialCoins := balRes.Balances @@ -851,10 +850,9 @@ func (s *E2ETestSuite) TestCLIMultisignSortSignatures() { s.Require().NoError(err) s.Require().NoError(s.network.WaitForNextBlock()) - resp, err = clitestutil.QueryBalancesExec(val1.ClientCtx, addr, addresscodec.NewBech32Codec("cosmos")) + resp, err = testutil.GetRequest(fmt.Sprintf("%s/cosmos/bank/v1beta1/balances/%s", val1.APIAddress, addr)) s.Require().NoError(err) - - err = val1.ClientCtx.Codec.UnmarshalJSON(resp.Bytes(), &balRes) + err = val1.ClientCtx.Codec.UnmarshalJSON(resp, &balRes) s.Require().NoError(err) diff, _ := balRes.Balances.SafeSub(intialCoins...) s.Require().Equal(sendTokens.Amount, diff.AmountOf(s.cfg.BondDenom)) @@ -993,11 +991,12 @@ func (s *E2ETestSuite) TestCLIMultisign() { var balRes banktypes.QueryAllBalancesResponse err = s.network.RetryForBlocks(func() error { - resp, err := clitestutil.QueryBalancesExec(val1.ClientCtx, addr, addresscodec.NewBech32Codec("cosmos")) + resp, err := testutil.GetRequest(fmt.Sprintf("%s/cosmos/bank/v1beta1/balances/%s", val1.APIAddress, addr)) + s.Require().NoError(err) if err != nil { return err } - return val1.ClientCtx.Codec.UnmarshalJSON(resp.Bytes(), &balRes) + return val1.ClientCtx.Codec.UnmarshalJSON(resp, &balRes) }, 3) s.Require().NoError(err) s.Require().True(sendTokens.Amount.Equal(balRes.Balances.AmountOf(s.cfg.BondDenom))) @@ -1393,10 +1392,10 @@ func (s *E2ETestSuite) TestSignWithMultiSignersAminoJSON() { require.Equal(uint32(0), txRes.Code, txRes.RawLog) // Make sure the addr1's balance got funded. - queryResJSON, err := clitestutil.QueryBalancesExec(val0.ClientCtx, addr1, addresscodec.NewBech32Codec("cosmos")) - require.NoError(err) + resp, err := testutil.GetRequest(fmt.Sprintf("%s/cosmos/bank/v1beta1/balances/%s", val0.APIAddress, addr1)) + s.Require().NoError(err) var queryRes banktypes.QueryAllBalancesResponse - err = val0.ClientCtx.Codec.UnmarshalJSON(queryResJSON.Bytes(), &queryRes) + err = val0.ClientCtx.Codec.UnmarshalJSON(resp, &queryRes) require.NoError(err) require.Equal(sdk.NewCoins(val0Coin, val1Coin), queryRes.Balances) } @@ -1729,11 +1728,11 @@ func (s *E2ETestSuite) createBankMsg(val *network.Validator, toAddr sdk.AccAddre } func (s *E2ETestSuite) getBalances(clientCtx client.Context, addr sdk.AccAddress, denom string) math.Int { - resp, err := clitestutil.QueryBalancesExec(clientCtx, addr, addresscodec.NewBech32Codec("cosmos")) + resp, err := testutil.GetRequest(fmt.Sprintf("%s/cosmos/bank/v1beta1/balances/%s/by_denom?denom=%s", s.cfg.APIAddress, addr.String(), denom)) s.Require().NoError(err) var balRes banktypes.QueryAllBalancesResponse - err = clientCtx.Codec.UnmarshalJSON(resp.Bytes(), &balRes) + err = clientCtx.Codec.UnmarshalJSON(resp, &balRes) s.Require().NoError(err) startTokens := balRes.Balances.AmountOf(denom) return startTokens diff --git a/tests/e2e/bank/suite.go b/tests/e2e/bank/suite.go index 449d46a310e0..48b34f12b483 100644 --- a/tests/e2e/bank/suite.go +++ b/tests/e2e/bank/suite.go @@ -18,7 +18,6 @@ import ( "github.com/cosmos/cosmos-sdk/testutil/network" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - "github.com/cosmos/cosmos-sdk/types/query" "github.com/cosmos/cosmos-sdk/x/bank/client/cli" "github.com/cosmos/cosmos-sdk/x/bank/types" ) @@ -96,276 +95,6 @@ func (s *E2ETestSuite) TearDownSuite() { s.network.Cleanup() } -func (s *E2ETestSuite) TestGetBalancesCmd() { - val := s.network.Validators[0] - - testCases := []struct { - name string - args []string - expectErr bool - respType proto.Message - expected proto.Message - }{ - {"no address provided", []string{}, true, nil, nil}, - { - "total account balance", - []string{ - val.Address.String(), - fmt.Sprintf("--%s=json", flags.FlagOutput), - fmt.Sprintf("--%s=1", flags.FlagHeight), - }, - false, - &types.QueryAllBalancesResponse{}, - &types.QueryAllBalancesResponse{ - Balances: sdk.NewCoins( - sdk.NewCoin(fmt.Sprintf("%stoken", val.Moniker), s.cfg.AccountTokens), - sdk.NewCoin(s.cfg.BondDenom, s.cfg.StakingTokens.Sub(s.cfg.BondedTokens)), - ), - Pagination: &query.PageResponse{}, - }, - }, - { - "total account balance of a specific denom", - []string{ - val.Address.String(), - fmt.Sprintf("--%s=json", flags.FlagOutput), - fmt.Sprintf("--%s=%s", cli.FlagDenom, s.cfg.BondDenom), - fmt.Sprintf("--%s=1", flags.FlagHeight), - }, - false, - &sdk.Coin{}, - NewCoin(s.cfg.BondDenom, s.cfg.StakingTokens.Sub(s.cfg.BondedTokens)), - }, - { - "total account balance of a bogus denom", - []string{ - val.Address.String(), - fmt.Sprintf("--%s=foobar", cli.FlagDenom), - fmt.Sprintf("--%s=json", flags.FlagOutput), - }, - false, - &sdk.Coin{}, - NewCoin("foobar", math.ZeroInt()), - }, - } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.GetBalancesCmd(addresscodec.NewBech32Codec("cosmos")) - out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, cmd, tc.args) - - if tc.expectErr { - s.Require().Error(err) - } else { - s.Require().NoError(err) - s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType)) - s.Require().Equal(tc.expected.String(), tc.respType.String()) - } - }) - } -} - -func (s *E2ETestSuite) TestGetCmdQueryTotalSupply() { - val := s.network.Validators[0] - - testCases := []struct { - name string - args []string - expectErr bool - respType proto.Message - expected proto.Message - }{ - { - name: "total supply", - args: []string{ - fmt.Sprintf("--%s=1", flags.FlagHeight), - fmt.Sprintf("--%s=json", flags.FlagOutput), - }, - respType: &types.QueryTotalSupplyResponse{}, - expected: &types.QueryTotalSupplyResponse{ - Supply: sdk.NewCoins( - sdk.NewCoin(fmt.Sprintf("%stoken", val.Moniker), s.cfg.AccountTokens), - sdk.NewCoin(s.cfg.BondDenom, s.cfg.StakingTokens.Add(math.NewInt(10))), - ), - Pagination: &query.PageResponse{Total: 0}, - }, - }, - { - name: "total supply of a specific denomination", - args: []string{ - fmt.Sprintf("--%s=1", flags.FlagHeight), - fmt.Sprintf("--%s=%s", cli.FlagDenom, s.cfg.BondDenom), - fmt.Sprintf("--%s=json", flags.FlagOutput), - }, - respType: &sdk.Coin{}, - expected: &sdk.Coin{ - Denom: s.cfg.BondDenom, - Amount: s.cfg.StakingTokens.Add(math.NewInt(10)), - }, - }, - { - name: "total supply of a bogus denom", - args: []string{ - fmt.Sprintf("--%s=1", flags.FlagHeight), - fmt.Sprintf("--%s=foobar", cli.FlagDenom), - fmt.Sprintf("--%s=json", flags.FlagOutput), - }, - respType: &sdk.Coin{}, - expected: &sdk.Coin{ - Denom: "foobar", - Amount: math.ZeroInt(), - }, - }, - } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.GetCmdQueryTotalSupply() - clientCtx := val.ClientCtx - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - if tc.expectErr { - s.Require().Error(err) - } else { - s.Require().NoError(err) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType)) - s.Require().Equal(tc.expected, tc.respType) - } - }) - } -} - -func (s *E2ETestSuite) TestGetCmdQueryDenomsMetadata() { - val := s.network.Validators[0] - - testCases := []struct { - name string - args []string - expectErr bool - respType proto.Message - expected proto.Message - }{ - { - name: "all denoms client metadata", - args: []string{ - fmt.Sprintf("--%s=1", flags.FlagHeight), - fmt.Sprintf("--%s=json", flags.FlagOutput), - }, - respType: &types.QueryDenomsMetadataResponse{}, - expected: &types.QueryDenomsMetadataResponse{ - Metadatas: []types.Metadata{ - { - Name: "Cosmos Hub Atom", - Symbol: "ATOM", - Description: "The native staking token of the Cosmos Hub.", - DenomUnits: []*types.DenomUnit{ - { - Denom: "uatom", - Exponent: 0, - Aliases: []string{"microatom"}, - }, - { - Denom: "atom", - Exponent: 6, - Aliases: []string{"ATOM"}, - }, - }, - Base: "uatom", - Display: "atom", - }, - { - Name: "Ethereum", - Symbol: "ETH", - Description: "Ethereum mainnet token", - DenomUnits: []*types.DenomUnit{ - { - Denom: "wei", - Exponent: 0, - Aliases: []string{}, - }, - { - Denom: "eth", - Exponent: 6, - Aliases: []string{"ETH"}, - }, - }, - Base: "wei", - Display: "eth", - }, - }, - Pagination: &query.PageResponse{Total: 2}, - }, - }, - { - name: "client metadata of a specific denomination", - args: []string{ - fmt.Sprintf("--%s=1", flags.FlagHeight), - fmt.Sprintf("--%s=%s", cli.FlagDenom, "uatom"), - fmt.Sprintf("--%s=json", flags.FlagOutput), - }, - respType: &types.QueryDenomMetadataResponse{}, - expected: &types.QueryDenomMetadataResponse{ - Metadata: types.Metadata{ - Name: "Cosmos Hub Atom", - Symbol: "ATOM", - Description: "The native staking token of the Cosmos Hub.", - DenomUnits: []*types.DenomUnit{ - { - Denom: "uatom", - Exponent: 0, - Aliases: []string{"microatom"}, - }, - { - Denom: "atom", - Exponent: 6, - Aliases: []string{"ATOM"}, - }, - }, - Base: "uatom", - Display: "atom", - }, - }, - }, - { - name: "client metadata of a bogus denom", - args: []string{ - fmt.Sprintf("--%s=1", flags.FlagHeight), - fmt.Sprintf("--%s=foobar", cli.FlagDenom), - fmt.Sprintf("--%s=json", flags.FlagOutput), - }, - expectErr: true, - respType: &types.QueryDenomMetadataResponse{}, - expected: &types.QueryDenomMetadataResponse{ - Metadata: types.Metadata{ - DenomUnits: []*types.DenomUnit{}, - }, - }, - }, - } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.GetCmdDenomsMetadata() - clientCtx := val.ClientCtx - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - if tc.expectErr { - s.Require().Error(err) - } else { - s.Require().NoError(err) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), tc.respType)) - s.Require().Equal(tc.expected, tc.respType) - } - }) - } -} - func (s *E2ETestSuite) TestNewSendTxCmdGenOnly() { val := s.network.Validators[0] diff --git a/tests/e2e/gov/tx.go b/tests/e2e/gov/tx.go index 8d8d51f824f9..8c37f1342fd8 100644 --- a/tests/e2e/gov/tx.go +++ b/tests/e2e/gov/tx.go @@ -10,7 +10,6 @@ import ( "cosmossdk.io/math" "github.com/cosmos/cosmos-sdk/client/flags" - addresscodec "github.com/cosmos/cosmos-sdk/codec/address" "github.com/cosmos/cosmos-sdk/testutil" clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" "github.com/cosmos/cosmos-sdk/testutil/network" @@ -353,9 +352,9 @@ func (s *E2ETestSuite) TestNewCmdCancelProposal() { var balRes banktypes.QueryAllBalancesResponse var newBalance banktypes.QueryAllBalancesResponse if !tc.expectErr && tc.expectedCode == 0 { - resp, err := clitestutil.QueryBalancesExec(clientCtx, val.Address, addresscodec.NewBech32Codec("cosmos")) + resp, err := testutil.GetRequest(fmt.Sprintf("%s/cosmos/bank/v1beta1/balances/%s", val.APIAddress, val.Address.String())) s.Require().NoError(err) - err = val.ClientCtx.Codec.UnmarshalJSON(resp.Bytes(), &balRes) + err = val.ClientCtx.Codec.UnmarshalJSON(resp, &balRes) s.Require().NoError(err) } @@ -364,14 +363,13 @@ func (s *E2ETestSuite) TestNewCmdCancelProposal() { s.Require().Error(err) } else { s.Require().NoError(err) - s.Require().NoError(clientCtx.Codec.UnmarshalJSON(out.Bytes(), &resp), out.String()) s.Require().NoError(clitestutil.CheckTxCode(s.network, clientCtx, resp.TxHash, tc.expectedCode)) if !tc.expectErr && tc.expectedCode == 0 { - resp, err := clitestutil.QueryBalancesExec(clientCtx, val.Address, addresscodec.NewBech32Codec("cosmos")) + resp, err := testutil.GetRequest(fmt.Sprintf("%s/cosmos/bank/v1beta1/balances/%s", val.APIAddress, val.Address.String())) s.Require().NoError(err) - err = val.ClientCtx.Codec.UnmarshalJSON(resp.Bytes(), &newBalance) + err = val.ClientCtx.Codec.UnmarshalJSON(resp, &newBalance) s.Require().NoError(err) remainingAmount := v1.DefaultMinDepositTokens.Mul( v1.DefaultProposalCancelRatio.Mul(math.LegacyMustNewDecFromStr("100")).TruncateInt(), diff --git a/tests/integration/auth/client/cli/suite_test.go b/tests/integration/auth/client/cli/suite_test.go index ce81f4b2fd44..f618c64b8d6d 100644 --- a/tests/integration/auth/client/cli/suite_test.go +++ b/tests/integration/auth/client/cli/suite_test.go @@ -1242,11 +1242,11 @@ func (s *CLITestSuite) TestAuxToFeeWithTips() { } func (s *CLITestSuite) getBalances(clientCtx client.Context, addr sdk.AccAddress, denom string) math.Int { - resp, err := clitestutil.QueryBalancesExec(clientCtx, addr, s.ac) + resp, err := testutil.GetRequest(fmt.Sprintf("%s/cosmos/bank/v1beta1/balances/%s/by_denom?denom=%s", s.baseCtx.NodeURI, addr.String(), denom)) s.Require().NoError(err) var balRes banktypes.QueryAllBalancesResponse - err = clientCtx.Codec.UnmarshalJSON(resp.Bytes(), &balRes) + err = clientCtx.Codec.UnmarshalJSON(resp, &balRes) s.Require().NoError(err) startTokens := balRes.Balances.AmountOf(denom) return startTokens diff --git a/testutil/cli/cmd.go b/testutil/cli/cmd.go index e9860c4d5272..57b5b11ee6e5 100644 --- a/testutil/cli/cmd.go +++ b/testutil/cli/cmd.go @@ -9,7 +9,6 @@ import ( "cosmossdk.io/core/address" "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/testutil" "github.com/cosmos/cosmos-sdk/x/bank/client/cli" ) @@ -37,10 +36,3 @@ func MsgSendExec(clientCtx client.Context, from, to, amount fmt.Stringer, ac add return ExecTestCLICmd(clientCtx, cli.NewSendTxCmd(ac), args) } - -func QueryBalancesExec(clientCtx client.Context, address fmt.Stringer, ac address.Codec, extraArgs ...string) (testutil.BufferWriter, error) { - args := []string{address.String(), fmt.Sprintf("--%s=json", flags.FlagOutput)} - args = append(args, extraArgs...) - - return ExecTestCLICmd(clientCtx, cli.GetBalancesCmd(ac), args) -} diff --git a/x/bank/autocli.go b/x/bank/autocli.go new file mode 100644 index 000000000000..6d839f94ca08 --- /dev/null +++ b/x/bank/autocli.go @@ -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"}}, + }, + }, + }, + } +} diff --git a/x/bank/client/cli/query.go b/x/bank/client/cli/query.go deleted file mode 100644 index 61950d88de45..000000000000 --- a/x/bank/client/cli/query.go +++ /dev/null @@ -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 -} diff --git a/x/bank/client/cli/query_test.go b/x/bank/client/cli/query_test.go deleted file mode 100644 index 800530b53d18..000000000000 --- a/x/bank/client/cli/query_test.go +++ /dev/null @@ -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) - } - }) - } -} diff --git a/x/bank/client/cli/suite_test.go b/x/bank/client/cli/suite_test.go deleted file mode 100644 index 9ba83b31b662..000000000000 --- a/x/bank/client/cli/suite_test.go +++ /dev/null @@ -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) -} diff --git a/x/bank/client/cli/tx_test.go b/x/bank/client/cli/tx_test.go index 1391ba835298..a9a5280f0bff 100644 --- a/x/bank/client/cli/tx_test.go +++ b/x/bank/client/cli/tx_test.go @@ -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")) diff --git a/x/bank/keeper/grpc_query_test.go b/x/bank/keeper/grpc_query_test.go index d9357f257abf..9381a787a63f 100644 --- a/x/bank/keeper/grpc_query_test.go +++ b/x/bank/keeper/grpc_query_test.go @@ -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) + origCoins := sdk.NewCoins(newBarCoin(30)) + suite.mockFundAccount(addr) + suite.Require().NoError(testutil.FundAccount(ctx, suite.bankKeeper, addr, origCoins)) - 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()) + 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))) + }, + }, + } - origCoins := sdk.NewCoins(newFooCoin(50), newBarCoin(30)) + for _, tc := range testCases { + tc := tc - suite.mockFundAccount(addr) - suite.Require().NoError(testutil.FundAccount(ctx, suite.bankKeeper, addr, origCoins)) + 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) + } - res, err = queryClient.Balance(gocontext.Background(), req) - suite.Require().NoError(err) - suite.Require().NotNil(res) - suite.True(res.Balance.IsEqual(newFooCoin(50))) + if tc.postFn != nil { + tc.postFn(res) + } + }) + } } func (suite *KeeperTestSuite) TestQueryAllBalances() { @@ -231,13 +281,18 @@ 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) +<<<<<<< HEAD suite. Require(). NoError(suite.bankKeeper.MintCoins(ctx, minttypes.ModuleName, testCoins)) +======= + suite.Require().NoError(suite.bankKeeper.MintCoins(ctx, types.MintModuleName, testCoins)) +>>>>>>> febeced2e (feat(bank): autocli query support (#16899)) res, err = queryClient.TotalSupply(gocontext.Background(), &types.QueryTotalSupplyRequest{}) suite.Require().NoError(err) @@ -256,9 +311,13 @@ func (suite *KeeperTestSuite) TestQueryTotalSupplyOf() { expectedTotalSupply := sdk.NewCoins(test1Supply, test2Supply) suite.mockMintCoins(mintAcc) +<<<<<<< HEAD suite. Require(). NoError(suite.bankKeeper.MintCoins(ctx, minttypes.ModuleName, expectedTotalSupply)) +======= + suite.Require().NoError(suite.bankKeeper.MintCoins(ctx, types.MintModuleName, expectedTotalSupply)) +>>>>>>> febeced2e (feat(bank): autocli query support (#16899)) _, err := queryClient.SupplyOf(gocontext.Background(), &types.QuerySupplyOfRequest{}) suite.Require().Error(err) @@ -266,8 +325,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 +341,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 +443,7 @@ func (suite *KeeperTestSuite) TestQueryDenomsMetadataRequest() { } } -func (suite *KeeperTestSuite) TestQueryDenomMetadataRequest() { +func (suite *KeeperTestSuite) TestQueryDenomMetadata() { var ( req *types.QueryDenomMetadataRequest expMetadata = types.Metadata{} @@ -456,7 +520,7 @@ func (suite *KeeperTestSuite) TestQueryDenomMetadataRequest() { } } -func (suite *KeeperTestSuite) TestGRPCDenomOwners() { +func (suite *KeeperTestSuite) TestQueryDenomOwners() { ctx := suite.ctx keeper := suite.bankKeeper diff --git a/x/bank/module.go b/x/bank/module.go index a4bb30d0208f..eb66e4292f76 100644 --- a/x/bank/module.go +++ b/x/bank/module.go @@ -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.