diff --git a/CHANGELOG.md b/CHANGELOG.md index bd2d5b3c606d..a58c3e625fe4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Improvements * (all) [#16497](https://github.com/cosmos/cosmos-sdk/pull/16497) Removed all exported vestiges of `sdk.MustSortJSON` and `sdk.SortJSON`. +* (x/distribution) [#16218](https://github.com/cosmos/cosmos-sdk/pull/16218) Add Autocli config to distribution module. ### Bug Fixes diff --git a/tests/e2e/distribution/grpc_query_suite.go b/tests/e2e/distribution/grpc_query_suite.go index c9765fbb8ae5..a397a5e06054 100644 --- a/tests/e2e/distribution/grpc_query_suite.go +++ b/tests/e2e/distribution/grpc_query_suite.go @@ -3,10 +3,11 @@ package distribution import ( "fmt" - "cosmossdk.io/simapp" "github.com/cosmos/gogoproto/proto" "github.com/stretchr/testify/suite" + "cosmossdk.io/simapp" + sdktestutil "github.com/cosmos/cosmos-sdk/testutil" "github.com/cosmos/cosmos-sdk/testutil/network" sdk "github.com/cosmos/cosmos-sdk/types" diff --git a/tests/e2e/distribution/suite.go b/tests/e2e/distribution/suite.go index f4d6e3dbf59b..7d10a239b27c 100644 --- a/tests/e2e/distribution/suite.go +++ b/tests/e2e/distribution/suite.go @@ -4,14 +4,14 @@ import ( "context" "encoding/hex" "fmt" - "strings" "time" "cosmossdk.io/math" - "cosmossdk.io/simapp" "github.com/cosmos/gogoproto/proto" "github.com/stretchr/testify/suite" + "cosmossdk.io/simapp" + "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/codec/address" @@ -72,430 +72,6 @@ func (s *E2ETestSuite) TearDownSuite() { s.network.Cleanup() } -func (s *E2ETestSuite) TestGetCmdQueryParams() { - val := s.network.Validators[0] - - testCases := []struct { - name string - args []string - expectedOutput string - }{ - { - "json output", - []string{fmt.Sprintf("--%s=json", flags.FlagOutput)}, - `{"community_tax":"0.020000000000000000","base_proposer_reward":"0.000000000000000000","bonus_proposer_reward":"0.000000000000000000","withdraw_addr_enabled":true}`, - }, - { - "text output", - []string{fmt.Sprintf("--%s=text", flags.FlagOutput)}, - `base_proposer_reward: "0.000000000000000000" -bonus_proposer_reward: "0.000000000000000000" -community_tax: "0.020000000000000000" -withdraw_addr_enabled: true`, - }, - } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.GetCmdQueryParams() - clientCtx := val.ClientCtx - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - s.Require().NoError(err) - s.Require().Equal(tc.expectedOutput, strings.TrimSpace(out.String())) - }) - } -} - -func (s *E2ETestSuite) TestGetCmdQueryValidatorDistributionInfo() { - val := s.network.Validators[0] - - testCases := []struct { - name string - args []string - expErr bool - }{ - { - "invalid val address", - []string{"invalid address", fmt.Sprintf("--%s=json", flags.FlagOutput)}, - true, - }, - { - "json output", - []string{val.ValAddress.String(), fmt.Sprintf("--%s=json", flags.FlagOutput)}, - false, - }, - { - "text output", - []string{val.ValAddress.String(), fmt.Sprintf("--%s=text", flags.FlagOutput)}, - false, - }, - } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.GetCmdQueryValidatorDistributionInfo() - clientCtx := val.ClientCtx - - _, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - if tc.expErr { - s.Require().Error(err) - } else { - s.Require().NoError(err) - } - }) - } -} - -func (s *E2ETestSuite) TestGetCmdQueryValidatorOutstandingRewards() { - val := s.network.Validators[0] - - _, err := s.network.WaitForHeight(4) - s.Require().NoError(err) - - testCases := []struct { - name string - args []string - expectErr bool - expectedOutput string - }{ - { - "invalid validator address", - []string{ - fmt.Sprintf("--%s=3", flags.FlagHeight), - "foo", - }, - true, - "", - }, - { - "json output", - []string{ - fmt.Sprintf("--%s=3", flags.FlagHeight), - sdk.ValAddress(val.Address).String(), - fmt.Sprintf("--%s=json", flags.FlagOutput), - }, - false, - `{"rewards":[{"denom":"stake","amount":"232.260000000000000000"}]}`, - }, - { - "text output", - []string{ - fmt.Sprintf("--%s=text", flags.FlagOutput), - fmt.Sprintf("--%s=3", flags.FlagHeight), - sdk.ValAddress(val.Address).String(), - }, - false, - `rewards: -- amount: "232.260000000000000000" - denom: stake`, - }, - } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.GetCmdQueryValidatorOutstandingRewards() - 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().Equal(tc.expectedOutput, strings.TrimSpace(out.String())) - } - }) - } -} - -func (s *E2ETestSuite) TestGetCmdQueryValidatorCommission() { - val := s.network.Validators[0] - - _, err := s.network.WaitForHeight(4) - s.Require().NoError(err) - - testCases := []struct { - name string - args []string - expectErr bool - expectedOutput string - }{ - { - "invalid validator address", - []string{ - fmt.Sprintf("--%s=3", flags.FlagHeight), - "foo", - }, - true, - "", - }, - { - "json output", - []string{ - fmt.Sprintf("--%s=3", flags.FlagHeight), - sdk.ValAddress(val.Address).String(), - fmt.Sprintf("--%s=json", flags.FlagOutput), - }, - false, - `{"commission":[{"denom":"stake","amount":"116.130000000000000000"}]}`, - }, - { - "text output", - []string{ - fmt.Sprintf("--%s=text", flags.FlagOutput), - fmt.Sprintf("--%s=3", flags.FlagHeight), - sdk.ValAddress(val.Address).String(), - }, - false, - `commission: -- amount: "116.130000000000000000" - denom: stake`, - }, - } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.GetCmdQueryValidatorCommission() - 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().Equal(tc.expectedOutput, strings.TrimSpace(out.String())) - } - }) - } -} - -func (s *E2ETestSuite) TestGetCmdQueryValidatorSlashes() { - val := s.network.Validators[0] - - _, err := s.network.WaitForHeight(4) - s.Require().NoError(err) - - testCases := []struct { - name string - args []string - expectErr bool - expectedOutput string - }{ - { - "invalid validator address", - []string{ - fmt.Sprintf("--%s=3", flags.FlagHeight), - "foo", "1", "3", - }, - true, - "", - }, - { - "invalid start height", - []string{ - fmt.Sprintf("--%s=3", flags.FlagHeight), - sdk.ValAddress(val.Address).String(), "-1", "3", - }, - true, - "", - }, - { - "invalid end height", - []string{ - fmt.Sprintf("--%s=3", flags.FlagHeight), - sdk.ValAddress(val.Address).String(), "1", "-3", - }, - true, - "", - }, - { - "json output", - []string{ - fmt.Sprintf("--%s=3", flags.FlagHeight), - sdk.ValAddress(val.Address).String(), "1", "3", - fmt.Sprintf("--%s=json", flags.FlagOutput), - }, - false, - "{\"slashes\":[],\"pagination\":{\"next_key\":null,\"total\":\"0\"}}", - }, - { - "text output", - []string{ - fmt.Sprintf("--%s=text", flags.FlagOutput), - fmt.Sprintf("--%s=3", flags.FlagHeight), - sdk.ValAddress(val.Address).String(), "1", "3", - }, - false, - "pagination:\n next_key: null\n total: \"0\"\nslashes: []", - }, - } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.GetCmdQueryValidatorSlashes() - 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().Equal(tc.expectedOutput, strings.TrimSpace(out.String())) - } - }) - } -} - -func (s *E2ETestSuite) TestGetCmdQueryDelegatorRewards() { - val := s.network.Validators[0] - addr := val.Address - valAddr := sdk.ValAddress(addr) - - _, err := s.network.WaitForHeightWithTimeout(11, time.Minute) - s.Require().NoError(err) - - testCases := []struct { - name string - args []string - expectErr bool - expectedOutput string - }{ - { - "invalid delegator address", - []string{ - fmt.Sprintf("--%s=5", flags.FlagHeight), - "foo", valAddr.String(), - }, - true, - "", - }, - { - "invalid validator address", - []string{ - fmt.Sprintf("--%s=5", flags.FlagHeight), - addr.String(), "foo", - }, - true, - "", - }, - { - "json output", - []string{ - fmt.Sprintf("--%s=5", flags.FlagHeight), - addr.String(), - fmt.Sprintf("--%s=json", flags.FlagOutput), - }, - false, - fmt.Sprintf(`{"rewards":[{"validator_address":"%s","reward":[{"denom":"stake","amount":"193.550000000000000000"}]}],"total":[{"denom":"stake","amount":"193.550000000000000000"}]}`, valAddr.String()), - }, - { - "json output (specific validator)", - []string{ - fmt.Sprintf("--%s=5", flags.FlagHeight), - addr.String(), valAddr.String(), - fmt.Sprintf("--%s=json", flags.FlagOutput), - }, - false, - `{"rewards":[{"denom":"stake","amount":"193.550000000000000000"}]}`, - }, - { - "text output", - []string{ - fmt.Sprintf("--%s=text", flags.FlagOutput), - fmt.Sprintf("--%s=5", flags.FlagHeight), - addr.String(), - }, - false, - fmt.Sprintf(`rewards: -- reward: - - amount: "193.550000000000000000" - denom: stake - validator_address: %s -total: -- amount: "193.550000000000000000" - denom: stake`, valAddr.String()), - }, - { - "text output (specific validator)", - []string{ - fmt.Sprintf("--%s=text", flags.FlagOutput), - fmt.Sprintf("--%s=5", flags.FlagHeight), - addr.String(), valAddr.String(), - }, - false, - `rewards: -- amount: "193.550000000000000000" - denom: stake`, - }, - } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.GetCmdQueryDelegatorRewards(address.NewBech32Codec("cosmos")) - 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().Equal(tc.expectedOutput, strings.TrimSpace(out.String())) - } - }) - } -} - -func (s *E2ETestSuite) TestGetCmdQueryCommunityPool() { - val := s.network.Validators[0] - - _, err := s.network.WaitForHeight(4) - s.Require().NoError(err) - - testCases := []struct { - name string - args []string - expectedOutput string - }{ - { - "json output", - []string{fmt.Sprintf("--%s=3", flags.FlagHeight), fmt.Sprintf("--%s=json", flags.FlagOutput)}, - `{"pool":[{"denom":"stake","amount":"4.740000000000000000"}]}`, - }, - { - "text output", - []string{fmt.Sprintf("--%s=text", flags.FlagOutput), fmt.Sprintf("--%s=3", flags.FlagHeight)}, - `pool: -- amount: "4.740000000000000000" - denom: stake`, - }, - } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.GetCmdQueryCommunityPool() - clientCtx := val.ClientCtx - - out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args) - s.Require().NoError(err) - s.Require().Equal(tc.expectedOutput, strings.TrimSpace(out.String())) - }) - } -} - func (s *E2ETestSuite) TestNewWithdrawRewardsCmd() { val := s.network.Validators[0] diff --git a/x/distribution/autocli.go b/x/distribution/autocli.go new file mode 100644 index 000000000000..8df238c8c203 --- /dev/null +++ b/x/distribution/autocli.go @@ -0,0 +1,105 @@ +package distribution + +import ( + "fmt" + "strings" + + autocliv1 "cosmossdk.io/api/cosmos/autocli/v1" + distirbuitonv1beta1 "cosmossdk.io/api/cosmos/distribution/v1beta1" + + "github.com/cosmos/cosmos-sdk/version" +) + +var ( + FlagCommission = "commission" + FlagMaxMessagesPerTx = "max-msgs" +) + +// AutoCLIOptions implements the autocli.HasAutoCLIConfig interface. +func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions { + exAccAddress, err := am.ac.BytesToString([]byte("A58856F0FD53BF058B4909A21AEC019107BA6A58856F0FD53BF058B4909A21AEC019107BA6")) + if err != nil { + panic(err) + } + + return &autocliv1.ModuleOptions{ + Query: &autocliv1.ServiceCommandDescriptor{ + Service: distirbuitonv1beta1.Query_ServiceDesc.ServiceName, + RpcCommandOptions: []*autocliv1.RpcCommandOptions{ + { + RpcMethod: "Params", + Use: "params", + Short: "Query the current distribution parameters.", + }, + { + RpcMethod: "ValidatorDistributionInfo", + Use: "validator-distribution-info [validator]", + Short: "Query validator distribution info", + Example: fmt.Sprintf(`Example: $ %s query distribution validator-distribution-info %s`, + version.AppName, exAccAddress, + ), + + PositionalArgs: []*autocliv1.PositionalArgDescriptor{ + {ProtoField: "validator_address"}, + }, + }, + { + RpcMethod: "ValidatorOutstandingRewards", + Use: "validator-outstanding-rewards [validator]", + Short: "Query distribution outstanding (un-withdrawn) rewards for a validator and all their delegations", + Example: fmt.Sprintf(`$ %s query distribution validator-outstanding-rewards [validator-address]`, version.AppName), + PositionalArgs: []*autocliv1.PositionalArgDescriptor{ + {ProtoField: "validator_address"}, + }, + }, + { + RpcMethod: "ValidatorCommission", + Use: "commission [validator]", + Short: "Query distribution validator commission", + Example: fmt.Sprintf(`$ %s query distribution commission [validator-address]`, version.AppName), + PositionalArgs: []*autocliv1.PositionalArgDescriptor{ + {ProtoField: "validator_address"}, + }, + }, + { + RpcMethod: "ValidatorSlashes", + Use: "slashes [validator] [start-height] [end-height]", + Short: "Query distribution validator slashes", + Example: fmt.Sprintf(`$ %s query distribution slashes [validator-address] 0 100`, version.AppName), + PositionalArgs: []*autocliv1.PositionalArgDescriptor{ + {ProtoField: "validator_address"}, + {ProtoField: "starting_height"}, + {ProtoField: "ending_height"}, + }, + }, + { + RpcMethod: "DelegationRewards", + Use: "rewards [delegator-addr] [validator-addr]", + Short: "Query all distribution delegator rewards or rewards from a particular validator", + Long: "Query all rewards earned by a delegator, optionally restrict to rewards from a single validator.", + Example: strings.TrimSpace( + fmt.Sprintf(` +$ %s query distribution rewards %s +$ %s query distribution rewards %s [validator-address] +`, + version.AppName, exAccAddress, version.AppName, exAccAddress, + ), + ), + PositionalArgs: []*autocliv1.PositionalArgDescriptor{ + {ProtoField: "delegator_address"}, + {ProtoField: "validator_address"}, + }, + }, + { + RpcMethod: "CommunityPool", + Use: "community-pool", + Short: "Query the amount of coins in the community pool", + Example: fmt.Sprintf(`$ %s query distribution community-pool`, version.AppName), + }, + }, + }, + Tx: &autocliv1.ServiceCommandDescriptor{ + Service: distirbuitonv1beta1.Msg_ServiceDesc.ServiceName, + }, + } +} diff --git a/x/distribution/client/cli/query.go b/x/distribution/client/cli/query.go deleted file mode 100644 index 5999fee397cd..000000000000 --- a/x/distribution/client/cli/query.go +++ /dev/null @@ -1,367 +0,0 @@ -package cli - -import ( - "fmt" - "strconv" - "strings" - - "cosmossdk.io/core/address" - "github.com/spf13/cobra" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/client/flags" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/version" - "github.com/cosmos/cosmos-sdk/x/distribution/types" -) - -// GetQueryCmd returns the cli query commands for this module -func GetQueryCmd(ac address.Codec) *cobra.Command { - distQueryCmd := &cobra.Command{ - Use: types.ModuleName, - Short: "Querying commands for the distribution module", - DisableFlagParsing: true, - SuggestionsMinimumDistance: 2, - RunE: client.ValidateCmd, - } - - distQueryCmd.AddCommand( - GetCmdQueryParams(), - GetCmdQueryValidatorDistributionInfo(), - GetCmdQueryValidatorOutstandingRewards(), - GetCmdQueryValidatorCommission(), - GetCmdQueryValidatorSlashes(), - GetCmdQueryDelegatorRewards(ac), - GetCmdQueryCommunityPool(), - ) - - return distQueryCmd -} - -// GetCmdQueryParams implements the query params command. -func GetCmdQueryParams() *cobra.Command { - cmd := &cobra.Command{ - Use: "params", - Args: cobra.NoArgs, - Short: "Query distribution params", - RunE: func(cmd *cobra.Command, _ []string) error { - clientCtx, err := client.GetClientQueryContext(cmd) - if err != nil { - return err - } - queryClient := types.NewQueryClient(clientCtx) - - res, err := queryClient.Params(cmd.Context(), &types.QueryParamsRequest{}) - if err != nil { - return err - } - - return clientCtx.PrintProto(&res.Params) - }, - } - - flags.AddQueryFlagsToCmd(cmd) - return cmd -} - -// GetCmdQueryValidatorDistributionInfo implements the query validator distribution info command. -func GetCmdQueryValidatorDistributionInfo() *cobra.Command { - bech32PrefixValAddr := sdk.GetConfig().GetBech32ValidatorAddrPrefix() - - cmd := &cobra.Command{ - Use: "validator-distribution-info [validator]", - Args: cobra.ExactArgs(1), - Short: "Query validator distribution info", - Long: strings.TrimSpace( - fmt.Sprintf(`Query validator distribution info. -Example: -$ %s query distribution validator-distribution-info %s1lwjmdnks33xwnmfayc64ycprww49n33mtm92ne -`, - version.AppName, bech32PrefixValAddr, - ), - ), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientQueryContext(cmd) - if err != nil { - return err - } - - validatorAddr, err := sdk.ValAddressFromBech32(args[0]) - if err != nil { - return err - } - - queryClient := types.NewQueryClient(clientCtx) - - res, err := queryClient.ValidatorDistributionInfo(cmd.Context(), &types.QueryValidatorDistributionInfoRequest{ - ValidatorAddress: validatorAddr.String(), - }) - if err != nil { - return err - } - - return clientCtx.PrintProto(res) - }, - } - - flags.AddQueryFlagsToCmd(cmd) - return cmd -} - -// GetCmdQueryValidatorOutstandingRewards implements the query validator -// outstanding rewards command. -func GetCmdQueryValidatorOutstandingRewards() *cobra.Command { - bech32PrefixValAddr := sdk.GetConfig().GetBech32ValidatorAddrPrefix() - - cmd := &cobra.Command{ - Use: "validator-outstanding-rewards [validator]", - Args: cobra.ExactArgs(1), - Short: "Query distribution outstanding (un-withdrawn) rewards for a validator and all their delegations", - Long: strings.TrimSpace( - fmt.Sprintf(`Query distribution outstanding (un-withdrawn) rewards for a validator and all their delegations. - -Example: -$ %s query distribution validator-outstanding-rewards %s1lwjmdnks33xwnmfayc64ycprww49n33mtm92ne -`, - version.AppName, bech32PrefixValAddr, - ), - ), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientQueryContext(cmd) - if err != nil { - return err - } - queryClient := types.NewQueryClient(clientCtx) - - validatorAddr, err := sdk.ValAddressFromBech32(args[0]) - if err != nil { - return err - } - - res, err := queryClient.ValidatorOutstandingRewards( - cmd.Context(), - &types.QueryValidatorOutstandingRewardsRequest{ValidatorAddress: validatorAddr.String()}, - ) - if err != nil { - return err - } - - return clientCtx.PrintProto(&res.Rewards) - }, - } - - flags.AddQueryFlagsToCmd(cmd) - return cmd -} - -// GetCmdQueryValidatorCommission implements the query validator commission command. -func GetCmdQueryValidatorCommission() *cobra.Command { - bech32PrefixValAddr := sdk.GetConfig().GetBech32ValidatorAddrPrefix() - - cmd := &cobra.Command{ - Use: "commission [validator]", - Args: cobra.ExactArgs(1), - Short: "Query distribution validator commission", - Long: strings.TrimSpace( - fmt.Sprintf(`Query validator commission rewards from delegators to that validator. - -Example: -$ %s query distribution commission %s1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj -`, - version.AppName, bech32PrefixValAddr, - ), - ), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientQueryContext(cmd) - if err != nil { - return err - } - queryClient := types.NewQueryClient(clientCtx) - - validatorAddr, err := sdk.ValAddressFromBech32(args[0]) - if err != nil { - return err - } - - res, err := queryClient.ValidatorCommission( - cmd.Context(), - &types.QueryValidatorCommissionRequest{ValidatorAddress: validatorAddr.String()}, - ) - if err != nil { - return err - } - - return clientCtx.PrintProto(&res.Commission) - }, - } - - flags.AddQueryFlagsToCmd(cmd) - return cmd -} - -// GetCmdQueryValidatorSlashes implements the query validator slashes command. -func GetCmdQueryValidatorSlashes() *cobra.Command { - bech32PrefixValAddr := sdk.GetConfig().GetBech32ValidatorAddrPrefix() - - cmd := &cobra.Command{ - Use: "slashes [validator] [start-height] [end-height]", - Args: cobra.ExactArgs(3), - Short: "Query distribution validator slashes", - Long: strings.TrimSpace( - fmt.Sprintf(`Query all slashes of a validator for a given block range. - -Example: -$ %s query distribution slashes %svaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj 0 100 -`, - version.AppName, bech32PrefixValAddr, - ), - ), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientQueryContext(cmd) - if err != nil { - return err - } - queryClient := types.NewQueryClient(clientCtx) - - validatorAddr, err := sdk.ValAddressFromBech32(args[0]) - if err != nil { - return err - } - - startHeight, err := strconv.ParseUint(args[1], 10, 64) - if err != nil { - return fmt.Errorf("start-height %s not a valid uint, please input a valid start-height", args[1]) - } - - endHeight, err := strconv.ParseUint(args[2], 10, 64) - if err != nil { - return fmt.Errorf("end-height %s not a valid uint, please input a valid end-height", args[2]) - } - - pageReq, err := client.ReadPageRequest(cmd.Flags()) - if err != nil { - return err - } - - res, err := queryClient.ValidatorSlashes( - cmd.Context(), - &types.QueryValidatorSlashesRequest{ - ValidatorAddress: validatorAddr.String(), - StartingHeight: startHeight, - EndingHeight: endHeight, - Pagination: pageReq, - }, - ) - if err != nil { - return err - } - - return clientCtx.PrintProto(res) - }, - } - - flags.AddQueryFlagsToCmd(cmd) - flags.AddPaginationFlagsToCmd(cmd, "validator slashes") - return cmd -} - -// GetCmdQueryDelegatorRewards implements the query delegator rewards command. -func GetCmdQueryDelegatorRewards(ac address.Codec) *cobra.Command { - bech32PrefixAccAddr := sdk.GetConfig().GetBech32AccountAddrPrefix() - bech32PrefixValAddr := sdk.GetConfig().GetBech32ValidatorAddrPrefix() - - cmd := &cobra.Command{ - Use: "rewards [delegator-addr] [validator-addr]", - Args: cobra.RangeArgs(1, 2), - Short: "Query all distribution delegator rewards or rewards from a particular validator", - Long: strings.TrimSpace( - fmt.Sprintf(`Query all rewards earned by a delegator, optionally restrict to rewards from a single validator. - -Example: -$ %s query distribution rewards %s1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p -$ %s query distribution rewards %s1gghjut3ccd8ay0zduzj64hwre2fxs9ld75ru9p %s1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj -`, - version.AppName, bech32PrefixAccAddr, version.AppName, bech32PrefixAccAddr, bech32PrefixValAddr, - ), - ), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientQueryContext(cmd) - if err != nil { - return err - } - queryClient := types.NewQueryClient(clientCtx) - - _, err = ac.StringToBytes(args[0]) - if err != nil { - return err - } - - // query for rewards from a particular delegation - ctx := cmd.Context() - if len(args) == 2 { - validatorAddr, err := sdk.ValAddressFromBech32(args[1]) - if err != nil { - return err - } - - res, err := queryClient.DelegationRewards( - ctx, - &types.QueryDelegationRewardsRequest{DelegatorAddress: args[0], ValidatorAddress: validatorAddr.String()}, - ) - if err != nil { - return err - } - - return clientCtx.PrintProto(res) - } - - res, err := queryClient.DelegationTotalRewards( - ctx, - &types.QueryDelegationTotalRewardsRequest{DelegatorAddress: args[0]}, - ) - if err != nil { - return err - } - - return clientCtx.PrintProto(res) - }, - } - - flags.AddQueryFlagsToCmd(cmd) - return cmd -} - -// GetCmdQueryCommunityPool returns the command for fetching community pool info. -func GetCmdQueryCommunityPool() *cobra.Command { - cmd := &cobra.Command{ - Use: "community-pool", - Args: cobra.NoArgs, - Short: "Query the amount of coins in the community pool", - Long: strings.TrimSpace( - fmt.Sprintf(`Query all coins in the community pool which is under Governance control. - -Example: -$ %s query distribution community-pool -`, - version.AppName, - ), - ), - RunE: func(cmd *cobra.Command, args []string) error { - clientCtx, err := client.GetClientQueryContext(cmd) - if err != nil { - return err - } - queryClient := types.NewQueryClient(clientCtx) - - res, err := queryClient.CommunityPool(cmd.Context(), &types.QueryCommunityPoolRequest{}) - if err != nil { - return err - } - - return clientCtx.PrintProto(res) - }, - } - - flags.AddQueryFlagsToCmd(cmd) - return cmd -} diff --git a/x/distribution/client/cli/query_test.go b/x/distribution/client/cli/query_test.go deleted file mode 100644 index 19f62c44bb56..000000000000 --- a/x/distribution/client/cli/query_test.go +++ /dev/null @@ -1,464 +0,0 @@ -package cli_test - -import ( - "fmt" - "io" - "strings" - "testing" - - abci "github.com/cometbft/cometbft/abci/types" - rpcclientmock "github.com/cometbft/cometbft/rpc/client/mock" - "github.com/stretchr/testify/suite" - - "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" - "github.com/cosmos/cosmos-sdk/testutil" - clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli" - "github.com/cosmos/cosmos-sdk/testutil/network" - 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/distribution/client/cli" - distrtestutil "github.com/cosmos/cosmos-sdk/x/distribution/testutil" - "github.com/cosmos/cosmos-sdk/x/gov" - minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" -) - -type CLITestSuite struct { - suite.Suite - - kr keyring.Keyring - encCfg testutilmod.TestEncodingConfig - baseCtx client.Context - clientCtx client.Context -} - -func TestCLITestSuite(t *testing.T) { - suite.Run(t, new(CLITestSuite)) -} - -func (s *CLITestSuite) SetupSuite() { - s.encCfg = testutilmod.MakeTestEncodingConfig(gov.AppModuleBasic{}, 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). - WithChainID("test-chain") - - ctxGen := func() client.Context { - bz, _ := s.encCfg.Codec.Marshal(&sdk.TxResponse{}) - c := clitestutil.NewMockCometRPC(abci.ResponseQuery{ - Value: bz, - }) - return s.baseCtx.WithClient(c) - } - s.clientCtx = ctxGen() - - cfg, err := network.DefaultConfigWithAppConfig(distrtestutil.AppConfig) - s.Require().NoError(err) - - genesisState := cfg.GenesisState - var mintData minttypes.GenesisState - s.Require().NoError(cfg.Codec.UnmarshalJSON(genesisState[minttypes.ModuleName], &mintData)) - - inflation := sdk.MustNewDecFromStr("1.0") - mintData.Minter.Inflation = inflation - mintData.Params.InflationMin = inflation - mintData.Params.InflationMax = inflation - - mintDataBz, err := cfg.Codec.MarshalJSON(&mintData) - s.Require().NoError(err) - genesisState[minttypes.ModuleName] = mintDataBz - cfg.GenesisState = genesisState -} - -func (s *CLITestSuite) TestGetCmdQueryParams() { - testCases := []struct { - name string - args []string - expectedOutput string - }{ - { - "json output", - []string{fmt.Sprintf("--%s=json", flags.FlagOutput)}, - `{"community_tax":"0","base_proposer_reward":"0","bonus_proposer_reward":"0","withdraw_addr_enabled":false}`, - }, - { - "text output", - []string{fmt.Sprintf("--%s=text", flags.FlagOutput)}, - `base_proposer_reward: "0" -bonus_proposer_reward: "0" -community_tax: "0" -withdraw_addr_enabled: false`, - }, - } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.GetCmdQueryParams() - - out, err := clitestutil.ExecTestCLICmd(s.clientCtx, cmd, tc.args) - s.Require().NoError(err) - s.Require().Equal(tc.expectedOutput, strings.TrimSpace(out.String())) - }) - } -} - -func (s *CLITestSuite) TestGetCmdQueryValidatorDistributionInfo() { - addr := testutil.CreateKeyringAccounts(s.T(), s.kr, 1) - val := sdk.ValAddress(addr[0].Address.String()) - - testCases := []struct { - name string - args []string - expErr bool - }{ - { - "invalid val address", - []string{"invalid address", fmt.Sprintf("--%s=json", flags.FlagOutput)}, - true, - }, - { - "json output", - []string{val.String(), fmt.Sprintf("--%s=json", flags.FlagOutput)}, - false, - }, - { - "text output", - []string{val.String(), fmt.Sprintf("--%s=text", flags.FlagOutput)}, - false, - }, - } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.GetCmdQueryValidatorDistributionInfo() - - _, err := clitestutil.ExecTestCLICmd(s.clientCtx, cmd, tc.args) - if tc.expErr { - s.Require().Error(err) - } else { - s.Require().NoError(err) - } - }) - } -} - -func (s *CLITestSuite) TestGetCmdQueryValidatorOutstandingRewards() { - val := testutil.CreateKeyringAccounts(s.T(), s.kr, 1) - - testCases := []struct { - name string - args []string - expectErr bool - expectedOutput string - }{ - { - "invalid validator address", - []string{ - fmt.Sprintf("--%s=3", flags.FlagHeight), - "foo", - }, - true, - "", - }, - { - "json output", - []string{ - fmt.Sprintf("--%s=3", flags.FlagHeight), - sdk.ValAddress(val[0].Address).String(), - fmt.Sprintf("--%s=json", flags.FlagOutput), - }, - false, - `{"rewards":[]}`, - }, - { - "text output", - []string{ - fmt.Sprintf("--%s=text", flags.FlagOutput), - fmt.Sprintf("--%s=3", flags.FlagHeight), - sdk.ValAddress(val[0].Address).String(), - }, - false, - `rewards: []`, - }, - } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.GetCmdQueryValidatorOutstandingRewards() - - out, err := clitestutil.ExecTestCLICmd(s.clientCtx, cmd, tc.args) - if tc.expectErr { - s.Require().Error(err) - } else { - s.Require().NoError(err) - s.Require().Equal(tc.expectedOutput, strings.TrimSpace(out.String())) - } - }) - } -} - -func (s *CLITestSuite) TestGetCmdQueryValidatorCommission() { - val := testutil.CreateKeyringAccounts(s.T(), s.kr, 1) - - testCases := []struct { - name string - args []string - expectErr bool - expectedOutput string - }{ - { - "invalid validator address", - []string{ - fmt.Sprintf("--%s=3", flags.FlagHeight), - "foo", - }, - true, - "", - }, - { - "json output", - []string{ - fmt.Sprintf("--%s=3", flags.FlagHeight), - sdk.ValAddress(val[0].Address).String(), - fmt.Sprintf("--%s=json", flags.FlagOutput), - }, - false, - `{"commission":[]}`, - }, - { - "text output", - []string{ - fmt.Sprintf("--%s=text", flags.FlagOutput), - fmt.Sprintf("--%s=3", flags.FlagHeight), - sdk.ValAddress(val[0].Address).String(), - }, - false, - `commission: []`, - }, - } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.GetCmdQueryValidatorCommission() - - out, err := clitestutil.ExecTestCLICmd(s.clientCtx, cmd, tc.args) - if tc.expectErr { - s.Require().Error(err) - } else { - s.Require().NoError(err) - s.Require().Equal(tc.expectedOutput, strings.TrimSpace(out.String())) - } - }) - } -} - -func (s *CLITestSuite) TestGetCmdQueryValidatorSlashes() { - val := testutil.CreateKeyringAccounts(s.T(), s.kr, 1) - - testCases := []struct { - name string - args []string - expectErr bool - expectedOutput string - }{ - { - "invalid validator address", - []string{ - fmt.Sprintf("--%s=3", flags.FlagHeight), - "foo", "1", "3", - }, - true, - "", - }, - { - "invalid start height", - []string{ - fmt.Sprintf("--%s=3", flags.FlagHeight), - sdk.ValAddress(val[0].Address).String(), "-1", "3", - }, - true, - "", - }, - { - "invalid end height", - []string{ - fmt.Sprintf("--%s=3", flags.FlagHeight), - sdk.ValAddress(val[0].Address).String(), "1", "-3", - }, - true, - "", - }, - { - "json output", - []string{ - fmt.Sprintf("--%s=3", flags.FlagHeight), - sdk.ValAddress(val[0].Address).String(), "1", "3", - fmt.Sprintf("--%s=json", flags.FlagOutput), - }, - false, - "{\"slashes\":[],\"pagination\":null}", - }, - { - "text output", - []string{ - fmt.Sprintf("--%s=text", flags.FlagOutput), - fmt.Sprintf("--%s=3", flags.FlagHeight), - sdk.ValAddress(val[0].Address).String(), "1", "3", - }, - false, - "pagination: null\nslashes: []", - }, - } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.GetCmdQueryValidatorSlashes() - - out, err := clitestutil.ExecTestCLICmd(s.clientCtx, cmd, tc.args) - if tc.expectErr { - s.Require().Error(err) - } else { - s.Require().NoError(err) - s.Require().Equal(tc.expectedOutput, strings.TrimSpace(out.String())) - } - }) - } -} - -func (s *CLITestSuite) TestGetCmdQueryDelegatorRewards() { - val := testutil.CreateKeyringAccounts(s.T(), s.kr, 1) - addr := val[0].Address - valAddr := sdk.ValAddress(addr) - - testCases := []struct { - name string - args []string - expectErr bool - expectedOutput string - }{ - { - "invalid delegator address", - []string{ - fmt.Sprintf("--%s=5", flags.FlagHeight), - "foo", valAddr.String(), - }, - true, - "", - }, - { - "invalid validator address", - []string{ - fmt.Sprintf("--%s=5", flags.FlagHeight), - addr.String(), "foo", - }, - true, - "", - }, - { - "json output", - []string{ - fmt.Sprintf("--%s=5", flags.FlagHeight), - addr.String(), - fmt.Sprintf("--%s=json", flags.FlagOutput), - }, - false, - `{"rewards":[],"total":[]}`, - }, - { - "json output (specific validator)", - []string{ - fmt.Sprintf("--%s=5", flags.FlagHeight), - addr.String(), valAddr.String(), - fmt.Sprintf("--%s=json", flags.FlagOutput), - }, - false, - `{"rewards":[]}`, - }, - { - "text output", - []string{ - fmt.Sprintf("--%s=text", flags.FlagOutput), - fmt.Sprintf("--%s=5", flags.FlagHeight), - addr.String(), - }, - false, - `rewards: [] -total: []`, - }, - { - "text output (specific validator)", - []string{ - fmt.Sprintf("--%s=text", flags.FlagOutput), - fmt.Sprintf("--%s=5", flags.FlagHeight), - addr.String(), valAddr.String(), - }, - false, - `rewards: []`, - }, - } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.GetCmdQueryDelegatorRewards(address.NewBech32Codec("cosmos")) - - out, err := clitestutil.ExecTestCLICmd(s.clientCtx, cmd, tc.args) - if tc.expectErr { - s.Require().Error(err) - } else { - s.Require().NoError(err) - s.Require().Equal(tc.expectedOutput, strings.TrimSpace(out.String())) - } - }) - } -} - -func (s *CLITestSuite) TestGetCmdQueryCommunityPool() { - testCases := []struct { - name string - args []string - expectedOutput string - }{ - { - "json output", - []string{fmt.Sprintf("--%s=3", flags.FlagHeight), fmt.Sprintf("--%s=json", flags.FlagOutput)}, - `{"pool":[]}`, - }, - { - "text output", - []string{fmt.Sprintf("--%s=text", flags.FlagOutput), fmt.Sprintf("--%s=3", flags.FlagHeight)}, - `pool: []`, - }, - } - - for _, tc := range testCases { - tc := tc - - s.Run(tc.name, func() { - cmd := cli.GetCmdQueryCommunityPool() - - out, err := clitestutil.ExecTestCLICmd(s.clientCtx, cmd, tc.args) - s.Require().NoError(err) - s.Require().Equal(tc.expectedOutput, strings.TrimSpace(out.String())) - }) - } -} diff --git a/x/distribution/client/cli/tx_test.go b/x/distribution/client/cli/tx_test.go index 3522faa9b43b..6ee154fca7e5 100644 --- a/x/distribution/client/cli/tx_test.go +++ b/x/distribution/client/cli/tx_test.go @@ -3,20 +3,84 @@ package cli_test import ( "context" "fmt" + "io" + "testing" sdkmath "cosmossdk.io/math" + abci "github.com/cometbft/cometbft/abci/types" + rpcclientmock "github.com/cometbft/cometbft/rpc/client/mock" "github.com/cosmos/gogoproto/proto" + "github.com/stretchr/testify/suite" "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" + "github.com/cosmos/cosmos-sdk/testutil/network" 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/distribution/client/cli" + distrtestutil "github.com/cosmos/cosmos-sdk/x/distribution/testutil" + "github.com/cosmos/cosmos-sdk/x/gov" + minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" ) +type CLITestSuite struct { + suite.Suite + + kr keyring.Keyring + encCfg testutilmod.TestEncodingConfig + baseCtx client.Context + clientCtx client.Context +} + +func TestCLITestSuite(t *testing.T) { + suite.Run(t, new(CLITestSuite)) +} + +func (s *CLITestSuite) SetupSuite() { + s.encCfg = testutilmod.MakeTestEncodingConfig(gov.AppModuleBasic{}, 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). + WithChainID("test-chain") + + ctxGen := func() client.Context { + bz, _ := s.encCfg.Codec.Marshal(&sdk.TxResponse{}) + c := clitestutil.NewMockCometRPC(abci.ResponseQuery{ + Value: bz, + }) + return s.baseCtx.WithClient(c) + } + s.clientCtx = ctxGen() + + cfg, err := network.DefaultConfigWithAppConfig(distrtestutil.AppConfig) + s.Require().NoError(err) + + genesisState := cfg.GenesisState + var mintData minttypes.GenesisState + s.Require().NoError(cfg.Codec.UnmarshalJSON(genesisState[minttypes.ModuleName], &mintData)) + + inflation := sdk.MustNewDecFromStr("1.0") + mintData.Minter.Inflation = inflation + mintData.Params.InflationMin = inflation + mintData.Params.InflationMax = inflation + + mintDataBz, err := cfg.Codec.MarshalJSON(&mintData) + s.Require().NoError(err) + genesisState[minttypes.ModuleName] = mintDataBz + cfg.GenesisState = genesisState +} + func (s *CLITestSuite) TestTxWithdrawRewardsCmd() { val := testutil.CreateKeyringAccounts(s.T(), s.kr, 1) diff --git a/x/distribution/module.go b/x/distribution/module.go index 2680181edd75..5d15832852b3 100644 --- a/x/distribution/module.go +++ b/x/distribution/module.go @@ -10,9 +10,10 @@ import ( "github.com/spf13/cobra" modulev1 "cosmossdk.io/api/cosmos/distribution/module/v1" + "cosmossdk.io/depinject" + "cosmossdk.io/core/address" "cosmossdk.io/core/appmodule" - "cosmossdk.io/depinject" "cosmossdk.io/core/store" @@ -63,7 +64,7 @@ func (AppModuleBasic) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage { } // ValidateGenesis performs genesis state validation for the distribution module. -func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, config sdkclient.TxEncodingConfig, bz json.RawMessage) error { +func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, _ sdkclient.TxEncodingConfig, bz json.RawMessage) error { var data types.GenesisState if err := cdc.UnmarshalJSON(bz, &data); err != nil { return fmt.Errorf("failed to unmarshal %s genesis state: %w", types.ModuleName, err) @@ -86,7 +87,7 @@ func (ab AppModuleBasic) GetTxCmd() *cobra.Command { // GetQueryCmd returns the root query command for the distribution module. func (ab AppModuleBasic) GetQueryCmd() *cobra.Command { - return cli.GetQueryCmd(ab.ac) + return nil } // RegisterInterfaces implements InterfaceModule @@ -191,7 +192,7 @@ func (AppModule) GenerateGenesisState(simState *module.SimulationState) { } // ProposalMsgs returns msgs used for governance proposals for simulations. -func (AppModule) ProposalMsgs(simState module.SimulationState) []simtypes.WeightedProposalMsg { +func (AppModule) ProposalMsgs(_ module.SimulationState) []simtypes.WeightedProposalMsg { return simulation.ProposalMsgs() }