@drift-labs/sdk 0.2.0-master.4 → 0.2.0-master.41

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 (247) hide show
  1. package/README.md +27 -27
  2. package/lib/accounts/bulkAccountLoader.d.ts +2 -0
  3. package/lib/accounts/bulkAccountLoader.js +36 -29
  4. package/lib/accounts/bulkUserStatsSubscription.d.ts +7 -0
  5. package/lib/accounts/bulkUserStatsSubscription.js +21 -0
  6. package/lib/accounts/bulkUserSubscription.d.ts +2 -2
  7. package/lib/accounts/bulkUserSubscription.js +0 -1
  8. package/lib/accounts/fetch.d.ts +2 -1
  9. package/lib/accounts/fetch.js +9 -1
  10. package/lib/accounts/{pollingClearingHouseAccountSubscriber.d.ts → pollingDriftClientAccountSubscriber.d.ts} +20 -25
  11. package/lib/accounts/{pollingClearingHouseAccountSubscriber.js → pollingDriftClientAccountSubscriber.js} +45 -49
  12. package/lib/accounts/{pollingOracleSubscriber.d.ts → pollingOracleAccountSubscriber.d.ts} +2 -2
  13. package/lib/accounts/{pollingOracleSubscriber.js → pollingOracleAccountSubscriber.js} +3 -3
  14. package/lib/accounts/pollingUserAccountSubscriber.d.ts +1 -1
  15. package/lib/accounts/pollingUserAccountSubscriber.js +5 -11
  16. package/lib/accounts/pollingUserStatsAccountSubscriber.d.ts +27 -0
  17. package/lib/accounts/pollingUserStatsAccountSubscriber.js +107 -0
  18. package/lib/accounts/types.d.ts +26 -15
  19. package/lib/accounts/webSocketDriftClientAccountSubscriber.d.ts +49 -0
  20. package/lib/accounts/{webSocketClearingHouseAccountSubscriber.js → webSocketDriftClientAccountSubscriber.js} +47 -45
  21. package/lib/accounts/webSocketUserStatsAccountSubsriber.d.ts +20 -0
  22. package/lib/accounts/webSocketUserStatsAccountSubsriber.js +47 -0
  23. package/lib/addresses/marketAddresses.d.ts +1 -3
  24. package/lib/addresses/marketAddresses.js +1 -1
  25. package/lib/addresses/pda.d.ts +15 -9
  26. package/lib/addresses/pda.js +73 -35
  27. package/lib/adminClient.d.ts +65 -0
  28. package/lib/adminClient.js +637 -0
  29. package/lib/config.d.ts +9 -9
  30. package/lib/config.js +25 -21
  31. package/lib/constants/numericConstants.d.ts +30 -12
  32. package/lib/constants/numericConstants.js +41 -21
  33. package/lib/constants/perpMarkets.d.ts +18 -0
  34. package/lib/constants/{markets.js → perpMarkets.js} +7 -7
  35. package/lib/constants/spotMarkets.d.ts +19 -0
  36. package/lib/constants/spotMarkets.js +53 -0
  37. package/lib/dlob/DLOB.d.ts +82 -0
  38. package/lib/dlob/DLOB.js +694 -0
  39. package/lib/dlob/DLOBNode.d.ts +54 -0
  40. package/lib/dlob/DLOBNode.js +77 -0
  41. package/lib/dlob/NodeList.d.ts +27 -0
  42. package/lib/dlob/NodeList.js +144 -0
  43. package/lib/driftClient.d.ts +234 -0
  44. package/lib/driftClient.js +2108 -0
  45. package/lib/{clearingHouseConfig.d.ts → driftClientConfig.d.ts} +9 -9
  46. package/lib/{clearingHouseConfig.js → driftClientConfig.js} +0 -0
  47. package/lib/events/eventList.js +3 -0
  48. package/lib/events/eventSubscriber.d.ts +5 -2
  49. package/lib/events/eventSubscriber.js +25 -11
  50. package/lib/events/fetchLogs.d.ts +13 -2
  51. package/lib/events/fetchLogs.js +40 -12
  52. package/lib/events/pollingLogProvider.d.ts +2 -1
  53. package/lib/events/pollingLogProvider.js +7 -3
  54. package/lib/events/sort.js +8 -11
  55. package/lib/events/types.d.ts +11 -3
  56. package/lib/events/types.js +8 -0
  57. package/lib/events/webSocketLogProvider.js +1 -1
  58. package/lib/examples/makeTradeExample.js +30 -18
  59. package/lib/factory/bigNum.d.ts +8 -4
  60. package/lib/factory/bigNum.js +109 -19
  61. package/lib/idl/drift.json +8386 -0
  62. package/lib/idl/{mock_usdc_faucet.json → token_faucet.json} +46 -23
  63. package/lib/index.d.ts +30 -13
  64. package/lib/index.js +30 -13
  65. package/lib/math/amm.d.ts +9 -6
  66. package/lib/math/amm.js +91 -38
  67. package/lib/math/conversion.js +1 -1
  68. package/lib/math/exchangeStatus.d.ts +4 -0
  69. package/lib/math/exchangeStatus.js +18 -0
  70. package/lib/math/funding.d.ts +6 -6
  71. package/lib/math/funding.js +23 -21
  72. package/lib/math/insurance.d.ts +4 -0
  73. package/lib/math/insurance.js +27 -0
  74. package/lib/math/margin.d.ts +11 -0
  75. package/lib/math/margin.js +82 -0
  76. package/lib/math/market.d.ts +14 -9
  77. package/lib/math/market.js +70 -10
  78. package/lib/math/oracles.d.ts +4 -0
  79. package/lib/math/oracles.js +36 -8
  80. package/lib/math/orders.d.ts +16 -6
  81. package/lib/math/orders.js +97 -17
  82. package/lib/math/position.d.ts +27 -13
  83. package/lib/math/position.js +92 -36
  84. package/lib/math/repeg.js +17 -8
  85. package/lib/math/spotBalance.d.ts +22 -0
  86. package/lib/math/spotBalance.js +192 -0
  87. package/lib/math/spotMarket.d.ts +4 -0
  88. package/lib/math/spotMarket.js +8 -0
  89. package/lib/math/spotPosition.d.ts +6 -0
  90. package/lib/math/spotPosition.js +23 -0
  91. package/lib/math/trade.d.ts +10 -10
  92. package/lib/math/trade.js +27 -31
  93. package/lib/oracles/pythClient.js +1 -1
  94. package/lib/oracles/quoteAssetOracleClient.js +1 -1
  95. package/lib/oracles/switchboardClient.js +1 -1
  96. package/lib/orderParams.d.ts +4 -4
  97. package/lib/orderParams.js +12 -4
  98. package/lib/serum/serumFulfillmentConfigMap.d.ts +10 -0
  99. package/lib/serum/serumFulfillmentConfigMap.js +17 -0
  100. package/lib/serum/serumSubscriber.d.ts +27 -0
  101. package/lib/serum/serumSubscriber.js +56 -0
  102. package/lib/serum/types.d.ts +11 -0
  103. package/lib/{clearingHouseUserConfig.js → serum/types.js} +0 -0
  104. package/lib/slot/SlotSubscriber.d.ts +7 -0
  105. package/lib/slot/SlotSubscriber.js +3 -0
  106. package/lib/{mockUSDCFaucet.d.ts → tokenFaucet.d.ts} +8 -5
  107. package/lib/{mockUSDCFaucet.js → tokenFaucet.js} +63 -51
  108. package/lib/tx/retryTxSender.d.ts +1 -1
  109. package/lib/tx/retryTxSender.js +13 -4
  110. package/lib/tx/types.d.ts +1 -1
  111. package/lib/tx/utils.js +1 -1
  112. package/lib/types.d.ts +688 -216
  113. package/lib/types.js +153 -24
  114. package/lib/user.d.ts +228 -0
  115. package/lib/user.js +959 -0
  116. package/lib/userConfig.d.ts +14 -0
  117. package/lib/userConfig.js +2 -0
  118. package/lib/userMap/userMap.d.ts +41 -0
  119. package/lib/userMap/userMap.js +85 -0
  120. package/lib/userMap/userStatsMap.d.ts +19 -0
  121. package/lib/userMap/userStatsMap.js +68 -0
  122. package/lib/userName.d.ts +1 -0
  123. package/lib/userName.js +3 -2
  124. package/lib/userStats.d.ts +18 -0
  125. package/lib/userStats.js +49 -0
  126. package/lib/userStatsConfig.d.ts +14 -0
  127. package/lib/userStatsConfig.js +2 -0
  128. package/lib/util/computeUnits.js +1 -1
  129. package/lib/util/getTokenAddress.d.ts +2 -0
  130. package/lib/util/getTokenAddress.js +9 -0
  131. package/package.json +11 -4
  132. package/src/accounts/bulkAccountLoader.ts +44 -34
  133. package/src/accounts/bulkUserStatsSubscription.ts +33 -0
  134. package/src/accounts/bulkUserSubscription.ts +2 -3
  135. package/src/accounts/fetch.ts +27 -2
  136. package/src/accounts/{pollingClearingHouseAccountSubscriber.ts → pollingDriftClientAccountSubscriber.ts} +65 -75
  137. package/src/accounts/{pollingOracleSubscriber.ts → pollingOracleAccountSubscriber.ts} +2 -2
  138. package/src/accounts/pollingUserAccountSubscriber.ts +5 -12
  139. package/src/accounts/pollingUserStatsAccountSubscriber.ts +166 -0
  140. package/src/accounts/types.ts +35 -15
  141. package/src/accounts/{webSocketClearingHouseAccountSubscriber.ts → webSocketDriftClientAccountSubscriber.ts} +78 -73
  142. package/src/accounts/webSocketUserStatsAccountSubsriber.ts +80 -0
  143. package/src/addresses/marketAddresses.ts +3 -4
  144. package/src/addresses/pda.ts +105 -33
  145. package/src/adminClient.ts +1207 -0
  146. package/src/assert/assert.js +9 -0
  147. package/src/config.ts +37 -31
  148. package/src/constants/numericConstants.ts +58 -24
  149. package/src/constants/{markets.ts → perpMarkets.ts} +10 -10
  150. package/src/constants/spotMarkets.ts +73 -0
  151. package/src/dlob/DLOB.ts +1120 -0
  152. package/src/dlob/DLOBNode.ts +155 -0
  153. package/src/dlob/NodeList.ts +195 -0
  154. package/src/driftClient.ts +3594 -0
  155. package/src/{clearingHouseConfig.ts → driftClientConfig.ts} +9 -8
  156. package/src/events/eventList.js +77 -0
  157. package/src/events/eventList.ts +3 -0
  158. package/src/events/eventSubscriber.ts +36 -14
  159. package/src/events/fetchLogs.ts +55 -13
  160. package/src/events/pollingLogProvider.ts +11 -3
  161. package/src/events/sort.ts +11 -15
  162. package/src/events/types.ts +27 -2
  163. package/src/events/webSocketLogProvider.ts +1 -1
  164. package/src/examples/makeTradeExample.js +157 -0
  165. package/src/examples/makeTradeExample.ts +44 -28
  166. package/src/factory/bigNum.ts +150 -22
  167. package/src/idl/drift.json +8386 -0
  168. package/src/idl/pyth.json +98 -2
  169. package/src/idl/{mock_usdc_faucet.json → token_faucet.json} +46 -23
  170. package/src/index.ts +30 -13
  171. package/src/math/amm.ts +161 -48
  172. package/src/math/conversion.ts +2 -2
  173. package/src/math/exchangeStatus.ts +31 -0
  174. package/src/math/funding.ts +41 -31
  175. package/src/math/insurance.ts +35 -0
  176. package/src/math/margin.ts +133 -0
  177. package/src/math/market.ts +143 -14
  178. package/src/math/oracles.ts +63 -9
  179. package/src/math/orders.ts +168 -26
  180. package/src/math/position.ts +136 -58
  181. package/src/math/repeg.ts +19 -9
  182. package/src/math/spotBalance.ts +319 -0
  183. package/src/math/spotMarket.ts +9 -0
  184. package/src/math/spotPosition.ts +47 -0
  185. package/src/math/trade.ts +33 -37
  186. package/src/oracles/pythClient.ts +2 -2
  187. package/src/oracles/quoteAssetOracleClient.ts +2 -2
  188. package/src/oracles/switchboardClient.ts +2 -2
  189. package/src/orderParams.ts +16 -8
  190. package/src/serum/serumFulfillmentConfigMap.ts +26 -0
  191. package/src/serum/serumSubscriber.ts +99 -0
  192. package/src/serum/types.ts +13 -0
  193. package/src/slot/SlotSubscriber.ts +11 -1
  194. package/src/token/index.js +38 -0
  195. package/src/{mockUSDCFaucet.ts → tokenFaucet.ts} +82 -70
  196. package/src/tx/retryTxSender.ts +16 -5
  197. package/src/tx/types.js +2 -0
  198. package/src/tx/types.ts +2 -1
  199. package/src/tx/utils.js +17 -0
  200. package/src/tx/utils.ts +1 -1
  201. package/src/types.ts +650 -189
  202. package/src/user.ts +1599 -0
  203. package/src/{clearingHouseUserConfig.ts → userConfig.ts} +5 -5
  204. package/src/userMap/userMap.ts +124 -0
  205. package/src/userMap/userStatsMap.ts +108 -0
  206. package/src/userName.ts +2 -1
  207. package/src/userStats.ts +75 -0
  208. package/src/userStatsConfig.ts +18 -0
  209. package/src/util/computeUnits.js +21 -11
  210. package/src/util/computeUnits.ts +1 -1
  211. package/src/util/getTokenAddress.js +9 -0
  212. package/src/util/getTokenAddress.ts +18 -0
  213. package/src/util/promiseTimeout.js +14 -0
  214. package/src/util/tps.js +27 -0
  215. package/tests/bn/test.ts +46 -11
  216. package/tests/dlob/helpers.ts +620 -0
  217. package/tests/dlob/test.ts +4586 -0
  218. package/yarn-error.log +3160 -0
  219. package/lib/accounts/webSocketClearingHouseAccountSubscriber.d.ts +0 -49
  220. package/lib/admin.d.ts +0 -44
  221. package/lib/admin.js +0 -433
  222. package/lib/clearingHouse.d.ts +0 -133
  223. package/lib/clearingHouse.js +0 -931
  224. package/lib/clearingHouseUser.d.ts +0 -187
  225. package/lib/clearingHouseUser.js +0 -643
  226. package/lib/clearingHouseUserConfig.d.ts +0 -14
  227. package/lib/constants/banks.d.ts +0 -16
  228. package/lib/constants/banks.js +0 -34
  229. package/lib/constants/markets.d.ts +0 -19
  230. package/lib/idl/clearing_house.json +0 -3998
  231. package/lib/math/bankBalance.d.ts +0 -9
  232. package/lib/math/bankBalance.js +0 -75
  233. package/lib/math/state.d.ts +0 -8
  234. package/lib/math/state.js +0 -15
  235. package/lib/orders.d.ts +0 -8
  236. package/lib/orders.js +0 -134
  237. package/src/admin.ts +0 -722
  238. package/src/clearingHouse.ts +0 -1451
  239. package/src/clearingHouseUser.ts +0 -989
  240. package/src/constants/banks.ts +0 -43
  241. package/src/idl/clearing_house.json +0 -3998
  242. package/src/math/bankBalance.ts +0 -112
  243. package/src/math/state.ts +0 -14
  244. package/src/math/utils.js +0 -27
  245. package/src/math/utils.js.map +0 -1
  246. package/src/orders.ts +0 -244
  247. package/src/util/computeUnits.js.map +0 -1
package/src/math/amm.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { BN } from '@project-serum/anchor';
2
2
  import {
3
3
  AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO,
4
- MARK_PRICE_PRECISION,
4
+ PRICE_PRECISION,
5
5
  PEG_PRECISION,
6
6
  ZERO,
7
7
  BID_ASK_SPREAD_PRECISION,
@@ -15,11 +15,11 @@ import {
15
15
  AMM,
16
16
  PositionDirection,
17
17
  SwapDirection,
18
- MarketAccount,
18
+ PerpMarketAccount,
19
19
  isVariant,
20
20
  } from '../types';
21
21
  import { assert } from '../assert/assert';
22
- import { squareRootBN } from '..';
22
+ import { squareRootBN, standardizeBaseAssetAmount } from '..';
23
23
 
24
24
  import { OraclePriceData } from '../oracles/types';
25
25
  import {
@@ -33,18 +33,21 @@ export function calculatePegFromTargetPrice(
33
33
  baseAssetReserve: BN,
34
34
  quoteAssetReserve: BN
35
35
  ): BN {
36
- return targetPrice
37
- .mul(baseAssetReserve)
38
- .div(quoteAssetReserve)
39
- .add(PRICE_DIV_PEG.div(new BN(2)))
40
- .div(PRICE_DIV_PEG);
36
+ return BN.max(
37
+ targetPrice
38
+ .mul(baseAssetReserve)
39
+ .div(quoteAssetReserve)
40
+ .add(PRICE_DIV_PEG.div(new BN(2)))
41
+ .div(PRICE_DIV_PEG),
42
+ ONE
43
+ );
41
44
  }
42
45
 
43
46
  export function calculateOptimalPegAndBudget(
44
47
  amm: AMM,
45
48
  oraclePriceData: OraclePriceData
46
49
  ): [BN, BN, BN, boolean] {
47
- const markPriceBefore = calculatePrice(
50
+ const reservePriceBefore = calculatePrice(
48
51
  amm.baseAssetReserve,
49
52
  amm.quoteAssetReserve,
50
53
  amm.pegMultiplier
@@ -67,15 +70,15 @@ export function calculateOptimalPegAndBudget(
67
70
  let newTargetPrice: BN;
68
71
  let newOptimalPeg: BN;
69
72
  let newBudget: BN;
70
- const targetPriceGap = markPriceBefore.sub(targetPrice);
73
+ const targetPriceGap = reservePriceBefore.sub(targetPrice);
71
74
 
72
75
  if (targetPriceGap.abs().gt(maxPriceSpread)) {
73
76
  const markAdj = targetPriceGap.abs().sub(maxPriceSpread);
74
77
 
75
78
  if (targetPriceGap.lt(new BN(0))) {
76
- newTargetPrice = markPriceBefore.add(markAdj);
79
+ newTargetPrice = reservePriceBefore.add(markAdj);
77
80
  } else {
78
- newTargetPrice = markPriceBefore.sub(markAdj);
81
+ newTargetPrice = reservePriceBefore.sub(markAdj);
79
82
  }
80
83
 
81
84
  newOptimalPeg = calculatePegFromTargetPrice(
@@ -114,7 +117,7 @@ export function calculateNewAmm(
114
117
  newAmm.sqrtK = newAmm.sqrtK.mul(pKNumer).div(pKDenom);
115
118
  const invariant = newAmm.sqrtK.mul(newAmm.sqrtK);
116
119
  newAmm.quoteAssetReserve = invariant.div(newAmm.baseAssetReserve);
117
- const directionToClose = amm.netBaseAssetAmount.gt(ZERO)
120
+ const directionToClose = amm.baseAssetAmountWithAmm.gt(ZERO)
118
121
  ? PositionDirection.SHORT
119
122
  : PositionDirection.LONG;
120
123
 
@@ -122,7 +125,7 @@ export function calculateNewAmm(
122
125
  calculateAmmReservesAfterSwap(
123
126
  newAmm,
124
127
  'base',
125
- amm.netBaseAssetAmount.abs(),
128
+ amm.baseAssetAmountWithAmm.abs(),
126
129
  getSwapDirection('base', directionToClose)
127
130
  );
128
131
 
@@ -154,7 +157,7 @@ export function calculateUpdatedAMM(
154
157
  newAmm.quoteAssetReserve = invariant.div(newAmm.baseAssetReserve);
155
158
  newAmm.pegMultiplier = newPeg;
156
159
 
157
- const directionToClose = amm.netBaseAssetAmount.gt(ZERO)
160
+ const directionToClose = amm.baseAssetAmountWithAmm.gt(ZERO)
158
161
  ? PositionDirection.SHORT
159
162
  : PositionDirection.LONG;
160
163
 
@@ -162,7 +165,7 @@ export function calculateUpdatedAMM(
162
165
  calculateAmmReservesAfterSwap(
163
166
  newAmm,
164
167
  'base',
165
- amm.netBaseAssetAmount.abs(),
168
+ amm.baseAssetAmountWithAmm.abs(),
166
169
  getSwapDirection('base', directionToClose)
167
170
  );
168
171
 
@@ -239,7 +242,7 @@ export function calculateBidAskPrice(
239
242
  * @param baseAssetReserves
240
243
  * @param quoteAssetReserves
241
244
  * @param pegMultiplier
242
- * @returns price : Precision MARK_PRICE_PRECISION
245
+ * @returns price : Precision PRICE_PRECISION
243
246
  */
244
247
  export function calculatePrice(
245
248
  baseAssetReserves: BN,
@@ -251,7 +254,7 @@ export function calculatePrice(
251
254
  }
252
255
 
253
256
  return quoteAssetReserves
254
- .mul(MARK_PRICE_PRECISION)
257
+ .mul(PRICE_PRECISION)
255
258
  .mul(pegMultiplier)
256
259
  .div(PEG_PRECISION)
257
260
  .div(baseAssetReserves);
@@ -305,13 +308,62 @@ export function calculateAmmReservesAfterSwap(
305
308
  return [newQuoteAssetReserve, newBaseAssetReserve];
306
309
  }
307
310
 
311
+ export function calculateMarketOpenBidAsk(
312
+ baseAssetReserve: BN,
313
+ minBaseAssetReserve: BN,
314
+ maxBaseAssetReserve: BN
315
+ ): [BN, BN] {
316
+ // open orders
317
+ let openAsks;
318
+ if (maxBaseAssetReserve > baseAssetReserve) {
319
+ openAsks = maxBaseAssetReserve.sub(baseAssetReserve).mul(new BN(-1));
320
+ } else {
321
+ openAsks = ZERO;
322
+ }
323
+
324
+ let openBids;
325
+ if (minBaseAssetReserve < baseAssetReserve) {
326
+ openBids = baseAssetReserve.sub(minBaseAssetReserve);
327
+ } else {
328
+ openBids = ZERO;
329
+ }
330
+ return [openBids, openAsks];
331
+ }
332
+
333
+ export function calculateInventoryScale(
334
+ netBaseAssetAmount: BN,
335
+ baseAssetReserve: BN,
336
+ minBaseAssetReserve: BN,
337
+ maxBaseAssetReserve: BN
338
+ ): number {
339
+ const maxScale = BID_ASK_SPREAD_PRECISION.mul(new BN(10));
340
+ // inventory skew
341
+ const [openBids, openAsks] = calculateMarketOpenBidAsk(
342
+ baseAssetReserve,
343
+ minBaseAssetReserve,
344
+ maxBaseAssetReserve
345
+ );
346
+
347
+ const minSideLiquidity = BN.max(
348
+ new BN(1),
349
+ BN.min(openBids.abs(), openAsks.abs())
350
+ );
351
+ const inventoryScale =
352
+ BN.min(
353
+ maxScale,
354
+ netBaseAssetAmount.mul(maxScale).div(minSideLiquidity).abs()
355
+ ).toNumber() / BID_ASK_SPREAD_PRECISION.toNumber();
356
+
357
+ return inventoryScale;
358
+ }
359
+
308
360
  export function calculateEffectiveLeverage(
309
361
  baseSpread: number,
310
362
  quoteAssetReserve: BN,
311
363
  terminalQuoteAssetReserve: BN,
312
364
  pegMultiplier: BN,
313
365
  netBaseAssetAmount: BN,
314
- markPrice: BN,
366
+ reservePrice: BN,
315
367
  totalFeeMinusDistributions: BN
316
368
  ): number {
317
369
  // inventory skew
@@ -321,8 +373,8 @@ export function calculateEffectiveLeverage(
321
373
  .div(AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO);
322
374
 
323
375
  const localBaseAssetValue = netBaseAssetAmount
324
- .mul(markPrice)
325
- .div(AMM_TO_QUOTE_PRECISION_RATIO.mul(MARK_PRICE_PRECISION));
376
+ .mul(reservePrice)
377
+ .div(AMM_TO_QUOTE_PRECISION_RATIO.mul(PRICE_PRECISION));
326
378
 
327
379
  const effectiveLeverage =
328
380
  localBaseAssetValue.sub(netBaseAssetValue).toNumber() /
@@ -342,34 +394,59 @@ export function calculateMaxSpread(marginRatioInitial: number): number {
342
394
 
343
395
  export function calculateSpreadBN(
344
396
  baseSpread: number,
345
- lastOracleMarkSpreadPct: BN,
397
+ lastOracleReservePriceSpreadPct: BN,
346
398
  lastOracleConfPct: BN,
347
399
  maxSpread: number,
348
400
  quoteAssetReserve: BN,
349
401
  terminalQuoteAssetReserve: BN,
350
402
  pegMultiplier: BN,
351
403
  netBaseAssetAmount: BN,
352
- markPrice: BN,
353
- totalFeeMinusDistributions: BN
404
+ reservePrice: BN,
405
+ totalFeeMinusDistributions: BN,
406
+ baseAssetReserve: BN,
407
+ minBaseAssetReserve: BN,
408
+ maxBaseAssetReserve: BN
354
409
  ): [number, number] {
355
410
  let longSpread = baseSpread / 2;
356
411
  let shortSpread = baseSpread / 2;
357
412
 
358
- if (lastOracleMarkSpreadPct.gt(ZERO)) {
413
+ if (lastOracleReservePriceSpreadPct.gt(ZERO)) {
359
414
  shortSpread = Math.max(
360
415
  shortSpread,
361
- lastOracleMarkSpreadPct.abs().toNumber() + lastOracleConfPct.toNumber()
416
+ lastOracleReservePriceSpreadPct.abs().toNumber() +
417
+ lastOracleConfPct.toNumber()
362
418
  );
363
- } else if (lastOracleMarkSpreadPct.lt(ZERO)) {
419
+ } else if (lastOracleReservePriceSpreadPct.lt(ZERO)) {
364
420
  longSpread = Math.max(
365
421
  longSpread,
366
- lastOracleMarkSpreadPct.abs().toNumber() + lastOracleConfPct.toNumber()
422
+ lastOracleReservePriceSpreadPct.abs().toNumber() +
423
+ lastOracleConfPct.toNumber()
367
424
  );
368
425
  }
369
426
 
370
- const maxTargetSpread: number = maxSpread;
427
+ const maxTargetSpread: number = Math.max(
428
+ maxSpread,
429
+ lastOracleReservePriceSpreadPct.abs().toNumber()
430
+ );
371
431
 
372
- const MAX_INVENTORY_SKEW = 5;
432
+ const MAX_BID_ASK_INVENTORY_SKEW_FACTOR = 10;
433
+
434
+ const inventoryScale = calculateInventoryScale(
435
+ netBaseAssetAmount,
436
+ baseAssetReserve,
437
+ minBaseAssetReserve,
438
+ maxBaseAssetReserve
439
+ );
440
+ const inventorySpreadScale = Math.min(
441
+ MAX_BID_ASK_INVENTORY_SKEW_FACTOR,
442
+ 1 + inventoryScale
443
+ );
444
+
445
+ if (netBaseAssetAmount.gt(ZERO)) {
446
+ longSpread *= inventorySpreadScale;
447
+ } else if (netBaseAssetAmount.lt(ZERO)) {
448
+ shortSpread *= inventorySpreadScale;
449
+ }
373
450
 
374
451
  const effectiveLeverage = calculateEffectiveLeverage(
375
452
  baseSpread,
@@ -377,20 +454,23 @@ export function calculateSpreadBN(
377
454
  terminalQuoteAssetReserve,
378
455
  pegMultiplier,
379
456
  netBaseAssetAmount,
380
- markPrice,
457
+ reservePrice,
381
458
  totalFeeMinusDistributions
382
459
  );
383
460
 
384
461
  if (totalFeeMinusDistributions.gt(ZERO)) {
385
- const spreadScale = Math.min(MAX_INVENTORY_SKEW, 1 + effectiveLeverage);
462
+ const spreadScale = Math.min(
463
+ MAX_BID_ASK_INVENTORY_SKEW_FACTOR,
464
+ 1 + effectiveLeverage
465
+ );
386
466
  if (netBaseAssetAmount.gt(ZERO)) {
387
467
  longSpread *= spreadScale;
388
468
  } else {
389
469
  shortSpread *= spreadScale;
390
470
  }
391
471
  } else {
392
- longSpread *= MAX_INVENTORY_SKEW;
393
- shortSpread *= MAX_INVENTORY_SKEW;
472
+ longSpread *= MAX_BID_ASK_INVENTORY_SKEW_FACTOR;
473
+ shortSpread *= MAX_BID_ASK_INVENTORY_SKEW_FACTOR;
394
474
  }
395
475
 
396
476
  const totalSpread = longSpread + shortSpread;
@@ -416,23 +496,23 @@ export function calculateSpread(
416
496
  return amm.baseSpread / 2;
417
497
  }
418
498
 
419
- const markPrice = calculatePrice(
499
+ const reservePrice = calculatePrice(
420
500
  amm.baseAssetReserve,
421
501
  amm.quoteAssetReserve,
422
502
  amm.pegMultiplier
423
503
  );
424
504
 
425
- const targetPrice = oraclePriceData?.price || markPrice;
505
+ const targetPrice = oraclePriceData?.price || reservePrice;
426
506
  const confInterval = oraclePriceData.confidence || ZERO;
427
507
 
428
- const targetMarkSpreadPct = markPrice
508
+ const targetMarkSpreadPct = reservePrice
429
509
  .sub(targetPrice)
430
510
  .mul(BID_ASK_SPREAD_PRECISION)
431
- .div(markPrice);
511
+ .div(reservePrice);
432
512
 
433
513
  const confIntervalPct = confInterval
434
514
  .mul(BID_ASK_SPREAD_PRECISION)
435
- .div(markPrice);
515
+ .div(reservePrice);
436
516
 
437
517
  const [longSpread, shortSpread] = calculateSpreadBN(
438
518
  amm.baseSpread,
@@ -442,9 +522,12 @@ export function calculateSpread(
442
522
  amm.quoteAssetReserve,
443
523
  amm.terminalQuoteAssetReserve,
444
524
  amm.pegMultiplier,
445
- amm.netBaseAssetAmount,
446
- markPrice,
447
- amm.totalFeeMinusDistributions
525
+ amm.baseAssetAmountWithAmm,
526
+ reservePrice,
527
+ amm.totalFeeMinusDistributions,
528
+ amm.baseAssetReserve,
529
+ amm.minBaseAssetReserve,
530
+ amm.maxBaseAssetReserve
448
531
  );
449
532
 
450
533
  let spread: number;
@@ -543,10 +626,10 @@ export function getSwapDirection(
543
626
  * Helper function calculating terminal price of amm
544
627
  *
545
628
  * @param market
546
- * @returns cost : Precision MARK_PRICE_PRECISION
629
+ * @returns cost : Precision PRICE_PRECISION
547
630
  */
548
- export function calculateTerminalPrice(market: MarketAccount) {
549
- const directionToClose = market.amm.netBaseAssetAmount.gt(ZERO)
631
+ export function calculateTerminalPrice(market: PerpMarketAccount) {
632
+ const directionToClose = market.amm.baseAssetAmountWithAmm.gt(ZERO)
550
633
  ? PositionDirection.SHORT
551
634
  : PositionDirection.LONG;
552
635
 
@@ -554,12 +637,12 @@ export function calculateTerminalPrice(market: MarketAccount) {
554
637
  calculateAmmReservesAfterSwap(
555
638
  market.amm,
556
639
  'base',
557
- market.amm.netBaseAssetAmount.abs(),
640
+ market.amm.baseAssetAmountWithAmm.abs(),
558
641
  getSwapDirection('base', directionToClose)
559
642
  );
560
643
 
561
644
  const terminalPrice = newQuoteAssetReserve
562
- .mul(MARK_PRICE_PRECISION)
645
+ .mul(PRICE_PRECISION)
563
646
  .mul(market.amm.pegMultiplier)
564
647
  .div(PEG_PRECISION)
565
648
  .div(newBaseAssetReserve);
@@ -576,7 +659,7 @@ export function calculateMaxBaseAssetAmountToTrade(
576
659
  const invariant = amm.sqrtK.mul(amm.sqrtK);
577
660
 
578
661
  const newBaseAssetReserveSquared = invariant
579
- .mul(MARK_PRICE_PRECISION)
662
+ .mul(PRICE_PRECISION)
580
663
  .mul(amm.pegMultiplier)
581
664
  .div(limit_price)
582
665
  .div(PEG_PRECISION);
@@ -610,6 +693,10 @@ export function calculateQuoteAssetAmountSwapped(
610
693
  pegMultiplier: BN,
611
694
  swapDirection: SwapDirection
612
695
  ): BN {
696
+ if (isVariant(swapDirection, 'remove')) {
697
+ quoteAssetReserves = quoteAssetReserves.add(ONE);
698
+ }
699
+
613
700
  let quoteAssetAmount = quoteAssetReserves
614
701
  .mul(pegMultiplier)
615
702
  .div(AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO);
@@ -620,3 +707,29 @@ export function calculateQuoteAssetAmountSwapped(
620
707
 
621
708
  return quoteAssetAmount;
622
709
  }
710
+
711
+ export function calculateMaxBaseAssetAmountFillable(
712
+ amm: AMM,
713
+ orderDirection: PositionDirection
714
+ ): BN {
715
+ const maxFillSize = amm.baseAssetReserve.div(
716
+ new BN(amm.maxFillReserveFraction)
717
+ );
718
+ let maxBaseAssetAmountOnSide: BN;
719
+ if (isVariant(orderDirection, 'long')) {
720
+ maxBaseAssetAmountOnSide = BN.max(
721
+ ZERO,
722
+ amm.baseAssetReserve.sub(amm.minBaseAssetReserve)
723
+ );
724
+ } else {
725
+ maxBaseAssetAmountOnSide = BN.max(
726
+ ZERO,
727
+ amm.maxBaseAssetReserve.sub(amm.baseAssetReserve)
728
+ );
729
+ }
730
+
731
+ return standardizeBaseAssetAmount(
732
+ BN.min(maxFillSize, maxBaseAssetAmountOnSide),
733
+ amm.orderStepSize
734
+ );
735
+ }
@@ -1,9 +1,9 @@
1
1
  import { BN } from '../';
2
- import { MARK_PRICE_PRECISION } from '../constants/numericConstants';
2
+ import { PRICE_PRECISION } from '../constants/numericConstants';
3
3
 
4
4
  export const convertToNumber = (
5
5
  bigNumber: BN,
6
- precision: BN = MARK_PRICE_PRECISION
6
+ precision: BN = PRICE_PRECISION
7
7
  ) => {
8
8
  if (!bigNumber) return 0;
9
9
  return (
@@ -0,0 +1,31 @@
1
+ import {
2
+ isOneOfVariant,
3
+ isVariant,
4
+ PerpMarketAccount,
5
+ SpotMarketAccount,
6
+ StateAccount,
7
+ } from '../types';
8
+
9
+ export function exchangePaused(state: StateAccount): boolean {
10
+ return isVariant(state.exchangeStatus, 'paused');
11
+ }
12
+
13
+ export function fillPaused(
14
+ state: StateAccount,
15
+ market: PerpMarketAccount | SpotMarketAccount
16
+ ): boolean {
17
+ return (
18
+ isOneOfVariant(state.exchangeStatus, ['paused', 'fillPaused']) ||
19
+ isOneOfVariant(market.status, ['paused', 'fillPaused'])
20
+ );
21
+ }
22
+
23
+ export function ammPaused(
24
+ state: StateAccount,
25
+ market: PerpMarketAccount | SpotMarketAccount
26
+ ): boolean {
27
+ return (
28
+ isOneOfVariant(state.exchangeStatus, ['paused', 'ammPaused']) ||
29
+ isOneOfVariant(market.status, ['paused', 'ammPaused'])
30
+ );
31
+ }
@@ -1,13 +1,13 @@
1
1
  import { BN } from '@project-serum/anchor';
2
2
  import {
3
3
  AMM_RESERVE_PRECISION,
4
- MARK_PRICE_PRECISION,
4
+ PRICE_PRECISION,
5
5
  QUOTE_PRECISION,
6
6
  ZERO,
7
7
  } from '../constants/numericConstants';
8
- import { MarketAccount } from '../types';
9
- import { calculateMarkPrice } from './market';
8
+ import { PerpMarketAccount, isVariant } from '../types';
10
9
  import { OraclePriceData } from '../oracles/types';
10
+ import { calculateBidAskPrice } from './amm';
11
11
 
12
12
  /**
13
13
  *
@@ -17,7 +17,7 @@ import { OraclePriceData } from '../oracles/types';
17
17
  * @returns Estimated funding rate. : Precision //TODO-PRECISION
18
18
  */
19
19
  export async function calculateAllEstimatedFundingRate(
20
- market: MarketAccount,
20
+ market: PerpMarketAccount,
21
21
  oraclePriceData?: OraclePriceData,
22
22
  periodAdjustment: BN = new BN(1)
23
23
  ): Promise<[BN, BN, BN, BN, BN]> {
@@ -29,7 +29,7 @@ export async function calculateAllEstimatedFundingRate(
29
29
  const hoursInDay = new BN(24);
30
30
  const ONE = new BN(1);
31
31
 
32
- if (!market.initialized) {
32
+ if (isVariant(market.status, 'uninitialized')) {
33
33
  return [ZERO, ZERO, ZERO, ZERO, ZERO];
34
34
  }
35
35
 
@@ -48,10 +48,8 @@ export async function calculateAllEstimatedFundingRate(
48
48
  secondsInHour,
49
49
  BN.max(ZERO, secondsInHour.sub(timeSinceLastMarkChange))
50
50
  );
51
- const baseAssetPriceWithMantissa = calculateMarkPrice(
52
- market,
53
- oraclePriceData
54
- );
51
+ const [bid, ask] = calculateBidAskPrice(market.amm, oraclePriceData);
52
+ const baseAssetPriceWithMantissa = bid.add(ask).div(new BN(2));
55
53
 
56
54
  const markTwapWithMantissa = markTwapTimeSinceLastUpdate
57
55
  .mul(lastMarkTwapWithMantissa)
@@ -60,8 +58,10 @@ export async function calculateAllEstimatedFundingRate(
60
58
 
61
59
  // calculate real-time (predicted) oracle twap
62
60
  // note: oracle twap depends on `when the chord is struck` (market is trade)
63
- const lastOracleTwapWithMantissa = market.amm.lastOraclePriceTwap;
64
- const lastOraclePriceTwapTs = market.amm.lastOraclePriceTwapTs;
61
+ const lastOracleTwapWithMantissa =
62
+ market.amm.historicalOracleData.lastOraclePriceTwap;
63
+ const lastOraclePriceTwapTs =
64
+ market.amm.historicalOracleData.lastOraclePriceTwapTs;
65
65
 
66
66
  const oracleInvalidDuration = BN.max(
67
67
  ZERO,
@@ -85,12 +85,12 @@ export async function calculateAllEstimatedFundingRate(
85
85
  const oracleLiveVsTwap = oraclePrice
86
86
  .sub(lastOracleTwapWithMantissa)
87
87
  .abs()
88
- .mul(MARK_PRICE_PRECISION)
88
+ .mul(PRICE_PRECISION)
89
89
  .mul(new BN(100))
90
90
  .div(lastOracleTwapWithMantissa);
91
91
 
92
92
  // verify pyth live input is within 10% of last twap for live update
93
- if (oracleLiveVsTwap.lte(MARK_PRICE_PRECISION.mul(new BN(10)))) {
93
+ if (oracleLiveVsTwap.lte(PRICE_PRECISION.mul(new BN(10)))) {
94
94
  oracleTwapWithMantissa = oracleTwapTimeSinceLastUpdate
95
95
  .mul(lastOracleTwapWithMantissa)
96
96
  .add(timeSinceLastMarkChange.mul(oraclePrice))
@@ -108,7 +108,7 @@ export async function calculateAllEstimatedFundingRate(
108
108
  );
109
109
 
110
110
  const twapSpreadPct = twapSpread
111
- .mul(MARK_PRICE_PRECISION)
111
+ .mul(PRICE_PRECISION)
112
112
  .mul(new BN(100))
113
113
  .div(shrunkLastOracleTwapwithMantissa);
114
114
 
@@ -125,7 +125,7 @@ export async function calculateAllEstimatedFundingRate(
125
125
  const interpRateQuote = twapSpreadPct
126
126
  .mul(periodAdjustment)
127
127
  .div(hoursInDay)
128
- .div(MARK_PRICE_PRECISION.div(QUOTE_PRECISION));
128
+ .div(PRICE_PRECISION.div(QUOTE_PRECISION));
129
129
 
130
130
  let feePoolSize = calculateFundingPool(market);
131
131
  if (interpRateQuote.lt(new BN(0))) {
@@ -135,9 +135,11 @@ export async function calculateAllEstimatedFundingRate(
135
135
  let cappedAltEst: BN;
136
136
  let largerSide: BN;
137
137
  let smallerSide: BN;
138
- if (market.baseAssetAmountLong.gt(market.baseAssetAmountShort.abs())) {
139
- largerSide = market.baseAssetAmountLong.abs();
140
- smallerSide = market.baseAssetAmountShort.abs();
138
+ if (
139
+ market.amm.baseAssetAmountLong.gt(market.amm.baseAssetAmountShort.abs())
140
+ ) {
141
+ largerSide = market.amm.baseAssetAmountLong.abs();
142
+ smallerSide = market.amm.baseAssetAmountShort.abs();
141
143
  if (twapSpread.gt(new BN(0))) {
142
144
  return [
143
145
  markTwapWithMantissa,
@@ -147,9 +149,11 @@ export async function calculateAllEstimatedFundingRate(
147
149
  interpEst,
148
150
  ];
149
151
  }
150
- } else if (market.baseAssetAmountLong.lt(market.baseAssetAmountShort.abs())) {
151
- largerSide = market.baseAssetAmountShort.abs();
152
- smallerSide = market.baseAssetAmountLong.abs();
152
+ } else if (
153
+ market.amm.baseAssetAmountLong.lt(market.amm.baseAssetAmountShort.abs())
154
+ ) {
155
+ largerSide = market.amm.baseAssetAmountShort.abs();
156
+ smallerSide = market.amm.baseAssetAmountLong.abs();
153
157
  if (twapSpread.lt(new BN(0))) {
154
158
  return [
155
159
  markTwapWithMantissa,
@@ -173,12 +177,12 @@ export async function calculateAllEstimatedFundingRate(
173
177
  // funding smaller flow
174
178
  cappedAltEst = smallerSide.mul(twapSpread).div(hoursInDay);
175
179
  const feePoolTopOff = feePoolSize
176
- .mul(MARK_PRICE_PRECISION.div(QUOTE_PRECISION))
180
+ .mul(PRICE_PRECISION.div(QUOTE_PRECISION))
177
181
  .mul(AMM_RESERVE_PRECISION);
178
182
  cappedAltEst = cappedAltEst.add(feePoolTopOff).div(largerSide);
179
183
 
180
184
  cappedAltEst = cappedAltEst
181
- .mul(MARK_PRICE_PRECISION)
185
+ .mul(PRICE_PRECISION)
182
186
  .mul(new BN(100))
183
187
  .div(oracleTwapWithMantissa)
184
188
  .mul(periodAdjustment);
@@ -208,7 +212,7 @@ export async function calculateAllEstimatedFundingRate(
208
212
  * @returns Estimated funding rate. : Precision //TODO-PRECISION
209
213
  */
210
214
  export async function calculateEstimatedFundingRate(
211
- market: MarketAccount,
215
+ market: PerpMarketAccount,
212
216
  oraclePriceData?: OraclePriceData,
213
217
  periodAdjustment: BN = new BN(1),
214
218
  estimationMethod?: 'interpolated' | 'lowerbound' | 'capped'
@@ -238,7 +242,7 @@ export async function calculateEstimatedFundingRate(
238
242
  * @returns Estimated funding rate. : Precision //TODO-PRECISION
239
243
  */
240
244
  export async function calculateLongShortFundingRate(
241
- market: MarketAccount,
245
+ market: PerpMarketAccount,
242
246
  oraclePriceData?: OraclePriceData,
243
247
  periodAdjustment: BN = new BN(1)
244
248
  ): Promise<[BN, BN]> {
@@ -249,9 +253,11 @@ export async function calculateLongShortFundingRate(
249
253
  periodAdjustment
250
254
  );
251
255
 
252
- if (market.baseAssetAmountLong.gt(market.baseAssetAmountShort)) {
256
+ if (market.amm.baseAssetAmountLong.gt(market.amm.baseAssetAmountShort)) {
253
257
  return [cappedAltEst, interpEst];
254
- } else if (market.baseAssetAmountLong.lt(market.baseAssetAmountShort)) {
258
+ } else if (
259
+ market.amm.baseAssetAmountLong.lt(market.amm.baseAssetAmountShort)
260
+ ) {
255
261
  return [interpEst, cappedAltEst];
256
262
  } else {
257
263
  return [interpEst, interpEst];
@@ -266,7 +272,7 @@ export async function calculateLongShortFundingRate(
266
272
  * @returns Estimated funding rate. : Precision //TODO-PRECISION
267
273
  */
268
274
  export async function calculateLongShortFundingRateAndLiveTwaps(
269
- market: MarketAccount,
275
+ market: PerpMarketAccount,
270
276
  oraclePriceData?: OraclePriceData,
271
277
  periodAdjustment: BN = new BN(1)
272
278
  ): Promise<[BN, BN, BN, BN]> {
@@ -277,9 +283,13 @@ export async function calculateLongShortFundingRateAndLiveTwaps(
277
283
  periodAdjustment
278
284
  );
279
285
 
280
- if (market.baseAssetAmountLong.gt(market.baseAssetAmountShort.abs())) {
286
+ if (
287
+ market.amm.baseAssetAmountLong.gt(market.amm.baseAssetAmountShort.abs())
288
+ ) {
281
289
  return [markTwapLive, oracleTwapLive, cappedAltEst, interpEst];
282
- } else if (market.baseAssetAmountLong.lt(market.baseAssetAmountShort.abs())) {
290
+ } else if (
291
+ market.amm.baseAssetAmountLong.lt(market.amm.baseAssetAmountShort.abs())
292
+ ) {
283
293
  return [markTwapLive, oracleTwapLive, interpEst, cappedAltEst];
284
294
  } else {
285
295
  return [markTwapLive, oracleTwapLive, interpEst, interpEst];
@@ -291,7 +301,7 @@ export async function calculateLongShortFundingRateAndLiveTwaps(
291
301
  * @param market
292
302
  * @returns Estimated fee pool size
293
303
  */
294
- export function calculateFundingPool(market: MarketAccount): BN {
304
+ export function calculateFundingPool(market: PerpMarketAccount): BN {
295
305
  // todo
296
306
  const totalFeeLB = market.amm.totalExchangeFee.div(new BN(2));
297
307
  const feePool = BN.max(
@@ -0,0 +1,35 @@
1
+ import { ZERO } from '../constants/numericConstants';
2
+ import { BN } from '../index';
3
+
4
+ export function stakeAmountToShares(
5
+ amount: BN,
6
+ totalIfShares: BN,
7
+ insuranceFundVaultBalance: BN
8
+ ): BN {
9
+ let nShares: BN;
10
+ if (insuranceFundVaultBalance.gt(ZERO)) {
11
+ nShares = amount.mul(totalIfShares).div(insuranceFundVaultBalance);
12
+ } else {
13
+ nShares = amount;
14
+ }
15
+
16
+ return nShares;
17
+ }
18
+
19
+ export function unstakeSharesToAmount(
20
+ nShares: BN,
21
+ totalIfShares: BN,
22
+ insuranceFundVaultBalance: BN
23
+ ): BN {
24
+ let amount: BN;
25
+ if (totalIfShares.gt(ZERO)) {
26
+ amount = BN.max(
27
+ ZERO,
28
+ nShares.mul(insuranceFundVaultBalance).div(totalIfShares)
29
+ );
30
+ } else {
31
+ amount = ZERO;
32
+ }
33
+
34
+ return amount;
35
+ }