Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: create settle position function #1632

Merged
merged 12 commits into from
Oct 18, 2023
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* [#1607](https://github.com/NibiruChain/nibiru/pull/1607) - Token factory transaction messages for CreateDenom, ChangeAdmin, and UpdateModuleParams
* [#1620](https://github.com/NibiruChain/nibiru/pull/1620) - Token factory transaction messages for Mint and Burn
* [#1573](https://github.com/NibiruChain/nibiru/pull/1573) - feat(perp): Close markets and compute settlement price
* [#1632](https://github.com/NibiruChain/nibiru/pull/1632) - feat(perp): Add settle position transaction

### State Machine Breaking

Expand Down
17 changes: 17 additions & 0 deletions proto/nibiru/perp/v2/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,27 @@ service Msg {

rpc PartialClose(MsgPartialClose) returns (MsgPartialCloseResponse) {}

rpc SettlePosition(MsgSettlePosition) returns (MsgClosePositionResponse) {}

rpc DonateToEcosystemFund(MsgDonateToEcosystemFund)
returns (MsgDonateToEcosystemFundResponse) {}
}

// -------------------------- Settle Position --------------------------

/* MsgSettlePosition: Msg to remove margin. */
message MsgSettlePosition {
string sender = 1;

string pair = 2 [
(gogoproto.customtype) =
"github.com/NibiruChain/nibiru/x/common/asset.Pair",
(gogoproto.nullable) = false
];

uint64 version = 3;
}

// -------------------------- RemoveMargin --------------------------

/* MsgRemoveMargin: Msg to remove margin. */
Expand Down
2 changes: 0 additions & 2 deletions x/perp/v2/client/cli/gen_market.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,6 @@ func newMarketFromFlags(flagSet *flag.FlagSet,
return types.Market{}, types.AMM{}, err
}

fmt.Println(maxFundingRate)

priceMultiplier, err := sdk.NewDecFromStr(priceMultiplierStr)
if err != nil {
return types.Market{}, types.AMM{}, err
Expand Down
46 changes: 46 additions & 0 deletions x/perp/v2/client/cli/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package cli

import (
"fmt"
"strconv"
"strings"

"github.com/cosmos/cosmos-sdk/client"
Expand Down Expand Up @@ -29,6 +30,7 @@ func GetTxCmd() *cobra.Command {
AddMarginCmd(),
MarketOrderCmd(),
ClosePositionCmd(),
SettlePositionCmd(),
PartialCloseCmd(),
MultiLiquidateCmd(),
DonateToEcosystemFundCmd(),
Expand Down Expand Up @@ -315,6 +317,50 @@ func AddMarginCmd() *cobra.Command {
return cmd
}

func SettlePositionCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "settle [market] [version]",
Short: "Settle position in a specific market version when the market is disabled",
Long: strings.TrimSpace(
fmt.Sprintf(`
$ %s tx perp settle osmo:nusd 1
`, version.AppName),
),
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}

version, err := strconv.ParseUint(args[1], 10, 64)
if err != nil {
return err
}

pair, err := asset.TryNewPair(args[0])
if err != nil {
return err
}

msg := &types.MsgSettlePosition{
Sender: clientCtx.GetFromAddress().String(),
Pair: pair,
Version: version,
}
if err = msg.ValidateBasic(); err != nil {
return err
}

return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
},
}

flags.AddTxFlagsToCmd(cmd)

return cmd
}

func DonateToEcosystemFundCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "donate-ef [amount]",
Expand Down
5 changes: 1 addition & 4 deletions x/perp/v2/integration/action/market.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package action

import (
"fmt"

sdkmath "cosmossdk.io/math"
sdk "github.com/cosmos/cosmos-sdk/types"

Expand All @@ -21,7 +19,6 @@ type logger struct {
}

func (e logger) Do(_ *app.NibiruApp, ctx sdk.Context) (sdk.Context, error, bool) {
fmt.Println(e.log)
return ctx, nil, true
}

Expand All @@ -38,7 +35,7 @@ type createMarketAction struct {
}

func (c createMarketAction) Do(app *app.NibiruApp, ctx sdk.Context) (sdk.Context, error, bool) {
app.PerpKeeperV2.MarketLastVersion.Insert(ctx, c.Market.Pair, types.MarketLastVersion{Version: 1})
app.PerpKeeperV2.MarketLastVersion.Insert(ctx, c.Market.Pair, types.MarketLastVersion{Version: c.Market.Version})
app.PerpKeeperV2.SaveMarket(ctx, c.Market)
app.PerpKeeperV2.SaveAMM(ctx, c.AMM)

Expand Down
97 changes: 97 additions & 0 deletions x/perp/v2/integration/action/settlement.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
package action

import (
"fmt"

sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/NibiruChain/nibiru/app"
"github.com/NibiruChain/nibiru/x/common/asset"
"github.com/NibiruChain/nibiru/x/common/testutil/action"
"github.com/NibiruChain/nibiru/x/perp/v2/types"
)

// closeMarket
type closeMarket struct {
pair asset.Pair
}
Expand All @@ -24,3 +28,96 @@ func (c closeMarket) Do(app *app.NibiruApp, ctx sdk.Context) (sdk.Context, error
func CloseMarket(pair asset.Pair) action.Action {
return closeMarket{pair: pair}
}

// closeMarketShouldFail
type closeMarketShouldFail struct {
pair asset.Pair
}

func (c closeMarketShouldFail) Do(app *app.NibiruApp, ctx sdk.Context) (sdk.Context, error, bool) {
err := app.PerpKeeperV2.CloseMarket(ctx, c.pair)
if err == nil {
return ctx, err, false
}

return ctx, nil, true
}

func CloseMarketShouldFail(pair asset.Pair) action.Action {
return closeMarketShouldFail{pair: pair}
}

// settlePosition
type settlePosition struct {
pair asset.Pair
version uint64
trader sdk.AccAddress
responseCheckers []SettlePositionChecker
}

func (c settlePosition) Do(app *app.NibiruApp, ctx sdk.Context) (sdk.Context, error, bool) {
resp, err := app.PerpKeeperV2.SettlePosition(ctx, c.pair, c.version, c.trader)
if err != nil {
return ctx, err, false
}

for _, checker := range c.responseCheckers {
if err := checker(*resp); err != nil {
return ctx, err, false
}
}

return ctx, nil, true
}

func SettlePosition(pair asset.Pair, version uint64, trader sdk.AccAddress, responseCheckers ...SettlePositionChecker) action.Action {
return settlePosition{pair: pair, version: version, trader: trader, responseCheckers: responseCheckers}
}

type SettlePositionChecker func(resp types.PositionResp) error

func SettlePositionChecker_PositionEquals(expected types.Position) SettlePositionChecker {
return func(resp types.PositionResp) error {
return types.PositionsAreEqual(&expected, &resp.Position)
}
}

func SettlePositionChecker_MarginToVault(expectedMarginToVault sdk.Dec) SettlePositionChecker {
return func(resp types.PositionResp) error {
if expectedMarginToVault.Equal(resp.MarginToVault) {
return nil
} else {
return fmt.Errorf("expected margin to vault %s, got %s", expectedMarginToVault, resp.MarginToVault)
}
}
}

func SettlePositionChecker_BadDebt(expectedBadDebt sdk.Dec) SettlePositionChecker {
return func(resp types.PositionResp) error {
if expectedBadDebt.Equal(resp.BadDebt) {
return nil
} else {
return fmt.Errorf("expected bad debt %s, got %s", expectedBadDebt, resp.BadDebt)
}
}
}

// settlePositionShouldFail
type settlePositionShouldFail struct {
pair asset.Pair
version uint64
trader sdk.AccAddress
}

func (c settlePositionShouldFail) Do(app *app.NibiruApp, ctx sdk.Context) (sdk.Context, error, bool) {
_, err := app.PerpKeeperV2.SettlePosition(ctx, c.pair, c.version, c.trader)
if err == nil {
return ctx, err, false
}

return ctx, nil, true
}

func SettlePositionShouldFail(pair asset.Pair, version uint64, trader sdk.AccAddress) action.Action {
return settlePositionShouldFail{pair: pair, version: version, trader: trader}
}
29 changes: 27 additions & 2 deletions x/perp/v2/integration/assertion/position.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,20 +61,45 @@ func Position_PositionShouldBeEqualTo(expectedPosition types.Position) PositionC
type positionShouldNotExist struct {
Account sdk.AccAddress
Pair asset.Pair
Version uint64
}

func (p positionShouldNotExist) Do(app *app.NibiruApp, ctx sdk.Context) (sdk.Context, error, bool) {
_, err := app.PerpKeeperV2.GetPosition(ctx, p.Pair, 1, p.Account)
_, err := app.PerpKeeperV2.GetPosition(ctx, p.Pair, p.Version, p.Account)
if err == nil {
return ctx, fmt.Errorf("position should not exist, but it does with pair %s", p.Pair), false
}

return ctx, nil, false
}

func PositionShouldNotExist(account sdk.AccAddress, pair asset.Pair) action.Action {
func PositionShouldNotExist(account sdk.AccAddress, pair asset.Pair, version uint64) action.Action {
return positionShouldNotExist{
Account: account,
Pair: pair,
Version: version,
}
}

type positionShouldExist struct {
Account sdk.AccAddress
Pair asset.Pair
Version uint64
}

func (p positionShouldExist) Do(app *app.NibiruApp, ctx sdk.Context) (sdk.Context, error, bool) {
_, err := app.PerpKeeperV2.GetPosition(ctx, p.Pair, p.Version, p.Account)
if err != nil {
return ctx, fmt.Errorf("position should exist, but it does not with pair %s", p.Pair), false
}

return ctx, nil, false
}

func PositionShouldExist(account sdk.AccAddress, pair asset.Pair, version uint64) action.Action {
return positionShouldExist{
Account: account,
Pair: pair,
Version: version,
}
}
Loading