Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add topN endpoint to supply module (disabled by default) #1800

Merged
merged 17 commits into from
Jan 30, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions proto/quicksilver/supply/v1/query.proto
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
syntax = "proto3";
package quicksilver.supply.v1;

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

option go_package = "github.com/quicksilver-zone/quicksilver/x/supply/types";
Expand All @@ -11,10 +14,30 @@ service Query {
rpc Supply(QuerySupplyRequest) returns (QuerySupplyResponse) {
option (google.api.http).get = "/quicksilver/supply/v1/supply";
}

rpc TopN(QueryTopNRequest) returns (QueryTopNResponse) {
option (google.api.http).get = "/quicksilver/supply/v1/topn/{n}";
}
}

message QuerySupplyRequest {}
message QuerySupplyResponse {
uint64 supply = 1;
uint64 circulating_supply = 2;
}

message Account {
string address = 1;
string balance = 2 [
(cosmos_proto.scalar) = "cosmos.Int",
(gogoproto.customtype) = "cosmossdk.io/math.Int",
(gogoproto.nullable) = false
];
}

message QueryTopNRequest {
uint64 n = 1;
}
message QueryTopNResponse {
repeated Account accounts = 1;
}
12 changes: 12 additions & 0 deletions x/supply/keeper/grpc_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,15 @@
}
return nil, fmt.Errorf("endpoint disabled")
}

func (q Querier) TopN(c context.Context, req *types.QueryTopNRequest) (*types.QueryTopNResponse, error) {
ctx := sdk.UnwrapSDKContext(c)

if q.endpointEnabled {

accounts := q.Keeper.TopN(ctx, q.stakingKeeper.BondDenom(ctx), int(req.N))

Check failure on line 53 in x/supply/keeper/grpc_query.go

View workflow job for this annotation

GitHub Actions / lint

G115: integer overflow conversion uint64 -> int (gosec)

return &types.QueryTopNResponse{Accounts: accounts}, nil
}
return nil, fmt.Errorf("endpoint disabled")
}
41 changes: 41 additions & 0 deletions x/supply/keeper/keeper.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package keeper

import (
"sort"

"github.com/tendermint/tendermint/libs/log"

"cosmossdk.io/math"
Expand Down Expand Up @@ -79,3 +81,42 @@ func (k Keeper) CalculateCirculatingSupply(ctx sdk.Context, baseDenom string, ex

return k.bankKeeper.GetSupply(ctx, baseDenom).Amount.Sub(nonCirculating)
}

func (k Keeper) TopN(ctx sdk.Context, baseDenom string, n int) []*types.Account {
accountMap := map[string]math.Int{}

modMap := map[string]bool{}

for _, mod := range k.moduleAccounts {
modMap[k.accountKeeper.GetModuleAddress(mod).String()] = true
}

k.accountKeeper.IterateAccounts(ctx, func(account authtypes.AccountI) (stop bool) {
if modMap[account.GetAddress().String()] {
return false
}
balance := k.bankKeeper.GetBalance(ctx, account.GetAddress(), baseDenom).Amount
accountMap[account.GetAddress().String()] = balance
return false
})

k.stakingKeeper.IterateAllDelegations(ctx, func(delegation stakingtypes.Delegation) (stop bool) {
if modMap[delegation.GetDelegatorAddr().String()] {
return false
}
balance := delegation.GetShares().TruncateInt()
accountMap[delegation.GetDelegatorAddr().String()] = accountMap[delegation.GetDelegatorAddr().String()].Add(balance)
return false
})

accountSlice := []*types.Account{}
for addr, balance := range accountMap {
accountSlice = append(accountSlice, &types.Account{Address: addr, Balance: balance})
}

sort.Slice(accountSlice, func(i, j int) bool {
return accountSlice[i].Balance.GT(accountSlice[j].Balance)
})

return accountSlice[:n]
}
2 changes: 2 additions & 0 deletions x/supply/types/expected_keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package types // noalias
import (
sdk "github.com/cosmos/cosmos-sdk/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
)

// AccountKeeper defines the contract required for account APIs.
Expand All @@ -21,4 +22,5 @@ type BankKeeper interface {

type StakingKeeper interface {
BondDenom(ctx sdk.Context) string
IterateAllDelegations(ctx sdk.Context, cb func(delegation stakingtypes.Delegation) (stop bool))
}
Loading
Loading