@drift-labs/sdk 0.2.0-master.26 → 0.2.0-master.28

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 (143) hide show
  1. package/lib/accounts/pollingClearingHouseAccountSubscriber.d.ts +1 -0
  2. package/lib/accounts/pollingClearingHouseAccountSubscriber.js +3 -0
  3. package/lib/accounts/types.d.ts +2 -0
  4. package/lib/accounts/webSocketClearingHouseAccountSubscriber.d.ts +1 -0
  5. package/lib/accounts/webSocketClearingHouseAccountSubscriber.js +3 -0
  6. package/lib/admin.d.ts +5 -2
  7. package/lib/admin.js +30 -4
  8. package/lib/clearingHouse.d.ts +3 -0
  9. package/lib/clearingHouse.js +19 -1
  10. package/lib/clearingHouseUser.d.ts +11 -9
  11. package/lib/clearingHouseUser.js +184 -108
  12. package/lib/config.js +1 -1
  13. package/lib/dlob/DLOB.d.ts +73 -0
  14. package/lib/dlob/DLOB.js +557 -0
  15. package/lib/dlob/DLOBNode.d.ts +52 -0
  16. package/lib/dlob/DLOBNode.js +82 -0
  17. package/lib/dlob/NodeList.d.ts +26 -0
  18. package/lib/dlob/NodeList.js +138 -0
  19. package/lib/idl/clearing_house.json +123 -203
  20. package/lib/index.d.ts +5 -0
  21. package/lib/index.js +5 -0
  22. package/lib/math/market.d.ts +3 -2
  23. package/lib/math/market.js +17 -12
  24. package/lib/math/orders.d.ts +3 -3
  25. package/lib/math/orders.js +31 -16
  26. package/lib/math/position.d.ts +3 -3
  27. package/lib/math/position.js +23 -16
  28. package/lib/math/repeg.js +8 -0
  29. package/lib/math/spotBalance.d.ts +3 -0
  30. package/lib/math/spotBalance.js +18 -1
  31. package/lib/math/spotPosition.d.ts +5 -1
  32. package/lib/math/spotPosition.js +16 -1
  33. package/lib/types.d.ts +25 -24
  34. package/lib/types.js +9 -3
  35. package/lib/userMap/userMap.d.ts +25 -0
  36. package/lib/userMap/userMap.js +73 -0
  37. package/lib/userMap/userStatsMap.d.ts +19 -0
  38. package/lib/userMap/userStatsMap.js +68 -0
  39. package/package.json +6 -3
  40. package/src/accounts/pollingClearingHouseAccountSubscriber.ts +4 -0
  41. package/src/accounts/types.ts +1 -0
  42. package/src/accounts/webSocketClearingHouseAccountSubscriber.ts +6 -0
  43. package/src/admin.ts +50 -8
  44. package/src/clearingHouse.ts +30 -1
  45. package/src/clearingHouseUser.ts +366 -167
  46. package/src/config.ts +1 -1
  47. package/src/dlob/DLOB.ts +884 -0
  48. package/src/dlob/DLOBNode.ts +163 -0
  49. package/src/dlob/NodeList.ts +185 -0
  50. package/src/idl/clearing_house.json +123 -203
  51. package/src/index.ts +5 -0
  52. package/src/math/market.ts +22 -13
  53. package/src/math/orders.ts +29 -21
  54. package/src/math/position.ts +36 -22
  55. package/src/math/repeg.ts +9 -0
  56. package/src/math/spotBalance.ts +26 -0
  57. package/src/math/spotPosition.ts +42 -1
  58. package/src/types.ts +26 -24
  59. package/src/userMap/userMap.ts +100 -0
  60. package/src/userMap/userStatsMap.ts +110 -0
  61. package/tests/bn/test.ts +2 -3
  62. package/tests/dlob/helpers.ts +322 -0
  63. package/tests/dlob/test.ts +2865 -0
  64. package/my-script/.env +0 -7
  65. package/my-script/getUserStats.ts +0 -106
  66. package/my-script/multiConnections.ts +0 -119
  67. package/my-script/test-regex.ts +0 -11
  68. package/my-script/utils.ts +0 -52
  69. package/src/accounts/bulkAccountLoader.js +0 -249
  70. package/src/accounts/bulkUserStatsSubscription.js +0 -75
  71. package/src/accounts/bulkUserSubscription.js +0 -75
  72. package/src/accounts/fetch.js +0 -92
  73. package/src/accounts/pollingClearingHouseAccountSubscriber.js +0 -465
  74. package/src/accounts/pollingOracleSubscriber.js +0 -156
  75. package/src/accounts/pollingTokenAccountSubscriber.js +0 -141
  76. package/src/accounts/pollingUserAccountSubscriber.js +0 -208
  77. package/src/accounts/pollingUserStatsAccountSubscriber.js +0 -208
  78. package/src/accounts/types.js +0 -28
  79. package/src/accounts/utils.js +0 -7
  80. package/src/accounts/webSocketAccountSubscriber.js +0 -138
  81. package/src/accounts/webSocketClearingHouseAccountSubscriber.js +0 -433
  82. package/src/accounts/webSocketUserAccountSubscriber.js +0 -113
  83. package/src/accounts/webSocketUserStatsAccountSubsriber.js +0 -113
  84. package/src/addresses/pda.js +0 -186
  85. package/src/admin.js +0 -1284
  86. package/src/assert/assert.js +0 -9
  87. package/src/clearingHouse.js +0 -3433
  88. package/src/clearingHouseConfig.js +0 -2
  89. package/src/clearingHouseUser.js +0 -874
  90. package/src/clearingHouseUserConfig.js +0 -2
  91. package/src/clearingHouseUserStats.js +0 -115
  92. package/src/clearingHouseUserStatsConfig.js +0 -2
  93. package/src/config.js +0 -80
  94. package/src/constants/numericConstants.js +0 -48
  95. package/src/constants/perpMarkets.js +0 -42
  96. package/src/constants/spotMarkets.js +0 -51
  97. package/src/events/eventList.js +0 -120
  98. package/src/events/eventSubscriber.js +0 -202
  99. package/src/events/fetchLogs.js +0 -117
  100. package/src/events/pollingLogProvider.js +0 -113
  101. package/src/events/sort.js +0 -41
  102. package/src/events/txEventCache.js +0 -74
  103. package/src/events/types.js +0 -25
  104. package/src/events/webSocketLogProvider.js +0 -76
  105. package/src/factory/bigNum.js +0 -393
  106. package/src/factory/oracleClient.js +0 -20
  107. package/src/index.js +0 -75
  108. package/src/math/amm.js +0 -422
  109. package/src/math/auction.js +0 -42
  110. package/src/math/conversion.js +0 -12
  111. package/src/math/funding.js +0 -296
  112. package/src/math/insurance.js +0 -27
  113. package/src/math/margin.js +0 -77
  114. package/src/math/market.js +0 -105
  115. package/src/math/oracles.js +0 -56
  116. package/src/math/orders.js +0 -153
  117. package/src/math/position.js +0 -172
  118. package/src/math/repeg.js +0 -128
  119. package/src/math/spotBalance.js +0 -176
  120. package/src/math/spotMarket.js +0 -8
  121. package/src/math/spotPosition.js +0 -8
  122. package/src/math/trade.js +0 -260
  123. package/src/math/utils.js +0 -27
  124. package/src/oracles/oracleClientCache.js +0 -20
  125. package/src/oracles/pythClient.js +0 -81
  126. package/src/oracles/quoteAssetOracleClient.js +0 -63
  127. package/src/oracles/switchboardClient.js +0 -101
  128. package/src/oracles/types.js +0 -2
  129. package/src/orderParams.js +0 -28
  130. package/src/serum/serumSubscriber.js +0 -102
  131. package/src/serum/types.js +0 -2
  132. package/src/slot/SlotSubscriber.js +0 -86
  133. package/src/token/index.js +0 -38
  134. package/src/tokenFaucet.js +0 -323
  135. package/src/tx/retryTxSender.js +0 -280
  136. package/src/tx/types.js +0 -2
  137. package/src/tx/utils.js +0 -18
  138. package/src/types.js +0 -216
  139. package/src/userName.js +0 -20
  140. package/src/util/computeUnits.js +0 -62
  141. package/src/util/promiseTimeout.js +0 -14
  142. package/src/util/tps.js +0 -61
  143. package/src/wallet.js +0 -72
@@ -80,7 +80,7 @@ function standardizeBaseAssetAmount(baseAssetAmount, stepSize) {
80
80
  return baseAssetAmount.sub(remainder);
81
81
  }
82
82
  exports.standardizeBaseAssetAmount = standardizeBaseAssetAmount;
83
- function getLimitPrice(order, market, oraclePriceData, slot) {
83
+ function getLimitPrice(order, oraclePriceData, slot, perpMarket) {
84
84
  let limitPrice;
85
85
  if (!order.oraclePriceOffset.eq(numericConstants_1.ZERO)) {
86
86
  limitPrice = oraclePriceData.price.add(order.oraclePriceOffset);
@@ -92,15 +92,29 @@ function getLimitPrice(order, market, oraclePriceData, slot) {
92
92
  else if (!order.price.eq(numericConstants_1.ZERO)) {
93
93
  limitPrice = order.price;
94
94
  }
95
- else if ((0, types_1.isVariant)(order.direction, 'long')) {
96
- const askPrice = (0, market_1.calculateAskPrice)(market, oraclePriceData);
97
- const delta = askPrice.div(new anchor_1.BN(market.amm.maxSlippageRatio));
98
- limitPrice = askPrice.add(delta);
99
- }
100
95
  else {
101
- const bidPrice = (0, market_1.calculateBidPrice)(market, oraclePriceData);
102
- const delta = bidPrice.div(new anchor_1.BN(market.amm.maxSlippageRatio));
103
- limitPrice = bidPrice.sub(delta);
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
+ }
107
+ }
108
+ 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
+ }
117
+ }
104
118
  }
105
119
  }
106
120
  else {
@@ -109,10 +123,10 @@ function getLimitPrice(order, market, oraclePriceData, slot) {
109
123
  return limitPrice;
110
124
  }
111
125
  exports.getLimitPrice = getLimitPrice;
112
- function isFillableByVAMM(order, market, oraclePriceData, slot, maxAuctionDuration) {
126
+ function isFillableByVAMM(order, market, oraclePriceData, slot) {
113
127
  return (((0, auction_1.isAuctionComplete)(order, slot) &&
114
128
  !calculateBaseAssetAmountForAmmToFulfill(order, market, oraclePriceData, slot).eq(numericConstants_1.ZERO)) ||
115
- isOrderExpired(order, slot, maxAuctionDuration));
129
+ isOrderExpired(order, slot));
116
130
  }
117
131
  exports.isFillableByVAMM = isFillableByVAMM;
118
132
  function calculateBaseAssetAmountForAmmToFulfill(order, market, oraclePriceData, slot) {
@@ -120,7 +134,7 @@ function calculateBaseAssetAmountForAmmToFulfill(order, market, oraclePriceData,
120
134
  order.triggered === false) {
121
135
  return numericConstants_1.ZERO;
122
136
  }
123
- const limitPrice = getLimitPrice(order, market, oraclePriceData, slot);
137
+ const limitPrice = getLimitPrice(order, oraclePriceData, slot, market);
124
138
  const baseAssetAmount = calculateBaseAssetAmountToFillUpToLimitPrice(order, market, limitPrice, oraclePriceData);
125
139
  const maxBaseAssetAmount = (0, amm_1.calculateMaxBaseAssetAmountFillable)(market.amm, order.direction);
126
140
  return anchor_1.BN.min(maxBaseAssetAmount, baseAssetAmount);
@@ -143,11 +157,12 @@ function isSameDirection(firstDirection, secondDirection) {
143
157
  return (((0, types_1.isVariant)(firstDirection, 'long') && (0, types_1.isVariant)(secondDirection, 'long')) ||
144
158
  ((0, types_1.isVariant)(firstDirection, 'short') && (0, types_1.isVariant)(secondDirection, 'short')));
145
159
  }
146
- function isOrderExpired(order, slot, maxAuctionDuration) {
147
- if (!(0, types_1.isVariant)(order.orderType, 'market') ||
148
- !(0, types_1.isVariant)(order.status, 'open')) {
160
+ function isOrderExpired(order, slot) {
161
+ if ((0, types_1.isOneOfVariant)(order.orderType, ['triggerMarket', 'triggerLimit']) ||
162
+ !(0, types_1.isVariant)(order.status, 'open') ||
163
+ order.timeInForce === 0) {
149
164
  return false;
150
165
  }
151
- return new anchor_1.BN(slot).sub(order.slot).gt(new anchor_1.BN(maxAuctionDuration));
166
+ return new anchor_1.BN(slot).sub(order.slot).gt(new anchor_1.BN(order.timeInForce));
152
167
  }
153
168
  exports.isOrderExpired = isOrderExpired;
@@ -1,5 +1,5 @@
1
1
  /// <reference types="bn.js" />
2
- import { BN } from '../';
2
+ import { BN, SpotMarketAccount } from '../';
3
3
  import { OraclePriceData } from '../oracles/types';
4
4
  import { PerpMarketAccount, PositionDirection, PerpPosition } from '../types';
5
5
  /**
@@ -10,7 +10,7 @@ import { PerpMarketAccount, PositionDirection, PerpPosition } from '../types';
10
10
  * @param oraclePriceData
11
11
  * @returns Base Asset Value. : Precision QUOTE_PRECISION
12
12
  */
13
- export declare function calculateBaseAssetValue(market: PerpMarketAccount, userPosition: PerpPosition, oraclePriceData: OraclePriceData): BN;
13
+ export declare function calculateBaseAssetValue(market: PerpMarketAccount, userPosition: PerpPosition, oraclePriceData: OraclePriceData, useSpread?: boolean, skipUpdate?: boolean): BN;
14
14
  /**
15
15
  * calculatePositionPNL
16
16
  * = BaseAssetAmount * (Avg Exit Price - Avg Entry Price)
@@ -21,7 +21,7 @@ export declare function calculateBaseAssetValue(market: PerpMarketAccount, userP
21
21
  * @returns BaseAssetAmount : Precision QUOTE_PRECISION
22
22
  */
23
23
  export declare function calculatePositionPNL(market: PerpMarketAccount, perpPosition: PerpPosition, withFunding: boolean, oraclePriceData: OraclePriceData): BN;
24
- export declare function calculateUnsettledPnl(market: PerpMarketAccount, perpPosition: PerpPosition, oraclePriceData: OraclePriceData): BN;
24
+ export declare function calculateClaimablePnl(market: PerpMarketAccount, spotMarket: SpotMarketAccount, perpPosition: PerpPosition, oraclePriceData: OraclePriceData): BN;
25
25
  /**
26
26
  *
27
27
  * @param market
@@ -1,11 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isEmptyPosition = exports.positionCurrentDirection = exports.findDirectionToClose = exports.calculateCostBasis = exports.calculateEntryPrice = exports.positionIsAvailable = exports.calculatePositionFundingPNL = exports.calculateUnsettledPnl = exports.calculatePositionPNL = exports.calculateBaseAssetValue = void 0;
3
+ exports.isEmptyPosition = exports.positionCurrentDirection = exports.findDirectionToClose = exports.calculateCostBasis = exports.calculateEntryPrice = exports.positionIsAvailable = exports.calculatePositionFundingPNL = exports.calculateClaimablePnl = exports.calculatePositionPNL = exports.calculateBaseAssetValue = void 0;
4
4
  const __1 = require("../");
5
5
  const numericConstants_1 = require("../constants/numericConstants");
6
6
  const types_1 = require("../types");
7
7
  const amm_1 = require("./amm");
8
8
  const margin_1 = require("./margin");
9
+ const market_1 = require("./market");
9
10
  /**
10
11
  * calculateBaseAssetValue
11
12
  * = market value of closing entire position
@@ -14,23 +15,28 @@ const margin_1 = require("./margin");
14
15
  * @param oraclePriceData
15
16
  * @returns Base Asset Value. : Precision QUOTE_PRECISION
16
17
  */
17
- function calculateBaseAssetValue(market, userPosition, oraclePriceData) {
18
+ function calculateBaseAssetValue(market, userPosition, oraclePriceData, useSpread = true, skipUpdate = false) {
18
19
  if (userPosition.baseAssetAmount.eq(numericConstants_1.ZERO)) {
19
20
  return numericConstants_1.ZERO;
20
21
  }
21
22
  const directionToClose = findDirectionToClose(userPosition);
22
23
  let prepegAmm;
23
- if (market.amm.baseSpread > 0) {
24
- const { baseAssetReserve, quoteAssetReserve, sqrtK, newPeg } = (0, amm_1.calculateUpdatedAMMSpreadReserves)(market.amm, directionToClose, oraclePriceData);
25
- prepegAmm = {
26
- baseAssetReserve,
27
- quoteAssetReserve,
28
- sqrtK: sqrtK,
29
- pegMultiplier: newPeg,
30
- };
24
+ if (!skipUpdate) {
25
+ if (market.amm.baseSpread > 0 && useSpread) {
26
+ const { baseAssetReserve, quoteAssetReserve, sqrtK, newPeg } = (0, amm_1.calculateUpdatedAMMSpreadReserves)(market.amm, directionToClose, oraclePriceData);
27
+ prepegAmm = {
28
+ baseAssetReserve,
29
+ quoteAssetReserve,
30
+ sqrtK: sqrtK,
31
+ pegMultiplier: newPeg,
32
+ };
33
+ }
34
+ else {
35
+ prepegAmm = (0, amm_1.calculateUpdatedAMM)(market.amm, oraclePriceData);
36
+ }
31
37
  }
32
38
  else {
33
- prepegAmm = (0, amm_1.calculateUpdatedAMM)(market.amm, oraclePriceData);
39
+ prepegAmm = market.amm;
34
40
  }
35
41
  const [newQuoteAssetReserve, _] = (0, amm_1.calculateAmmReservesAfterSwap)(prepegAmm, 'base', userPosition.baseAssetAmount.abs(), (0, amm_1.getSwapDirection)('base', directionToClose));
36
42
  switch (directionToClose) {
@@ -75,19 +81,20 @@ function calculatePositionPNL(market, perpPosition, withFunding = false, oracleP
75
81
  return pnl;
76
82
  }
77
83
  exports.calculatePositionPNL = calculatePositionPNL;
78
- function calculateUnsettledPnl(market, perpPosition, oraclePriceData) {
84
+ function calculateClaimablePnl(market, spotMarket, perpPosition, oraclePriceData) {
79
85
  const unrealizedPnl = calculatePositionPNL(market, perpPosition, true, oraclePriceData);
80
- let unsettledPnl = unrealizedPnl;
86
+ const fundingPnL = calculatePositionFundingPNL(market, perpPosition).div(numericConstants_1.PRICE_TO_QUOTE_PRECISION);
87
+ let unsettledPnl = unrealizedPnl.add(fundingPnL);
81
88
  if (unrealizedPnl.gt(numericConstants_1.ZERO)) {
82
- const fundingPnL = calculatePositionFundingPNL(market, perpPosition).div(numericConstants_1.PRICE_TO_QUOTE_PRECISION);
89
+ const excessPnlPool = __1.BN.max(numericConstants_1.ZERO, (0, market_1.calculateNetUserPnlImbalance)(market, spotMarket, oraclePriceData).mul(new __1.BN(-1)));
83
90
  const maxPositivePnl = __1.BN.max(perpPosition.quoteAssetAmount
84
91
  .sub(perpPosition.quoteEntryAmount)
85
- .add(fundingPnL), numericConstants_1.ZERO);
92
+ .add(excessPnlPool), numericConstants_1.ZERO);
86
93
  unsettledPnl = __1.BN.min(maxPositivePnl, unrealizedPnl);
87
94
  }
88
95
  return unsettledPnl;
89
96
  }
90
- exports.calculateUnsettledPnl = calculateUnsettledPnl;
97
+ exports.calculateClaimablePnl = calculateClaimablePnl;
91
98
  /**
92
99
  *
93
100
  * @param market
package/lib/math/repeg.js CHANGED
@@ -71,6 +71,14 @@ function calculateBudgetedKBN(x, y, budget, Q, d) {
71
71
  .div(numericConstants_1.AMM_RESERVE_PRECISION)
72
72
  .div(numericConstants_1.QUOTE_PRECISION);
73
73
  const denom2 = pegged_y_d_d;
74
+ // protocol is spending to increase k
75
+ if (C.lt(numericConstants_1.ZERO)) {
76
+ // thus denom1 is negative and solution is unstable
77
+ if (denom1.lt(pegged_y_d_d.abs())) {
78
+ console.log('budget cost exceeds stable K solution');
79
+ return [new anchor_1.BN(10000), new anchor_1.BN(1)];
80
+ }
81
+ }
74
82
  const numerator = numer1.sub(numer2).div(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO);
75
83
  const denominator = denom1.add(denom2).div(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO);
76
84
  return [numerator, denominator];
@@ -1,8 +1,11 @@
1
1
  /// <reference types="bn.js" />
2
2
  import { SpotMarketAccount, SpotBalanceType, MarginCategory } from '../types';
3
3
  import { BN } from '@project-serum/anchor';
4
+ import { OraclePriceData } from '../oracles/types';
4
5
  export declare function getBalance(tokenAmount: BN, spotMarket: SpotMarketAccount, balanceType: SpotBalanceType): BN;
5
6
  export declare function getTokenAmount(balanceAmount: BN, spotMarket: SpotMarketAccount, balanceType: SpotBalanceType): BN;
7
+ export declare function getSignedTokenAmount(tokenAmount: BN, balanceType: SpotBalanceType): BN;
8
+ export declare function getTokenValue(tokenAmount: BN, spotDecimals: number, oraclePriceData: OraclePriceData): BN;
6
9
  export declare function calculateAssetWeight(balanceAmount: BN, spotMarket: SpotMarketAccount, marginCategory: MarginCategory): BN;
7
10
  export declare function calculateLiabilityWeight(balanceAmount: BN, spotMarket: SpotMarketAccount, marginCategory: MarginCategory): BN;
8
11
  export declare function calculateUtilization(bank: SpotMarketAccount): BN;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.calculateWithdrawLimit = exports.calculateInterestAccumulated = exports.calculateBorrowRate = exports.calculateDepositRate = exports.calculateInterestRate = exports.calculateUtilization = exports.calculateLiabilityWeight = exports.calculateAssetWeight = exports.getTokenAmount = exports.getBalance = void 0;
3
+ exports.calculateWithdrawLimit = exports.calculateInterestAccumulated = exports.calculateBorrowRate = exports.calculateDepositRate = exports.calculateInterestRate = exports.calculateUtilization = exports.calculateLiabilityWeight = exports.calculateAssetWeight = exports.getTokenValue = exports.getSignedTokenAmount = exports.getTokenAmount = exports.getBalance = void 0;
4
4
  const types_1 = require("../types");
5
5
  const anchor_1 = require("@project-serum/anchor");
6
6
  const numericConstants_1 = require("../constants/numericConstants");
@@ -25,6 +25,23 @@ function getTokenAmount(balanceAmount, spotMarket, balanceType) {
25
25
  return balanceAmount.mul(cumulativeInterest).div(precisionDecrease);
26
26
  }
27
27
  exports.getTokenAmount = getTokenAmount;
28
+ function getSignedTokenAmount(tokenAmount, balanceType) {
29
+ if ((0, types_1.isVariant)(balanceType, 'deposit')) {
30
+ return tokenAmount;
31
+ }
32
+ else {
33
+ return tokenAmount.abs().neg();
34
+ }
35
+ }
36
+ exports.getSignedTokenAmount = getSignedTokenAmount;
37
+ function getTokenValue(tokenAmount, spotDecimals, oraclePriceData) {
38
+ if (tokenAmount.eq(numericConstants_1.ZERO)) {
39
+ return numericConstants_1.ZERO;
40
+ }
41
+ const precisionDecrease = numericConstants_1.TEN.pow(new anchor_1.BN(10 + spotDecimals - 6));
42
+ return tokenAmount.mul(oraclePriceData.price).div(precisionDecrease);
43
+ }
44
+ exports.getTokenValue = getTokenValue;
28
45
  function calculateAssetWeight(balanceAmount, spotMarket, marginCategory) {
29
46
  const sizePrecision = numericConstants_1.TEN.pow(new anchor_1.BN(spotMarket.decimals));
30
47
  let sizeInAmmReservePrecision;
@@ -1,2 +1,6 @@
1
- import { SpotPosition } from '../types';
1
+ /// <reference types="bn.js" />
2
+ import { SpotMarketAccount, SpotPosition } from '../types';
3
+ import { BN } from '@project-serum/anchor';
4
+ import { OraclePriceData } from '../oracles/types';
2
5
  export declare function isSpotPositionAvailable(position: SpotPosition): boolean;
6
+ export declare function getWorstCaseTokenAmounts(spotPosition: SpotPosition, spotMarketAccount: SpotMarketAccount, oraclePriceData: OraclePriceData): [BN, BN];
@@ -1,8 +1,23 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isSpotPositionAvailable = void 0;
3
+ exports.getWorstCaseTokenAmounts = exports.isSpotPositionAvailable = void 0;
4
4
  const numericConstants_1 = require("../constants/numericConstants");
5
+ const spotBalance_1 = require("./spotBalance");
5
6
  function isSpotPositionAvailable(position) {
6
7
  return position.balance.eq(numericConstants_1.ZERO) && position.openOrders === 0;
7
8
  }
8
9
  exports.isSpotPositionAvailable = isSpotPositionAvailable;
10
+ function getWorstCaseTokenAmounts(spotPosition, spotMarketAccount, oraclePriceData) {
11
+ const tokenAmount = (0, spotBalance_1.getSignedTokenAmount)((0, spotBalance_1.getTokenAmount)(spotPosition.balance, spotMarketAccount, spotPosition.balanceType), spotPosition.balanceType);
12
+ const tokenAmountAllBidsFill = tokenAmount.add(spotPosition.openBids);
13
+ const tokenAmountAllAsksFill = tokenAmount.add(spotPosition.openAsks);
14
+ if (tokenAmountAllAsksFill.abs().gt(tokenAmountAllBidsFill.abs())) {
15
+ const worstCaseQuoteTokenAmount = (0, spotBalance_1.getTokenValue)(spotPosition.openBids.neg(), spotMarketAccount.decimals, oraclePriceData);
16
+ return [tokenAmountAllBidsFill, worstCaseQuoteTokenAmount];
17
+ }
18
+ else {
19
+ const worstCaseQuoteTokenAmount = (0, spotBalance_1.getTokenValue)(spotPosition.openAsks.neg(), spotMarketAccount.decimals, oraclePriceData);
20
+ return [tokenAmountAllAsksFill, worstCaseQuoteTokenAmount];
21
+ }
22
+ }
23
+ exports.getWorstCaseTokenAmounts = getWorstCaseTokenAmounts;
package/lib/types.d.ts CHANGED
@@ -11,6 +11,9 @@ export declare class MarketStatus {
11
11
  static readonly SETTLEMENT: {
12
12
  settlement: {};
13
13
  };
14
+ static readonly DELISTED: {
15
+ delisted: {};
16
+ };
14
17
  }
15
18
  export declare class ContractType {
16
19
  static readonly PERPETUAL: {
@@ -77,6 +80,7 @@ export declare class OrderType {
77
80
  market: {};
78
81
  };
79
82
  }
83
+ export declare type MarketTypeStr = 'perp' | 'spot';
80
84
  export declare class MarketType {
81
85
  static readonly SPOT: {
82
86
  spot: {};
@@ -167,6 +171,7 @@ export declare class SpotFulfillmentStatus {
167
171
  }
168
172
  export declare function isVariant(object: unknown, type: string): boolean;
169
173
  export declare function isOneOfVariant(object: unknown, types: string[]): boolean;
174
+ export declare function getVariant(object: unknown): string;
170
175
  export declare enum TradeSide {
171
176
  None = 0,
172
177
  Buy = 1,
@@ -283,6 +288,7 @@ export declare type LiquidationRecord = {
283
288
  marginRequirement: BN;
284
289
  totalCollateral: BN;
285
290
  liquidationId: number;
291
+ canceledOrderIds: BN[];
286
292
  liquidatePerp: LiquidatePerpRecord;
287
293
  liquidateBorrow: LiquidateBorrowRecord;
288
294
  liquidateBorrowForPerpPnl: LiquidateBorrowForPerpPnlRecord;
@@ -312,17 +318,16 @@ export declare class LiquidationType {
312
318
  }
313
319
  export declare type LiquidatePerpRecord = {
314
320
  marketIndex: BN;
315
- orderIds: BN[];
316
321
  oraclePrice: BN;
317
322
  baseAssetAmount: BN;
318
323
  quoteAssetAmount: BN;
319
324
  lpShares: BN;
320
325
  userPnl: BN;
321
326
  liquidatorPnl: BN;
322
- canceledOrdersFee: BN;
323
327
  userOrderId: BN;
324
328
  liquidatorOrderId: BN;
325
329
  fillRecordId: BN;
330
+ ifFee: BN;
326
331
  };
327
332
  export declare type LiquidateBorrowRecord = {
328
333
  assetMarketIndex: BN;
@@ -331,6 +336,7 @@ export declare type LiquidateBorrowRecord = {
331
336
  liabilityMarketIndex: BN;
332
337
  liabilityPrice: BN;
333
338
  liabilityTransfer: BN;
339
+ ifFee: BN;
334
340
  };
335
341
  export declare type LiquidateBorrowForPerpPnlRecord = {
336
342
  perpMarketIndex: BN;
@@ -413,17 +419,6 @@ export declare type StateAccount = {
413
419
  exchangePaused: boolean;
414
420
  adminControlsPrices: boolean;
415
421
  insuranceVault: PublicKey;
416
- marginRatioInitial: BN;
417
- marginRatioMaintenance: BN;
418
- marginRatioPartial: BN;
419
- partialLiquidationClosePercentageNumerator: BN;
420
- partialLiquidationClosePercentageDenominator: BN;
421
- partialLiquidationPenaltyPercentageNumerator: BN;
422
- partialLiquidationPenaltyPercentageDenominator: BN;
423
- fullLiquidationPenaltyPercentageNumerator: BN;
424
- fullLiquidationPenaltyPercentageDenominator: BN;
425
- partialLiquidationLiquidatorShareDenominator: BN;
426
- fullLiquidationLiquidatorShareDenominator: BN;
427
422
  perpFeeStructure: FeeStructure;
428
423
  spotFeeStructure: FeeStructure;
429
424
  totalFee: BN;
@@ -437,8 +432,9 @@ export declare type StateAccount = {
437
432
  minOrderQuoteAssetAmount: BN;
438
433
  signer: PublicKey;
439
434
  signerNonce: number;
440
- maxAuctionDuration: number;
441
- minAuctionDuration: number;
435
+ defaultMarketOrderTimeInForce: number;
436
+ minPerpAuctionDuration: number;
437
+ defaultSpotAuctionDuration: number;
442
438
  liquidationMarginBufferRatio: number;
443
439
  };
444
440
  export declare type PerpMarketAccount = {
@@ -457,7 +453,8 @@ export declare type PerpMarketAccount = {
457
453
  marginRatioMaintenance: number;
458
454
  nextFillRecordId: BN;
459
455
  pnlPool: PoolBalance;
460
- liquidationFee: BN;
456
+ liquidatorFee: BN;
457
+ ifLiquidationFee: BN;
461
458
  imfFactor: BN;
462
459
  unrealizedImfFactor: BN;
463
460
  unrealizedMaxImbalance: BN;
@@ -481,7 +478,7 @@ export declare type SpotMarketAccount = {
481
478
  userIfShares: BN;
482
479
  userIfFactor: BN;
483
480
  totalIfFactor: BN;
484
- liquidationIfFactor: BN;
481
+ ifLiquidationFee: BN;
485
482
  decimals: number;
486
483
  optimalUtilization: BN;
487
484
  optimalBorrowRate: BN;
@@ -497,7 +494,7 @@ export declare type SpotMarketAccount = {
497
494
  maintenanceAssetWeight: BN;
498
495
  initialLiabilityWeight: BN;
499
496
  maintenanceLiabilityWeight: BN;
500
- liquidationFee: BN;
497
+ liquidatorFee: BN;
501
498
  imfFactor: BN;
502
499
  withdrawGuardThreshold: BN;
503
500
  depositTokenTwap: BN;
@@ -584,7 +581,7 @@ export declare type PerpPosition = {
584
581
  openOrders: BN;
585
582
  openBids: BN;
586
583
  openAsks: BN;
587
- realizedPnl: BN;
584
+ settledPnl: BN;
588
585
  lpShares: BN;
589
586
  lastFeePerLp: BN;
590
587
  lastNetBaseAssetAmountPerLp: BN;
@@ -621,6 +618,7 @@ export declare type UserAccount = {
621
618
  bankrupt: boolean;
622
619
  nextLiquidationId: number;
623
620
  nextOrderId: BN;
621
+ customMarginRatio: number;
624
622
  };
625
623
  export declare type SpotPosition = {
626
624
  marketIndex: BN;
@@ -657,6 +655,7 @@ export declare type Order = {
657
655
  auctionDuration: number;
658
656
  auctionStartPrice: BN;
659
657
  auctionEndPrice: BN;
658
+ timeInForce: number;
660
659
  };
661
660
  export declare type OrderParams = {
662
661
  orderType: OrderType;
@@ -673,8 +672,9 @@ export declare type OrderParams = {
673
672
  triggerCondition: OrderTriggerCondition;
674
673
  positionLimit: BN;
675
674
  oraclePriceOffset: BN;
676
- padding0: boolean;
677
- padding1: BN;
675
+ auctionDuration: number | null;
676
+ timeInForce: number | null;
677
+ auctionStartPrice: BN | null;
678
678
  };
679
679
  export declare type NecessaryOrderParams = {
680
680
  orderType: OrderType;
@@ -708,8 +708,9 @@ export declare const DefaultOrderParams: {
708
708
  };
709
709
  positionLimit: BN;
710
710
  oraclePriceOffset: BN;
711
- padding0: BN;
712
- padding1: BN;
711
+ auctionDuration: any;
712
+ timeInForce: any;
713
+ auctionStartPrice: any;
713
714
  };
714
715
  export declare type MakerInfo = {
715
716
  maker: PublicKey;
@@ -765,7 +766,7 @@ export declare type FeeStructure = {
765
766
  makerRebateNumerator: BN;
766
767
  makerRebateDenominator: BN;
767
768
  fillerRewardStructure: OrderFillerRewardStructure;
768
- cancelOrderFee: BN;
769
+ flatFillerFee: BN;
769
770
  };
770
771
  export declare type OracleGuardRails = {
771
772
  priceDivergence: {
package/lib/types.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DefaultOrderParams = exports.LiquidationType = exports.LPAction = exports.TradeSide = exports.isOneOfVariant = exports.isVariant = exports.SpotFulfillmentStatus = exports.SpotFulfillmentType = exports.OrderTriggerCondition = exports.OrderActionExplanation = exports.OrderAction = exports.OrderDiscountTier = exports.OrderStatus = exports.MarketType = exports.OrderType = exports.OracleSource = exports.DepositDirection = exports.PositionDirection = exports.SpotBalanceType = exports.SwapDirection = exports.ContractType = exports.MarketStatus = void 0;
3
+ exports.DefaultOrderParams = exports.LiquidationType = exports.LPAction = exports.TradeSide = exports.getVariant = exports.isOneOfVariant = exports.isVariant = exports.SpotFulfillmentStatus = exports.SpotFulfillmentType = exports.OrderTriggerCondition = exports.OrderActionExplanation = exports.OrderAction = exports.OrderDiscountTier = exports.OrderStatus = exports.MarketType = exports.OrderType = exports.OracleSource = exports.DepositDirection = exports.PositionDirection = exports.SpotBalanceType = exports.SwapDirection = exports.ContractType = exports.MarketStatus = void 0;
4
4
  const _1 = require(".");
5
5
  // # Utility Types / Enums / Constants
6
6
  class MarketStatus {
@@ -9,6 +9,7 @@ exports.MarketStatus = MarketStatus;
9
9
  MarketStatus.INITIALIZED = { initialized: {} };
10
10
  MarketStatus.REDUCEONLY = { reduceonly: {} };
11
11
  MarketStatus.SETTLEMENT = { settlement: {} };
12
+ MarketStatus.DELISTED = { delisted: {} };
12
13
  class ContractType {
13
14
  }
14
15
  exports.ContractType = ContractType;
@@ -113,6 +114,10 @@ function isOneOfVariant(object, types) {
113
114
  }, false);
114
115
  }
115
116
  exports.isOneOfVariant = isOneOfVariant;
117
+ function getVariant(object) {
118
+ return Object.keys(object)[0];
119
+ }
120
+ exports.getVariant = getVariant;
116
121
  var TradeSide;
117
122
  (function (TradeSide) {
118
123
  TradeSide[TradeSide["None"] = 0] = "None";
@@ -157,6 +162,7 @@ exports.DefaultOrderParams = {
157
162
  triggerCondition: OrderTriggerCondition.ABOVE,
158
163
  positionLimit: _1.ZERO,
159
164
  oraclePriceOffset: _1.ZERO,
160
- padding0: _1.ZERO,
161
- padding1: _1.ZERO,
165
+ auctionDuration: null,
166
+ timeInForce: null,
167
+ auctionStartPrice: null,
162
168
  };
@@ -0,0 +1,25 @@
1
+ import { ClearingHouseUser, ClearingHouse, OrderRecord, ClearingHouseUserAccountSubscriptionConfig } from '..';
2
+ import { PublicKey } from '@solana/web3.js';
3
+ export declare class UserMap {
4
+ private userMap;
5
+ private clearingHouse;
6
+ private accountSubscription;
7
+ constructor(clearingHouse: ClearingHouse, accountSubscription: ClearingHouseUserAccountSubscriptionConfig);
8
+ fetchAllUsers(): Promise<void>;
9
+ addPubkey(userAccountPublicKey: PublicKey): Promise<void>;
10
+ has(key: string): boolean;
11
+ /**
12
+ * gets the ClearingHouseUser for a particular userAccountPublicKey, if no ClearingHouseUser exists, undefined is returned
13
+ * @param key userAccountPublicKey to get ClearngHouseUserFor
14
+ * @returns user ClearingHouseUser | undefined
15
+ */
16
+ get(key: string): ClearingHouseUser | undefined;
17
+ /**
18
+ * gets the ClearingHouseUser for a particular userAccountPublicKey, if no ClearingHouseUser exists, new one is created
19
+ * @param key userAccountPublicKey to get ClearngHouseUserFor
20
+ * @returns ClearingHouseUser
21
+ */
22
+ mustGet(key: string): Promise<ClearingHouseUser>;
23
+ updateWithOrderRecord(record: OrderRecord): Promise<void>;
24
+ values(): IterableIterator<ClearingHouseUser>;
25
+ }
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.UserMap = void 0;
4
+ const __1 = require("..");
5
+ const web3_js_1 = require("@solana/web3.js");
6
+ class UserMap {
7
+ constructor(clearingHouse, accountSubscription) {
8
+ this.userMap = new Map();
9
+ this.clearingHouse = clearingHouse;
10
+ this.accountSubscription = accountSubscription;
11
+ }
12
+ async fetchAllUsers() {
13
+ const userArray = [];
14
+ const programUserAccounts = (await this.clearingHouse.program.account.user.all());
15
+ for (const programUserAccount of programUserAccounts) {
16
+ if (this.userMap.has(programUserAccount.publicKey.toString())) {
17
+ continue;
18
+ }
19
+ const user = new __1.ClearingHouseUser({
20
+ clearingHouse: this.clearingHouse,
21
+ userAccountPublicKey: programUserAccount.publicKey,
22
+ accountSubscription: this.accountSubscription,
23
+ });
24
+ userArray.push(user);
25
+ }
26
+ if (this.accountSubscription.type === 'polling') {
27
+ await (0, __1.bulkPollingUserSubscribe)(userArray, this.accountSubscription.accountLoader);
28
+ }
29
+ for (const user of userArray) {
30
+ this.userMap.set(user.getUserAccountPublicKey().toString(), user);
31
+ }
32
+ }
33
+ async addPubkey(userAccountPublicKey) {
34
+ const user = new __1.ClearingHouseUser({
35
+ clearingHouse: this.clearingHouse,
36
+ userAccountPublicKey,
37
+ accountSubscription: this.accountSubscription,
38
+ });
39
+ await user.subscribe();
40
+ this.userMap.set(userAccountPublicKey.toString(), user);
41
+ }
42
+ has(key) {
43
+ return this.userMap.has(key);
44
+ }
45
+ /**
46
+ * gets the ClearingHouseUser for a particular userAccountPublicKey, if no ClearingHouseUser exists, undefined is returned
47
+ * @param key userAccountPublicKey to get ClearngHouseUserFor
48
+ * @returns user ClearingHouseUser | undefined
49
+ */
50
+ get(key) {
51
+ return this.userMap.get(key);
52
+ }
53
+ /**
54
+ * gets the ClearingHouseUser for a particular userAccountPublicKey, if no ClearingHouseUser exists, new one is created
55
+ * @param key userAccountPublicKey to get ClearngHouseUserFor
56
+ * @returns ClearingHouseUser
57
+ */
58
+ async mustGet(key) {
59
+ if (!this.has(key)) {
60
+ await this.addPubkey(new web3_js_1.PublicKey(key));
61
+ }
62
+ const user = this.userMap.get(key);
63
+ await user.fetchAccounts();
64
+ return user;
65
+ }
66
+ async updateWithOrderRecord(record) {
67
+ await this.addPubkey(record.user);
68
+ }
69
+ values() {
70
+ return this.userMap.values();
71
+ }
72
+ }
73
+ exports.UserMap = UserMap;
@@ -0,0 +1,19 @@
1
+ import { ClearingHouse, OrderRecord, ClearingHouseUserStats, ClearingHouseUserStatsAccountSubscriptionConfig } from '..';
2
+ import { PublicKey } from '@solana/web3.js';
3
+ import { UserMap } from './userMap';
4
+ export declare class UserStatsMap {
5
+ /**
6
+ * map from authority pubkey to ClearingHouseUserStats
7
+ */
8
+ private userStatsMap;
9
+ private clearingHouse;
10
+ private accountSubscription;
11
+ constructor(clearingHouse: ClearingHouse, accountSubscription: ClearingHouseUserStatsAccountSubscriptionConfig);
12
+ fetchAllUserStats(): Promise<void>;
13
+ addUserStat(authority: PublicKey): Promise<void>;
14
+ updateWithOrderRecord(record: OrderRecord, userMap: UserMap): Promise<void>;
15
+ has(authorityPublicKey: string): boolean;
16
+ get(authorityPublicKey: string): ClearingHouseUserStats;
17
+ mustGet(authorityPublicKey: string): Promise<ClearingHouseUserStats>;
18
+ values(): IterableIterator<ClearingHouseUserStats>;
19
+ }