2019-11-25 19:46:02 +00:00
|
|
|
package keeper
|
|
|
|
|
|
|
|
import (
|
2022-01-08 00:39:27 +00:00
|
|
|
"fmt"
|
2021-10-23 18:09:59 +00:00
|
|
|
|
2020-09-17 00:45:10 +00:00
|
|
|
"github.com/cosmos/cosmos-sdk/client"
|
2019-11-25 19:46:02 +00:00
|
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
2020-04-23 16:35:58 +00:00
|
|
|
|
2019-11-25 19:46:02 +00:00
|
|
|
"github.com/kava-labs/kava/x/cdp/types"
|
|
|
|
)
|
|
|
|
|
2020-09-17 00:45:10 +00:00
|
|
|
// FilterCDPs queries the store for all CDPs that match query params
|
2022-01-08 00:39:27 +00:00
|
|
|
func FilterCDPs(ctx sdk.Context, k Keeper, params types.QueryCdpsParams) (types.AugmentedCDPs, error) {
|
2020-09-17 00:45:10 +00:00
|
|
|
var matchCollateralType, matchOwner, matchID, matchRatio types.CDPs
|
|
|
|
|
|
|
|
// match cdp owner (if supplied)
|
|
|
|
if len(params.Owner) > 0 {
|
|
|
|
denoms := k.GetCollateralTypes(ctx)
|
|
|
|
for _, denom := range denoms {
|
|
|
|
cdp, found := k.GetCdpByOwnerAndCollateralType(ctx, params.Owner, denom)
|
|
|
|
if found {
|
|
|
|
matchOwner = append(matchOwner, cdp)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// match cdp collateral denom (if supplied)
|
|
|
|
if len(params.CollateralType) > 0 {
|
|
|
|
// if owner is specified only iterate over already matched cdps for efficiency
|
|
|
|
if len(params.Owner) > 0 {
|
|
|
|
for _, cdp := range matchOwner {
|
|
|
|
if cdp.Type == params.CollateralType {
|
|
|
|
matchCollateralType = append(matchCollateralType, cdp)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2022-01-08 00:39:27 +00:00
|
|
|
_, found := k.GetCollateral(ctx, params.CollateralType)
|
|
|
|
if !found {
|
|
|
|
return nil, fmt.Errorf("invalid collateral type")
|
|
|
|
}
|
2020-09-17 00:45:10 +00:00
|
|
|
matchCollateralType = k.GetAllCdpsByCollateralType(ctx, params.CollateralType)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// match cdp ID (if supplied)
|
|
|
|
if params.ID != 0 {
|
|
|
|
denoms := k.GetCollateralTypes(ctx)
|
|
|
|
for _, denom := range denoms {
|
|
|
|
cdp, found := k.GetCDP(ctx, denom, params.ID)
|
|
|
|
if found {
|
|
|
|
matchID = append(matchID, cdp)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// match cdp ratio (if supplied)
|
2022-01-08 00:39:27 +00:00
|
|
|
if !params.Ratio.IsNil() && params.Ratio.GT(sdk.ZeroDec()) {
|
2020-09-17 00:45:10 +00:00
|
|
|
denoms := k.GetCollateralTypes(ctx)
|
|
|
|
for _, denom := range denoms {
|
|
|
|
ratio, err := k.CalculateCollateralizationRatioFromAbsoluteRatio(ctx, denom, params.Ratio, "liquidation")
|
|
|
|
if err != nil {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
cdpsUnderRatio := k.GetAllCdpsByCollateralTypeAndRatio(ctx, denom, ratio)
|
|
|
|
matchRatio = append(matchRatio, cdpsUnderRatio...)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var commonCDPs types.CDPs
|
|
|
|
// If no params specified, fetch all CDPs
|
2022-01-08 00:39:27 +00:00
|
|
|
if params.CollateralType == "" && len(params.Owner) == 0 && params.ID == 0 && params.Ratio.Equal(sdk.ZeroDec()) {
|
2020-09-17 00:45:10 +00:00
|
|
|
commonCDPs = k.GetAllCdps(ctx)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Find the intersection of any matched CDPs
|
2022-01-08 00:39:27 +00:00
|
|
|
if params.CollateralType != "" {
|
|
|
|
if len(matchCollateralType) == 0 {
|
|
|
|
return nil, nil
|
2020-09-17 00:45:10 +00:00
|
|
|
}
|
2022-01-08 00:39:27 +00:00
|
|
|
|
|
|
|
commonCDPs = matchCollateralType
|
2020-09-17 00:45:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if len(params.Owner) > 0 {
|
|
|
|
if len(matchCollateralType) > 0 {
|
|
|
|
if len(commonCDPs) > 0 {
|
|
|
|
commonCDPs = FindIntersection(commonCDPs, matchOwner)
|
|
|
|
} else {
|
|
|
|
commonCDPs = matchOwner
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
commonCDPs = matchOwner
|
|
|
|
}
|
|
|
|
}
|
2022-01-08 00:39:27 +00:00
|
|
|
|
2020-09-17 00:45:10 +00:00
|
|
|
if params.ID != 0 {
|
2022-01-08 00:39:27 +00:00
|
|
|
if len(matchID) == 0 {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(commonCDPs) > 0 {
|
|
|
|
commonCDPs = FindIntersection(commonCDPs, matchID)
|
2020-09-17 00:45:10 +00:00
|
|
|
} else {
|
2022-01-08 00:39:27 +00:00
|
|
|
commonCDPs = matchID
|
2020-09-17 00:45:10 +00:00
|
|
|
}
|
|
|
|
}
|
2022-01-08 00:39:27 +00:00
|
|
|
|
|
|
|
if !params.Ratio.IsNil() && params.Ratio.GT(sdk.ZeroDec()) {
|
|
|
|
if len(matchRatio) == 0 {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(commonCDPs) > 0 {
|
|
|
|
commonCDPs = FindIntersection(commonCDPs, matchRatio)
|
2020-09-17 00:45:10 +00:00
|
|
|
} else {
|
2022-01-08 00:39:27 +00:00
|
|
|
commonCDPs = matchRatio
|
2020-09-17 00:45:10 +00:00
|
|
|
}
|
|
|
|
}
|
2022-01-08 00:39:27 +00:00
|
|
|
|
2020-09-17 00:45:10 +00:00
|
|
|
// Load augmented CDPs
|
|
|
|
var augmentedCDPs types.AugmentedCDPs
|
|
|
|
for _, cdp := range commonCDPs {
|
|
|
|
augmentedCDP := k.LoadAugmentedCDP(ctx, cdp)
|
|
|
|
augmentedCDPs = append(augmentedCDPs, augmentedCDP)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Apply page and limit params
|
|
|
|
start, end := client.Paginate(len(augmentedCDPs), params.Page, params.Limit, 100)
|
|
|
|
if start < 0 || end < 0 {
|
2022-01-08 00:39:27 +00:00
|
|
|
return nil, nil
|
2020-09-17 00:45:10 +00:00
|
|
|
}
|
|
|
|
|
2022-01-08 00:39:27 +00:00
|
|
|
return augmentedCDPs[start:end], nil
|
2020-09-17 00:45:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// FindIntersection finds the intersection of two CDP arrays in linear time complexity O(n + n)
|
|
|
|
func FindIntersection(x types.CDPs, y types.CDPs) types.CDPs {
|
|
|
|
cdpSet := make(types.CDPs, 0)
|
|
|
|
cdpMap := make(map[uint64]bool)
|
|
|
|
|
|
|
|
for i := 0; i < len(x); i++ {
|
|
|
|
cdp := x[i]
|
|
|
|
cdpMap[cdp.ID] = true
|
|
|
|
}
|
|
|
|
|
|
|
|
for i := 0; i < len(y); i++ {
|
|
|
|
cdp := y[i]
|
|
|
|
if _, found := cdpMap[cdp.ID]; found {
|
|
|
|
cdpSet = append(cdpSet, cdp)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return cdpSet
|
|
|
|
}
|