2019-11-25 19:46:02 +00:00
|
|
|
package keeper
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
|
|
|
|
"github.com/cosmos/cosmos-sdk/codec"
|
2020-01-12 15:35:34 +00:00
|
|
|
"github.com/cosmos/cosmos-sdk/store/prefix"
|
2019-11-25 19:46:02 +00:00
|
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
|
|
"github.com/cosmos/cosmos-sdk/x/params/subspace"
|
|
|
|
"github.com/kava-labs/kava/x/cdp/types"
|
|
|
|
)
|
|
|
|
|
2020-01-12 15:35:34 +00:00
|
|
|
// Keeper keeper for the cdp module
|
2019-11-25 19:46:02 +00:00
|
|
|
type Keeper struct {
|
|
|
|
key sdk.StoreKey
|
|
|
|
cdc *codec.Codec
|
|
|
|
paramSubspace subspace.Subspace
|
|
|
|
pricefeedKeeper types.PricefeedKeeper
|
2020-01-12 15:35:34 +00:00
|
|
|
supplyKeeper types.SupplyKeeper
|
2020-01-15 14:19:33 +00:00
|
|
|
auctionKeeper types.AuctionKeeper
|
2020-01-12 15:35:34 +00:00
|
|
|
codespace sdk.CodespaceType
|
2019-11-25 19:46:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// NewKeeper creates a new keeper
|
2020-01-15 14:19:33 +00:00
|
|
|
func NewKeeper(cdc *codec.Codec, key sdk.StoreKey, paramstore subspace.Subspace, pfk types.PricefeedKeeper, ak types.AuctionKeeper, sk types.SupplyKeeper, codespace sdk.CodespaceType) Keeper {
|
2020-01-12 15:35:34 +00:00
|
|
|
|
2020-01-15 14:19:33 +00:00
|
|
|
// ensure cdp module account is set
|
2020-01-12 15:35:34 +00:00
|
|
|
if addr := sk.GetModuleAddress(types.ModuleName); addr == nil {
|
|
|
|
panic(fmt.Sprintf("%s module account has not been set", types.ModuleName))
|
|
|
|
}
|
|
|
|
|
2020-01-15 14:19:33 +00:00
|
|
|
// ensure liquidator module account is set
|
|
|
|
if addr := sk.GetModuleAddress(types.LiquidatorMacc); addr == nil {
|
|
|
|
panic(fmt.Sprintf("%s module account has not been set", types.LiquidatorMacc))
|
|
|
|
}
|
|
|
|
|
2019-11-25 19:46:02 +00:00
|
|
|
return Keeper{
|
|
|
|
key: key,
|
|
|
|
cdc: cdc,
|
|
|
|
paramSubspace: paramstore.WithKeyTable(types.ParamKeyTable()),
|
|
|
|
pricefeedKeeper: pfk,
|
2020-01-15 14:19:33 +00:00
|
|
|
auctionKeeper: ak,
|
2020-01-12 15:35:34 +00:00
|
|
|
supplyKeeper: sk,
|
|
|
|
codespace: codespace,
|
2019-11-25 19:46:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-12 15:35:34 +00:00
|
|
|
// CdpDenomIndexIterator returns an sdk.Iterator for all cdps with matching collateral denom
|
|
|
|
func (k Keeper) CdpDenomIndexIterator(ctx sdk.Context, denom string) sdk.Iterator {
|
|
|
|
store := prefix.NewStore(ctx.KVStore(k.key), types.CdpKeyPrefix)
|
|
|
|
db, _ := k.GetDenomPrefix(ctx, denom)
|
|
|
|
return sdk.KVStorePrefixIterator(store, types.DenomIterKey(db))
|
2019-11-25 19:46:02 +00:00
|
|
|
}
|
|
|
|
|
2020-01-12 15:35:34 +00:00
|
|
|
// CdpCollateralRatioIndexIterator returns an sdk.Iterator for all cdps that have collateral denom
|
|
|
|
// matching denom and collateral:debt ratio LESS THAN targetRatio
|
|
|
|
func (k Keeper) CdpCollateralRatioIndexIterator(ctx sdk.Context, denom string, targetRatio sdk.Dec) sdk.Iterator {
|
|
|
|
store := prefix.NewStore(ctx.KVStore(k.key), types.CollateralRatioIndexPrefix)
|
|
|
|
db, _ := k.GetDenomPrefix(ctx, denom)
|
|
|
|
return store.Iterator(types.CollateralRatioIterKey(db, sdk.ZeroDec()), types.CollateralRatioIterKey(db, targetRatio))
|
2019-11-25 19:46:02 +00:00
|
|
|
}
|
|
|
|
|
2020-01-12 15:35:34 +00:00
|
|
|
// IterateAllCdps iterates over all cdps and performs a callback function
|
|
|
|
func (k Keeper) IterateAllCdps(ctx sdk.Context, cb func(cdp types.CDP) (stop bool)) {
|
|
|
|
store := prefix.NewStore(ctx.KVStore(k.key), types.CdpKeyPrefix)
|
|
|
|
iterator := sdk.KVStorePrefixIterator(store, []byte{})
|
|
|
|
defer iterator.Close()
|
|
|
|
for ; iterator.Valid(); iterator.Next() {
|
2019-11-25 19:46:02 +00:00
|
|
|
var cdp types.CDP
|
2020-01-12 15:35:34 +00:00
|
|
|
k.cdc.MustUnmarshalBinaryLengthPrefixed(iterator.Value(), &cdp)
|
2019-11-25 19:46:02 +00:00
|
|
|
|
2020-01-12 15:35:34 +00:00
|
|
|
if cb(cdp) {
|
|
|
|
break
|
2019-11-25 19:46:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-12 15:35:34 +00:00
|
|
|
// IterateCdpsByDenom iterates over cdps with matching denom and performs a callback function
|
|
|
|
func (k Keeper) IterateCdpsByDenom(ctx sdk.Context, denom string, cb func(cdp types.CDP) (stop bool)) {
|
|
|
|
iterator := k.CdpDenomIndexIterator(ctx, denom)
|
2019-11-25 19:46:02 +00:00
|
|
|
|
2020-01-12 15:35:34 +00:00
|
|
|
defer iterator.Close()
|
|
|
|
for ; iterator.Valid(); iterator.Next() {
|
|
|
|
var cdp types.CDP
|
|
|
|
k.cdc.MustUnmarshalBinaryLengthPrefixed(iterator.Value(), &cdp)
|
|
|
|
if cb(cdp) {
|
|
|
|
break
|
2019-11-25 19:46:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-12 15:35:34 +00:00
|
|
|
// IterateCdpsByCollateralRatio iterate over cdps with collateral denom equal to denom and
|
|
|
|
// collateral:debt ratio LESS THAN targetRatio and performs a callback function.
|
|
|
|
func (k Keeper) IterateCdpsByCollateralRatio(ctx sdk.Context, denom string, targetRatio sdk.Dec, cb func(cdp types.CDP) (stop bool)) {
|
|
|
|
iterator := k.CdpCollateralRatioIndexIterator(ctx, denom, targetRatio)
|
|
|
|
|
|
|
|
defer iterator.Close()
|
|
|
|
for ; iterator.Valid(); iterator.Next() {
|
|
|
|
db, id, _ := types.SplitCollateralRatioKey(iterator.Key())
|
|
|
|
d := k.getDenomFromByte(ctx, db)
|
|
|
|
cdp, found := k.GetCDP(ctx, d, id)
|
|
|
|
if !found {
|
|
|
|
panic(fmt.Sprintf("cdp %d does not exist", id))
|
2019-11-25 19:46:02 +00:00
|
|
|
}
|
2020-01-12 15:35:34 +00:00
|
|
|
if cb(cdp) {
|
|
|
|
break
|
2019-11-25 19:46:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|