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 Pagination to Pool With Filter Query #3563

Merged
merged 9 commits into from
Nov 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
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
3 changes: 3 additions & 0 deletions proto/osmosis/gamm/v1beta1/query.proto
Original file line number Diff line number Diff line change
Expand Up @@ -239,11 +239,14 @@ message QueryPoolsWithFilterRequest {
(gogoproto.nullable) = false
];
string pool_type = 2;
cosmos.base.query.v1beta1.PageRequest pagination = 3;
}

message QueryPoolsWithFilterResponse {
repeated google.protobuf.Any pools = 1
[ (cosmos_proto.accepts_interface) = "PoolI" ];
// pagination defines the pagination in the response.
cosmos.base.query.v1beta1.PageResponse pagination = 2;
}

// QuerySpotPriceResponse defines the gRPC response structure for a SpotPrice
Expand Down
88 changes: 28 additions & 60 deletions x/gamm/keeper/grpc_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,91 +158,59 @@ func (q Querier) CalcJoinPoolShares(ctx context.Context, req *types.QueryCalcJoi

// PoolsWithFilter query allows to query pools with specific parameters
func (q Querier) PoolsWithFilter(ctx context.Context, req *types.QueryPoolsWithFilterRequest) (*types.QueryPoolsWithFilterResponse, error) {
res, err := q.Pools(ctx, &types.QueryPoolsRequest{
Pagination: &query.PageRequest{},
})
sdkCtx := sdk.UnwrapSDKContext(ctx)

if err != nil {
return nil, err
}

pools := res.Pools
store := sdkCtx.KVStore(q.Keeper.storeKey)
poolStore := prefix.NewStore(store, types.KeyPrefixPools)

var response = []*codectypes.Any{}

// set filters
min_liquidity := req.MinLiquidity
pool_type := req.PoolType
checks_needed := 0
// increase amount of needed checks for each filter by 1
if min_liquidity != nil {
checks_needed++
}

if pool_type != "" {
checks_needed++
}

for _, p := range pools {
var checks = 0
var pool types.PoolI

err := q.cdc.UnpackAny(p, &pool)
pageRes, err := query.FilteredPaginate(poolStore, req.Pagination, func(_, value []byte, accumulate bool) (bool, error) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using FilteredPaginate instead of Paginate method allows us to iterate until pagination count has been reached

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cosmos/cosmos-sdk#12242

We can backport the fix for that to clean this up a little if we want.
(Or just copy/paste cosmos/cosmos-sdk#12253 into osmoutils)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was also checking generic pagination as well! Sad that we don't have it yet. I say we refactor this to use generic pagination later on when it gets backported and for now leave as is

pool, err := q.Keeper.UnmarshalPool(value)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where does this value as the input to UnmarshalPool come from?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It comes from the FilteredPagination method, where it iterates over the given kv store!

if err != nil {
return nil, sdkerrors.ErrUnpackAny
return false, err
}

poolId := pool.GetId()

// if liquidity specified in request
if min_liquidity != nil {
if len(req.MinLiquidity) > 0 {
poolLiquidity := pool.GetTotalPoolLiquidity(sdkCtx)
amount_of_denoms := 0
check_amount := false
check_denoms := false

if poolLiquidity.IsAllGTE(min_liquidity) {
check_amount = true
}

for _, req_coin := range min_liquidity {
for _, coin := range poolLiquidity {
if req_coin.Denom == coin.Denom {
amount_of_denoms++
}
}
}

if amount_of_denoms == len(min_liquidity) {
check_denoms = true
}

if check_amount && check_denoms {
checks++
if !poolLiquidity.IsAllGTE(req.MinLiquidity) {
return false, nil
}
}

// if pool type specified in request
if pool_type != "" {
if req.PoolType != "" {
poolType, err := q.GetPoolType(sdkCtx, poolId)
if err != nil {
return nil, types.ErrPoolNotFound
return false, types.ErrPoolNotFound
}

if poolType == pool_type {
checks++
} else {
continue
if poolType != req.PoolType {
return false, nil
}
}

if checks == checks_needed {
response = append(response, p)
any, err := codectypes.NewAnyWithValue(pool)
if err != nil {
return false, err
}

if accumulate {
response = append(response, any)
}

return true, nil
})

if err != nil {
return nil, status.Error(codes.Internal, err.Error())
}

return &types.QueryPoolsWithFilterResponse{
Pools: response,
Pools: response,
Pagination: pageRes,
}, nil
}

Expand Down
Loading