@drift-labs/sdk 0.2.0-master.32 → 0.2.0-master.34

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 (108) hide show
  1. package/lib/accounts/bulkAccountLoader.js +2 -1
  2. package/lib/accounts/pollingClearingHouseAccountSubscriber.d.ts +2 -2
  3. package/lib/accounts/pollingClearingHouseAccountSubscriber.js +8 -8
  4. package/lib/accounts/types.d.ts +1 -0
  5. package/lib/accounts/webSocketClearingHouseAccountSubscriber.d.ts +2 -2
  6. package/lib/accounts/webSocketClearingHouseAccountSubscriber.js +7 -7
  7. package/lib/addresses/marketAddresses.js +1 -1
  8. package/lib/addresses/pda.d.ts +4 -4
  9. package/lib/addresses/pda.js +23 -22
  10. package/lib/admin.d.ts +30 -32
  11. package/lib/admin.js +111 -119
  12. package/lib/clearingHouse.d.ts +43 -34
  13. package/lib/clearingHouse.js +353 -193
  14. package/lib/clearingHouseConfig.d.ts +2 -2
  15. package/lib/clearingHouseUser.d.ts +26 -5
  16. package/lib/clearingHouseUser.js +151 -51
  17. package/lib/config.d.ts +2 -0
  18. package/lib/config.js +5 -1
  19. package/lib/constants/numericConstants.d.ts +1 -0
  20. package/lib/constants/numericConstants.js +3 -2
  21. package/lib/dlob/DLOB.d.ts +18 -11
  22. package/lib/dlob/DLOB.js +179 -107
  23. package/lib/dlob/DLOBNode.js +2 -10
  24. package/lib/dlob/NodeList.js +1 -1
  25. package/lib/events/eventSubscriber.d.ts +1 -0
  26. package/lib/events/eventSubscriber.js +11 -4
  27. package/lib/events/fetchLogs.d.ts +3 -1
  28. package/lib/events/fetchLogs.js +13 -5
  29. package/lib/events/pollingLogProvider.js +1 -1
  30. package/lib/events/types.d.ts +1 -1
  31. package/lib/events/webSocketLogProvider.js +1 -1
  32. package/lib/factory/bigNum.d.ts +5 -4
  33. package/lib/factory/bigNum.js +36 -6
  34. package/lib/idl/clearing_house.json +1540 -1246
  35. package/lib/index.d.ts +3 -0
  36. package/lib/index.js +3 -0
  37. package/lib/math/amm.js +9 -9
  38. package/lib/math/exchangeStatus.d.ts +4 -0
  39. package/lib/math/exchangeStatus.js +18 -0
  40. package/lib/math/funding.js +10 -10
  41. package/lib/math/margin.js +6 -1
  42. package/lib/math/market.js +9 -9
  43. package/lib/math/orders.d.ts +7 -3
  44. package/lib/math/orders.js +39 -31
  45. package/lib/math/repeg.js +3 -3
  46. package/lib/math/spotBalance.js +3 -3
  47. package/lib/math/spotPosition.js +2 -2
  48. package/lib/serum/serumFulfillmentConfigMap.d.ts +10 -0
  49. package/lib/serum/serumFulfillmentConfigMap.js +17 -0
  50. package/lib/serum/serumSubscriber.d.ts +4 -0
  51. package/lib/serum/serumSubscriber.js +16 -1
  52. package/lib/types.d.ts +60 -75
  53. package/lib/types.js +2 -1
  54. package/lib/userMap/userMap.d.ts +17 -1
  55. package/lib/userMap/userMap.js +12 -0
  56. package/lib/userName.d.ts +1 -0
  57. package/lib/userName.js +3 -2
  58. package/package.json +1 -1
  59. package/src/accounts/bulkAccountLoader.ts +5 -1
  60. package/src/accounts/pollingClearingHouseAccountSubscriber.ts +9 -9
  61. package/src/accounts/webSocketClearingHouseAccountSubscriber.ts +8 -8
  62. package/src/addresses/marketAddresses.ts +2 -2
  63. package/src/addresses/pda.ts +20 -20
  64. package/src/admin.ts +246 -221
  65. package/src/assert/assert.js +9 -0
  66. package/src/clearingHouse.ts +556 -236
  67. package/src/clearingHouseConfig.ts +2 -2
  68. package/src/clearingHouseUser.ts +237 -87
  69. package/src/config.ts +8 -1
  70. package/src/constants/numericConstants.ts +5 -1
  71. package/src/dlob/DLOB.ts +257 -120
  72. package/src/dlob/DLOBNode.ts +2 -14
  73. package/src/dlob/NodeList.ts +1 -1
  74. package/src/events/eventList.js +77 -0
  75. package/src/events/eventSubscriber.ts +18 -4
  76. package/src/events/fetchLogs.ts +20 -5
  77. package/src/events/pollingLogProvider.ts +1 -1
  78. package/src/events/types.ts +2 -1
  79. package/src/events/webSocketLogProvider.ts +1 -1
  80. package/src/examples/makeTradeExample.js +157 -0
  81. package/src/factory/bigNum.ts +59 -6
  82. package/src/idl/clearing_house.json +1540 -1246
  83. package/src/idl/pyth.json +98 -2
  84. package/src/index.ts +3 -0
  85. package/src/math/amm.ts +9 -9
  86. package/src/math/exchangeStatus.ts +31 -0
  87. package/src/math/funding.ts +20 -10
  88. package/src/math/margin.ts +7 -1
  89. package/src/math/market.ts +9 -9
  90. package/src/math/orders.ts +44 -29
  91. package/src/math/repeg.ts +3 -3
  92. package/src/math/spotBalance.ts +4 -4
  93. package/src/math/spotPosition.ts +2 -2
  94. package/src/serum/serumFulfillmentConfigMap.ts +26 -0
  95. package/src/serum/serumSubscriber.ts +20 -1
  96. package/src/token/index.js +38 -0
  97. package/src/tx/types.js +2 -0
  98. package/src/tx/utils.js +17 -0
  99. package/src/types.ts +65 -51
  100. package/src/userMap/userMap.ts +25 -1
  101. package/src/userName.ts +2 -1
  102. package/src/util/computeUnits.js +27 -0
  103. package/src/util/getTokenAddress.js +9 -0
  104. package/src/util/promiseTimeout.js +14 -0
  105. package/src/util/tps.js +27 -0
  106. package/tests/bn/test.ts +22 -1
  107. package/tests/dlob/helpers.ts +252 -81
  108. package/tests/dlob/test.ts +1040 -219
package/lib/index.d.ts CHANGED
@@ -33,6 +33,7 @@ export * from './events/fetchLogs';
33
33
  export * from './math/auction';
34
34
  export * from './math/spotMarket';
35
35
  export * from './math/conversion';
36
+ export * from './math/exchangeStatus';
36
37
  export * from './math/funding';
37
38
  export * from './math/market';
38
39
  export * from './math/position';
@@ -51,9 +52,11 @@ export * from './math/utils';
51
52
  export * from './config';
52
53
  export * from './constants/numericConstants';
53
54
  export * from './serum/serumSubscriber';
55
+ export * from './serum/serumFulfillmentConfigMap';
54
56
  export * from './tx/retryTxSender';
55
57
  export * from './util/computeUnits';
56
58
  export * from './util/tps';
59
+ export * from './util/promiseTimeout';
57
60
  export * from './math/spotBalance';
58
61
  export * from './constants/spotMarkets';
59
62
  export * from './clearingHouseConfig';
package/lib/index.js CHANGED
@@ -56,6 +56,7 @@ __exportStar(require("./events/fetchLogs"), exports);
56
56
  __exportStar(require("./math/auction"), exports);
57
57
  __exportStar(require("./math/spotMarket"), exports);
58
58
  __exportStar(require("./math/conversion"), exports);
59
+ __exportStar(require("./math/exchangeStatus"), exports);
59
60
  __exportStar(require("./math/funding"), exports);
60
61
  __exportStar(require("./math/market"), exports);
61
62
  __exportStar(require("./math/position"), exports);
@@ -74,9 +75,11 @@ __exportStar(require("./math/utils"), exports);
74
75
  __exportStar(require("./config"), exports);
75
76
  __exportStar(require("./constants/numericConstants"), exports);
76
77
  __exportStar(require("./serum/serumSubscriber"), exports);
78
+ __exportStar(require("./serum/serumFulfillmentConfigMap"), exports);
77
79
  __exportStar(require("./tx/retryTxSender"), exports);
78
80
  __exportStar(require("./util/computeUnits"), exports);
79
81
  __exportStar(require("./util/tps"), exports);
82
+ __exportStar(require("./util/promiseTimeout"), exports);
80
83
  __exportStar(require("./math/spotBalance"), exports);
81
84
  __exportStar(require("./constants/spotMarkets"), exports);
82
85
  __exportStar(require("./clearingHouseConfig"), exports);
package/lib/math/amm.js CHANGED
@@ -62,10 +62,10 @@ function calculateNewAmm(amm, oraclePriceData) {
62
62
  newAmm.sqrtK = newAmm.sqrtK.mul(pKNumer).div(pKDenom);
63
63
  const invariant = newAmm.sqrtK.mul(newAmm.sqrtK);
64
64
  newAmm.quoteAssetReserve = invariant.div(newAmm.baseAssetReserve);
65
- const directionToClose = amm.netBaseAssetAmount.gt(numericConstants_1.ZERO)
65
+ const directionToClose = amm.baseAssetAmountWithAmm.gt(numericConstants_1.ZERO)
66
66
  ? types_1.PositionDirection.SHORT
67
67
  : types_1.PositionDirection.LONG;
68
- const [newQuoteAssetReserve, _newBaseAssetReserve] = calculateAmmReservesAfterSwap(newAmm, 'base', amm.netBaseAssetAmount.abs(), getSwapDirection('base', directionToClose));
68
+ const [newQuoteAssetReserve, _newBaseAssetReserve] = calculateAmmReservesAfterSwap(newAmm, 'base', amm.baseAssetAmountWithAmm.abs(), getSwapDirection('base', directionToClose));
69
69
  newAmm.terminalQuoteAssetReserve = newQuoteAssetReserve;
70
70
  newPeg = (0, repeg_1.calculateBudgetedPeg)(newAmm, prePegCost, targetPrice);
71
71
  prePegCost = (0, repeg_1.calculateRepegCost)(newAmm, newPeg);
@@ -84,10 +84,10 @@ function calculateUpdatedAMM(amm, oraclePriceData) {
84
84
  const invariant = newAmm.sqrtK.mul(newAmm.sqrtK);
85
85
  newAmm.quoteAssetReserve = invariant.div(newAmm.baseAssetReserve);
86
86
  newAmm.pegMultiplier = newPeg;
87
- const directionToClose = amm.netBaseAssetAmount.gt(numericConstants_1.ZERO)
87
+ const directionToClose = amm.baseAssetAmountWithAmm.gt(numericConstants_1.ZERO)
88
88
  ? types_1.PositionDirection.SHORT
89
89
  : types_1.PositionDirection.LONG;
90
- const [newQuoteAssetReserve, _newBaseAssetReserve] = calculateAmmReservesAfterSwap(newAmm, 'base', amm.netBaseAssetAmount.abs(), getSwapDirection('base', directionToClose));
90
+ const [newQuoteAssetReserve, _newBaseAssetReserve] = calculateAmmReservesAfterSwap(newAmm, 'base', amm.baseAssetAmountWithAmm.abs(), getSwapDirection('base', directionToClose));
91
91
  newAmm.terminalQuoteAssetReserve = newQuoteAssetReserve;
92
92
  newAmm.totalFeeMinusDistributions =
93
93
  newAmm.totalFeeMinusDistributions.sub(prepegCost);
@@ -278,7 +278,7 @@ function calculateSpread(amm, direction, oraclePriceData) {
278
278
  const confIntervalPct = confInterval
279
279
  .mul(numericConstants_1.BID_ASK_SPREAD_PRECISION)
280
280
  .div(reservePrice);
281
- const [longSpread, shortSpread] = calculateSpreadBN(amm.baseSpread, targetMarkSpreadPct, confIntervalPct, amm.maxSpread, amm.quoteAssetReserve, amm.terminalQuoteAssetReserve, amm.pegMultiplier, amm.netBaseAssetAmount, reservePrice, amm.totalFeeMinusDistributions, amm.baseAssetReserve, amm.minBaseAssetReserve, amm.maxBaseAssetReserve);
281
+ const [longSpread, shortSpread] = calculateSpreadBN(amm.baseSpread, targetMarkSpreadPct, confIntervalPct, amm.maxSpread, amm.quoteAssetReserve, amm.terminalQuoteAssetReserve, amm.pegMultiplier, amm.baseAssetAmountWithAmm, reservePrice, amm.totalFeeMinusDistributions, amm.baseAssetReserve, amm.minBaseAssetReserve, amm.maxBaseAssetReserve);
282
282
  let spread;
283
283
  if ((0, types_1.isVariant)(direction, 'long')) {
284
284
  spread = longSpread;
@@ -356,10 +356,10 @@ exports.getSwapDirection = getSwapDirection;
356
356
  * @returns cost : Precision PRICE_PRECISION
357
357
  */
358
358
  function calculateTerminalPrice(market) {
359
- const directionToClose = market.amm.netBaseAssetAmount.gt(numericConstants_1.ZERO)
359
+ const directionToClose = market.amm.baseAssetAmountWithAmm.gt(numericConstants_1.ZERO)
360
360
  ? types_1.PositionDirection.SHORT
361
361
  : types_1.PositionDirection.LONG;
362
- const [newQuoteAssetReserve, newBaseAssetReserve] = calculateAmmReservesAfterSwap(market.amm, 'base', market.amm.netBaseAssetAmount.abs(), getSwapDirection('base', directionToClose));
362
+ const [newQuoteAssetReserve, newBaseAssetReserve] = calculateAmmReservesAfterSwap(market.amm, 'base', market.amm.baseAssetAmountWithAmm.abs(), getSwapDirection('base', directionToClose));
363
363
  const terminalPrice = newQuoteAssetReserve
364
364
  .mul(numericConstants_1.PRICE_PRECISION)
365
365
  .mul(market.amm.pegMultiplier)
@@ -409,7 +409,7 @@ function calculateQuoteAssetAmountSwapped(quoteAssetReserves, pegMultiplier, swa
409
409
  }
410
410
  exports.calculateQuoteAssetAmountSwapped = calculateQuoteAssetAmountSwapped;
411
411
  function calculateMaxBaseAssetAmountFillable(amm, orderDirection) {
412
- const maxFillSize = amm.baseAssetReserve.div(new anchor_1.BN(amm.maxBaseAssetAmountRatio));
412
+ const maxFillSize = amm.baseAssetReserve.div(new anchor_1.BN(amm.maxFillReserveFraction));
413
413
  let maxBaseAssetAmountOnSide;
414
414
  if ((0, types_1.isVariant)(orderDirection, 'long')) {
415
415
  maxBaseAssetAmountOnSide = anchor_1.BN.max(numericConstants_1.ZERO, amm.baseAssetReserve.sub(amm.minBaseAssetReserve));
@@ -417,6 +417,6 @@ function calculateMaxBaseAssetAmountFillable(amm, orderDirection) {
417
417
  else {
418
418
  maxBaseAssetAmountOnSide = anchor_1.BN.max(numericConstants_1.ZERO, amm.maxBaseAssetReserve.sub(amm.baseAssetReserve));
419
419
  }
420
- return (0, __1.standardizeBaseAssetAmount)(anchor_1.BN.min(maxFillSize, maxBaseAssetAmountOnSide), amm.baseAssetAmountStepSize);
420
+ return (0, __1.standardizeBaseAssetAmount)(anchor_1.BN.min(maxFillSize, maxBaseAssetAmountOnSide), amm.orderStepSize);
421
421
  }
422
422
  exports.calculateMaxBaseAssetAmountFillable = calculateMaxBaseAssetAmountFillable;
@@ -0,0 +1,4 @@
1
+ import { PerpMarketAccount, SpotMarketAccount, StateAccount } from '../types';
2
+ export declare function exchangePaused(state: StateAccount): boolean;
3
+ export declare function fillPaused(state: StateAccount, market: PerpMarketAccount | SpotMarketAccount): boolean;
4
+ export declare function ammPaused(state: StateAccount, market: PerpMarketAccount | SpotMarketAccount): boolean;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ammPaused = exports.fillPaused = exports.exchangePaused = void 0;
4
+ const types_1 = require("../types");
5
+ function exchangePaused(state) {
6
+ return (0, types_1.isVariant)(state.exchangeStatus, 'paused');
7
+ }
8
+ exports.exchangePaused = exchangePaused;
9
+ function fillPaused(state, market) {
10
+ return ((0, types_1.isOneOfVariant)(state.exchangeStatus, ['paused', 'fillPaused']) ||
11
+ (0, types_1.isOneOfVariant)(market.status, ['paused', 'fillPaused']));
12
+ }
13
+ exports.fillPaused = fillPaused;
14
+ function ammPaused(state, market) {
15
+ return ((0, types_1.isOneOfVariant)(state.exchangeStatus, ['paused', 'ammPaused']) ||
16
+ (0, types_1.isOneOfVariant)(market.status, ['paused', 'ammPaused']));
17
+ }
18
+ exports.ammPaused = ammPaused;
@@ -90,9 +90,9 @@ async function calculateAllEstimatedFundingRate(market, oraclePriceData, periodA
90
90
  let cappedAltEst;
91
91
  let largerSide;
92
92
  let smallerSide;
93
- if (market.baseAssetAmountLong.gt(market.baseAssetAmountShort.abs())) {
94
- largerSide = market.baseAssetAmountLong.abs();
95
- smallerSide = market.baseAssetAmountShort.abs();
93
+ if (market.amm.baseAssetAmountLong.gt(market.amm.baseAssetAmountShort.abs())) {
94
+ largerSide = market.amm.baseAssetAmountLong.abs();
95
+ smallerSide = market.amm.baseAssetAmountShort.abs();
96
96
  if (twapSpread.gt(new anchor_1.BN(0))) {
97
97
  return [
98
98
  markTwapWithMantissa,
@@ -103,9 +103,9 @@ async function calculateAllEstimatedFundingRate(market, oraclePriceData, periodA
103
103
  ];
104
104
  }
105
105
  }
106
- else if (market.baseAssetAmountLong.lt(market.baseAssetAmountShort.abs())) {
107
- largerSide = market.baseAssetAmountShort.abs();
108
- smallerSide = market.baseAssetAmountLong.abs();
106
+ else if (market.amm.baseAssetAmountLong.lt(market.amm.baseAssetAmountShort.abs())) {
107
+ largerSide = market.amm.baseAssetAmountShort.abs();
108
+ smallerSide = market.amm.baseAssetAmountLong.abs();
109
109
  if (twapSpread.lt(new anchor_1.BN(0))) {
110
110
  return [
111
111
  markTwapWithMantissa,
@@ -184,10 +184,10 @@ exports.calculateEstimatedFundingRate = calculateEstimatedFundingRate;
184
184
  */
185
185
  async function calculateLongShortFundingRate(market, oraclePriceData, periodAdjustment = new anchor_1.BN(1)) {
186
186
  const [_1, _2, _, cappedAltEst, interpEst] = await calculateAllEstimatedFundingRate(market, oraclePriceData, periodAdjustment);
187
- if (market.baseAssetAmountLong.gt(market.baseAssetAmountShort)) {
187
+ if (market.amm.baseAssetAmountLong.gt(market.amm.baseAssetAmountShort)) {
188
188
  return [cappedAltEst, interpEst];
189
189
  }
190
- else if (market.baseAssetAmountLong.lt(market.baseAssetAmountShort)) {
190
+ else if (market.amm.baseAssetAmountLong.lt(market.amm.baseAssetAmountShort)) {
191
191
  return [interpEst, cappedAltEst];
192
192
  }
193
193
  else {
@@ -204,10 +204,10 @@ exports.calculateLongShortFundingRate = calculateLongShortFundingRate;
204
204
  */
205
205
  async function calculateLongShortFundingRateAndLiveTwaps(market, oraclePriceData, periodAdjustment = new anchor_1.BN(1)) {
206
206
  const [markTwapLive, oracleTwapLive, _2, cappedAltEst, interpEst] = await calculateAllEstimatedFundingRate(market, oraclePriceData, periodAdjustment);
207
- if (market.baseAssetAmountLong.gt(market.baseAssetAmountShort.abs())) {
207
+ if (market.amm.baseAssetAmountLong.gt(market.amm.baseAssetAmountShort.abs())) {
208
208
  return [markTwapLive, oracleTwapLive, cappedAltEst, interpEst];
209
209
  }
210
- else if (market.baseAssetAmountLong.lt(market.baseAssetAmountShort.abs())) {
210
+ else if (market.amm.baseAssetAmountLong.lt(market.amm.baseAssetAmountShort.abs())) {
211
211
  return [markTwapLive, oracleTwapLive, interpEst, cappedAltEst];
212
212
  }
213
213
  else {
@@ -4,6 +4,7 @@ exports.calculateWorstCaseBaseAssetAmount = exports.calculateBaseAssetValueWithO
4
4
  const utils_1 = require("./utils");
5
5
  const numericConstants_1 = require("../constants/numericConstants");
6
6
  const anchor_1 = require("@project-serum/anchor");
7
+ const types_1 = require("../types");
7
8
  const assert_1 = require("../assert/assert");
8
9
  function calculateSizePremiumLiabilityWeight(size, // AMM_RESERVE_PRECISION
9
10
  imfFactor, liabilityWeight, precision) {
@@ -58,9 +59,13 @@ function calculateOraclePriceForPerpMargin(perpPosition, market, oraclePriceData
58
59
  }
59
60
  exports.calculateOraclePriceForPerpMargin = calculateOraclePriceForPerpMargin;
60
61
  function calculateBaseAssetValueWithOracle(market, perpPosition, oraclePriceData) {
62
+ let price = oraclePriceData.price;
63
+ if ((0, types_1.isVariant)(market.status, 'settlement')) {
64
+ price = market.expiryPrice;
65
+ }
61
66
  return perpPosition.baseAssetAmount
62
67
  .abs()
63
- .mul(oraclePriceData.price)
68
+ .mul(price)
64
69
  .div(numericConstants_1.AMM_RESERVE_PRECISION);
65
70
  }
66
71
  exports.calculateBaseAssetValueWithOracle = calculateBaseAssetValueWithOracle;
@@ -76,30 +76,30 @@ function calculateUnrealizedAssetWeight(market, quoteSpotMarket, unrealizedPnl,
76
76
  let assetWeight;
77
77
  switch (marginCategory) {
78
78
  case 'Initial':
79
- assetWeight = new anchor_1.BN(market.unrealizedInitialAssetWeight);
80
- if (market.unrealizedMaxImbalance.gt(numericConstants_1.ZERO)) {
79
+ assetWeight = new anchor_1.BN(market.unrealizedPnlInitialAssetWeight);
80
+ if (market.unrealizedPnlMaxImbalance.gt(numericConstants_1.ZERO)) {
81
81
  const netUnsettledPnl = calculateNetUserPnlImbalance(market, quoteSpotMarket, oraclePriceData);
82
- if (netUnsettledPnl.gt(market.unrealizedMaxImbalance)) {
82
+ if (netUnsettledPnl.gt(market.unrealizedPnlMaxImbalance)) {
83
83
  assetWeight = assetWeight
84
- .mul(market.unrealizedMaxImbalance)
84
+ .mul(market.unrealizedPnlMaxImbalance)
85
85
  .div(netUnsettledPnl);
86
86
  }
87
87
  }
88
- assetWeight = (0, margin_1.calculateSizeDiscountAssetWeight)(unrealizedPnl, market.unrealizedImfFactor, assetWeight);
88
+ assetWeight = (0, margin_1.calculateSizeDiscountAssetWeight)(unrealizedPnl, market.unrealizedPnlImfFactor, assetWeight);
89
89
  break;
90
90
  case 'Maintenance':
91
- assetWeight = new anchor_1.BN(market.unrealizedMaintenanceAssetWeight);
91
+ assetWeight = new anchor_1.BN(market.unrealizedPnlMaintenanceAssetWeight);
92
92
  break;
93
93
  }
94
94
  return assetWeight;
95
95
  }
96
96
  exports.calculateUnrealizedAssetWeight = calculateUnrealizedAssetWeight;
97
97
  function calculateMarketAvailablePNL(perpMarket, spotMarket) {
98
- return (0, spotBalance_1.getTokenAmount)(perpMarket.pnlPool.balance, spotMarket, types_1.SpotBalanceType.DEPOSIT);
98
+ return (0, spotBalance_1.getTokenAmount)(perpMarket.pnlPool.scaledBalance, spotMarket, types_1.SpotBalanceType.DEPOSIT);
99
99
  }
100
100
  exports.calculateMarketAvailablePNL = calculateMarketAvailablePNL;
101
101
  function calculateNetUserPnl(perpMarket, oraclePriceData) {
102
- const netUserPositionValue = perpMarket.amm.netBaseAssetAmount
102
+ const netUserPositionValue = perpMarket.amm.baseAssetAmountWithAmm
103
103
  .mul(oraclePriceData.price)
104
104
  .div(numericConstants_1.BASE_PRECISION)
105
105
  .div(numericConstants_1.PRICE_TO_QUOTE_PRECISION);
@@ -112,7 +112,7 @@ function calculateNetUserPnl(perpMarket, oraclePriceData) {
112
112
  exports.calculateNetUserPnl = calculateNetUserPnl;
113
113
  function calculateNetUserPnlImbalance(perpMarket, spotMarket, oraclePriceData) {
114
114
  const netUserPnl = calculateNetUserPnl(perpMarket, oraclePriceData);
115
- const pnlPool = (0, spotBalance_1.getTokenAmount)(perpMarket.pnlPool.balance, spotMarket, types_1.SpotBalanceType.DEPOSIT);
115
+ const pnlPool = (0, spotBalance_1.getTokenAmount)(perpMarket.pnlPool.scaledBalance, spotMarket, types_1.SpotBalanceType.DEPOSIT);
116
116
  const imbalance = netUserPnl.sub(pnlPool);
117
117
  return imbalance;
118
118
  }
@@ -7,8 +7,12 @@ export declare function isOrderRiskIncreasing(user: ClearingHouseUser, order: Or
7
7
  export declare function isOrderRiskIncreasingInSameDirection(user: ClearingHouseUser, order: Order): boolean;
8
8
  export declare function isOrderReduceOnly(user: ClearingHouseUser, order: Order): boolean;
9
9
  export declare function standardizeBaseAssetAmount(baseAssetAmount: BN, stepSize: BN): BN;
10
- export declare function getLimitPrice(order: Order, oraclePriceData: OraclePriceData, slot: number, perpMarket?: PerpMarketAccount): BN;
11
- export declare function isFillableByVAMM(order: Order, market: PerpMarketAccount, oraclePriceData: OraclePriceData, slot: number): boolean;
10
+ export declare function getLimitPrice(order: Order, oraclePriceData: OraclePriceData, slot: number): BN;
11
+ export declare function getOptionalLimitPrice(order: Order, oraclePriceData: OraclePriceData, slot: number): BN | undefined;
12
+ export declare function hasLimitPrice(order: Order, slot: number): boolean;
13
+ export declare function isFillableByVAMM(order: Order, market: PerpMarketAccount, oraclePriceData: OraclePriceData, slot: number, ts: number): boolean;
12
14
  export declare function calculateBaseAssetAmountForAmmToFulfill(order: Order, market: PerpMarketAccount, oraclePriceData: OraclePriceData, slot: number): BN;
13
15
  export declare function calculateBaseAssetAmountToFillUpToLimitPrice(order: Order, market: PerpMarketAccount, limitPrice: BN, oraclePriceData: OraclePriceData): BN;
14
- export declare function isOrderExpired(order: Order, slot: number): boolean;
16
+ export declare function isOrderExpired(order: Order, ts: number): boolean;
17
+ export declare function isMarketOrder(order: Order): boolean;
18
+ export declare function isLimitOrder(order: Order): boolean;
@@ -1,11 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isOrderExpired = exports.calculateBaseAssetAmountToFillUpToLimitPrice = exports.calculateBaseAssetAmountForAmmToFulfill = exports.isFillableByVAMM = exports.getLimitPrice = exports.standardizeBaseAssetAmount = exports.isOrderReduceOnly = exports.isOrderRiskIncreasingInSameDirection = exports.isOrderRiskIncreasing = void 0;
3
+ exports.isLimitOrder = exports.isMarketOrder = exports.isOrderExpired = exports.calculateBaseAssetAmountToFillUpToLimitPrice = exports.calculateBaseAssetAmountForAmmToFulfill = exports.isFillableByVAMM = exports.hasLimitPrice = exports.getOptionalLimitPrice = exports.getLimitPrice = exports.standardizeBaseAssetAmount = exports.isOrderReduceOnly = exports.isOrderRiskIncreasingInSameDirection = exports.isOrderRiskIncreasing = void 0;
4
4
  const types_1 = require("../types");
5
5
  const numericConstants_1 = require("../constants/numericConstants");
6
6
  const anchor_1 = require("@project-serum/anchor");
7
7
  const auction_1 = require("./auction");
8
- const market_1 = require("./market");
9
8
  const amm_1 = require("./amm");
10
9
  function isOrderRiskIncreasing(user, order) {
11
10
  if ((0, types_1.isVariant)(order.status, 'init')) {
@@ -80,10 +79,10 @@ function standardizeBaseAssetAmount(baseAssetAmount, stepSize) {
80
79
  return baseAssetAmount.sub(remainder);
81
80
  }
82
81
  exports.standardizeBaseAssetAmount = standardizeBaseAssetAmount;
83
- function getLimitPrice(order, oraclePriceData, slot, perpMarket) {
82
+ function getLimitPrice(order, oraclePriceData, slot) {
84
83
  let limitPrice;
85
- if (!order.oraclePriceOffset.eq(numericConstants_1.ZERO)) {
86
- limitPrice = oraclePriceData.price.add(order.oraclePriceOffset);
84
+ if (order.oraclePriceOffset !== 0) {
85
+ limitPrice = oraclePriceData.price.add(new anchor_1.BN(order.oraclePriceOffset));
87
86
  }
88
87
  else if ((0, types_1.isOneOfVariant)(order.orderType, ['market', 'triggerMarket'])) {
89
88
  if (!(0, auction_1.isAuctionComplete)(order, slot)) {
@@ -93,27 +92,13 @@ function getLimitPrice(order, oraclePriceData, slot, perpMarket) {
93
92
  limitPrice = order.price;
94
93
  }
95
94
  else {
96
- if (perpMarket) {
97
- if ((0, types_1.isVariant)(order.direction, 'long')) {
98
- const askPrice = (0, market_1.calculateAskPrice)(perpMarket, oraclePriceData);
99
- const delta = askPrice.div(new anchor_1.BN(perpMarket.amm.maxSlippageRatio));
100
- limitPrice = askPrice.add(delta);
101
- }
102
- else {
103
- const bidPrice = (0, market_1.calculateBidPrice)(perpMarket, oraclePriceData);
104
- const delta = bidPrice.div(new anchor_1.BN(perpMarket.amm.maxSlippageRatio));
105
- limitPrice = bidPrice.sub(delta);
106
- }
95
+ // check oracle validity?
96
+ const oraclePrice1Pct = oraclePriceData.price.div(new anchor_1.BN(100));
97
+ if ((0, types_1.isVariant)(order.direction, 'long')) {
98
+ limitPrice = oraclePriceData.price.add(oraclePrice1Pct);
107
99
  }
108
100
  else {
109
- // check oracle validity?
110
- const oraclePrice1Pct = oraclePriceData.price.div(new anchor_1.BN(100));
111
- if ((0, types_1.isVariant)(order.direction, 'long')) {
112
- limitPrice = oraclePriceData.price.add(oraclePrice1Pct);
113
- }
114
- else {
115
- limitPrice = oraclePriceData.price.sub(oraclePrice1Pct);
116
- }
101
+ limitPrice = oraclePriceData.price.sub(oraclePrice1Pct);
117
102
  }
118
103
  }
119
104
  }
@@ -123,10 +108,25 @@ function getLimitPrice(order, oraclePriceData, slot, perpMarket) {
123
108
  return limitPrice;
124
109
  }
125
110
  exports.getLimitPrice = getLimitPrice;
126
- function isFillableByVAMM(order, market, oraclePriceData, slot) {
111
+ function getOptionalLimitPrice(order, oraclePriceData, slot) {
112
+ if (hasLimitPrice(order, slot)) {
113
+ return getLimitPrice(order, oraclePriceData, slot);
114
+ }
115
+ else {
116
+ return undefined;
117
+ }
118
+ }
119
+ exports.getOptionalLimitPrice = getOptionalLimitPrice;
120
+ function hasLimitPrice(order, slot) {
121
+ return (order.price.gt(numericConstants_1.ZERO) ||
122
+ order.oraclePriceOffset != 0 ||
123
+ !(0, auction_1.isAuctionComplete)(order, slot));
124
+ }
125
+ exports.hasLimitPrice = hasLimitPrice;
126
+ function isFillableByVAMM(order, market, oraclePriceData, slot, ts) {
127
127
  return (((0, auction_1.isAuctionComplete)(order, slot) &&
128
128
  !calculateBaseAssetAmountForAmmToFulfill(order, market, oraclePriceData, slot).eq(numericConstants_1.ZERO)) ||
129
- isOrderExpired(order, slot));
129
+ isOrderExpired(order, ts));
130
130
  }
131
131
  exports.isFillableByVAMM = isFillableByVAMM;
132
132
  function calculateBaseAssetAmountForAmmToFulfill(order, market, oraclePriceData, slot) {
@@ -134,7 +134,7 @@ function calculateBaseAssetAmountForAmmToFulfill(order, market, oraclePriceData,
134
134
  order.triggered === false) {
135
135
  return numericConstants_1.ZERO;
136
136
  }
137
- const limitPrice = getLimitPrice(order, oraclePriceData, slot, market);
137
+ const limitPrice = getLimitPrice(order, oraclePriceData, slot);
138
138
  const baseAssetAmount = calculateBaseAssetAmountToFillUpToLimitPrice(order, market, limitPrice, oraclePriceData);
139
139
  const maxBaseAssetAmount = (0, amm_1.calculateMaxBaseAssetAmountFillable)(market.amm, order.direction);
140
140
  return anchor_1.BN.min(maxBaseAssetAmount, baseAssetAmount);
@@ -142,7 +142,7 @@ function calculateBaseAssetAmountForAmmToFulfill(order, market, oraclePriceData,
142
142
  exports.calculateBaseAssetAmountForAmmToFulfill = calculateBaseAssetAmountForAmmToFulfill;
143
143
  function calculateBaseAssetAmountToFillUpToLimitPrice(order, market, limitPrice, oraclePriceData) {
144
144
  const [maxAmountToTrade, direction] = (0, amm_1.calculateMaxBaseAssetAmountToTrade)(market.amm, limitPrice, order.direction, oraclePriceData);
145
- const baseAssetAmount = standardizeBaseAssetAmount(maxAmountToTrade, market.amm.baseAssetAmountStepSize);
145
+ const baseAssetAmount = standardizeBaseAssetAmount(maxAmountToTrade, market.amm.orderStepSize);
146
146
  // Check that directions are the same
147
147
  const sameDirection = isSameDirection(direction, order.direction);
148
148
  if (!sameDirection) {
@@ -157,12 +157,20 @@ function isSameDirection(firstDirection, secondDirection) {
157
157
  return (((0, types_1.isVariant)(firstDirection, 'long') && (0, types_1.isVariant)(secondDirection, 'long')) ||
158
158
  ((0, types_1.isVariant)(firstDirection, 'short') && (0, types_1.isVariant)(secondDirection, 'short')));
159
159
  }
160
- function isOrderExpired(order, slot) {
160
+ function isOrderExpired(order, ts) {
161
161
  if ((0, types_1.isOneOfVariant)(order.orderType, ['triggerMarket', 'triggerLimit']) ||
162
162
  !(0, types_1.isVariant)(order.status, 'open') ||
163
- order.timeInForce === 0) {
163
+ order.maxTs.eq(numericConstants_1.ZERO)) {
164
164
  return false;
165
165
  }
166
- return new anchor_1.BN(slot).sub(order.slot).gt(new anchor_1.BN(order.timeInForce));
166
+ return new anchor_1.BN(ts).gt(order.maxTs);
167
167
  }
168
168
  exports.isOrderExpired = isOrderExpired;
169
+ function isMarketOrder(order) {
170
+ return (0, types_1.isOneOfVariant)(order.orderType, ['market', 'triggerMarket']);
171
+ }
172
+ exports.isMarketOrder = isMarketOrder;
173
+ function isLimitOrder(order) {
174
+ return (0, types_1.isOneOfVariant)(order.orderType, ['limit', 'triggerLimit']);
175
+ }
176
+ exports.isLimitOrder = isLimitOrder;
package/lib/math/repeg.js CHANGED
@@ -15,7 +15,7 @@ function calculateAdjustKCost(amm, numerator, denomenator) {
15
15
  // const k = market.amm.sqrtK.mul(market.amm.sqrtK);
16
16
  const x = amm.baseAssetReserve;
17
17
  const y = amm.quoteAssetReserve;
18
- const d = amm.netBaseAssetAmount;
18
+ const d = amm.baseAssetAmountWithAmm;
19
19
  const Q = amm.pegMultiplier;
20
20
  const quoteScale = y.mul(d).mul(Q); //.div(AMM_RESERVE_PRECISION);
21
21
  const p = numerator.mul(numericConstants_1.PRICE_PRECISION).div(denomenator);
@@ -101,7 +101,7 @@ function calculateBudgetedK(amm, cost) {
101
101
  // otherwise use: (y(1-p) + (kp^2/(x*p+d)) - k/(x+d)) * Q = C solve for p
102
102
  const x = amm.baseAssetReserve;
103
103
  const y = amm.quoteAssetReserve;
104
- const d = amm.netBaseAssetAmount;
104
+ const d = amm.baseAssetAmountWithAmm;
105
105
  const Q = amm.pegMultiplier;
106
106
  const [numerator, denominator] = calculateBudgetedKBN(x, y, cost, Q, d);
107
107
  return [numerator, denominator];
@@ -120,7 +120,7 @@ function calculateBudgetedPeg(amm, cost, targetPrice) {
120
120
  const k = amm.sqrtK.mul(amm.sqrtK);
121
121
  const x = amm.baseAssetReserve;
122
122
  const y = amm.quoteAssetReserve;
123
- const d = amm.netBaseAssetAmount;
123
+ const d = amm.baseAssetAmountWithAmm;
124
124
  const Q = amm.pegMultiplier;
125
125
  const C = cost.mul(new anchor_1.BN(-1));
126
126
  const deltaQuoteAssetReserves = y.sub(k.div(x.add(d)));
@@ -177,12 +177,12 @@ function calculateWithdrawLimit(spotMarket, now) {
177
177
  const borrowTokenTwapLive = spotMarket.borrowTokenTwap
178
178
  .mul(sinceStart)
179
179
  .add(marketBorrowTokenAmount.mul(sinceLast))
180
- .div(sinceLast.add(sinceLast));
180
+ .div(sinceLast.add(sinceStart));
181
181
  const depositTokenTwapLive = spotMarket.depositTokenTwap
182
182
  .mul(sinceStart)
183
183
  .add(marketDepositTokenAmount.mul(sinceLast))
184
- .div(sinceLast.add(sinceLast));
185
- const maxBorrowTokens = anchor_1.BN.min(anchor_1.BN.max(marketDepositTokenAmount.div(new anchor_1.BN(6)), borrowTokenTwapLive.add(borrowTokenTwapLive.div(new anchor_1.BN(5)))), marketDepositTokenAmount.sub(marketDepositTokenAmount.div(new anchor_1.BN(10)))); // between ~15-90% utilization with friction on twap
184
+ .div(sinceLast.add(sinceStart));
185
+ const maxBorrowTokens = anchor_1.BN.min(anchor_1.BN.max(marketDepositTokenAmount.div(new anchor_1.BN(6)), borrowTokenTwapLive.add(borrowTokenTwapLive.div(new anchor_1.BN(5)))), marketDepositTokenAmount.sub(marketDepositTokenAmount.div(new anchor_1.BN(5)))); // between ~15-80% utilization with friction on twap
186
186
  const minDepositTokens = depositTokenTwapLive.sub(anchor_1.BN.min(anchor_1.BN.max(depositTokenTwapLive.div(new anchor_1.BN(5)), spotMarket.withdrawGuardThreshold), depositTokenTwapLive));
187
187
  return {
188
188
  borrowLimit: maxBorrowTokens.sub(marketBorrowTokenAmount),
@@ -4,11 +4,11 @@ exports.getWorstCaseTokenAmounts = exports.isSpotPositionAvailable = void 0;
4
4
  const numericConstants_1 = require("../constants/numericConstants");
5
5
  const spotBalance_1 = require("./spotBalance");
6
6
  function isSpotPositionAvailable(position) {
7
- return position.balance.eq(numericConstants_1.ZERO) && position.openOrders === 0;
7
+ return position.scaledBalance.eq(numericConstants_1.ZERO) && position.openOrders === 0;
8
8
  }
9
9
  exports.isSpotPositionAvailable = isSpotPositionAvailable;
10
10
  function getWorstCaseTokenAmounts(spotPosition, spotMarketAccount, oraclePriceData) {
11
- const tokenAmount = (0, spotBalance_1.getSignedTokenAmount)((0, spotBalance_1.getTokenAmount)(spotPosition.balance, spotMarketAccount, spotPosition.balanceType), spotPosition.balanceType);
11
+ const tokenAmount = (0, spotBalance_1.getSignedTokenAmount)((0, spotBalance_1.getTokenAmount)(spotPosition.scaledBalance, spotMarketAccount, spotPosition.balanceType), spotPosition.balanceType);
12
12
  const tokenAmountAllBidsFill = tokenAmount.add(spotPosition.openBids);
13
13
  const tokenAmountAllAsksFill = tokenAmount.add(spotPosition.openAsks);
14
14
  if (tokenAmountAllAsksFill.abs().gt(tokenAmountAllBidsFill.abs())) {
@@ -0,0 +1,10 @@
1
+ import { PublicKey } from '@solana/web3.js';
2
+ import { SerumV3FulfillmentConfigAccount } from '../types';
3
+ import { ClearingHouse } from '../clearingHouse';
4
+ export declare class SerumFulfillmentConfigMap {
5
+ clearingHouse: ClearingHouse;
6
+ map: Map<number, SerumV3FulfillmentConfigAccount>;
7
+ constructor(clearingHouse: ClearingHouse);
8
+ add(marketIndex: number, serumMarketAddress: PublicKey): Promise<void>;
9
+ get(marketIndex: number): SerumV3FulfillmentConfigAccount;
10
+ }
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SerumFulfillmentConfigMap = void 0;
4
+ class SerumFulfillmentConfigMap {
5
+ constructor(clearingHouse) {
6
+ this.map = new Map();
7
+ this.clearingHouse = clearingHouse;
8
+ }
9
+ async add(marketIndex, serumMarketAddress) {
10
+ const account = await this.clearingHouse.getSerumV3FulfillmentConfig(serumMarketAddress);
11
+ this.map.set(marketIndex, account);
12
+ }
13
+ get(marketIndex) {
14
+ return this.map.get(marketIndex);
15
+ }
16
+ }
17
+ exports.SerumFulfillmentConfigMap = SerumFulfillmentConfigMap;
@@ -1,7 +1,9 @@
1
+ /// <reference types="bn.js" />
1
2
  import { Connection, PublicKey } from '@solana/web3.js';
2
3
  import { BulkAccountLoader } from '../accounts/bulkAccountLoader';
3
4
  import { Market, Orderbook } from '@project-serum/serum';
4
5
  import { SerumMarketSubscriberConfig } from './types';
6
+ import { BN } from '@project-serum/anchor';
5
7
  export declare class SerumSubscriber {
6
8
  connection: Connection;
7
9
  programId: PublicKey;
@@ -19,5 +21,7 @@ export declare class SerumSubscriber {
19
21
  lastBidsSlot: number;
20
22
  constructor(config: SerumMarketSubscriberConfig);
21
23
  subscribe(): Promise<void>;
24
+ getBestBid(): BN | undefined;
25
+ getBestAsk(): BN | undefined;
22
26
  unsubscribe(): Promise<void>;
23
27
  }
@@ -2,6 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SerumSubscriber = void 0;
4
4
  const serum_1 = require("@project-serum/serum");
5
+ const anchor_1 = require("@project-serum/anchor");
6
+ const numericConstants_1 = require("../constants/numericConstants");
5
7
  class SerumSubscriber {
6
8
  constructor(config) {
7
9
  this.connection = config.connection;
@@ -19,7 +21,6 @@ class SerumSubscriber {
19
21
  this.asksCallbackId = this.accountLoader.addAccount(this.asksAddress, (buffer, slot) => {
20
22
  this.lastAsksSlot = slot;
21
23
  this.asks = serum_1.Orderbook.decode(this.market, buffer);
22
- console.log(this.asks.getL2(3));
23
24
  });
24
25
  this.bidsAddress = this.market.bidsAddress;
25
26
  this.bids = await this.market.loadBids(this.connection);
@@ -29,6 +30,20 @@ class SerumSubscriber {
29
30
  });
30
31
  this.subscribed = true;
31
32
  }
33
+ getBestBid() {
34
+ const bestBid = this.bids.getL2(1)[0];
35
+ if (!bestBid) {
36
+ return undefined;
37
+ }
38
+ return new anchor_1.BN(bestBid[0] * numericConstants_1.PRICE_PRECISION.toNumber());
39
+ }
40
+ getBestAsk() {
41
+ const bestAsk = this.asks.getL2(1)[0];
42
+ if (!bestAsk) {
43
+ return undefined;
44
+ }
45
+ return new anchor_1.BN(bestAsk[0] * numericConstants_1.PRICE_PRECISION.toNumber());
46
+ }
32
47
  async unsubscribe() {
33
48
  if (!this.subscribed) {
34
49
  return;