Skip to content

Commit

Permalink
feat(tradeshield): lock order amount when creating an order (#983)
Browse files Browse the repository at this point in the history
  • Loading branch information
cosmic-vagabond authored Nov 21, 2024
1 parent d974e53 commit 6215e5d
Show file tree
Hide file tree
Showing 28 changed files with 334 additions and 106 deletions.
1 change: 1 addition & 0 deletions app/keepers/keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,7 @@ func NewAppKeeper(
appCodec,
runtime.NewKVStoreService(app.keys[tradeshieldmoduletypes.StoreKey]),
authtypes.NewModuleAddress(govtypes.ModuleName).String(),
app.BankKeeper,
app.AmmKeeper,
app.TierKeeper,
app.PerpetualKeeper,
Expand Down
6 changes: 4 additions & 2 deletions testutil/keeper/tradeshield.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (
"github.com/stretchr/testify/require"
)

func TradeshieldKeeper(t testing.TB) (*keeper.Keeper, sdk.Context, *mocks.AmmKeeper, *mocks.TierKeeper, *mocks.PerpetualKeeper) {
func TradeshieldKeeper(t testing.TB) (*keeper.Keeper, sdk.Context, *mocks.BankKeeper, *mocks.AmmKeeper, *mocks.TierKeeper, *mocks.PerpetualKeeper) {
storeKey := storetypes.NewKVStoreKey(types.StoreKey)
storeService := runtime.NewKVStoreService(storeKey)

Expand All @@ -34,13 +34,15 @@ func TradeshieldKeeper(t testing.TB) (*keeper.Keeper, sdk.Context, *mocks.AmmKee
cdc := codec.NewProtoCodec(registry)
govAddress := sdk.AccAddress(address.Module("gov"))

bankKeeper := mocks.NewBankKeeper(t)
ammKeeper := mocks.NewAmmKeeper(t)
tierKeeper := mocks.NewTierKeeper(t)
perpetualKeeper := mocks.NewPerpetualKeeper(t)
k := keeper.NewKeeper(
cdc,
storeService,
govAddress.String(),
bankKeeper,
ammKeeper,
tierKeeper,
perpetualKeeper,
Expand All @@ -52,5 +54,5 @@ func TradeshieldKeeper(t testing.TB) (*keeper.Keeper, sdk.Context, *mocks.AmmKee
params := types.DefaultParams()
k.SetParams(ctx, &params)

return k, ctx, ammKeeper, tierKeeper, perpetualKeeper
return k, ctx, bankKeeper, ammKeeper, tierKeeper, perpetualKeeper
}
2 changes: 1 addition & 1 deletion x/accountedpool/types/mocks/amm_keeper.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion x/accountedpool/types/mocks/bank_keeper.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion x/accountedpool/types/mocks/perpetual_keeper.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion x/amm/types/mocks/accounted_pool_keeper.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion x/amm/types/mocks/oracle_keeper.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion x/burner/types/mocks/bank_keeper.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion x/leveragelp/types/mocks/bank_keeper.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion x/tradeshield/genesis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func TestGenesis(t *testing.T) {
// this line is used by starport scaffolding # genesis/test/state
}

k, ctx, _, _, _ := keepertest.TradeshieldKeeper(t)
k, ctx, _, _, _, _ := keepertest.TradeshieldKeeper(t)
tradeshield.InitGenesis(ctx, *k, genesisState)
got := tradeshield.ExportGenesis(ctx, *k)
require.NotNil(t, got)
Expand Down
3 changes: 3 additions & 0 deletions x/tradeshield/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ type (
cdc codec.BinaryCodec
storeService store.KVStoreService
authority string
bank types.BankKeeper
amm types.AmmKeeper
tier types.TierKeeper
perpetual types.PerpetualKeeper
Expand All @@ -27,6 +28,7 @@ func NewKeeper(
cdc codec.BinaryCodec,
storeService store.KVStoreService,
authority string,
bank types.BankKeeper,
amm types.AmmKeeper,
tier types.TierKeeper,
perpetual types.PerpetualKeeper,
Expand All @@ -35,6 +37,7 @@ func NewKeeper(
cdc: cdc,
storeService: storeService,
authority: authority,
bank: bank,
amm: amm,
tier: tier,
perpetual: perpetual,
Expand Down
20 changes: 19 additions & 1 deletion x/tradeshield/keeper/msg_server_perpetual_order.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,18 @@ func (k msgServer) CreatePerpetualOpenOrder(goCtx context.Context, msg *types.Ms
return nil, err
}

// set the order id
pendingPerpetualOrder.OrderId = id

// send collateral amount from owner to the order address
ownerAddress := sdk.MustAccAddressFromBech32(pendingPerpetualOrder.OwnerAddress)
err = k.Keeper.bank.SendCoins(ctx, ownerAddress, pendingPerpetualOrder.GetOrderAddress(), sdk.NewCoins(pendingPerpetualOrder.Collateral))
if err != nil {
return nil, err
}

return &types.MsgCreatePerpetualOpenOrderResponse{
OrderId: id,
OrderId: pendingPerpetualOrder.OrderId,
}, nil
}

Expand Down Expand Up @@ -134,6 +144,7 @@ func (k msgServer) UpdatePerpetualOrder(goCtx context.Context, msg *types.MsgUpd
return nil, errorsmod.Wrap(sdkerrors.ErrUnauthorized, "incorrect owner")
}

// update the order
order.TriggerPrice = msg.TriggerPrice
k.SetPendingPerpetualOrder(ctx, order)

Expand All @@ -154,6 +165,13 @@ func (k msgServer) CancelPerpetualOrder(goCtx context.Context, msg *types.MsgCan
return nil, errorsmod.Wrap(sdkerrors.ErrUnauthorized, "incorrect owner")
}

// send the collateral amount back to the owner
ownerAddress := sdk.MustAccAddressFromBech32(order.OwnerAddress)
err := k.Keeper.bank.SendCoins(ctx, order.GetOrderAddress(), ownerAddress, sdk.NewCoins(order.Collateral))
if err != nil {
return nil, err
}

k.RemovePendingPerpetualOrder(ctx, msg.OrderId)
types.EmitCancelPerpetualOrderEvent(ctx, order)

Expand Down
39 changes: 37 additions & 2 deletions x/tradeshield/keeper/msg_server_spot_order.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package keeper

import (
"context"

errorsmod "cosmossdk.io/errors"

sdk "github.com/cosmos/cosmos-sdk/types"
Expand Down Expand Up @@ -31,18 +32,45 @@ func (k msgServer) CreateSpotOrder(goCtx context.Context, msg *types.MsgCreateSp
return &types.MsgCreateSpotOrderResponse{}, nil
}

// add the order to the pending orders
id := k.AppendPendingSpotOrder(
ctx,
pendingSpotOrder,
)

// set the order id
pendingSpotOrder.OrderId = id

// send order amount from owner to the order address
ownerAddress := sdk.MustAccAddressFromBech32(pendingSpotOrder.OwnerAddress)
err := k.Keeper.bank.SendCoins(ctx, ownerAddress, pendingSpotOrder.GetOrderAddress(), sdk.NewCoins(pendingSpotOrder.OrderAmount))
if err != nil {
return nil, err
}

// return the order id
return &types.MsgCreateSpotOrderResponse{
OrderId: id,
OrderId: pendingSpotOrder.OrderId,
}, nil
}

func (k msgServer) UpdateSpotOrder(goCtx context.Context, msg *types.MsgUpdateSpotOrder) (*types.MsgUpdateSpotOrderResponse, error) {
// _ := sdk.UnwrapSDKContext(goCtx)
ctx := sdk.UnwrapSDKContext(goCtx)

// Checks that the element exists
order, found := k.GetPendingSpotOrder(ctx, msg.OrderId)
if !found {
return nil, types.ErrSpotOrderNotFound
}

// Checks if the the msg creator is the same as the current owner
if msg.OwnerAddress != order.OwnerAddress {
return nil, errorsmod.Wrap(sdkerrors.ErrUnauthorized, "incorrect owner")
}

// update the order
order.OrderPrice = msg.OrderPrice
k.SetPendingSpotOrder(ctx, order)

return &types.MsgUpdateSpotOrderResponse{}, nil
}
Expand All @@ -60,6 +88,13 @@ func (k msgServer) CancelSpotOrder(goCtx context.Context, msg *types.MsgCancelSp
return nil, errorsmod.Wrap(sdkerrors.ErrUnauthorized, "incorrect owner")
}

// send the order amount back to the owner
ownerAddress := sdk.MustAccAddressFromBech32(spotOrder.OwnerAddress)
err := k.Keeper.bank.SendCoins(ctx, spotOrder.GetOrderAddress(), ownerAddress, sdk.NewCoins(spotOrder.OrderAmount))
if err != nil {
return nil, err
}

k.RemovePendingSpotOrder(ctx, msg.OrderId)
types.EmitCloseSpotOrderEvent(ctx, spotOrder)

Expand Down
2 changes: 1 addition & 1 deletion x/tradeshield/keeper/msg_server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
)

func setupMsgServer(t testing.TB) (types.MsgServer, context.Context) {
k, ctx, _, _, _ := keepertest.TradeshieldKeeper(t)
k, ctx, _, _, _, _ := keepertest.TradeshieldKeeper(t)
return keeper.NewMsgServerImpl(*k), ctx
}

Expand Down
2 changes: 1 addition & 1 deletion x/tradeshield/keeper/params_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
)

func TestGetParams(t *testing.T) {
k, ctx, _, _, _ := testkeeper.TradeshieldKeeper(t)
k, ctx, _, _, _, _ := testkeeper.TradeshieldKeeper(t)
params := types.DefaultParams()

k.SetParams(ctx, &params)
Expand Down
112 changes: 43 additions & 69 deletions x/tradeshield/keeper/pending_perpetual_order.go
Original file line number Diff line number Diff line change
Expand Up @@ -201,55 +201,43 @@ func (k Keeper) ExecuteLimitOpenOrder(ctx sdk.Context, order types.PerpetualOrde
return err
}

found := false

switch order.Position {
case types.PerpetualPosition_LONG:
if marketPrice.LTE(order.TriggerPrice.Rate) {
_, err = k.perpetual.Open(ctx, &perpetualtypes.MsgOpen{
Creator: order.OwnerAddress,
Position: perpetualtypes.Position(order.Position),
Leverage: order.Leverage,
TradingAsset: order.TradingAsset,
Collateral: order.Collateral,
TakeProfitPrice: order.TakeProfitPrice,
StopLossPrice: order.StopLossPrice,
PoolId: order.PoolId,
})
if err != nil {
return err
}

found = true
if marketPrice.GT(order.TriggerPrice.Rate) {
// skip the order
return nil
}
case types.PerpetualPosition_SHORT:
if marketPrice.GTE(order.TriggerPrice.Rate) {
_, err = k.perpetual.Open(ctx, &perpetualtypes.MsgOpen{
Creator: order.OwnerAddress,
Position: perpetualtypes.Position(order.Position),
Leverage: order.Leverage,
TradingAsset: order.TradingAsset,
Collateral: order.Collateral,
TakeProfitPrice: order.TakeProfitPrice,
StopLossPrice: order.StopLossPrice,
PoolId: order.PoolId,
})
if err != nil {
return err
}

found = true
if marketPrice.LT(order.TriggerPrice.Rate) {
// skip the order
return nil
}
}

if found {
// Remove the order from the pending order list
k.RemovePendingPerpetualOrder(ctx, order.OrderId)
// send the collateral amount back to the owner
ownerAddress := sdk.MustAccAddressFromBech32(order.OwnerAddress)
err = k.bank.SendCoins(ctx, order.GetOrderAddress(), ownerAddress, sdk.NewCoins(order.Collateral))
if err != nil {
return err
}

return nil
_, err = k.perpetual.Open(ctx, &perpetualtypes.MsgOpen{
Creator: order.OwnerAddress,
Position: perpetualtypes.Position(order.Position),
Leverage: order.Leverage,
TradingAsset: order.TradingAsset,
Collateral: order.Collateral,
TakeProfitPrice: order.TakeProfitPrice,
StopLossPrice: order.StopLossPrice,
PoolId: order.PoolId,
})
if err != nil {
return err
}

// skip the order
// Remove the order from the pending order list
k.RemovePendingPerpetualOrder(ctx, order.OrderId)

return nil
}

Expand All @@ -260,45 +248,31 @@ func (k Keeper) ExecuteLimitCloseOrder(ctx sdk.Context, order types.PerpetualOrd
return err
}

found := false

switch order.Position {
case types.PerpetualPosition_LONG:
if marketPrice.GTE(order.TriggerPrice.Rate) {
_, err := k.perpetual.Close(ctx, &perpetualtypes.MsgClose{
Creator: order.OwnerAddress,
Id: order.PositionId,
Amount: sdkmath.ZeroInt(),
})
if err != nil {
return err
}

found = true
if marketPrice.LT(order.TriggerPrice.Rate) {
// skip the order
return nil
}
case types.PerpetualPosition_SHORT:
if marketPrice.LTE(order.TriggerPrice.Rate) {
_, err := k.perpetual.Close(ctx, &perpetualtypes.MsgClose{
Creator: order.OwnerAddress,
Id: order.PositionId,
Amount: sdkmath.ZeroInt(),
})
if err != nil {
return err
}

found = true
if marketPrice.GT(order.TriggerPrice.Rate) {
// skip the order
return nil
}
}

if found {
// Remove the order from the pending order list
k.RemovePendingPerpetualOrder(ctx, order.OrderId)

return nil
_, err = k.perpetual.Close(ctx, &perpetualtypes.MsgClose{
Creator: order.OwnerAddress,
Id: order.PositionId,
Amount: sdkmath.ZeroInt(),
})
if err != nil {
return err
}

// skip the order
// Remove the order from the pending order list
k.RemovePendingPerpetualOrder(ctx, order.OrderId)

return nil
}

Expand Down
Loading

0 comments on commit 6215e5d

Please sign in to comment.