Skip to content

Commit

Permalink
feat: Add Supply Offsets to bank module (cosmos#119)
Browse files Browse the repository at this point in the history
  • Loading branch information
czarcas7ic committed May 8, 2024
1 parent 5046a6d commit 9b55c73
Show file tree
Hide file tree
Showing 16 changed files with 4,198 additions and 582 deletions.
3,006 changes: 2,575 additions & 431 deletions api/cosmos/bank/v1beta1/query.pulsar.go

Large diffs are not rendered by default.

78 changes: 78 additions & 0 deletions api/cosmos/bank/v1beta1/query_grpc.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

53 changes: 53 additions & 0 deletions proto/cosmos/bank/v1beta1/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,18 @@ service Query {
option (google.api.http).get = "/cosmos/bank/v1beta1/supply/by_denom";
}

// TotalSupplyWithoutOffset queries the total supply of all coins.
rpc TotalSupplyWithoutOffset(QueryTotalSupplyWithoutOffsetRequest) returns (QueryTotalSupplyWithoutOffsetResponse) {
option (cosmos.query.v1.module_query_safe) = true;
option (google.api.http).get = "/cosmos/bank/v1beta1/supply_without_offset";
}

// SupplyOf queries the supply of a single coin.
rpc SupplyOfWithoutOffset(QuerySupplyOfWithoutOffsetRequest) returns (QuerySupplyOfWithoutOffsetResponse) {
option (cosmos.query.v1.module_query_safe) = true;
option (google.api.http).get = "/cosmos/bank/v1beta1/supply_without_offset/{denom}";
}

// Params queries the parameters of x/bank module.
rpc Params(QueryParamsRequest) returns (QueryParamsResponse) {
option (cosmos.query.v1.module_query_safe) = true;
Expand Down Expand Up @@ -277,6 +289,47 @@ message QuerySupplyOfResponse {
cosmos.base.v1beta1.Coin amount = 1 [(gogoproto.nullable) = false, (amino.dont_omitempty) = true];
}

// QueryTotalSupplyWithoutOffsetRequest is the request type for the Query/TotalSupplyWithoutOffset RPC
// method.
message QueryTotalSupplyWithoutOffsetRequest {
option (gogoproto.equal) = false;
option (gogoproto.goproto_getters) = false;

// pagination defines an optional pagination for the request.
//
// Since: cosmos-sdk 0.43
cosmos.base.query.v1beta1.PageRequest pagination = 1;
}

// QueryTotalSupplyWithoutOffsetResponse is the response type for the Query/TotalSupplyWithoutOffset RPC
// method
message QueryTotalSupplyWithoutOffsetResponse {
// supply is the supply of the coins
repeated cosmos.base.v1beta1.Coin supply = 1 [
(gogoproto.nullable) = false,
(amino.dont_omitempty) = true,
(amino.encoding) = "legacy_coins",
(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins"
];

// pagination defines the pagination in the response.
//
// Since: cosmos-sdk 0.43
cosmos.base.query.v1beta1.PageResponse pagination = 2;
}

// QuerySupplyOfWithoutOffsetRequest is the request type for the Query/SupplyOfWithoutOffset RPC method.
message QuerySupplyOfWithoutOffsetRequest {
// denom is the coin denom to query balances for.
string denom = 1;
}

// QuerySupplyOfWithoutOffsetResponse is the response type for the Query/SupplyOfWithoutOffset RPC method.
message QuerySupplyOfWithoutOffsetResponse {
// amount is the supply of the coin.
cosmos.base.v1beta1.Coin amount = 1 [(gogoproto.nullable) = false];
}

// QueryParamsRequest defines the request type for querying x/bank parameters.
message QueryParamsRequest {}

Expand Down
4 changes: 2 additions & 2 deletions tests/integration/bank/keeper/deterministic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ func TestGRPCQueryTotalSupply(t *testing.T) {
assert.NilError(t, f.bankKeeper.MintCoins(f.ctx, minttypes.ModuleName, coins))

req := &banktypes.QueryTotalSupplyRequest{}
testdata.DeterministicIterations(f.ctx, t, req, f.queryClient.TotalSupply, 150, false)
testdata.DeterministicIterations(f.ctx, t, req, f.queryClient.TotalSupply, 2174, false)
}

func TestGRPCQueryTotalSupplyOf(t *testing.T) {
Expand All @@ -293,7 +293,7 @@ func TestGRPCQueryTotalSupplyOf(t *testing.T) {

assert.NilError(t, f.bankKeeper.MintCoins(f.ctx, minttypes.ModuleName, sdk.NewCoins(coin)))
req := &banktypes.QuerySupplyOfRequest{Denom: coin.GetDenom()}
testdata.DeterministicIterations(f.ctx, t, req, f.queryClient.SupplyOf, 1021, false)
testdata.DeterministicIterations(f.ctx, t, req, f.queryClient.SupplyOf, 2033, false)
}

func TestGRPCQueryParams(t *testing.T) {
Expand Down
57 changes: 35 additions & 22 deletions tests/integration/staking/keeper/delegation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,39 +115,52 @@ func TestUnbondingDelegationsMaxEntries(t *testing.T) {
}

func TestInstantUndelegate(t *testing.T) {
_, app, ctx := createTestInput(t)
t.Parallel()
f := initFixture(t)

delAddrs := simapp.AddTestAddrsIncremental(app, ctx, 1, sdk.NewInt(10000))
valAddrs := simtestutil.ConvertAddrsToValAddrs(delAddrs)
ctx := f.sdkCtx

startTokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 10)
notBondedPool := app.StakingKeeper.GetNotBondedPool(ctx)
initTokens := f.stakingKeeper.TokensFromConsensusPower(ctx, int64(1000))
assert.NilError(t, f.bankKeeper.MintCoins(ctx, types.ModuleName, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, initTokens))))

require.NoError(t, banktestutil.FundModuleAccount(app.BankKeeper, ctx, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), startTokens))))
app.AccountKeeper.SetModuleAccount(ctx, notBondedPool)
addrDel := sdk.AccAddress([]byte("addr"))
accAmt := math.NewInt(10000)
bondDenom, err := f.stakingKeeper.BondDenom(ctx)
assert.NilError(t, err)

// create a validator and a delegator to that validator
// note this validator starts not-bonded
validator := testutil.NewValidator(t, valAddrs[0], PKs[0])
initCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, accAmt))
assert.NilError(t, f.bankKeeper.MintCoins(ctx, types.ModuleName, initCoins))
assert.NilError(t, f.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, addrDel, initCoins))
addrVal := sdk.ValAddress(addrDel)

validator, issuedShares := validator.AddTokensFromDel(startTokens)
require.Equal(t, startTokens, issuedShares.RoundInt())
startTokens := f.stakingKeeper.TokensFromConsensusPower(ctx, 10)

validator = keeper.TestingUpdateValidator(app.StakingKeeper, ctx, validator, true)
notBondedPool := f.stakingKeeper.GetNotBondedPool(ctx)

delegation := types.NewDelegation(delAddrs[0], valAddrs[0], issuedShares)
app.StakingKeeper.SetDelegation(ctx, delegation)
assert.NilError(t, banktestutil.FundModuleAccount(ctx, f.bankKeeper, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(bondDenom, startTokens))))
f.accountKeeper.SetModuleAccount(ctx, notBondedPool)

bondTokens := app.StakingKeeper.TokensFromConsensusPower(ctx, 6)
// create a validator and a delegator to that validator
validator := testutil.NewValidator(t, addrVal, PKs[0])

oldBal := app.BankKeeper.GetBalance(ctx, delAddrs[0], app.StakingKeeper.BondDenom(ctx))
validator, issuedShares := validator.AddTokensFromDel(startTokens)
assert.DeepEqual(t, startTokens, issuedShares.RoundInt())

res, err := app.StakingKeeper.InstantUndelegate(ctx, delAddrs[0], valAddrs[0], sdk.NewDecFromInt(bondTokens))
require.NoError(t, err)
validator = keeper.TestingUpdateValidator(f.stakingKeeper, ctx, validator, true)
assert.Assert(math.IntEq(t, startTokens, validator.BondedTokens()))
assert.Assert(t, validator.IsBonded())

require.Equal(t, res, sdk.NewCoins(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), bondTokens)))
delegation := types.NewDelegation(addrDel.String(), addrVal.String(), issuedShares)
assert.NilError(t, f.stakingKeeper.SetDelegation(ctx, delegation))

bondTokens := f.stakingKeeper.TokensFromConsensusPower(ctx, 6)
oldBal := f.bankKeeper.GetBalance(ctx, addrDel, bondDenom)

res, err := f.stakingKeeper.InstantUndelegate(ctx, addrDel, addrVal, math.LegacyNewDecFromInt(bondTokens))
assert.NilError(t, err)

newBal := app.BankKeeper.GetBalance(ctx, delAddrs[0], app.StakingKeeper.BondDenom(ctx))
assert.DeepEqual(t, res, sdk.NewCoins(sdk.NewCoin(bondDenom, bondTokens)))

require.Equal(t, oldBal.Add(sdk.NewCoin(app.StakingKeeper.BondDenom(ctx), bondTokens)), newBal)
newBal := f.bankKeeper.GetBalance(ctx, addrDel, bondDenom)
assert.DeepEqual(t, oldBal.Add(sdk.NewCoin(bondDenom, bondTokens)), newBal)
}
31 changes: 29 additions & 2 deletions x/bank/keeper/grpc_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ func (k BaseKeeper) SpendableBalanceByDenom(ctx context.Context, req *types.Quer
// TotalSupply implements the Query/TotalSupply gRPC method
func (k BaseKeeper) TotalSupply(ctx context.Context, req *types.QueryTotalSupplyRequest) (*types.QueryTotalSupplyResponse, error) {
sdkCtx := sdk.UnwrapSDKContext(ctx)
totalSupply, pageRes, err := k.GetPaginatedTotalSupply(sdkCtx, req.Pagination)
totalSupply, pageRes, err := k.GetPaginatedTotalSupplyWithOffsets(sdkCtx, req.Pagination)
if err != nil {
return nil, status.Error(codes.Internal, err.Error())
}
Expand All @@ -158,11 +158,38 @@ func (k BaseKeeper) SupplyOf(c context.Context, req *types.QuerySupplyOfRequest)
}

ctx := sdk.UnwrapSDKContext(c)
supply := k.GetSupply(ctx, req.Denom)
supply := k.GetSupplyWithOffset(ctx, req.Denom)

return &types.QuerySupplyOfResponse{Amount: sdk.NewCoin(req.Denom, supply.Amount)}, nil
}

// TotalSupply implements the Query/TotalSupplyWithoutOffset gRPC method
func (k BaseKeeper) TotalSupplyWithoutOffset(ctx context.Context, req *types.QueryTotalSupplyWithoutOffsetRequest) (*types.QueryTotalSupplyWithoutOffsetResponse, error) {
sdkCtx := sdk.UnwrapSDKContext(ctx)
totalSupply, pageRes, err := k.GetPaginatedTotalSupply(sdkCtx, req.Pagination)
if err != nil {
return nil, status.Error(codes.Internal, err.Error())
}

return &types.QueryTotalSupplyWithoutOffsetResponse{Supply: totalSupply, Pagination: pageRes}, nil
}

// SupplyOf implements the Query/SupplyOf gRPC method
func (k BaseKeeper) SupplyOfWithoutOffset(c context.Context, req *types.QuerySupplyOfWithoutOffsetRequest) (*types.QuerySupplyOfWithoutOffsetResponse, error) {
if req == nil {
return nil, status.Error(codes.InvalidArgument, "empty request")
}

if req.Denom == "" {
return nil, status.Error(codes.InvalidArgument, "invalid denom")
}

ctx := sdk.UnwrapSDKContext(c)
supply := k.GetSupply(ctx, req.Denom)

return &types.QuerySupplyOfWithoutOffsetResponse{Amount: sdk.NewCoin(req.Denom, supply.Amount)}, nil
}

// Params implements the gRPC service handler for querying x/bank parameters.
func (k BaseKeeper) Params(ctx context.Context, req *types.QueryParamsRequest) (*types.QueryParamsResponse, error) {
if req == nil {
Expand Down
Loading

0 comments on commit 9b55c73

Please sign in to comment.