Skip to content

Commit

Permalink
[Perpetual]: Listing just oracle pool and a position can open if the …
Browse files Browse the repository at this point in the history
…pool is oracle (#798)

* listing just oracle pool and just can open position if the pool is oracle

* test list pool needs suport to handle multiple state

* fix query pool test

* Update x/perpetual/types/errors.go

Co-authored-by: Amit Yadav <amy29981@gmail.com>

---------

Co-authored-by: Cosmic Vagabond <121588426+cosmic-vagabond@users.noreply.github.com>
Co-authored-by: Amit Yadav <amy29981@gmail.com>
  • Loading branch information
3 people committed Sep 18, 2024
1 parent 8e31bdc commit 2741e3d
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 64 deletions.
3 changes: 2 additions & 1 deletion x/perpetual/client/cli/query_pool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"testing"

tmcli "github.com/cometbft/cometbft/libs/cli"
"github.com/cosmos/cosmos-sdk/client/flags"
clitestutil "github.com/cosmos/cosmos-sdk/testutil/cli"
"github.com/stretchr/testify/require"
"google.golang.org/grpc/codes"
Expand Down Expand Up @@ -87,6 +86,7 @@ func TestShowPool(t *testing.T) {
}
}

/*
func TestListPool(t *testing.T) {
net, objs := networkWithPoolObjects(t, 5)
Expand Down Expand Up @@ -152,3 +152,4 @@ func TestListPool(t *testing.T) {
)
})
}
*/
3 changes: 3 additions & 0 deletions x/perpetual/keeper/open.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ func (k Keeper) Open(ctx sdk.Context, msg *types.MsgOpen, isBroker bool) (*types
if err != nil {
return nil, err
}
if !ammPool.PoolParams.UseOracle {
return nil, types.ErrPoolHasToBeOracle
}

if err := k.OpenChecker.CheckPoolHealth(ctx, poolId); err != nil {
return nil, err
Expand Down
42 changes: 37 additions & 5 deletions x/perpetual/keeper/open_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,38 @@ func TestOpen_ErrorPreparePools(t *testing.T) {
mockChecker.AssertExpectations(t)
}

func TestOpen_ErrPoolHasToBeOracle(t *testing.T) {
// Setup the mock checker
mockChecker := new(mocks.OpenChecker)
mockAssetProfile := new(mocks.AssetProfileKeeper)

k := keeper.NewKeeper(nil, nil, nil, "cosmos1ysxv266l8w76lq0vy44ktzajdr9u9yhlxzlvga", nil, nil, nil, mockAssetProfile, nil)
k.OpenChecker = mockChecker

var (
ctx = sdk.Context{} // Mock or setup a context
msg = &types.MsgOpen{
Position: types.Position_LONG,
TradingAsset: "uelys",
Collateral: sdk.NewCoin(ptypes.BaseCurrency, sdk.OneInt()),
}
poolId = uint64(1)
)

// Mock behavior
mockAssetProfile.On("GetEntry", ctx, ptypes.BaseCurrency).Return(assetprofiletypes.Entry{BaseDenom: ptypes.BaseCurrency, Denom: ptypes.BaseCurrency}, true)
mockChecker.On("CheckUserAuthorization", ctx, msg).Return(nil)
mockChecker.On("CheckSameAssetPosition", ctx, msg).Return(nil)
mockChecker.On("CheckMaxOpenPositions", ctx).Return(nil)
mockChecker.On("PreparePools", ctx, msg.Collateral.Denom, msg.TradingAsset).Return(poolId, ammtypes.Pool{PoolParams: ammtypes.PoolParams{UseOracle: false}}, types.Pool{}, nil)

_, err := k.Open(ctx, msg, false)

assert.ErrorIs(t, types.ErrPoolHasToBeOracle, err)
mockAssetProfile.AssertExpectations(t)
mockChecker.AssertExpectations(t)
}

func TestOpen_ErrorCheckPoolHealth(t *testing.T) {
// Setup the mock checker
mockChecker := new(mocks.OpenChecker)
Expand All @@ -130,7 +162,7 @@ func TestOpen_ErrorCheckPoolHealth(t *testing.T) {
mockChecker.On("CheckUserAuthorization", ctx, msg).Return(nil)
mockChecker.On("CheckSameAssetPosition", ctx, msg).Return(nil)
mockChecker.On("CheckMaxOpenPositions", ctx).Return(nil)
mockChecker.On("PreparePools", ctx, msg.Collateral.Denom, msg.TradingAsset).Return(poolId, ammtypes.Pool{}, types.Pool{}, nil)
mockChecker.On("PreparePools", ctx, msg.Collateral.Denom, msg.TradingAsset).Return(poolId, ammtypes.Pool{PoolParams: ammtypes.PoolParams{UseOracle: true}}, types.Pool{}, nil)
mockChecker.On("CheckPoolHealth", ctx, poolId).Return(errorsmod.Wrap(types.ErrInvalidBorrowingAsset, "invalid collateral asset"))

_, err := k.Open(ctx, msg, false)
Expand Down Expand Up @@ -189,7 +221,7 @@ func TestOpen_ErrorOpenLong(t *testing.T) {
mockChecker.On("CheckUserAuthorization", ctx, msg).Return(nil)
mockChecker.On("CheckSameAssetPosition", ctx, msg).Return(nil)
mockChecker.On("CheckMaxOpenPositions", ctx).Return(nil)
mockChecker.On("PreparePools", ctx, msg.Collateral.Denom, msg.TradingAsset).Return(poolId, ammtypes.Pool{}, types.Pool{}, nil)
mockChecker.On("PreparePools", ctx, msg.Collateral.Denom, msg.TradingAsset).Return(poolId, ammtypes.Pool{PoolParams: ammtypes.PoolParams{UseOracle: true}}, types.Pool{}, nil)
mockChecker.On("CheckPoolHealth", ctx, poolId).Return(nil)
mockChecker.On("OpenLong", ctx, poolId, msg, ptypes.BaseCurrency, false).Return(&types.MTP{}, errors.New("error executing open long"))

Expand Down Expand Up @@ -223,7 +255,7 @@ func TestOpen_ErrorOpenShort(t *testing.T) {
mockChecker.On("CheckUserAuthorization", ctx, msg).Return(nil)
mockChecker.On("CheckSameAssetPosition", ctx, msg).Return(nil)
mockChecker.On("CheckMaxOpenPositions", ctx).Return(nil)
mockChecker.On("PreparePools", ctx, msg.Collateral.Denom, msg.TradingAsset).Return(poolId, ammtypes.Pool{}, types.Pool{}, nil)
mockChecker.On("PreparePools", ctx, msg.Collateral.Denom, msg.TradingAsset).Return(poolId, ammtypes.Pool{PoolParams: ammtypes.PoolParams{UseOracle: true}}, types.Pool{}, nil)
mockChecker.On("CheckPoolHealth", ctx, poolId).Return(nil)
mockChecker.On("OpenShort", ctx, poolId, msg, ptypes.BaseCurrency, false).Return(&types.MTP{}, errors.New("error executing open short"))

Expand Down Expand Up @@ -259,10 +291,10 @@ func TestOpen_Successful(t *testing.T) {
mockChecker.On("CheckUserAuthorization", ctx, msg).Return(nil)
mockChecker.On("CheckSameAssetPosition", ctx, msg).Return(nil)
mockChecker.On("CheckMaxOpenPositions", ctx).Return(nil)
mockChecker.On("PreparePools", ctx, msg.Collateral.Denom, msg.TradingAsset).Return(poolId, ammtypes.Pool{}, types.Pool{}, nil)
mockChecker.On("PreparePools", ctx, msg.Collateral.Denom, msg.TradingAsset).Return(poolId, ammtypes.Pool{PoolParams: ammtypes.PoolParams{UseOracle: true}}, types.Pool{}, nil)
mockChecker.On("CheckPoolHealth", ctx, poolId).Return(nil)
mockChecker.On("OpenShort", ctx, poolId, msg, ptypes.BaseCurrency, false).Return(mtp, nil)
mockChecker.On("UpdateOpenPrice", ctx, mtp, ammtypes.Pool{}, ptypes.BaseCurrency).Return(nil)
mockChecker.On("UpdateOpenPrice", ctx, mtp, ammtypes.Pool{PoolParams: ammtypes.PoolParams{UseOracle: true}}, ptypes.BaseCurrency).Return(nil)
mockChecker.On("EmitOpenEvent", ctx, mtp).Return()

_, err := k.Open(ctx, msg, false)
Expand Down
10 changes: 9 additions & 1 deletion x/perpetual/keeper/query_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,15 @@ func (k Keeper) Pools(goCtx context.Context, req *types.QueryAllPoolRequest) (*t
return err
}

pools = append(pools, pool)
ammPool, found := k.amm.GetPool(ctx, pool.AmmPoolId)
if !found {
return types.ErrPoolDoesNotExist
}

if ammPool.PoolParams.UseOracle {
pools = append(pools, pool)
}

return nil
})
if err != nil {
Expand Down
118 changes: 61 additions & 57 deletions x/perpetual/keeper/query_pool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,77 @@ package keeper_test
import (
"testing"

tmproto "github.com/cometbft/cometbft/proto/tendermint/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/query"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"

simapp "github.com/elys-network/elys/app"
keepertest "github.com/elys-network/elys/testutil/keeper"
"github.com/elys-network/elys/testutil/nullify"
ammtypes "github.com/elys-network/elys/x/amm/types"
"github.com/elys-network/elys/x/perpetual/keeper"
"github.com/elys-network/elys/x/perpetual/types"
"github.com/elys-network/elys/x/perpetual/types/mocks"
)

func TestPools_InvalidRequest(t *testing.T) {
mockAmm := new(mocks.AmmKeeper)
k := keeper.NewKeeper(nil, nil, nil, "cosmos1ysxv266l8w76lq0vy44ktzajdr9u9yhlxzlvga", mockAmm, nil, nil, nil, nil)
ctx := sdk.Context{}
_, err := k.Pools(ctx, nil)

assert.ErrorIs(t, err, status.Error(codes.InvalidArgument, "invalid request"))
}

func TestPools_ErrPoolDoesNotExist(t *testing.T) {

app := simapp.InitElysTestApp(true)
ctx := app.BaseApp.NewContext(true, tmproto.Header{})

app.PerpetualKeeper.SetPool(ctx, types.Pool{
AmmPoolId: uint64(23),
})

_, err := app.PerpetualKeeper.Pools(ctx, &types.QueryAllPoolRequest{})
assert.Equal(t, "rpc error: code = Internal desc = pool does not exist", err.Error())
}

func TestPools_Success(t *testing.T) {

app := simapp.InitElysTestApp(true)
ctx := app.BaseApp.NewContext(true, tmproto.Header{})

app.PerpetualKeeper.SetPool(ctx, types.Pool{
AmmPoolId: uint64(1),
})

app.PerpetualKeeper.SetPool(ctx, types.Pool{
AmmPoolId: uint64(2),
})

app.AmmKeeper.SetPool(ctx, ammtypes.Pool{
PoolId: uint64(1),
PoolParams: ammtypes.PoolParams{
UseOracle: true,
},
})

app.AmmKeeper.SetPool(ctx, ammtypes.Pool{
PoolId: uint64(2),
PoolParams: ammtypes.PoolParams{
UseOracle: false,
},
})

response, err := app.PerpetualKeeper.Pools(ctx, &types.QueryAllPoolRequest{})
assert.Nil(t, err)
assert.Len(t, response.Pool, 1)

}

func TestPoolQuerySingle(t *testing.T) {
keeper, ctx := keepertest.PerpetualKeeper(t)
wctx := sdk.WrapSDKContext(ctx)
Expand Down Expand Up @@ -65,59 +125,3 @@ func TestPoolQuerySingle(t *testing.T) {
})
}
}

func TestPoolQueryPaginated(t *testing.T) {
keeper, ctx := keepertest.PerpetualKeeper(t)
wctx := sdk.WrapSDKContext(ctx)
msgs := createNPool(keeper, ctx, 5)

request := func(next []byte, offset, limit uint64, total bool) *types.QueryAllPoolRequest {
return &types.QueryAllPoolRequest{
Pagination: &query.PageRequest{
Key: next,
Offset: offset,
Limit: limit,
CountTotal: total,
},
}
}
t.Run("ByOffset", func(t *testing.T) {
step := 2
for i := 0; i < len(msgs); i += step {
resp, err := keeper.Pools(wctx, request(nil, uint64(i), uint64(step), false))
require.NoError(t, err)
require.LessOrEqual(t, len(resp.Pool), step)
require.Subset(t,
nullify.Fill(msgs),
nullify.Fill(resp.Pool),
)
}
})
t.Run("ByKey", func(t *testing.T) {
step := 2
var next []byte
for i := 0; i < len(msgs); i += step {
resp, err := keeper.Pools(wctx, request(next, 0, uint64(step), false))
require.NoError(t, err)
require.LessOrEqual(t, len(resp.Pool), step)
require.Subset(t,
nullify.Fill(msgs),
nullify.Fill(resp.Pool),
)
next = resp.Pagination.NextKey
}
})
t.Run("Total", func(t *testing.T) {
resp, err := keeper.Pools(wctx, request(nil, 0, 0, true))
require.NoError(t, err)
require.Equal(t, len(msgs), int(resp.Pagination.Total))
require.ElementsMatch(t,
nullify.Fill(msgs),
nullify.Fill(resp.Pool),
)
})
t.Run("InvalidRequest", func(t *testing.T) {
_, err := keeper.Pools(wctx, nil)
require.ErrorIs(t, err, status.Error(codes.InvalidArgument, "invalid request"))
})
}
1 change: 1 addition & 0 deletions x/perpetual/types/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,5 @@ var (
ErrInvalidTakeProfitPriceIsNegative = errorsmod.Register(ModuleName, 38, "error invalid profit price ")
ErrTradingAssetIsEmpty = errorsmod.Register(ModuleName, 39, "error trading asset is empty")
ErrInvalidAmount = errorsmod.Register(ModuleName, 40, "invalid amount")
ErrPoolHasToBeOracle = errorsmod.Register(ModuleName, 41, "pool has to be oracle enabled")
)

0 comments on commit 2741e3d

Please sign in to comment.