@drift-labs/sdk 2.13.0-beta.2 → 2.14.0-beta.0

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.
Files changed (67) hide show
  1. package/lib/accounts/bulkAccountLoader.d.ts +1 -0
  2. package/lib/accounts/bulkAccountLoader.js +3 -3
  3. package/lib/accounts/fetch.js +2 -2
  4. package/lib/accounts/pollingDriftClientAccountSubscriber.js +7 -7
  5. package/lib/accounts/pollingTokenAccountSubscriber.js +2 -2
  6. package/lib/accounts/pollingUserAccountSubscriber.js +2 -2
  7. package/lib/accounts/pollingUserStatsAccountSubscriber.js +2 -2
  8. package/lib/accounts/types.d.ts +1 -0
  9. package/lib/accounts/webSocketAccountSubscriber.js +1 -1
  10. package/lib/accounts/webSocketDriftClientAccountSubscriber.js +3 -3
  11. package/lib/addresses/marketAddresses.js +1 -1
  12. package/lib/addresses/pda.js +5 -1
  13. package/lib/adminClient.js +61 -57
  14. package/lib/dlob/DLOB.js +67 -67
  15. package/lib/dlob/DLOBNode.js +7 -7
  16. package/lib/dlob/NodeList.js +2 -2
  17. package/lib/driftClient.d.ts +33 -33
  18. package/lib/driftClient.js +120 -116
  19. package/lib/events/eventSubscriber.js +2 -2
  20. package/lib/events/pollingLogProvider.js +1 -1
  21. package/lib/events/types.d.ts +1 -0
  22. package/lib/examples/loadDlob.js +2 -2
  23. package/lib/examples/makeTradeExample.js +9 -9
  24. package/lib/factory/bigNum.js +9 -9
  25. package/lib/factory/oracleClient.js +2 -2
  26. package/lib/idl/drift.json +1 -1
  27. package/lib/index.js +5 -1
  28. package/lib/math/amm.js +23 -23
  29. package/lib/math/auction.js +6 -6
  30. package/lib/math/exchangeStatus.js +2 -2
  31. package/lib/math/funding.d.ts +1 -1
  32. package/lib/math/funding.js +8 -8
  33. package/lib/math/margin.js +5 -5
  34. package/lib/math/market.js +13 -13
  35. package/lib/math/oracles.js +1 -1
  36. package/lib/math/orders.js +23 -23
  37. package/lib/math/position.js +5 -5
  38. package/lib/math/repeg.js +1 -1
  39. package/lib/math/spotBalance.js +9 -9
  40. package/lib/math/spotPosition.js +3 -3
  41. package/lib/math/trade.js +42 -42
  42. package/lib/oracles/oracleClientCache.js +1 -1
  43. package/lib/oracles/pythClient.js +1 -1
  44. package/lib/token/index.js +1 -1
  45. package/lib/tokenFaucet.js +5 -1
  46. package/lib/tx/retryTxSender.js +1 -1
  47. package/lib/user.d.ts +8 -9
  48. package/lib/user.js +153 -158
  49. package/lib/userMap/userMap.js +1 -1
  50. package/lib/userMap/userStatsMap.js +3 -3
  51. package/lib/userStats.js +2 -2
  52. package/package.json +3 -3
  53. package/src/driftClient.ts +209 -68
  54. package/src/events/types.ts +15 -0
  55. package/src/idl/drift.json +1 -1
  56. package/src/math/funding.ts +7 -8
  57. package/src/math/spotBalance.ts +14 -7
  58. package/src/token/index.ts +1 -1
  59. package/src/user.ts +187 -184
  60. package/src/assert/assert.js +0 -9
  61. package/src/token/index.js +0 -38
  62. package/src/tx/types.js +0 -2
  63. package/src/tx/utils.js +0 -17
  64. package/src/util/computeUnits.js +0 -27
  65. package/src/util/getTokenAddress.js +0 -9
  66. package/src/util/promiseTimeout.js +0 -14
  67. package/src/util/tps.js +0 -27
package/lib/user.js CHANGED
@@ -142,7 +142,7 @@ class User {
142
142
  return [numericConstants_1.ZERO, numericConstants_1.ZERO];
143
143
  }
144
144
  const market = this.driftClient.getPerpMarketAccount(marketIndex);
145
- const [marketOpenBids, marketOpenAsks] = amm_1.calculateMarketOpenBidAsk(market.amm.baseAssetReserve, market.amm.minBaseAssetReserve, market.amm.maxBaseAssetReserve, market.amm.orderStepSize);
145
+ const [marketOpenBids, marketOpenAsks] = (0, amm_1.calculateMarketOpenBidAsk)(market.amm.baseAssetReserve, market.amm.minBaseAssetReserve, market.amm.maxBaseAssetReserve, market.amm.orderStepSize);
146
146
  const lpOpenBids = marketOpenBids
147
147
  .mul(position.lpShares)
148
148
  .div(market.amm.sqrtK);
@@ -245,13 +245,13 @@ class User {
245
245
  getBuyingPower(marketIndex) {
246
246
  const perpPosition = this.getPerpPosition(marketIndex);
247
247
  const worstCaseBaseAssetAmount = perpPosition
248
- ? margin_1.calculateWorstCaseBaseAssetAmount(perpPosition)
248
+ ? (0, margin_1.calculateWorstCaseBaseAssetAmount)(perpPosition)
249
249
  : numericConstants_1.ZERO;
250
250
  const freeCollateral = this.getFreeCollateral();
251
251
  return this.getBuyingPowerFromFreeCollateralAndBaseAssetAmount(marketIndex, freeCollateral, worstCaseBaseAssetAmount);
252
252
  }
253
253
  getBuyingPowerFromFreeCollateralAndBaseAssetAmount(marketIndex, freeCollateral, baseAssetAmount) {
254
- const marginRatio = _1.calculateMarketMarginRatio(this.driftClient.getPerpMarketAccount(marketIndex), baseAssetAmount, 'Initial');
254
+ const marginRatio = (0, _1.calculateMarketMarginRatio)(this.driftClient.getPerpMarketAccount(marketIndex), baseAssetAmount, 'Initial');
255
255
  return freeCollateral.mul(numericConstants_1.MARGIN_PRECISION).div(new _1.BN(marginRatio));
256
256
  }
257
257
  /**
@@ -302,11 +302,11 @@ class User {
302
302
  if (perpPosition.lpShares.gt(numericConstants_1.ZERO)) {
303
303
  perpPosition = this.getSettledLPPosition(perpPosition.marketIndex)[0];
304
304
  }
305
- let positionUnrealizedPnl = _1.calculatePositionPNL(market, perpPosition, withFunding, oraclePriceData);
305
+ let positionUnrealizedPnl = (0, _1.calculatePositionPNL)(market, perpPosition, withFunding, oraclePriceData);
306
306
  if (withWeightMarginCategory !== undefined) {
307
307
  if (positionUnrealizedPnl.gt(numericConstants_1.ZERO)) {
308
308
  positionUnrealizedPnl = positionUnrealizedPnl
309
- .mul(_1.calculateUnrealizedAssetWeight(market, quoteSpotMarket, positionUnrealizedPnl, withWeightMarginCategory, oraclePriceData))
309
+ .mul((0, _1.calculateUnrealizedAssetWeight)(market, quoteSpotMarket, positionUnrealizedPnl, withWeightMarginCategory, oraclePriceData))
310
310
  .div(new _1.BN(numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION));
311
311
  }
312
312
  }
@@ -322,21 +322,21 @@ class User {
322
322
  .perpPositions.filter((pos) => marketIndex ? pos.marketIndex === marketIndex : true)
323
323
  .reduce((pnl, perpPosition) => {
324
324
  const market = this.driftClient.getPerpMarketAccount(perpPosition.marketIndex);
325
- return pnl.add(_1.calculatePositionFundingPNL(market, perpPosition));
325
+ return pnl.add((0, _1.calculatePositionFundingPNL)(market, perpPosition));
326
326
  }, numericConstants_1.ZERO);
327
327
  }
328
328
  getSpotMarketLiabilityValue(marketIndex, marginCategory, liquidationBuffer, includeOpenOrders, strict = false, now) {
329
329
  now = now || new _1.BN(new Date().getTime() / 1000);
330
330
  return this.getUserAccount().spotPositions.reduce((totalLiabilityValue, spotPosition) => {
331
- if (spotPosition_1.isSpotPositionAvailable(spotPosition) ||
331
+ if ((0, spotPosition_1.isSpotPositionAvailable)(spotPosition) ||
332
332
  (marketIndex !== undefined &&
333
333
  spotPosition.marketIndex !== marketIndex)) {
334
334
  return totalLiabilityValue;
335
335
  }
336
336
  const spotMarketAccount = this.driftClient.getSpotMarketAccount(spotPosition.marketIndex);
337
337
  if (spotPosition.marketIndex === numericConstants_1.QUOTE_SPOT_MARKET_INDEX) {
338
- if (types_1.isVariant(spotPosition.balanceType, 'borrow')) {
339
- const tokenAmount = spotBalance_1.getTokenAmount(spotPosition.scaledBalance, spotMarketAccount, spotPosition.balanceType);
338
+ if ((0, types_1.isVariant)(spotPosition.balanceType, 'borrow')) {
339
+ const tokenAmount = (0, spotBalance_1.getTokenAmount)(spotPosition.scaledBalance, spotMarketAccount, spotPosition.balanceType);
340
340
  let weight = numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION;
341
341
  if (marginCategory === 'Initial') {
342
342
  weight = _1.BN.max(weight, new _1.BN(this.getUserAccount().maxMarginRatio));
@@ -352,8 +352,8 @@ class User {
352
352
  }
353
353
  const oraclePriceData = this.getOracleDataForSpotMarket(spotPosition.marketIndex);
354
354
  if (!includeOpenOrders) {
355
- if (types_1.isVariant(spotPosition.balanceType, 'borrow')) {
356
- const tokenAmount = spotBalance_1.getTokenAmount(spotPosition.scaledBalance, spotMarketAccount, spotPosition.balanceType);
355
+ if ((0, types_1.isVariant)(spotPosition.balanceType, 'borrow')) {
356
+ const tokenAmount = (0, spotBalance_1.getTokenAmount)(spotPosition.scaledBalance, spotMarketAccount, spotPosition.balanceType);
357
357
  const liabilityValue = this.getSpotLiabilityValue(tokenAmount, oraclePriceData, spotMarketAccount, marginCategory, liquidationBuffer, strict, now);
358
358
  return totalLiabilityValue.add(liabilityValue);
359
359
  }
@@ -361,7 +361,7 @@ class User {
361
361
  return totalLiabilityValue;
362
362
  }
363
363
  }
364
- const [worstCaseTokenAmount, worstCaseQuoteTokenAmount] = spotPosition_1.getWorstCaseTokenAmounts(spotPosition, spotMarketAccount, this.getOracleDataForSpotMarket(spotPosition.marketIndex));
364
+ const [worstCaseTokenAmount, worstCaseQuoteTokenAmount] = (0, spotPosition_1.getWorstCaseTokenAmounts)(spotPosition, spotMarketAccount, this.getOracleDataForSpotMarket(spotPosition.marketIndex));
365
365
  let newTotalLiabilityValue = totalLiabilityValue;
366
366
  if (worstCaseTokenAmount.lt(numericConstants_1.ZERO)) {
367
367
  const baseLiabilityValue = this.getSpotLiabilityValue(worstCaseTokenAmount.abs(), oraclePriceData, spotMarketAccount, marginCategory, liquidationBuffer, strict, now);
@@ -387,15 +387,15 @@ class User {
387
387
  getSpotLiabilityValue(tokenAmount, oraclePriceData, spotMarketAccount, marginCategory, liquidationBuffer, strict = false, now) {
388
388
  let liabilityValue = null;
389
389
  if (strict && spotMarketAccount.marketIndex != numericConstants_1.QUOTE_SPOT_MARKET_INDEX) {
390
- const estOracleTwap = oracles_1.calculateLiveOracleTwap(spotMarketAccount.historicalOracleData, oraclePriceData, now, numericConstants_1.FIVE_MINUTE // 5MIN
390
+ const estOracleTwap = (0, oracles_1.calculateLiveOracleTwap)(spotMarketAccount.historicalOracleData, oraclePriceData, now, numericConstants_1.FIVE_MINUTE // 5MIN
391
391
  );
392
- liabilityValue = _1.getStrictTokenValue(tokenAmount, spotMarketAccount.decimals, oraclePriceData, estOracleTwap);
392
+ liabilityValue = (0, _1.getStrictTokenValue)(tokenAmount, spotMarketAccount.decimals, oraclePriceData, estOracleTwap);
393
393
  }
394
394
  else {
395
- liabilityValue = _1.getTokenValue(tokenAmount, spotMarketAccount.decimals, oraclePriceData);
395
+ liabilityValue = (0, _1.getTokenValue)(tokenAmount, spotMarketAccount.decimals, oraclePriceData);
396
396
  }
397
397
  if (marginCategory !== undefined) {
398
- let weight = spotBalance_1.calculateLiabilityWeight(tokenAmount, spotMarketAccount, marginCategory);
398
+ let weight = (0, spotBalance_1.calculateLiabilityWeight)(tokenAmount, spotMarketAccount, marginCategory);
399
399
  if (marginCategory === 'Initial') {
400
400
  weight = _1.BN.max(weight, new _1.BN(this.getUserAccount().maxMarginRatio));
401
401
  }
@@ -411,7 +411,7 @@ class User {
411
411
  getSpotMarketAssetValue(marketIndex, marginCategory, includeOpenOrders, strict = false, now) {
412
412
  now = now || new _1.BN(new Date().getTime() / 1000);
413
413
  return this.getUserAccount().spotPositions.reduce((totalAssetValue, spotPosition) => {
414
- if (spotPosition_1.isSpotPositionAvailable(spotPosition) ||
414
+ if ((0, spotPosition_1.isSpotPositionAvailable)(spotPosition) ||
415
415
  (marketIndex !== undefined &&
416
416
  spotPosition.marketIndex !== marketIndex)) {
417
417
  return totalAssetValue;
@@ -419,8 +419,8 @@ class User {
419
419
  // Todo this needs to account for whether it's based on initial or maintenance requirements
420
420
  const spotMarketAccount = this.driftClient.getSpotMarketAccount(spotPosition.marketIndex);
421
421
  if (spotPosition.marketIndex === numericConstants_1.QUOTE_SPOT_MARKET_INDEX) {
422
- if (types_1.isVariant(spotPosition.balanceType, 'deposit')) {
423
- const tokenAmount = spotBalance_1.getTokenAmount(spotPosition.scaledBalance, spotMarketAccount, spotPosition.balanceType);
422
+ if ((0, types_1.isVariant)(spotPosition.balanceType, 'deposit')) {
423
+ const tokenAmount = (0, spotBalance_1.getTokenAmount)(spotPosition.scaledBalance, spotMarketAccount, spotPosition.balanceType);
424
424
  return totalAssetValue.add(tokenAmount);
425
425
  }
426
426
  else {
@@ -429,8 +429,8 @@ class User {
429
429
  }
430
430
  const oraclePriceData = this.getOracleDataForSpotMarket(spotPosition.marketIndex);
431
431
  if (!includeOpenOrders) {
432
- if (types_1.isVariant(spotPosition.balanceType, 'deposit')) {
433
- const tokenAmount = spotBalance_1.getTokenAmount(spotPosition.scaledBalance, spotMarketAccount, spotPosition.balanceType);
432
+ if ((0, types_1.isVariant)(spotPosition.balanceType, 'deposit')) {
433
+ const tokenAmount = (0, spotBalance_1.getTokenAmount)(spotPosition.scaledBalance, spotMarketAccount, spotPosition.balanceType);
434
434
  const assetValue = this.getSpotAssetValue(tokenAmount, oraclePriceData, spotMarketAccount, marginCategory, strict, now);
435
435
  return totalAssetValue.add(assetValue);
436
436
  }
@@ -438,7 +438,7 @@ class User {
438
438
  return totalAssetValue;
439
439
  }
440
440
  }
441
- const [worstCaseTokenAmount, worstCaseQuoteTokenAmount] = spotPosition_1.getWorstCaseTokenAmounts(spotPosition, spotMarketAccount, this.getOracleDataForSpotMarket(spotPosition.marketIndex));
441
+ const [worstCaseTokenAmount, worstCaseQuoteTokenAmount] = (0, spotPosition_1.getWorstCaseTokenAmounts)(spotPosition, spotMarketAccount, this.getOracleDataForSpotMarket(spotPosition.marketIndex));
442
442
  let newTotalAssetValue = totalAssetValue;
443
443
  if (worstCaseTokenAmount.gt(numericConstants_1.ZERO)) {
444
444
  const baseAssetValue = this.getSpotAssetValue(worstCaseTokenAmount, oraclePriceData, spotMarketAccount, marginCategory, strict, now);
@@ -453,15 +453,15 @@ class User {
453
453
  getSpotAssetValue(tokenAmount, oraclePriceData, spotMarketAccount, marginCategory, strict = false, now) {
454
454
  let assetValue = null;
455
455
  if (strict && spotMarketAccount.marketIndex != numericConstants_1.QUOTE_SPOT_MARKET_INDEX) {
456
- const estOracleTwap = oracles_1.calculateLiveOracleTwap(spotMarketAccount.historicalOracleData, oraclePriceData, now, numericConstants_1.FIVE_MINUTE // 5MIN
456
+ const estOracleTwap = (0, oracles_1.calculateLiveOracleTwap)(spotMarketAccount.historicalOracleData, oraclePriceData, now, numericConstants_1.FIVE_MINUTE // 5MIN
457
457
  );
458
- assetValue = _1.getStrictTokenValue(tokenAmount, spotMarketAccount.decimals, oraclePriceData, estOracleTwap);
458
+ assetValue = (0, _1.getStrictTokenValue)(tokenAmount, spotMarketAccount.decimals, oraclePriceData, estOracleTwap);
459
459
  }
460
460
  else {
461
- assetValue = _1.getTokenValue(tokenAmount, spotMarketAccount.decimals, oraclePriceData);
461
+ assetValue = (0, _1.getTokenValue)(tokenAmount, spotMarketAccount.decimals, oraclePriceData);
462
462
  }
463
463
  if (marginCategory !== undefined) {
464
- const weight = spotBalance_1.calculateAssetWeight(tokenAmount, spotMarketAccount, marginCategory);
464
+ const weight = (0, spotBalance_1.calculateAssetWeight)(tokenAmount, spotMarketAccount, marginCategory);
465
465
  assetValue = assetValue.mul(weight).div(numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION);
466
466
  }
467
467
  return assetValue;
@@ -482,8 +482,8 @@ class User {
482
482
  */
483
483
  getHealth() {
484
484
  const userAccount = this.getUserAccount();
485
- if (types_1.isVariant(userAccount.status, 'beingLiquidated') ||
486
- types_1.isVariant(userAccount.status, 'bankrupt')) {
485
+ if ((0, types_1.isVariant)(userAccount.status, 'beingLiquidated') ||
486
+ (0, types_1.isVariant)(userAccount.status, 'bankrupt')) {
487
487
  return 0;
488
488
  }
489
489
  const totalCollateral = this.getTotalCollateral('Maintenance');
@@ -529,25 +529,25 @@ class User {
529
529
  perpPosition.openBids = totalOpenBids;
530
530
  }
531
531
  let valuationPrice = this.getOracleDataForPerpMarket(market.marketIndex).price;
532
- if (types_1.isVariant(market.status, 'settlement')) {
532
+ if ((0, types_1.isVariant)(market.status, 'settlement')) {
533
533
  valuationPrice = market.expiryPrice;
534
534
  }
535
535
  const baseAssetAmount = includeOpenOrders
536
- ? margin_1.calculateWorstCaseBaseAssetAmount(perpPosition)
536
+ ? (0, margin_1.calculateWorstCaseBaseAssetAmount)(perpPosition)
537
537
  : perpPosition.baseAssetAmount;
538
538
  let baseAssetValue = baseAssetAmount
539
539
  .abs()
540
540
  .mul(valuationPrice)
541
541
  .div(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO.mul(numericConstants_1.PRICE_PRECISION));
542
542
  if (marginCategory) {
543
- let marginRatio = new _1.BN(_1.calculateMarketMarginRatio(market, baseAssetAmount.abs(), marginCategory));
543
+ let marginRatio = new _1.BN((0, _1.calculateMarketMarginRatio)(market, baseAssetAmount.abs(), marginCategory));
544
544
  if (marginCategory === 'Initial') {
545
545
  marginRatio = _1.BN.max(marginRatio, new _1.BN(this.getUserAccount().maxMarginRatio));
546
546
  }
547
547
  if (liquidationBuffer !== undefined) {
548
548
  marginRatio = marginRatio.add(liquidationBuffer);
549
549
  }
550
- if (types_1.isVariant(market.status, 'settlement')) {
550
+ if ((0, types_1.isVariant)(market.status, 'settlement')) {
551
551
  marginRatio = numericConstants_1.ZERO;
552
552
  }
553
553
  baseAssetValue = baseAssetValue
@@ -567,7 +567,7 @@ class User {
567
567
  getPerpPositionValue(marketIndex, oraclePriceData, includeOpenOrders = false) {
568
568
  const userPosition = this.getPerpPosition(marketIndex) || this.getEmptyPosition(marketIndex);
569
569
  const market = this.driftClient.getPerpMarketAccount(userPosition.marketIndex);
570
- return margin_1.calculateBaseAssetValueWithOracle(market, userPosition, oraclePriceData, includeOpenOrders);
570
+ return (0, margin_1.calculateBaseAssetValueWithOracle)(market, userPosition, oraclePriceData, includeOpenOrders);
571
571
  }
572
572
  getPositionSide(currentPosition) {
573
573
  if (currentPosition.baseAssetAmount.gt(numericConstants_1.ZERO)) {
@@ -586,11 +586,11 @@ class User {
586
586
  */
587
587
  getPositionEstimatedExitPriceAndPnl(position, amountToClose, useAMMClose = false) {
588
588
  const market = this.driftClient.getPerpMarketAccount(position.marketIndex);
589
- const entryPrice = position_1.calculateEntryPrice(position);
589
+ const entryPrice = (0, position_1.calculateEntryPrice)(position);
590
590
  const oraclePriceData = this.getOracleDataForPerpMarket(position.marketIndex);
591
591
  if (amountToClose) {
592
592
  if (amountToClose.eq(numericConstants_1.ZERO)) {
593
- return [_1.calculateReservePrice(market, oraclePriceData), numericConstants_1.ZERO];
593
+ return [(0, _1.calculateReservePrice)(market, oraclePriceData), numericConstants_1.ZERO];
594
594
  }
595
595
  position = {
596
596
  baseAssetAmount: amountToClose,
@@ -601,10 +601,10 @@ class User {
601
601
  }
602
602
  let baseAssetValue;
603
603
  if (useAMMClose) {
604
- baseAssetValue = _1.calculateBaseAssetValue(market, position, oraclePriceData);
604
+ baseAssetValue = (0, _1.calculateBaseAssetValue)(market, position, oraclePriceData);
605
605
  }
606
606
  else {
607
- baseAssetValue = margin_1.calculateBaseAssetValueWithOracle(market, position, oraclePriceData);
607
+ baseAssetValue = (0, margin_1.calculateBaseAssetValueWithOracle)(market, position, oraclePriceData);
608
608
  }
609
609
  if (position.baseAssetAmount.eq(numericConstants_1.ZERO)) {
610
610
  return [numericConstants_1.ZERO, numericConstants_1.ZERO];
@@ -656,7 +656,7 @@ class User {
656
656
  return numericConstants_1.ZERO;
657
657
  }
658
658
  const totalLiabilityValue = totalPerpLiability.add(totalSpotLiability);
659
- const marginRatio = _1.calculateMarketMarginRatio(market,
659
+ const marginRatio = (0, _1.calculateMarketMarginRatio)(market,
660
660
  // worstCaseBaseAssetAmount.abs(),
661
661
  numericConstants_1.ZERO, // todo
662
662
  category);
@@ -689,7 +689,7 @@ class User {
689
689
  const totalCollateral = this.getTotalCollateral('Maintenance');
690
690
  // if user being liq'd, can continue to be liq'd until total collateral above the margin requirement plus buffer
691
691
  let liquidationBuffer = undefined;
692
- const isBeingLiquidated = types_1.isVariant(this.getUserAccount().status, 'beingLiquidated');
692
+ const isBeingLiquidated = (0, types_1.isVariant)(this.getUserAccount().status, 'beingLiquidated');
693
693
  if (isBeingLiquidated) {
694
694
  liquidationBuffer = new _1.BN(this.driftClient.getStateAccount().liquidationMarginBufferRatio);
695
695
  }
@@ -697,13 +697,13 @@ class User {
697
697
  return totalCollateral.lt(maintenanceRequirement);
698
698
  }
699
699
  isBeingLiquidated() {
700
- return types_1.isOneOfVariant(this.getUserAccount().status, [
700
+ return (0, types_1.isOneOfVariant)(this.getUserAccount().status, [
701
701
  'beingLiquidated',
702
702
  'bankrupt',
703
703
  ]);
704
704
  }
705
705
  isBankrupt() {
706
- return types_1.isVariant(this.getUserAccount().status, 'bankrupt');
706
+ return (0, types_1.isVariant)(this.getUserAccount().status, 'bankrupt');
707
707
  }
708
708
  /**
709
709
  * Checks if any user position cumulative funding differs from respective market cumulative funding
@@ -724,139 +724,136 @@ class User {
724
724
  return false;
725
725
  }
726
726
  /**
727
- * Calculate the liquidation price of a perp position, with optional parameter to calculate the liquidation price after a trade
728
- * @param PerpPosition
729
- * @param positionBaseSizeChange // change in position size to calculate liquidation price for : Precision 10^13
730
- * @param partial
727
+ * Calculate the liquidation price of a spot position
728
+ * @param marketIndex
731
729
  * @returns Precision : PRICE_PRECISION
732
730
  */
733
- spotLiquidationPrice(spotPosition) {
734
- const currentSpotPosition = this.getSpotPosition(spotPosition.marketIndex);
731
+ spotLiquidationPrice(marketIndex) {
732
+ const currentSpotPosition = this.getSpotPosition(marketIndex);
735
733
  if (!currentSpotPosition) {
736
734
  return new _1.BN(-1);
737
735
  }
738
- const mtc = this.getTotalCollateral('Maintenance');
739
- const mmr = this.getMaintenanceMarginRequirement();
740
- const deltaValueToLiq = mtc.sub(mmr); // QUOTE_PRECISION
741
- const currentSpotMarket = this.driftClient.getSpotMarketAccount(spotPosition.marketIndex);
742
- const tokenAmount = spotBalance_1.getTokenAmount(currentSpotPosition.scaledBalance, currentSpotMarket, currentSpotPosition.balanceType);
743
- const tokenAmountQP = tokenAmount
744
- .mul(numericConstants_1.QUOTE_PRECISION)
745
- .div(new _1.BN(10 ** currentSpotMarket.decimals));
746
- if (tokenAmountQP.abs().eq(numericConstants_1.ZERO)) {
736
+ const totalCollateral = this.getTotalCollateral('Maintenance');
737
+ const maintenanceMarginRequirement = this.getMaintenanceMarginRequirement();
738
+ const freeCollateral = _1.BN.max(numericConstants_1.ZERO, totalCollateral.sub(maintenanceMarginRequirement));
739
+ const market = this.driftClient.getSpotMarketAccount(marketIndex);
740
+ const signedTokenAmount = (0, _1.getSignedTokenAmount)((0, spotBalance_1.getTokenAmount)(currentSpotPosition.scaledBalance, market, currentSpotPosition.balanceType), currentSpotPosition.balanceType);
741
+ if (signedTokenAmount.eq(numericConstants_1.ZERO)) {
747
742
  return new _1.BN(-1);
748
743
  }
749
- let liqPriceDelta;
750
- if (types_1.isVariant(currentSpotPosition.balanceType, 'borrow')) {
751
- liqPriceDelta = deltaValueToLiq
752
- .mul(numericConstants_1.PRICE_PRECISION)
753
- .mul(numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION)
754
- .div(tokenAmountQP)
755
- .div(new _1.BN(currentSpotMarket.maintenanceLiabilityWeight));
744
+ let freeCollateralDelta = this.calculateFreeCollateralDeltaForSpot(market, signedTokenAmount);
745
+ const oracle = market.oracle;
746
+ const perpMarketWithSameOracle = this.driftClient
747
+ .getPerpMarketAccounts()
748
+ .find((market) => market.amm.oracle.equals(oracle));
749
+ if (perpMarketWithSameOracle) {
750
+ const perpPosition = this.getPerpPosition(perpMarketWithSameOracle.marketIndex);
751
+ if (perpPosition) {
752
+ const freeCollateralDeltaForPerp = this.calculateFreeCollateralDeltaForPerp(perpMarketWithSameOracle, perpPosition, numericConstants_1.ZERO);
753
+ freeCollateralDelta = freeCollateralDelta.add(freeCollateralDeltaForPerp || numericConstants_1.ZERO);
754
+ }
756
755
  }
757
- else {
758
- liqPriceDelta = deltaValueToLiq
759
- .mul(numericConstants_1.PRICE_PRECISION)
760
- .mul(numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION)
761
- .div(tokenAmountQP)
762
- .div(new _1.BN(currentSpotMarket.maintenanceAssetWeight))
763
- .mul(new _1.BN(-1));
756
+ if (freeCollateralDelta.eq(numericConstants_1.ZERO)) {
757
+ return new _1.BN(-1);
758
+ }
759
+ const oraclePrice = this.driftClient.getOracleDataForSpotMarket(marketIndex).price;
760
+ const liqPriceDelta = freeCollateral
761
+ .mul(numericConstants_1.QUOTE_PRECISION)
762
+ .div(freeCollateralDelta);
763
+ const liqPrice = oraclePrice.sub(liqPriceDelta);
764
+ if (liqPrice.lt(numericConstants_1.ZERO)) {
765
+ return new _1.BN(-1);
764
766
  }
765
- const currentPrice = this.driftClient.getOracleDataForSpotMarket(spotPosition.marketIndex).price;
766
- const liqPrice = currentPrice.add(liqPriceDelta);
767
767
  return liqPrice;
768
768
  }
769
769
  /**
770
770
  * Calculate the liquidation price of a perp position, with optional parameter to calculate the liquidation price after a trade
771
- * @param PerpPosition
771
+ * @param marketIndex
772
772
  * @param positionBaseSizeChange // change in position size to calculate liquidation price for : Precision 10^13
773
- * @param partial
774
773
  * @returns Precision : PRICE_PRECISION
775
774
  */
776
- liquidationPrice(perpPosition, positionBaseSizeChange = numericConstants_1.ZERO) {
777
- // solves formula for example canBeLiquidated below
778
- /* example: assume BTC price is $40k (examine 10% up/down)
779
-
780
- if 10k deposit and levered 10x short BTC => BTC up $400 means:
781
- 1. higher base_asset_value (+$4k)
782
- 2. lower collateral (-$4k)
783
- 3. (10k - 4k)/(100k + 4k) => 6k/104k => .0576
784
-
785
- for 10x long, BTC down $400:
786
- 3. (10k - 4k) / (100k - 4k) = 6k/96k => .0625 */
775
+ liquidationPrice(marketIndex, positionBaseSizeChange = numericConstants_1.ZERO) {
787
776
  const totalCollateral = this.getTotalCollateral('Maintenance');
788
- // calculate the total position value ignoring any value from the target market of the trade
789
- const totalPositionValueExcludingTargetMarket = this.getTotalPerpPositionValueExcludingMarket(perpPosition.marketIndex, undefined, undefined, true);
790
- const currentPerpPosition = this.getPerpPosition(perpPosition.marketIndex) ||
791
- this.getEmptyPosition(perpPosition.marketIndex);
792
- const currentPerpPositionBaseSize = currentPerpPosition.baseAssetAmount;
793
- const proposedBaseAssetAmount = currentPerpPositionBaseSize.add(positionBaseSizeChange);
794
- // calculate position for current market after trade
795
- const proposedPerpPosition = {
796
- marketIndex: perpPosition.marketIndex,
797
- baseAssetAmount: proposedBaseAssetAmount,
798
- remainderBaseAssetAmount: 0,
799
- quoteAssetAmount: currentPerpPosition.quoteAssetAmount,
800
- lastCumulativeFundingRate: numericConstants_1.ZERO,
801
- quoteBreakEvenAmount: new _1.BN(0),
802
- quoteEntryAmount: new _1.BN(0),
803
- openOrders: 0,
804
- openBids: currentPerpPosition.openBids,
805
- openAsks: currentPerpPosition.openAsks,
806
- settledPnl: numericConstants_1.ZERO,
807
- lpShares: numericConstants_1.ZERO,
808
- lastBaseAssetAmountPerLp: numericConstants_1.ZERO,
809
- lastQuoteAssetAmountPerLp: numericConstants_1.ZERO,
810
- };
811
- if (proposedBaseAssetAmount.eq(numericConstants_1.ZERO))
777
+ const maintenanceMarginRequirement = this.getMaintenanceMarginRequirement();
778
+ const freeCollateral = _1.BN.max(numericConstants_1.ZERO, totalCollateral.sub(maintenanceMarginRequirement));
779
+ const market = this.driftClient.getPerpMarketAccount(marketIndex);
780
+ const currentPerpPosition = this.getPerpPosition(marketIndex);
781
+ let freeCollateralDelta = this.calculateFreeCollateralDeltaForPerp(market, currentPerpPosition, positionBaseSizeChange);
782
+ if (!freeCollateralDelta) {
812
783
  return new _1.BN(-1);
813
- const market = this.driftClient.getPerpMarketAccount(proposedPerpPosition.marketIndex);
814
- const proposedPerpPositionValue = margin_1.calculateBaseAssetValueWithOracle(market, proposedPerpPosition, this.getOracleDataForPerpMarket(market.marketIndex), true);
815
- // total position value after trade
816
- const totalPositionValueAfterTrade = totalPositionValueExcludingTargetMarket.add(proposedPerpPositionValue);
817
- const marginRequirementOfAll = this.getMaintenanceMarginRequirement();
818
- const positionValue = margin_1.calculateBaseAssetValueWithOracle(market, currentPerpPosition, this.getOracleDataForPerpMarket(market.marketIndex), true);
819
- const marginRequirementOfTargetMarket = positionValue
820
- .mul(new _1.BN(_1.calculateMarketMarginRatio(market, margin_1.calculateWorstCaseBaseAssetAmount(currentPerpPosition).abs(), 'Maintenance')))
821
- .div(numericConstants_1.MARGIN_PRECISION);
822
- const marginRequirementExcludingTargetMarket = marginRequirementOfAll.sub(marginRequirementOfTargetMarket);
823
- const freeCollateralExcludingTargetMarket = totalCollateral.sub(marginRequirementExcludingTargetMarket);
824
- // if the position value after the trade is less than free collateral, there is no liq price
825
- if (totalPositionValueAfterTrade.lte(freeCollateralExcludingTargetMarket) &&
826
- proposedPerpPosition.baseAssetAmount.gt(numericConstants_1.ZERO)) {
784
+ }
785
+ const oracle = this.driftClient.getPerpMarketAccount(marketIndex).amm.oracle;
786
+ const spotMarketWithSameOracle = this.driftClient
787
+ .getSpotMarketAccounts()
788
+ .find((market) => market.oracle.equals(oracle));
789
+ if (spotMarketWithSameOracle) {
790
+ const spotPosition = this.getSpotPosition(spotMarketWithSameOracle.marketIndex);
791
+ if (spotPosition) {
792
+ const signedTokenAmount = (0, _1.getSignedTokenAmount)((0, spotBalance_1.getTokenAmount)(spotPosition.scaledBalance, spotMarketWithSameOracle, spotPosition.balanceType), spotPosition.balanceType);
793
+ const spotFreeCollateralDelta = this.calculateFreeCollateralDeltaForSpot(spotMarketWithSameOracle, signedTokenAmount);
794
+ freeCollateralDelta = freeCollateralDelta.add(spotFreeCollateralDelta || numericConstants_1.ZERO);
795
+ }
796
+ }
797
+ if (freeCollateralDelta.eq(numericConstants_1.ZERO)) {
827
798
  return new _1.BN(-1);
828
799
  }
829
- const proposedWorstCastBaseAssetAmount = margin_1.calculateWorstCaseBaseAssetAmount(proposedPerpPosition);
830
- const marginRequirementTargetMarket = proposedPerpPositionValue
831
- .mul(new _1.BN(_1.calculateMarketMarginRatio(market, proposedWorstCastBaseAssetAmount.abs(), 'Maintenance')))
800
+ const oraclePrice = this.driftClient.getOracleDataForPerpMarket(marketIndex).price;
801
+ const liqPriceDelta = freeCollateral
802
+ .mul(numericConstants_1.QUOTE_PRECISION)
803
+ .div(freeCollateralDelta);
804
+ const liqPrice = oraclePrice.sub(liqPriceDelta);
805
+ if (liqPrice.lt(numericConstants_1.ZERO)) {
806
+ return new _1.BN(-1);
807
+ }
808
+ return liqPrice;
809
+ }
810
+ calculateFreeCollateralDeltaForPerp(market, perpPosition, positionBaseSizeChange) {
811
+ const currentBaseAssetAmount = perpPosition.baseAssetAmount;
812
+ const worstCaseBaseAssetAmount = (0, margin_1.calculateWorstCaseBaseAssetAmount)(perpPosition);
813
+ const orderBaseAssetAmount = worstCaseBaseAssetAmount.sub(currentBaseAssetAmount);
814
+ const proposedBaseAssetAmount = currentBaseAssetAmount.add(positionBaseSizeChange);
815
+ const proposedWorstCaseBaseAssetAmount = worstCaseBaseAssetAmount.add(positionBaseSizeChange);
816
+ const marginRatio = (0, _1.calculateMarketMarginRatio)(market, proposedWorstCaseBaseAssetAmount.abs(), 'Maintenance');
817
+ const marginRatioQuotePrecision = new _1.BN(marginRatio)
818
+ .mul(numericConstants_1.QUOTE_PRECISION)
832
819
  .div(numericConstants_1.MARGIN_PRECISION);
833
- const marginRequirementAfterTrade = marginRequirementExcludingTargetMarket.add(marginRequirementTargetMarket);
834
- const freeCollateralAfterTrade = totalCollateral.sub(marginRequirementAfterTrade);
835
- const marketMaxMaintLeverage = new _1.BN(numericConstants_1.TEN_THOUSAND.mul(numericConstants_1.TEN_THOUSAND).toNumber() /
836
- _1.calculateMarketMarginRatio(market, proposedWorstCastBaseAssetAmount.abs(), 'Maintenance'));
837
- let priceDelta;
838
- if (proposedBaseAssetAmount.lt(numericConstants_1.ZERO)) {
839
- priceDelta = freeCollateralAfterTrade
840
- .mul(marketMaxMaintLeverage) // precision is TEN_THOUSAND
841
- .div(marketMaxMaintLeverage.add(numericConstants_1.TEN_THOUSAND))
842
- .mul(numericConstants_1.PRICE_TO_QUOTE_PRECISION)
843
- .mul(numericConstants_1.AMM_RESERVE_PRECISION)
844
- .div(proposedBaseAssetAmount);
820
+ if (proposedWorstCaseBaseAssetAmount.eq(numericConstants_1.ZERO)) {
821
+ return undefined;
822
+ }
823
+ let freeCollateralDelta = numericConstants_1.ZERO;
824
+ if (proposedBaseAssetAmount.gt(numericConstants_1.ZERO)) {
825
+ freeCollateralDelta = numericConstants_1.QUOTE_PRECISION.sub(marginRatioQuotePrecision)
826
+ .mul(proposedBaseAssetAmount)
827
+ .div(numericConstants_1.BASE_PRECISION);
845
828
  }
846
829
  else {
847
- priceDelta = freeCollateralAfterTrade
848
- .mul(marketMaxMaintLeverage) // precision is TEN_THOUSAND
849
- .div(marketMaxMaintLeverage.sub(numericConstants_1.TEN_THOUSAND))
850
- .mul(numericConstants_1.PRICE_TO_QUOTE_PRECISION)
851
- .mul(numericConstants_1.AMM_RESERVE_PRECISION)
852
- .div(proposedBaseAssetAmount);
853
- }
854
- const currentPrice = this.getOracleDataForPerpMarket(perpPosition.marketIndex).price;
855
- if (priceDelta.gt(currentPrice) &&
856
- proposedPerpPosition.baseAssetAmount.gte(numericConstants_1.ZERO)) {
857
- return new _1.BN(-1);
830
+ freeCollateralDelta = numericConstants_1.QUOTE_PRECISION.neg()
831
+ .sub(marginRatioQuotePrecision)
832
+ .mul(proposedBaseAssetAmount.abs())
833
+ .div(numericConstants_1.BASE_PRECISION);
834
+ }
835
+ if (!orderBaseAssetAmount.eq(numericConstants_1.ZERO)) {
836
+ freeCollateralDelta = freeCollateralDelta.sub(marginRatioQuotePrecision);
837
+ }
838
+ return freeCollateralDelta;
839
+ }
840
+ calculateFreeCollateralDeltaForSpot(market, signedTokenAmount) {
841
+ const tokenPrecision = new _1.BN(Math.pow(10, market.decimals));
842
+ if (signedTokenAmount.gt(numericConstants_1.ZERO)) {
843
+ const assetWeight = (0, spotBalance_1.calculateAssetWeight)(signedTokenAmount, market, 'Maintenance');
844
+ return numericConstants_1.QUOTE_PRECISION.mul(assetWeight)
845
+ .div(numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION)
846
+ .mul(signedTokenAmount)
847
+ .div(tokenPrecision);
848
+ }
849
+ else {
850
+ const liabilityWeight = (0, spotBalance_1.calculateLiabilityWeight)(signedTokenAmount.abs(), market, 'Maintenance');
851
+ return numericConstants_1.QUOTE_PRECISION.neg()
852
+ .mul(liabilityWeight)
853
+ .div(numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION)
854
+ .mul(signedTokenAmount.abs())
855
+ .div(tokenPrecision);
858
856
  }
859
- return currentPrice.sub(priceDelta);
860
857
  }
861
858
  /**
862
859
  * Calculates the estimated liquidation price for a position after closing a quote amount of the position.
@@ -874,9 +871,7 @@ class User {
874
871
  .mul(closeQuoteAmount)
875
872
  .mod(currentPosition.quoteAssetAmount.abs()))
876
873
  .neg();
877
- return this.liquidationPrice({
878
- marketIndex: positionMarketIndex,
879
- }, closeBaseAmount);
874
+ return this.liquidationPrice(positionMarketIndex, closeBaseAmount);
880
875
  }
881
876
  /**
882
877
  * Get the maximum trade size for a given market, taking into account the user's current leverage, positions, collateral, etc.
@@ -902,7 +897,7 @@ class User {
902
897
  getMaxTradeSizeUSDC(targetMarketIndex, tradeSide) {
903
898
  const currentPosition = this.getPerpPosition(targetMarketIndex) ||
904
899
  this.getEmptyPosition(targetMarketIndex);
905
- const targetSide = types_1.isVariant(tradeSide, 'short') ? 'short' : 'long';
900
+ const targetSide = (0, types_1.isVariant)(tradeSide, 'short') ? 'short' : 'long';
906
901
  const currentPositionSide = (currentPosition === null || currentPosition === void 0 ? void 0 : currentPosition.baseAssetAmount.isNeg())
907
902
  ? 'short'
908
903
  : 'long';
@@ -1014,7 +1009,7 @@ class User {
1014
1009
  const nowTs = new _1.BN(Math.floor(Date.now() / 1000));
1015
1010
  const spotMarket = this.driftClient.getSpotMarketAccount(marketIndex);
1016
1011
  // eslint-disable-next-line prefer-const
1017
- let { borrowLimit, withdrawLimit } = spotBalance_1.calculateWithdrawLimit(spotMarket, nowTs);
1012
+ let { borrowLimit, withdrawLimit } = (0, spotBalance_1.calculateWithdrawLimit)(spotMarket, nowTs);
1018
1013
  const freeCollateral = this.getFreeCollateral();
1019
1014
  const oracleData = this.getOracleDataForSpotMarket(marketIndex);
1020
1015
  const precisionIncrease = numericConstants_1.TEN.pow(new _1.BN(spotMarket.decimals - 6));
@@ -1060,7 +1055,7 @@ class User {
1060
1055
  netDeposits,
1061
1056
  };
1062
1057
  }
1063
- if (types_1.isVariant(position.balanceType, 'borrow')) {
1058
+ if ((0, types_1.isVariant)(position.balanceType, 'borrow')) {
1064
1059
  return {
1065
1060
  canBypass: false,
1066
1061
  maxDepositAmount,
@@ -1068,12 +1063,12 @@ class User {
1068
1063
  depositAmount: numericConstants_1.ZERO,
1069
1064
  };
1070
1065
  }
1071
- const depositAmount = spotBalance_1.getTokenAmount(position.scaledBalance, spotMarket, 'deposit');
1066
+ const depositAmount = (0, spotBalance_1.getTokenAmount)(position.scaledBalance, spotMarket, 'deposit');
1072
1067
  if (netDeposits.lt(numericConstants_1.ZERO)) {
1073
1068
  return {
1074
1069
  canBypass: false,
1075
1070
  maxDepositAmount,
1076
- depositAmount: numericConstants_1.ZERO,
1071
+ depositAmount,
1077
1072
  netDeposits,
1078
1073
  };
1079
1074
  }
@@ -26,7 +26,7 @@ class UserMap {
26
26
  userAccountArray.push(programUserAccount.account);
27
27
  }
28
28
  if (this.accountSubscription.type === 'polling') {
29
- await __1.bulkPollingUserSubscribe(userArray, this.accountSubscription.accountLoader);
29
+ await (0, __1.bulkPollingUserSubscribe)(userArray, this.accountSubscription.accountLoader);
30
30
  }
31
31
  else {
32
32
  await Promise.all(userArray.map((user, i) => user.subscribe(userAccountArray[i])));
@@ -23,14 +23,14 @@ class UserStatsMap {
23
23
  }
24
24
  const chUserStat = new __1.UserStats({
25
25
  driftClient: this.driftClient,
26
- userStatsAccountPublicKey: __1.getUserStatsAccountPublicKey(this.driftClient.program.programId, userStat.authority),
26
+ userStatsAccountPublicKey: (0, __1.getUserStatsAccountPublicKey)(this.driftClient.program.programId, userStat.authority),
27
27
  accountSubscription: this.accountSubscription,
28
28
  });
29
29
  userStatArray.push(chUserStat);
30
30
  userStatsAccountArray.push(userStat);
31
31
  }
32
32
  if (this.accountSubscription.type === 'polling') {
33
- await __1.bulkPollingUserStatsSubscribe(userStatArray, this.accountSubscription.accountLoader);
33
+ await (0, __1.bulkPollingUserStatsSubscribe)(userStatArray, this.accountSubscription.accountLoader);
34
34
  }
35
35
  else {
36
36
  await Promise.all(userStatArray.map((userStat, i) => userStat.subscribe(userStatsAccountArray[i])));
@@ -42,7 +42,7 @@ class UserStatsMap {
42
42
  async addUserStat(authority) {
43
43
  const userStat = new __1.UserStats({
44
44
  driftClient: this.driftClient,
45
- userStatsAccountPublicKey: __1.getUserStatsAccountPublicKey(this.driftClient.program.programId, authority),
45
+ userStatsAccountPublicKey: (0, __1.getUserStatsAccountPublicKey)(this.driftClient.program.programId, authority),
46
46
  accountSubscription: this.accountSubscription,
47
47
  });
48
48
  await userStat.subscribe();
package/lib/userStats.js CHANGED
@@ -40,8 +40,8 @@ class UserStats {
40
40
  }
41
41
  else {
42
42
  return {
43
- referrer: pda_1.getUserAccountPublicKeySync(this.driftClient.program.programId, this.getAccount().referrer, 0),
44
- referrerStats: pda_1.getUserStatsAccountPublicKey(this.driftClient.program.programId, this.getAccount().referrer),
43
+ referrer: (0, pda_1.getUserAccountPublicKeySync)(this.driftClient.program.programId, this.getAccount().referrer, 0),
44
+ referrerStats: (0, pda_1.getUserStatsAccountPublicKey)(this.driftClient.program.programId, this.getAccount().referrer),
45
45
  };
46
46
  }
47
47
  }