@drift-labs/sdk 2.31.0-beta.4 → 2.31.0-beta.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/config.js CHANGED
@@ -78,8 +78,8 @@ async function findAllMarketAndOracles(program) {
78
78
  const perpMarketIndexes = [];
79
79
  const spotMarketIndexes = [];
80
80
  const oracleInfos = new Map();
81
- const perpMarketProgramAccounts = await program.account.perpMarket.all();
82
- const spotMarketProgramAccounts = await program.account.spotMarket.all();
81
+ const perpMarketProgramAccounts = (await program.account.perpMarket.all());
82
+ const spotMarketProgramAccounts = (await program.account.spotMarket.all());
83
83
  for (const perpMarketProgramAccount of perpMarketProgramAccounts) {
84
84
  const perpMarket = perpMarketProgramAccount.account;
85
85
  perpMarketIndexes.push(perpMarket.marketIndex);
@@ -41,5 +41,5 @@ export declare function getVammL2Generator({ marketAccount, oraclePriceData, num
41
41
  numOrders: number;
42
42
  now?: BN;
43
43
  }): L2OrderBookGenerator;
44
- export declare function groupL2(l2: L2OrderBook, grouping: BN): L2OrderBook;
44
+ export declare function groupL2(l2: L2OrderBook, grouping: BN, depth: number): L2OrderBook;
45
45
  export {};
@@ -135,14 +135,14 @@ function getVammL2Generator({ marketAccount, oraclePriceData, numOrders, now, })
135
135
  };
136
136
  }
137
137
  exports.getVammL2Generator = getVammL2Generator;
138
- function groupL2(l2, grouping) {
138
+ function groupL2(l2, grouping, depth) {
139
139
  return {
140
- bids: groupL2Levels(l2.bids, grouping, __1.PositionDirection.LONG),
141
- asks: groupL2Levels(l2.asks, grouping, __1.PositionDirection.SHORT),
140
+ bids: groupL2Levels(l2.bids, grouping, __1.PositionDirection.LONG, depth),
141
+ asks: groupL2Levels(l2.asks, grouping, __1.PositionDirection.SHORT, depth),
142
142
  };
143
143
  }
144
144
  exports.groupL2 = groupL2;
145
- function groupL2Levels(levels, grouping, direction) {
145
+ function groupL2Levels(levels, grouping, direction, depth) {
146
146
  const groupedLevels = [];
147
147
  for (const level of levels) {
148
148
  const price = (0, __1.standardizePrice)(level.price, grouping, direction);
@@ -168,6 +168,9 @@ function groupL2Levels(levels, grouping, direction) {
168
168
  };
169
169
  groupedLevels.push(groupedLevel);
170
170
  }
171
+ if (groupedLevels.length === depth) {
172
+ break;
173
+ }
171
174
  }
172
175
  return groupedLevels;
173
176
  }
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "2.31.0-beta.4",
2
+ "version": "2.31.0-beta.6",
3
3
  "name": "drift",
4
4
  "instructions": [
5
5
  {
@@ -5,6 +5,7 @@ import { OraclePriceData } from '../oracles/types';
5
5
  import { DLOB } from '../dlob/DLOB';
6
6
  import { PublicKey } from '@solana/web3.js';
7
7
  import { Orderbook } from '@project-serum/serum';
8
+ import { L2OrderBook } from '../dlob/orderBookLevels';
8
9
  export type PriceImpactUnit = 'entryPrice' | 'maxPrice' | 'priceDelta' | 'priceDeltaAsNumber' | 'pctAvg' | 'pctMax' | 'quoteAssetAmount' | 'quoteAssetAmountPeg' | 'acquiredBaseAssetAmount' | 'acquiredQuoteAssetAmount' | 'all';
9
10
  /**
10
11
  * Calculates avg/max slippage (price impact) for candidate trade
@@ -104,3 +105,11 @@ export declare function calculateEstimatedSpotEntryPrice(assetType: AssetType, a
104
105
  baseFilled: BN;
105
106
  quoteFilled: BN;
106
107
  };
108
+ export declare function calculateEstimatedEntryPriceWithL2(assetType: AssetType, amount: BN, direction: PositionDirection, basePrecision: BN, l2: L2OrderBook): {
109
+ entryPrice: BN;
110
+ priceImpact: BN;
111
+ bestPrice: BN;
112
+ worstPrice: BN;
113
+ baseFilled: BN;
114
+ quoteFilled: BN;
115
+ };
package/lib/math/trade.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.calculateEstimatedSpotEntryPrice = exports.calculateEstimatedPerpEntryPrice = exports.calculateTargetPriceTrade = exports.calculateTradeAcquiredAmounts = exports.calculateTradeSlippage = void 0;
3
+ exports.calculateEstimatedEntryPriceWithL2 = exports.calculateEstimatedSpotEntryPrice = exports.calculateEstimatedPerpEntryPrice = exports.calculateTargetPriceTrade = exports.calculateTradeAcquiredAmounts = exports.calculateTradeSlippage = void 0;
4
4
  const types_1 = require("../types");
5
5
  const anchor_1 = require("@coral-xyz/anchor");
6
6
  const assert_1 = require("../assert/assert");
@@ -571,3 +571,61 @@ function calculateEstimatedSpotEntryPrice(assetType, amount, direction, market,
571
571
  };
572
572
  }
573
573
  exports.calculateEstimatedSpotEntryPrice = calculateEstimatedSpotEntryPrice;
574
+ function calculateEstimatedEntryPriceWithL2(assetType, amount, direction, basePrecision, l2) {
575
+ const takerIsLong = (0, types_2.isVariant)(direction, 'long');
576
+ let cumulativeBaseFilled = numericConstants_1.ZERO;
577
+ let cumulativeQuoteFilled = numericConstants_1.ZERO;
578
+ const levels = [...(takerIsLong ? l2.asks : l2.bids)];
579
+ let nextLevel = levels.shift();
580
+ let bestPrice;
581
+ let worstPrice;
582
+ if (nextLevel) {
583
+ bestPrice = nextLevel.price;
584
+ worstPrice = nextLevel.price;
585
+ }
586
+ else {
587
+ bestPrice = takerIsLong ? numericConstants_1.BN_MAX : numericConstants_1.ZERO;
588
+ worstPrice = bestPrice;
589
+ }
590
+ if (assetType === 'base') {
591
+ while (!cumulativeBaseFilled.eq(amount) && nextLevel) {
592
+ const price = nextLevel.price;
593
+ const size = nextLevel.size;
594
+ worstPrice = price;
595
+ const baseFilled = anchor_1.BN.min(size, amount.sub(cumulativeBaseFilled));
596
+ const quoteFilled = baseFilled.mul(price).div(basePrecision);
597
+ cumulativeBaseFilled = cumulativeBaseFilled.add(baseFilled);
598
+ cumulativeQuoteFilled = cumulativeQuoteFilled.add(quoteFilled);
599
+ nextLevel = levels.shift();
600
+ }
601
+ }
602
+ else {
603
+ while (!cumulativeQuoteFilled.eq(amount) && nextLevel) {
604
+ const price = nextLevel.price;
605
+ const size = nextLevel.size;
606
+ worstPrice = price;
607
+ const quoteFilled = anchor_1.BN.min(size.mul(price).div(basePrecision), amount.sub(cumulativeQuoteFilled));
608
+ const baseFilled = quoteFilled.mul(basePrecision).div(price);
609
+ cumulativeBaseFilled = cumulativeBaseFilled.add(baseFilled);
610
+ cumulativeQuoteFilled = cumulativeQuoteFilled.add(quoteFilled);
611
+ nextLevel = levels.shift();
612
+ }
613
+ }
614
+ const entryPrice = cumulativeQuoteFilled
615
+ .mul(basePrecision)
616
+ .div(cumulativeBaseFilled);
617
+ const priceImpact = entryPrice
618
+ .sub(bestPrice)
619
+ .mul(numericConstants_1.PRICE_PRECISION)
620
+ .div(bestPrice)
621
+ .abs();
622
+ return {
623
+ entryPrice,
624
+ priceImpact,
625
+ bestPrice,
626
+ worstPrice,
627
+ baseFilled: cumulativeBaseFilled,
628
+ quoteFilled: cumulativeQuoteFilled,
629
+ };
630
+ }
631
+ exports.calculateEstimatedEntryPriceWithL2 = calculateEstimatedEntryPriceWithL2;
package/lib/memcmp.d.ts CHANGED
@@ -3,3 +3,4 @@ export declare function getUserFilter(): MemcmpFilter;
3
3
  export declare function getNonIdleUserFilter(): MemcmpFilter;
4
4
  export declare function getUserWithOrderFilter(): MemcmpFilter;
5
5
  export declare function getUserWithAuctionFilter(): MemcmpFilter;
6
+ export declare function getUserThatHasBeenLP(): MemcmpFilter;
package/lib/memcmp.js CHANGED
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.getUserWithAuctionFilter = exports.getUserWithOrderFilter = exports.getNonIdleUserFilter = exports.getUserFilter = void 0;
6
+ exports.getUserThatHasBeenLP = exports.getUserWithAuctionFilter = exports.getUserWithOrderFilter = exports.getNonIdleUserFilter = exports.getUserFilter = void 0;
7
7
  const bs58_1 = __importDefault(require("bs58"));
8
8
  const anchor_1 = require("@coral-xyz/anchor");
9
9
  function getUserFilter() {
@@ -42,3 +42,12 @@ function getUserWithAuctionFilter() {
42
42
  };
43
43
  }
44
44
  exports.getUserWithAuctionFilter = getUserWithAuctionFilter;
45
+ function getUserThatHasBeenLP() {
46
+ return {
47
+ memcmp: {
48
+ offset: 4267,
49
+ bytes: bs58_1.default.encode(Uint8Array.from([99])),
50
+ },
51
+ };
52
+ }
53
+ exports.getUserThatHasBeenLP = getUserThatHasBeenLP;
@@ -55,11 +55,20 @@ class RetryTxSender {
55
55
  return tx;
56
56
  }
57
57
  async sendVersionedTransaction(tx, additionalSigners, opts) {
58
- additionalSigners === null || additionalSigners === void 0 ? void 0 : additionalSigners.filter((s) => s !== undefined).forEach((kp) => {
59
- tx.sign([kp]);
60
- });
58
+ let signedTx;
61
59
  // @ts-ignore
62
- const signedTx = await this.provider.wallet.signTransaction(tx);
60
+ if (this.provider.wallet.payer) {
61
+ // @ts-ignore
62
+ tx.sign((additionalSigners !== null && additionalSigners !== void 0 ? additionalSigners : []).concat(this.provider.wallet.payer));
63
+ signedTx = tx;
64
+ }
65
+ else {
66
+ additionalSigners === null || additionalSigners === void 0 ? void 0 : additionalSigners.filter((s) => s !== undefined).forEach((kp) => {
67
+ tx.sign([kp]);
68
+ });
69
+ // @ts-ignore
70
+ signedTx = await this.provider.wallet.signTransaction(tx);
71
+ }
63
72
  if (opts === undefined) {
64
73
  opts = this.provider.opts;
65
74
  }
package/lib/user.d.ts CHANGED
@@ -82,7 +82,7 @@ export declare class User {
82
82
  * @returns : the dust base asset amount (ie, < stepsize)
83
83
  * @returns : pnl from settle
84
84
  */
85
- getSettledLPPosition(marketIndex: number): [PerpPosition, BN, BN];
85
+ getPerpPositionWithLPSettle(marketIndex: number, originalPosition?: PerpPosition): [PerpPosition, BN, BN];
86
86
  /**
87
87
  * calculates Buying Power = free collateral / initial margin ratio
88
88
  * @returns : Precision QUOTE_PRECISION
package/lib/user.js CHANGED
@@ -175,12 +175,12 @@ class User {
175
175
  * @returns : the dust base asset amount (ie, < stepsize)
176
176
  * @returns : pnl from settle
177
177
  */
178
- getSettledLPPosition(marketIndex) {
179
- const _position = this.getPerpPosition(marketIndex);
180
- const position = this.getClonedPosition(_position);
181
- if (position.lpShares.eq(numericConstants_1.ZERO)) {
182
- return [position, numericConstants_1.ZERO, numericConstants_1.ZERO];
178
+ getPerpPositionWithLPSettle(marketIndex, originalPosition) {
179
+ originalPosition = originalPosition !== null && originalPosition !== void 0 ? originalPosition : this.getPerpPosition(marketIndex);
180
+ if (originalPosition.lpShares.eq(numericConstants_1.ZERO)) {
181
+ return [originalPosition, numericConstants_1.ZERO, numericConstants_1.ZERO];
183
182
  }
183
+ const position = this.getClonedPosition(originalPosition);
184
184
  const market = this.driftClient.getPerpMarketAccount(position.marketIndex);
185
185
  const nShares = position.lpShares;
186
186
  const deltaBaa = market.amm.baseAssetAmountPerLp
@@ -192,11 +192,10 @@ class User {
192
192
  .mul(nShares)
193
193
  .div(numericConstants_1.AMM_RESERVE_PRECISION);
194
194
  function sign(v) {
195
- const sign = { true: new _1.BN(1), false: new _1.BN(-1) }[v.gte(numericConstants_1.ZERO).toString()];
196
- return sign;
195
+ return v.isNeg() ? new _1.BN(-1) : new _1.BN(1);
197
196
  }
198
- function standardize(amount, stepsize) {
199
- const remainder = amount.abs().mod(stepsize).mul(sign(amount));
197
+ function standardize(amount, stepSize) {
198
+ const remainder = amount.abs().mod(stepSize).mul(sign(amount));
200
199
  const standardizedAmount = amount.sub(remainder);
201
200
  return [standardizedAmount, remainder];
202
201
  }
@@ -319,7 +318,7 @@ class User {
319
318
  const quoteSpotMarket = this.driftClient.getSpotMarketAccount(market.quoteSpotMarketIndex);
320
319
  const quoteOraclePriceData = this.getOracleDataForSpotMarket(market.quoteSpotMarketIndex);
321
320
  if (perpPosition.lpShares.gt(numericConstants_1.ZERO)) {
322
- perpPosition = this.getSettledLPPosition(perpPosition.marketIndex)[0];
321
+ perpPosition = this.getPerpPositionWithLPSettle(perpPosition.marketIndex)[0];
323
322
  }
324
323
  let positionUnrealizedPnl = (0, _1.calculatePositionPNL)(market, perpPosition, withFunding, oraclePriceData);
325
324
  let quotePrice;
@@ -546,7 +545,7 @@ class User {
546
545
  // clone so we dont mutate the position
547
546
  perpPosition = this.getClonedPosition(perpPosition);
548
547
  // settle position
549
- const [settledPosition, dustBaa, _] = this.getSettledLPPosition(market.marketIndex);
548
+ const [settledPosition, dustBaa, _] = this.getPerpPositionWithLPSettle(market.marketIndex);
550
549
  perpPosition.baseAssetAmount =
551
550
  settledPosition.baseAssetAmount.add(dustBaa);
552
551
  perpPosition.quoteAssetAmount = settledPosition.quoteAssetAmount;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drift-labs/sdk",
3
- "version": "2.31.0-beta.4",
3
+ "version": "2.31.0-beta.6",
4
4
  "main": "lib/index.js",
5
5
  "types": "lib/index.d.ts",
6
6
  "author": "crispheaney",
package/src/config.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { PerpMarketAccount, SpotMarketAccount } from '.';
1
2
  import {
2
3
  DevnetPerpMarkets,
3
4
  MainnetPerpMarkets,
@@ -11,7 +12,7 @@ import {
11
12
  MainnetSpotMarkets,
12
13
  } from './constants/spotMarkets';
13
14
  import { OracleInfo } from './oracles/types';
14
- import { Program } from '@coral-xyz/anchor';
15
+ import { Program, ProgramAccount } from '@coral-xyz/anchor';
15
16
 
16
17
  type DriftConfig = {
17
18
  ENV: DriftEnv;
@@ -124,8 +125,10 @@ export async function findAllMarketAndOracles(program: Program): Promise<{
124
125
  const spotMarketIndexes = [];
125
126
  const oracleInfos = new Map<string, OracleInfo>();
126
127
 
127
- const perpMarketProgramAccounts = await program.account.perpMarket.all();
128
- const spotMarketProgramAccounts = await program.account.spotMarket.all();
128
+ const perpMarketProgramAccounts =
129
+ (await program.account.perpMarket.all()) as ProgramAccount<PerpMarketAccount>[];
130
+ const spotMarketProgramAccounts =
131
+ (await program.account.spotMarket.all()) as ProgramAccount<SpotMarketAccount>[];
129
132
 
130
133
  for (const perpMarketProgramAccount of perpMarketProgramAccounts) {
131
134
  const perpMarket = perpMarketProgramAccount.account;
@@ -244,17 +244,22 @@ export function getVammL2Generator({
244
244
  };
245
245
  }
246
246
 
247
- export function groupL2(l2: L2OrderBook, grouping: BN): L2OrderBook {
247
+ export function groupL2(
248
+ l2: L2OrderBook,
249
+ grouping: BN,
250
+ depth: number
251
+ ): L2OrderBook {
248
252
  return {
249
- bids: groupL2Levels(l2.bids, grouping, PositionDirection.LONG),
250
- asks: groupL2Levels(l2.asks, grouping, PositionDirection.SHORT),
253
+ bids: groupL2Levels(l2.bids, grouping, PositionDirection.LONG, depth),
254
+ asks: groupL2Levels(l2.asks, grouping, PositionDirection.SHORT, depth),
251
255
  };
252
256
  }
253
257
 
254
258
  function groupL2Levels(
255
259
  levels: L2Level[],
256
260
  grouping: BN,
257
- direction: PositionDirection
261
+ direction: PositionDirection,
262
+ depth: number
258
263
  ): L2Level[] {
259
264
  const groupedLevels = [];
260
265
  for (const level of levels) {
@@ -281,6 +286,10 @@ function groupL2Levels(
281
286
  };
282
287
  groupedLevels.push(groupedLevel);
283
288
  }
289
+
290
+ if (groupedLevels.length === depth) {
291
+ break;
292
+ }
284
293
  }
285
294
  return groupedLevels;
286
295
  }
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "2.31.0-beta.4",
2
+ "version": "2.31.0-beta.6",
3
3
  "name": "drift",
4
4
  "instructions": [
5
5
  {
package/src/math/trade.ts CHANGED
@@ -34,6 +34,7 @@ import { OraclePriceData } from '../oracles/types';
34
34
  import { DLOB } from '../dlob/DLOB';
35
35
  import { PublicKey } from '@solana/web3.js';
36
36
  import { Orderbook } from '@project-serum/serum';
37
+ import { L2OrderBook } from '../dlob/orderBookLevels';
37
38
 
38
39
  const MAXPCT = new BN(1000); //percentage units are [0,1000] => [0,1]
39
40
 
@@ -884,3 +885,90 @@ export function calculateEstimatedSpotEntryPrice(
884
885
  quoteFilled: cumulativeQuoteFilled,
885
886
  };
886
887
  }
888
+
889
+ export function calculateEstimatedEntryPriceWithL2(
890
+ assetType: AssetType,
891
+ amount: BN,
892
+ direction: PositionDirection,
893
+ basePrecision: BN,
894
+ l2: L2OrderBook
895
+ ): {
896
+ entryPrice: BN;
897
+ priceImpact: BN;
898
+ bestPrice: BN;
899
+ worstPrice: BN;
900
+ baseFilled: BN;
901
+ quoteFilled: BN;
902
+ } {
903
+ const takerIsLong = isVariant(direction, 'long');
904
+
905
+ let cumulativeBaseFilled = ZERO;
906
+ let cumulativeQuoteFilled = ZERO;
907
+
908
+ const levels = [...(takerIsLong ? l2.asks : l2.bids)];
909
+ let nextLevel = levels.shift();
910
+
911
+ let bestPrice;
912
+ let worstPrice;
913
+ if (nextLevel) {
914
+ bestPrice = nextLevel.price;
915
+ worstPrice = nextLevel.price;
916
+ } else {
917
+ bestPrice = takerIsLong ? BN_MAX : ZERO;
918
+ worstPrice = bestPrice;
919
+ }
920
+
921
+ if (assetType === 'base') {
922
+ while (!cumulativeBaseFilled.eq(amount) && nextLevel) {
923
+ const price = nextLevel.price;
924
+ const size = nextLevel.size;
925
+
926
+ worstPrice = price;
927
+
928
+ const baseFilled = BN.min(size, amount.sub(cumulativeBaseFilled));
929
+ const quoteFilled = baseFilled.mul(price).div(basePrecision);
930
+
931
+ cumulativeBaseFilled = cumulativeBaseFilled.add(baseFilled);
932
+ cumulativeQuoteFilled = cumulativeQuoteFilled.add(quoteFilled);
933
+
934
+ nextLevel = levels.shift();
935
+ }
936
+ } else {
937
+ while (!cumulativeQuoteFilled.eq(amount) && nextLevel) {
938
+ const price = nextLevel.price;
939
+ const size = nextLevel.size;
940
+
941
+ worstPrice = price;
942
+
943
+ const quoteFilled = BN.min(
944
+ size.mul(price).div(basePrecision),
945
+ amount.sub(cumulativeQuoteFilled)
946
+ );
947
+ const baseFilled = quoteFilled.mul(basePrecision).div(price);
948
+
949
+ cumulativeBaseFilled = cumulativeBaseFilled.add(baseFilled);
950
+ cumulativeQuoteFilled = cumulativeQuoteFilled.add(quoteFilled);
951
+
952
+ nextLevel = levels.shift();
953
+ }
954
+ }
955
+
956
+ const entryPrice = cumulativeQuoteFilled
957
+ .mul(basePrecision)
958
+ .div(cumulativeBaseFilled);
959
+
960
+ const priceImpact = entryPrice
961
+ .sub(bestPrice)
962
+ .mul(PRICE_PRECISION)
963
+ .div(bestPrice)
964
+ .abs();
965
+
966
+ return {
967
+ entryPrice,
968
+ priceImpact,
969
+ bestPrice,
970
+ worstPrice,
971
+ baseFilled: cumulativeBaseFilled,
972
+ quoteFilled: cumulativeQuoteFilled,
973
+ };
974
+ }
package/src/memcmp.ts CHANGED
@@ -37,3 +37,12 @@ export function getUserWithAuctionFilter(): MemcmpFilter {
37
37
  },
38
38
  };
39
39
  }
40
+
41
+ export function getUserThatHasBeenLP(): MemcmpFilter {
42
+ return {
43
+ memcmp: {
44
+ offset: 4267,
45
+ bytes: bs58.encode(Uint8Array.from([99])),
46
+ },
47
+ };
48
+ }
@@ -119,14 +119,21 @@ export class RetryTxSender implements TxSender {
119
119
  additionalSigners?: Array<Signer>,
120
120
  opts?: ConfirmOptions
121
121
  ): Promise<TxSigAndSlot> {
122
- additionalSigners
123
- ?.filter((s): s is Signer => s !== undefined)
124
- .forEach((kp) => {
125
- tx.sign([kp]);
126
- });
127
-
122
+ let signedTx;
128
123
  // @ts-ignore
129
- const signedTx = await this.provider.wallet.signTransaction(tx);
124
+ if (this.provider.wallet.payer) {
125
+ // @ts-ignore
126
+ tx.sign((additionalSigners ?? []).concat(this.provider.wallet.payer));
127
+ signedTx = tx;
128
+ } else {
129
+ additionalSigners
130
+ ?.filter((s): s is Signer => s !== undefined)
131
+ .forEach((kp) => {
132
+ tx.sign([kp]);
133
+ });
134
+ // @ts-ignore
135
+ signedTx = await this.provider.wallet.signTransaction(tx);
136
+ }
130
137
 
131
138
  if (opts === undefined) {
132
139
  opts = this.provider.opts;
package/src/user.ts CHANGED
@@ -297,14 +297,18 @@ export class User {
297
297
  * @returns : the dust base asset amount (ie, < stepsize)
298
298
  * @returns : pnl from settle
299
299
  */
300
- public getSettledLPPosition(marketIndex: number): [PerpPosition, BN, BN] {
301
- const _position = this.getPerpPosition(marketIndex);
302
- const position = this.getClonedPosition(_position);
300
+ public getPerpPositionWithLPSettle(
301
+ marketIndex: number,
302
+ originalPosition?: PerpPosition
303
+ ): [PerpPosition, BN, BN] {
304
+ originalPosition = originalPosition ?? this.getPerpPosition(marketIndex);
303
305
 
304
- if (position.lpShares.eq(ZERO)) {
305
- return [position, ZERO, ZERO];
306
+ if (originalPosition.lpShares.eq(ZERO)) {
307
+ return [originalPosition, ZERO, ZERO];
306
308
  }
307
309
 
310
+ const position = this.getClonedPosition(originalPosition);
311
+
308
312
  const market = this.driftClient.getPerpMarketAccount(position.marketIndex);
309
313
  const nShares = position.lpShares;
310
314
 
@@ -318,14 +322,11 @@ export class User {
318
322
  .div(AMM_RESERVE_PRECISION);
319
323
 
320
324
  function sign(v: BN) {
321
- const sign = { true: new BN(1), false: new BN(-1) }[
322
- v.gte(ZERO).toString()
323
- ];
324
- return sign;
325
+ return v.isNeg() ? new BN(-1) : new BN(1);
325
326
  }
326
327
 
327
- function standardize(amount: BN, stepsize: BN) {
328
- const remainder = amount.abs().mod(stepsize).mul(sign(amount));
328
+ function standardize(amount: BN, stepSize: BN) {
329
+ const remainder = amount.abs().mod(stepSize).mul(sign(amount));
329
330
  const standardizedAmount = amount.sub(remainder);
330
331
  return [standardizedAmount, remainder];
331
332
  }
@@ -517,7 +518,9 @@ export class User {
517
518
  );
518
519
 
519
520
  if (perpPosition.lpShares.gt(ZERO)) {
520
- perpPosition = this.getSettledLPPosition(perpPosition.marketIndex)[0];
521
+ perpPosition = this.getPerpPositionWithLPSettle(
522
+ perpPosition.marketIndex
523
+ )[0];
521
524
  }
522
525
 
523
526
  let positionUnrealizedPnl = calculatePositionPNL(
@@ -1022,9 +1025,8 @@ export class User {
1022
1025
  perpPosition = this.getClonedPosition(perpPosition);
1023
1026
 
1024
1027
  // settle position
1025
- const [settledPosition, dustBaa, _] = this.getSettledLPPosition(
1026
- market.marketIndex
1027
- );
1028
+ const [settledPosition, dustBaa, _] =
1029
+ this.getPerpPositionWithLPSettle(market.marketIndex);
1028
1030
  perpPosition.baseAssetAmount =
1029
1031
  settledPosition.baseAssetAmount.add(dustBaa);
1030
1032
  perpPosition.quoteAssetAmount = settledPosition.quoteAssetAmount;