mirror of
https://github.com/0glabs/0g-chain.git
synced 2024-12-24 15:25:18 +00:00
R4R: add collateral value, collateralization ratio to CDP querier (#347)
* AugmentedCDP type, codec registration, querier update * added unique error for augmented cdp loading * added AugmentedCDPs type for cdps query res * query results for cdps (by denom) & cdps-by-ratio (by denom & ratio) * status: converting collateral value into debt coin denom * collateral value denominated in debt coin * query cdps-by-ratio now searches by collateralization ratio instead of absolute ratio * updated alias, code comments * updated querier tests * support multiple principal coins and their associated fees * collateralization ratio calculations on updated fees * include calculated fees in total debt calculation
This commit is contained in:
parent
075a3089ce
commit
bf64a5c02c
@ -28,6 +28,7 @@ const (
|
|||||||
CodeCdpNotAvailable = types.CodeCdpNotAvailable
|
CodeCdpNotAvailable = types.CodeCdpNotAvailable
|
||||||
CodeBelowDebtFloor = types.CodeBelowDebtFloor
|
CodeBelowDebtFloor = types.CodeBelowDebtFloor
|
||||||
CodePaymentExceedsDebt = types.CodePaymentExceedsDebt
|
CodePaymentExceedsDebt = types.CodePaymentExceedsDebt
|
||||||
|
CodeLoadingAugmentedCDP = types.CodeLoadingAugmentedCDP
|
||||||
EventTypeCreateCdp = types.EventTypeCreateCdp
|
EventTypeCreateCdp = types.EventTypeCreateCdp
|
||||||
EventTypeCdpDeposit = types.EventTypeCdpDeposit
|
EventTypeCdpDeposit = types.EventTypeCdpDeposit
|
||||||
EventTypeCdpDraw = types.EventTypeCdpDraw
|
EventTypeCdpDraw = types.EventTypeCdpDraw
|
||||||
@ -76,6 +77,7 @@ var (
|
|||||||
ErrCdpNotAvailable = types.ErrCdpNotAvailable
|
ErrCdpNotAvailable = types.ErrCdpNotAvailable
|
||||||
ErrBelowDebtFloor = types.ErrBelowDebtFloor
|
ErrBelowDebtFloor = types.ErrBelowDebtFloor
|
||||||
ErrPaymentExceedsDebt = types.ErrPaymentExceedsDebt
|
ErrPaymentExceedsDebt = types.ErrPaymentExceedsDebt
|
||||||
|
ErrLoadingAugmentedCDP = types.ErrLoadingAugmentedCDP
|
||||||
DefaultGenesisState = types.DefaultGenesisState
|
DefaultGenesisState = types.DefaultGenesisState
|
||||||
GetCdpIDBytes = types.GetCdpIDBytes
|
GetCdpIDBytes = types.GetCdpIDBytes
|
||||||
GetCdpIDFromBytes = types.GetCdpIDFromBytes
|
GetCdpIDFromBytes = types.GetCdpIDFromBytes
|
||||||
@ -143,6 +145,8 @@ var (
|
|||||||
type (
|
type (
|
||||||
CDP = types.CDP
|
CDP = types.CDP
|
||||||
CDPs = types.CDPs
|
CDPs = types.CDPs
|
||||||
|
AugmentedCDP = types.AugmentedCDP
|
||||||
|
AugmentedCDPs = types.AugmentedCDPs
|
||||||
Deposit = types.Deposit
|
Deposit = types.Deposit
|
||||||
Deposits = types.Deposits
|
Deposits = types.Deposits
|
||||||
SupplyKeeper = types.SupplyKeeper
|
SupplyKeeper = types.SupplyKeeper
|
||||||
|
@ -69,7 +69,7 @@ $ %s query %s cdp kava15qdefkmwswysgg4qxgqpqr35k3m49pkx2jdfnw uatom
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Decode and print results
|
// Decode and print results
|
||||||
var cdp types.CDP
|
var cdp types.AugmentedCDP
|
||||||
cdc.MustUnmarshalJSON(res, &cdp)
|
cdc.MustUnmarshalJSON(res, &cdp)
|
||||||
return cliCtx.PrintOutput(cdp)
|
return cliCtx.PrintOutput(cdp)
|
||||||
},
|
},
|
||||||
@ -105,9 +105,9 @@ $ %s query %s cdps uatom
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Decode and print results
|
// Decode and print results
|
||||||
var out types.CDPs
|
var cdps types.AugmentedCDPs
|
||||||
cdc.MustUnmarshalJSON(res, &out)
|
cdc.MustUnmarshalJSON(res, &cdps)
|
||||||
return cliCtx.PrintOutput(out)
|
return cliCtx.PrintOutput(cdps)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -119,7 +119,7 @@ func QueryCdpsByDenomAndRatioCmd(queryRoute string, cdc *codec.Codec) *cobra.Com
|
|||||||
Use: "cdps-by-ratio [collateral-name] [collateralization-ratio]",
|
Use: "cdps-by-ratio [collateral-name] [collateralization-ratio]",
|
||||||
Short: "get cdps under a collateralization ratio",
|
Short: "get cdps under a collateralization ratio",
|
||||||
Long: strings.TrimSpace(
|
Long: strings.TrimSpace(
|
||||||
fmt.Sprintf(`List all CDPs under a collateralization ratios.
|
fmt.Sprintf(`List all CDPs under a specified collateralization ratio.
|
||||||
Collateralization ratio is: collateral * price / debt.
|
Collateralization ratio is: collateral * price / debt.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
@ -150,9 +150,9 @@ $ %s query %s cdps-by-ratio uatom 1.5
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Decode and print results
|
// Decode and print results
|
||||||
var out types.CDPs
|
var cdps types.AugmentedCDPs
|
||||||
cdc.MustUnmarshalJSON(res, &out)
|
cdc.MustUnmarshalJSON(res, &cdps)
|
||||||
return cliCtx.PrintOutput(out)
|
return cliCtx.PrintOutput(cdps)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,9 @@ import (
|
|||||||
"github.com/kava-labs/kava/x/cdp/types"
|
"github.com/kava-labs/kava/x/cdp/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// BaseDigitFactor is 10**18, used during coin calculations
|
||||||
|
const BaseDigitFactor = 1000000000000000000
|
||||||
|
|
||||||
// AddCdp adds a cdp for a specific owner and collateral type
|
// AddCdp adds a cdp for a specific owner and collateral type
|
||||||
func (k Keeper) AddCdp(ctx sdk.Context, owner sdk.AccAddress, collateral sdk.Coins, principal sdk.Coins) sdk.Error {
|
func (k Keeper) AddCdp(ctx sdk.Context, owner sdk.AccAddress, collateral sdk.Coins, principal sdk.Coins) sdk.Error {
|
||||||
// validation
|
// validation
|
||||||
@ -410,6 +413,38 @@ func (k Keeper) CalculateCollateralToDebtRatio(ctx sdk.Context, collateral sdk.C
|
|||||||
return collateralBaseUnits.Quo(debtTotal)
|
return collateralBaseUnits.Quo(debtTotal)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LoadAugmentedCDP creates a new augmented CDP from an existing CDP
|
||||||
|
func (k Keeper) LoadAugmentedCDP(ctx sdk.Context, cdp types.CDP) (types.AugmentedCDP, sdk.Error) {
|
||||||
|
// calculate additional fees
|
||||||
|
periods := sdk.NewInt(ctx.BlockTime().Unix()).Sub(sdk.NewInt(cdp.FeesUpdated.Unix()))
|
||||||
|
fees := k.CalculateFees(ctx, cdp.Principal.Add(cdp.AccumulatedFees), periods, cdp.Collateral[0].Denom)
|
||||||
|
totalFees := cdp.AccumulatedFees.Add(fees)
|
||||||
|
|
||||||
|
// calculate collateralization ratio
|
||||||
|
collateralizationRatio, err := k.CalculateCollateralizationRatio(ctx, cdp.Collateral, cdp.Principal, totalFees)
|
||||||
|
if err != nil {
|
||||||
|
return types.AugmentedCDP{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// total debt is the sum of all oustanding principal and fees
|
||||||
|
var totalDebt int64
|
||||||
|
for _, principalCoin := range cdp.Principal {
|
||||||
|
totalDebt += principalCoin.Amount.Int64()
|
||||||
|
}
|
||||||
|
for _, feeCoin := range cdp.AccumulatedFees.Add(fees) {
|
||||||
|
totalDebt += feeCoin.Amount.Int64()
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert collateral value to debt coin
|
||||||
|
debtBaseAdjusted := sdk.NewDec(totalDebt).QuoInt64(BaseDigitFactor)
|
||||||
|
collateralValueInDebtDenom := collateralizationRatio.Mul(debtBaseAdjusted)
|
||||||
|
collateralValueInDebt := sdk.NewInt64Coin(cdp.Principal[0].Denom, collateralValueInDebtDenom.Int64())
|
||||||
|
|
||||||
|
// create new augmuented cdp
|
||||||
|
augmentedCDP := types.NewAugmentedCDP(cdp, collateralValueInDebt, collateralizationRatio)
|
||||||
|
return augmentedCDP, nil
|
||||||
|
}
|
||||||
|
|
||||||
// CalculateCollateralizationRatio returns the collateralization ratio of the input collateral to the input debt plus fees
|
// CalculateCollateralizationRatio returns the collateralization ratio of the input collateral to the input debt plus fees
|
||||||
func (k Keeper) CalculateCollateralizationRatio(ctx sdk.Context, collateral sdk.Coins, principal sdk.Coins, fees sdk.Coins) (sdk.Dec, sdk.Error) {
|
func (k Keeper) CalculateCollateralizationRatio(ctx sdk.Context, collateral sdk.Coins, principal sdk.Coins, fees sdk.Coins) (sdk.Dec, sdk.Error) {
|
||||||
if collateral.IsZero() {
|
if collateral.IsZero() {
|
||||||
@ -422,6 +457,7 @@ func (k Keeper) CalculateCollateralizationRatio(ctx sdk.Context, collateral sdk.
|
|||||||
}
|
}
|
||||||
collateralBaseUnits := k.convertCollateralToBaseUnits(ctx, collateral[0])
|
collateralBaseUnits := k.convertCollateralToBaseUnits(ctx, collateral[0])
|
||||||
collateralValue := collateralBaseUnits.Mul(price.Price)
|
collateralValue := collateralBaseUnits.Mul(price.Price)
|
||||||
|
|
||||||
principalTotal := sdk.ZeroDec()
|
principalTotal := sdk.ZeroDec()
|
||||||
for _, pc := range principal {
|
for _, pc := range principal {
|
||||||
prinicpalBaseUnits := k.convertDebtToBaseUnits(ctx, pc)
|
prinicpalBaseUnits := k.convertDebtToBaseUnits(ctx, pc)
|
||||||
@ -435,6 +471,19 @@ func (k Keeper) CalculateCollateralizationRatio(ctx sdk.Context, collateral sdk.
|
|||||||
return collateralRatio, nil
|
return collateralRatio, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CalculateCollateralizationRatioFromAbsoluteRatio takes a coin's denom and an absolute ratio and returns the respective collateralization ratio
|
||||||
|
func (k Keeper) CalculateCollateralizationRatioFromAbsoluteRatio(ctx sdk.Context, collateralDenom string, absoluteRatio sdk.Dec) (sdk.Dec, sdk.Error) {
|
||||||
|
// get price collateral
|
||||||
|
marketID := k.getMarketID(ctx, collateralDenom)
|
||||||
|
price, err := k.pricefeedKeeper.GetCurrentPrice(ctx, marketID)
|
||||||
|
if err != nil {
|
||||||
|
return sdk.Dec{}, err
|
||||||
|
}
|
||||||
|
// convert absolute ratio to collateralization ratio
|
||||||
|
respectiveCollateralRatio := absoluteRatio.Quo(price.Price)
|
||||||
|
return respectiveCollateralRatio, nil
|
||||||
|
}
|
||||||
|
|
||||||
// converts the input collateral to base units (ie multiplies the input by 10^(-ConversionFactor))
|
// converts the input collateral to base units (ie multiplies the input by 10^(-ConversionFactor))
|
||||||
func (k Keeper) convertCollateralToBaseUnits(ctx sdk.Context, collateral sdk.Coin) (baseUnits sdk.Dec) {
|
func (k Keeper) convertCollateralToBaseUnits(ctx sdk.Context, collateral sdk.Coin) (baseUnits sdk.Dec) {
|
||||||
cp, _ := k.GetCollateral(ctx, collateral.Denom)
|
cp, _ := k.GetCollateral(ctx, collateral.Denom)
|
||||||
|
@ -44,7 +44,12 @@ func queryGetCdp(ctx sdk.Context, req abci.RequestQuery, keeper Keeper) ([]byte,
|
|||||||
return nil, types.ErrCdpNotFound(keeper.codespace, requestParams.Owner, requestParams.CollateralDenom)
|
return nil, types.ErrCdpNotFound(keeper.codespace, requestParams.Owner, requestParams.CollateralDenom)
|
||||||
}
|
}
|
||||||
|
|
||||||
bz, err := codec.MarshalJSONIndent(keeper.cdc, cdp)
|
augmentedCDP, err := keeper.LoadAugmentedCDP(ctx, cdp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, types.ErrLoadingAugmentedCDP(keeper.codespace, cdp.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
bz, err := codec.MarshalJSONIndent(keeper.cdc, augmentedCDP)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error()))
|
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error()))
|
||||||
}
|
}
|
||||||
@ -64,8 +69,21 @@ func queryGetCdpsByRatio(ctx sdk.Context, req abci.RequestQuery, keeper Keeper)
|
|||||||
return nil, types.ErrInvalidCollateralDenom(keeper.codespace, requestParams.CollateralDenom)
|
return nil, types.ErrInvalidCollateralDenom(keeper.codespace, requestParams.CollateralDenom)
|
||||||
}
|
}
|
||||||
|
|
||||||
cdps := keeper.GetAllCdpsByDenomAndRatio(ctx, requestParams.CollateralDenom, requestParams.Ratio)
|
ratio, err := keeper.CalculateCollateralizationRatioFromAbsoluteRatio(ctx, requestParams.CollateralDenom, requestParams.Ratio)
|
||||||
bz, err := codec.MarshalJSONIndent(keeper.cdc, cdps)
|
if err != nil {
|
||||||
|
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could get collateralization ratio from absolute ratio", err.Error()))
|
||||||
|
}
|
||||||
|
|
||||||
|
cdps := keeper.GetAllCdpsByDenomAndRatio(ctx, requestParams.CollateralDenom, ratio)
|
||||||
|
// augment CDPs by adding collateral value and collateralization ratio
|
||||||
|
var augmentedCDPs types.AugmentedCDPs
|
||||||
|
for _, cdp := range cdps {
|
||||||
|
augmentedCDP, err := keeper.LoadAugmentedCDP(ctx, cdp)
|
||||||
|
if err == nil {
|
||||||
|
augmentedCDPs = append(augmentedCDPs, augmentedCDP)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bz, err := codec.MarshalJSONIndent(keeper.cdc, augmentedCDPs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error()))
|
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error()))
|
||||||
}
|
}
|
||||||
@ -85,7 +103,15 @@ func queryGetCdpsByDenom(ctx sdk.Context, req abci.RequestQuery, keeper Keeper)
|
|||||||
}
|
}
|
||||||
|
|
||||||
cdps := keeper.GetAllCdpsByDenom(ctx, requestParams.CollateralDenom)
|
cdps := keeper.GetAllCdpsByDenom(ctx, requestParams.CollateralDenom)
|
||||||
bz, err := codec.MarshalJSONIndent(keeper.cdc, cdps)
|
// augment CDPs by adding collateral value and collateralization ratio
|
||||||
|
var augmentedCDPs types.AugmentedCDPs
|
||||||
|
for _, cdp := range cdps {
|
||||||
|
augmentedCDP, err := keeper.LoadAugmentedCDP(ctx, cdp)
|
||||||
|
if err == nil {
|
||||||
|
augmentedCDPs = append(augmentedCDPs, augmentedCDP)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bz, err := codec.MarshalJSONIndent(keeper.cdc, augmentedCDPs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error()))
|
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error()))
|
||||||
}
|
}
|
||||||
|
@ -5,12 +5,15 @@ import (
|
|||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
"github.com/cosmos/cosmos-sdk/x/simulation"
|
"github.com/cosmos/cosmos-sdk/x/simulation"
|
||||||
"github.com/kava-labs/kava/app"
|
"github.com/kava-labs/kava/app"
|
||||||
"github.com/kava-labs/kava/x/cdp/keeper"
|
"github.com/kava-labs/kava/x/cdp/keeper"
|
||||||
"github.com/kava-labs/kava/x/cdp/types"
|
"github.com/kava-labs/kava/x/cdp/types"
|
||||||
|
pfkeeper "github.com/kava-labs/kava/x/pricefeed/keeper"
|
||||||
|
pftypes "github.com/kava-labs/kava/x/pricefeed/types"
|
||||||
"github.com/stretchr/testify/suite"
|
"github.com/stretchr/testify/suite"
|
||||||
abci "github.com/tendermint/tendermint/abci/types"
|
abci "github.com/tendermint/tendermint/abci/types"
|
||||||
tmtime "github.com/tendermint/tendermint/types/time"
|
tmtime "github.com/tendermint/tendermint/types/time"
|
||||||
@ -23,18 +26,21 @@ const (
|
|||||||
type QuerierTestSuite struct {
|
type QuerierTestSuite struct {
|
||||||
suite.Suite
|
suite.Suite
|
||||||
|
|
||||||
keeper keeper.Keeper
|
keeper keeper.Keeper
|
||||||
addrs []sdk.AccAddress
|
pricefeedKeeper pfkeeper.Keeper
|
||||||
app app.TestApp
|
addrs []sdk.AccAddress
|
||||||
cdps types.CDPs
|
app app.TestApp
|
||||||
ctx sdk.Context
|
cdps types.CDPs
|
||||||
querier sdk.Querier
|
augmentedCDPs types.AugmentedCDPs
|
||||||
|
ctx sdk.Context
|
||||||
|
querier sdk.Querier
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *QuerierTestSuite) SetupTest() {
|
func (suite *QuerierTestSuite) SetupTest() {
|
||||||
tApp := app.NewTestApp()
|
tApp := app.NewTestApp()
|
||||||
ctx := tApp.NewContext(true, abci.Header{Height: 1, Time: tmtime.Now()})
|
ctx := tApp.NewContext(true, abci.Header{Height: 1, Time: tmtime.Now()})
|
||||||
cdps := make(types.CDPs, 100)
|
cdps := make(types.CDPs, 100)
|
||||||
|
augmentedCDPs := make(types.AugmentedCDPs, 100)
|
||||||
_, addrs := app.GeneratePrivKeyAddressPairs(100)
|
_, addrs := app.GeneratePrivKeyAddressPairs(100)
|
||||||
coins := []sdk.Coins{}
|
coins := []sdk.Coins{}
|
||||||
|
|
||||||
@ -53,6 +59,30 @@ func (suite *QuerierTestSuite) SetupTest() {
|
|||||||
suite.ctx = ctx
|
suite.ctx = ctx
|
||||||
suite.app = tApp
|
suite.app = tApp
|
||||||
suite.keeper = tApp.GetCDPKeeper()
|
suite.keeper = tApp.GetCDPKeeper()
|
||||||
|
suite.pricefeedKeeper = tApp.GetPriceFeedKeeper()
|
||||||
|
|
||||||
|
// Set up markets
|
||||||
|
oracle := addrs[9]
|
||||||
|
marketParams := pftypes.Params{
|
||||||
|
Markets: pftypes.Markets{
|
||||||
|
pftypes.Market{MarketID: "xrp-usd", BaseAsset: "xrp", QuoteAsset: "usd", Oracles: []sdk.AccAddress{oracle}, Active: true},
|
||||||
|
pftypes.Market{MarketID: "btc-usd", BaseAsset: "btc", QuoteAsset: "usd", Oracles: []sdk.AccAddress{oracle}, Active: true},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
suite.pricefeedKeeper.SetParams(ctx, marketParams)
|
||||||
|
|
||||||
|
// Set collateral prices for use in collateralization calculations
|
||||||
|
_, err := suite.pricefeedKeeper.SetPrice(
|
||||||
|
ctx, oracle, "xrp-usd",
|
||||||
|
sdk.MustNewDecFromStr("0.75"),
|
||||||
|
time.Now().Add(1*time.Hour))
|
||||||
|
suite.Nil(err)
|
||||||
|
|
||||||
|
_, err = suite.pricefeedKeeper.SetPrice(
|
||||||
|
ctx, oracle, "btc-usd",
|
||||||
|
sdk.MustNewDecFromStr("5000"),
|
||||||
|
time.Now().Add(1*time.Hour))
|
||||||
|
suite.Nil(err)
|
||||||
|
|
||||||
for j := 0; j < 100; j++ {
|
for j := 0; j < 100; j++ {
|
||||||
collateral := "xrp"
|
collateral := "xrp"
|
||||||
@ -67,9 +97,12 @@ func (suite *QuerierTestSuite) SetupTest() {
|
|||||||
c, f := suite.keeper.GetCDP(suite.ctx, collateral, uint64(j+1))
|
c, f := suite.keeper.GetCDP(suite.ctx, collateral, uint64(j+1))
|
||||||
suite.True(f)
|
suite.True(f)
|
||||||
cdps[j] = c
|
cdps[j] = c
|
||||||
|
aCDP, _ := suite.keeper.LoadAugmentedCDP(suite.ctx, c)
|
||||||
|
augmentedCDPs[j] = aCDP
|
||||||
}
|
}
|
||||||
|
|
||||||
suite.cdps = cdps
|
suite.cdps = cdps
|
||||||
|
suite.augmentedCDPs = augmentedCDPs
|
||||||
suite.querier = keeper.NewQuerier(suite.keeper)
|
suite.querier = keeper.NewQuerier(suite.keeper)
|
||||||
suite.addrs = addrs
|
suite.addrs = addrs
|
||||||
}
|
}
|
||||||
@ -84,9 +117,9 @@ func (suite *QuerierTestSuite) TestQueryCdp() {
|
|||||||
suite.Nil(err)
|
suite.Nil(err)
|
||||||
suite.NotNil(bz)
|
suite.NotNil(bz)
|
||||||
|
|
||||||
var c types.CDP
|
var c types.AugmentedCDP
|
||||||
suite.Nil(types.ModuleCdc.UnmarshalJSON(bz, &c))
|
suite.Nil(types.ModuleCdc.UnmarshalJSON(bz, &c))
|
||||||
suite.Equal(suite.cdps[0], c)
|
suite.Equal(suite.augmentedCDPs[0], c)
|
||||||
|
|
||||||
query = abci.RequestQuery{
|
query = abci.RequestQuery{
|
||||||
Path: strings.Join([]string{custom, types.QuerierRoute, types.QueryGetCdp}, "/"),
|
Path: strings.Join([]string{custom, types.QuerierRoute, types.QueryGetCdp}, "/"),
|
||||||
@ -125,7 +158,7 @@ func (suite *QuerierTestSuite) TestQueryCdpsByDenom() {
|
|||||||
suite.Nil(err)
|
suite.Nil(err)
|
||||||
suite.NotNil(bz)
|
suite.NotNil(bz)
|
||||||
|
|
||||||
var c types.CDPs
|
var c types.AugmentedCDPs
|
||||||
suite.Nil(types.ModuleCdc.UnmarshalJSON(bz, &c))
|
suite.Nil(types.ModuleCdc.UnmarshalJSON(bz, &c))
|
||||||
suite.Equal(50, len(c))
|
suite.Equal(50, len(c))
|
||||||
|
|
||||||
@ -140,19 +173,21 @@ func (suite *QuerierTestSuite) TestQueryCdpsByDenom() {
|
|||||||
func (suite *QuerierTestSuite) TestQueryCdpsByRatio() {
|
func (suite *QuerierTestSuite) TestQueryCdpsByRatio() {
|
||||||
ratioCountBtc := 0
|
ratioCountBtc := 0
|
||||||
ratioCountXrp := 0
|
ratioCountXrp := 0
|
||||||
xrpRatio := d("50.0")
|
xrpRatio := d("2.0")
|
||||||
btcRatio := d("0.003")
|
btcRatio := d("2500")
|
||||||
expectedXrpIds := []int{}
|
expectedXrpIds := []int{}
|
||||||
expectedBtcIds := []int{}
|
expectedBtcIds := []int{}
|
||||||
for _, cdp := range suite.cdps {
|
for _, cdp := range suite.cdps {
|
||||||
r := suite.keeper.CalculateCollateralToDebtRatio(suite.ctx, cdp.Collateral, cdp.Principal)
|
absoluteRatio := suite.keeper.CalculateCollateralToDebtRatio(suite.ctx, cdp.Collateral, cdp.Principal)
|
||||||
|
collateralizationRatio, err := suite.keeper.CalculateCollateralizationRatioFromAbsoluteRatio(suite.ctx, cdp.Collateral[0].Denom, absoluteRatio)
|
||||||
|
suite.Nil(err)
|
||||||
if cdp.Collateral[0].Denom == "xrp" {
|
if cdp.Collateral[0].Denom == "xrp" {
|
||||||
if r.LT(xrpRatio) {
|
if collateralizationRatio.LT(xrpRatio) {
|
||||||
ratioCountXrp += 1
|
ratioCountXrp += 1
|
||||||
expectedXrpIds = append(expectedXrpIds, int(cdp.ID))
|
expectedXrpIds = append(expectedXrpIds, int(cdp.ID))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if r.LT(btcRatio) {
|
if collateralizationRatio.LT(btcRatio) {
|
||||||
ratioCountBtc += 1
|
ratioCountBtc += 1
|
||||||
expectedBtcIds = append(expectedBtcIds, int(cdp.ID))
|
expectedBtcIds = append(expectedBtcIds, int(cdp.ID))
|
||||||
}
|
}
|
||||||
@ -168,7 +203,7 @@ func (suite *QuerierTestSuite) TestQueryCdpsByRatio() {
|
|||||||
suite.Nil(err)
|
suite.Nil(err)
|
||||||
suite.NotNil(bz)
|
suite.NotNil(bz)
|
||||||
|
|
||||||
var c types.CDPs
|
var c types.AugmentedCDPs
|
||||||
actualXrpIds := []int{}
|
actualXrpIds := []int{}
|
||||||
suite.Nil(types.ModuleCdc.UnmarshalJSON(bz, &c))
|
suite.Nil(types.ModuleCdc.UnmarshalJSON(bz, &c))
|
||||||
for _, k := range c {
|
for _, k := range c {
|
||||||
@ -185,7 +220,7 @@ func (suite *QuerierTestSuite) TestQueryCdpsByRatio() {
|
|||||||
suite.Nil(err)
|
suite.Nil(err)
|
||||||
suite.NotNil(bz)
|
suite.NotNil(bz)
|
||||||
|
|
||||||
c = types.CDPs{}
|
c = types.AugmentedCDPs{}
|
||||||
actualBtcIds := []int{}
|
actualBtcIds := []int{}
|
||||||
suite.Nil(types.ModuleCdc.UnmarshalJSON(bz, &c))
|
suite.Nil(types.ModuleCdc.UnmarshalJSON(bz, &c))
|
||||||
for _, k := range c {
|
for _, k := range c {
|
||||||
@ -201,7 +236,7 @@ func (suite *QuerierTestSuite) TestQueryCdpsByRatio() {
|
|||||||
bz, err = suite.querier(ctx, []string{types.QueryGetCdpsByCollateralization}, query)
|
bz, err = suite.querier(ctx, []string{types.QueryGetCdpsByCollateralization}, query)
|
||||||
suite.Nil(err)
|
suite.Nil(err)
|
||||||
suite.NotNil(bz)
|
suite.NotNil(bz)
|
||||||
c = types.CDPs{}
|
c = types.AugmentedCDPs{}
|
||||||
suite.Nil(types.ModuleCdc.UnmarshalJSON(bz, &c))
|
suite.Nil(types.ModuleCdc.UnmarshalJSON(bz, &c))
|
||||||
suite.Equal(0, len(c))
|
suite.Equal(0, len(c))
|
||||||
}
|
}
|
||||||
|
@ -62,3 +62,63 @@ func (cdps CDPs) String() string {
|
|||||||
}
|
}
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AugmentedCDP provides additional information about an active CDP
|
||||||
|
type AugmentedCDP struct {
|
||||||
|
CDP `json:"cdp" yaml:"cdp"`
|
||||||
|
CollateralValue sdk.Coin `json:"collateral_value" yaml:"collateral_value"` // collateral's market value in debt coin
|
||||||
|
CollateralizationRatio sdk.Dec `json:"collateralization_ratio" yaml:"collateralization_ratio"` // current collateralization ratio
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewAugmentedCDP creates a new AugmentedCDP object
|
||||||
|
func NewAugmentedCDP(cdp CDP, collateralValue sdk.Coin, collateralizationRatio sdk.Dec) AugmentedCDP {
|
||||||
|
augmentedCDP := AugmentedCDP{
|
||||||
|
CDP: CDP{
|
||||||
|
ID: cdp.ID,
|
||||||
|
Owner: cdp.Owner,
|
||||||
|
Collateral: cdp.Collateral,
|
||||||
|
Principal: cdp.Principal,
|
||||||
|
AccumulatedFees: cdp.AccumulatedFees,
|
||||||
|
FeesUpdated: cdp.FeesUpdated,
|
||||||
|
},
|
||||||
|
CollateralValue: collateralValue,
|
||||||
|
CollateralizationRatio: collateralizationRatio,
|
||||||
|
}
|
||||||
|
return augmentedCDP
|
||||||
|
}
|
||||||
|
|
||||||
|
// String implements fmt.stringer
|
||||||
|
func (augCDP AugmentedCDP) String() string {
|
||||||
|
return strings.TrimSpace(fmt.Sprintf(`AugmentedCDP:
|
||||||
|
Owner: %s
|
||||||
|
ID: %d
|
||||||
|
Collateral Type: %s
|
||||||
|
Collateral: %s
|
||||||
|
Collateral Value: %s
|
||||||
|
Principal: %s
|
||||||
|
Fees: %s
|
||||||
|
Fees Last Updated: %s
|
||||||
|
Collateralization ratio: %s`,
|
||||||
|
augCDP.Owner,
|
||||||
|
augCDP.ID,
|
||||||
|
augCDP.Collateral[0].Denom,
|
||||||
|
augCDP.Collateral,
|
||||||
|
augCDP.CollateralValue,
|
||||||
|
augCDP.Principal,
|
||||||
|
augCDP.AccumulatedFees,
|
||||||
|
augCDP.FeesUpdated,
|
||||||
|
augCDP.CollateralizationRatio,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
// AugmentedCDPs a collection of AugmentedCDP objects
|
||||||
|
type AugmentedCDPs []AugmentedCDP
|
||||||
|
|
||||||
|
// String implements stringer
|
||||||
|
func (augcdps AugmentedCDPs) String() string {
|
||||||
|
out := ""
|
||||||
|
for _, augcdp := range augcdps {
|
||||||
|
out += augcdp.String() + "\n"
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
@ -26,6 +26,7 @@ const (
|
|||||||
CodeCdpNotAvailable sdk.CodeType = 14
|
CodeCdpNotAvailable sdk.CodeType = 14
|
||||||
CodeBelowDebtFloor sdk.CodeType = 15
|
CodeBelowDebtFloor sdk.CodeType = 15
|
||||||
CodePaymentExceedsDebt sdk.CodeType = 16
|
CodePaymentExceedsDebt sdk.CodeType = 16
|
||||||
|
CodeLoadingAugmentedCDP sdk.CodeType = 17
|
||||||
)
|
)
|
||||||
|
|
||||||
// ErrCdpAlreadyExists error for duplicate cdps
|
// ErrCdpAlreadyExists error for duplicate cdps
|
||||||
@ -107,3 +108,8 @@ func ErrBelowDebtFloor(codespace sdk.CodespaceType, debt sdk.Coins, floor sdk.In
|
|||||||
func ErrPaymentExceedsDebt(codespace sdk.CodespaceType, payment sdk.Coins, principal sdk.Coins) sdk.Error {
|
func ErrPaymentExceedsDebt(codespace sdk.CodespaceType, payment sdk.Coins, principal sdk.Coins) sdk.Error {
|
||||||
return sdk.NewError(codespace, CodePaymentExceedsDebt, fmt.Sprintf("payment of %s exceeds debt of %s", payment, principal))
|
return sdk.NewError(codespace, CodePaymentExceedsDebt, fmt.Sprintf("payment of %s exceeds debt of %s", payment, principal))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ErrLoadingAugmentedCDP error loading augmented cdp
|
||||||
|
func ErrLoadingAugmentedCDP(codespace sdk.CodespaceType, cdpID uint64) sdk.Error {
|
||||||
|
return sdk.NewError(codespace, CodeCdpNotFound, fmt.Sprintf("augmented cdp could not be loaded from cdp id %d", cdpID))
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user