Skip to content

Commit

Permalink
Merge pull request #520 from UnUniFi/feature/reserve-type-in-proto
Browse files Browse the repository at this point in the history
define reserve type
  • Loading branch information
kimurayu45z authored Jun 8, 2023
2 parents afb48c5 + ba65a99 commit c5744c9
Show file tree
Hide file tree
Showing 7 changed files with 399 additions and 117 deletions.
18 changes: 17 additions & 1 deletion proto/derivatives/derivatives.proto
Original file line number Diff line number Diff line change
Expand Up @@ -181,4 +181,20 @@ message EventPriceIsNotFeeded {
string asset = 1 [
(gogoproto.moretags) = "yaml:\"asset\""
];
}
}

enum MarketType {
UNKNOWN = 0;
FUTURES = 1;
OPTIONS = 2;
}

message Reserve {
MarketType market_type = 1 [
(gogoproto.moretags) = "yaml:\"market_type\""
];
cosmos.base.v1beta1.Coin amount = 2 [
(gogoproto.moretags) = "yaml:\"amount\"",
(gogoproto.nullable) = false
];
}
22 changes: 12 additions & 10 deletions x/derivatives/keeper/perpetual_futures.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,13 +93,13 @@ func (k Keeper) OpenPerpetualFuturesPosition(ctx sdk.Context, positionId string,
case types.PositionType_LONG:
k.AddPerpetualFuturesGrossPositionOfMarket(ctx, market, positionInstance.PositionType, positionInstance.SizeInDenomExponent(types.OneMillionInt))
// Reserve tokens to pay profit
if err := k.AddReserveTokensForPosition(ctx, positionInstance.SizeInDenomExponent(types.OneMillionInt), position.Market.BaseDenom); err != nil {
if err := k.AddReserveTokensForPosition(ctx, types.MarketType_FUTURES, positionInstance.SizeInDenomExponent(types.OneMillionInt), position.Market.BaseDenom); err != nil {
return nil, err
}
case types.PositionType_SHORT:
k.AddPerpetualFuturesGrossPositionOfMarket(ctx, market, positionInstance.PositionType, positionInstance.SizeInDenomExponent(types.OneMillionInt))
// Reserve tokens to pay profit
if err := k.AddReserveTokensForPosition(ctx, positionInstance.SizeInDenomExponent(types.OneMillionInt), position.Market.QuoteDenom); err != nil {
if err := k.AddReserveTokensForPosition(ctx, types.MarketType_FUTURES, positionInstance.SizeInDenomExponent(types.OneMillionInt), position.Market.QuoteDenom); err != nil {
return nil, err
}
case types.PositionType_POSITION_UNKNOWN:
Expand All @@ -116,29 +116,31 @@ func (k Keeper) OpenPerpetualFuturesPosition(ctx sdk.Context, positionId string,

// AddReserveTokensForPosition adds the tokens o the amount of the popsition size to pay the maximum profit
// in reserved property of the PoolMarketCap
func (k Keeper) AddReserveTokensForPosition(ctx sdk.Context, positionSizeInDenomExponent sdk.Int, denom string) error {
reserveOld, err := k.GetReservedCoin(ctx, denom)
func (k Keeper) AddReserveTokensForPosition(ctx sdk.Context, marketType types.MarketType, positionSizeInDenomExponent sdk.Int, denom string) error {
reserveOld, err := k.GetReservedCoin(ctx, marketType, denom)
if err != nil {
return err
}

reserveNew := reserveOld.AddAmount(positionSizeInDenomExponent)
if err := k.SetReservedCoin(ctx, reserveNew); err != nil {
reserveNew := reserveOld.Amount.AddAmount(positionSizeInDenomExponent)

if err := k.SetReservedCoin(ctx, types.NewReserve(marketType, reserveNew)); err != nil {
return err
}
return nil
}

// SubReserveTokensForPosition subtracts the tokens o the amount of the popsition size to pay the maximum profit
// in reserved property of the PoolMarketCap
func (k Keeper) SubReserveTokensForPosition(ctx sdk.Context, positionSizeInDenomExponent sdk.Int, denom string) error {
reserveOld, err := k.GetReservedCoin(ctx, denom)
func (k Keeper) SubReserveTokensForPosition(ctx sdk.Context, marketType types.MarketType, positionSizeInDenomExponent sdk.Int, denom string) error {
reserveOld, err := k.GetReservedCoin(ctx, marketType, denom)
if err != nil {
return err
}

reserveNew := reserveOld.SubAmount(positionSizeInDenomExponent)
if err := k.SetReservedCoin(ctx, reserveNew); err != nil {
reserveNew := reserveOld.Amount.SubAmount(positionSizeInDenomExponent)

if err := k.SetReservedCoin(ctx, types.NewReserve(marketType, reserveNew)); err != nil {
return err
}

Expand Down
11 changes: 6 additions & 5 deletions x/derivatives/keeper/perpetual_futures_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package keeper_test

import (
// "fmt"
"time"

"github.com/cometbft/cometbft/crypto/ed25519"
Expand Down Expand Up @@ -123,10 +124,10 @@ func (suite *KeeperTestSuite) TestAddReserveTokensForPosition() {
}

for _, tc := range testCases {
err := suite.keeper.AddReserveTokensForPosition(suite.ctx, tc.reserveCoin.Amount, tc.reserveCoin.Denom)
err := suite.keeper.AddReserveTokensForPosition(suite.ctx, types.MarketType_FUTURES, tc.reserveCoin.Amount, tc.reserveCoin.Denom)
suite.Require().NoError(err)

reserve, err := suite.keeper.GetReservedCoin(suite.ctx, tc.reserveCoin.Denom)
reserve, err := suite.keeper.GetReservedCoin(suite.ctx, types.MarketType_FUTURES, tc.reserveCoin.Denom)
suite.Require().NoError(err)
suite.Require().Equal(tc.expReserve, reserve)
}
Expand Down Expand Up @@ -154,12 +155,12 @@ func (suite *KeeperTestSuite) TestSubReserveTokensForPosition() {
}

for _, tc := range testCases {
err := suite.keeper.SetReservedCoin(suite.ctx, tc.reserveCoin)
err := suite.keeper.SetReservedCoin(suite.ctx, types.NewReserve(types.MarketType_FUTURES, tc.reserveCoin))
suite.Require().NoError(err)
err = suite.keeper.SubReserveTokensForPosition(suite.ctx, tc.subReserve.Amount, tc.subReserve.Denom)
err = suite.keeper.SubReserveTokensForPosition(suite.ctx, types.MarketType_FUTURES, tc.subReserve.Amount, tc.subReserve.Denom)
suite.Require().NoError(err)

reserve, err := suite.keeper.GetReservedCoin(suite.ctx, tc.reserveCoin.Denom)
reserve, err := suite.keeper.GetReservedCoin(suite.ctx, types.MarketType_FUTURES, tc.reserveCoin.Denom)
suite.Require().NoError(err)
suite.Require().Equal(tc.expReserve, reserve)
}
Expand Down
43 changes: 29 additions & 14 deletions x/derivatives/keeper/pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,57 +142,72 @@ func (k Keeper) IsPriceReady(ctx sdk.Context) bool {
return true
}

func (k Keeper) SetReservedCoin(ctx sdk.Context, reserve sdk.Coin) error {
func (k Keeper) SetReservedCoin(ctx sdk.Context, reserve types.Reserve) error {
bz, err := reserve.Amount.Marshal()
if err != nil {
return err
}

store := ctx.KVStore(k.storeKey)
store.Set(types.ReservedCoinKeyPrefix(reserve.Denom), bz)
store.Set(types.ReservedCoinKeyPrefix(reserve.MarketType, reserve.Amount.Denom), bz)

return nil
}

func (k Keeper) GetReservedCoin(ctx sdk.Context, denom string) (sdk.Coin, error) {
func (k Keeper) GetReservedCoin(ctx sdk.Context, marketType types.MarketType, denom string) (types.Reserve, error) {
store := ctx.KVStore(k.storeKey)

bz := store.Get(types.ReservedCoinKeyPrefix(denom))
reserveAmount := sdk.Int{}
if err := reserveAmount.Unmarshal(bz); err != nil {
return sdk.Coin{}, err
bz := store.Get(types.ReservedCoinKeyPrefix(marketType, denom))
var reserve types.Reserve

if err := k.cdc.Unmarshal(bz, &reserve); err != nil {
return types.Reserve{}, err
}

if reserveAmount.IsNil() {
reserveAmount = sdk.ZeroInt()
if reserve.Amount.Amount.IsNil() {
reserve.Amount.Amount = sdk.ZeroInt()
}

return sdk.NewCoin(denom, reserveAmount), nil
return reserve, nil
}

func (k Keeper) AvailableAssetInPool(ctx sdk.Context, denom string) (sdk.Coin, error) {
func (k Keeper) AvailableAssetInPoolWithMarketType(ctx sdk.Context, marketType types.MarketType, denom string) (sdk.Coin, error) {
assetBalance := k.GetAssetBalanceInPoolByDenom(ctx, denom)
reserve, err := k.GetReservedCoin(ctx, denom)
reserve, err := k.GetReservedCoin(ctx, marketType, denom)

if err != nil {
return sdk.Coin{}, err
}

if reserve.Amount.IsZero() {
reserve = sdk.NewCoin(denom, sdk.ZeroInt())
reserve.Amount = sdk.NewCoin(denom, sdk.ZeroInt())
}

available := assetBalance.Sub(reserve)
available := assetBalance.Sub(reserve.Amount)
return available, nil
}

func (k Keeper) AvailableAssetInPool(ctx sdk.Context, denom string) (sdk.Coin, error) {
availableInFutures, err := k.AvailableAssetInPoolWithMarketType(ctx, types.MarketType_FUTURES, denom)
availableInOptions, err := k.AvailableAssetInPoolWithMarketType(ctx, types.MarketType_OPTIONS, denom)

if err != nil {
return sdk.Coin{}, err
}

availableInTotal := availableInFutures.Add(availableInOptions)

return availableInTotal, nil
}

// AvailableAssetInPool returns the available amount of the all asset in the pool.
func (k Keeper) AllAvailableAssetsInPool(ctx sdk.Context) (sdk.Coins, error) {
assets := k.GetPoolAcceptedAssetsConf(ctx)

availableCoins := sdk.Coins{}
for _, asset := range assets {
available, err := k.AvailableAssetInPool(ctx, asset.Denom)

if err != nil {
return sdk.Coins{}, err
}
Expand Down
Loading

0 comments on commit c5744c9

Please sign in to comment.