Skip to content

Commit

Permalink
feat: create a query that directly returns all module accounts withou…
Browse files Browse the repository at this point in the history
…t pagination or iteration (#987)

* add skeleton for query

* temp commit

* rename var

* add accounts with balances into response

* add module accounts for query

* add test for query

* add changelog
  • Loading branch information
jgimeno authored Oct 12, 2022
1 parent b744a99 commit d571914
Show file tree
Hide file tree
Showing 14 changed files with 1,288 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* [#956](https://github.com/NibiruChain/nibiru/pull/956) - test(perp): partial liquidate unit test
* [#981](https://github.com/NibiruChain/nibiru/pull/981) - chore(testutil): clean up x/testutil packages
* [#980](https://github.com/NibiruChain/nibiru/pull/980) - test(perp): add `MsgClosePosition`, `MsgAddMargin`, and `MsgRemoveMargin` simulation tests
* [#987](https://github.com/NibiruChain/nibiru/pull/987) - feat: create a query that directly returns all module accounts without pagination or iteration
* [#982](https://github.com/NibiruChain/nibiru/pull/982) - improvements for pricefeed genesis
* [#989](https://github.com/NibiruChain/nibiru/pull/989) - test(perp): cli test for AddMargin

Expand Down
8 changes: 8 additions & 0 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ import (
pricefeedcli "github.com/NibiruChain/nibiru/x/pricefeed/client/cli"
pricefeedkeeper "github.com/NibiruChain/nibiru/x/pricefeed/keeper"
pricefeedtypes "github.com/NibiruChain/nibiru/x/pricefeed/types"
"github.com/NibiruChain/nibiru/x/util"
utiltypes "github.com/NibiruChain/nibiru/x/util/types"
"github.com/NibiruChain/nibiru/x/vpool"
vpoolcli "github.com/NibiruChain/nibiru/x/vpool/client/cli"
vpoolkeeper "github.com/NibiruChain/nibiru/x/vpool/keeper"
Expand Down Expand Up @@ -164,6 +166,7 @@ var (
epochs.AppModuleBasic{},
perp.AppModuleBasic{},
vpool.AppModuleBasic{},
util.AppModule{},
)

// module account permissions
Expand Down Expand Up @@ -495,6 +498,7 @@ func NewNibiruApp(
vpoolModule := vpool.NewAppModule(
appCodec, app.vpoolKeeper, app.pricefeedKeeper,
)
utilModule := util.NewAppModule(app.bankKeeper)

// NOTE: Any module instantiated in the module manager that is later modified
// must be passed by reference here.
Expand Down Expand Up @@ -523,6 +527,7 @@ func NewNibiruApp(
epochsModule,
vpoolModule,
perpModule,
utilModule,

// ibc
evidence.NewAppModule(app.evidenceKeeper),
Expand Down Expand Up @@ -557,6 +562,7 @@ func NewNibiruApp(
epochstypes.ModuleName,
vpooltypes.ModuleName,
perptypes.ModuleName,
utiltypes.ModuleName,
// ibc modules
ibchost.ModuleName,
ibctransfertypes.ModuleName,
Expand All @@ -583,6 +589,7 @@ func NewNibiruApp(
pricefeedtypes.ModuleName,
vpooltypes.ModuleName,
perptypes.ModuleName,
utiltypes.ModuleName,
// ibc
ibchost.ModuleName,
ibctransfertypes.ModuleName,
Expand Down Expand Up @@ -615,6 +622,7 @@ func NewNibiruApp(
epochstypes.ModuleName,
vpooltypes.ModuleName,
perptypes.ModuleName,
utiltypes.ModuleName,
// ibc
ibchost.ModuleName,
ibctransfertypes.ModuleName,
Expand Down
35 changes: 35 additions & 0 deletions proto/util/v1/query.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
syntax = "proto3";

package nibiru.util.v1;

import "gogoproto/gogo.proto";
import "google/api/annotations.proto";
import "cosmos/base/v1beta1/coin.proto";
import "vpool/v1/state.proto";

option go_package = "github.com/NibiruChain/nibiru/x/util/types";

// Query defines the gRPC querier service.
service Query {

// Queries the reserve assets in a given pool, identified by a token pair.
rpc ModuleAccounts(QueryModuleAccountsRequest) returns (QueryModuleAccountsResponse) {
option (google.api.http).get = "/nibiru/util/module_accounts";
}
}

// ----------------------------------------

message QueryModuleAccountsRequest {}

message QueryModuleAccountsResponse {
repeated AccountWithBalance accounts = 1 [(gogoproto.nullable) = false];
}

message AccountWithBalance {
string name = 1;
string address = 2;

repeated cosmos.base.v1beta1.Coin balance = 3
[(gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"];
}
58 changes: 58 additions & 0 deletions x/util/client/cli/query.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package cli

import (
"fmt"

"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/spf13/cobra"

utiltypes "github.com/NibiruChain/nibiru/x/util/types"
)

// GetQueryCmd returns the cli query commands for this module
func GetQueryCmd() *cobra.Command {
queryCmd := &cobra.Command{
Use: utiltypes.ModuleName,
Short: fmt.Sprintf(
"Querying commands for the %s module", utiltypes.ModuleName),
DisableFlagParsing: true,
SuggestionsMinimumDistance: 2,
RunE: client.ValidateCmd,
}

for _, cmd := range []*cobra.Command{
CmdQueryModuleAccounts(),
} {
queryCmd.AddCommand(cmd)
}

return queryCmd
}

func CmdQueryModuleAccounts() *cobra.Command {
cmd := &cobra.Command{
Use: "module-accounts",
Short: "shows all the module accounts in the blockchain",
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientQueryContext(cmd)
if err != nil {
return err
}

queryClient := utiltypes.NewQueryClient(clientCtx)

res, err := queryClient.ModuleAccounts(cmd.Context(), &utiltypes.QueryModuleAccountsRequest{})
if err != nil {
return err
}

return clientCtx.PrintProto(res)
},
}

flags.AddQueryFlagsToCmd(cmd)

return cmd
}
18 changes: 18 additions & 0 deletions x/util/handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package util

import (
"fmt"

sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"

utiltypes "github.com/NibiruChain/nibiru/x/util/types"
)

// NewHandler ...
func NewHandler() sdk.Handler {
return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
errMsg := fmt.Sprintf("unrecognized %s message type: %T", utiltypes.ModuleName, msg)
return nil, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, errMsg)
}
}
41 changes: 41 additions & 0 deletions x/util/keeper/query_server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package keeper

import (
"context"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth/types"

utiltypes "github.com/NibiruChain/nibiru/x/util/types"
)

type queryServer struct {
k utiltypes.BankKeeper
}

func NewQueryServer(k utiltypes.BankKeeper) utiltypes.QueryServer {
return &queryServer{k: k}
}

func (q queryServer) ModuleAccounts(
ctx context.Context,
_ *utiltypes.QueryModuleAccountsRequest,
) (*utiltypes.QueryModuleAccountsResponse, error) {
sdkContext := sdk.UnwrapSDKContext(ctx)

var moduleAccountsWithBalances []utiltypes.AccountWithBalance
for _, acc := range utiltypes.ModuleAccounts {
account := types.NewModuleAddress(acc)

balances := q.k.GetAllBalances(sdkContext, account)

accWithBalance := utiltypes.AccountWithBalance{
Name: acc,
Address: account.String(),
Balance: balances,
}
moduleAccountsWithBalances = append(moduleAccountsWithBalances, accWithBalance)
}

return &utiltypes.QueryModuleAccountsResponse{Accounts: moduleAccountsWithBalances}, nil
}
40 changes: 40 additions & 0 deletions x/util/keeper/query_server_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package keeper_test

import (
"testing"

sdktypes "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/require"

"github.com/NibiruChain/nibiru/simapp"
"github.com/NibiruChain/nibiru/x/util/keeper"
"github.com/NibiruChain/nibiru/x/util/types"
)

func TestQueryServer_ModuleAccounts(t *testing.T) {
app, ctx := simapp.NewTestNibiruAppAndContext(false)
goCtx := sdktypes.WrapSDKContext(ctx)

qServer := keeper.NewQueryServer(app.BankKeeper)

t.Log("query accounts and check empty balance")
accounts, err := qServer.ModuleAccounts(goCtx, &types.QueryModuleAccountsRequest{})
require.NoError(t, err)
require.Len(t, accounts.Accounts, len(types.ModuleAccounts))
require.Equal(t, accounts.Accounts[0].Balance, sdktypes.Coins{})

t.Log("we send some money")
someModuleAccount := types.ModuleAccounts[0]
err = app.BankKeeper.MintCoins(
ctx,
someModuleAccount,
sdktypes.NewCoins(sdktypes.NewInt64Coin("uniques", 1_000_000)),
)
require.NoError(t, err)

t.Log("we check that it returns some balance")
accounts, err = qServer.ModuleAccounts(goCtx, &types.QueryModuleAccountsRequest{})
require.NoError(t, err)
require.Len(t, accounts.Accounts, len(types.ModuleAccounts))
require.Equal(t, accounts.Accounts[0].Balance, sdktypes.NewCoins(sdktypes.NewInt64Coin("uniques", 1_000_000)))
}
74 changes: 74 additions & 0 deletions x/util/module.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package util

import (
"encoding/json"

"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
"github.com/gorilla/mux"
"github.com/grpc-ecosystem/grpc-gateway/runtime"
"github.com/spf13/cobra"
abci "github.com/tendermint/tendermint/abci/types"

"github.com/NibiruChain/nibiru/x/util/client/cli"
"github.com/NibiruChain/nibiru/x/util/keeper"
utiltypes "github.com/NibiruChain/nibiru/x/util/types"
)

var (
_ module.AppModule = AppModule{}
)

type AppModule struct {
bankKeeper utiltypes.BankKeeper
}

func NewAppModule(bk utiltypes.BankKeeper) *AppModule {
return &AppModule{
bankKeeper: bk,
}
}

func (a AppModule) Name() string {
return "util"
}

func (a AppModule) RegisterLegacyAminoCodec(*codec.LegacyAmino) {}
func (a AppModule) RegisterInterfaces(codectypes.InterfaceRegistry) {}
func (a AppModule) DefaultGenesis(codec.JSONCodec) json.RawMessage { return nil }
func (a AppModule) ValidateGenesis(codec.JSONCodec, client.TxEncodingConfig, json.RawMessage) error {
return nil
}
func (a AppModule) RegisterRESTRoutes(client.Context, *mux.Router) {}
func (a AppModule) RegisterGRPCGatewayRoutes(client.Context, *runtime.ServeMux) {}
func (a AppModule) GetTxCmd() *cobra.Command { return nil }
func (a AppModule) GetQueryCmd() *cobra.Command { return cli.GetQueryCmd() }
func (a AppModule) InitGenesis(sdk.Context, codec.JSONCodec, json.RawMessage) []abci.ValidatorUpdate {
return nil
}
func (a AppModule) ExportGenesis(sdk.Context, codec.JSONCodec) json.RawMessage {
return nil
}
func (a AppModule) RegisterInvariants(sdk.InvariantRegistry) {}
func (a AppModule) Route() sdk.Route {
return sdk.NewRoute("", NewHandler())
}
func (a AppModule) QuerierRoute() string {
return ""
}
func (a AppModule) LegacyQuerierHandler(*codec.LegacyAmino) sdk.Querier {
return nil
}
func (a AppModule) RegisterServices(cfg module.Configurator) {
utiltypes.RegisterQueryServer(cfg.QueryServer(), keeper.NewQueryServer(a.bankKeeper))
}
func (a AppModule) ConsensusVersion() uint64 {
return 1
}
func (a AppModule) BeginBlock(sdk.Context, abci.RequestBeginBlock) {}
func (a AppModule) EndBlock(sdk.Context, abci.RequestEndBlock) []abci.ValidatorUpdate {
return nil
}
8 changes: 8 additions & 0 deletions x/util/types/expected_keepers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package types

import sdk "github.com/cosmos/cosmos-sdk/types"

// BankKeeper defines the expected interface needed to retrieve account balances.
type BankKeeper interface {
GetAllBalances(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins
}
6 changes: 6 additions & 0 deletions x/util/types/keys.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package types

const (
ModuleName = "util"
RouterKey = ModuleName
)
14 changes: 14 additions & 0 deletions x/util/types/module_accounts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package types

import (
"github.com/NibiruChain/nibiru/x/common"
perptypes "github.com/NibiruChain/nibiru/x/perp/types"
)

var ModuleAccounts = []string{
perptypes.ModuleName,
perptypes.VaultModuleAccount,
perptypes.PerpEFModuleAccount,
perptypes.FeePoolModuleAccount,
common.TreasuryPoolModuleAccount,
}
Loading

0 comments on commit d571914

Please sign in to comment.