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

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 (234) 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/pollingUserStatsAccountSubscriber.d.ts +27 -0
  15. package/lib/accounts/pollingUserStatsAccountSubscriber.js +113 -0
  16. package/lib/accounts/types.d.ts +26 -15
  17. package/lib/accounts/webSocketDriftClientAccountSubscriber.d.ts +49 -0
  18. package/lib/accounts/{webSocketClearingHouseAccountSubscriber.js → webSocketDriftClientAccountSubscriber.js} +47 -45
  19. package/lib/accounts/webSocketUserStatsAccountSubsriber.d.ts +20 -0
  20. package/lib/accounts/webSocketUserStatsAccountSubsriber.js +47 -0
  21. package/lib/addresses/marketAddresses.d.ts +1 -3
  22. package/lib/addresses/marketAddresses.js +1 -1
  23. package/lib/addresses/pda.d.ts +15 -9
  24. package/lib/addresses/pda.js +73 -35
  25. package/lib/adminClient.d.ts +65 -0
  26. package/lib/adminClient.js +637 -0
  27. package/lib/config.d.ts +9 -9
  28. package/lib/config.js +25 -21
  29. package/lib/constants/numericConstants.d.ts +30 -12
  30. package/lib/constants/numericConstants.js +41 -21
  31. package/lib/constants/perpMarkets.d.ts +18 -0
  32. package/lib/constants/{markets.js → perpMarkets.js} +7 -7
  33. package/lib/constants/spotMarkets.d.ts +19 -0
  34. package/lib/constants/spotMarkets.js +53 -0
  35. package/lib/dlob/DLOB.d.ts +82 -0
  36. package/lib/dlob/DLOB.js +696 -0
  37. package/lib/dlob/DLOBNode.d.ts +54 -0
  38. package/lib/dlob/DLOBNode.js +77 -0
  39. package/lib/dlob/NodeList.d.ts +27 -0
  40. package/lib/dlob/NodeList.js +144 -0
  41. package/lib/driftClient.d.ts +233 -0
  42. package/lib/driftClient.js +2096 -0
  43. package/lib/{clearingHouseConfig.d.ts → driftClientConfig.d.ts} +9 -9
  44. package/lib/{clearingHouseConfig.js → driftClientConfig.js} +0 -0
  45. package/lib/events/eventList.js +3 -0
  46. package/lib/events/eventSubscriber.d.ts +5 -2
  47. package/lib/events/eventSubscriber.js +25 -11
  48. package/lib/events/fetchLogs.d.ts +13 -2
  49. package/lib/events/fetchLogs.js +40 -12
  50. package/lib/events/pollingLogProvider.d.ts +2 -1
  51. package/lib/events/pollingLogProvider.js +7 -3
  52. package/lib/events/sort.js +8 -11
  53. package/lib/events/types.d.ts +9 -3
  54. package/lib/events/types.js +6 -0
  55. package/lib/events/webSocketLogProvider.js +1 -1
  56. package/lib/examples/makeTradeExample.js +30 -18
  57. package/lib/factory/bigNum.d.ts +8 -4
  58. package/lib/factory/bigNum.js +109 -19
  59. package/lib/idl/drift.json +8250 -0
  60. package/lib/idl/{mock_usdc_faucet.json → token_faucet.json} +46 -23
  61. package/lib/index.d.ts +30 -13
  62. package/lib/index.js +30 -13
  63. package/lib/math/amm.d.ts +9 -6
  64. package/lib/math/amm.js +91 -38
  65. package/lib/math/conversion.js +1 -1
  66. package/lib/math/exchangeStatus.d.ts +4 -0
  67. package/lib/math/exchangeStatus.js +18 -0
  68. package/lib/math/funding.d.ts +6 -6
  69. package/lib/math/funding.js +23 -21
  70. package/lib/math/insurance.d.ts +4 -0
  71. package/lib/math/insurance.js +27 -0
  72. package/lib/math/margin.d.ts +11 -0
  73. package/lib/math/margin.js +82 -0
  74. package/lib/math/market.d.ts +14 -9
  75. package/lib/math/market.js +70 -10
  76. package/lib/math/oracles.d.ts +4 -0
  77. package/lib/math/oracles.js +36 -8
  78. package/lib/math/orders.d.ts +14 -6
  79. package/lib/math/orders.js +90 -17
  80. package/lib/math/position.d.ts +27 -13
  81. package/lib/math/position.js +92 -36
  82. package/lib/math/repeg.js +17 -8
  83. package/lib/math/spotBalance.d.ts +22 -0
  84. package/lib/math/spotBalance.js +192 -0
  85. package/lib/math/spotMarket.d.ts +4 -0
  86. package/lib/math/spotMarket.js +8 -0
  87. package/lib/math/spotPosition.d.ts +6 -0
  88. package/lib/math/spotPosition.js +23 -0
  89. package/lib/math/trade.d.ts +10 -10
  90. package/lib/math/trade.js +27 -31
  91. package/lib/oracles/pythClient.js +1 -1
  92. package/lib/oracles/quoteAssetOracleClient.js +1 -1
  93. package/lib/oracles/switchboardClient.js +1 -1
  94. package/lib/orderParams.d.ts +4 -4
  95. package/lib/orderParams.js +12 -4
  96. package/lib/serum/serumFulfillmentConfigMap.d.ts +10 -0
  97. package/lib/serum/serumFulfillmentConfigMap.js +17 -0
  98. package/lib/serum/serumSubscriber.d.ts +27 -0
  99. package/lib/serum/serumSubscriber.js +56 -0
  100. package/lib/serum/types.d.ts +11 -0
  101. package/lib/{clearingHouseUserConfig.js → serum/types.js} +0 -0
  102. package/lib/slot/SlotSubscriber.d.ts +7 -0
  103. package/lib/slot/SlotSubscriber.js +3 -0
  104. package/lib/{mockUSDCFaucet.d.ts → tokenFaucet.d.ts} +8 -5
  105. package/lib/{mockUSDCFaucet.js → tokenFaucet.js} +63 -51
  106. package/lib/tx/retryTxSender.d.ts +1 -1
  107. package/lib/tx/retryTxSender.js +13 -4
  108. package/lib/tx/types.d.ts +1 -1
  109. package/lib/tx/utils.js +1 -1
  110. package/lib/types.d.ts +589 -196
  111. package/lib/types.js +108 -17
  112. package/lib/user.d.ts +226 -0
  113. package/lib/user.js +949 -0
  114. package/lib/userConfig.d.ts +14 -0
  115. package/lib/userConfig.js +2 -0
  116. package/lib/userMap/userMap.d.ts +41 -0
  117. package/lib/userMap/userMap.js +85 -0
  118. package/lib/userMap/userStatsMap.d.ts +19 -0
  119. package/lib/userMap/userStatsMap.js +68 -0
  120. package/lib/userName.d.ts +1 -0
  121. package/lib/userName.js +3 -2
  122. package/lib/userStats.d.ts +18 -0
  123. package/lib/userStats.js +49 -0
  124. package/lib/userStatsConfig.d.ts +14 -0
  125. package/lib/userStatsConfig.js +2 -0
  126. package/lib/util/computeUnits.js +1 -1
  127. package/lib/util/getTokenAddress.d.ts +2 -0
  128. package/lib/util/getTokenAddress.js +9 -0
  129. package/package.json +10 -3
  130. package/src/accounts/bulkAccountLoader.ts +44 -34
  131. package/src/accounts/bulkUserStatsSubscription.ts +33 -0
  132. package/src/accounts/bulkUserSubscription.ts +2 -3
  133. package/src/accounts/fetch.ts +27 -2
  134. package/src/accounts/{pollingClearingHouseAccountSubscriber.ts → pollingDriftClientAccountSubscriber.ts} +65 -75
  135. package/src/accounts/{pollingOracleSubscriber.ts → pollingOracleAccountSubscriber.ts} +2 -2
  136. package/src/accounts/pollingUserStatsAccountSubscriber.ts +172 -0
  137. package/src/accounts/types.ts +35 -15
  138. package/src/accounts/{webSocketClearingHouseAccountSubscriber.ts → webSocketDriftClientAccountSubscriber.ts} +78 -73
  139. package/src/accounts/webSocketUserStatsAccountSubsriber.ts +80 -0
  140. package/src/addresses/marketAddresses.ts +3 -4
  141. package/src/addresses/pda.ts +105 -33
  142. package/src/adminClient.ts +1207 -0
  143. package/src/config.ts +37 -31
  144. package/src/constants/numericConstants.ts +58 -24
  145. package/src/constants/{markets.ts → perpMarkets.ts} +10 -10
  146. package/src/constants/spotMarkets.ts +73 -0
  147. package/src/dlob/DLOB.ts +1123 -0
  148. package/src/dlob/DLOBNode.ts +155 -0
  149. package/src/dlob/NodeList.ts +195 -0
  150. package/src/driftClient.ts +3564 -0
  151. package/src/{clearingHouseConfig.ts → driftClientConfig.ts} +9 -8
  152. package/src/events/eventList.ts +3 -0
  153. package/src/events/eventSubscriber.ts +36 -14
  154. package/src/events/fetchLogs.ts +55 -13
  155. package/src/events/pollingLogProvider.ts +11 -3
  156. package/src/events/sort.ts +11 -15
  157. package/src/events/types.ts +21 -2
  158. package/src/events/webSocketLogProvider.ts +1 -1
  159. package/src/examples/makeTradeExample.ts +44 -28
  160. package/src/factory/bigNum.ts +150 -22
  161. package/src/idl/drift.json +8250 -0
  162. package/src/idl/pyth.json +98 -2
  163. package/src/idl/{mock_usdc_faucet.json → token_faucet.json} +46 -23
  164. package/src/index.ts +30 -13
  165. package/src/math/amm.ts +161 -48
  166. package/src/math/conversion.ts +2 -2
  167. package/src/math/exchangeStatus.ts +31 -0
  168. package/src/math/funding.ts +41 -31
  169. package/src/math/insurance.ts +35 -0
  170. package/src/math/margin.ts +133 -0
  171. package/src/math/market.ts +143 -14
  172. package/src/math/oracles.ts +63 -9
  173. package/src/math/orders.ts +163 -26
  174. package/src/math/position.ts +136 -58
  175. package/src/math/repeg.ts +19 -9
  176. package/src/math/spotBalance.ts +319 -0
  177. package/src/math/spotMarket.ts +9 -0
  178. package/src/math/spotPosition.ts +47 -0
  179. package/src/math/trade.ts +33 -37
  180. package/src/oracles/pythClient.ts +2 -2
  181. package/src/oracles/quoteAssetOracleClient.ts +2 -2
  182. package/src/oracles/switchboardClient.ts +2 -2
  183. package/src/orderParams.ts +16 -8
  184. package/src/serum/serumFulfillmentConfigMap.ts +26 -0
  185. package/src/serum/serumSubscriber.ts +99 -0
  186. package/src/serum/types.ts +13 -0
  187. package/src/slot/SlotSubscriber.ts +11 -1
  188. package/src/{mockUSDCFaucet.ts → tokenFaucet.ts} +82 -70
  189. package/src/tx/retryTxSender.ts +16 -5
  190. package/src/tx/types.ts +2 -1
  191. package/src/tx/utils.ts +1 -1
  192. package/src/types.ts +572 -178
  193. package/src/user.ts +1582 -0
  194. package/src/{clearingHouseUserConfig.ts → userConfig.ts} +5 -5
  195. package/src/userMap/userMap.ts +124 -0
  196. package/src/userMap/userStatsMap.ts +108 -0
  197. package/src/userName.ts +2 -1
  198. package/src/userStats.ts +75 -0
  199. package/src/userStatsConfig.ts +18 -0
  200. package/src/util/computeUnits.ts +1 -1
  201. package/src/util/getTokenAddress.ts +18 -0
  202. package/tests/bn/test.ts +46 -11
  203. package/tests/dlob/helpers.ts +611 -0
  204. package/tests/dlob/test.ts +4588 -0
  205. package/lib/accounts/webSocketClearingHouseAccountSubscriber.d.ts +0 -49
  206. package/lib/admin.d.ts +0 -44
  207. package/lib/admin.js +0 -433
  208. package/lib/clearingHouse.d.ts +0 -133
  209. package/lib/clearingHouse.js +0 -931
  210. package/lib/clearingHouseUser.d.ts +0 -187
  211. package/lib/clearingHouseUser.js +0 -643
  212. package/lib/clearingHouseUserConfig.d.ts +0 -14
  213. package/lib/constants/banks.d.ts +0 -16
  214. package/lib/constants/banks.js +0 -34
  215. package/lib/constants/markets.d.ts +0 -19
  216. package/lib/idl/clearing_house.json +0 -3998
  217. package/lib/math/bankBalance.d.ts +0 -9
  218. package/lib/math/bankBalance.js +0 -75
  219. package/lib/math/state.d.ts +0 -8
  220. package/lib/math/state.js +0 -15
  221. package/lib/orders.d.ts +0 -8
  222. package/lib/orders.js +0 -134
  223. package/src/admin.ts +0 -722
  224. package/src/clearingHouse.ts +0 -1451
  225. package/src/clearingHouseUser.ts +0 -989
  226. package/src/constants/banks.ts +0 -43
  227. package/src/idl/clearing_house.json +0 -3998
  228. package/src/math/bankBalance.ts +0 -112
  229. package/src/math/state.ts +0 -14
  230. package/src/math/utils.js +0 -27
  231. package/src/math/utils.js.map +0 -1
  232. package/src/orders.ts +0 -244
  233. package/src/util/computeUnits.js +0 -17
  234. package/src/util/computeUnits.js.map +0 -1
@@ -0,0 +1,9 @@
1
+ import { BN } from '@project-serum/anchor';
2
+ import { SpotMarketAccount } from '../types';
3
+
4
+ export function castNumberToSpotPrecision(
5
+ value: number,
6
+ spotMarket: SpotMarketAccount
7
+ ): BN {
8
+ return new BN(value * Math.pow(10, spotMarket.decimals));
9
+ }
@@ -0,0 +1,47 @@
1
+ import { SpotMarketAccount, SpotPosition } from '../types';
2
+ import { ZERO } from '../constants/numericConstants';
3
+ import { BN } from '@project-serum/anchor';
4
+ import {
5
+ getSignedTokenAmount,
6
+ getTokenAmount,
7
+ getTokenValue,
8
+ } from './spotBalance';
9
+ import { OraclePriceData } from '../oracles/types';
10
+
11
+ export function isSpotPositionAvailable(position: SpotPosition): boolean {
12
+ return position.scaledBalance.eq(ZERO) && position.openOrders === 0;
13
+ }
14
+
15
+ export function getWorstCaseTokenAmounts(
16
+ spotPosition: SpotPosition,
17
+ spotMarketAccount: SpotMarketAccount,
18
+ oraclePriceData: OraclePriceData
19
+ ): [BN, BN] {
20
+ const tokenAmount = getSignedTokenAmount(
21
+ getTokenAmount(
22
+ spotPosition.scaledBalance,
23
+ spotMarketAccount,
24
+ spotPosition.balanceType
25
+ ),
26
+ spotPosition.balanceType
27
+ );
28
+
29
+ const tokenAmountAllBidsFill = tokenAmount.add(spotPosition.openBids);
30
+ const tokenAmountAllAsksFill = tokenAmount.add(spotPosition.openAsks);
31
+
32
+ if (tokenAmountAllAsksFill.abs().gt(tokenAmountAllBidsFill.abs())) {
33
+ const worstCaseQuoteTokenAmount = getTokenValue(
34
+ spotPosition.openAsks.neg(),
35
+ spotMarketAccount.decimals,
36
+ oraclePriceData
37
+ );
38
+ return [tokenAmountAllBidsFill, worstCaseQuoteTokenAmount];
39
+ } else {
40
+ const worstCaseQuoteTokenAmount = getTokenValue(
41
+ spotPosition.openBids.neg(),
42
+ spotMarketAccount.decimals,
43
+ oraclePriceData
44
+ );
45
+ return [tokenAmountAllAsksFill, worstCaseQuoteTokenAmount];
46
+ }
47
+ }
package/src/math/trade.ts CHANGED
@@ -1,8 +1,8 @@
1
- import { MarketAccount, PositionDirection } from '../types';
1
+ import { PerpMarketAccount, PositionDirection } from '../types';
2
2
  import { BN } from '@project-serum/anchor';
3
3
  import { assert } from '../assert/assert';
4
4
  import {
5
- MARK_PRICE_PRECISION,
5
+ PRICE_PRECISION,
6
6
  PEG_PRECISION,
7
7
  AMM_TO_QUOTE_PRECISION_RATIO,
8
8
  ZERO,
@@ -10,7 +10,7 @@ import {
10
10
  import {
11
11
  calculateBidPrice,
12
12
  calculateAskPrice,
13
- calculateMarkPrice,
13
+ calculateReservePrice,
14
14
  } from './market';
15
15
  import {
16
16
  calculateAmmReservesAfterSwap,
@@ -48,18 +48,18 @@ export type PriceImpactUnit =
48
48
  * @param useSpread whether to consider spread with calculating slippage
49
49
  * @return [pctAvgSlippage, pctMaxSlippage, entryPrice, newPrice]
50
50
  *
51
- * 'pctAvgSlippage' => the percentage change to entryPrice (average est slippage in execution) : Precision MARK_PRICE_PRECISION
51
+ * 'pctAvgSlippage' => the percentage change to entryPrice (average est slippage in execution) : Precision PRICE_PRECISION
52
52
  *
53
- * 'pctMaxSlippage' => the percentage change to maxPrice (highest est slippage in execution) : Precision MARK_PRICE_PRECISION
53
+ * 'pctMaxSlippage' => the percentage change to maxPrice (highest est slippage in execution) : Precision PRICE_PRECISION
54
54
  *
55
- * 'entryPrice' => the average price of the trade : Precision MARK_PRICE_PRECISION
55
+ * 'entryPrice' => the average price of the trade : Precision PRICE_PRECISION
56
56
  *
57
- * 'newPrice' => the price of the asset after the trade : Precision MARK_PRICE_PRECISION
57
+ * 'newPrice' => the price of the asset after the trade : Precision PRICE_PRECISION
58
58
  */
59
59
  export function calculateTradeSlippage(
60
60
  direction: PositionDirection,
61
61
  amount: BN,
62
- market: MarketAccount,
62
+ market: PerpMarketAccount,
63
63
  inputAssetType: AssetType = 'quote',
64
64
  oraclePriceData?: OraclePriceData,
65
65
  useSpread = true
@@ -73,7 +73,7 @@ export function calculateTradeSlippage(
73
73
  oldPrice = calculateBidPrice(market, oraclePriceData);
74
74
  }
75
75
  } else {
76
- oldPrice = calculateMarkPrice(market, oraclePriceData);
76
+ oldPrice = calculateReservePrice(market, oraclePriceData);
77
77
  }
78
78
  if (amount.eq(ZERO)) {
79
79
  return [ZERO, ZERO, oldPrice, oldPrice];
@@ -90,7 +90,7 @@ export function calculateTradeSlippage(
90
90
 
91
91
  const entryPrice = acquiredQuoteAssetAmount
92
92
  .mul(AMM_TO_QUOTE_PRECISION_RATIO)
93
- .mul(MARK_PRICE_PRECISION)
93
+ .mul(PRICE_PRECISION)
94
94
  .div(acquiredBaseReserve.abs());
95
95
 
96
96
  let amm: Parameters<typeof calculateAmmReservesAfterSwap>[0];
@@ -121,12 +121,12 @@ export function calculateTradeSlippage(
121
121
 
122
122
  const pctMaxSlippage = newPrice
123
123
  .sub(oldPrice)
124
- .mul(MARK_PRICE_PRECISION)
124
+ .mul(PRICE_PRECISION)
125
125
  .div(oldPrice)
126
126
  .abs();
127
127
  const pctAvgSlippage = entryPrice
128
128
  .sub(oldPrice)
129
- .mul(MARK_PRICE_PRECISION)
129
+ .mul(PRICE_PRECISION)
130
130
  .div(oldPrice)
131
131
  .abs();
132
132
 
@@ -147,7 +147,7 @@ export function calculateTradeSlippage(
147
147
  export function calculateTradeAcquiredAmounts(
148
148
  direction: PositionDirection,
149
149
  amount: BN,
150
- market: MarketAccount,
150
+ market: PerpMarketAccount,
151
151
  inputAssetType: AssetType = 'quote',
152
152
  oraclePriceData: OraclePriceData,
153
153
  useSpread = true
@@ -177,13 +177,13 @@ export function calculateTradeAcquiredAmounts(
177
177
 
178
178
  const acquiredBase = amm.baseAssetReserve.sub(newBaseAssetReserve);
179
179
  const acquiredQuote = amm.quoteAssetReserve.sub(newQuoteAssetReserve);
180
- const acquiredQuoteAssetamount = calculateQuoteAssetAmountSwapped(
180
+ const acquiredQuoteAssetAmount = calculateQuoteAssetAmountSwapped(
181
181
  acquiredQuote.abs(),
182
182
  amm.pegMultiplier,
183
183
  swapDirection
184
184
  );
185
185
 
186
- return [acquiredBase, acquiredQuote, acquiredQuoteAssetamount];
186
+ return [acquiredBase, acquiredQuote, acquiredQuoteAssetAmount];
187
187
  }
188
188
 
189
189
  /**
@@ -199,12 +199,12 @@ export function calculateTradeAcquiredAmounts(
199
199
  * [
200
200
  * direction => direction of trade required, PositionDirection
201
201
  * tradeSize => size of trade required, TODO-PRECISION
202
- * entryPrice => the entry price for the trade, MARK_PRICE_PRECISION
203
- * targetPrice => the target price MARK_PRICE_PRECISION
202
+ * entryPrice => the entry price for the trade, PRICE_PRECISION
203
+ * targetPrice => the target price PRICE_PRECISION
204
204
  * ]
205
205
  */
206
206
  export function calculateTargetPriceTrade(
207
- market: MarketAccount,
207
+ market: PerpMarketAccount,
208
208
  targetPrice: BN,
209
209
  pct: BN = MAXPCT,
210
210
  outputAssetType: AssetType = 'quote',
@@ -215,20 +215,20 @@ export function calculateTargetPriceTrade(
215
215
  assert(targetPrice.gt(ZERO));
216
216
  assert(pct.lte(MAXPCT) && pct.gt(ZERO));
217
217
 
218
- const markPriceBefore = calculateMarkPrice(market, oraclePriceData);
218
+ const reservePriceBefore = calculateReservePrice(market, oraclePriceData);
219
219
  const bidPriceBefore = calculateBidPrice(market, oraclePriceData);
220
220
  const askPriceBefore = calculateAskPrice(market, oraclePriceData);
221
221
 
222
222
  let direction;
223
- if (targetPrice.gt(markPriceBefore)) {
224
- const priceGap = targetPrice.sub(markPriceBefore);
223
+ if (targetPrice.gt(reservePriceBefore)) {
224
+ const priceGap = targetPrice.sub(reservePriceBefore);
225
225
  const priceGapScaled = priceGap.mul(pct).div(MAXPCT);
226
- targetPrice = markPriceBefore.add(priceGapScaled);
226
+ targetPrice = reservePriceBefore.add(priceGapScaled);
227
227
  direction = PositionDirection.LONG;
228
228
  } else {
229
- const priceGap = markPriceBefore.sub(targetPrice);
229
+ const priceGap = reservePriceBefore.sub(targetPrice);
230
230
  const priceGapScaled = priceGap.mul(pct).div(MAXPCT);
231
- targetPrice = markPriceBefore.sub(priceGapScaled);
231
+ targetPrice = reservePriceBefore.sub(priceGapScaled);
232
232
  direction = PositionDirection.SHORT;
233
233
  }
234
234
 
@@ -252,7 +252,7 @@ export function calculateTargetPriceTrade(
252
252
  }
253
253
 
254
254
  const invariant = market.amm.sqrtK.mul(market.amm.sqrtK);
255
- const k = invariant.mul(MARK_PRICE_PRECISION);
255
+ const k = invariant.mul(PRICE_PRECISION);
256
256
 
257
257
  let baseAssetReserveAfter;
258
258
  let quoteAssetReserveAfter;
@@ -265,21 +265,19 @@ export function calculateTargetPriceTrade(
265
265
  targetPrice.gt(bidPriceBefore)
266
266
  ) {
267
267
  // no trade, market is at target
268
- if (markPriceBefore.gt(targetPrice)) {
268
+ if (reservePriceBefore.gt(targetPrice)) {
269
269
  direction = PositionDirection.SHORT;
270
270
  } else {
271
271
  direction = PositionDirection.LONG;
272
272
  }
273
273
  tradeSize = ZERO;
274
274
  return [direction, tradeSize, targetPrice, targetPrice];
275
- } else if (markPriceBefore.gt(targetPrice)) {
275
+ } else if (reservePriceBefore.gt(targetPrice)) {
276
276
  // overestimate y2
277
277
  baseAssetReserveAfter = squareRootBN(
278
278
  k.div(targetPrice).mul(peg).div(PEG_PRECISION).sub(biasModifier)
279
279
  ).sub(new BN(1));
280
- quoteAssetReserveAfter = k
281
- .div(MARK_PRICE_PRECISION)
282
- .div(baseAssetReserveAfter);
280
+ quoteAssetReserveAfter = k.div(PRICE_PRECISION).div(baseAssetReserveAfter);
283
281
 
284
282
  markPriceAfter = calculatePrice(
285
283
  baseAssetReserveAfter,
@@ -293,14 +291,12 @@ export function calculateTargetPriceTrade(
293
291
  .div(PEG_PRECISION)
294
292
  .div(AMM_TO_QUOTE_PRECISION_RATIO);
295
293
  baseSize = baseAssetReserveAfter.sub(baseAssetReserveBefore);
296
- } else if (markPriceBefore.lt(targetPrice)) {
294
+ } else if (reservePriceBefore.lt(targetPrice)) {
297
295
  // underestimate y2
298
296
  baseAssetReserveAfter = squareRootBN(
299
297
  k.div(targetPrice).mul(peg).div(PEG_PRECISION).add(biasModifier)
300
298
  ).add(new BN(1));
301
- quoteAssetReserveAfter = k
302
- .div(MARK_PRICE_PRECISION)
303
- .div(baseAssetReserveAfter);
299
+ quoteAssetReserveAfter = k.div(PRICE_PRECISION).div(baseAssetReserveAfter);
304
300
 
305
301
  markPriceAfter = calculatePrice(
306
302
  baseAssetReserveAfter,
@@ -324,17 +320,17 @@ export function calculateTargetPriceTrade(
324
320
 
325
321
  let tp1 = targetPrice;
326
322
  let tp2 = markPriceAfter;
327
- let originalDiff = targetPrice.sub(markPriceBefore);
323
+ let originalDiff = targetPrice.sub(reservePriceBefore);
328
324
 
329
325
  if (direction == PositionDirection.SHORT) {
330
326
  tp1 = markPriceAfter;
331
327
  tp2 = targetPrice;
332
- originalDiff = markPriceBefore.sub(targetPrice);
328
+ originalDiff = reservePriceBefore.sub(targetPrice);
333
329
  }
334
330
 
335
331
  const entryPrice = tradeSize
336
332
  .mul(AMM_TO_QUOTE_PRECISION_RATIO)
337
- .mul(MARK_PRICE_PRECISION)
333
+ .mul(PRICE_PRECISION)
338
334
  .div(baseSize.abs());
339
335
 
340
336
  assert(tp1.sub(tp2).lte(originalDiff), 'Target Price Calculation incorrect');
@@ -2,7 +2,7 @@ import { parsePriceData } from '@pythnetwork/client';
2
2
  import { Connection, PublicKey } from '@solana/web3.js';
3
3
  import { OracleClient, OraclePriceData } from './types';
4
4
  import { BN } from '@project-serum/anchor';
5
- import { MARK_PRICE_PRECISION, TEN } from '../constants/numericConstants';
5
+ import { PRICE_PRECISION, TEN } from '../constants/numericConstants';
6
6
 
7
7
  export class PythClient implements OracleClient {
8
8
  private connection: Connection;
@@ -38,6 +38,6 @@ export function convertPythPrice(price: number, exponent: number): BN {
38
38
  exponent = Math.abs(exponent);
39
39
  const pythPrecision = TEN.pow(new BN(exponent).abs());
40
40
  return new BN(price * Math.pow(10, exponent))
41
- .mul(MARK_PRICE_PRECISION)
41
+ .mul(PRICE_PRECISION)
42
42
  .div(pythPrecision);
43
43
  }
@@ -1,10 +1,10 @@
1
1
  import { PublicKey } from '@solana/web3.js';
2
2
  import { OracleClient, OraclePriceData } from './types';
3
3
  import { BN } from '@project-serum/anchor';
4
- import { MARK_PRICE_PRECISION } from '../constants/numericConstants';
4
+ import { PRICE_PRECISION } from '../constants/numericConstants';
5
5
 
6
6
  export const QUOTE_ORACLE_PRICE_DATA: OraclePriceData = {
7
- price: MARK_PRICE_PRECISION,
7
+ price: PRICE_PRECISION,
8
8
  slot: new BN(0),
9
9
  confidence: new BN(1),
10
10
  hasSufficientNumberOfDataPoints: true,
@@ -1,7 +1,7 @@
1
1
  import { SwitchboardDecimal } from '@switchboard-xyz/switchboard-v2';
2
2
  import { Connection, Keypair, PublicKey } from '@solana/web3.js';
3
3
  import { BN, Program, Idl, AnchorProvider } from '@project-serum/anchor';
4
- import { MARK_PRICE_PRECISION, TEN } from '../constants/numericConstants';
4
+ import { PRICE_PRECISION, TEN } from '../constants/numericConstants';
5
5
  import { OracleClient, OraclePriceData } from './types';
6
6
  import { Wallet } from '../wallet';
7
7
  import switchboardV2Idl from '../idl/switchboard_v2.json';
@@ -74,6 +74,6 @@ function getSwitchboardProgram(connection: Connection): Program {
74
74
  function convertSwitchboardDecimal(switchboardDecimal: SwitchboardDecimal): BN {
75
75
  const switchboardPrecision = TEN.pow(new BN(switchboardDecimal.scale));
76
76
  return switchboardDecimal.mantissa
77
- .mul(MARK_PRICE_PRECISION)
77
+ .mul(PRICE_PRECISION)
78
78
  .div(switchboardPrecision);
79
79
  }
@@ -2,32 +2,40 @@ import { OptionalOrderParams, OrderTriggerCondition, OrderType } from './types';
2
2
  import { BN } from '@project-serum/anchor';
3
3
 
4
4
  export function getLimitOrderParams(
5
- params: Omit<OptionalOrderParams, 'orderType'> & { price: BN }
5
+ params: Omit<OptionalOrderParams, 'orderType' | 'marketType'> & { price: BN }
6
6
  ): OptionalOrderParams {
7
- return Object.assign({}, params, { orderType: OrderType.LIMIT });
7
+ return Object.assign({}, params, {
8
+ orderType: OrderType.LIMIT,
9
+ });
8
10
  }
9
11
 
10
12
  export function getTriggerMarketOrderParams(
11
- params: Omit<OptionalOrderParams, 'orderType'> & {
13
+ params: Omit<OptionalOrderParams, 'orderType' | 'marketType'> & {
12
14
  triggerCondition: OrderTriggerCondition;
13
15
  triggerPrice: BN;
14
16
  }
15
17
  ): OptionalOrderParams {
16
- return Object.assign({}, params, { orderType: OrderType.TRIGGER_MARKET });
18
+ return Object.assign({}, params, {
19
+ orderType: OrderType.TRIGGER_MARKET,
20
+ });
17
21
  }
18
22
 
19
23
  export function getTriggerLimitOrderParams(
20
- params: Omit<OptionalOrderParams, 'orderType'> & {
24
+ params: Omit<OptionalOrderParams, 'orderType' | 'marketType'> & {
21
25
  triggerCondition: OrderTriggerCondition;
22
26
  triggerPrice: BN;
23
27
  price: BN;
24
28
  }
25
29
  ): OptionalOrderParams {
26
- return Object.assign({}, params, { orderType: OrderType.TRIGGER_LIMIT });
30
+ return Object.assign({}, params, {
31
+ orderType: OrderType.TRIGGER_LIMIT,
32
+ });
27
33
  }
28
34
 
29
35
  export function getMarketOrderParams(
30
- params: Omit<OptionalOrderParams, 'orderType'>
36
+ params: Omit<OptionalOrderParams, 'orderType' | 'marketType'>
31
37
  ): OptionalOrderParams {
32
- return Object.assign({}, params, { orderType: OrderType.MARKET });
38
+ return Object.assign({}, params, {
39
+ orderType: OrderType.MARKET,
40
+ });
33
41
  }
@@ -0,0 +1,26 @@
1
+ import { PublicKey } from '@solana/web3.js';
2
+ import { SerumV3FulfillmentConfigAccount } from '../types';
3
+ import { DriftClient } from '../driftClient';
4
+
5
+ export class SerumFulfillmentConfigMap {
6
+ driftClient: DriftClient;
7
+ map = new Map<number, SerumV3FulfillmentConfigAccount>();
8
+
9
+ public constructor(driftClient: DriftClient) {
10
+ this.driftClient = driftClient;
11
+ }
12
+
13
+ public async add(
14
+ marketIndex: number,
15
+ serumMarketAddress: PublicKey
16
+ ): Promise<void> {
17
+ const account = await this.driftClient.getSerumV3FulfillmentConfig(
18
+ serumMarketAddress
19
+ );
20
+ this.map.set(marketIndex, account);
21
+ }
22
+
23
+ public get(marketIndex: number): SerumV3FulfillmentConfigAccount {
24
+ return this.map.get(marketIndex);
25
+ }
26
+ }
@@ -0,0 +1,99 @@
1
+ import { Connection, PublicKey } from '@solana/web3.js';
2
+ import { BulkAccountLoader } from '../accounts/bulkAccountLoader';
3
+ import { Market, Orderbook } from '@project-serum/serum';
4
+ import { SerumMarketSubscriberConfig } from './types';
5
+ import { BN } from '@project-serum/anchor';
6
+ import { PRICE_PRECISION } from '../constants/numericConstants';
7
+
8
+ export class SerumSubscriber {
9
+ connection: Connection;
10
+ programId: PublicKey;
11
+ marketAddress: PublicKey;
12
+ accountLoader: BulkAccountLoader;
13
+ market: Market;
14
+
15
+ subscribed: boolean;
16
+
17
+ asksAddress: PublicKey;
18
+ asks: Orderbook;
19
+ asksCallbackId: string;
20
+ lastAsksSlot: number;
21
+
22
+ bidsAddress: PublicKey;
23
+ bids: Orderbook;
24
+ bidsCallbackId: string;
25
+ lastBidsSlot: number;
26
+
27
+ public constructor(config: SerumMarketSubscriberConfig) {
28
+ this.connection = config.connection;
29
+ this.programId = config.programId;
30
+ this.marketAddress = config.marketAddress;
31
+ this.accountLoader = config.accountSubscription.accountLoader;
32
+ }
33
+
34
+ public async subscribe(): Promise<void> {
35
+ if (this.subscribed) {
36
+ return;
37
+ }
38
+
39
+ this.market = await Market.load(
40
+ this.connection,
41
+ this.marketAddress,
42
+ undefined,
43
+ this.programId
44
+ );
45
+
46
+ this.asksAddress = this.market.asksAddress;
47
+ this.asks = await this.market.loadAsks(this.connection);
48
+
49
+ this.asksCallbackId = this.accountLoader.addAccount(
50
+ this.asksAddress,
51
+ (buffer, slot) => {
52
+ this.lastAsksSlot = slot;
53
+ this.asks = Orderbook.decode(this.market, buffer);
54
+ }
55
+ );
56
+
57
+ this.bidsAddress = this.market.bidsAddress;
58
+ this.bids = await this.market.loadBids(this.connection);
59
+
60
+ this.bidsCallbackId = this.accountLoader.addAccount(
61
+ this.bidsAddress,
62
+ (buffer, slot) => {
63
+ this.lastBidsSlot = slot;
64
+ this.bids = Orderbook.decode(this.market, buffer);
65
+ }
66
+ );
67
+
68
+ this.subscribed = true;
69
+ }
70
+
71
+ public getBestBid(): BN | undefined {
72
+ const bestBid = this.bids.getL2(1)[0];
73
+ if (!bestBid) {
74
+ return undefined;
75
+ }
76
+
77
+ return new BN(bestBid[0] * PRICE_PRECISION.toNumber());
78
+ }
79
+
80
+ public getBestAsk(): BN | undefined {
81
+ const bestAsk = this.asks.getL2(1)[0];
82
+ if (!bestAsk) {
83
+ return undefined;
84
+ }
85
+
86
+ return new BN(bestAsk[0] * PRICE_PRECISION.toNumber());
87
+ }
88
+
89
+ public async unsubscribe(): Promise<void> {
90
+ if (!this.subscribed) {
91
+ return;
92
+ }
93
+
94
+ this.accountLoader.removeAccount(this.asksAddress, this.asksCallbackId);
95
+ this.accountLoader.removeAccount(this.bidsAddress, this.bidsCallbackId);
96
+
97
+ this.subscribed = false;
98
+ }
99
+ }
@@ -0,0 +1,13 @@
1
+ import { Connection, PublicKey } from '@solana/web3.js';
2
+ import { BulkAccountLoader } from '../accounts/bulkAccountLoader';
3
+
4
+ export type SerumMarketSubscriberConfig = {
5
+ connection: Connection;
6
+ programId: PublicKey;
7
+ marketAddress: PublicKey;
8
+ accountSubscription: {
9
+ // enables use to add web sockets in the future
10
+ type: 'polling';
11
+ accountLoader: BulkAccountLoader;
12
+ };
13
+ };
@@ -1,22 +1,32 @@
1
1
  import { Connection } from '@solana/web3.js';
2
+ import { EventEmitter } from 'events';
3
+ import StrictEventEmitter from 'strict-event-emitter-types/types/src';
2
4
 
3
5
  // eslint-disable-next-line @typescript-eslint/ban-types
4
6
  type SlotSubscriberConfig = {}; // for future customization
5
7
 
8
+ export interface SlotSubscriberEvents {
9
+ newSlot: (newSlot: number) => void;
10
+ }
11
+
6
12
  export class SlotSubscriber {
7
13
  currentSlot: number;
8
14
  subscriptionId: number;
15
+ eventEmitter: StrictEventEmitter<EventEmitter, SlotSubscriberEvents>;
9
16
 
10
17
  public constructor(
11
18
  private connection: Connection,
12
19
  _config?: SlotSubscriberConfig
13
- ) {}
20
+ ) {
21
+ this.eventEmitter = new EventEmitter();
22
+ }
14
23
 
15
24
  public async subscribe(): Promise<void> {
16
25
  this.currentSlot = await this.connection.getSlot('confirmed');
17
26
 
18
27
  this.subscriptionId = this.connection.onSlotChange((slotInfo) => {
19
28
  this.currentSlot = slotInfo.slot;
29
+ this.eventEmitter.emit('newSlot', slotInfo.slot);
20
30
  });
21
31
  }
22
32