@drift-labs/sdk 0.2.0-master.3 → 0.2.0-master.30

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 (208) hide show
  1. package/README.md +13 -13
  2. package/lib/accounts/bulkUserStatsSubscription.d.ts +7 -0
  3. package/lib/accounts/bulkUserStatsSubscription.js +21 -0
  4. package/lib/accounts/bulkUserSubscription.js +0 -1
  5. package/lib/accounts/fetch.d.ts +2 -1
  6. package/lib/accounts/fetch.js +9 -1
  7. package/lib/accounts/pollingClearingHouseAccountSubscriber.d.ts +16 -16
  8. package/lib/accounts/pollingClearingHouseAccountSubscriber.js +31 -28
  9. package/lib/accounts/pollingUserStatsAccountSubscriber.d.ts +27 -0
  10. package/lib/accounts/pollingUserStatsAccountSubscriber.js +113 -0
  11. package/lib/accounts/types.d.ts +22 -11
  12. package/lib/accounts/webSocketClearingHouseAccountSubscriber.d.ts +17 -17
  13. package/lib/accounts/webSocketClearingHouseAccountSubscriber.js +37 -35
  14. package/lib/accounts/webSocketUserStatsAccountSubsriber.d.ts +20 -0
  15. package/lib/accounts/webSocketUserStatsAccountSubsriber.js +47 -0
  16. package/lib/addresses/marketAddresses.d.ts +1 -3
  17. package/lib/addresses/pda.d.ts +10 -4
  18. package/lib/addresses/pda.js +51 -14
  19. package/lib/admin.d.ts +34 -22
  20. package/lib/admin.js +182 -73
  21. package/lib/clearingHouse.d.ts +120 -42
  22. package/lib/clearingHouse.js +1505 -254
  23. package/lib/clearingHouseConfig.d.ts +4 -4
  24. package/lib/clearingHouseUser.d.ts +50 -38
  25. package/lib/clearingHouseUser.js +410 -190
  26. package/lib/clearingHouseUserStats.d.ts +18 -0
  27. package/lib/clearingHouseUserStats.js +49 -0
  28. package/lib/clearingHouseUserStatsConfig.d.ts +14 -0
  29. package/lib/clearingHouseUserStatsConfig.js +2 -0
  30. package/lib/config.d.ts +7 -9
  31. package/lib/config.js +21 -21
  32. package/lib/constants/numericConstants.d.ts +18 -12
  33. package/lib/constants/numericConstants.js +28 -21
  34. package/lib/constants/perpMarkets.d.ts +18 -0
  35. package/lib/constants/{markets.js → perpMarkets.js} +7 -7
  36. package/lib/constants/spotMarkets.d.ts +19 -0
  37. package/lib/constants/spotMarkets.js +53 -0
  38. package/lib/dlob/DLOB.d.ts +73 -0
  39. package/lib/dlob/DLOB.js +553 -0
  40. package/lib/dlob/DLOBNode.d.ts +52 -0
  41. package/lib/dlob/DLOBNode.js +82 -0
  42. package/lib/dlob/NodeList.d.ts +26 -0
  43. package/lib/dlob/NodeList.js +138 -0
  44. package/lib/events/eventList.js +3 -0
  45. package/lib/events/eventSubscriber.d.ts +4 -2
  46. package/lib/events/eventSubscriber.js +16 -9
  47. package/lib/events/fetchLogs.d.ts +10 -1
  48. package/lib/events/fetchLogs.js +27 -7
  49. package/lib/events/pollingLogProvider.d.ts +2 -1
  50. package/lib/events/pollingLogProvider.js +6 -2
  51. package/lib/events/sort.js +8 -11
  52. package/lib/events/types.d.ts +7 -2
  53. package/lib/events/types.js +5 -0
  54. package/lib/examples/makeTradeExample.js +20 -8
  55. package/lib/factory/bigNum.d.ts +1 -0
  56. package/lib/factory/bigNum.js +34 -10
  57. package/lib/idl/clearing_house.json +4313 -1433
  58. package/lib/idl/{mock_usdc_faucet.json → token_faucet.json} +46 -23
  59. package/lib/index.d.ts +21 -6
  60. package/lib/index.js +25 -6
  61. package/lib/math/amm.d.ts +8 -5
  62. package/lib/math/amm.js +68 -46
  63. package/lib/math/auction.js +4 -1
  64. package/lib/math/conversion.js +1 -1
  65. package/lib/math/funding.d.ts +6 -6
  66. package/lib/math/funding.js +11 -10
  67. package/lib/math/insurance.d.ts +4 -0
  68. package/lib/math/insurance.js +27 -0
  69. package/lib/math/margin.d.ts +11 -0
  70. package/lib/math/margin.js +77 -0
  71. package/lib/math/market.d.ts +14 -9
  72. package/lib/math/market.js +69 -7
  73. package/lib/math/oracles.d.ts +4 -0
  74. package/lib/math/oracles.js +36 -8
  75. package/lib/math/orders.d.ts +6 -2
  76. package/lib/math/orders.js +78 -3
  77. package/lib/math/position.d.ts +21 -13
  78. package/lib/math/position.js +76 -36
  79. package/lib/math/repeg.js +14 -5
  80. package/lib/math/spotBalance.d.ts +22 -0
  81. package/lib/math/spotBalance.js +193 -0
  82. package/lib/math/spotMarket.d.ts +4 -0
  83. package/lib/math/spotMarket.js +8 -0
  84. package/lib/math/spotPosition.d.ts +6 -0
  85. package/lib/math/spotPosition.js +23 -0
  86. package/lib/math/trade.d.ts +10 -10
  87. package/lib/math/trade.js +22 -29
  88. package/lib/oracles/pythClient.js +1 -1
  89. package/lib/oracles/quoteAssetOracleClient.js +1 -1
  90. package/lib/oracles/switchboardClient.js +1 -1
  91. package/lib/orderParams.d.ts +14 -5
  92. package/lib/orderParams.js +12 -92
  93. package/lib/serum/serumSubscriber.d.ts +23 -0
  94. package/lib/serum/serumSubscriber.js +41 -0
  95. package/lib/serum/types.d.ts +11 -0
  96. package/lib/serum/types.js +2 -0
  97. package/lib/slot/SlotSubscriber.d.ts +7 -0
  98. package/lib/slot/SlotSubscriber.js +3 -0
  99. package/lib/{mockUSDCFaucet.d.ts → tokenFaucet.d.ts} +8 -5
  100. package/lib/{mockUSDCFaucet.js → tokenFaucet.js} +63 -51
  101. package/lib/tx/retryTxSender.d.ts +1 -1
  102. package/lib/tx/retryTxSender.js +13 -4
  103. package/lib/tx/types.d.ts +1 -1
  104. package/lib/tx/utils.js +1 -1
  105. package/lib/types.d.ts +474 -123
  106. package/lib/types.js +99 -5
  107. package/lib/userMap/userMap.d.ts +25 -0
  108. package/lib/userMap/userMap.js +73 -0
  109. package/lib/userMap/userStatsMap.d.ts +19 -0
  110. package/lib/userMap/userStatsMap.js +68 -0
  111. package/lib/util/computeUnits.js +1 -1
  112. package/lib/util/getTokenAddress.d.ts +2 -0
  113. package/lib/util/getTokenAddress.js +9 -0
  114. package/package.json +9 -5
  115. package/src/accounts/bulkUserStatsSubscription.ts +33 -0
  116. package/src/accounts/bulkUserSubscription.ts +0 -1
  117. package/src/accounts/fetch.ts +27 -2
  118. package/src/accounts/pollingClearingHouseAccountSubscriber.ts +46 -42
  119. package/src/accounts/pollingUserStatsAccountSubscriber.ts +172 -0
  120. package/src/accounts/types.ts +31 -11
  121. package/src/accounts/webSocketClearingHouseAccountSubscriber.ts +64 -59
  122. package/src/accounts/webSocketUserStatsAccountSubsriber.ts +80 -0
  123. package/src/addresses/marketAddresses.ts +1 -2
  124. package/src/addresses/pda.ts +88 -14
  125. package/src/admin.ts +333 -128
  126. package/src/assert/assert.js +9 -0
  127. package/src/clearingHouse.ts +2464 -458
  128. package/src/clearingHouseConfig.ts +4 -3
  129. package/src/clearingHouseUser.ts +747 -291
  130. package/src/clearingHouseUserStats.ts +75 -0
  131. package/src/clearingHouseUserStatsConfig.ts +18 -0
  132. package/src/config.ts +30 -31
  133. package/src/constants/numericConstants.ts +41 -25
  134. package/src/constants/{markets.ts → perpMarkets.ts} +10 -10
  135. package/src/constants/spotMarkets.ts +72 -0
  136. package/src/dlob/DLOB.ts +868 -0
  137. package/src/dlob/DLOBNode.ts +162 -0
  138. package/src/dlob/NodeList.ts +185 -0
  139. package/src/events/eventList.js +77 -0
  140. package/src/events/eventList.ts +3 -0
  141. package/src/events/eventSubscriber.ts +20 -12
  142. package/src/events/fetchLogs.ts +35 -8
  143. package/src/events/pollingLogProvider.ts +10 -2
  144. package/src/events/sort.ts +11 -15
  145. package/src/events/types.ts +16 -1
  146. package/src/examples/makeTradeExample.js +157 -0
  147. package/src/examples/makeTradeExample.ts +32 -14
  148. package/src/factory/bigNum.ts +42 -13
  149. package/src/idl/clearing_house.json +4313 -1433
  150. package/src/idl/{mock_usdc_faucet.json → token_faucet.json} +46 -23
  151. package/src/index.ts +21 -6
  152. package/src/math/amm.ts +136 -66
  153. package/src/math/auction.ts +5 -1
  154. package/src/math/conversion.ts +2 -2
  155. package/src/math/funding.ts +20 -18
  156. package/src/math/insurance.ts +35 -0
  157. package/src/math/margin.ts +127 -0
  158. package/src/math/market.ts +138 -12
  159. package/src/math/oracles.ts +63 -9
  160. package/src/math/orders.ts +138 -4
  161. package/src/math/position.ts +119 -58
  162. package/src/math/repeg.ts +16 -6
  163. package/src/math/spotBalance.ts +316 -0
  164. package/src/math/spotMarket.ts +9 -0
  165. package/src/math/spotPosition.ts +47 -0
  166. package/src/math/trade.ts +43 -49
  167. package/src/oracles/pythClient.ts +2 -2
  168. package/src/oracles/quoteAssetOracleClient.ts +2 -2
  169. package/src/oracles/switchboardClient.ts +2 -2
  170. package/src/orderParams.ts +24 -137
  171. package/src/serum/serumSubscriber.ts +80 -0
  172. package/src/serum/types.ts +13 -0
  173. package/src/slot/SlotSubscriber.ts +11 -1
  174. package/src/token/index.js +38 -0
  175. package/src/{mockUSDCFaucet.ts → tokenFaucet.ts} +82 -70
  176. package/src/tx/retryTxSender.ts +16 -5
  177. package/src/tx/types.js +2 -0
  178. package/src/tx/types.ts +2 -1
  179. package/src/tx/utils.js +17 -0
  180. package/src/tx/utils.ts +1 -1
  181. package/src/types.ts +477 -125
  182. package/src/userMap/userMap.ts +100 -0
  183. package/src/userMap/userStatsMap.ts +110 -0
  184. package/src/util/computeUnits.js +21 -11
  185. package/src/util/computeUnits.ts +1 -1
  186. package/src/util/getTokenAddress.js +9 -0
  187. package/src/util/getTokenAddress.ts +18 -0
  188. package/src/util/promiseTimeout.js +14 -0
  189. package/src/util/tps.js +27 -0
  190. package/tests/bn/test.ts +12 -3
  191. package/tests/dlob/helpers.ts +374 -0
  192. package/tests/dlob/test.ts +2865 -0
  193. package/lib/constants/banks.d.ts +0 -16
  194. package/lib/constants/banks.js +0 -34
  195. package/lib/constants/markets.d.ts +0 -19
  196. package/lib/math/bankBalance.d.ts +0 -9
  197. package/lib/math/bankBalance.js +0 -75
  198. package/lib/math/state.d.ts +0 -8
  199. package/lib/math/state.js +0 -15
  200. package/lib/orders.d.ts +0 -8
  201. package/lib/orders.js +0 -134
  202. package/src/constants/banks.ts +0 -43
  203. package/src/math/bankBalance.ts +0 -112
  204. package/src/math/state.ts +0 -14
  205. package/src/math/utils.js +0 -27
  206. package/src/math/utils.js.map +0 -1
  207. package/src/orders.ts +0 -244
  208. package/src/util/computeUnits.js.map +0 -1
@@ -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.balance.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.balance,
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, SwapDirection } 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,33 +73,25 @@ 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];
80
80
  }
81
- const [acquiredBase, acquiredQuote] = calculateTradeAcquiredAmounts(
82
- direction,
83
- amount,
84
- market,
85
- inputAssetType,
86
- oraclePriceData,
87
- useSpread
88
- );
89
-
90
- const swapDirection = isVariant(direction, 'long')
91
- ? SwapDirection.REMOVE
92
- : SwapDirection.ADD;
93
- const quoteAssetAmountAcquired = calculateQuoteAssetAmountSwapped(
94
- acquiredQuote.abs(),
95
- market.amm.pegMultiplier,
96
- swapDirection
97
- );
81
+ const [acquiredBaseReserve, acquiredQuoteReserve, acquiredQuoteAssetAmount] =
82
+ calculateTradeAcquiredAmounts(
83
+ direction,
84
+ amount,
85
+ market,
86
+ inputAssetType,
87
+ oraclePriceData,
88
+ useSpread
89
+ );
98
90
 
99
- const entryPrice = quoteAssetAmountAcquired
91
+ const entryPrice = acquiredQuoteAssetAmount
100
92
  .mul(AMM_TO_QUOTE_PRECISION_RATIO)
101
- .mul(MARK_PRICE_PRECISION)
102
- .div(acquiredBase.abs());
93
+ .mul(PRICE_PRECISION)
94
+ .div(acquiredBaseReserve.abs());
103
95
 
104
96
  let amm: Parameters<typeof calculateAmmReservesAfterSwap>[0];
105
97
  if (useSpread && market.amm.baseSpread > 0) {
@@ -116,8 +108,8 @@ export function calculateTradeSlippage(
116
108
  }
117
109
 
118
110
  const newPrice = calculatePrice(
119
- amm.baseAssetReserve.sub(acquiredBase),
120
- amm.quoteAssetReserve.sub(acquiredQuote),
111
+ amm.baseAssetReserve.sub(acquiredBaseReserve),
112
+ amm.quoteAssetReserve.sub(acquiredQuoteReserve),
121
113
  amm.pegMultiplier
122
114
  );
123
115
 
@@ -129,12 +121,12 @@ export function calculateTradeSlippage(
129
121
 
130
122
  const pctMaxSlippage = newPrice
131
123
  .sub(oldPrice)
132
- .mul(MARK_PRICE_PRECISION)
124
+ .mul(PRICE_PRECISION)
133
125
  .div(oldPrice)
134
126
  .abs();
135
127
  const pctAvgSlippage = entryPrice
136
128
  .sub(oldPrice)
137
- .mul(MARK_PRICE_PRECISION)
129
+ .mul(PRICE_PRECISION)
138
130
  .div(oldPrice)
139
131
  .abs();
140
132
 
@@ -155,13 +147,13 @@ export function calculateTradeSlippage(
155
147
  export function calculateTradeAcquiredAmounts(
156
148
  direction: PositionDirection,
157
149
  amount: BN,
158
- market: MarketAccount,
150
+ market: PerpMarketAccount,
159
151
  inputAssetType: AssetType = 'quote',
160
152
  oraclePriceData: OraclePriceData,
161
153
  useSpread = true
162
- ): [BN, BN] {
154
+ ): [BN, BN, BN] {
163
155
  if (amount.eq(ZERO)) {
164
- return [ZERO, ZERO];
156
+ return [ZERO, ZERO, ZERO];
165
157
  }
166
158
 
167
159
  const swapDirection = getSwapDirection(inputAssetType, direction);
@@ -185,7 +177,13 @@ export function calculateTradeAcquiredAmounts(
185
177
 
186
178
  const acquiredBase = amm.baseAssetReserve.sub(newBaseAssetReserve);
187
179
  const acquiredQuote = amm.quoteAssetReserve.sub(newQuoteAssetReserve);
188
- return [acquiredBase, acquiredQuote];
180
+ const acquiredQuoteAssetAmount = calculateQuoteAssetAmountSwapped(
181
+ acquiredQuote.abs(),
182
+ amm.pegMultiplier,
183
+ swapDirection
184
+ );
185
+
186
+ return [acquiredBase, acquiredQuote, acquiredQuoteAssetAmount];
189
187
  }
190
188
 
191
189
  /**
@@ -201,12 +199,12 @@ export function calculateTradeAcquiredAmounts(
201
199
  * [
202
200
  * direction => direction of trade required, PositionDirection
203
201
  * tradeSize => size of trade required, TODO-PRECISION
204
- * entryPrice => the entry price for the trade, MARK_PRICE_PRECISION
205
- * targetPrice => the target price MARK_PRICE_PRECISION
202
+ * entryPrice => the entry price for the trade, PRICE_PRECISION
203
+ * targetPrice => the target price PRICE_PRECISION
206
204
  * ]
207
205
  */
208
206
  export function calculateTargetPriceTrade(
209
- market: MarketAccount,
207
+ market: PerpMarketAccount,
210
208
  targetPrice: BN,
211
209
  pct: BN = MAXPCT,
212
210
  outputAssetType: AssetType = 'quote',
@@ -217,7 +215,7 @@ export function calculateTargetPriceTrade(
217
215
  assert(targetPrice.gt(ZERO));
218
216
  assert(pct.lte(MAXPCT) && pct.gt(ZERO));
219
217
 
220
- const markPriceBefore = calculateMarkPrice(market, oraclePriceData);
218
+ const markPriceBefore = calculateReservePrice(market, oraclePriceData);
221
219
  const bidPriceBefore = calculateBidPrice(market, oraclePriceData);
222
220
  const askPriceBefore = calculateAskPrice(market, oraclePriceData);
223
221
 
@@ -254,7 +252,7 @@ export function calculateTargetPriceTrade(
254
252
  }
255
253
 
256
254
  const invariant = market.amm.sqrtK.mul(market.amm.sqrtK);
257
- const k = invariant.mul(MARK_PRICE_PRECISION);
255
+ const k = invariant.mul(PRICE_PRECISION);
258
256
 
259
257
  let baseAssetReserveAfter;
260
258
  let quoteAssetReserveAfter;
@@ -279,9 +277,7 @@ export function calculateTargetPriceTrade(
279
277
  baseAssetReserveAfter = squareRootBN(
280
278
  k.div(targetPrice).mul(peg).div(PEG_PRECISION).sub(biasModifier)
281
279
  ).sub(new BN(1));
282
- quoteAssetReserveAfter = k
283
- .div(MARK_PRICE_PRECISION)
284
- .div(baseAssetReserveAfter);
280
+ quoteAssetReserveAfter = k.div(PRICE_PRECISION).div(baseAssetReserveAfter);
285
281
 
286
282
  markPriceAfter = calculatePrice(
287
283
  baseAssetReserveAfter,
@@ -300,9 +296,7 @@ export function calculateTargetPriceTrade(
300
296
  baseAssetReserveAfter = squareRootBN(
301
297
  k.div(targetPrice).mul(peg).div(PEG_PRECISION).add(biasModifier)
302
298
  ).add(new BN(1));
303
- quoteAssetReserveAfter = k
304
- .div(MARK_PRICE_PRECISION)
305
- .div(baseAssetReserveAfter);
299
+ quoteAssetReserveAfter = k.div(PRICE_PRECISION).div(baseAssetReserveAfter);
306
300
 
307
301
  markPriceAfter = calculatePrice(
308
302
  baseAssetReserveAfter,
@@ -336,7 +330,7 @@ export function calculateTargetPriceTrade(
336
330
 
337
331
  const entryPrice = tradeSize
338
332
  .mul(AMM_TO_QUOTE_PRECISION_RATIO)
339
- .mul(MARK_PRICE_PRECISION)
333
+ .mul(PRICE_PRECISION)
340
334
  .div(baseSize.abs());
341
335
 
342
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
  }
@@ -1,154 +1,41 @@
1
- import {
2
- OrderParams,
3
- OrderTriggerCondition,
4
- OrderType,
5
- PositionDirection,
6
- } from './types';
1
+ import { OptionalOrderParams, OrderTriggerCondition, OrderType } from './types';
7
2
  import { BN } from '@project-serum/anchor';
8
- import { ZERO } from './constants/numericConstants';
9
3
 
10
4
  export function getLimitOrderParams(
11
- marketIndex: BN,
12
- direction: PositionDirection,
13
- baseAssetAmount: BN,
14
- price: BN,
15
- reduceOnly: boolean,
16
- discountToken = false,
17
- referrer = false,
18
- userOrderId = 0,
19
- postOnly = false,
20
- oraclePriceOffset = ZERO,
21
- immediateOrCancel = false
22
- ): OrderParams {
23
- return {
5
+ params: Omit<OptionalOrderParams, 'orderType' | 'marketType'> & { price: BN }
6
+ ): OptionalOrderParams {
7
+ return Object.assign({}, params, {
24
8
  orderType: OrderType.LIMIT,
25
- userOrderId,
26
- marketIndex,
27
- direction,
28
- quoteAssetAmount: ZERO,
29
- baseAssetAmount,
30
- price,
31
- reduceOnly,
32
- postOnly,
33
- immediateOrCancel,
34
- positionLimit: ZERO,
35
- padding0: true,
36
- padding1: ZERO,
37
- optionalAccounts: {
38
- discountToken,
39
- referrer,
40
- },
41
- triggerCondition: OrderTriggerCondition.ABOVE,
42
- triggerPrice: ZERO,
43
- oraclePriceOffset,
44
- };
9
+ });
45
10
  }
46
11
 
47
12
  export function getTriggerMarketOrderParams(
48
- marketIndex: BN,
49
- direction: PositionDirection,
50
- baseAssetAmount: BN,
51
- triggerPrice: BN,
52
- triggerCondition: OrderTriggerCondition,
53
- reduceOnly: boolean,
54
- discountToken = false,
55
- referrer = false,
56
- userOrderId = 0
57
- ): OrderParams {
58
- return {
13
+ params: Omit<OptionalOrderParams, 'orderType' | 'marketType'> & {
14
+ triggerCondition: OrderTriggerCondition;
15
+ triggerPrice: BN;
16
+ }
17
+ ): OptionalOrderParams {
18
+ return Object.assign({}, params, {
59
19
  orderType: OrderType.TRIGGER_MARKET,
60
- userOrderId,
61
- marketIndex,
62
- direction,
63
- quoteAssetAmount: ZERO,
64
- baseAssetAmount,
65
- price: ZERO,
66
- reduceOnly,
67
- postOnly: false,
68
- immediateOrCancel: false,
69
- positionLimit: ZERO,
70
- padding0: true,
71
- padding1: ZERO,
72
- optionalAccounts: {
73
- discountToken,
74
- referrer,
75
- },
76
- triggerCondition,
77
- triggerPrice,
78
- oraclePriceOffset: ZERO,
79
- };
20
+ });
80
21
  }
81
22
 
82
23
  export function getTriggerLimitOrderParams(
83
- marketIndex: BN,
84
- direction: PositionDirection,
85
- baseAssetAmount: BN,
86
- price: BN,
87
- triggerPrice: BN,
88
- triggerCondition: OrderTriggerCondition,
89
- reduceOnly: boolean,
90
- discountToken = false,
91
- referrer = false,
92
- userOrderId = 0
93
- ): OrderParams {
94
- return {
24
+ params: Omit<OptionalOrderParams, 'orderType' | 'marketType'> & {
25
+ triggerCondition: OrderTriggerCondition;
26
+ triggerPrice: BN;
27
+ price: BN;
28
+ }
29
+ ): OptionalOrderParams {
30
+ return Object.assign({}, params, {
95
31
  orderType: OrderType.TRIGGER_LIMIT,
96
- userOrderId,
97
- marketIndex,
98
- direction,
99
- quoteAssetAmount: ZERO,
100
- baseAssetAmount,
101
- price,
102
- reduceOnly,
103
- postOnly: false,
104
- immediateOrCancel: false,
105
- positionLimit: ZERO,
106
- padding0: true,
107
- padding1: ZERO,
108
- optionalAccounts: {
109
- discountToken,
110
- referrer,
111
- },
112
- triggerCondition,
113
- triggerPrice,
114
- oraclePriceOffset: ZERO,
115
- };
32
+ });
116
33
  }
117
34
 
118
35
  export function getMarketOrderParams(
119
- marketIndex: BN,
120
- direction: PositionDirection,
121
- quoteAssetAmount: BN,
122
- baseAssetAmount: BN,
123
- reduceOnly: boolean,
124
- price = ZERO,
125
- discountToken = false,
126
- referrer = false
127
- ): OrderParams {
128
- if (baseAssetAmount.eq(ZERO) && quoteAssetAmount.eq(ZERO)) {
129
- throw Error('baseAssetAmount or quoteAssetAmount must be zero');
130
- }
131
-
132
- return {
36
+ params: Omit<OptionalOrderParams, 'orderType' | 'marketType'>
37
+ ): OptionalOrderParams {
38
+ return Object.assign({}, params, {
133
39
  orderType: OrderType.MARKET,
134
- userOrderId: 0,
135
- marketIndex,
136
- direction,
137
- quoteAssetAmount,
138
- baseAssetAmount,
139
- price,
140
- reduceOnly,
141
- postOnly: false,
142
- immediateOrCancel: false,
143
- positionLimit: ZERO,
144
- padding0: true,
145
- padding1: ZERO,
146
- optionalAccounts: {
147
- discountToken,
148
- referrer,
149
- },
150
- triggerCondition: OrderTriggerCondition.ABOVE,
151
- triggerPrice: ZERO,
152
- oraclePriceOffset: ZERO,
153
- };
40
+ });
154
41
  }
@@ -0,0 +1,80 @@
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
+
6
+ export class SerumSubscriber {
7
+ connection: Connection;
8
+ programId: PublicKey;
9
+ marketAddress: PublicKey;
10
+ accountLoader: BulkAccountLoader;
11
+ market: Market;
12
+
13
+ subscribed: boolean;
14
+
15
+ asksAddress: PublicKey;
16
+ asks: Orderbook;
17
+ asksCallbackId: string;
18
+ lastAsksSlot: number;
19
+
20
+ bidsAddress: PublicKey;
21
+ bids: Orderbook;
22
+ bidsCallbackId: string;
23
+ lastBidsSlot: number;
24
+
25
+ public constructor(config: SerumMarketSubscriberConfig) {
26
+ this.connection = config.connection;
27
+ this.programId = config.programId;
28
+ this.marketAddress = config.marketAddress;
29
+ this.accountLoader = config.accountSubscription.accountLoader;
30
+ }
31
+
32
+ public async subscribe(): Promise<void> {
33
+ if (this.subscribed) {
34
+ return;
35
+ }
36
+
37
+ this.market = await Market.load(
38
+ this.connection,
39
+ this.marketAddress,
40
+ undefined,
41
+ this.programId
42
+ );
43
+
44
+ this.asksAddress = this.market.asksAddress;
45
+ this.asks = await this.market.loadAsks(this.connection);
46
+
47
+ this.asksCallbackId = this.accountLoader.addAccount(
48
+ this.asksAddress,
49
+ (buffer, slot) => {
50
+ this.lastAsksSlot = slot;
51
+ this.asks = Orderbook.decode(this.market, buffer);
52
+ console.log(this.asks.getL2(3));
53
+ }
54
+ );
55
+
56
+ this.bidsAddress = this.market.bidsAddress;
57
+ this.bids = await this.market.loadBids(this.connection);
58
+
59
+ this.bidsCallbackId = this.accountLoader.addAccount(
60
+ this.bidsAddress,
61
+ (buffer, slot) => {
62
+ this.lastBidsSlot = slot;
63
+ this.bids = Orderbook.decode(this.market, buffer);
64
+ }
65
+ );
66
+
67
+ this.subscribed = true;
68
+ }
69
+
70
+ public async unsubscribe(): Promise<void> {
71
+ if (!this.subscribed) {
72
+ return;
73
+ }
74
+
75
+ this.accountLoader.removeAccount(this.asksAddress, this.asksCallbackId);
76
+ this.accountLoader.removeAccount(this.bidsAddress, this.bidsCallbackId);
77
+
78
+ this.subscribed = false;
79
+ }
80
+ }
@@ -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
 
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseTokenAccount = void 0;
4
+ const spl_token_1 = require("@solana/spl-token");
5
+ const web3_js_1 = require("@solana/web3.js");
6
+ function parseTokenAccount(data) {
7
+ const accountInfo = spl_token_1.AccountLayout.decode(data);
8
+ accountInfo.mint = new web3_js_1.PublicKey(accountInfo.mint);
9
+ accountInfo.owner = new web3_js_1.PublicKey(accountInfo.owner);
10
+ accountInfo.amount = spl_token_1.u64.fromBuffer(accountInfo.amount);
11
+ if (accountInfo.delegateOption === 0) {
12
+ accountInfo.delegate = null;
13
+ // eslint-disable-next-line new-cap
14
+ accountInfo.delegatedAmount = new spl_token_1.u64(0);
15
+ }
16
+ else {
17
+ accountInfo.delegate = new web3_js_1.PublicKey(accountInfo.delegate);
18
+ accountInfo.delegatedAmount = spl_token_1.u64.fromBuffer(accountInfo.delegatedAmount);
19
+ }
20
+ accountInfo.isInitialized = accountInfo.state !== 0;
21
+ accountInfo.isFrozen = accountInfo.state === 2;
22
+ if (accountInfo.isNativeOption === 1) {
23
+ accountInfo.rentExemptReserve = spl_token_1.u64.fromBuffer(accountInfo.isNative);
24
+ accountInfo.isNative = true;
25
+ }
26
+ else {
27
+ accountInfo.rentExemptReserve = null;
28
+ accountInfo.isNative = false;
29
+ }
30
+ if (accountInfo.closeAuthorityOption === 0) {
31
+ accountInfo.closeAuthority = null;
32
+ }
33
+ else {
34
+ accountInfo.closeAuthority = new web3_js_1.PublicKey(accountInfo.closeAuthority);
35
+ }
36
+ return accountInfo;
37
+ }
38
+ exports.parseTokenAccount = parseTokenAccount;