package keeper import ( "context" "strings" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/query" "github.com/kava-labs/kava/x/swap/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{} // Params implements the gRPC service handler for querying x/swap parameters. func (s queryServer) Params(ctx context.Context, req *types.QueryParamsRequest) (*types.QueryParamsResponse, error) { if req == nil { return nil, status.Errorf(codes.InvalidArgument, "empty request") } sdkCtx := sdk.UnwrapSDKContext(ctx) params := s.keeper.GetParams(sdkCtx) return &types.QueryParamsResponse{Params: params}, nil } // Pools implements the Query/Pools gRPC method func (s queryServer) Pools(c context.Context, req *types.QueryPoolsRequest) (*types.QueryPoolsResponse, error) { if req == nil { return nil, status.Error(codes.InvalidArgument, "empty request") } ctx := sdk.UnwrapSDKContext(c) store := prefix.NewStore(ctx.KVStore(s.keeper.key), types.PoolKeyPrefix) var queryResults []types.PoolResponse pageRes, err := query.FilteredPaginate(store, req.Pagination, func(_, value []byte, shouldAccumulate bool) (bool, error) { var poolRecord types.PoolRecord err := s.keeper.cdc.Unmarshal(value, &poolRecord) if err != nil { return false, err } if (len(req.PoolId) > 0) && strings.Compare(poolRecord.PoolID, req.PoolId) != 0 { return false, nil } if shouldAccumulate { denominatedPool, err := types.NewDenominatedPoolWithExistingShares(poolRecord.Reserves(), poolRecord.TotalShares) if err != nil { return true, types.ErrInvalidPool } totalCoins := denominatedPool.ShareValue(denominatedPool.TotalShares()) queryResult := types.PoolResponse{ Name: poolRecord.PoolID, Coins: totalCoins, TotalShares: denominatedPool.TotalShares(), } queryResults = append(queryResults, queryResult) } return true, nil }) if err != nil { return nil, status.Errorf(codes.InvalidArgument, "paginate: %v", err) } return &types.QueryPoolsResponse{ Pools: queryResults, Pagination: pageRes, }, nil } // Deposits implements the Query/Deposits gRPC method func (s queryServer) Deposits(c context.Context, req *types.QueryDepositsRequest) (*types.QueryDepositsResponse, error) { if req == nil { return nil, status.Error(codes.InvalidArgument, "empty request") } ctx := sdk.UnwrapSDKContext(c) store := prefix.NewStore(ctx.KVStore(s.keeper.key), types.DepositorPoolSharesPrefix) records := types.ShareRecords{} pageRes, err := query.FilteredPaginate( store, req.Pagination, func(key []byte, value []byte, accumulate bool) (bool, error) { var record types.ShareRecord err := s.keeper.cdc.Unmarshal(value, &record) if err != nil { return false, err } // Filter for results match the request's pool ID/owner params if given matchOwner, matchPool := true, true if len(req.Owner) > 0 { matchOwner = record.Depositor.String() == req.Owner } if len(req.PoolId) > 0 { matchPool = strings.Compare(record.PoolID, req.PoolId) == 0 } if !(matchOwner && matchPool) { // inform paginate that there was no match on this key return false, nil } if accumulate { // only add to results if paginate tells us to records = append(records, record) } // inform paginate that were was a match on this key return true, nil }, ) if err != nil { return nil, status.Error(codes.Internal, err.Error()) } var queryResults []types.DepositResponse for _, record := range records { pool, err := s.keeper.loadDenominatedPool(ctx, record.PoolID) if err != nil { return nil, err } shareValue := pool.ShareValue(record.SharesOwned) queryResult := types.DepositResponse{ Depositor: record.Depositor.String(), PoolId: record.PoolID, SharesOwned: record.SharesOwned, SharesValue: shareValue, } queryResults = append(queryResults, queryResult) } return &types.QueryDepositsResponse{ Deposits: queryResults, Pagination: pageRes, }, nil }