Skip to content

Commit

Permalink
feat: Add gRPC query for remainder and account fractional balance (#1971
Browse files Browse the repository at this point in the history
)
  • Loading branch information
drklee3 authored Jul 25, 2024
1 parent 74f76d1 commit 608f70b
Show file tree
Hide file tree
Showing 6 changed files with 1,128 additions and 37 deletions.
61 changes: 61 additions & 0 deletions docs/core/proto-docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,10 @@
- [GenesisState](#kava.precisebank.v1.GenesisState)

- [kava/precisebank/v1/query.proto](#kava/precisebank/v1/query.proto)
- [QueryFractionalBalanceRequest](#kava.precisebank.v1.QueryFractionalBalanceRequest)
- [QueryFractionalBalanceResponse](#kava.precisebank.v1.QueryFractionalBalanceResponse)
- [QueryRemainderRequest](#kava.precisebank.v1.QueryRemainderRequest)
- [QueryRemainderResponse](#kava.precisebank.v1.QueryRemainderResponse)
- [QueryTotalFractionalBalancesRequest](#kava.precisebank.v1.QueryTotalFractionalBalancesRequest)
- [QueryTotalFractionalBalancesResponse](#kava.precisebank.v1.QueryTotalFractionalBalancesResponse)

Expand Down Expand Up @@ -6689,6 +6693,61 @@ GenesisState defines the precisebank module's genesis state.



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

### QueryFractionalBalanceRequest
QueryFractionalBalanceRequest defines the request type for Query/FractionalBalance method.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `address` | [string](#string) | | address is the account address to query fractional balance for. |






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

### QueryFractionalBalanceResponse
QueryFractionalBalanceResponse defines the response type for Query/FractionalBalance method.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `fractional_balance` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | fractional_balance is the fractional balance of the address. |






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

### QueryRemainderRequest
QueryRemainderRequest defines the request type for Query/Remainder method.






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

### QueryRemainderResponse
QueryRemainderResponse defines the response type for Query/Remainder method.


| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `remainder` | [cosmos.base.v1beta1.Coin](#cosmos.base.v1beta1.Coin) | | remainder is the amount backed by the reserve, but not yet owned by any account, i.e. not in circulation. |






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

### QueryTotalFractionalBalancesRequest
Expand Down Expand Up @@ -6728,6 +6787,8 @@ 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|
| `Remainder` | [QueryRemainderRequest](#kava.precisebank.v1.QueryRemainderRequest) | [QueryRemainderResponse](#kava.precisebank.v1.QueryRemainderResponse) | Remainder returns the amount backed by the reserve, but not yet owned by any account, i.e. not in circulation. | GET|/kava/precisebank/v1/remainder|
| `FractionalBalance` | [QueryFractionalBalanceRequest](#kava.precisebank.v1.QueryFractionalBalanceRequest) | [QueryFractionalBalanceResponse](#kava.precisebank.v1.QueryFractionalBalanceResponse) | FractionalBalance returns only the fractional balance of an address. This does not include any integer balance. | GET|/kava/precisebank/v1/fractional_balance/{address}|

<!-- end services -->

Expand Down
34 changes: 34 additions & 0 deletions proto/kava/precisebank/v1/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,18 @@ service Query {
rpc TotalFractionalBalances(QueryTotalFractionalBalancesRequest) returns (QueryTotalFractionalBalancesResponse) {
option (google.api.http).get = "/kava/precisebank/v1/total_fractional_balances";
}

// Remainder returns the amount backed by the reserve, but not yet owned by
// any account, i.e. not in circulation.
rpc Remainder(QueryRemainderRequest) returns (QueryRemainderResponse) {
option (google.api.http).get = "/kava/precisebank/v1/remainder";
}

// FractionalBalance returns only the fractional balance of an address. This
// does not include any integer balance.
rpc FractionalBalance(QueryFractionalBalanceRequest) returns (QueryFractionalBalanceResponse) {
option (google.api.http).get = "/kava/precisebank/v1/fractional_balance/{address}";
}
}

// QueryTotalFractionalBalancesRequest defines the request type for Query/TotalFractionalBalances method.
Expand All @@ -26,3 +38,25 @@ message QueryTotalFractionalBalancesResponse {
// module.
cosmos.base.v1beta1.Coin total = 1 [(gogoproto.nullable) = false];
}

// QueryRemainderRequest defines the request type for Query/Remainder method.
message QueryRemainderRequest {}

// QueryRemainderResponse defines the response type for Query/Remainder method.
message QueryRemainderResponse {
// remainder is the amount backed by the reserve, but not yet owned by any
// account, i.e. not in circulation.
cosmos.base.v1beta1.Coin remainder = 1 [(gogoproto.nullable) = false];
}

// QueryFractionalBalanceRequest defines the request type for Query/FractionalBalance method.
message QueryFractionalBalanceRequest {
// address is the account address to query fractional balance for.
string address = 1;
}

// QueryFractionalBalanceResponse defines the response type for Query/FractionalBalance method.
message QueryFractionalBalanceResponse {
// fractional_balance is the fractional balance of the address.
cosmos.base.v1beta1.Coin fractional_balance = 1 [(gogoproto.nullable) = false];
}
35 changes: 35 additions & 0 deletions x/precisebank/keeper/grpc_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,38 @@ func (s queryServer) TotalFractionalBalances(
Total: totalCoin,
}, nil
}

// Remainder returns the remainder amount in x/precisebank.
func (s queryServer) Remainder(
goCtx context.Context,
req *types.QueryRemainderRequest,
) (*types.QueryRemainderResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)

remainder := s.keeper.GetRemainderAmount(ctx)
remainderCoin := sdk.NewCoin(types.ExtendedCoinDenom, remainder)

return &types.QueryRemainderResponse{
Remainder: remainderCoin,
}, nil
}

// FractionalBalance returns the fractional balance of an account.
func (s queryServer) FractionalBalance(
goCtx context.Context,
req *types.QueryFractionalBalanceRequest,
) (*types.QueryFractionalBalanceResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)

address, err := sdk.AccAddressFromBech32(req.Address)
if err != nil {
return nil, err
}

amt := s.keeper.GetFractionalBalance(ctx, address)
fractionalBalance := sdk.NewCoin(types.ExtendedCoinDenom, amt)

return &types.QueryFractionalBalanceResponse{
FractionalBalance: fractionalBalance,
}, nil
}
85 changes: 85 additions & 0 deletions x/precisebank/keeper/grpc_query_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
sdkmath "cosmossdk.io/math"
"github.com/cosmos/cosmos-sdk/baseapp"
sdk "github.com/cosmos/cosmos-sdk/types"
minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
"github.com/stretchr/testify/suite"

"github.com/kava-labs/kava/x/precisebank/keeper"
Expand Down Expand Up @@ -84,3 +85,87 @@ func (suite *grpcQueryTestSuite) TestQueryTotalFractionalBalance() {
})
}
}

func (suite *grpcQueryTestSuite) TestQueryRemainder() {
res, err := suite.queryClient.Remainder(
context.Background(),
&types.QueryRemainderRequest{},
)
suite.Require().NoError(err)

expRemainder := sdk.NewCoin(types.ExtendedCoinDenom, sdkmath.ZeroInt())
suite.Require().Equal(expRemainder, res.Remainder)

// Mint fractional coins to create non-zero remainder

pbk := suite.App.GetPrecisebankKeeper()

coin := sdk.NewCoin(types.ExtendedCoinDenom, sdkmath.OneInt())
err = pbk.MintCoins(
suite.Ctx,
minttypes.ModuleName,
sdk.NewCoins(coin),
)
suite.Require().NoError(err)

res, err = suite.queryClient.Remainder(
context.Background(),
&types.QueryRemainderRequest{},
)
suite.Require().NoError(err)

expRemainder.Amount = types.ConversionFactor().Sub(coin.Amount)
suite.Require().Equal(expRemainder, res.Remainder)
}

func (suite *grpcQueryTestSuite) TestQueryFractionalBalance() {
testCases := []struct {
name string
giveBalance sdkmath.Int
}{
{
"zero",
sdkmath.ZeroInt(),
},
{
"min amount",
sdkmath.OneInt(),
},
{
"max amount",
types.ConversionFactor().SubRaw(1),
},
{
"multiple integer amounts, 0 fractional",
types.ConversionFactor().MulRaw(5),
},
{
"multiple integer amounts, non-zero fractional",
types.ConversionFactor().MulRaw(5).Add(types.ConversionFactor().QuoRaw(2)),
},
}

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

addr := sdk.AccAddress([]byte("test"))

coin := sdk.NewCoin(types.ExtendedCoinDenom, tc.giveBalance)
suite.MintToAccount(addr, sdk.NewCoins(coin))

res, err := suite.queryClient.FractionalBalance(
context.Background(),
&types.QueryFractionalBalanceRequest{
Address: addr.String(),
},
)
suite.Require().NoError(err)

// Only fractional amount, even if minted more than conversion factor
expAmount := tc.giveBalance.Mod(types.ConversionFactor())
expFractionalBalance := sdk.NewCoin(types.ExtendedCoinDenom, expAmount)
suite.Require().Equal(expFractionalBalance, res.FractionalBalance)
})
}
}
Loading

0 comments on commit 608f70b

Please sign in to comment.