@drift-labs/common 1.0.0

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 (400) hide show
  1. package/lib/Config.d.ts +26 -0
  2. package/lib/Config.js +29 -0
  3. package/lib/Config.js.map +1 -0
  4. package/lib/EnvironmentConstants.d.ts +40 -0
  5. package/lib/EnvironmentConstants.js +64 -0
  6. package/lib/EnvironmentConstants.js.map +1 -0
  7. package/lib/actions/actionHelpers/accountDeletionHelpers.d.ts +16 -0
  8. package/lib/actions/actionHelpers/accountDeletionHelpers.js +151 -0
  9. package/lib/actions/actionHelpers/accountDeletionHelpers.js.map +1 -0
  10. package/lib/actions/actionHelpers/actionHelpers.d.ts +13 -0
  11. package/lib/actions/actionHelpers/actionHelpers.js +8 -0
  12. package/lib/actions/actionHelpers/actionHelpers.js.map +1 -0
  13. package/lib/chartConstants.d.ts +2 -0
  14. package/lib/chartConstants.js +14 -0
  15. package/lib/chartConstants.js.map +1 -0
  16. package/lib/clients/candleClient.d.ts +74 -0
  17. package/lib/clients/candleClient.js +364 -0
  18. package/lib/clients/candleClient.js.map +1 -0
  19. package/lib/clients/dataApiWsClient.d.ts +33 -0
  20. package/lib/clients/dataApiWsClient.js +118 -0
  21. package/lib/clients/dataApiWsClient.js.map +1 -0
  22. package/lib/clients/index.d.ts +1 -0
  23. package/lib/clients/index.js +19 -0
  24. package/lib/clients/index.js.map +1 -0
  25. package/lib/clients/marketDataFeed.d.ts +42 -0
  26. package/lib/clients/marketDataFeed.js +422 -0
  27. package/lib/clients/marketDataFeed.js.map +1 -0
  28. package/lib/clients/redisClient.d.ts +89 -0
  29. package/lib/clients/redisClient.js +647 -0
  30. package/lib/clients/redisClient.js.map +1 -0
  31. package/lib/clients/swiftClient.d.ts +57 -0
  32. package/lib/clients/swiftClient.js +289 -0
  33. package/lib/clients/swiftClient.js.map +1 -0
  34. package/lib/clients/tvFeed.d.ts +63 -0
  35. package/lib/clients/tvFeed.js +351 -0
  36. package/lib/clients/tvFeed.js.map +1 -0
  37. package/lib/common-ui-utils/commonUiUtils.d.ts +211 -0
  38. package/lib/common-ui-utils/commonUiUtils.js +624 -0
  39. package/lib/common-ui-utils/commonUiUtils.js.map +1 -0
  40. package/lib/common-ui-utils/index.d.ts +6 -0
  41. package/lib/common-ui-utils/index.js +23 -0
  42. package/lib/common-ui-utils/index.js.map +1 -0
  43. package/lib/common-ui-utils/market.d.ts +27 -0
  44. package/lib/common-ui-utils/market.js +80 -0
  45. package/lib/common-ui-utils/market.js.map +1 -0
  46. package/lib/common-ui-utils/order.d.ts +11 -0
  47. package/lib/common-ui-utils/order.js +161 -0
  48. package/lib/common-ui-utils/order.js.map +1 -0
  49. package/lib/common-ui-utils/settings/settings.d.ts +51 -0
  50. package/lib/common-ui-utils/settings/settings.js +84 -0
  51. package/lib/common-ui-utils/settings/settings.js.map +1 -0
  52. package/lib/common-ui-utils/trading.d.ts +56 -0
  53. package/lib/common-ui-utils/trading.js +200 -0
  54. package/lib/common-ui-utils/trading.js.map +1 -0
  55. package/lib/common-ui-utils/user.d.ts +13 -0
  56. package/lib/common-ui-utils/user.js +124 -0
  57. package/lib/common-ui-utils/user.js.map +1 -0
  58. package/lib/constants/autogenerated/driftErrors.json +1787 -0
  59. package/lib/constants/autogenerated/jup-v4-error-codes.json +67 -0
  60. package/lib/constants/autogenerated/jup-v6-error-codes.json +115 -0
  61. package/lib/constants/dev.d.ts +15 -0
  62. package/lib/constants/dev.js +19 -0
  63. package/lib/constants/dev.js.map +1 -0
  64. package/lib/constants/geoblockList.d.ts +4 -0
  65. package/lib/constants/geoblockList.js +32 -0
  66. package/lib/constants/geoblockList.js.map +1 -0
  67. package/lib/constants/index.d.ts +9 -0
  68. package/lib/constants/index.js +26 -0
  69. package/lib/constants/index.js.map +1 -0
  70. package/lib/constants/markets.d.ts +1 -0
  71. package/lib/constants/markets.js +5 -0
  72. package/lib/constants/markets.js.map +1 -0
  73. package/lib/constants/misc.d.ts +23 -0
  74. package/lib/constants/misc.js +27 -0
  75. package/lib/constants/misc.js.map +1 -0
  76. package/lib/constants/orders.d.ts +12 -0
  77. package/lib/constants/orders.js +79 -0
  78. package/lib/constants/orders.js.map +1 -0
  79. package/lib/constants/pools.d.ts +5 -0
  80. package/lib/constants/pools.js +9 -0
  81. package/lib/constants/pools.js.map +1 -0
  82. package/lib/constants/predictionMarket.d.ts +3 -0
  83. package/lib/constants/predictionMarket.js +7 -0
  84. package/lib/constants/predictionMarket.js.map +1 -0
  85. package/lib/constants/superstake.d.ts +22 -0
  86. package/lib/constants/superstake.js +45 -0
  87. package/lib/constants/superstake.js.map +1 -0
  88. package/lib/constants/trade.d.ts +2 -0
  89. package/lib/constants/trade.js +9 -0
  90. package/lib/constants/trade.js.map +1 -0
  91. package/lib/drift/Drift/clients/AuthorityDrift/DriftL2OrderbookManager.d.ts +68 -0
  92. package/lib/drift/Drift/clients/AuthorityDrift/DriftL2OrderbookManager.js +146 -0
  93. package/lib/drift/Drift/clients/AuthorityDrift/DriftL2OrderbookManager.js.map +1 -0
  94. package/lib/drift/Drift/clients/AuthorityDrift/DriftOperations/index.d.ts +204 -0
  95. package/lib/drift/Drift/clients/AuthorityDrift/DriftOperations/index.js +530 -0
  96. package/lib/drift/Drift/clients/AuthorityDrift/DriftOperations/index.js.map +1 -0
  97. package/lib/drift/Drift/clients/AuthorityDrift/DriftOperations/types.d.ts +90 -0
  98. package/lib/drift/Drift/clients/AuthorityDrift/DriftOperations/types.js +3 -0
  99. package/lib/drift/Drift/clients/AuthorityDrift/DriftOperations/types.js.map +1 -0
  100. package/lib/drift/Drift/clients/AuthorityDrift/SubscriptionManager.d.ts +139 -0
  101. package/lib/drift/Drift/clients/AuthorityDrift/SubscriptionManager.js +287 -0
  102. package/lib/drift/Drift/clients/AuthorityDrift/SubscriptionManager.js.map +1 -0
  103. package/lib/drift/Drift/clients/AuthorityDrift/index.d.ts +242 -0
  104. package/lib/drift/Drift/clients/AuthorityDrift/index.js +503 -0
  105. package/lib/drift/Drift/clients/AuthorityDrift/index.js.map +1 -0
  106. package/lib/drift/Drift/clients/CentralServerDrift.d.ts +91 -0
  107. package/lib/drift/Drift/clients/CentralServerDrift.js +326 -0
  108. package/lib/drift/Drift/clients/CentralServerDrift.js.map +1 -0
  109. package/lib/drift/Drift/clients/index.d.ts +3 -0
  110. package/lib/drift/Drift/clients/index.js +20 -0
  111. package/lib/drift/Drift/clients/index.js.map +1 -0
  112. package/lib/drift/Drift/constants/blockchain.d.ts +24 -0
  113. package/lib/drift/Drift/constants/blockchain.js +32 -0
  114. package/lib/drift/Drift/constants/blockchain.js.map +1 -0
  115. package/lib/drift/Drift/constants/errors.d.ts +6 -0
  116. package/lib/drift/Drift/constants/errors.js +14 -0
  117. package/lib/drift/Drift/constants/errors.js.map +1 -0
  118. package/lib/drift/Drift/constants/index.d.ts +3 -0
  119. package/lib/drift/Drift/constants/index.js +20 -0
  120. package/lib/drift/Drift/constants/index.js.map +1 -0
  121. package/lib/drift/Drift/constants/orderbook.d.ts +7 -0
  122. package/lib/drift/Drift/constants/orderbook.js +10 -0
  123. package/lib/drift/Drift/constants/orderbook.js.map +1 -0
  124. package/lib/drift/Drift/data/PollingDlob.d.ts +154 -0
  125. package/lib/drift/Drift/data/PollingDlob.js +387 -0
  126. package/lib/drift/Drift/data/PollingDlob.js.map +1 -0
  127. package/lib/drift/Drift/data/index.d.ts +1 -0
  128. package/lib/drift/Drift/data/index.js +18 -0
  129. package/lib/drift/Drift/data/index.js.map +1 -0
  130. package/lib/drift/Drift/index.d.ts +4 -0
  131. package/lib/drift/Drift/index.js +21 -0
  132. package/lib/drift/Drift/index.js.map +1 -0
  133. package/lib/drift/Drift/stores/MarkPriceCache.d.ts +27 -0
  134. package/lib/drift/Drift/stores/MarkPriceCache.js +59 -0
  135. package/lib/drift/Drift/stores/MarkPriceCache.js.map +1 -0
  136. package/lib/drift/Drift/stores/OraclePriceCache.d.ts +21 -0
  137. package/lib/drift/Drift/stores/OraclePriceCache.js +57 -0
  138. package/lib/drift/Drift/stores/OraclePriceCache.js.map +1 -0
  139. package/lib/drift/Drift/stores/UserAccountCache.d.ts +49 -0
  140. package/lib/drift/Drift/stores/UserAccountCache.js +107 -0
  141. package/lib/drift/Drift/stores/UserAccountCache.js.map +1 -0
  142. package/lib/drift/Drift/stores/index.d.ts +3 -0
  143. package/lib/drift/Drift/stores/index.js +20 -0
  144. package/lib/drift/Drift/stores/index.js.map +1 -0
  145. package/lib/drift/base/actions/index.d.ts +4 -0
  146. package/lib/drift/base/actions/index.js +21 -0
  147. package/lib/drift/base/actions/index.js.map +1 -0
  148. package/lib/drift/base/actions/perp/index.d.ts +2 -0
  149. package/lib/drift/base/actions/perp/index.js +19 -0
  150. package/lib/drift/base/actions/perp/index.js.map +1 -0
  151. package/lib/drift/base/actions/perp/settleFunding.d.ts +25 -0
  152. package/lib/drift/base/actions/perp/settleFunding.js +41 -0
  153. package/lib/drift/base/actions/perp/settleFunding.js.map +1 -0
  154. package/lib/drift/base/actions/perp/settlePnl.d.ts +35 -0
  155. package/lib/drift/base/actions/perp/settlePnl.js +44 -0
  156. package/lib/drift/base/actions/perp/settlePnl.js.map +1 -0
  157. package/lib/drift/base/actions/spot/borrow.d.ts +1 -0
  158. package/lib/drift/base/actions/spot/borrow.js +8 -0
  159. package/lib/drift/base/actions/spot/borrow.js.map +1 -0
  160. package/lib/drift/base/actions/spot/deposit.d.ts +40 -0
  161. package/lib/drift/base/actions/spot/deposit.js +82 -0
  162. package/lib/drift/base/actions/spot/deposit.js.map +1 -0
  163. package/lib/drift/base/actions/spot/index.d.ts +3 -0
  164. package/lib/drift/base/actions/spot/index.js +20 -0
  165. package/lib/drift/base/actions/spot/index.js.map +1 -0
  166. package/lib/drift/base/actions/spot/withdraw.d.ts +16 -0
  167. package/lib/drift/base/actions/spot/withdraw.js +39 -0
  168. package/lib/drift/base/actions/spot/withdraw.js.map +1 -0
  169. package/lib/drift/base/actions/trade/cancelOrder.d.ts +47 -0
  170. package/lib/drift/base/actions/trade/cancelOrder.js +55 -0
  171. package/lib/drift/base/actions/trade/cancelOrder.js.map +1 -0
  172. package/lib/drift/base/actions/trade/editOrder.d.ts +55 -0
  173. package/lib/drift/base/actions/trade/editOrder.js +35 -0
  174. package/lib/drift/base/actions/trade/editOrder.js.map +1 -0
  175. package/lib/drift/base/actions/trade/index.d.ts +4 -0
  176. package/lib/drift/base/actions/trade/index.js +21 -0
  177. package/lib/drift/base/actions/trade/index.js.map +1 -0
  178. package/lib/drift/base/actions/trade/openPerpOrder/index.d.ts +3 -0
  179. package/lib/drift/base/actions/trade/openPerpOrder/index.js +20 -0
  180. package/lib/drift/base/actions/trade/openPerpOrder/index.js.map +1 -0
  181. package/lib/drift/base/actions/trade/openPerpOrder/openPerpMarketOrder/index.d.ts +84 -0
  182. package/lib/drift/base/actions/trade/openPerpOrder/openPerpMarketOrder/index.js +293 -0
  183. package/lib/drift/base/actions/trade/openPerpOrder/openPerpMarketOrder/index.js.map +1 -0
  184. package/lib/drift/base/actions/trade/openPerpOrder/openPerpNonMarketOrder/index.d.ts +19 -0
  185. package/lib/drift/base/actions/trade/openPerpOrder/openPerpNonMarketOrder/index.js +161 -0
  186. package/lib/drift/base/actions/trade/openPerpOrder/openPerpNonMarketOrder/index.js.map +1 -0
  187. package/lib/drift/base/actions/trade/openPerpOrder/openSwiftOrder/index.d.ts +166 -0
  188. package/lib/drift/base/actions/trade/openPerpOrder/openSwiftOrder/index.js +156 -0
  189. package/lib/drift/base/actions/trade/openPerpOrder/openSwiftOrder/index.js.map +1 -0
  190. package/lib/drift/base/actions/trade/swap.d.ts +62 -0
  191. package/lib/drift/base/actions/trade/swap.js +60 -0
  192. package/lib/drift/base/actions/trade/swap.js.map +1 -0
  193. package/lib/drift/base/actions/user/create.d.ts +75 -0
  194. package/lib/drift/base/actions/user/create.js +104 -0
  195. package/lib/drift/base/actions/user/create.js.map +1 -0
  196. package/lib/drift/base/actions/user/delete.d.ts +47 -0
  197. package/lib/drift/base/actions/user/delete.js +39 -0
  198. package/lib/drift/base/actions/user/delete.js.map +1 -0
  199. package/lib/drift/base/actions/user/index.d.ts +1 -0
  200. package/lib/drift/base/actions/user/index.js +18 -0
  201. package/lib/drift/base/actions/user/index.js.map +1 -0
  202. package/lib/drift/base/constants/accountNames.d.ts +1 -0
  203. package/lib/drift/base/constants/accountNames.js +13 -0
  204. package/lib/drift/base/constants/accountNames.js.map +1 -0
  205. package/lib/drift/base/details/index.d.ts +2 -0
  206. package/lib/drift/base/details/index.js +19 -0
  207. package/lib/drift/base/details/index.js.map +1 -0
  208. package/lib/drift/base/details/market/funding.d.ts +9 -0
  209. package/lib/drift/base/details/market/funding.js +50 -0
  210. package/lib/drift/base/details/market/funding.js.map +1 -0
  211. package/lib/drift/base/details/market/index.d.ts +2 -0
  212. package/lib/drift/base/details/market/index.js +19 -0
  213. package/lib/drift/base/details/market/index.js.map +1 -0
  214. package/lib/drift/base/details/market/openInterest.d.ts +5 -0
  215. package/lib/drift/base/details/market/openInterest.js +12 -0
  216. package/lib/drift/base/details/market/openInterest.js.map +1 -0
  217. package/lib/drift/base/details/user/balances.d.ts +40 -0
  218. package/lib/drift/base/details/user/balances.js +39 -0
  219. package/lib/drift/base/details/user/balances.js.map +1 -0
  220. package/lib/drift/base/details/user/index.d.ts +4 -0
  221. package/lib/drift/base/details/user/index.js +21 -0
  222. package/lib/drift/base/details/user/index.js.map +1 -0
  223. package/lib/drift/base/details/user/marginInfo.d.ts +29 -0
  224. package/lib/drift/base/details/user/marginInfo.js +49 -0
  225. package/lib/drift/base/details/user/marginInfo.js.map +1 -0
  226. package/lib/drift/base/details/user/orders.d.ts +3 -0
  227. package/lib/drift/base/details/user/orders.js +11 -0
  228. package/lib/drift/base/details/user/orders.js.map +1 -0
  229. package/lib/drift/base/details/user/positions.d.ts +70 -0
  230. package/lib/drift/base/details/user/positions.js +146 -0
  231. package/lib/drift/base/details/user/positions.js.map +1 -0
  232. package/lib/drift/cli.d.ts +25 -0
  233. package/lib/drift/cli.js +900 -0
  234. package/lib/drift/cli.js.map +1 -0
  235. package/lib/drift/constants/apiUrls.d.ts +27 -0
  236. package/lib/drift/constants/apiUrls.js +31 -0
  237. package/lib/drift/constants/apiUrls.js.map +1 -0
  238. package/lib/drift/example.d.ts +19 -0
  239. package/lib/drift/example.js +249 -0
  240. package/lib/drift/example.js.map +1 -0
  241. package/lib/drift/index.d.ts +3 -0
  242. package/lib/drift/index.js +20 -0
  243. package/lib/drift/index.js.map +1 -0
  244. package/lib/drift/utils/auctionParamsResponseMapper.d.ts +45 -0
  245. package/lib/drift/utils/auctionParamsResponseMapper.js +148 -0
  246. package/lib/drift/utils/auctionParamsResponseMapper.js.map +1 -0
  247. package/lib/drift/utils/funding.d.ts +2 -0
  248. package/lib/drift/utils/funding.js +9 -0
  249. package/lib/drift/utils/funding.js.map +1 -0
  250. package/lib/drift/utils/index.d.ts +3 -0
  251. package/lib/drift/utils/index.js +23 -0
  252. package/lib/drift/utils/index.js.map +1 -0
  253. package/lib/drift/utils/orderParams.d.ts +48 -0
  254. package/lib/drift/utils/orderParams.js +140 -0
  255. package/lib/drift/utils/orderParams.js.map +1 -0
  256. package/lib/index.d.ts +45 -0
  257. package/lib/index.js +68 -0
  258. package/lib/index.js.map +1 -0
  259. package/lib/serializableTypes.d.ts +961 -0
  260. package/lib/serializableTypes.js +3887 -0
  261. package/lib/serializableTypes.js.map +1 -0
  262. package/lib/types/MarketId.d.ts +26 -0
  263. package/lib/types/MarketId.js +64 -0
  264. package/lib/types/MarketId.js.map +1 -0
  265. package/lib/types/Superstake.d.ts +7 -0
  266. package/lib/types/Superstake.js +3 -0
  267. package/lib/types/Superstake.js.map +1 -0
  268. package/lib/types/UIEnv.d.ts +26 -0
  269. package/lib/types/UIEnv.js +49 -0
  270. package/lib/types/UIEnv.js.map +1 -0
  271. package/lib/types/UIMarket.d.ts +94 -0
  272. package/lib/types/UIMarket.js +224 -0
  273. package/lib/types/UIMarket.js.map +1 -0
  274. package/lib/types/candles.d.ts +4 -0
  275. package/lib/types/candles.js +9 -0
  276. package/lib/types/candles.js.map +1 -0
  277. package/lib/types/dataServer.d.ts +53 -0
  278. package/lib/types/dataServer.js +3 -0
  279. package/lib/types/dataServer.js.map +1 -0
  280. package/lib/types/historyServer.d.ts +38 -0
  281. package/lib/types/historyServer.js +11 -0
  282. package/lib/types/historyServer.js.map +1 -0
  283. package/lib/types/index.d.ts +12 -0
  284. package/lib/types/index.js +29 -0
  285. package/lib/types/index.js.map +1 -0
  286. package/lib/types/leaderboard.d.ts +80 -0
  287. package/lib/types/leaderboard.js +11 -0
  288. package/lib/types/leaderboard.js.map +1 -0
  289. package/lib/types/remote-configs.d.ts +61 -0
  290. package/lib/types/remote-configs.js +3 -0
  291. package/lib/types/remote-configs.js.map +1 -0
  292. package/lib/types/trade.d.ts +18 -0
  293. package/lib/types/trade.js +3 -0
  294. package/lib/types/trade.js.map +1 -0
  295. package/lib/types/user.d.ts +40 -0
  296. package/lib/types/user.js +3 -0
  297. package/lib/types/user.js.map +1 -0
  298. package/lib/types/utility.d.ts +15 -0
  299. package/lib/types/utility.js +3 -0
  300. package/lib/types/utility.js.map +1 -0
  301. package/lib/utils/CircularBuffers/CircularBuffer.d.ts +22 -0
  302. package/lib/utils/CircularBuffers/CircularBuffer.js +73 -0
  303. package/lib/utils/CircularBuffers/CircularBuffer.js.map +1 -0
  304. package/lib/utils/CircularBuffers/UniqueCircularBuffer.d.ts +19 -0
  305. package/lib/utils/CircularBuffers/UniqueCircularBuffer.js +78 -0
  306. package/lib/utils/CircularBuffers/UniqueCircularBuffer.js.map +1 -0
  307. package/lib/utils/CircularBuffers/index.d.ts +2 -0
  308. package/lib/utils/CircularBuffers/index.js +19 -0
  309. package/lib/utils/CircularBuffers/index.js.map +1 -0
  310. package/lib/utils/MultiplexWebSocket.d.ts +95 -0
  311. package/lib/utils/MultiplexWebSocket.js +416 -0
  312. package/lib/utils/MultiplexWebSocket.js.map +1 -0
  313. package/lib/utils/NumLib.d.ts +106 -0
  314. package/lib/utils/NumLib.js +300 -0
  315. package/lib/utils/NumLib.js.map +1 -0
  316. package/lib/utils/SharedInterval.d.ts +21 -0
  317. package/lib/utils/SharedInterval.js +47 -0
  318. package/lib/utils/SharedInterval.js.map +1 -0
  319. package/lib/utils/SlotBasedResultValidator.d.ts +9 -0
  320. package/lib/utils/SlotBasedResultValidator.js +27 -0
  321. package/lib/utils/SlotBasedResultValidator.js.map +1 -0
  322. package/lib/utils/Stopwatch.d.ts +15 -0
  323. package/lib/utils/Stopwatch.js +31 -0
  324. package/lib/utils/Stopwatch.js.map +1 -0
  325. package/lib/utils/StrictEventEmitter.d.ts +15 -0
  326. package/lib/utils/StrictEventEmitter.js +55 -0
  327. package/lib/utils/StrictEventEmitter.js.map +1 -0
  328. package/lib/utils/WalletConnectionState.d.ts +31 -0
  329. package/lib/utils/WalletConnectionState.js +83 -0
  330. package/lib/utils/WalletConnectionState.js.map +1 -0
  331. package/lib/utils/assert.d.ts +1 -0
  332. package/lib/utils/assert.js +10 -0
  333. package/lib/utils/assert.js.map +1 -0
  334. package/lib/utils/candles/Candle.d.ts +94 -0
  335. package/lib/utils/candles/Candle.js +580 -0
  336. package/lib/utils/candles/Candle.js.map +1 -0
  337. package/lib/utils/candles/types.d.ts +8 -0
  338. package/lib/utils/candles/types.js +3 -0
  339. package/lib/utils/candles/types.js.map +1 -0
  340. package/lib/utils/dlob-server/DlobServerWebsocketUtils.d.ts +57 -0
  341. package/lib/utils/dlob-server/DlobServerWebsocketUtils.js +137 -0
  342. package/lib/utils/dlob-server/DlobServerWebsocketUtils.js.map +1 -0
  343. package/lib/utils/driftEvents.d.ts +10 -0
  344. package/lib/utils/driftEvents.js +123 -0
  345. package/lib/utils/driftEvents.js.map +1 -0
  346. package/lib/utils/equalityChecks.d.ts +12 -0
  347. package/lib/utils/equalityChecks.js +71 -0
  348. package/lib/utils/equalityChecks.js.map +1 -0
  349. package/lib/utils/featureFlags.d.ts +3 -0
  350. package/lib/utils/featureFlags.js +7 -0
  351. package/lib/utils/featureFlags.js.map +1 -0
  352. package/lib/utils/geoblock/index.d.ts +4 -0
  353. package/lib/utils/geoblock/index.js +20 -0
  354. package/lib/utils/geoblock/index.js.map +1 -0
  355. package/lib/utils/index.d.ts +181 -0
  356. package/lib/utils/index.js +608 -0
  357. package/lib/utils/index.js.map +1 -0
  358. package/lib/utils/insuranceFund.d.ts +15 -0
  359. package/lib/utils/insuranceFund.js +84 -0
  360. package/lib/utils/insuranceFund.js.map +1 -0
  361. package/lib/utils/logger.d.ts +5 -0
  362. package/lib/utils/logger.js +53 -0
  363. package/lib/utils/logger.js.map +1 -0
  364. package/lib/utils/math.d.ts +10 -0
  365. package/lib/utils/math.js +89 -0
  366. package/lib/utils/math.js.map +1 -0
  367. package/lib/utils/orderbook/index.d.ts +65 -0
  368. package/lib/utils/orderbook/index.js +80 -0
  369. package/lib/utils/orderbook/index.js.map +1 -0
  370. package/lib/utils/pollingSequenceGuard.d.ts +9 -0
  371. package/lib/utils/pollingSequenceGuard.js +24 -0
  372. package/lib/utils/pollingSequenceGuard.js.map +1 -0
  373. package/lib/utils/priority-fees/PriorityFeeCalculator.d.ts +24 -0
  374. package/lib/utils/priority-fees/PriorityFeeCalculator.js +53 -0
  375. package/lib/utils/priority-fees/PriorityFeeCalculator.js.map +1 -0
  376. package/lib/utils/priority-fees/PriorityFeeStrategies.d.ts +5 -0
  377. package/lib/utils/priority-fees/PriorityFeeStrategies.js +43 -0
  378. package/lib/utils/priority-fees/PriorityFeeStrategies.js.map +1 -0
  379. package/lib/utils/priority-fees/index.d.ts +2 -0
  380. package/lib/utils/priority-fees/index.js +19 -0
  381. package/lib/utils/priority-fees/index.js.map +1 -0
  382. package/lib/utils/priorityFees.d.ts +14 -0
  383. package/lib/utils/priorityFees.js +68 -0
  384. package/lib/utils/priorityFees.js.map +1 -0
  385. package/lib/utils/rpcLatency.d.ts +7 -0
  386. package/lib/utils/rpcLatency.js +49 -0
  387. package/lib/utils/rpcLatency.js.map +1 -0
  388. package/lib/utils/rxjs.d.ts +11 -0
  389. package/lib/utils/rxjs.js +24 -0
  390. package/lib/utils/rxjs.js.map +1 -0
  391. package/lib/utils/s3Buckets.d.ts +43 -0
  392. package/lib/utils/s3Buckets.js +108 -0
  393. package/lib/utils/s3Buckets.js.map +1 -0
  394. package/lib/utils/superstake.d.ts +86 -0
  395. package/lib/utils/superstake.js +224 -0
  396. package/lib/utils/superstake.js.map +1 -0
  397. package/lib/utils/token.d.ts +16 -0
  398. package/lib/utils/token.js +44 -0
  399. package/lib/utils/token.js.map +1 -0
  400. package/package.json +87 -0
@@ -0,0 +1,42 @@
1
+ import { CandleResolution } from '@drift-labs/sdk';
2
+ import { MarketSymbol, Opaque } from '../types';
3
+ import { Subject } from 'rxjs';
4
+ import { JsonCandle } from 'src/types';
5
+ import { JsonTrade } from 'src/types';
6
+ import { UIEnv } from '../types';
7
+ type SubscriptionType = 'candles' | 'trades';
8
+ interface ISubscriptionConfig<T extends SubscriptionType> {
9
+ readonly type: T;
10
+ readonly env: UIEnv;
11
+ marketSymbol: MarketSymbol;
12
+ }
13
+ type CandleSubscriptionConfig = ISubscriptionConfig<'candles'> & {
14
+ resolution: CandleResolution;
15
+ };
16
+ type TradeSubscriptionConfig = ISubscriptionConfig<'trades'>;
17
+ type SubscriberId = Opaque<string, 'SubscriberId'>;
18
+ declare abstract class SubscriberSubscription<T> {
19
+ readonly id: SubscriberId;
20
+ private readonly _subject;
21
+ get observable(): import("rxjs").Observable<T>;
22
+ constructor(id: SubscriberId, subject: Subject<T>);
23
+ }
24
+ export declare class CandleSubscriberSubscription extends SubscriberSubscription<JsonCandle> {
25
+ constructor(id: SubscriberId, subject: Subject<JsonCandle>);
26
+ }
27
+ export declare class TradeSubscriberSubscription extends SubscriberSubscription<JsonTrade[]> {
28
+ constructor(id: SubscriberId, subject: Subject<JsonTrade[]>);
29
+ }
30
+ /**
31
+ * This class will handle subscribing to market data from the Drift Data API's websocket. See https://data.api.drift.trade/playground for more information about the API.
32
+ *
33
+ * It currently supports subscribing to candles and to trades.
34
+ */
35
+ export declare class MarketDataFeed {
36
+ private static subscriptionManager;
37
+ constructor();
38
+ static subscribe(config: CandleSubscriptionConfig): CandleSubscriberSubscription;
39
+ static subscribe(config: TradeSubscriptionConfig): TradeSubscriberSubscription;
40
+ static unsubscribe(subscriberId: SubscriberId): void;
41
+ }
42
+ export {};
@@ -0,0 +1,422 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.MarketDataFeed = exports.TradeSubscriberSubscription = exports.CandleSubscriberSubscription = void 0;
7
+ const rxjs_1 = require("rxjs");
8
+ const dataApiWsClient_1 = require("./dataApiWsClient");
9
+ const assert_1 = __importDefault(require("assert"));
10
+ const tiny_invariant_1 = __importDefault(require("tiny-invariant"));
11
+ const DEFAULT_CANDLE_RESOLUTION_FOR_TRADE_SUBSCRIPTIONS = '1';
12
+ class SubscriberSubscription {
13
+ get observable() {
14
+ return this._subject.asObservable();
15
+ }
16
+ constructor(id, subject) {
17
+ this.id = id;
18
+ this._subject = subject;
19
+ }
20
+ }
21
+ class CandleSubscriberSubscription extends SubscriberSubscription {
22
+ constructor(id, subject) {
23
+ super(id, subject);
24
+ }
25
+ }
26
+ exports.CandleSubscriberSubscription = CandleSubscriberSubscription;
27
+ class TradeSubscriberSubscription extends SubscriberSubscription {
28
+ constructor(id, subject) {
29
+ super(id, subject);
30
+ }
31
+ }
32
+ exports.TradeSubscriberSubscription = TradeSubscriberSubscription;
33
+ class _Subscriber {
34
+ get subscription() {
35
+ return this._apiSubscription;
36
+ }
37
+ generateSubscriberId() {
38
+ var _a, _b, _c;
39
+ return `${(_a = this.config) === null || _a === void 0 ? void 0 : _a.type}:${(_b = this.config) === null || _b === void 0 ? void 0 : _b.marketSymbol}:${(_c = this.config) === null || _c === void 0 ? void 0 : _c.env.key}:(${_Subscriber.idIncrementer++})`;
40
+ }
41
+ constructor(config) {
42
+ this.config = { ...config }; // Make a copy of the config to avoid mutability issues
43
+ this.id = this.generateSubscriberId();
44
+ }
45
+ setSubscription(subscription) {
46
+ this._apiSubscription = subscription;
47
+ }
48
+ next(data) {
49
+ this.subject.next(data);
50
+ }
51
+ }
52
+ _Subscriber.idIncrementer = 0;
53
+ class CandleSubscriber extends _Subscriber {
54
+ constructor(config) {
55
+ super(config);
56
+ this.subject = new rxjs_1.Subject();
57
+ this.subscriberSubscription = new CandleSubscriberSubscription(this.id, this.subject);
58
+ }
59
+ }
60
+ class TradeSubscriber extends _Subscriber {
61
+ constructor(config) {
62
+ super(config);
63
+ this.subject = new rxjs_1.Subject();
64
+ this.subscriberSubscription = new TradeSubscriberSubscription(this.id, this.subject);
65
+ }
66
+ }
67
+ function getCompatibleCandleSubscriptionLookupKey(config) {
68
+ return `${config.marketSymbol}:${config.resolution}:${config.env.key}`;
69
+ }
70
+ function getCompatibleTradeSubscriptionLookupKey(config) {
71
+ return `${config.marketSymbol}:${config.env.key}`;
72
+ }
73
+ class ApiSubscription {
74
+ generateSubscriptionId() {
75
+ return `${getCompatibleCandleSubscriptionLookupKey(this.config)}(${ApiSubscription.idIncrementer++})`;
76
+ }
77
+ /**
78
+ * Any trade subscription with a matching key can use this ApiSubscription.
79
+ */
80
+ get tradeSubscriptionsLookupKey() {
81
+ return getCompatibleTradeSubscriptionLookupKey(this.config);
82
+ }
83
+ /**
84
+ * Any candle subscription with a matching key can use this ApiSubscription.
85
+ */
86
+ get candleSubscriptionsLookupKey() {
87
+ return getCompatibleCandleSubscriptionLookupKey(this.config);
88
+ }
89
+ constructor(resolution, initialSubscriber, onNoMoreSubscribers) {
90
+ const marketSymbol = initialSubscriber.config.marketSymbol;
91
+ const env = initialSubscriber.config.env;
92
+ this.config = { marketSymbol, resolution, env };
93
+ this.id = this.generateSubscriptionId();
94
+ this.onNoMoreSubscribers = () => onNoMoreSubscribers(this.id);
95
+ console.log(`marketDataFeed::creating_new_api_subscription:${this.id}`);
96
+ const initialSubscriberType = initialSubscriber.config.type;
97
+ this.apiClient = new dataApiWsClient_1.DataApiWsClient({
98
+ marketSymbol: this.config.marketSymbol,
99
+ resolution: this.config.resolution,
100
+ env: this.config.env,
101
+ });
102
+ initialSubscriber.setSubscription(this);
103
+ switch (initialSubscriberType) {
104
+ case 'candles': {
105
+ this.candleSubscribers = new Map([
106
+ [initialSubscriber.id, initialSubscriber],
107
+ ]);
108
+ this.tradeSubscribers = new Map();
109
+ break;
110
+ }
111
+ case 'trades': {
112
+ this.candleSubscribers = new Map();
113
+ this.tradeSubscribers = new Map([
114
+ [initialSubscriber.id, initialSubscriber],
115
+ ]);
116
+ break;
117
+ }
118
+ default: {
119
+ const _never = initialSubscriberType;
120
+ throw new Error(`Unknown subscription type: ${_never}`);
121
+ }
122
+ }
123
+ this.subscribeToApi();
124
+ }
125
+ async subscribeToApi() {
126
+ await this.apiClient.subscribe();
127
+ this.apiClient.candlesObservable.subscribe((candle) => {
128
+ this.candleSubscribers.forEach((subscriber) => {
129
+ subscriber.next(candle);
130
+ });
131
+ });
132
+ this.apiClient.tradesObservable.subscribe((trades) => {
133
+ this.tradeSubscribers.forEach((subscriber) => {
134
+ subscriber.next(trades);
135
+ });
136
+ });
137
+ }
138
+ attachNewCandleSubscriberToExistingSubscription(subscriber) {
139
+ subscriber.setSubscription(this);
140
+ this.candleSubscribers.set(subscriber.id, subscriber);
141
+ }
142
+ attachNewTradeSubscriberToExistingSubscription(subscriber) {
143
+ subscriber.setSubscription(this);
144
+ this.tradeSubscribers.set(subscriber.id, subscriber);
145
+ }
146
+ unsubscribeFromApi() {
147
+ console.log(`marketDataFeed::unsubscribing_api_subscription:${this.id}`);
148
+ this.apiClient.unsubscribe();
149
+ }
150
+ removeSubscriber(subscriberId) {
151
+ this.candleSubscribers.delete(subscriberId);
152
+ this.tradeSubscribers.delete(subscriberId);
153
+ // Handle the case where there are no more subscribers for this subscription
154
+ if (this.candleSubscribers.size === 0 && this.tradeSubscribers.size === 0) {
155
+ this.unsubscribeFromApi();
156
+ this.onNoMoreSubscribers();
157
+ }
158
+ }
159
+ }
160
+ ApiSubscription.idIncrementer = 0;
161
+ class SubscriptionLookup {
162
+ has(subscriptionLookupKey) {
163
+ return !!this.get(subscriptionLookupKey);
164
+ }
165
+ }
166
+ class TradeSubscriptionLookup extends SubscriptionLookup {
167
+ constructor() {
168
+ super();
169
+ this.subscriptions = new Map();
170
+ }
171
+ add(apiSubscription) {
172
+ const subscriptions = this.subscriptions.get(apiSubscription.tradeSubscriptionsLookupKey);
173
+ if (!subscriptions) {
174
+ this.subscriptions.set(apiSubscription.tradeSubscriptionsLookupKey, [
175
+ apiSubscription,
176
+ ]);
177
+ }
178
+ else {
179
+ subscriptions.push(apiSubscription);
180
+ }
181
+ }
182
+ get(subscriptionLookupKey) {
183
+ var _a, _b;
184
+ return (_b = (_a = this.subscriptions.get(subscriptionLookupKey)) === null || _a === void 0 ? void 0 : _a[0]) !== null && _b !== void 0 ? _b : null;
185
+ }
186
+ getAll(subscriptionLookupKey) {
187
+ var _a;
188
+ return (_a = this.subscriptions.get(subscriptionLookupKey)) !== null && _a !== void 0 ? _a : [];
189
+ }
190
+ remove(apiSubscription) {
191
+ const subscriptionLookupKey = apiSubscription.tradeSubscriptionsLookupKey;
192
+ const apiSubscriptionId = apiSubscription.id;
193
+ const subscriptions = this.subscriptions.get(subscriptionLookupKey);
194
+ if (!subscriptions)
195
+ return;
196
+ const index = subscriptions.findIndex((subscription) => subscription.id === apiSubscriptionId);
197
+ if (index === -1)
198
+ return;
199
+ subscriptions.splice(index, 1);
200
+ // Clean up empty arrays to prevent memory leaks and ensure has() works correctly
201
+ if (subscriptions.length === 0) {
202
+ this.subscriptions.delete(subscriptionLookupKey);
203
+ }
204
+ }
205
+ has(subscriptionLookupKey) {
206
+ return super.has(subscriptionLookupKey);
207
+ }
208
+ }
209
+ class CandleSubscriptionLookup extends SubscriptionLookup {
210
+ constructor() {
211
+ super();
212
+ this.subscriptions = new Map();
213
+ }
214
+ add(apiSubscription) {
215
+ this.subscriptions.set(apiSubscription.candleSubscriptionsLookupKey, apiSubscription);
216
+ }
217
+ get(subscriptionLookupKey) {
218
+ var _a;
219
+ return (_a = this.subscriptions.get(subscriptionLookupKey)) !== null && _a !== void 0 ? _a : null;
220
+ }
221
+ remove(apiSubscription) {
222
+ const subscriptionLookupKey = apiSubscription.candleSubscriptionsLookupKey;
223
+ this.subscriptions.delete(subscriptionLookupKey);
224
+ }
225
+ has(subscriptionLookupKey) {
226
+ return super.has(subscriptionLookupKey);
227
+ }
228
+ }
229
+ /**
230
+ * Internal class that manages the complex subscription orchestration logic.
231
+ * This handles subscription sharing, transfer logic, and lifecycle management.
232
+ */
233
+ class SubscriptionManager {
234
+ constructor() {
235
+ // Stores all current subscribers
236
+ this.subscribers = new Map();
237
+ // Stores all current subscriptions :: subscribers:subscriptions is N:M (Subscribers may share a subscription but not vice versa)
238
+ this.apiSubscriptions = new Map();
239
+ // Lookup table for any existing subscriptions which have a compatible configuration for a trade subscriber. Can be multiple compatible subscriptions for a trade subscriber.
240
+ this.compatibleTradeSubscriptionLookup = new TradeSubscriptionLookup();
241
+ // Lookup table for any existing subscriptions which have a compatible configuration for a candle subscriber. Should only be one compatible subscription for a candle subscriber.
242
+ this.compatibleCandleSubscriptionLookup = new CandleSubscriptionLookup();
243
+ }
244
+ /**
245
+ * Handles a new subscription by adding it to the necessary lookup tables
246
+ * @param subscription
247
+ */
248
+ handleNewApiSubscription(subscription) {
249
+ this.apiSubscriptions.set(subscription.id, subscription);
250
+ // Add to the trade subscription compatibility lookup
251
+ this.compatibleTradeSubscriptionLookup.add(subscription);
252
+ // Add to the candle subscription compatibility lookup if a previous one suiting this subscription doesn't already exist
253
+ if (!this.compatibleCandleSubscriptionLookup.has(subscription.candleSubscriptionsLookupKey)) {
254
+ this.compatibleCandleSubscriptionLookup.add(subscription);
255
+ }
256
+ this.checkForTradeSubscriptionTransferForNewSubscription(subscription);
257
+ }
258
+ transferTradeSubscribersToNewSubscription(existingTradeSubscription, newSubscription) {
259
+ (0, tiny_invariant_1.default)(existingTradeSubscription.id !== newSubscription.id, 'Expected different subscriptions when transferring trade subscribers');
260
+ (0, tiny_invariant_1.default)(existingTradeSubscription.candleSubscribers.size === 0, 'Expected existing trade subscription to have no candle subscribers when transferring trade subscribers');
261
+ // Transfer the subscribers to the new subscription
262
+ const tradeSubscribers = Array.from(existingTradeSubscription.tradeSubscribers.values());
263
+ if (tradeSubscribers.length === 0)
264
+ return; // Skip early if there are no trade subscribers to transfer
265
+ console.log(`marketDataFeed::transferring_previous_trade_subscribers_to_new_subscription`);
266
+ tradeSubscribers.forEach((tradeSubscriber) => {
267
+ newSubscription.attachNewTradeSubscriberToExistingSubscription(tradeSubscriber);
268
+ existingTradeSubscription.removeSubscriber(tradeSubscriber.id);
269
+ });
270
+ }
271
+ /**
272
+ * When we have a new subscription, we want to check if there is an existing subscription with trade subscribers which should be transferred to the new subscription.
273
+ *
274
+ * Reasoning:
275
+ * - If a TRADE SUBSCRIBER caused a new subscription to be created
276
+ * - and then a following CANDLE SUBSCRIBER is created for the same market
277
+ * => then it is wasteful to keep the previous trade subscription open, because the new candle subscription can collect the data for both subscribers
278
+ *
279
+ * @param newSubscription
280
+ */
281
+ checkForTradeSubscriptionTransferForNewSubscription(newSubscription) {
282
+ const tradeSubscriptionLookupKey = newSubscription.tradeSubscriptionsLookupKey;
283
+ (0, tiny_invariant_1.default)(!!this.compatibleTradeSubscriptionLookup.get(tradeSubscriptionLookupKey), `Expect a matching trade subscription when checking for transfers for a new subscription`);
284
+ const allCompatibleTradeSubscriptions = this.compatibleTradeSubscriptionLookup.getAll(tradeSubscriptionLookupKey);
285
+ for (const existingTradeSubscription of allCompatibleTradeSubscriptions) {
286
+ if (existingTradeSubscription.id === newSubscription.id)
287
+ continue; // If the subscription is the current subscription, then there are no subscribers to transfer.
288
+ if (existingTradeSubscription.candleSubscribers.size > 0)
289
+ continue; // If the existing subscription has candle subscribers, skip doing any transfers because it's not any extra efficient to do so.
290
+ this.transferTradeSubscribersToNewSubscription(existingTradeSubscription, newSubscription);
291
+ }
292
+ }
293
+ /**
294
+ * When a subscriber unsubscribes and causes the subscription to have some remaining trade subscribers, but no candle subscribers, we want to check if there is another compatible subscription to transfer the trade subscribers to.
295
+ * @param apiSubscription
296
+ */
297
+ checkForSubscriptionTransferOnUnsubscribe(apiSubscription) {
298
+ if (apiSubscription.tradeSubscribers.size === 0)
299
+ return; // Skip early if there are no trade subscribers to transfer
300
+ if (apiSubscription.candleSubscribers.size > 0)
301
+ return; // Skip early if there are candle subscribers
302
+ // Look for another compatible subscription to transfer the trade subscribers to
303
+ const tradeSubscriptionLookupKey = apiSubscription.tradeSubscriptionsLookupKey;
304
+ // Get all compatible subscriptions for this market
305
+ const compatibleSubscriptions = this.compatibleTradeSubscriptionLookup.getAll(tradeSubscriptionLookupKey);
306
+ if (!compatibleSubscriptions || compatibleSubscriptions.length <= 1) {
307
+ // No other compatible subscriptions available, or only this subscription exists
308
+ return;
309
+ }
310
+ // Find a different subscription that can accept the trade subscribers
311
+ const targetSubscription = compatibleSubscriptions.find((subscription) => subscription.id !== apiSubscription.id);
312
+ if (!targetSubscription) {
313
+ // No suitable target subscription found
314
+ return;
315
+ }
316
+ console.log(`marketDataFeed::transferring_trade_subscribers_on_unsubscribe`);
317
+ // Transfer all trade subscribers to the target subscription
318
+ this.transferTradeSubscribersToNewSubscription(apiSubscription, targetSubscription);
319
+ }
320
+ handleNewCandleSubscriber(subscriber) {
321
+ const candleSubscriptionLookupKey = getCompatibleCandleSubscriptionLookupKey(subscriber.config);
322
+ const hasExistingSuitableSubscription = this.compatibleCandleSubscriptionLookup.has(candleSubscriptionLookupKey);
323
+ if (hasExistingSuitableSubscription) {
324
+ console.log(`marketDataFeed::attaching_new_candle_subscriber_to_existing_subscription`);
325
+ const existingSubscription = this.compatibleCandleSubscriptionLookup.get(candleSubscriptionLookupKey);
326
+ existingSubscription.attachNewCandleSubscriberToExistingSubscription(subscriber);
327
+ }
328
+ else {
329
+ console.log(`marketDataFeed::creating_new_candle_subscription`);
330
+ const newSubscription = new ApiSubscription(subscriber.config.resolution, subscriber, this.cleanupApiSubscription.bind(this));
331
+ this.handleNewApiSubscription(newSubscription);
332
+ }
333
+ (0, assert_1.default)(this.subscribers.has(subscriber.id), 'Subscriber should be added to subscribers map');
334
+ }
335
+ handleNewTradeSubscriber(subscriber) {
336
+ // Check if any existing subscriptions already suit the new subscriber
337
+ const tradeSubscriptionLookupKey = getCompatibleTradeSubscriptionLookupKey(subscriber.config);
338
+ const hasExistingSuitableSubscription = this.compatibleTradeSubscriptionLookup.has(tradeSubscriptionLookupKey);
339
+ if (hasExistingSuitableSubscription) {
340
+ console.log(`marketDataFeed::attaching_new_trade_subscriber_to_existing_subscription`);
341
+ const existingSubscription = this.compatibleTradeSubscriptionLookup.get(tradeSubscriptionLookupKey);
342
+ existingSubscription.attachNewTradeSubscriberToExistingSubscription(subscriber);
343
+ }
344
+ else {
345
+ console.log(`marketDataFeed::creating_new_trade_subscription`);
346
+ const newSubscription = new ApiSubscription(DEFAULT_CANDLE_RESOLUTION_FOR_TRADE_SUBSCRIPTIONS, subscriber, this.cleanupApiSubscription.bind(this));
347
+ this.handleNewApiSubscription(newSubscription);
348
+ }
349
+ (0, assert_1.default)(this.subscribers.has(subscriber.id), 'Subscriber should be added to subscribers map');
350
+ }
351
+ /**
352
+ * This method gets called when we no longer need an ApiSubscription and can close it down completely.
353
+ * @param apiSubscriptionId
354
+ */
355
+ cleanupApiSubscription(apiSubscriptionId) {
356
+ const apiSubscription = this.apiSubscriptions.get(apiSubscriptionId);
357
+ (0, tiny_invariant_1.default)(apiSubscription.candleSubscribers.size === 0, 'Expected api subscription to have no candle subscribers when cleaning up');
358
+ (0, tiny_invariant_1.default)(apiSubscription.tradeSubscribers.size === 0, 'Expected api subscription to have no trade subscribers when cleaning up');
359
+ // Remove the subscription from the lookup tables
360
+ this.compatibleTradeSubscriptionLookup.remove(apiSubscription);
361
+ this.compatibleCandleSubscriptionLookup.remove(apiSubscription);
362
+ // We can delete the subscription from the lookup table when we're cleaning up an ApiSubscription
363
+ this.apiSubscriptions.delete(apiSubscriptionId);
364
+ }
365
+ /**
366
+ * Creates a new subscriber and manages its subscription lifecycle
367
+ */
368
+ subscribe(config) {
369
+ switch (config.type) {
370
+ case 'candles': {
371
+ // Create the new Subscriber
372
+ const newSubscriber = new CandleSubscriber(config);
373
+ // Add to current subscribers
374
+ this.subscribers.set(newSubscriber.id, newSubscriber);
375
+ this.handleNewCandleSubscriber(newSubscriber);
376
+ return newSubscriber.subscriberSubscription;
377
+ }
378
+ case 'trades': {
379
+ // Create the new Subscriber
380
+ const newSubscriber = new TradeSubscriber(config);
381
+ // Add to current subscribers
382
+ this.subscribers.set(newSubscriber.id, newSubscriber);
383
+ this.handleNewTradeSubscriber(newSubscriber);
384
+ return newSubscriber.subscriberSubscription;
385
+ }
386
+ default: {
387
+ const _never = config;
388
+ throw new Error(`Unknown subscription type: ${_never}`);
389
+ }
390
+ }
391
+ }
392
+ /**
393
+ * Removes a subscriber and cleans up resources as needed
394
+ */
395
+ unsubscribe(subscriberId) {
396
+ const subscriber = this.subscribers.get(subscriberId);
397
+ if (!subscriber) {
398
+ throw new Error(`Subscriber not found: ${subscriberId}`);
399
+ }
400
+ const apiSubscription = subscriber.subscription;
401
+ apiSubscription.removeSubscriber(subscriberId);
402
+ this.checkForSubscriptionTransferOnUnsubscribe(apiSubscription);
403
+ this.subscribers.delete(subscriberId);
404
+ }
405
+ }
406
+ /**
407
+ * This class will handle subscribing to market data from the Drift Data API's websocket. See https://data.api.drift.trade/playground for more information about the API.
408
+ *
409
+ * It currently supports subscribing to candles and to trades.
410
+ */
411
+ class MarketDataFeed {
412
+ constructor() { }
413
+ static subscribe(config) {
414
+ return this.subscriptionManager.subscribe(config);
415
+ }
416
+ static unsubscribe(subscriberId) {
417
+ this.subscriptionManager.unsubscribe(subscriberId);
418
+ }
419
+ }
420
+ exports.MarketDataFeed = MarketDataFeed;
421
+ MarketDataFeed.subscriptionManager = new SubscriptionManager();
422
+ //# sourceMappingURL=marketDataFeed.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"marketDataFeed.js","sourceRoot":"","sources":["../../src/clients/marketDataFeed.ts"],"names":[],"mappings":"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","sourcesContent":["import { CandleResolution } from '@drift-labs/sdk';\nimport { MarketSymbol, Opaque } from '../types';\nimport { Subject } from 'rxjs';\nimport { DataApiWsClient } from './dataApiWsClient';\nimport { JsonCandle } from 'src/types';\nimport { JsonTrade } from 'src/types';\nimport { UIEnv } from '../types';\nimport assert from 'assert';\nimport invariant from 'tiny-invariant';\n\n/*\n\n# Internal/Functional explanation of the MarketDataFeed class\n\nThis class was implmented as a singleton so that we can avoid making duplicate websockets where they are not necessary.\n\nOne key thing to understand about the logic is that on the API side, there is only a \"single\" websocket available which is to subscribe to CANDLES.\n\nEach of these \"candles\" websockets also returns the TRADES which resulted in the updated candle.\n\nTo ensure that trades and candles are in sync, we want to make sure that subscriptions for these things (which is done seperately) actually use the same websocket connection. Which is why this class is necessary.\n\n## Explanation of terminology:\n- A \"subscription\" is an actual underlying websocket connection to the Drift Data API. A subscription may have multiple subscribers attached to it, where the data coming through that subscription is sufficient for the subsciption config. A Subscription can have the data for both CANDLES and TRADES subscribers.\n- A \"subscriber\" is a specific instance of an external party making a subscription. It is either a TRADE or CANDLE subscriber.\n- A \"subscriber subscription\" represents the subscription information that we return to an external subscriber. It contains the subscription ID they can use to unsubscriber, an an observable to listen to the data.\n\n## Explanation for tradeSubscriptionLookup and candleSubscriptionLookup:\nThis class supports subscribing to multiple arbitrary markets (and candle resolutions) at the same time. It also supports sharing a single websocket connection between multiple subscribers where possible. This creates one bit of complexity where we need to search for existing \"compatible\" subscriptions whenever a new subscriber comes through. Example:\n- Imagine a CANDLE subscription for SOL-PERP-Resolution-1 (Subscription A).\n- When a TRADE subscription comes through for SOL-PERP (Subscription B) we want it to use the same websocket connection as Subscription A, because they are for the same market - even though they are different subscription types. We use the `tradeSubscriptionLookup` to see that there is an existing subscription for this market and then attach the new trade subscriber to it.\n- When another CANDLE subscription comes through for SOL-PERP-Resolution-5 (Subscription C), there is no existing subscription in the `candleSubscriptionsLookup`, because the resolution is different. Hence we create a new subscription.\n- TO SUMMARISE :: A trade subscription can share any subscription with the same market. But a candle subscription must share the same market AND resolution. We use seperate lookup tables to index into compatible subscriptions.\n\nThere is a minor inefficiency remaining in this implementation, where to be optimal we may want to \"re-organise\" subscriptions when they close. E.g.:\n- <open> SOL-PERP-Resolution-1 (Subscriber A) => will create new Subscription A\n- <open> SOL-PERP-Resolution-5 (Subscriber B) => will create new Subscription B\n- <open> SOL-PERP-TRADE (Subscriber C) => will use existing Subscription A\n- <close> SOL-PERP-Resolution-1 (Subscriber A) => will keep Subscription A open because Subscriber C is still listening\n- * We could more optimally close Subscription A and make Subscriber C use Subscription B\n- * We're not doing this for the same of simplicity. In the future we could add this optimisation if it becomes necessary.\n\n---\n\n## Explanation of each of the classes in this file and their purpose:\n\n### Core Data Classes:\n- **SubscriberSubscription (abstract)**: Base class for subscription objects returned to external consumers. Contains an ID and an observable for receiving data.\n- **CandleSubscriberSubscription**: Concrete implementation for candle data subscriptions, emits JsonCandle objects.\n- **TradeSubscriberSubscription**: Concrete implementation for trade data subscriptions, emits JsonTrade[] arrays.\n\n### Internal Subscriber Management:\n- **_Subscriber (abstract)**: Base class for internal subscriber management. Tracks subscriber config, generates unique IDs, and manages the connection to ApiSubscription.\n- **CandleSubscriber**: Internal subscriber for candle data, creates and manages a Subject<JsonCandle> for data distribution.\n- **TradeSubscriber**: Internal subscriber for trade data, creates and manages a Subject<JsonTrade[]> for data distribution.\n\n### WebSocket Connection Management:\n- **ApiSubscription**: Manages a single websocket connection to the Drift Data API. Can serve multiple subscribers (both candle and trade) if they're compatible. Handles the actual API communication and data distribution to attached subscribers.\n\n### Subscription Discovery and Sharing:\n- **SubscriptionLookup (abstract)**: Base class for lookup tables that help find compatible existing subscriptions for new subscribers.\n- **TradeSubscriptionLookup**: Manages lookup table for trade subscriptions. Multiple ApiSubscriptions can be compatible for trade subscribers (any subscription for the same market works).\n- **CandleSubscriptionLookup**: Manages lookup table for candle subscriptions. Only one ApiSubscription per market+resolution combination.\n\n### Core Orchestration:\n- **SubscriptionManager**: The main orchestrator that handles all subscription logic, manages the lifecycle of subscribers and ApiSubscriptions, handles subscription sharing and transfer optimization.\n- **MarketDataFeed**: Public singleton interface that external code uses to subscribe/unsubscribe. Delegates all work to the internal SubscriptionManager.\n*/\n\ntype SubscriptionType = 'candles' | 'trades';\n\ninterface ISubscriptionConfig<T extends SubscriptionType> {\n\treadonly type: T;\n\treadonly env: UIEnv;\n\tmarketSymbol: MarketSymbol;\n}\ntype CandleSubscriptionConfig = ISubscriptionConfig<'candles'> & {\n\tresolution: CandleResolution;\n};\ntype TradeSubscriptionConfig = ISubscriptionConfig<'trades'>;\ntype SubscriptionConfig = CandleSubscriptionConfig | TradeSubscriptionConfig;\n\ntype SubscriberId = Opaque<string, 'SubscriberId'>;\ntype ApiSubscriptionId = Opaque<string, 'ApiSubscriptionId'>;\n\ntype CandleSubscriptionLookupKey = Opaque<\n\tstring,\n\t'CandleSubscriptionLookupKey'\n>;\ntype TradeSubscriptionLookupKey = Opaque<string, 'TradeSubscriptionLookupKey'>;\n\nconst DEFAULT_CANDLE_RESOLUTION_FOR_TRADE_SUBSCRIPTIONS: CandleResolution = '1';\n\nabstract class SubscriberSubscription<T> {\n\tpublic readonly id: SubscriberId;\n\tprivate readonly _subject: Subject<T>;\n\n\tpublic get observable() {\n\t\treturn this._subject.asObservable();\n\t}\n\n\tconstructor(id: SubscriberId, subject: Subject<T>) {\n\t\tthis.id = id;\n\t\tthis._subject = subject;\n\t}\n}\n\nexport class CandleSubscriberSubscription extends SubscriberSubscription<JsonCandle> {\n\tconstructor(id: SubscriberId, subject: Subject<JsonCandle>) {\n\t\tsuper(id, subject);\n\t}\n}\n\nexport class TradeSubscriberSubscription extends SubscriberSubscription<\n\tJsonTrade[]\n> {\n\tconstructor(id: SubscriberId, subject: Subject<JsonTrade[]>) {\n\t\tsuper(id, subject);\n\t}\n}\n\nabstract class _Subscriber<T> {\n\tpublic readonly id: SubscriberId;\n\tpublic readonly config: SubscriptionConfig;\n\tprotected _apiSubscription: ApiSubscription;\n\tprotected subject: Subject<T>;\n\tprivate static idIncrementer: number = 0;\n\n\tpublic get subscription(): ApiSubscription {\n\t\treturn this._apiSubscription;\n\t}\n\n\tprivate generateSubscriberId(): SubscriberId {\n\t\treturn `${this.config?.type}:${this.config?.marketSymbol}:${\n\t\t\tthis.config?.env.key\n\t\t}:(${_Subscriber.idIncrementer++})` as SubscriberId;\n\t}\n\n\tconstructor(config: SubscriptionConfig) {\n\t\tthis.config = { ...config }; // Make a copy of the config to avoid mutability issues\n\t\tthis.id = this.generateSubscriberId();\n\t}\n\n\tsetSubscription(subscription: ApiSubscription) {\n\t\tthis._apiSubscription = subscription;\n\t}\n\n\tnext(data: T) {\n\t\tthis.subject.next(data);\n\t}\n}\n\nclass CandleSubscriber extends _Subscriber<JsonCandle> {\n\tpublic declare readonly config: CandleSubscriptionConfig;\n\tpublic readonly subscriberSubscription: CandleSubscriberSubscription;\n\n\tconstructor(config: CandleSubscriptionConfig) {\n\t\tsuper(config);\n\t\tthis.subject = new Subject<JsonCandle>();\n\t\tthis.subscriberSubscription = new CandleSubscriberSubscription(\n\t\t\tthis.id,\n\t\t\tthis.subject\n\t\t);\n\t}\n}\n\nclass TradeSubscriber extends _Subscriber<JsonTrade[]> {\n\tpublic declare readonly config: TradeSubscriptionConfig;\n\tpublic readonly subscriberSubscription: TradeSubscriberSubscription;\n\n\tconstructor(config: TradeSubscriptionConfig) {\n\t\tsuper(config);\n\t\tthis.subject = new Subject<JsonTrade[]>();\n\t\tthis.subscriberSubscription = new TradeSubscriberSubscription(\n\t\t\tthis.id,\n\t\t\tthis.subject\n\t\t);\n\t}\n}\n\ntype Subscriber = CandleSubscriber | TradeSubscriber;\n\nfunction getCompatibleCandleSubscriptionLookupKey(\n\tconfig: Pick<CandleSubscriptionConfig, 'marketSymbol' | 'resolution' | 'env'>\n): CandleSubscriptionLookupKey {\n\treturn `${config.marketSymbol}:${config.resolution}:${config.env.key}` as CandleSubscriptionLookupKey;\n}\n\nfunction getCompatibleTradeSubscriptionLookupKey(\n\tconfig: Pick<CandleSubscriptionConfig, 'marketSymbol' | 'env'>\n): TradeSubscriptionLookupKey {\n\treturn `${config.marketSymbol}:${config.env.key}` as TradeSubscriptionLookupKey;\n}\n\nclass ApiSubscription {\n\tpublic readonly id: ApiSubscriptionId;\n\tpublic readonly candleSubscribers: Map<SubscriberId, CandleSubscriber>;\n\tpublic readonly tradeSubscribers: Map<SubscriberId, TradeSubscriber>;\n\tpublic readonly config: Pick<\n\t\tCandleSubscriptionConfig,\n\t\t'marketSymbol' | 'resolution' | 'env'\n\t>;\n\tprivate apiClient: DataApiWsClient;\n\tprivate onNoMoreSubscribers: () => void;\n\tprivate static idIncrementer: number = 0;\n\n\tprivate generateSubscriptionId(): ApiSubscriptionId {\n\t\treturn `${getCompatibleCandleSubscriptionLookupKey(\n\t\t\tthis.config\n\t\t)}(${ApiSubscription.idIncrementer++})` as ApiSubscriptionId;\n\t}\n\n\t/**\n\t * Any trade subscription with a matching key can use this ApiSubscription.\n\t */\n\tget tradeSubscriptionsLookupKey() {\n\t\treturn getCompatibleTradeSubscriptionLookupKey(this.config);\n\t}\n\n\t/**\n\t * Any candle subscription with a matching key can use this ApiSubscription.\n\t */\n\tget candleSubscriptionsLookupKey() {\n\t\treturn getCompatibleCandleSubscriptionLookupKey(this.config);\n\t}\n\n\tconstructor(\n\t\tresolution: CandleResolution,\n\t\tinitialSubscriber: Subscriber,\n\t\tonNoMoreSubscribers: (subscription: ApiSubscriptionId) => void\n\t) {\n\t\tconst marketSymbol = initialSubscriber.config.marketSymbol;\n\t\tconst env = initialSubscriber.config.env;\n\t\tthis.config = { marketSymbol, resolution, env };\n\t\tthis.id = this.generateSubscriptionId();\n\t\tthis.onNoMoreSubscribers = () => onNoMoreSubscribers(this.id);\n\t\tconsole.log(`marketDataFeed::creating_new_api_subscription:${this.id}`);\n\n\t\tconst initialSubscriberType = initialSubscriber.config.type;\n\n\t\tthis.apiClient = new DataApiWsClient({\n\t\t\tmarketSymbol: this.config.marketSymbol,\n\t\t\tresolution: this.config.resolution,\n\t\t\tenv: this.config.env,\n\t\t});\n\n\t\tinitialSubscriber.setSubscription(this);\n\n\t\tswitch (initialSubscriberType) {\n\t\t\tcase 'candles': {\n\t\t\t\tthis.candleSubscribers = new Map([\n\t\t\t\t\t[initialSubscriber.id, initialSubscriber as CandleSubscriber],\n\t\t\t\t]);\n\t\t\t\tthis.tradeSubscribers = new Map();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'trades': {\n\t\t\t\tthis.candleSubscribers = new Map();\n\t\t\t\tthis.tradeSubscribers = new Map([\n\t\t\t\t\t[initialSubscriber.id, initialSubscriber as TradeSubscriber],\n\t\t\t\t]);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tdefault: {\n\t\t\t\tconst _never: never = initialSubscriberType;\n\t\t\t\tthrow new Error(`Unknown subscription type: ${_never}`);\n\t\t\t}\n\t\t}\n\n\t\tthis.subscribeToApi();\n\t}\n\n\tprivate async subscribeToApi() {\n\t\tawait this.apiClient.subscribe();\n\t\tthis.apiClient.candlesObservable.subscribe((candle) => {\n\t\t\tthis.candleSubscribers.forEach((subscriber) => {\n\t\t\t\tsubscriber.next(candle);\n\t\t\t});\n\t\t});\n\t\tthis.apiClient.tradesObservable.subscribe((trades) => {\n\t\t\tthis.tradeSubscribers.forEach((subscriber) => {\n\t\t\t\tsubscriber.next(trades);\n\t\t\t});\n\t\t});\n\t}\n\n\tpublic attachNewCandleSubscriberToExistingSubscription(\n\t\tsubscriber: CandleSubscriber\n\t) {\n\t\tsubscriber.setSubscription(this);\n\t\tthis.candleSubscribers.set(subscriber.id, subscriber);\n\t}\n\n\tpublic attachNewTradeSubscriberToExistingSubscription(\n\t\tsubscriber: TradeSubscriber\n\t) {\n\t\tsubscriber.setSubscription(this);\n\t\tthis.tradeSubscribers.set(subscriber.id, subscriber);\n\t}\n\n\tprivate unsubscribeFromApi() {\n\t\tconsole.log(`marketDataFeed::unsubscribing_api_subscription:${this.id}`);\n\t\tthis.apiClient.unsubscribe();\n\t}\n\n\tpublic removeSubscriber(subscriberId: SubscriberId) {\n\t\tthis.candleSubscribers.delete(subscriberId);\n\t\tthis.tradeSubscribers.delete(subscriberId);\n\n\t\t// Handle the case where there are no more subscribers for this subscription\n\t\tif (this.candleSubscribers.size === 0 && this.tradeSubscribers.size === 0) {\n\t\t\tthis.unsubscribeFromApi();\n\t\t\tthis.onNoMoreSubscribers();\n\t\t}\n\t}\n}\n\nabstract class SubscriptionLookup {\n\tabstract add(apiSubscription: ApiSubscription): void;\n\tabstract get(subscriptionLookupKey: string): ApiSubscription | null;\n\tabstract remove(apiSubscription: ApiSubscription): void;\n\thas(subscriptionLookupKey: string): boolean {\n\t\treturn !!this.get(subscriptionLookupKey);\n\t}\n}\n\nclass TradeSubscriptionLookup extends SubscriptionLookup {\n\tprivate subscriptions: Map<TradeSubscriptionLookupKey, ApiSubscription[]> =\n\t\tnew Map();\n\n\tconstructor() {\n\t\tsuper();\n\t}\n\n\tadd(apiSubscription: ApiSubscription): void {\n\t\tconst subscriptions = this.subscriptions.get(\n\t\t\tapiSubscription.tradeSubscriptionsLookupKey\n\t\t);\n\n\t\tif (!subscriptions) {\n\t\t\tthis.subscriptions.set(apiSubscription.tradeSubscriptionsLookupKey, [\n\t\t\t\tapiSubscription,\n\t\t\t]);\n\t\t} else {\n\t\t\tsubscriptions.push(apiSubscription);\n\t\t}\n\t}\n\n\tget(\n\t\tsubscriptionLookupKey: TradeSubscriptionLookupKey\n\t): ApiSubscription | null {\n\t\treturn this.subscriptions.get(subscriptionLookupKey)?.[0] ?? null;\n\t}\n\n\tgetAll(subscriptionLookupKey: TradeSubscriptionLookupKey): ApiSubscription[] {\n\t\treturn this.subscriptions.get(subscriptionLookupKey) ?? [];\n\t}\n\n\tremove(apiSubscription: ApiSubscription): void {\n\t\tconst subscriptionLookupKey = apiSubscription.tradeSubscriptionsLookupKey;\n\t\tconst apiSubscriptionId = apiSubscription.id;\n\n\t\tconst subscriptions = this.subscriptions.get(subscriptionLookupKey);\n\n\t\tif (!subscriptions) return;\n\n\t\tconst index = subscriptions.findIndex(\n\t\t\t(subscription) => subscription.id === apiSubscriptionId\n\t\t);\n\n\t\tif (index === -1) return;\n\n\t\tsubscriptions.splice(index, 1);\n\n\t\t// Clean up empty arrays to prevent memory leaks and ensure has() works correctly\n\t\tif (subscriptions.length === 0) {\n\t\t\tthis.subscriptions.delete(subscriptionLookupKey);\n\t\t}\n\t}\n\n\thas(subscriptionLookupKey: TradeSubscriptionLookupKey) {\n\t\treturn super.has(subscriptionLookupKey);\n\t}\n}\n\nclass CandleSubscriptionLookup extends SubscriptionLookup {\n\tprivate subscriptions: Map<CandleSubscriptionLookupKey, ApiSubscription> =\n\t\tnew Map();\n\n\tconstructor() {\n\t\tsuper();\n\t}\n\n\tadd(apiSubscription: ApiSubscription): void {\n\t\tthis.subscriptions.set(\n\t\t\tapiSubscription.candleSubscriptionsLookupKey,\n\t\t\tapiSubscription\n\t\t);\n\t}\n\n\tget(\n\t\tsubscriptionLookupKey: CandleSubscriptionLookupKey\n\t): ApiSubscription | null {\n\t\treturn this.subscriptions.get(subscriptionLookupKey) ?? null;\n\t}\n\n\tremove(apiSubscription: ApiSubscription): void {\n\t\tconst subscriptionLookupKey = apiSubscription.candleSubscriptionsLookupKey;\n\t\tthis.subscriptions.delete(subscriptionLookupKey);\n\t}\n\n\thas(subscriptionLookupKey: CandleSubscriptionLookupKey) {\n\t\treturn super.has(subscriptionLookupKey);\n\t}\n}\n\n/**\n * Internal class that manages the complex subscription orchestration logic.\n * This handles subscription sharing, transfer logic, and lifecycle management.\n */\nclass SubscriptionManager {\n\t// Stores all current subscribers\n\tprivate subscribers = new Map<SubscriberId, Subscriber>();\n\n\t// Stores all current subscriptions :: subscribers:subscriptions is N:M (Subscribers may share a subscription but not vice versa)\n\tprivate apiSubscriptions = new Map<ApiSubscriptionId, ApiSubscription>();\n\n\t// Lookup table for any existing subscriptions which have a compatible configuration for a trade subscriber. Can be multiple compatible subscriptions for a trade subscriber.\n\tprivate compatibleTradeSubscriptionLookup = new TradeSubscriptionLookup();\n\n\t// Lookup table for any existing subscriptions which have a compatible configuration for a candle subscriber. Should only be one compatible subscription for a candle subscriber.\n\tprivate compatibleCandleSubscriptionLookup = new CandleSubscriptionLookup();\n\n\t/**\n\t * Handles a new subscription by adding it to the necessary lookup tables\n\t * @param subscription\n\t */\n\tprivate handleNewApiSubscription(subscription: ApiSubscription) {\n\t\tthis.apiSubscriptions.set(subscription.id, subscription);\n\n\t\t// Add to the trade subscription compatibility lookup\n\t\tthis.compatibleTradeSubscriptionLookup.add(subscription);\n\n\t\t// Add to the candle subscription compatibility lookup if a previous one suiting this subscription doesn't already exist\n\t\tif (\n\t\t\t!this.compatibleCandleSubscriptionLookup.has(\n\t\t\t\tsubscription.candleSubscriptionsLookupKey\n\t\t\t)\n\t\t) {\n\t\t\tthis.compatibleCandleSubscriptionLookup.add(subscription);\n\t\t}\n\n\t\tthis.checkForTradeSubscriptionTransferForNewSubscription(subscription);\n\t}\n\n\tprivate transferTradeSubscribersToNewSubscription(\n\t\texistingTradeSubscription: ApiSubscription,\n\t\tnewSubscription: ApiSubscription\n\t) {\n\t\tinvariant(\n\t\t\texistingTradeSubscription.id !== newSubscription.id,\n\t\t\t'Expected different subscriptions when transferring trade subscribers'\n\t\t);\n\t\tinvariant(\n\t\t\texistingTradeSubscription.candleSubscribers.size === 0,\n\t\t\t'Expected existing trade subscription to have no candle subscribers when transferring trade subscribers'\n\t\t);\n\n\t\t// Transfer the subscribers to the new subscription\n\t\tconst tradeSubscribers = Array.from(\n\t\t\texistingTradeSubscription.tradeSubscribers.values()\n\t\t);\n\n\t\tif (tradeSubscribers.length === 0) return; // Skip early if there are no trade subscribers to transfer\n\n\t\tconsole.log(\n\t\t\t`marketDataFeed::transferring_previous_trade_subscribers_to_new_subscription`\n\t\t);\n\n\t\ttradeSubscribers.forEach((tradeSubscriber) => {\n\t\t\tnewSubscription.attachNewTradeSubscriberToExistingSubscription(\n\t\t\t\ttradeSubscriber\n\t\t\t);\n\n\t\t\texistingTradeSubscription.removeSubscriber(tradeSubscriber.id);\n\t\t});\n\t}\n\n\t/**\n\t * When we have a new subscription, we want to check if there is an existing subscription with trade subscribers which should be transferred to the new subscription.\n\t *\n\t * Reasoning:\n\t * - If a TRADE SUBSCRIBER caused a new subscription to be created\n\t * - and then a following CANDLE SUBSCRIBER is created for the same market\n\t * => then it is wasteful to keep the previous trade subscription open, because the new candle subscription can collect the data for both subscribers\n\t *\n\t * @param newSubscription\n\t */\n\tprivate checkForTradeSubscriptionTransferForNewSubscription(\n\t\tnewSubscription: ApiSubscription\n\t) {\n\t\tconst tradeSubscriptionLookupKey =\n\t\t\tnewSubscription.tradeSubscriptionsLookupKey;\n\n\t\tinvariant(\n\t\t\t!!this.compatibleTradeSubscriptionLookup.get(tradeSubscriptionLookupKey),\n\t\t\t`Expect a matching trade subscription when checking for transfers for a new subscription`\n\t\t);\n\n\t\tconst allCompatibleTradeSubscriptions =\n\t\t\tthis.compatibleTradeSubscriptionLookup.getAll(tradeSubscriptionLookupKey);\n\n\t\tfor (const existingTradeSubscription of allCompatibleTradeSubscriptions) {\n\t\t\tif (existingTradeSubscription.id === newSubscription.id) continue; // If the subscription is the current subscription, then there are no subscribers to transfer.\n\t\t\tif (existingTradeSubscription.candleSubscribers.size > 0) continue; // If the existing subscription has candle subscribers, skip doing any transfers because it's not any extra efficient to do so.\n\n\t\t\tthis.transferTradeSubscribersToNewSubscription(\n\t\t\t\texistingTradeSubscription,\n\t\t\t\tnewSubscription\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * When a subscriber unsubscribes and causes the subscription to have some remaining trade subscribers, but no candle subscribers, we want to check if there is another compatible subscription to transfer the trade subscribers to.\n\t * @param apiSubscription\n\t */\n\tprivate checkForSubscriptionTransferOnUnsubscribe(\n\t\tapiSubscription: ApiSubscription\n\t) {\n\t\tif (apiSubscription.tradeSubscribers.size === 0) return; // Skip early if there are no trade subscribers to transfer\n\t\tif (apiSubscription.candleSubscribers.size > 0) return; // Skip early if there are candle subscribers\n\n\t\t// Look for another compatible subscription to transfer the trade subscribers to\n\t\tconst tradeSubscriptionLookupKey =\n\t\t\tapiSubscription.tradeSubscriptionsLookupKey;\n\n\t\t// Get all compatible subscriptions for this market\n\t\tconst compatibleSubscriptions =\n\t\t\tthis.compatibleTradeSubscriptionLookup.getAll(tradeSubscriptionLookupKey);\n\n\t\tif (!compatibleSubscriptions || compatibleSubscriptions.length <= 1) {\n\t\t\t// No other compatible subscriptions available, or only this subscription exists\n\t\t\treturn;\n\t\t}\n\n\t\t// Find a different subscription that can accept the trade subscribers\n\t\tconst targetSubscription = compatibleSubscriptions.find(\n\t\t\t(subscription) => subscription.id !== apiSubscription.id\n\t\t);\n\n\t\tif (!targetSubscription) {\n\t\t\t// No suitable target subscription found\n\t\t\treturn;\n\t\t}\n\n\t\tconsole.log(\n\t\t\t`marketDataFeed::transferring_trade_subscribers_on_unsubscribe`\n\t\t);\n\n\t\t// Transfer all trade subscribers to the target subscription\n\t\tthis.transferTradeSubscribersToNewSubscription(\n\t\t\tapiSubscription,\n\t\t\ttargetSubscription\n\t\t);\n\t}\n\n\tprivate handleNewCandleSubscriber(subscriber: CandleSubscriber) {\n\t\tconst candleSubscriptionLookupKey =\n\t\t\tgetCompatibleCandleSubscriptionLookupKey(subscriber.config);\n\t\tconst hasExistingSuitableSubscription =\n\t\t\tthis.compatibleCandleSubscriptionLookup.has(candleSubscriptionLookupKey);\n\n\t\tif (hasExistingSuitableSubscription) {\n\t\t\tconsole.log(\n\t\t\t\t`marketDataFeed::attaching_new_candle_subscriber_to_existing_subscription`\n\t\t\t);\n\t\t\tconst existingSubscription = this.compatibleCandleSubscriptionLookup.get(\n\t\t\t\tcandleSubscriptionLookupKey\n\t\t\t);\n\t\t\texistingSubscription.attachNewCandleSubscriberToExistingSubscription(\n\t\t\t\tsubscriber\n\t\t\t);\n\t\t} else {\n\t\t\tconsole.log(`marketDataFeed::creating_new_candle_subscription`);\n\t\t\tconst newSubscription = new ApiSubscription(\n\t\t\t\tsubscriber.config.resolution,\n\t\t\t\tsubscriber,\n\t\t\t\tthis.cleanupApiSubscription.bind(this)\n\t\t\t);\n\n\t\t\tthis.handleNewApiSubscription(newSubscription);\n\t\t}\n\n\t\tassert(\n\t\t\tthis.subscribers.has(subscriber.id),\n\t\t\t'Subscriber should be added to subscribers map'\n\t\t);\n\t}\n\n\tprivate handleNewTradeSubscriber(subscriber: TradeSubscriber) {\n\t\t// Check if any existing subscriptions already suit the new subscriber\n\t\tconst tradeSubscriptionLookupKey = getCompatibleTradeSubscriptionLookupKey(\n\t\t\tsubscriber.config\n\t\t);\n\t\tconst hasExistingSuitableSubscription =\n\t\t\tthis.compatibleTradeSubscriptionLookup.has(tradeSubscriptionLookupKey);\n\n\t\tif (hasExistingSuitableSubscription) {\n\t\t\tconsole.log(\n\t\t\t\t`marketDataFeed::attaching_new_trade_subscriber_to_existing_subscription`\n\t\t\t);\n\t\t\tconst existingSubscription = this.compatibleTradeSubscriptionLookup.get(\n\t\t\t\ttradeSubscriptionLookupKey\n\t\t\t);\n\t\t\texistingSubscription.attachNewTradeSubscriberToExistingSubscription(\n\t\t\t\tsubscriber\n\t\t\t);\n\t\t} else {\n\t\t\tconsole.log(`marketDataFeed::creating_new_trade_subscription`);\n\t\t\tconst newSubscription = new ApiSubscription(\n\t\t\t\tDEFAULT_CANDLE_RESOLUTION_FOR_TRADE_SUBSCRIPTIONS,\n\t\t\t\tsubscriber,\n\t\t\t\tthis.cleanupApiSubscription.bind(this)\n\t\t\t);\n\t\t\tthis.handleNewApiSubscription(newSubscription);\n\t\t}\n\n\t\tassert(\n\t\t\tthis.subscribers.has(subscriber.id),\n\t\t\t'Subscriber should be added to subscribers map'\n\t\t);\n\t}\n\n\t/**\n\t * This method gets called when we no longer need an ApiSubscription and can close it down completely.\n\t * @param apiSubscriptionId\n\t */\n\tprivate cleanupApiSubscription(apiSubscriptionId: ApiSubscriptionId) {\n\t\tconst apiSubscription = this.apiSubscriptions.get(apiSubscriptionId);\n\n\t\tinvariant(\n\t\t\tapiSubscription.candleSubscribers.size === 0,\n\t\t\t'Expected api subscription to have no candle subscribers when cleaning up'\n\t\t);\n\t\tinvariant(\n\t\t\tapiSubscription.tradeSubscribers.size === 0,\n\t\t\t'Expected api subscription to have no trade subscribers when cleaning up'\n\t\t);\n\n\t\t// Remove the subscription from the lookup tables\n\t\tthis.compatibleTradeSubscriptionLookup.remove(apiSubscription);\n\t\tthis.compatibleCandleSubscriptionLookup.remove(apiSubscription);\n\n\t\t// We can delete the subscription from the lookup table when we're cleaning up an ApiSubscription\n\t\tthis.apiSubscriptions.delete(apiSubscriptionId);\n\t}\n\n\t/**\n\t * Creates a new subscriber and manages its subscription lifecycle\n\t */\n\tpublic subscribe(\n\t\tconfig: SubscriptionConfig\n\t): CandleSubscriberSubscription | TradeSubscriberSubscription {\n\t\tswitch (config.type) {\n\t\t\tcase 'candles': {\n\t\t\t\t// Create the new Subscriber\n\t\t\t\tconst newSubscriber = new CandleSubscriber(config);\n\n\t\t\t\t// Add to current subscribers\n\t\t\t\tthis.subscribers.set(newSubscriber.id, newSubscriber);\n\n\t\t\t\tthis.handleNewCandleSubscriber(newSubscriber);\n\n\t\t\t\treturn newSubscriber.subscriberSubscription;\n\t\t\t}\n\t\t\tcase 'trades': {\n\t\t\t\t// Create the new Subscriber\n\t\t\t\tconst newSubscriber = new TradeSubscriber(config);\n\n\t\t\t\t// Add to current subscribers\n\t\t\t\tthis.subscribers.set(newSubscriber.id, newSubscriber);\n\n\t\t\t\tthis.handleNewTradeSubscriber(newSubscriber);\n\n\t\t\t\treturn newSubscriber.subscriberSubscription;\n\t\t\t}\n\t\t\tdefault: {\n\t\t\t\tconst _never: never = config;\n\t\t\t\tthrow new Error(`Unknown subscription type: ${_never}`);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Removes a subscriber and cleans up resources as needed\n\t */\n\tpublic unsubscribe(subscriberId: SubscriberId) {\n\t\tconst subscriber = this.subscribers.get(subscriberId);\n\n\t\tif (!subscriber) {\n\t\t\tthrow new Error(`Subscriber not found: ${subscriberId}`);\n\t\t}\n\n\t\tconst apiSubscription = subscriber.subscription;\n\n\t\tapiSubscription.removeSubscriber(subscriberId);\n\n\t\tthis.checkForSubscriptionTransferOnUnsubscribe(apiSubscription);\n\n\t\tthis.subscribers.delete(subscriberId);\n\t}\n}\n\n/**\n * This class will handle subscribing to market data from the Drift Data API's websocket. See https://data.api.drift.trade/playground for more information about the API.\n *\n * It currently supports subscribing to candles and to trades.\n */\nexport class MarketDataFeed {\n\tprivate static subscriptionManager = new SubscriptionManager();\n\n\tconstructor() {}\n\n\t// Function overload, ensures the correct type is returned based on the config type\n\tpublic static subscribe(\n\t\tconfig: CandleSubscriptionConfig\n\t): CandleSubscriberSubscription;\n\tpublic static subscribe(\n\t\tconfig: TradeSubscriptionConfig\n\t): TradeSubscriberSubscription;\n\tpublic static subscribe(\n\t\tconfig: SubscriptionConfig\n\t): CandleSubscriberSubscription | TradeSubscriberSubscription {\n\t\treturn this.subscriptionManager.subscribe(config);\n\t}\n\n\tpublic static unsubscribe(subscriberId: SubscriberId) {\n\t\tthis.subscriptionManager.unsubscribe(subscriberId);\n\t}\n}\n"]}
@@ -0,0 +1,89 @@
1
+ /// <reference types="node" />
2
+ import Redis, { Cluster, RedisOptions } from 'ioredis';
3
+ export declare enum RedisClientPrefix {
4
+ EXCHANGE = "",
5
+ USER_MAP = "usermap-server:",
6
+ DLOB = "dlob:",
7
+ DLOB_HELIUS = "dlob-helius:"
8
+ }
9
+ export declare const getRedisClusterClient: (host: string, port: string, prefix: string, opts?: RedisOptions) => Cluster;
10
+ export declare const getRedisClient: (host: string, port: string, prefix: string, opts?: RedisOptions) => Redis;
11
+ /**
12
+ * Wrapper around the redis client.
13
+ *
14
+ * You can hover over the underlying redis client methods for explanations of the methods, but will also include links to DOCS for some important concepts below:
15
+ *
16
+ * zRange, zRangeByScore etc.:
17
+ * - All of the "z" methods are methods that use sorted sets.
18
+ * - Sorted sets are explained here : https://redis.io/docs/data-types/sorted-sets/
19
+ */
20
+ export declare class RedisClient {
21
+ private client;
22
+ private prefix;
23
+ connectionPromise: Promise<void>;
24
+ constructor({ host, port, prefix, opts, cluster, }: {
25
+ host?: string;
26
+ port?: string;
27
+ prefix?: RedisClientPrefix;
28
+ opts?: RedisOptions;
29
+ cluster?: boolean;
30
+ });
31
+ /**
32
+ * Should avoid using this unless necessary.
33
+ * @returns
34
+ */
35
+ forceGetClient(): Cluster | Redis;
36
+ getPrefix(): RedisClientPrefix;
37
+ get connected(): boolean;
38
+ connect(): Promise<true | void>;
39
+ disconnect(): void;
40
+ private assertConnected;
41
+ /**
42
+ * IMPORTANT NOTE: non-expiring keys will not be cleared up by the eviction policy, so they must be cleared manually
43
+ * @param key
44
+ * @param value
45
+ */
46
+ set(key: string, value: any): Promise<void>;
47
+ setRaw(key: string, value: any): Promise<void>;
48
+ /**
49
+ * IMPORTANT NOTE: non-expiring keys will not be cleared up by the eviction policy, so they must be cleared manually
50
+ * @param key
51
+ * @param value
52
+ */
53
+ mset(values: [string, any][]): Promise<void>;
54
+ setExpiring(key: string, value: any, expirySeconds: number): Promise<"OK">;
55
+ msetExpiring(values: [string, any][], expirySeconds: number): Promise<void>;
56
+ expireKey(key: string, expirySeconds: number): Promise<number>;
57
+ get<T = string | number | Record<string, unknown> | undefined>(key: string): Promise<T>;
58
+ getRaw(key: string): Promise<string>;
59
+ mget(keys: string[]): Promise<any[]>;
60
+ smembers(key: string): Promise<string[]>;
61
+ zRange(key: string, min: number, max: number): Promise<string[]>;
62
+ zRevRange(key: string, start: number, stop: number, withScores?: 'WITHSCORES'): Promise<string[]>;
63
+ zRangeByScore(key: string, min: number | string, max: number | string): Promise<string[]>;
64
+ zRevRangeByScore(key: string, max: number | string, min: number | string): Promise<string[]>;
65
+ zRank(key: string, member: string): Promise<number>;
66
+ zRevRank(key: string, member: string): Promise<number>;
67
+ zRem(key: string, member: string | number | Buffer): Promise<number>;
68
+ zRemRange(key: string, start: number, stop: number): Promise<number>;
69
+ zRemRangeByScore(key: string, start: number, stop: number): Promise<number>;
70
+ zCount(key: string, start: number, stop: number): Promise<number>;
71
+ zCard(key: string): Promise<number>;
72
+ zAdd(key: string, ...scoreMembers: (string | number | Buffer)[]): Promise<number>;
73
+ lPush(key: string, ...elements: (string | number | Buffer)[]): Promise<number>;
74
+ rPush(key: string, ...elements: (string | number | Buffer)[]): Promise<number>;
75
+ lTrim(key: string, start: number, stop: number): Promise<"OK">;
76
+ lRem(key: string, count: number, element: string | number | Buffer): Promise<number>;
77
+ lSet(key: string, index: number, element: string | number | Buffer): Promise<"OK">;
78
+ lRange(key: string, start: number, stop: number): Promise<string[]>;
79
+ lLen(key: string): Promise<number>;
80
+ lIndex(key: string, index: number): Promise<string>;
81
+ publish(key: string, value: any): Promise<number>;
82
+ subscribe(key: string): Promise<unknown>;
83
+ unsubscribe(key: string): Promise<unknown>;
84
+ /**
85
+ * Clears the entire cache of the current DB (not the other DBs in the redis instance)
86
+ */
87
+ flush(): Promise<"OK">;
88
+ delete(...keys: string[]): Promise<number>;
89
+ }