Skip to content

Commit

Permalink
feat(x/precisebank): Add query service with TotalFractionalBalances (#…
Browse files Browse the repository at this point in the history
…1970)

Add query service to precisebank, mostly for e2e test purposes in #1966
Also fix client grpc codec
  • Loading branch information
drklee3 authored Jul 19, 2024
1 parent 7aef2f0 commit 3853e27
Show file tree
Hide file tree
Showing 9 changed files with 950 additions and 31 deletions.
16 changes: 15 additions & 1 deletion client/grpc/query/connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"fmt"
"net/url"

"github.com/cosmos/cosmos-sdk/codec"
"github.com/kava-labs/kava/app"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/credentials/insecure"
Expand All @@ -28,8 +30,20 @@ func newGrpcConnection(ctx context.Context, endpoint string) (*grpc.ClientConn,
return nil, fmt.Errorf("unknown grpc url scheme: %s", grpcUrl.Scheme)
}

// Ensure the encoding config is set up correctly with the query client
// otherwise it will produce panics like:
// invalid Go type math.Int for field ...
encodingConfig := app.MakeEncodingConfig()
protoCodec := codec.NewProtoCodec(encodingConfig.InterfaceRegistry)
grpcCodec := protoCodec.GRPCCodec()

secureOpt := grpc.WithTransportCredentials(creds)
grpcConn, err := grpc.DialContext(ctx, grpcUrl.Host, secureOpt)
grpcConn, err := grpc.DialContext(
ctx,
grpcUrl.Host,
secureOpt,
grpc.WithDefaultCallOptions(grpc.ForceCodec(grpcCodec)),
)
if err != nil {
return nil, err
}
Expand Down
63 changes: 33 additions & 30 deletions client/grpc/query/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import (
issuancetypes "github.com/kava-labs/kava/x/issuance/types"
kavadisttypes "github.com/kava-labs/kava/x/kavadist/types"
liquidtypes "github.com/kava-labs/kava/x/liquid/types"
precisebanktypes "github.com/kava-labs/kava/x/precisebank/types"
pricefeedtypes "github.com/kava-labs/kava/x/pricefeed/types"
savingstypes "github.com/kava-labs/kava/x/savings/types"
swaptypes "github.com/kava-labs/kava/x/swap/types"
Expand Down Expand Up @@ -70,21 +71,22 @@ type QueryClient struct {

// kava module query clients

Auction auctiontypes.QueryClient
Bep3 bep3types.QueryClient
Cdp cdptypes.QueryClient
Committee committeetypes.QueryClient
Community communitytypes.QueryClient
Earn earntypes.QueryClient
Evmutil evmutiltypes.QueryClient
Hard hardtypes.QueryClient
Incentive incentivetypes.QueryClient
Issuance issuancetypes.QueryClient
Kavadist kavadisttypes.QueryClient
Liquid liquidtypes.QueryClient
Pricefeed pricefeedtypes.QueryClient
Savings savingstypes.QueryClient
Swap swaptypes.QueryClient
Auction auctiontypes.QueryClient
Bep3 bep3types.QueryClient
Cdp cdptypes.QueryClient
Committee committeetypes.QueryClient
Community communitytypes.QueryClient
Earn earntypes.QueryClient
Evmutil evmutiltypes.QueryClient
Hard hardtypes.QueryClient
Incentive incentivetypes.QueryClient
Issuance issuancetypes.QueryClient
Kavadist kavadisttypes.QueryClient
Liquid liquidtypes.QueryClient
Pricefeed pricefeedtypes.QueryClient
Savings savingstypes.QueryClient
Swap swaptypes.QueryClient
Precisebank precisebanktypes.QueryClient
}

// NewQueryClient creates a new QueryClient and initializes all the module query clients
Expand Down Expand Up @@ -115,21 +117,22 @@ func NewQueryClient(grpcEndpoint string) (*QueryClient, error) {
IbcClient: ibcclienttypes.NewQueryClient(conn),
IbcTransfer: ibctransfertypes.NewQueryClient(conn),

Auction: auctiontypes.NewQueryClient(conn),
Bep3: bep3types.NewQueryClient(conn),
Cdp: cdptypes.NewQueryClient(conn),
Committee: committeetypes.NewQueryClient(conn),
Community: communitytypes.NewQueryClient(conn),
Earn: earntypes.NewQueryClient(conn),
Evmutil: evmutiltypes.NewQueryClient(conn),
Hard: hardtypes.NewQueryClient(conn),
Incentive: incentivetypes.NewQueryClient(conn),
Issuance: issuancetypes.NewQueryClient(conn),
Kavadist: kavadisttypes.NewQueryClient(conn),
Liquid: liquidtypes.NewQueryClient(conn),
Pricefeed: pricefeedtypes.NewQueryClient(conn),
Savings: savingstypes.NewQueryClient(conn),
Swap: swaptypes.NewQueryClient(conn),
Auction: auctiontypes.NewQueryClient(conn),
Bep3: bep3types.NewQueryClient(conn),
Cdp: cdptypes.NewQueryClient(conn),
Committee: committeetypes.NewQueryClient(conn),
Community: communitytypes.NewQueryClient(conn),
Earn: earntypes.NewQueryClient(conn),
Evmutil: evmutiltypes.NewQueryClient(conn),
Hard: hardtypes.NewQueryClient(conn),
Incentive: incentivetypes.NewQueryClient(conn),
Issuance: issuancetypes.NewQueryClient(conn),
Kavadist: kavadisttypes.NewQueryClient(conn),
Liquid: liquidtypes.NewQueryClient(conn),
Pricefeed: pricefeedtypes.NewQueryClient(conn),
Savings: savingstypes.NewQueryClient(conn),
Swap: swaptypes.NewQueryClient(conn),
Precisebank: precisebanktypes.NewQueryClient(conn),
}
return client, nil
}
57 changes: 57 additions & 0 deletions docs/core/proto-docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,12 @@
- [FractionalBalance](#kava.precisebank.v1.FractionalBalance)
- [GenesisState](#kava.precisebank.v1.GenesisState)

- [kava/precisebank/v1/query.proto](#kava/precisebank/v1/query.proto)
- [QueryTotalFractionalBalancesRequest](#kava.precisebank.v1.QueryTotalFractionalBalancesRequest)
- [QueryTotalFractionalBalancesResponse](#kava.precisebank.v1.QueryTotalFractionalBalancesResponse)

- [Query](#kava.precisebank.v1.Query)

- [kava/pricefeed/v1beta1/store.proto](#kava/pricefeed/v1beta1/store.proto)
- [CurrentPrice](#kava.pricefeed.v1beta1.CurrentPrice)
- [Market](#kava.pricefeed.v1beta1.Market)
Expand Down Expand Up @@ -6676,6 +6682,57 @@ GenesisState defines the precisebank module's genesis state.



<a name="kava/precisebank/v1/query.proto"></a>
<p align="right"><a href="#top">Top</a></p>

## kava/precisebank/v1/query.proto



<a name="kava.precisebank.v1.QueryTotalFractionalBalancesRequest"></a>

### QueryTotalFractionalBalancesRequest
QueryTotalFractionalBalancesRequest defines the request type for Query/TotalFractionalBalances method.






<a name="kava.precisebank.v1.QueryTotalFractionalBalancesResponse"></a>

### QueryTotalFractionalBalancesResponse
QueryTotalFractionalBalancesResponse defines the response type for Query/TotalFractionalBalances method.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `total` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | total is the total sum of all fractional balances managed by the precisebank module. |





<!-- end messages -->

<!-- end enums -->

<!-- end HasExtensions -->


<a name="kava.precisebank.v1.Query"></a>

### Query
Query defines the gRPC querier service for precisebank module

| Method Name | Request Type | Response Type | Description | HTTP Verb | Endpoint |
| ----------- | ------------ | ------------- | ------------| ------- | -------- |
| `TotalFractionalBalances` | [QueryTotalFractionalBalancesRequest](#kava.precisebank.v1.QueryTotalFractionalBalancesRequest) | [QueryTotalFractionalBalancesResponse](#kava.precisebank.v1.QueryTotalFractionalBalancesResponse) | TotalFractionalBalances returns the total sum of all fractional balances managed by the precisebank module. | GET|/kava/precisebank/v1/total_fractional_balances|

<!-- end services -->



<a name="kava/pricefeed/v1beta1/store.proto"></a>
<p align="right"><a href="#top">Top</a></p>

Expand Down
28 changes: 28 additions & 0 deletions proto/kava/precisebank/v1/query.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
syntax = "proto3";
package kava.precisebank.v1;

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

option go_package = "github.com/kava-labs/kava/x/precisebank/types";
option (gogoproto.goproto_getters_all) = false;

// Query defines the gRPC querier service for precisebank module
service Query {
// TotalFractionalBalances returns the total sum of all fractional balances
// managed by the precisebank module.
rpc TotalFractionalBalances(QueryTotalFractionalBalancesRequest) returns (QueryTotalFractionalBalancesResponse) {
option (google.api.http).get = "/kava/precisebank/v1/total_fractional_balances";
}
}

// QueryTotalFractionalBalancesRequest defines the request type for Query/TotalFractionalBalances method.
message QueryTotalFractionalBalancesRequest {}

// QueryTotalFractionalBalancesResponse defines the response type for Query/TotalFractionalBalances method.
message QueryTotalFractionalBalancesResponse {
// total is the total sum of all fractional balances managed by the precisebank
// module.
cosmos.base.v1beta1.Coin total = 1 [(gogoproto.nullable) = false];
}
38 changes: 38 additions & 0 deletions x/precisebank/keeper/grpc_query.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package keeper

import (
"context"

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

"github.com/kava-labs/kava/x/precisebank/types"
)

type queryServer struct {
keeper Keeper
}

// NewQueryServerImpl creates a new server for handling gRPC queries.
func NewQueryServerImpl(k Keeper) types.QueryServer {
return &queryServer{keeper: k}
}

var _ types.QueryServer = queryServer{}

// TotalFractionalBalances returns the total sum of all fractional balances.
// This is mostly for external verification of the total fractional balances,
// being a multiple of the conversion factor and backed by the reserve.
func (s queryServer) TotalFractionalBalances(
goCtx context.Context,
req *types.QueryTotalFractionalBalancesRequest,
) (*types.QueryTotalFractionalBalancesResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)

totalAmount := s.keeper.GetTotalSumFractionalBalances(ctx)

totalCoin := sdk.NewCoin(types.ExtendedCoinDenom, totalAmount)

return &types.QueryTotalFractionalBalancesResponse{
Total: totalCoin,
}, nil
}
86 changes: 86 additions & 0 deletions x/precisebank/keeper/grpc_query_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package keeper_test

import (
"context"
"strconv"
"testing"

sdkmath "cosmossdk.io/math"
"github.com/cosmos/cosmos-sdk/baseapp"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/suite"

"github.com/kava-labs/kava/x/precisebank/keeper"
"github.com/kava-labs/kava/x/precisebank/testutil"
"github.com/kava-labs/kava/x/precisebank/types"
)

type grpcQueryTestSuite struct {
testutil.Suite

queryClient types.QueryClient
}

func (suite *grpcQueryTestSuite) SetupTest() {
suite.Suite.SetupTest()

queryHelper := baseapp.NewQueryServerTestHelper(suite.Ctx, suite.App.InterfaceRegistry())
types.RegisterQueryServer(queryHelper, keeper.NewQueryServerImpl(suite.Keeper))

suite.queryClient = types.NewQueryClient(queryHelper)
}

func TestGrpcQueryTestSuite(t *testing.T) {
suite.Run(t, new(grpcQueryTestSuite))
}

func (suite *grpcQueryTestSuite) TestQueryTotalFractionalBalance() {
testCases := []struct {
name string
giveBalances []sdkmath.Int
}{
{
"empty",
[]sdkmath.Int{},
},
{
"min amount",
[]sdkmath.Int{
types.ConversionFactor().QuoRaw(2),
types.ConversionFactor().QuoRaw(2),
},
},
{
"exceeds conversion factor",
[]sdkmath.Int{
// 4 accounts * 0.5 == 2
types.ConversionFactor().QuoRaw(2),
types.ConversionFactor().QuoRaw(2),
types.ConversionFactor().QuoRaw(2),
types.ConversionFactor().QuoRaw(2),
},
},
}

for _, tc := range testCases {
suite.Run(tc.name, func() {
suite.SetupTest()

total := sdk.NewCoin(types.ExtendedCoinDenom, sdkmath.ZeroInt())
for i, balance := range tc.giveBalances {
addr := sdk.AccAddress([]byte(strconv.Itoa(i)))
suite.Keeper.SetFractionalBalance(suite.Ctx, addr, balance)

total.Amount = total.Amount.Add(balance)
}

res, err := suite.queryClient.TotalFractionalBalances(
context.Background(),
&types.QueryTotalFractionalBalancesRequest{},
)
suite.Require().NoError(err)

suite.Require().Equal(total, res.Total)
})
}
}
5 changes: 5 additions & 0 deletions x/precisebank/module.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package precisebank

import (
"context"
"encoding/json"

"github.com/grpc-ecosystem/grpc-gateway/runtime"
Expand Down Expand Up @@ -70,6 +71,9 @@ func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, config client.TxEncod

// RegisterGRPCGatewayRoutes registers the gRPC Gateway routes for precisebank module.
func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) {
if err := types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx)); err != nil {
panic(err)
}
}

// GetTxCmd returns precisebank module's root tx command.
Expand Down Expand Up @@ -117,6 +121,7 @@ func (am AppModule) Name() string {
// RegisterServices registers a GRPC query service to respond to the
// module-specific GRPC queries.
func (am AppModule) RegisterServices(cfg module.Configurator) {
types.RegisterQueryServer(cfg.QueryServer(), keeper.NewQueryServerImpl(am.keeper))
}

// RegisterInvariants registers precisebank module's invariants.
Expand Down
Loading

0 comments on commit 3853e27

Please sign in to comment.