mirror of
				https://github.com/0glabs/0g-chain.git
				synced 2025-11-04 02:17:31 +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"
 | 
				
			||||||
@ -24,9 +27,11 @@ type QuerierTestSuite struct {
 | 
				
			|||||||
	suite.Suite
 | 
						suite.Suite
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	keeper          keeper.Keeper
 | 
						keeper          keeper.Keeper
 | 
				
			||||||
 | 
						pricefeedKeeper pfkeeper.Keeper
 | 
				
			||||||
	addrs           []sdk.AccAddress
 | 
						addrs           []sdk.AccAddress
 | 
				
			||||||
	app             app.TestApp
 | 
						app             app.TestApp
 | 
				
			||||||
	cdps            types.CDPs
 | 
						cdps            types.CDPs
 | 
				
			||||||
 | 
						augmentedCDPs   types.AugmentedCDPs
 | 
				
			||||||
	ctx             sdk.Context
 | 
						ctx             sdk.Context
 | 
				
			||||||
	querier         sdk.Querier
 | 
						querier         sdk.Querier
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -35,6 +40,7 @@ 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