Skip to content

Commit

Permalink
feat(auth): autocli query support (backport #16650) (#16900)
Browse files Browse the repository at this point in the history
Co-authored-by: Julien Robert <julien@rbrt.fr>
  • Loading branch information
mergify[bot] and julienrbrt committed Jul 10, 2023
1 parent 8295e4a commit 3fee9db
Show file tree
Hide file tree
Showing 8 changed files with 57 additions and 486 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ 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.
* (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.

Expand Down
203 changes: 1 addition & 202 deletions tests/e2e/auth/suite.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ import (
authcli "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
authclitestutil "github.com/cosmos/cosmos-sdk/x/auth/client/testutil"
authtestutil "github.com/cosmos/cosmos-sdk/x/auth/testutil"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
bank "github.com/cosmos/cosmos-sdk/x/bank/client/cli"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/cosmos/cosmos-sdk/x/genutil/client/cli"
Expand Down Expand Up @@ -289,50 +288,6 @@ func (s *E2ETestSuite) TestCLISignBatch() {
s.Require().Equal(sigs[0].Sequence, seq1)
}

func (s *E2ETestSuite) TestCliGetAccountAddressByID() {
require := s.Require()
val1 := s.network.Validators[0]
testCases := []struct {
name string
args []string
expectErr bool
}{
{
"not enough args",
[]string{fmt.Sprintf("--%s=json", flags.FlagOutput)},
true,
},
{
"invalid account id",
[]string{fmt.Sprint(-1), fmt.Sprintf("--%s=json", flags.FlagOutput)},
true,
},
{
"valid account id",
[]string{fmt.Sprint(0), fmt.Sprintf("--%s=json", flags.FlagOutput)},
false,
},
}

for _, tc := range testCases {
tc := tc
s.Run(tc.name, func() {
cmd := authcli.GetAccountAddressByIDCmd()
clientCtx := val1.ClientCtx

queryResJSON, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
if tc.expectErr {
s.Require().Error(err)
} else {
s.Require().NoError(err)
var res authtypes.QueryAccountAddressByIDResponse
require.NoError(val1.ClientCtx.Codec.UnmarshalJSON(queryResJSON.Bytes(), &res))
require.NotNil(res.GetAccountAddress())
}
})
}
}

func (s *E2ETestSuite) TestCLIQueryTxCmdByHash() {
val := s.network.Validators[0]

Expand Down Expand Up @@ -1228,10 +1183,8 @@ func (s *E2ETestSuite) TestMultisignBatch() {
defer filename.Close()
val.ClientCtx.HomeDir = strings.Replace(val.ClientCtx.HomeDir, "simd", "simcli", 1)

queryResJSON, err := authclitestutil.QueryAccountExec(val.ClientCtx, addr, addresscodec.NewBech32Codec("cosmos"))
account, err := val.ClientCtx.AccountRetriever.GetAccount(val.ClientCtx, addr)
s.Require().NoError(err)
var account sdk.AccountI
s.Require().NoError(val.ClientCtx.Codec.UnmarshalInterfaceJSON(queryResJSON.Bytes(), &account))

// sign-batch file
addr1, err := account1.GetAddress()
Expand Down Expand Up @@ -1270,121 +1223,6 @@ func (s *E2ETestSuite) TestMultisignBatch() {
}
}

func (s *E2ETestSuite) TestGetAccountCmd() {
val := s.network.Validators[0]
_, _, addr1 := testdata.KeyTestPubAddr()

testCases := []struct {
name string
address sdk.AccAddress
expectErr bool
}{
{
"invalid address",
addr1,
true,
},
{
"valid address",
val.Address,
false,
},
}

for _, tc := range testCases {
tc := tc
s.Run(tc.name, func() {
clientCtx := val.ClientCtx

out, err := authclitestutil.QueryAccountExec(clientCtx, tc.address, addresscodec.NewBech32Codec("cosmos"))
if tc.expectErr {
s.Require().Error(err)
s.Require().NotEqual("internal", err.Error())
} else {
var acc sdk.AccountI
s.Require().NoError(val.ClientCtx.Codec.UnmarshalInterfaceJSON(out.Bytes(), &acc))
s.Require().Equal(val.Address, acc.GetAddress())
}
})
}
}

func (s *E2ETestSuite) TestGetAccountsCmd() {
val := s.network.Validators[0]
clientCtx := val.ClientCtx

out, err := clitestutil.ExecTestCLICmd(clientCtx, authcli.GetAccountsCmd(), []string{
fmt.Sprintf("--%s=json", flags.FlagOutput),
})
s.Require().NoError(err)

var res authtypes.QueryAccountsResponse
s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &res))
s.Require().NotEmpty(res.Accounts)
}

func (s *E2ETestSuite) TestQueryModuleAccountByNameCmd() {
val := s.network.Validators[0]

testCases := []struct {
name string
moduleName string
expectErr bool
}{
{
"invalid module name",
"gover",
true,
},
{
"valid module name",
"mint",
false,
},
}

for _, tc := range testCases {
tc := tc
s.Run(tc.name, func() {
clientCtx := val.ClientCtx

out, err := clitestutil.ExecTestCLICmd(clientCtx, authcli.QueryModuleAccountByNameCmd(), []string{
tc.moduleName,
fmt.Sprintf("--%s=json", flags.FlagOutput),
})
if tc.expectErr {
s.Require().Error(err)
s.Require().NotEqual("internal", err.Error())
} else {
var res authtypes.QueryModuleAccountByNameResponse
s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &res))

var account sdk.AccountI
err := val.ClientCtx.InterfaceRegistry.UnpackAny(res.Account, &account)
s.Require().NoError(err)

moduleAccount, ok := account.(sdk.ModuleAccountI)
s.Require().True(ok)
s.Require().Equal(tc.moduleName, moduleAccount.GetName())
}
})
}
}

func (s *E2ETestSuite) TestQueryModuleAccountsCmd() {
val := s.network.Validators[0]
clientCtx := val.ClientCtx

out, err := clitestutil.ExecTestCLICmd(clientCtx, authcli.QueryModuleAccountsCmd(), []string{
fmt.Sprintf("--%s=json", flags.FlagOutput),
})
s.Require().NoError(err)

var res authtypes.QueryModuleAccountsResponse
s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &res))
s.Require().NotEmpty(res.Accounts)
}

func TestGetBroadcastCommandOfflineFlag(t *testing.T) {
cmd := authcli.GetBroadcastCommand()
_ = testutil.ApplyMockIODiscardOutErr(cmd)
Expand Down Expand Up @@ -1427,45 +1265,6 @@ func TestGetBroadcastCommandWithoutOfflineFlag(t *testing.T) {
require.Contains(t, out.String(), "connect: connection refused")
}

func (s *E2ETestSuite) TestQueryParamsCmd() {
val := s.network.Validators[0]

testCases := []struct {
name string
args []string
expectErr bool
}{
{
"happy case",
[]string{fmt.Sprintf("--%s=json", flags.FlagOutput)},
false,
},
{
"with specific height",
[]string{fmt.Sprintf("--%s=1", flags.FlagHeight), fmt.Sprintf("--%s=json", flags.FlagOutput)},
false,
},
}

for _, tc := range testCases {
tc := tc
s.Run(tc.name, func() {
cmd := authcli.QueryParamsCmd()
clientCtx := val.ClientCtx

out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
if tc.expectErr {
s.Require().Error(err)
s.Require().NotEqual("internal", err.Error())
} else {
var authParams authtypes.Params
s.Require().NoError(val.ClientCtx.Codec.UnmarshalJSON(out.Bytes(), &authParams))
s.Require().NotNil(authParams.MaxMemoCharacters)
}
})
}
}

// TestTxWithoutPublicKey makes sure sending a proto tx message without the
// public key doesn't cause any error in the RPC layer (broadcast).
// See https://github.com/cosmos/cosmos-sdk/issues/7585 for more details.
Expand Down
38 changes: 0 additions & 38 deletions tests/integration/auth/client/cli/suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ import (
"github.com/cosmos/cosmos-sdk/x/auth"
authcli "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
authtestutil "github.com/cosmos/cosmos-sdk/x/auth/client/testutil"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/cosmos/cosmos-sdk/x/bank"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/cosmos/cosmos-sdk/x/genutil/client/cli"
Expand Down Expand Up @@ -818,43 +817,6 @@ func (s *CLITestSuite) TestGetBroadcastCommandWithoutOfflineFlag() {
s.Require().Contains(out.String(), "connect: connection refused")
}

func (s *CLITestSuite) TestQueryParamsCmd() {
testCases := []struct {
name string
args []string
expectErr bool
}{
{
"happy case",
[]string{fmt.Sprintf("--%s=json", flags.FlagOutput)},
false,
},
{
"with specific height",
[]string{fmt.Sprintf("--%s=1", flags.FlagHeight), fmt.Sprintf("--%s=json", flags.FlagOutput)},
false,
},
}

for _, tc := range testCases {
tc := tc
s.Run(tc.name, func() {
cmd := authcli.QueryParamsCmd()
clientCtx := s.clientCtx

out, err := clitestutil.ExecTestCLICmd(clientCtx, cmd, tc.args)
if tc.expectErr {
s.Require().Error(err)
s.Require().NotEqual("internal", err.Error())
} else {
var authParams authtypes.Params
s.Require().NoError(s.clientCtx.Codec.UnmarshalJSON(out.Bytes(), &authParams))
s.Require().NotNil(authParams.MaxMemoCharacters)
}
})
}
}

// TestTxWithoutPublicKey makes sure sending a proto tx message without the
// public key doesn't cause any error in the RPC layer (broadcast).
// See https://github.com/cosmos/cosmos-sdk/issues/7585 for more details.
Expand Down
55 changes: 53 additions & 2 deletions x/auth/autocli.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
package auth

import (
"fmt"

authv1beta1 "cosmossdk.io/api/cosmos/auth/v1beta1"
autocliv1 "cosmossdk.io/api/cosmos/autocli/v1"
_ "cosmossdk.io/api/cosmos/crypto/secp256k1" // register to that it shows up in protoregistry.GlobalTypes
_ "cosmossdk.io/api/cosmos/crypto/secp256r1" // register to that it shows up in protoregistry.GlobalTypes

"github.com/cosmos/cosmos-sdk/version"
)

// AutoCLIOptions implements the autocli.HasAutoCLIConfig interface.
Expand All @@ -11,18 +17,63 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions {
Query: &autocliv1.ServiceCommandDescriptor{
Service: authv1beta1.Query_ServiceDesc.ServiceName,
RpcCommandOptions: []*autocliv1.RpcCommandOptions{
{
RpcMethod: "Accounts",
Use: "accounts",
Short: "Query all the accounts",
},
{
RpcMethod: "Account",
Use: "account [address]",
Short: "query account by address",
Short: "Query account by address",
PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "address"}},
},
{
RpcMethod: "AccountInfo",
Use: "account-info [address]",
Short: "Query account info which is common to all account types.",
PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "address"}},
},
{
RpcMethod: "AccountAddressByID",
Use: "address-by-acc-num [acc-num]",
Short: "query account address by account number",
Short: "Query account address by account number",
PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "id"}},
},
{
RpcMethod: "ModuleAccounts",
Use: "module-accounts",
Short: "Query all module accounts",
},
{
RpcMethod: "ModuleAccountByName",
Use: "module-account [module-name]",
Short: "Query module account info by module name",
Example: fmt.Sprintf("%s q auth module-account gov", version.AppName),
PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "name"}},
},
{
RpcMethod: "AddressBytesToString",
Use: "address-bytes-to-string [address-bytes]",
Short: "Transform an address bytes to string",
PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "address_bytes"}},
},
{
RpcMethod: "AddressStringToBytes",
Use: "address-string-to-bytes [address-string]",
Short: "Transform an address string to bytes",
PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "address_string"}},
},
{
RpcMethod: "Bech32Prefix",
Use: "bech32-prefix",
Short: "Query the chain bech32 prefix (if applicable)",
},
{
RpcMethod: "Params",
Use: "params",
Short: "Query the current auth parameters",
},
},
},
// Tx is purposely left empty, as the only tx is MsgUpdateParams which is gov gated.
Expand Down
Loading

0 comments on commit 3fee9db

Please sign in to comment.