From 060ab8f468aec861a5d19a8660a9dc64222d6dc5 Mon Sep 17 00:00:00 2001 From: Walter White <101130700+NibiruHeisenberg@users.noreply.github.com> Date: Thu, 7 Jul 2022 11:41:53 -0700 Subject: [PATCH] feat(perp): Add fields to `QueryPositionResponse` (#679) * Refactor names * Add fields to query position resp * Calculate fields on query position * Clean TestOpenPositionsAndCloseCmd * Add assertions to TestOpenPositionsAndCloseCmd Co-authored-by: Mat-Cosmos <97468149+matthiasmatt@users.noreply.github.com> --- proto/perp/v1/query.proto | 16 +++ x/perp/client/cli/cli_test.go | 178 ++++++++++++----------- x/perp/client/cli/tx.go | 4 +- x/perp/keeper/clearing_house.go | 50 +++---- x/perp/keeper/clearing_house_test.go | 2 +- x/perp/keeper/grpc_query.go | 15 +- x/perp/keeper/grpc_query_test.go | 136 ++++++++++++++---- x/perp/keeper/liquidate.go | 2 +- x/perp/types/query.pb.go | 204 +++++++++++++++++++++++---- 9 files changed, 436 insertions(+), 171 deletions(-) diff --git a/proto/perp/v1/query.proto b/proto/perp/v1/query.proto index aefbf00ce..dd0bfd083 100644 --- a/proto/perp/v1/query.proto +++ b/proto/perp/v1/query.proto @@ -41,7 +41,23 @@ message QueryTraderPositionRequest { } message QueryTraderPositionResponse { + // The position as it exists in the blockchain state Position position = 1; + + // The position's current notional value, if it were to be entirely closed (in margin units). + string position_notional = 2 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false]; + + // The position's unrealized PnL. + string unrealized_pnl = 3 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false]; + + // The position's margin ratio, calculated from margin, unrealized PnL, and position notional. + string margin_ratio = 4 [ + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", + (gogoproto.nullable) = false]; } // ---------------------------------------- OtherQuery \ No newline at end of file diff --git a/x/perp/client/cli/cli_test.go b/x/perp/client/cli/cli_test.go index 194432bc2..34cce8c56 100644 --- a/x/perp/client/cli/cli_test.go +++ b/x/perp/client/cli/cli_test.go @@ -5,7 +5,6 @@ import ( "testing" "time" - "github.com/stretchr/testify/require" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -82,7 +81,7 @@ func (s *IntegrationTestSuite) SetupSuite() { vpoolGenesis := vpooltypes.DefaultGenesis() vpoolGenesis.Vpools = []*vpooltypes.Pool{ { - Pair: common.MustNewAssetPair("ubtc:unibi"), + Pair: common.PairBTCStable, BaseAssetReserve: sdk.NewDec(10_000_000), QuoteAssetReserve: sdk.NewDec(60_000_000_000), TradeLimitRatio: sdk.MustNewDecFromStr("0.8"), @@ -114,7 +113,7 @@ func (s *IntegrationTestSuite) SetupSuite() { perpGenesis := perptypes.DefaultGenesis() perpGenesis.PairMetadata = []*perptypes.PairMetadata{ { - Pair: common.MustNewAssetPair("ubtc:unibi"), + Pair: common.PairBTCStable, CumulativePremiumFractions: []sdk.Dec{ sdk.ZeroDec(), }, @@ -143,12 +142,12 @@ func (s *IntegrationTestSuite) SetupSuite() { s.network = testutilcli.NewNetwork(s.T(), s.cfg) _, err := s.network.WaitForHeight(1) - s.Require().NoError(err) + s.NoError(err) val := s.network.Validators[0] info, _, err := val.ClientCtx.Keyring. NewMnemonic("user1", keyring.English, sdk.FullFundraiserPath, "", hd.Secp256k1) - s.Require().NoError(err) + s.NoError(err) user1 := sdk.AccAddress(info.GetPubKey().Address()) s.users = []sdk.AccAddress{user1} @@ -164,7 +163,7 @@ func (s *IntegrationTestSuite) SetupSuite() { val, s.cfg.BondDenom, ) - s.Require().NoError(err) + s.NoError(err) } func (s *IntegrationTestSuite) TearDownSuite() { @@ -174,145 +173,158 @@ func (s *IntegrationTestSuite) TearDownSuite() { func (s *IntegrationTestSuite) TestOpenPositionsAndCloseCmd() { val := s.network.Validators[0] - assetPair := common.AssetPair{ - Token0: "ubtc", - Token1: "unibi", - } user := s.users[0] s.T().Log("A. check vpool balances") - reserveAssets, err := testutilcli.QueryVpoolReserveAssets(val.ClientCtx, assetPair) + reserveAssets, err := testutilcli.QueryVpoolReserveAssets(val.ClientCtx, common.PairBTCStable) s.T().Logf("reserve assets: %+v", reserveAssets) - s.Require().NoError(err) - s.Assert().EqualValues(sdk.NewDec(10_000_000), reserveAssets.BaseAssetReserve) - s.Assert().EqualValues(sdk.NewDec(60_000_000_000), reserveAssets.QuoteAssetReserve) + s.NoError(err) + s.EqualValues(sdk.NewDec(10_000_000), reserveAssets.BaseAssetReserve) + s.EqualValues(sdk.NewDec(60_000_000_000), reserveAssets.QuoteAssetReserve) s.T().Log("A. check trader has no existing positions") - _, err = testutilcli.QueryTraderPosition(val.ClientCtx, assetPair, user) - s.Assert().Error(err, "no position found") + _, err = testutilcli.QueryTraderPosition(val.ClientCtx, common.PairBTCStable, user) + s.Error(err, "no position found") s.T().Log("B. open position") args := []string{ "--from", user.String(), "buy", - assetPair.String(), - "1", // Leverage - "1000000", // 1 BTC - "1", + common.PairBTCStable.String(), + /* leverage */ "1", + /* quoteAmt */ "1000000", // 10^6 uNUSD + /* baseAssetLimit */ "1", } _, err = clitestutil.ExecTestCLICmd(val.ClientCtx, cli.OpenPositionCmd(), append(args, commonArgs...)) - s.Require().NoError(err) + s.NoError(err) s.T().Log("B. check vpool balance after open position") - reserveAssets, err = testutilcli.QueryVpoolReserveAssets(val.ClientCtx, assetPair) + reserveAssets, err = testutilcli.QueryVpoolReserveAssets(val.ClientCtx, common.PairBTCStable) s.T().Logf("reserve assets: %+v", reserveAssets) - s.Require().NoError(err) - s.Assert().EqualValues(sdk.MustNewDecFromStr("9999833.336111064815586407"), reserveAssets.BaseAssetReserve) - s.Assert().EqualValues(sdk.NewDec(60_001_000_000), reserveAssets.QuoteAssetReserve) + s.NoError(err) + s.EqualValues(sdk.MustNewDecFromStr("9999833.336111064815586407"), reserveAssets.BaseAssetReserve) + s.EqualValues(sdk.NewDec(60_001_000_000), reserveAssets.QuoteAssetReserve) s.T().Log("B. check vpool balances") - queryResp, err := testutilcli.QueryTraderPosition(val.ClientCtx, assetPair, user) + queryResp, err := testutilcli.QueryTraderPosition(val.ClientCtx, common.PairBTCStable, user) s.T().Logf("query response: %+v", queryResp) - s.Require().NoError(err) - s.Assert().EqualValues(user.String(), queryResp.Position.TraderAddress) - s.Assert().EqualValues(assetPair, queryResp.Position.Pair) - s.Assert().EqualValues(sdk.NewDec(1_000_000), queryResp.Position.Margin) - s.Assert().EqualValues(sdk.NewDec(1_000_000), queryResp.Position.OpenNotional) + s.NoError(err) + s.EqualValues(user.String(), queryResp.Position.TraderAddress) + s.EqualValues(common.PairBTCStable, queryResp.Position.Pair) + s.EqualValues(sdk.MustNewDecFromStr("166.663888935184413593"), queryResp.Position.Size_) + s.EqualValues(sdk.NewDec(1_000_000), queryResp.Position.Margin) + s.EqualValues(sdk.NewDec(1_000_000), queryResp.Position.OpenNotional) + s.EqualValues(sdk.MustNewDecFromStr("999999.999999999999999359"), queryResp.PositionNotional) + s.EqualValues(sdk.MustNewDecFromStr("-0.000000000000000641"), queryResp.UnrealizedPnl) + s.EqualValues(sdk.NewDec(1), queryResp.MarginRatio) s.T().Log("C. open position with 2x leverage and zero baseAmtLimit") args = []string{ "--from", user.String(), "buy", - assetPair.String(), + common.PairBTCStable.String(), /* leverage */ "2", - /* quoteAmt */ "1000000", // 10^6 unusd + /* quoteAmt */ "1000000", // 10^6 uNUSD /* baseAmtLimit */ "0", } _, err = clitestutil.ExecTestCLICmd(val.ClientCtx, cli.OpenPositionCmd(), append(args, commonArgs...)) - s.Require().NoError(err) + s.NoError(err) s.T().Log("C. check trader position") - queryResp, err = testutilcli.QueryTraderPosition(val.ClientCtx, assetPair, user) + queryResp, err = testutilcli.QueryTraderPosition(val.ClientCtx, common.PairBTCStable, user) s.T().Logf("query response: %+v", queryResp) - s.Require().NoError(err) - s.Assert().EqualValues(user.String(), queryResp.Position.TraderAddress) - s.Assert().EqualValues(assetPair, queryResp.Position.Pair) - s.Assert().EqualValues(sdk.NewDec(2_000_000), queryResp.Position.Margin) - s.Assert().EqualValues(sdk.NewDec(3_000_000), queryResp.Position.OpenNotional) + s.NoError(err) + s.EqualValues(user.String(), queryResp.Position.TraderAddress) + s.EqualValues(common.PairBTCStable, queryResp.Position.Pair) + s.EqualValues(sdk.MustNewDecFromStr("499.975001249937503125"), queryResp.Position.Size_) + s.EqualValues(sdk.NewDec(2_000_000), queryResp.Position.Margin) + s.EqualValues(sdk.NewDec(3_000_000), queryResp.Position.OpenNotional) + s.EqualValues(sdk.MustNewDecFromStr("3000000.000000000000000938"), queryResp.PositionNotional) + s.EqualValues(sdk.MustNewDecFromStr("0.000000000000000938"), queryResp.UnrealizedPnl) + s.EqualValues(sdk.MustNewDecFromStr("0.666666666666666667"), queryResp.MarginRatio) s.T().Log("D. Open a reverse position smaller than the existing position") args = []string{ "--from", user.String(), "sell", - assetPair.String(), - "1", // Leverage - "100", // unusd - "1", + common.PairBTCStable.String(), + /* leverage */ "1", + /* quoteAmt */ "100", // 100 uNUSD + /* baseAssetLimit */ "1", } res, err := clitestutil.ExecTestCLICmd(val.ClientCtx, cli.OpenPositionCmd(), append(args, commonArgs...)) - s.Require().NoError(err) - s.Assert().NotContains(res.String(), "fail") + s.NoError(err) + s.NotContains(res.String(), "fail") s.T().Log("D. Check vpool after opening reverse position") - reserveAssets, err = testutilcli.QueryVpoolReserveAssets(val.ClientCtx, assetPair) + reserveAssets, err = testutilcli.QueryVpoolReserveAssets(val.ClientCtx, common.PairBTCStable) s.T().Logf(" \n reserve assets: %+v \n", reserveAssets) - s.Require().NoError(err) - s.Assert().EqualValues(sdk.MustNewDecFromStr("9999500.041663750215262154"), reserveAssets.BaseAssetReserve) - s.Assert().EqualValues(sdk.NewDec(60_002_999_900), reserveAssets.QuoteAssetReserve) + s.NoError(err) + s.EqualValues(sdk.MustNewDecFromStr("9999500.041663750215262154"), reserveAssets.BaseAssetReserve) + s.EqualValues(sdk.NewDec(60_002_999_900), reserveAssets.QuoteAssetReserve) s.T().Log("D. Check trader position") - queryResp, err = testutilcli.QueryTraderPosition(val.ClientCtx, assetPair, user) + queryResp, err = testutilcli.QueryTraderPosition(val.ClientCtx, common.PairBTCStable, user) s.T().Logf("query response: %+v", queryResp) - s.Require().NoError(err) - s.Assert().EqualValues(user.String(), queryResp.Position.TraderAddress) - s.Assert().EqualValues(assetPair, queryResp.Position.Pair) - s.Assert().EqualValues(sdk.NewDec(2_000_000), queryResp.Position.Margin) - s.Assert().EqualValues(sdk.NewDec(2_999_900), queryResp.Position.OpenNotional) + s.NoError(err) + s.EqualValues(user.String(), queryResp.Position.TraderAddress) + s.EqualValues(common.PairBTCStable, queryResp.Position.Pair) + s.EqualValues(sdk.MustNewDecFromStr("499.958336249784737846"), queryResp.Position.Size_) + s.EqualValues(sdk.NewDec(2_000_000), queryResp.Position.Margin) + s.EqualValues(sdk.NewDec(2_999_900), queryResp.Position.OpenNotional) + s.EqualValues(sdk.MustNewDecFromStr("2999899.999999999999999506"), queryResp.PositionNotional) + s.EqualValues(sdk.MustNewDecFromStr("-0.000000000000000494"), queryResp.UnrealizedPnl) + s.EqualValues(sdk.MustNewDecFromStr("0.666688889629654322"), queryResp.MarginRatio) s.T().Log("E. Open a reverse position larger than the existing position") args = []string{ "--from", user.String(), "sell", - assetPair.String(), - "1", // Leverage - "4000000", // 4*10^6 unusd - "2000000000", // TODO: just threw a large number here, figure out a more appropriate amount + common.PairBTCStable.String(), + /* leverage */ "1", + /* quoteAmt */ "4000000", // 4*10^6 uNUSD + /* baseAssetLimit */ "0", } res, err = clitestutil.ExecTestCLICmd(val.ClientCtx, cli.OpenPositionCmd(), append(args, commonArgs...)) - s.Require().NoError(err) - s.Assert().NotContains(res.String(), "fail") + s.NoError(err) + s.NotContains(res.String(), "fail") s.T().Log("E. Check trader position") - queryResp, err = testutilcli.QueryTraderPosition(val.ClientCtx, assetPair, user) + queryResp, err = testutilcli.QueryTraderPosition(val.ClientCtx, common.PairBTCStable, user) s.T().Logf("query response: %+v", queryResp) - s.Require().NoError(err) - s.Assert().EqualValues(user.String(), queryResp.Position.TraderAddress) - s.Assert().EqualValues(assetPair, queryResp.Position.Pair) - s.Assert().EqualValues(sdk.MustNewDecFromStr("1000100.000000000000000494"), queryResp.Position.OpenNotional) - s.Assert().EqualValues(sdk.MustNewDecFromStr("-166.686111713005402945"), queryResp.Position.Size_) - s.Assert().EqualValues(sdk.MustNewDecFromStr("1000100.000000000000000494"), queryResp.Position.Margin) + s.NoError(err) + s.EqualValues(user.String(), queryResp.Position.TraderAddress) + s.EqualValues(common.PairBTCStable, queryResp.Position.Pair) + s.EqualValues(sdk.MustNewDecFromStr("-166.686111713005402945"), queryResp.Position.Size_) + s.EqualValues(sdk.MustNewDecFromStr("1000100.000000000000000494"), queryResp.Position.OpenNotional) + s.EqualValues(sdk.MustNewDecFromStr("1000100.000000000000000494"), queryResp.Position.Margin) + s.EqualValues(sdk.MustNewDecFromStr("1000099.999999999999999651"), queryResp.PositionNotional) + s.EqualValues(sdk.MustNewDecFromStr("0.000000000000000843"), queryResp.UnrealizedPnl) + s.EqualValues(sdk.NewDec(1), queryResp.MarginRatio) s.T().Log("F. Close position") args = []string{ "--from", user.String(), - assetPair.String(), + common.PairBTCStable.String(), } _, err = clitestutil.ExecTestCLICmd(val.ClientCtx, cli.ClosePositionCmd(), append(args, commonArgs...)) - s.Require().NoError(err) + s.NoError(err) s.T().Log("F. check trader position") - queryResp, err = testutilcli.QueryTraderPosition(val.ClientCtx, assetPair, user) + queryResp, err = testutilcli.QueryTraderPosition(val.ClientCtx, common.PairBTCStable, user) + s.T().Logf("query response: %+v", queryResp) s.Error(err) + status, ok := status.FromError(err) - require.True(s.T(), ok) - require.Equal(s.T(), status.Code(), codes.InvalidArgument) + s.True(ok) + s.EqualValues(codes.InvalidArgument, status.Code()) } func (s *IntegrationTestSuite) TestPositionEmptyAndClose() { @@ -326,7 +338,7 @@ func (s *IntegrationTestSuite) TestPositionEmptyAndClose() { // verify trader has no position (empty) _, err := testutilcli.QueryTraderPosition(val.ClientCtx, assetPair, user) - s.Assert().Error(err, "no position found") + s.Error(err, "no position found") // close position should produce error args := []string{ @@ -335,7 +347,7 @@ func (s *IntegrationTestSuite) TestPositionEmptyAndClose() { assetPair.String(), } out, _ := clitestutil.ExecTestCLICmd(val.ClientCtx, cli.ClosePositionCmd(), append(args, commonArgs...)) - s.Assert().Contains(out.String(), "no position found") + s.Contains(out.String(), "no position found") } func (s *IntegrationTestSuite) TestGetPrices() { @@ -347,15 +359,15 @@ func (s *IntegrationTestSuite) TestGetPrices() { s.T().Log("check vpool balances") reserveAssets, err := testutilcli.QueryVpoolReserveAssets(val.ClientCtx, assetPair) - s.Require().NoError(err) - s.Assert().EqualValues(sdk.MustNewDecFromStr("10000000"), reserveAssets.BaseAssetReserve) - s.Assert().EqualValues(sdk.MustNewDecFromStr("60000000000"), reserveAssets.QuoteAssetReserve) + s.NoError(err) + s.EqualValues(sdk.MustNewDecFromStr("10000000"), reserveAssets.BaseAssetReserve) + s.EqualValues(sdk.MustNewDecFromStr("60000000000"), reserveAssets.QuoteAssetReserve) s.T().Log("check prices") priceInfo, err := testutilcli.QueryBaseAssetPrice(val.ClientCtx, assetPair, "1", "100") s.T().Logf("priceInfo: %+v", priceInfo) - s.Assert().EqualValues(sdk.MustNewDecFromStr("599994.000059999400006000"), priceInfo.PriceInQuoteDenom) - s.Require().NoError(err) + s.EqualValues(sdk.MustNewDecFromStr("599994.000059999400006000"), priceInfo.PriceInQuoteDenom) + s.NoError(err) } func (s *IntegrationTestSuite) TestRemoveMargin() { @@ -378,7 +390,7 @@ func (s *IntegrationTestSuite) TestRemoveMargin() { if err != nil { s.T().Logf("user1 open position err: %+v", err) } - s.Require().NoError(err) + s.NoError(err) // Remove margin to trigger bad debt on user 1 s.T().Log("removing margin on user 1....") @@ -393,7 +405,7 @@ func (s *IntegrationTestSuite) TestRemoveMargin() { s.T().Logf("user1 remove margin err: %+v", err) } - s.Require().Contains(out.String(), perptypes.ErrFailedRemoveMarginCanCauseBadDebt.Error()) + s.Contains(out.String(), perptypes.ErrFailedRemoveMarginCanCauseBadDebt.Error()) } func TestIntegrationTestSuite(t *testing.T) { diff --git a/x/perp/client/cli/tx.go b/x/perp/client/cli/tx.go index 3d406a8e2..c8d83c180 100644 --- a/x/perp/client/cli/tx.go +++ b/x/perp/client/cli/tx.go @@ -71,7 +71,7 @@ func OpenPositionCmd() *cobra.Command { return fmt.Errorf("invalid quote amount: %s", args[3]) } - baseAssetAmountLimit := sdk.MustNewDecFromStr(args[4]) + baseAmtLimit := sdk.MustNewDecFromStr(args[4]) msg := &types.MsgOpenPosition{ Sender: clientCtx.GetFromAddress().String(), @@ -79,7 +79,7 @@ func OpenPositionCmd() *cobra.Command { Side: side, QuoteAssetAmount: amount, Leverage: leverage, - BaseAssetAmountLimit: baseAssetAmountLimit.RoundInt(), + BaseAssetAmountLimit: baseAmtLimit.RoundInt(), } if err := msg.ValidateBasic(); err != nil { diff --git a/x/perp/keeper/clearing_house.go b/x/perp/keeper/clearing_house.go index b0f121109..74ea8d872 100644 --- a/x/perp/keeper/clearing_house.go +++ b/x/perp/keeper/clearing_house.go @@ -19,13 +19,12 @@ func (k Keeper) OpenPosition( traderAddr sdk.AccAddress, quoteAssetAmount sdk.Int, leverage sdk.Dec, - baseAssetAmountLimit sdk.Dec, + baseAmtLimit sdk.Dec, ) (err error) { - ctx.BlockTime().UnixMilli() - err = k.requireVpool(ctx, pair) - if err != nil { + if err = k.requireVpool(ctx, pair); err != nil { return err } + // require params params := k.GetParams(ctx) // TODO: missing checks @@ -52,7 +51,7 @@ func (k Keeper) OpenPosition( *position, side, /* openNotional */ leverage.MulInt(quoteAssetAmount), - /* minPositionSize */ baseAssetAmountLimit, + /* minPositionSize */ baseAmtLimit, /* leverage */ leverage) if err != nil { return err @@ -65,7 +64,7 @@ func (k Keeper) OpenPosition( *position, /* quoteAssetAmount */ quoteAssetAmount.ToDec(), /* leverage */ leverage, - /* baseAssetAmountLimit */ baseAssetAmountLimit, + /* baseAmtLimit */ baseAmtLimit, /* canOverFluctuationLimit */ false, ) if err != nil { @@ -184,7 +183,7 @@ args: - currentPosition: the current position - side: whether the position is increasing in the BUY or SELL direction - increasedNotional: the notional value to increase the position by, in margin units - - baseAssetAmountLimit: the limit on the base asset amount to make sure the trader doesn't get screwed, in base asset units + - baseAmtLimit: the limit on the base asset amount to make sure the trader doesn't get screwed, in base asset units - leverage: the amount of leverage to take, as sdk.Dec ret: @@ -196,7 +195,7 @@ func (k Keeper) increasePosition( currentPosition types.Position, side types.Side, increasedNotional sdk.Dec, - baseAssetAmountLimit sdk.Dec, + baseAmtLimit sdk.Dec, leverage sdk.Dec, ) (positionResp *types.PositionResp, err error) { positionResp = &types.PositionResp{} @@ -206,7 +205,7 @@ func (k Keeper) increasePosition( currentPosition.Pair, side, increasedNotional, - baseAssetAmountLimit, + baseAmtLimit, false, ) if err != nil { @@ -250,11 +249,6 @@ func (k Keeper) increasePosition( BlockNumber: ctx.BlockHeight(), } - k.Logger(ctx).Debug("increase_position", - "positionResp", - positionResp.String(), - ) - return positionResp, nil } @@ -377,7 +371,7 @@ func (k Keeper) openReversePosition( currentPosition types.Position, quoteAssetAmount sdk.Dec, leverage sdk.Dec, - baseAssetAmountLimit sdk.Dec, + baseAmtLimit sdk.Dec, canOverFluctuationLimit bool, ) (positionResp *types.PositionResp, err error) { notionalToDecreaseBy := leverage.Mul(quoteAssetAmount) @@ -396,7 +390,7 @@ func (k Keeper) openReversePosition( ctx, currentPosition, notionalToDecreaseBy, - baseAssetAmountLimit, + baseAmtLimit, canOverFluctuationLimit, ) } else { @@ -406,7 +400,7 @@ func (k Keeper) openReversePosition( currentPosition, quoteAssetAmount, leverage, - baseAssetAmountLimit, + baseAmtLimit, ) } } @@ -425,7 +419,7 @@ args: - ctx: cosmos-sdk context - currentPosition: the current position - decreasedNotional: the notional value to decrease the position by, in margin units - - baseAssetAmountLimit: the limit on the base asset amount to make sure the trader doesn't get screwed, in base asset units + - baseAmtLimit: the limit on the base asset amount to make sure the trader doesn't get screwed, in base asset units - canOverFluctuationLimit: whether or not the position change can go over the fluctuation limit ret: @@ -437,7 +431,7 @@ func (k Keeper) decreasePosition( ctx sdk.Context, currentPosition types.Position, decreasedNotional sdk.Dec, - baseAssetAmountLimit sdk.Dec, + baseAmtLimit sdk.Dec, canOverFluctuationLimit bool, ) (positionResp *types.PositionResp, err error) { positionResp = &types.PositionResp{ @@ -468,7 +462,7 @@ func (k Keeper) decreasePosition( currentPosition.Pair, sideToTake, decreasedNotional, - baseAssetAmountLimit, + baseAmtLimit, canOverFluctuationLimit, ) if err != nil { @@ -541,7 +535,7 @@ args: - existingPosition: current position - quoteAssetAmount: the amount of notional value to move by. Must be greater than the existingPosition's notional value. - leverage: the amount of leverage to take - - baseAssetAmountLimit: limit on the base asset movement to ensure trader doesn't get screwed + - baseAmtLimit: limit on the base asset movement to ensure trader doesn't get screwed ret: - positionResp: response object containing information about the position change @@ -552,7 +546,7 @@ func (k Keeper) closeAndOpenReversePosition( existingPosition types.Position, quoteAssetAmount sdk.Dec, leverage sdk.Dec, - baseAssetAmountLimit sdk.Dec, + baseAmtLimit sdk.Dec, ) (positionResp *types.PositionResp, err error) { trader, err := sdk.AccAddressFromBech32(existingPosition.TraderAddress) if err != nil { @@ -582,15 +576,15 @@ func (k Keeper) closeAndOpenReversePosition( "provided quote asset amount and leverage not large enough to close position. need %s but got %s", closePositionResp.ExchangedNotionalValue.String(), reverseNotionalValue.String()) } else if remainingReverseNotionalValue.IsPositive() { - updatedBaseAssetAmountLimit := baseAssetAmountLimit - if baseAssetAmountLimit.IsPositive() { - updatedBaseAssetAmountLimit = baseAssetAmountLimit. + updatedbaseAmtLimit := baseAmtLimit + if baseAmtLimit.IsPositive() { + updatedbaseAmtLimit = baseAmtLimit. Sub(closePositionResp.ExchangedPositionSize.Abs()) } - if updatedBaseAssetAmountLimit.IsNegative() { + if updatedbaseAmtLimit.IsNegative() { return nil, fmt.Errorf( "position size changed by greater than the specified base limit: %s", - baseAssetAmountLimit.String(), + baseAmtLimit.String(), ) } @@ -612,7 +606,7 @@ func (k Keeper) closeAndOpenReversePosition( *newPosition, sideToTake, remainingReverseNotionalValue, - updatedBaseAssetAmountLimit, + updatedbaseAmtLimit, leverage, ) if err != nil { diff --git a/x/perp/keeper/clearing_house_test.go b/x/perp/keeper/clearing_house_test.go index 0caacb96d..498bd983d 100644 --- a/x/perp/keeper/clearing_house_test.go +++ b/x/perp/keeper/clearing_house_test.go @@ -27,7 +27,7 @@ import ( vpooltypes "github.com/NibiruChain/nibiru/x/vpool/types" ) -func TestKeeper_getLatestCumulativePremiumFraction(t *testing.T) { +func TestGetLatestCumulativePremiumFraction(t *testing.T) { testCases := []struct { name string test func() diff --git a/x/perp/keeper/grpc_query.go b/x/perp/keeper/grpc_query.go index b3011855f..c4375472b 100644 --- a/x/perp/keeper/grpc_query.go +++ b/x/perp/keeper/grpc_query.go @@ -44,7 +44,20 @@ func (q queryServer) TraderPosition( return nil, err } + positionNotional, unrealizedPnl, err := q.Keeper.getPositionNotionalAndUnrealizedPnL(ctx, *position, types.PnLCalcOption_SPOT_PRICE) + if err != nil { + return nil, err + } + + marginRatio, err := q.Keeper.GetMarginRatio(ctx, *position, types.MarginCalculationPriceOption_SPOT) + if err != nil { + return nil, err + } + return &types.QueryTraderPositionResponse{ - Position: position, + Position: position, + PositionNotional: positionNotional, + UnrealizedPnl: unrealizedPnl, + MarginRatio: marginRatio, }, nil } diff --git a/x/perp/keeper/grpc_query_test.go b/x/perp/keeper/grpc_query_test.go index b17657d26..687da7b51 100644 --- a/x/perp/keeper/grpc_query_test.go +++ b/x/perp/keeper/grpc_query_test.go @@ -1,7 +1,6 @@ package keeper_test import ( - "fmt" "testing" sdk "github.com/cosmos/cosmos-sdk/types" @@ -15,38 +14,117 @@ import ( "github.com/NibiruChain/nibiru/x/testutil/testapp" ) -func TestQueryPosition_Ok(t *testing.T) { - t.Log("initialize keeper") - nibiruApp, ctx := testapp.NewNibiruAppAndContext(true) - perpKeeper := &nibiruApp.PerpKeeper +func TestQueryPosition(t *testing.T) { + tests := []struct { + name string + initialPosition *types.Position - queryServer := keeper.NewQuerier(*perpKeeper) + quoteAssetReserve sdk.Dec + baseAssetReserve sdk.Dec - trader := sample.AccAddress() - vpoolPair := common.MustNewAssetPair("btc:nusd") - - oldPosition := &types.Position{ - TraderAddress: trader.String(), - Pair: vpoolPair, - Size_: sdk.NewDec(10), - OpenNotional: sdk.NewDec(10), - Margin: sdk.NewDec(1), + expectedPositionNotional sdk.Dec + expectedUnrealizedPnl sdk.Dec + expectedMarginRatio sdk.Dec + }{ + { + name: "positive PnL", + initialPosition: &types.Position{ + Pair: common.PairBTCStable, + Size_: sdk.NewDec(10), + OpenNotional: sdk.NewDec(10), + Margin: sdk.NewDec(1), + BlockNumber: 1, + LastUpdateCumulativePremiumFraction: sdk.ZeroDec(), + }, + quoteAssetReserve: sdk.NewDec(1_000_000), + baseAssetReserve: sdk.NewDec(500_000), + expectedPositionNotional: sdk.MustNewDecFromStr("19.999600007999840003"), + expectedUnrealizedPnl: sdk.MustNewDecFromStr("9.999600007999840003"), + expectedMarginRatio: sdk.MustNewDecFromStr("0.549991"), + }, + { + name: "negative PnL, positive margin ratio", + initialPosition: &types.Position{ + Pair: common.PairBTCStable, + Size_: sdk.NewDec(10), + OpenNotional: sdk.NewDec(10), + Margin: sdk.NewDec(1), + BlockNumber: 1, + LastUpdateCumulativePremiumFraction: sdk.ZeroDec(), + }, + quoteAssetReserve: sdk.NewDec(1_000_000), + baseAssetReserve: sdk.NewDec(1_000_000), + expectedPositionNotional: sdk.MustNewDecFromStr("9.99990000099999"), + expectedUnrealizedPnl: sdk.MustNewDecFromStr("-0.00009999900001"), + expectedMarginRatio: sdk.MustNewDecFromStr("0.099991"), + }, + { + name: "negative PnL, negative margin ratio", + initialPosition: &types.Position{ + Pair: common.PairBTCStable, + Size_: sdk.NewDec(10), + OpenNotional: sdk.NewDec(10), + Margin: sdk.NewDec(1), + BlockNumber: 1, + LastUpdateCumulativePremiumFraction: sdk.ZeroDec(), + }, + quoteAssetReserve: sdk.NewDec(500_000), + baseAssetReserve: sdk.NewDec(1_000_000), + expectedPositionNotional: sdk.MustNewDecFromStr("4.999950000499995"), + expectedUnrealizedPnl: sdk.MustNewDecFromStr("-5.000049999500005"), + expectedMarginRatio: sdk.MustNewDecFromStr("-0.800018"), + }, } - perpKeeper.SetPosition( - ctx, vpoolPair, trader, oldPosition) + for _, tc := range tests { + tc := tc + t.Run(tc.name, func(t *testing.T) { + t.Log("initialize trader address") + traderAddr := sample.AccAddress() + tc.initialPosition.TraderAddress = traderAddr.String() - res, err := queryServer.TraderPosition( - sdk.WrapSDKContext(ctx), - &types.QueryTraderPositionRequest{ - Trader: trader.String(), - TokenPair: vpoolPair.String(), - }, - ) - fmt.Println("res:", res) - require.NoError(t, err) + t.Log("initialize app and keeper") + nibiruApp, ctx := testapp.NewNibiruAppAndContext(true) + perpKeeper := &nibiruApp.PerpKeeper + vpoolKeeper := &nibiruApp.VpoolKeeper + queryServer := keeper.NewQuerier(*perpKeeper) - assert.Equal(t, oldPosition.TraderAddress, res.Position.TraderAddress) - assert.Equal(t, oldPosition.Pair, res.Position.Pair) - assert.Equal(t, oldPosition.Size_, res.Position.Size_) + t.Log("initialize vpool and pair") + vpoolKeeper.CreatePool( + ctx, + common.PairBTCStable, + /* tradeLimitRatio */ sdk.OneDec(), + /* quoteReserve */ tc.quoteAssetReserve, + /* baseReserve */ tc.baseAssetReserve, + /* fluctuationLimitRatio */ sdk.OneDec(), + /* maxOracleSpreadRatio */ sdk.OneDec(), + ) + perpKeeper.PairMetadataState(ctx).Set(&types.PairMetadata{ + Pair: common.PairBTCStable, + CumulativePremiumFractions: []sdk.Dec{ + sdk.ZeroDec(), + }, + }) + + t.Log("initialize position") + perpKeeper.SetPosition(ctx, common.PairBTCStable, traderAddr, tc.initialPosition) + + t.Log("query position") + resp, err := queryServer.TraderPosition( + sdk.WrapSDKContext(ctx), + &types.QueryTraderPositionRequest{ + Trader: traderAddr.String(), + TokenPair: common.PairBTCStable.String(), + }, + ) + require.NoError(t, err) + + t.Log("assert response") + assert.EqualValues(t, tc.initialPosition, resp.Position) + + assert.Equal(t, tc.expectedPositionNotional, resp.PositionNotional) + assert.Equal(t, tc.expectedUnrealizedPnl, resp.UnrealizedPnl) + assert.Equal(t, tc.expectedMarginRatio, resp.MarginRatio) + }) + } } diff --git a/x/perp/keeper/liquidate.go b/x/perp/keeper/liquidate.go index 062a61eae..29b2fab5f 100644 --- a/x/perp/keeper/liquidate.go +++ b/x/perp/keeper/liquidate.go @@ -289,7 +289,7 @@ func (k Keeper) ExecutePartialLiquidation( /* currentPosition */ *currentPosition, /* quoteAssetAmount */ partiallyLiquidatedPositionNotional, /* leverage */ sdk.OneDec(), - /* baseAssetAmountLimit */ sdk.ZeroDec(), + /* baseAmtLimit */ sdk.ZeroDec(), /* canOverFluctuationLimit */ true, ) if err != nil { diff --git a/x/perp/types/query.pb.go b/x/perp/types/query.pb.go index a02332f20..4f6682eb5 100644 --- a/x/perp/types/query.pb.go +++ b/x/perp/types/query.pb.go @@ -6,6 +6,7 @@ package types import ( context "context" fmt "fmt" + github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types" _ "github.com/gogo/protobuf/gogoproto" grpc1 "github.com/gogo/protobuf/grpc" proto "github.com/gogo/protobuf/proto" @@ -167,7 +168,14 @@ func (m *QueryTraderPositionRequest) GetTrader() string { } type QueryTraderPositionResponse struct { + // The position as it exists in the blockchain state Position *Position `protobuf:"bytes,1,opt,name=position,proto3" json:"position,omitempty"` + // The position's current notional value, if it were to be entirely closed (in margin units). + PositionNotional github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,2,opt,name=position_notional,json=positionNotional,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"position_notional"` + // The position's unrealized PnL. + UnrealizedPnl github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,3,opt,name=unrealized_pnl,json=unrealizedPnl,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"unrealized_pnl"` + // The position's margin ratio, calculated from margin, unrealized PnL, and position notional. + MarginRatio github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,4,opt,name=margin_ratio,json=marginRatio,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"margin_ratio"` } func (m *QueryTraderPositionResponse) Reset() { *m = QueryTraderPositionResponse{} } @@ -220,32 +228,38 @@ func init() { func init() { proto.RegisterFile("perp/v1/query.proto", fileDescriptor_8212d8958be09421) } var fileDescriptor_8212d8958be09421 = []byte{ - // 388 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x92, 0x41, 0x6f, 0xda, 0x30, - 0x1c, 0xc5, 0x13, 0xb4, 0x45, 0xc3, 0x93, 0x38, 0x18, 0x86, 0x50, 0x60, 0xd9, 0x94, 0xed, 0x30, - 0x31, 0x29, 0x16, 0x6c, 0x9f, 0x80, 0xed, 0x36, 0x69, 0x62, 0xb0, 0x53, 0x2f, 0xc8, 0xb4, 0x56, - 0xb0, 0x5a, 0x6c, 0x63, 0x3b, 0xa8, 0x5c, 0x7b, 0xeb, 0xa9, 0x95, 0xfa, 0xa5, 0x38, 0x22, 0xf5, - 0xd2, 0x53, 0x55, 0x41, 0x3f, 0x48, 0x15, 0xdb, 0x20, 0xa5, 0xa0, 0xaa, 0xb7, 0xe4, 0xfd, 0xdf, - 0xff, 0xf9, 0xe7, 0x97, 0x80, 0xaa, 0x20, 0x52, 0xa0, 0x79, 0x07, 0xcd, 0x32, 0x22, 0x17, 0x89, - 0x90, 0x5c, 0x73, 0x58, 0x61, 0x74, 0x4c, 0x65, 0x96, 0xe4, 0xb3, 0x64, 0xde, 0x09, 0x6b, 0x29, - 0x4f, 0xb9, 0x19, 0xa1, 0xfc, 0xc9, 0xba, 0xc2, 0x56, 0xca, 0x79, 0x7a, 0x46, 0x10, 0x16, 0x14, - 0x61, 0xc6, 0xb8, 0xc6, 0x9a, 0x72, 0xa6, 0xdc, 0x74, 0x17, 0xac, 0x34, 0xd6, 0xc4, 0x8a, 0x71, - 0x0d, 0xc0, 0x7f, 0xf9, 0x39, 0x7d, 0x2c, 0xf1, 0x54, 0x0d, 0xc8, 0x2c, 0x23, 0x4a, 0xc7, 0x7f, - 0x40, 0xb5, 0xa0, 0x2a, 0xc1, 0x99, 0x22, 0xf0, 0x27, 0x08, 0x84, 0x51, 0x1a, 0xfe, 0x67, 0xff, - 0xdb, 0xfb, 0x6e, 0x3d, 0x29, 0x62, 0x25, 0xd6, 0xdf, 0x7b, 0xb3, 0xbc, 0xff, 0xe4, 0x0d, 0x9c, - 0x37, 0x1e, 0x82, 0xd0, 0x84, 0xfd, 0x97, 0xf8, 0x84, 0xc8, 0x3e, 0x57, 0x34, 0xa7, 0x72, 0x47, - 0xc1, 0x8f, 0x00, 0x68, 0x7e, 0x4a, 0xd8, 0x48, 0x60, 0x2a, 0x4d, 0x6e, 0x79, 0x50, 0x36, 0x4a, - 0x1f, 0x53, 0x09, 0xeb, 0x20, 0xd0, 0x66, 0xaf, 0x51, 0x32, 0x23, 0xf7, 0x16, 0x0f, 0x41, 0xf3, - 0x60, 0xe8, 0x8e, 0xf4, 0x9d, 0x70, 0x9a, 0x63, 0x6d, 0xec, 0xb1, 0x6e, 0x77, 0x76, 0xce, 0xee, - 0x65, 0x09, 0xbc, 0x35, 0xa9, 0x90, 0x81, 0xc0, 0xde, 0x05, 0xc6, 0xcf, 0xf7, 0xf6, 0xeb, 0x0a, - 0xbf, 0xbc, 0xe8, 0xb1, 0x48, 0x71, 0xf3, 0xe2, 0xf6, 0xf1, 0xa6, 0xf4, 0x01, 0x56, 0x91, 0x35, - 0x23, 0xf3, 0x39, 0x6c, 0x47, 0xf0, 0xca, 0x07, 0x95, 0xe2, 0x55, 0x60, 0xfb, 0x60, 0xe8, 0xc1, - 0x12, 0xc3, 0xef, 0xaf, 0xf2, 0x3a, 0x90, 0xaf, 0x06, 0x24, 0x82, 0xad, 0x02, 0x88, 0xed, 0x75, - 0xb4, 0xed, 0xa2, 0xf7, 0x7b, 0xb9, 0x8e, 0xfc, 0xd5, 0x3a, 0xf2, 0x1f, 0xd6, 0x91, 0x7f, 0xbd, - 0x89, 0xbc, 0xd5, 0x26, 0xf2, 0xee, 0x36, 0x91, 0x77, 0xd4, 0x4e, 0xa9, 0x9e, 0x64, 0xe3, 0xe4, - 0x98, 0x4f, 0xd1, 0x5f, 0x93, 0xf0, 0x6b, 0x82, 0x29, 0xdb, 0xa6, 0x9d, 0xbb, 0xbc, 0x85, 0x20, - 0x6a, 0x1c, 0x98, 0xbf, 0xec, 0xc7, 0x53, 0x00, 0x00, 0x00, 0xff, 0xff, 0x1d, 0x16, 0xb0, 0x4e, - 0xd5, 0x02, 0x00, 0x00, + // 485 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x93, 0xcf, 0x6f, 0xd3, 0x30, + 0x14, 0xc7, 0x9b, 0x32, 0x2a, 0xe6, 0x41, 0x05, 0xee, 0x98, 0xa2, 0x6c, 0x64, 0x28, 0x20, 0x84, + 0x86, 0x88, 0xb5, 0xc1, 0x5f, 0x50, 0x76, 0x43, 0x9a, 0xba, 0x00, 0x17, 0x38, 0x44, 0x6e, 0x6b, + 0x65, 0xd6, 0x52, 0xdb, 0xb3, 0x9d, 0x89, 0x71, 0xe4, 0xc6, 0x09, 0x24, 0xfe, 0xa9, 0x1d, 0x27, + 0x71, 0x41, 0x3b, 0x4c, 0xa8, 0xe5, 0x0f, 0x41, 0xfe, 0x91, 0x42, 0x58, 0x85, 0xd0, 0x4e, 0x76, + 0xdf, 0xfb, 0xfa, 0xf3, 0xbe, 0x7d, 0xef, 0x05, 0xf4, 0x04, 0x91, 0x02, 0x1d, 0x6f, 0xa3, 0xa3, + 0x8a, 0xc8, 0x93, 0x54, 0x48, 0xae, 0x39, 0xec, 0x32, 0x3a, 0xa4, 0xb2, 0x4a, 0x4d, 0x2e, 0x3d, + 0xde, 0x8e, 0x56, 0x0b, 0x5e, 0x70, 0x9b, 0x42, 0xe6, 0xe6, 0x54, 0xd1, 0x46, 0xc1, 0x79, 0x51, + 0x12, 0x84, 0x05, 0x45, 0x98, 0x31, 0xae, 0xb1, 0xa6, 0x9c, 0x29, 0x9f, 0x9d, 0x83, 0x95, 0xc6, + 0x9a, 0xb8, 0x60, 0xb2, 0x0a, 0xe0, 0xbe, 0xa9, 0x33, 0xc0, 0x12, 0x4f, 0x54, 0x46, 0x8e, 0x2a, + 0xa2, 0x74, 0xf2, 0x12, 0xf4, 0x1a, 0x51, 0x25, 0x38, 0x53, 0x04, 0x3e, 0x07, 0x1d, 0x61, 0x23, + 0x61, 0x70, 0x3f, 0x78, 0xbc, 0xb2, 0xb3, 0x96, 0x36, 0x6d, 0xa5, 0x4e, 0xdf, 0x5f, 0x3a, 0xbd, + 0xd8, 0x6c, 0x65, 0x5e, 0x9b, 0xbc, 0x02, 0x91, 0x85, 0xbd, 0x96, 0x78, 0x4c, 0xe4, 0x80, 0x2b, + 0x6a, 0x5c, 0xf9, 0x52, 0xf0, 0x1e, 0x00, 0x9a, 0x1f, 0x12, 0x96, 0x0b, 0x4c, 0xa5, 0xe5, 0x2e, + 0x67, 0xcb, 0x36, 0x32, 0xc0, 0x54, 0xc2, 0x35, 0xd0, 0xd1, 0xf6, 0x5d, 0xd8, 0xb6, 0x29, 0xff, + 0x2b, 0x39, 0x6f, 0x83, 0xf5, 0x85, 0xd4, 0xb9, 0xd5, 0x1b, 0xc2, 0xc7, 0xbc, 0xd9, 0xf0, 0x92, + 0xd9, 0xfa, 0xcd, 0x5c, 0x09, 0xdf, 0x81, 0x3b, 0xf5, 0x3d, 0x67, 0xdc, 0x1c, 0xb8, 0x74, 0x85, + 0xfb, 0xa9, 0xf9, 0x4f, 0xe7, 0x17, 0x9b, 0x8f, 0x0a, 0xaa, 0x0f, 0xaa, 0x61, 0x3a, 0xe2, 0x13, + 0x34, 0xe2, 0x6a, 0xc2, 0x95, 0x3f, 0x9e, 0xaa, 0xf1, 0x21, 0xd2, 0x27, 0x82, 0xa8, 0x74, 0x97, + 0x8c, 0xb2, 0xdb, 0x35, 0x68, 0xcf, 0x73, 0xe0, 0x1b, 0xd0, 0xad, 0x98, 0x24, 0xb8, 0xa4, 0x1f, + 0xc8, 0x38, 0x17, 0xac, 0x0c, 0xaf, 0x5d, 0x89, 0x7c, 0xeb, 0x37, 0x65, 0xc0, 0x4a, 0xb8, 0x0f, + 0x6e, 0x4e, 0xb0, 0x2c, 0x28, 0xcb, 0xa5, 0x19, 0x77, 0xb8, 0x74, 0x25, 0xe8, 0x8a, 0x63, 0x64, + 0x06, 0xb1, 0xf3, 0xa9, 0x0d, 0xae, 0xdb, 0xe6, 0x42, 0x06, 0x3a, 0x6e, 0xa6, 0x30, 0xf9, 0xbb, + 0x7d, 0x97, 0xd7, 0x26, 0x7a, 0xf0, 0x4f, 0x8d, 0x9b, 0x4c, 0xb2, 0xfe, 0xf1, 0xdb, 0xcf, 0xaf, + 0xed, 0xbb, 0xb0, 0x87, 0x9c, 0x18, 0xd9, 0xb5, 0x74, 0xbb, 0x02, 0x3f, 0x07, 0xa0, 0xdb, 0x9c, + 0x28, 0xdc, 0x5a, 0x08, 0x5d, 0xb8, 0x4c, 0xd1, 0x93, 0xff, 0xd2, 0x7a, 0x23, 0x0f, 0xad, 0x91, + 0x18, 0x6e, 0x34, 0x8c, 0xb8, 0xfd, 0xca, 0xeb, 0xe9, 0xf5, 0x77, 0x4f, 0xa7, 0x71, 0x70, 0x36, + 0x8d, 0x83, 0x1f, 0xd3, 0x38, 0xf8, 0x32, 0x8b, 0x5b, 0x67, 0xb3, 0xb8, 0xf5, 0x7d, 0x16, 0xb7, + 0xde, 0x6e, 0xfd, 0xd1, 0xda, 0x3d, 0x4b, 0x78, 0x71, 0x80, 0x29, 0xab, 0x69, 0xef, 0x3d, 0xcf, + 0xb4, 0x78, 0xd8, 0xb1, 0x5f, 0xdb, 0xb3, 0x5f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x18, 0x52, 0x93, + 0x1b, 0xdd, 0x03, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -479,6 +493,36 @@ func (m *QueryTraderPositionResponse) MarshalToSizedBuffer(dAtA []byte) (int, er _ = i var l int _ = l + { + size := m.MarginRatio.Size() + i -= size + if _, err := m.MarginRatio.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + { + size := m.UnrealizedPnl.Size() + i -= size + if _, err := m.UnrealizedPnl.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + { + size := m.PositionNotional.Size() + i -= size + if _, err := m.PositionNotional.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 if m.Position != nil { { size, err := m.Position.MarshalToSizedBuffer(dAtA[:i]) @@ -552,6 +596,12 @@ func (m *QueryTraderPositionResponse) Size() (n int) { l = m.Position.Size() n += 1 + l + sovQuery(uint64(l)) } + l = m.PositionNotional.Size() + n += 1 + l + sovQuery(uint64(l)) + l = m.UnrealizedPnl.Size() + n += 1 + l + sovQuery(uint64(l)) + l = m.MarginRatio.Size() + n += 1 + l + sovQuery(uint64(l)) return n } @@ -873,6 +923,108 @@ func (m *QueryTraderPositionResponse) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field PositionNotional", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.PositionNotional.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field UnrealizedPnl", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.UnrealizedPnl.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MarginRatio", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.MarginRatio.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipQuery(dAtA[iNdEx:])