feat(cli): add module-account cli cmd and grpc get api (#13612)

This commit is contained in:
Sai Kumar 2022-10-22 23:53:24 +05:30 committed by GitHub
parent e2792711ba
commit ddf5cf0d8d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 3219 additions and 1515 deletions

View File

@ -53,6 +53,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
* (x/bank) [#11981](https://github.com/cosmos/cosmos-sdk/pull/11981) Create the `SetSendEnabled` endpoint for managing the bank's SendEnabled settings.
* (x/auth) [#13210](https://github.com/cosmos/cosmos-sdk/pull/13210) Add `Query/AccountInfo` endpoint for simplified access to basic account info.
* (x/consensus) [#12905](https://github.com/cosmos/cosmos-sdk/pull/12905) Create a new `x/consensus` module that is now responsible for maintaining Tendermint consensus parameters instead of `x/param`. Legacy types remain in order to facilitate parameter migration from the deprecated `x/params`. App developers should ensure that they execute `baseapp.MigrateParams` during their chain upgrade. These legacy types will be removed in a future release.
* (x/auth) [#13612](https://github.com/cosmos/cosmos-sdk/pull/13612) Add `Query/ModuleAccountByName` endpoint for accessing the module account info by module name.
### Improvements

File diff suppressed because it is too large Load Diff

View File

@ -41,6 +41,8 @@ type QueryClient interface {
//
// Since: cosmos-sdk 0.46
ModuleAccounts(ctx context.Context, in *QueryModuleAccountsRequest, opts ...grpc.CallOption) (*QueryModuleAccountsResponse, error)
// ModuleAccountByName returns the module account info by module name
ModuleAccountByName(ctx context.Context, in *QueryModuleAccountByNameRequest, opts ...grpc.CallOption) (*QueryModuleAccountByNameResponse, error)
// Bech32Prefix queries bech32Prefix
//
// Since: cosmos-sdk 0.46
@ -112,6 +114,15 @@ func (c *queryClient) ModuleAccounts(ctx context.Context, in *QueryModuleAccount
return out, nil
}
func (c *queryClient) ModuleAccountByName(ctx context.Context, in *QueryModuleAccountByNameRequest, opts ...grpc.CallOption) (*QueryModuleAccountByNameResponse, error) {
out := new(QueryModuleAccountByNameResponse)
err := c.cc.Invoke(ctx, "/cosmos.auth.v1beta1.Query/ModuleAccountByName", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *queryClient) Bech32Prefix(ctx context.Context, in *Bech32PrefixRequest, opts ...grpc.CallOption) (*Bech32PrefixResponse, error) {
out := new(Bech32PrefixResponse)
err := c.cc.Invoke(ctx, "/cosmos.auth.v1beta1.Query/Bech32Prefix", in, out, opts...)
@ -171,6 +182,8 @@ type QueryServer interface {
//
// Since: cosmos-sdk 0.46
ModuleAccounts(context.Context, *QueryModuleAccountsRequest) (*QueryModuleAccountsResponse, error)
// ModuleAccountByName returns the module account info by module name
ModuleAccountByName(context.Context, *QueryModuleAccountByNameRequest) (*QueryModuleAccountByNameResponse, error)
// Bech32Prefix queries bech32Prefix
//
// Since: cosmos-sdk 0.46
@ -209,6 +222,9 @@ func (UnimplementedQueryServer) Params(context.Context, *QueryParamsRequest) (*Q
func (UnimplementedQueryServer) ModuleAccounts(context.Context, *QueryModuleAccountsRequest) (*QueryModuleAccountsResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method ModuleAccounts not implemented")
}
func (UnimplementedQueryServer) ModuleAccountByName(context.Context, *QueryModuleAccountByNameRequest) (*QueryModuleAccountByNameResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method ModuleAccountByName not implemented")
}
func (UnimplementedQueryServer) Bech32Prefix(context.Context, *Bech32PrefixRequest) (*Bech32PrefixResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Bech32Prefix not implemented")
}
@ -324,6 +340,24 @@ func _Query_ModuleAccounts_Handler(srv interface{}, ctx context.Context, dec fun
return interceptor(ctx, in, info, handler)
}
func _Query_ModuleAccountByName_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(QueryModuleAccountByNameRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(QueryServer).ModuleAccountByName(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/cosmos.auth.v1beta1.Query/ModuleAccountByName",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(QueryServer).ModuleAccountByName(ctx, req.(*QueryModuleAccountByNameRequest))
}
return interceptor(ctx, in, info, handler)
}
func _Query_Bech32Prefix_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(Bech32PrefixRequest)
if err := dec(in); err != nil {
@ -423,6 +457,10 @@ var Query_ServiceDesc = grpc.ServiceDesc{
MethodName: "ModuleAccounts",
Handler: _Query_ModuleAccounts_Handler,
},
{
MethodName: "ModuleAccountByName",
Handler: _Query_ModuleAccountByName_Handler,
},
{
MethodName: "Bech32Prefix",
Handler: _Query_Bech32Prefix_Handler,

View File

@ -52,6 +52,12 @@ service Query {
option (google.api.http).get = "/cosmos/auth/v1beta1/module_accounts";
}
// ModuleAccountByName returns the module account info by module name
rpc ModuleAccountByName(QueryModuleAccountByNameRequest) returns (QueryModuleAccountByNameResponse) {
option (cosmos.query.v1.module_query_safe) = true;
option (google.api.http).get = "/cosmos/auth/v1beta1/module_accounts/{name}";
}
// Bech32Prefix queries bech32Prefix
//
// Since: cosmos-sdk 0.46
@ -114,17 +120,6 @@ message QueryAccountRequest {
string address = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"];
}
// QueryModuleAccountsRequest is the request type for the Query/ModuleAccounts RPC method.
//
// Since: cosmos-sdk 0.46
message QueryModuleAccountsRequest {}
// QueryParamsResponse is the response type for the Query/Params RPC method.
message QueryParamsResponse {
// params defines the parameters of the module.
Params params = 1 [(gogoproto.nullable) = false];
}
// QueryAccountResponse is the response type for the Query/Account RPC method.
message QueryAccountResponse {
// account defines the account of the corresponding address.
@ -134,6 +129,17 @@ message QueryAccountResponse {
// QueryParamsRequest is the request type for the Query/Params RPC method.
message QueryParamsRequest {}
// QueryParamsResponse is the response type for the Query/Params RPC method.
message QueryParamsResponse {
// params defines the parameters of the module.
Params params = 1 [(gogoproto.nullable) = false];
}
// QueryModuleAccountsRequest is the request type for the Query/ModuleAccounts RPC method.
//
// Since: cosmos-sdk 0.46
message QueryModuleAccountsRequest {}
// QueryModuleAccountsResponse is the response type for the Query/ModuleAccounts RPC method.
//
// Since: cosmos-sdk 0.46
@ -141,6 +147,16 @@ message QueryModuleAccountsResponse {
repeated google.protobuf.Any accounts = 1 [(cosmos_proto.accepts_interface) = "ModuleAccountI"];
}
// QueryModuleAccountByNameRequest is the request type for the Query/ModuleAccountByName RPC method.
message QueryModuleAccountByNameRequest {
string name = 1;
}
// QueryModuleAccountByNameResponse is the response type for the Query/ModuleAccountByName RPC method.
message QueryModuleAccountByNameResponse {
google.protobuf.Any account = 1 [(cosmos_proto.accepts_interface) = "ModuleAccountI"];
}
// Bech32PrefixRequest is the request type for Bech32Prefix rpc method.
//
// Since: cosmos-sdk 0.46

View File

@ -18,6 +18,7 @@ import (
"cosmossdk.io/math"
authtestutil "github.com/cosmos/cosmos-sdk/x/auth/testutil"
"github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/cosmos/cosmos-sdk/client"
@ -1422,6 +1423,68 @@ func (s *IntegrationTestSuite) TestGetAccountsCmd() {
s.Require().NotEmpty(res.Accounts)
}
func (s *IntegrationTestSuite) 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", tmcli.OutputFlag),
})
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 types.AccountI
err := val.ClientCtx.InterfaceRegistry.UnpackAny(res.Account, &account)
s.Require().NoError(err)
moduleAccount, ok := account.(types.ModuleAccountI)
s.Require().True(ok)
s.Require().Equal(tc.moduleName, moduleAccount.GetName())
}
})
}
}
func (s *IntegrationTestSuite) TestQueryModuleAccountsCmd() {
val := s.network.Validators[0]
clientCtx := val.ClientCtx
out, err := clitestutil.ExecTestCLICmd(clientCtx, authcli.QueryModuleAccountsCmd(), []string{
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
})
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)

View File

@ -46,6 +46,7 @@ func GetQueryCmd() *cobra.Command {
GetAccountsCmd(),
QueryParamsCmd(),
QueryModuleAccountsCmd(),
QueryModuleAccountByNameCmd(),
)
return cmd
@ -219,6 +220,40 @@ func QueryModuleAccountsCmd() *cobra.Command {
return cmd
}
// QueryModuleAccountByNameCmd returns a command to
func QueryModuleAccountByNameCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "module-account [module-name]",
Short: "Query module account info by module name",
Args: cobra.ExactArgs(1),
Example: fmt.Sprintf("%s q auth module-account auth", version.AppName),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}
moduleName := args[0]
if len(moduleName) == 0 {
return fmt.Errorf("module name should not be empty")
}
queryClient := types.NewQueryClient(clientCtx)
res, err := queryClient.ModuleAccountByName(context.Background(), &types.QueryModuleAccountByNameRequest{Name: moduleName})
if err != nil {
return err
}
return clientCtx.PrintProto(res)
},
}
flags.AddQueryFlagsToCmd(cmd)
return cmd
}
// QueryTxsByEventsCmd returns a command to search through transactions by events.
func QueryTxsByEventsCmd() *cobra.Command {
cmd := &cobra.Command{

View File

@ -135,6 +135,31 @@ func (ak AccountKeeper) ModuleAccounts(c context.Context, req *types.QueryModule
return &types.QueryModuleAccountsResponse{Accounts: modAccounts}, nil
}
// ModuleAccountByName returns module account by module name
func (ak AccountKeeper) ModuleAccountByName(c context.Context, req *types.QueryModuleAccountByNameRequest) (*types.QueryModuleAccountByNameResponse, error) {
if req == nil {
return nil, status.Errorf(codes.InvalidArgument, "empty request")
}
if len(req.Name) == 0 {
return nil, status.Error(codes.InvalidArgument, "module name is empty")
}
ctx := sdk.UnwrapSDKContext(c)
moduleName := req.Name
account := ak.GetModuleAccount(ctx, moduleName)
if account == nil {
return nil, status.Errorf(codes.NotFound, "account %s not found", moduleName)
}
any, err := codectypes.NewAnyWithValue(account)
if err != nil {
return nil, status.Errorf(codes.Internal, err.Error())
}
return &types.QueryModuleAccountByNameResponse{Account: any}, nil
}
// Bech32Prefix returns the keeper internally stored bech32 prefix.
func (ak AccountKeeper) Bech32Prefix(ctx context.Context, req *types.Bech32PrefixRequest) (*types.Bech32PrefixResponse, error) {
bech32Prefix, err := ak.getBech32Prefix()

View File

@ -350,6 +350,61 @@ func (suite *KeeperTestSuite) TestGRPCQueryModuleAccounts() {
}
}
func (suite *KeeperTestSuite) TestGRPCQueryModuleAccountByName() {
var req *types.QueryModuleAccountByNameRequest
testCases := []struct {
msg string
malleate func()
expPass bool
posttests func(res *types.QueryModuleAccountByNameResponse)
}{
{
"success",
func() {
req = &types.QueryModuleAccountByNameRequest{Name: "mint"}
},
true,
func(res *types.QueryModuleAccountByNameResponse) {
var account types.AccountI
err := suite.encCfg.InterfaceRegistry.UnpackAny(res.Account, &account)
suite.Require().NoError(err)
moduleAccount, ok := account.(types.ModuleAccountI)
suite.Require().True(ok)
suite.Require().Equal(moduleAccount.GetName(), "mint")
},
},
{
"invalid module name",
func() {
req = &types.QueryModuleAccountByNameRequest{Name: "gover"}
},
false,
func(res *types.QueryModuleAccountByNameResponse) {
},
},
}
for _, tc := range testCases {
suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
suite.SetupTest() // reset
tc.malleate()
ctx := sdk.WrapSDKContext(suite.ctx)
res, err := suite.queryClient.ModuleAccountByName(ctx, req)
if tc.expPass {
suite.Require().NoError(err)
suite.Require().NotNil(res)
} else {
suite.Require().Error(err)
suite.Require().Nil(res)
}
tc.posttests(res)
})
}
}
func (suite *KeeperTestSuite) TestBech32Prefix() {
suite.SetupTest() // reset
req := &types.Bech32PrefixRequest{}

File diff suppressed because it is too large Load Diff

View File

@ -213,6 +213,60 @@ func local_request_Query_ModuleAccounts_0(ctx context.Context, marshaler runtime
}
func request_Query_ModuleAccountByName_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq QueryModuleAccountByNameRequest
var metadata runtime.ServerMetadata
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["name"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "name")
}
protoReq.Name, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "name", err)
}
msg, err := client.ModuleAccountByName(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_Query_ModuleAccountByName_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq QueryModuleAccountByNameRequest
var metadata runtime.ServerMetadata
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["name"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "name")
}
protoReq.Name, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "name", err)
}
msg, err := server.ModuleAccountByName(ctx, &protoReq)
return msg, metadata, err
}
func request_Query_Bech32Prefix_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq Bech32PrefixRequest
var metadata runtime.ServerMetadata
@ -514,6 +568,29 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv
})
mux.Handle("GET", pattern_Query_ModuleAccountByName_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
var stream runtime.ServerTransportStream
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_Query_ModuleAccountByName_0(rctx, inboundMarshaler, server, req, pathParams)
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_Query_ModuleAccountByName_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_Query_Bech32Prefix_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
@ -747,6 +824,26 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie
})
mux.Handle("GET", pattern_Query_ModuleAccountByName_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_Query_ModuleAccountByName_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_Query_ModuleAccountByName_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_Query_Bech32Prefix_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
@ -841,6 +938,8 @@ var (
pattern_Query_ModuleAccounts_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"cosmos", "auth", "v1beta1", "module_accounts"}, "", runtime.AssumeColonVerbOpt(false)))
pattern_Query_ModuleAccountByName_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"cosmos", "auth", "v1beta1", "module_accounts", "name"}, "", runtime.AssumeColonVerbOpt(false)))
pattern_Query_Bech32Prefix_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"cosmos", "auth", "v1beta1", "bech32"}, "", runtime.AssumeColonVerbOpt(false)))
pattern_Query_AddressBytesToString_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"cosmos", "auth", "v1beta1", "bech32", "address_bytes"}, "", runtime.AssumeColonVerbOpt(false)))
@ -861,6 +960,8 @@ var (
forward_Query_ModuleAccounts_0 = runtime.ForwardResponseMessage
forward_Query_ModuleAccountByName_0 = runtime.ForwardResponseMessage
forward_Query_Bech32Prefix_0 = runtime.ForwardResponseMessage
forward_Query_AddressBytesToString_0 = runtime.ForwardResponseMessage