0g-chain/x/cdp/keeper/keeper.go
Kevin Davis d849d690e5
R4R: CDP types and methods (#275)
* wip: tpyes and keeper methods

* wip: iterators

* wip: types and keeper methods

* wip: add msgs

* wip: client methods

* wip: rebase develop

* wip: types tests

* wip: keeper tests, small fixes

* wip: add cdp tests

* wip: deposit tests

* wip: keeper tests

* wip: tests and module methods

* feat: error when fetching expired price

* feat: conversion factor for external assets

* feat: debt floor for new cdps

* feat: save deposits on export genesis

* feat: ensure messages implement msg

* feat: index deposits by status

* fix: stray comment

* wip: address review comments

* address review comments
2020-01-12 16:35:34 +01:00

104 lines
3.5 KiB
Go

package keeper
import (
"fmt"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/store/prefix"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/params/subspace"
"github.com/kava-labs/kava/x/cdp/types"
)
// Keeper keeper for the cdp module
type Keeper struct {
key sdk.StoreKey
cdc *codec.Codec
paramSubspace subspace.Subspace
pricefeedKeeper types.PricefeedKeeper
supplyKeeper types.SupplyKeeper
codespace sdk.CodespaceType
}
// NewKeeper creates a new keeper
func NewKeeper(cdc *codec.Codec, key sdk.StoreKey, paramstore subspace.Subspace, pfk types.PricefeedKeeper, sk types.SupplyKeeper, codespace sdk.CodespaceType) Keeper {
// ensure module account is set
if addr := sk.GetModuleAddress(types.ModuleName); addr == nil {
panic(fmt.Sprintf("%s module account has not been set", types.ModuleName))
}
return Keeper{
key: key,
cdc: cdc,
paramSubspace: paramstore.WithKeyTable(types.ParamKeyTable()),
pricefeedKeeper: pfk,
supplyKeeper: sk,
codespace: codespace,
}
}
// 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))
}
// 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))
}
// 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() {
var cdp types.CDP
k.cdc.MustUnmarshalBinaryLengthPrefixed(iterator.Value(), &cdp)
if cb(cdp) {
break
}
}
}
// 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)
defer iterator.Close()
for ; iterator.Valid(); iterator.Next() {
var cdp types.CDP
k.cdc.MustUnmarshalBinaryLengthPrefixed(iterator.Value(), &cdp)
if cb(cdp) {
break
}
}
}
// 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))
}
if cb(cdp) {
break
}
}
}