@velocity-exchange/sdk 0.4.0 → 0.6.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 (323) hide show
  1. package/README.md +3 -3
  2. package/lib/browser/adminClient.d.ts +35 -0
  3. package/lib/browser/adminClient.js +65 -0
  4. package/lib/browser/config.js +6 -7
  5. package/lib/browser/constants/numericConstants.d.ts +1 -1
  6. package/lib/browser/constants/numericConstants.js +1 -1
  7. package/lib/browser/decode/user.js +5 -1
  8. package/lib/browser/idl/velocity.d.ts +146 -3
  9. package/lib/browser/idl/velocity.json +147 -4
  10. package/lib/browser/orderSubscriber/OrderSubscriber.js +3 -0
  11. package/lib/browser/pyth/pythLazerSubscriber.js +37 -27
  12. package/lib/browser/types.d.ts +4 -0
  13. package/lib/browser/user.d.ts +15 -0
  14. package/lib/browser/user.js +37 -1
  15. package/lib/browser/velocityClient.d.ts +46 -10
  16. package/lib/browser/velocityClient.js +107 -35
  17. package/lib/node/adminClient.d.ts +35 -0
  18. package/lib/node/adminClient.d.ts.map +1 -1
  19. package/lib/node/adminClient.js +65 -0
  20. package/lib/node/config.d.ts.map +1 -1
  21. package/lib/node/config.js +6 -7
  22. package/lib/node/constants/numericConstants.d.ts +1 -1
  23. package/lib/node/constants/numericConstants.d.ts.map +1 -1
  24. package/lib/node/constants/numericConstants.js +1 -1
  25. package/lib/node/decode/user.d.ts.map +1 -1
  26. package/lib/node/decode/user.js +5 -1
  27. package/lib/node/idl/velocity.d.ts +146 -3
  28. package/lib/node/idl/velocity.d.ts.map +1 -1
  29. package/lib/node/idl/velocity.json +147 -4
  30. package/lib/node/orderSubscriber/OrderSubscriber.d.ts.map +1 -1
  31. package/lib/node/orderSubscriber/OrderSubscriber.js +3 -0
  32. package/lib/node/pyth/pythLazerSubscriber.d.ts.map +1 -1
  33. package/lib/node/pyth/pythLazerSubscriber.js +37 -27
  34. package/lib/node/types.d.ts +4 -0
  35. package/lib/node/types.d.ts.map +1 -1
  36. package/lib/node/user.d.ts +15 -0
  37. package/lib/node/user.d.ts.map +1 -1
  38. package/lib/node/user.js +37 -1
  39. package/lib/node/velocityClient.d.ts +46 -10
  40. package/lib/node/velocityClient.d.ts.map +1 -1
  41. package/lib/node/velocityClient.js +107 -35
  42. package/package.json +7 -3
  43. package/.prettierignore +0 -1
  44. package/CHANGELOG.md +0 -132
  45. package/build-browser.js +0 -58
  46. package/bunfig.toml +0 -3
  47. package/esbuild-shims.js +0 -12
  48. package/scripts/deposit-isolated-positions.ts +0 -110
  49. package/scripts/find-flagged-users.ts +0 -213
  50. package/scripts/grpc-client-test-comparison.ts +0 -372
  51. package/scripts/grpc-multiuser-client-test-comparison.ts +0 -158
  52. package/scripts/postbuild.js +0 -95
  53. package/scripts/single-grpc-client-test.ts +0 -284
  54. package/scripts/withdraw-isolated-positions.ts +0 -174
  55. package/src/accounts/README_WebSocketAccountSubscriberV2.md +0 -95
  56. package/src/accounts/README_WebSocketProgramAccountSubscriberV2.md +0 -135
  57. package/src/accounts/basicUserAccountSubscriber.ts +0 -79
  58. package/src/accounts/basicUserStatsAccountSubscriber.ts +0 -87
  59. package/src/accounts/bulkAccountLoader.ts +0 -358
  60. package/src/accounts/bulkUserStatsSubscription.ts +0 -40
  61. package/src/accounts/bulkUserSubscription.ts +0 -39
  62. package/src/accounts/customizedCadenceBulkAccountLoader.ts +0 -250
  63. package/src/accounts/fetch.ts +0 -200
  64. package/src/accounts/grpcAccountSubscriber.ts +0 -225
  65. package/src/accounts/grpcInsuranceFundStakeAccountSubscriber.ts +0 -73
  66. package/src/accounts/grpcMultiAccountSubscriber.ts +0 -566
  67. package/src/accounts/grpcMultiUserAccountSubscriber.ts +0 -328
  68. package/src/accounts/grpcProgramAccountSubscriber.ts +0 -264
  69. package/src/accounts/grpcUserAccountSubscriber.ts +0 -63
  70. package/src/accounts/grpcUserStatsAccountSubscriber.ts +0 -65
  71. package/src/accounts/grpcVelocityClientAccountSubscriber.ts +0 -257
  72. package/src/accounts/grpcVelocityClientAccountSubscriberV2.ts +0 -941
  73. package/src/accounts/laserProgramAccountSubscriber.ts +0 -266
  74. package/src/accounts/oneShotUserAccountSubscriber.ts +0 -88
  75. package/src/accounts/oneShotUserStatsAccountSubscriber.ts +0 -94
  76. package/src/accounts/pollingInsuranceFundStakeAccountSubscriber.ts +0 -223
  77. package/src/accounts/pollingOracleAccountSubscriber.ts +0 -151
  78. package/src/accounts/pollingTokenAccountSubscriber.ts +0 -147
  79. package/src/accounts/pollingUserAccountSubscriber.ts +0 -198
  80. package/src/accounts/pollingUserStatsAccountSubscriber.ts +0 -180
  81. package/src/accounts/pollingVelocityClientAccountSubscriber.ts +0 -774
  82. package/src/accounts/testBulkAccountLoader.ts +0 -59
  83. package/src/accounts/types.ts +0 -428
  84. package/src/accounts/utils.ts +0 -90
  85. package/src/accounts/webSocketAccountSubscriber.ts +0 -304
  86. package/src/accounts/webSocketAccountSubscriberV2.ts +0 -536
  87. package/src/accounts/webSocketInsuranceFundStakeAccountSubscriber.ts +0 -171
  88. package/src/accounts/webSocketProgramAccountSubscriber.ts +0 -244
  89. package/src/accounts/webSocketProgramAccountSubscriberV2.ts +0 -1048
  90. package/src/accounts/webSocketProgramAccountsSubscriberV2.ts +0 -1042
  91. package/src/accounts/webSocketUserAccountSubscriber.ts +0 -139
  92. package/src/accounts/webSocketUserStatsAccountSubsriber.ts +0 -131
  93. package/src/accounts/webSocketVelocityClientAccountSubscriber.ts +0 -865
  94. package/src/accounts/webSocketVelocityClientAccountSubscriberV2.ts +0 -897
  95. package/src/accounts/websocketProgramUserAccountSubscriber.ts +0 -127
  96. package/src/addresses/marketAddresses.ts +0 -28
  97. package/src/addresses/pda.ts +0 -620
  98. package/src/adminClient.ts +0 -8136
  99. package/src/assert/assert.ts +0 -5
  100. package/src/auctionSubscriber/auctionSubscriber.ts +0 -86
  101. package/src/auctionSubscriber/auctionSubscriberGrpc.ts +0 -99
  102. package/src/auctionSubscriber/index.ts +0 -9
  103. package/src/auctionSubscriber/types.ts +0 -30
  104. package/src/bankrun/bankrunConnection.ts +0 -630
  105. package/src/blockhashSubscriber/BlockhashSubscriber.ts +0 -160
  106. package/src/blockhashSubscriber/index.ts +0 -6
  107. package/src/blockhashSubscriber/types.ts +0 -13
  108. package/src/clock/clockSubscriber.ts +0 -146
  109. package/src/config.ts +0 -312
  110. package/src/constants/index.ts +0 -9
  111. package/src/constants/numericConstants.ts +0 -194
  112. package/src/constants/perpMarkets.ts +0 -127
  113. package/src/constants/spotMarkets.ts +0 -104
  114. package/src/constants/txConstants.ts +0 -2
  115. package/src/constituentMap/constituentMap.ts +0 -305
  116. package/src/constituentMap/pollingConstituentAccountSubscriber.ts +0 -99
  117. package/src/constituentMap/webSocketConstituentAccountSubscriber.ts +0 -121
  118. package/src/core/VelocityCore.ts +0 -606
  119. package/src/core/index.ts +0 -12
  120. package/src/core/instructions/deposit.ts +0 -64
  121. package/src/core/instructions/fill.ts +0 -51
  122. package/src/core/instructions/funding.ts +0 -33
  123. package/src/core/instructions/liquidation.ts +0 -55
  124. package/src/core/instructions/orders.ts +0 -84
  125. package/src/core/instructions/perpOrders.ts +0 -312
  126. package/src/core/instructions/settlement.ts +0 -40
  127. package/src/core/instructions/trigger.ts +0 -41
  128. package/src/core/instructions/withdraw.ts +0 -65
  129. package/src/core/remainingAccounts.ts +0 -320
  130. package/src/core/signedMsg.ts +0 -109
  131. package/src/decode/customCoder.ts +0 -148
  132. package/src/decode/user.ts +0 -401
  133. package/src/dlob/DLOB.ts +0 -2793
  134. package/src/dlob/DLOBNode.ts +0 -305
  135. package/src/dlob/DLOBSubscriber.ts +0 -269
  136. package/src/dlob/NodeList.ts +0 -244
  137. package/src/dlob/orderBookLevels.ts +0 -695
  138. package/src/dlob/types.ts +0 -37
  139. package/src/events/eventList.ts +0 -114
  140. package/src/events/eventSubscriber.ts +0 -521
  141. package/src/events/eventsServerLogProvider.ts +0 -189
  142. package/src/events/fetchLogs.ts +0 -219
  143. package/src/events/parse.ts +0 -271
  144. package/src/events/pollingLogProvider.ts +0 -113
  145. package/src/events/sort.ts +0 -51
  146. package/src/events/txEventCache.ts +0 -92
  147. package/src/events/types.ts +0 -337
  148. package/src/events/webSocketLogProvider.ts +0 -152
  149. package/src/factory/bigNum.ts +0 -709
  150. package/src/factory/oracleClient.ts +0 -73
  151. package/src/idl/pyth.json +0 -142
  152. package/src/idl/pyth.ts +0 -97
  153. package/src/idl/pyth_solana_receiver.json +0 -628
  154. package/src/idl/token_faucet.json +0 -229
  155. package/src/idl/token_faucet.ts +0 -197
  156. package/src/idl/velocity.json +0 -23974
  157. package/src/idl/velocity.ts +0 -23980
  158. package/src/index.ts +0 -150
  159. package/src/indicative-quotes/indicativeQuotesSender.ts +0 -233
  160. package/src/isomorphic/README.md +0 -19
  161. package/src/isomorphic/anchor.browser.ts +0 -44
  162. package/src/isomorphic/anchor.node.ts +0 -1
  163. package/src/isomorphic/anchor.ts +0 -1
  164. package/src/isomorphic/anchor29.browser.ts +0 -24
  165. package/src/isomorphic/anchor29.node.ts +0 -1
  166. package/src/isomorphic/anchor29.ts +0 -1
  167. package/src/isomorphic/grpc.browser.ts +0 -4
  168. package/src/isomorphic/grpc.node.ts +0 -130
  169. package/src/isomorphic/grpc.ts +0 -1
  170. package/src/jupiter/jupiterClient.ts +0 -502
  171. package/src/keypair.ts +0 -32
  172. package/src/margin/README.md +0 -138
  173. package/src/marginCalculation.ts +0 -407
  174. package/src/marinade/idl/idl.json +0 -1962
  175. package/src/marinade/index.ts +0 -73
  176. package/src/marinade/types.ts +0 -3925
  177. package/src/math/amm.ts +0 -1758
  178. package/src/math/auction.ts +0 -480
  179. package/src/math/bankruptcy.ts +0 -138
  180. package/src/math/builder.ts +0 -130
  181. package/src/math/conversion.ts +0 -45
  182. package/src/math/exchangeStatus.ts +0 -261
  183. package/src/math/funding.ts +0 -498
  184. package/src/math/insurance.ts +0 -171
  185. package/src/math/liquidation.ts +0 -433
  186. package/src/math/margin.ts +0 -327
  187. package/src/math/market.ts +0 -487
  188. package/src/math/oracles.ts +0 -477
  189. package/src/math/orders.ts +0 -500
  190. package/src/math/position.ts +0 -381
  191. package/src/math/repeg.ts +0 -223
  192. package/src/math/spotBalance.ts +0 -996
  193. package/src/math/spotMarket.ts +0 -115
  194. package/src/math/spotPosition.ts +0 -263
  195. package/src/math/state.ts +0 -71
  196. package/src/math/superStake.ts +0 -602
  197. package/src/math/tiers.ts +0 -73
  198. package/src/math/trade.ts +0 -879
  199. package/src/math/utils.ts +0 -183
  200. package/src/memcmp.ts +0 -279
  201. package/src/oracles/oracleClientCache.ts +0 -41
  202. package/src/oracles/oracleId.ts +0 -99
  203. package/src/oracles/prelaunchOracleClient.ts +0 -63
  204. package/src/oracles/pythClient.ts +0 -125
  205. package/src/oracles/pythLazerClient.ts +0 -141
  206. package/src/oracles/quoteAssetOracleClient.ts +0 -43
  207. package/src/oracles/strictOraclePrice.ts +0 -40
  208. package/src/oracles/types.ts +0 -82
  209. package/src/oracles/utils.ts +0 -45
  210. package/src/orderParams.ts +0 -117
  211. package/src/orderSubscriber/OrderSubscriber.ts +0 -378
  212. package/src/orderSubscriber/PollingSubscription.ts +0 -50
  213. package/src/orderSubscriber/WebsocketSubscription.ts +0 -137
  214. package/src/orderSubscriber/grpcSubscription.ts +0 -155
  215. package/src/orderSubscriber/index.ts +0 -7
  216. package/src/orderSubscriber/types.ts +0 -64
  217. package/src/priorityFee/averageOverSlotsStrategy.ts +0 -17
  218. package/src/priorityFee/averageStrategy.ts +0 -13
  219. package/src/priorityFee/ewmaStrategy.ts +0 -51
  220. package/src/priorityFee/heliusPriorityFeeMethod.ts +0 -68
  221. package/src/priorityFee/index.ts +0 -16
  222. package/src/priorityFee/maxOverSlotsStrategy.ts +0 -18
  223. package/src/priorityFee/maxStrategy.ts +0 -8
  224. package/src/priorityFee/priorityFeeSubscriber.ts +0 -328
  225. package/src/priorityFee/priorityFeeSubscriberMap.ts +0 -134
  226. package/src/priorityFee/solanaPriorityFeeMethod.ts +0 -46
  227. package/src/priorityFee/types.ts +0 -82
  228. package/src/priorityFee/velocityPriorityFeeMethod.ts +0 -53
  229. package/src/pyth/constants.ts +0 -9
  230. package/src/pyth/index.ts +0 -15
  231. package/src/pyth/pythLazerSubscriber.ts +0 -365
  232. package/src/pyth/types.ts +0 -4451
  233. package/src/pyth/utils.ts +0 -13
  234. package/src/slot/SlotSubscriber.ts +0 -126
  235. package/src/slot/SlothashSubscriber.ts +0 -163
  236. package/src/swap/UnifiedSwapClient.ts +0 -315
  237. package/src/swift/grpcSignedMsgUserAccountSubscriber.ts +0 -81
  238. package/src/swift/index.ts +0 -10
  239. package/src/swift/signedMsgUserAccountSubscriber.ts +0 -251
  240. package/src/swift/swiftOrderSubscriber.ts +0 -351
  241. package/src/testClient.ts +0 -42
  242. package/src/titan/titanClient.ts +0 -438
  243. package/src/token/index.ts +0 -13
  244. package/src/tokenFaucet.ts +0 -296
  245. package/src/tx/baseTxSender.ts +0 -651
  246. package/src/tx/blockhashFetcher/baseBlockhashFetcher.ts +0 -31
  247. package/src/tx/blockhashFetcher/cachedBlockhashFetcher.ts +0 -105
  248. package/src/tx/blockhashFetcher/types.ts +0 -9
  249. package/src/tx/fastSingleTxSender.ts +0 -200
  250. package/src/tx/forwardOnlyTxSender.ts +0 -193
  251. package/src/tx/priorityFeeCalculator.ts +0 -117
  252. package/src/tx/reportTransactionError.ts +0 -176
  253. package/src/tx/retryTxSender.ts +0 -177
  254. package/src/tx/txHandler.ts +0 -1009
  255. package/src/tx/txParamProcessor.ts +0 -225
  256. package/src/tx/types.ts +0 -117
  257. package/src/tx/utils.ts +0 -133
  258. package/src/tx/whileValidTxSender.ts +0 -377
  259. package/src/types.ts +0 -2575
  260. package/src/user.ts +0 -5316
  261. package/src/userConfig.ts +0 -38
  262. package/src/userMap/PollingSubscription.ts +0 -61
  263. package/src/userMap/WebsocketSubscription.ts +0 -93
  264. package/src/userMap/grpcSubscription.ts +0 -93
  265. package/src/userMap/referrerMap.ts +0 -360
  266. package/src/userMap/revenueShareEscrowMap.ts +0 -342
  267. package/src/userMap/userMap.ts +0 -784
  268. package/src/userMap/userMapConfig.ts +0 -82
  269. package/src/userMap/userStatsMap.ts +0 -393
  270. package/src/userName.ts +0 -37
  271. package/src/userStats.ts +0 -159
  272. package/src/userStatsConfig.ts +0 -35
  273. package/src/util/TransactionConfirmationManager.ts +0 -333
  274. package/src/util/chainClock.ts +0 -65
  275. package/src/util/computeUnits.ts +0 -101
  276. package/src/util/digest.ts +0 -33
  277. package/src/util/ed25519Utils.ts +0 -95
  278. package/src/util/promiseTimeout.ts +0 -23
  279. package/src/velocityClient.ts +0 -14802
  280. package/src/velocityClientConfig.ts +0 -119
  281. package/src/wallet.ts +0 -91
  282. package/tests/VelocityCore/builder_escrow.test.ts +0 -121
  283. package/tests/VelocityCore/decode.test.ts +0 -16
  284. package/tests/VelocityCore/fill_trigger.test.ts +0 -73
  285. package/tests/VelocityCore/instructions.test.ts +0 -46
  286. package/tests/VelocityCore/pdas.test.ts +0 -30
  287. package/tests/VelocityCore/perp_orders.test.ts +0 -205
  288. package/tests/VelocityCore/remainingAccounts.test.ts +0 -72
  289. package/tests/VelocityCore/settlement_liquidation.test.ts +0 -69
  290. package/tests/accounts/customizedCadenceBulkAccountLoader.test.ts +0 -211
  291. package/tests/amm/test.ts +0 -2402
  292. package/tests/auctions/test.ts +0 -81
  293. package/tests/bn/test.ts +0 -355
  294. package/tests/builder/builderFee.test.ts +0 -42
  295. package/tests/ci/verifyConstants.ts +0 -393
  296. package/tests/decode/test.ts +0 -262
  297. package/tests/decode/userAccountBufferStrings.ts +0 -102
  298. package/tests/dlob/helpers.ts +0 -748
  299. package/tests/dlob/test.ts +0 -6969
  300. package/tests/dlob/tickSizeStandardization.ts +0 -545
  301. package/tests/events/parseLogsForCuUsage.ts +0 -139
  302. package/tests/exchangeStatus/test.ts +0 -45
  303. package/tests/insurance/test.ts +0 -40
  304. package/tests/liquidation/test.ts +0 -125
  305. package/tests/oracles/mmOracleGate.test.ts +0 -379
  306. package/tests/oracles/pythPegSnap.test.ts +0 -76
  307. package/tests/sdkParity/enumParity.test.ts +0 -84
  308. package/tests/sdkParity/marginCategoryFill.test.ts +0 -143
  309. package/tests/sdkParity/memcmpOffsets.test.ts +0 -139
  310. package/tests/spot/test.ts +0 -281
  311. package/tests/tx/TransactionConfirmationManager.test.ts +0 -312
  312. package/tests/tx/cachedBlockhashFetcher.test.ts +0 -96
  313. package/tests/tx/priorityFeeCalculator.ts +0 -77
  314. package/tests/tx/priorityFeeStrategy.ts +0 -95
  315. package/tests/user/bankruptcy.ts +0 -165
  316. package/tests/user/feeAndWithdrawLimits.ts +0 -284
  317. package/tests/user/getMarginCalculation.ts +0 -586
  318. package/tests/user/helpers.ts +0 -184
  319. package/tests/user/liquidations.ts +0 -129
  320. package/tests/user/marginCalculations.test.ts +0 -321
  321. package/tests/user/test.ts +0 -833
  322. package/tsconfig.browser.json +0 -18
  323. package/tsconfig.json +0 -36
@@ -1,774 +0,0 @@
1
- import {
2
- AccountToPoll,
3
- DataAndSlot,
4
- DelistedMarketSetting,
5
- VelocityClientAccountEvents,
6
- VelocityClientAccountSubscriber,
7
- NotSubscribedError,
8
- OraclesToPoll,
9
- } from './types';
10
- import StrictEventEmitter from 'strict-event-emitter-types';
11
- import { EventEmitter } from 'events';
12
- import {
13
- PerpMarketAccount,
14
- SpotMarketAccount,
15
- StateAccount,
16
- UserAccount,
17
- OracleSource,
18
- } from '../types';
19
- import {
20
- getVelocityStateAccountPublicKey,
21
- getPerpMarketPublicKey,
22
- getSpotMarketPublicKey,
23
- } from '../addresses/pda';
24
- import { BulkAccountLoader } from './bulkAccountLoader';
25
- import { findDelistedPerpMarketsAndOracles } from './utils';
26
- import { PublicKey } from '@solana/web3.js';
27
- import { OracleInfo, OraclePriceData } from '../oracles/types';
28
- import { OracleClientCache } from '../oracles/oracleClientCache';
29
- import { QUOTE_ORACLE_PRICE_DATA } from '../oracles/quoteAssetOracleClient';
30
- import { findAllMarketAndOracles, VelocityProgram } from '../config';
31
- import { getOracleId } from '../oracles/oracleId';
32
-
33
- const ORACLE_DEFAULT_ID = getOracleId(
34
- PublicKey.default,
35
- OracleSource.QUOTE_ASSET
36
- );
37
-
38
- /**
39
- * `VelocityClientAccountSubscriber` that batches the `State`, every tracked `PerpMarket`/
40
- * `SpotMarket`, and every tracked oracle behind a single `BulkAccountLoader` instead of one
41
- * WebSocket subscription per account. Cheaper on connection count at the cost of update latency
42
- * bounded by the loader's poll interval. `subscribe()` retries the initial load up to 5 times
43
- * before giving up (returning `false`) if the `State` account never appears — `didSubscriptionSucceed`
44
- * checks only for `state`, since market/oracle data can be added incrementally afterward via
45
- * `addPerpMarket`/`addSpotMarket`/`addOracle`.
46
- */
47
- export class PollingVelocityClientAccountSubscriber
48
- implements VelocityClientAccountSubscriber
49
- {
50
- isSubscribed: boolean;
51
- program: VelocityProgram;
52
- perpMarketIndexes: number[];
53
- spotMarketIndexes: number[];
54
- oracleInfos: OracleInfo[];
55
- oracleClientCache = new OracleClientCache();
56
-
57
- shouldFindAllMarketsAndOracles: boolean;
58
-
59
- eventEmitter: StrictEventEmitter<EventEmitter, VelocityClientAccountEvents>;
60
-
61
- accountLoader: BulkAccountLoader;
62
- accountsToPoll = new Map<string, AccountToPoll>();
63
- oraclesToPoll = new Map<string, OraclesToPoll>();
64
- errorCallbackId?: string;
65
-
66
- state?: DataAndSlot<StateAccount>;
67
- perpMarket = new Map<number, DataAndSlot<PerpMarketAccount>>();
68
- perpOracleMap = new Map<number, PublicKey>();
69
- perpOracleStringMap = new Map<number, string>();
70
- spotMarket = new Map<number, DataAndSlot<SpotMarketAccount>>();
71
- spotOracleMap = new Map<number, PublicKey>();
72
- spotOracleStringMap = new Map<number, string>();
73
- oracles = new Map<string, DataAndSlot<OraclePriceData>>();
74
- user?: DataAndSlot<UserAccount>;
75
- delistedMarketSetting: DelistedMarketSetting;
76
-
77
- private isSubscribing = false;
78
- private subscriptionPromiseResolver: (val: boolean) => void = () => {};
79
- private subscriptionPromise: Promise<boolean> = new Promise((res) => {
80
- this.subscriptionPromiseResolver = res;
81
- });
82
-
83
- /**
84
- * @param program Anchor program used to derive PDAs, decode accounts, and resolve oracle clients.
85
- * @param accountLoader Shared `BulkAccountLoader` all state/market/oracle accounts are registered with.
86
- * @param perpMarketIndexes Perp market indexes to track, if `shouldFindAllMarketsAndOracles` is false.
87
- * @param spotMarketIndexes Spot market indexes to track, if `shouldFindAllMarketsAndOracles` is false.
88
- * @param oracleInfos Oracles to track up front, if `shouldFindAllMarketsAndOracles` is false.
89
- * @param shouldFindAllMarketsAndOracles If true, `subscribe()` first discovers every market/oracle from on-chain state, ignoring the index/info args above.
90
- * @param delistedMarketSetting Behavior applied to delisted perp markets/oracles after subscribing; see `DelistedMarketSetting`.
91
- */
92
- public constructor(
93
- program: VelocityProgram,
94
- accountLoader: BulkAccountLoader,
95
- perpMarketIndexes: number[],
96
- spotMarketIndexes: number[],
97
- oracleInfos: OracleInfo[],
98
- shouldFindAllMarketsAndOracles: boolean,
99
- delistedMarketSetting: DelistedMarketSetting
100
- ) {
101
- this.isSubscribed = false;
102
- this.program = program;
103
- this.eventEmitter = new EventEmitter();
104
- this.accountLoader = accountLoader;
105
- this.perpMarketIndexes = perpMarketIndexes;
106
- this.spotMarketIndexes = spotMarketIndexes;
107
- this.oracleInfos = oracleInfos;
108
- this.shouldFindAllMarketsAndOracles = shouldFindAllMarketsAndOracles;
109
- this.delistedMarketSetting = delistedMarketSetting;
110
- }
111
-
112
- /**
113
- * Registers state/market/oracle accounts with the `BulkAccountLoader` and retries the initial
114
- * load up to 5 times until the `State` account has appeared. Idempotent: a no-op if already
115
- * subscribed, and concurrent calls while a subscribe is in flight share the same result via
116
- * `subscriptionPromise` rather than issuing duplicate loads.
117
- * @returns `true` if `State` account data loaded within the retry budget, `false` otherwise.
118
- */
119
- public async subscribe(): Promise<boolean> {
120
- if (this.isSubscribed) {
121
- return true;
122
- }
123
-
124
- if (this.isSubscribing) {
125
- return await this.subscriptionPromise;
126
- }
127
-
128
- this.isSubscribing = true;
129
-
130
- this.subscriptionPromise = new Promise((res) => {
131
- this.subscriptionPromiseResolver = res;
132
- });
133
-
134
- if (this.shouldFindAllMarketsAndOracles) {
135
- const { perpMarketIndexes, spotMarketIndexes, oracleInfos } =
136
- await findAllMarketAndOracles(this.program);
137
- this.perpMarketIndexes = perpMarketIndexes;
138
- this.spotMarketIndexes = spotMarketIndexes;
139
- this.oracleInfos = oracleInfos;
140
- }
141
-
142
- await this.updateAccountsToPoll();
143
- this.updateOraclesToPoll();
144
- await this.addToAccountLoader();
145
-
146
- let subscriptionSucceeded = false;
147
- let retries = 0;
148
- while (!subscriptionSucceeded && retries < 5) {
149
- await this.fetch();
150
- subscriptionSucceeded = this.didSubscriptionSucceed();
151
- retries++;
152
- }
153
-
154
- if (subscriptionSucceeded) {
155
- this.eventEmitter.emit('update');
156
- }
157
-
158
- this.handleDelistedMarkets();
159
-
160
- await Promise.all([this.setPerpOracleMap(), this.setSpotOracleMap()]);
161
-
162
- this.isSubscribing = false;
163
- this.isSubscribed = subscriptionSucceeded;
164
- this.subscriptionPromiseResolver(subscriptionSucceeded);
165
-
166
- return subscriptionSucceeded;
167
- }
168
-
169
- async updateAccountsToPoll(): Promise<void> {
170
- if (this.accountsToPoll.size > 0) {
171
- return;
172
- }
173
-
174
- const statePublicKey = await getVelocityStateAccountPublicKey(
175
- this.program.programId
176
- );
177
-
178
- this.accountsToPoll.set(statePublicKey.toString(), {
179
- key: 'state',
180
- publicKey: statePublicKey,
181
- eventType: 'stateAccountUpdate',
182
- });
183
-
184
- await Promise.all([
185
- this.updatePerpMarketAccountsToPoll(),
186
- this.updateSpotMarketAccountsToPoll(),
187
- ]);
188
- }
189
-
190
- async updatePerpMarketAccountsToPoll(): Promise<boolean> {
191
- await Promise.all(
192
- this.perpMarketIndexes.map((marketIndex) => {
193
- return this.addPerpMarketAccountToPoll(marketIndex);
194
- })
195
- );
196
- return true;
197
- }
198
-
199
- async addPerpMarketAccountToPoll(marketIndex: number): Promise<boolean> {
200
- const perpMarketPublicKey = await getPerpMarketPublicKey(
201
- this.program.programId,
202
- marketIndex
203
- );
204
-
205
- this.accountsToPoll.set(perpMarketPublicKey.toString(), {
206
- key: 'perpMarket',
207
- publicKey: perpMarketPublicKey,
208
- eventType: 'perpMarketAccountUpdate',
209
- mapKey: marketIndex,
210
- });
211
-
212
- return true;
213
- }
214
-
215
- async updateSpotMarketAccountsToPoll(): Promise<boolean> {
216
- await Promise.all(
217
- this.spotMarketIndexes.map(async (marketIndex) => {
218
- await this.addSpotMarketAccountToPoll(marketIndex);
219
- })
220
- );
221
-
222
- return true;
223
- }
224
-
225
- async addSpotMarketAccountToPoll(marketIndex: number): Promise<boolean> {
226
- const marketPublicKey = await getSpotMarketPublicKey(
227
- this.program.programId,
228
- marketIndex
229
- );
230
-
231
- this.accountsToPoll.set(marketPublicKey.toString(), {
232
- key: 'spotMarket',
233
- publicKey: marketPublicKey,
234
- eventType: 'spotMarketAccountUpdate',
235
- mapKey: marketIndex,
236
- });
237
- return true;
238
- }
239
-
240
- updateOraclesToPoll(): boolean {
241
- for (const oracleInfo of this.oracleInfos) {
242
- if (!oracleInfo.publicKey.equals(PublicKey.default)) {
243
- this.addOracleToPoll(oracleInfo);
244
- }
245
- }
246
-
247
- return true;
248
- }
249
-
250
- addOracleToPoll(oracleInfo: OracleInfo): boolean {
251
- this.oraclesToPoll.set(
252
- getOracleId(oracleInfo.publicKey, oracleInfo.source),
253
- {
254
- publicKey: oracleInfo.publicKey,
255
- source: oracleInfo.source,
256
- }
257
- );
258
-
259
- return true;
260
- }
261
- async addToAccountLoader(): Promise<void> {
262
- const accountPromises = [];
263
- for (const [_, accountToPoll] of this.accountsToPoll) {
264
- accountPromises.push(this.addAccountToAccountLoader(accountToPoll));
265
- }
266
-
267
- const oraclePromises = [];
268
- for (const [_, oracleToPoll] of this.oraclesToPoll) {
269
- oraclePromises.push(this.addOracleToAccountLoader(oracleToPoll));
270
- }
271
-
272
- await Promise.all([...accountPromises, ...oraclePromises]);
273
-
274
- this.errorCallbackId = this.accountLoader.addErrorCallbacks((error) => {
275
- this.eventEmitter.emit('error', error);
276
- });
277
- }
278
-
279
- /**
280
- * Routes a freshly-decoded account into the correct container based on
281
- * its poll key. Replaces dynamic `this[key]` indexing with explicit,
282
- * type-checked dispatch.
283
- */
284
- private storeDecodedAccount(
285
- accountToPoll: AccountToPoll,
286
- account: any,
287
- slot: number
288
- ): void {
289
- const dataAndSlot = { data: account, slot };
290
- switch (accountToPoll.key) {
291
- case 'perpMarket':
292
- if (accountToPoll.mapKey !== undefined) {
293
- this.perpMarket.set(accountToPoll.mapKey, dataAndSlot);
294
- }
295
- break;
296
- case 'spotMarket':
297
- if (accountToPoll.mapKey !== undefined) {
298
- this.spotMarket.set(accountToPoll.mapKey, dataAndSlot);
299
- }
300
- break;
301
- case 'state':
302
- this.state = dataAndSlot;
303
- break;
304
- default: {
305
- const _exhaustive: never = accountToPoll.key;
306
- throw new Error(`Unhandled account poll key: ${String(_exhaustive)}`);
307
- }
308
- }
309
- }
310
-
311
- async addAccountToAccountLoader(accountToPoll: AccountToPoll): Promise<void> {
312
- accountToPoll.callbackId = await this.accountLoader.addAccount(
313
- accountToPoll.publicKey,
314
- (buffer: Buffer, slot: number) => {
315
- if (!buffer) return;
316
-
317
- const account = this.program.coder.accounts.decodeUnchecked(
318
- accountToPoll.key,
319
- buffer
320
- );
321
- this.storeDecodedAccount(accountToPoll, account, slot);
322
-
323
- // @ts-ignore
324
- this.eventEmitter.emit(accountToPoll.eventType, account);
325
- this.eventEmitter.emit('update');
326
-
327
- if (!this.isSubscribed) {
328
- this.isSubscribed = this.didSubscriptionSucceed();
329
- }
330
- }
331
- );
332
- }
333
-
334
- async addOracleToAccountLoader(oracleToPoll: OraclesToPoll): Promise<void> {
335
- const oracleClient = this.oracleClientCache.get(
336
- oracleToPoll.source,
337
- this.program.provider.connection,
338
- this.program
339
- );
340
-
341
- const oracleId = getOracleId(oracleToPoll.publicKey, oracleToPoll.source);
342
-
343
- oracleToPoll.callbackId = await this.accountLoader.addAccount(
344
- oracleToPoll.publicKey,
345
- (buffer: Buffer, slot: number) => {
346
- if (!buffer) return;
347
- if (!oracleClient) return;
348
-
349
- const oraclePriceData =
350
- oracleClient.getOraclePriceDataFromBuffer(buffer);
351
- const dataAndSlot = {
352
- data: oraclePriceData,
353
- slot,
354
- };
355
-
356
- this.oracles.set(oracleId, dataAndSlot);
357
-
358
- this.eventEmitter.emit(
359
- 'oraclePriceUpdate',
360
- oracleToPoll.publicKey,
361
- oracleToPoll.source,
362
- oraclePriceData
363
- );
364
- this.eventEmitter.emit('update');
365
- }
366
- );
367
- }
368
-
369
- /** Forces the shared `BulkAccountLoader` to load, then re-decodes every tracked state/market/oracle account from the loader's cached buffers into this subscriber's maps. */
370
- public async fetch(): Promise<void> {
371
- await this.accountLoader.load();
372
- for (const [_, accountToPoll] of this.accountsToPoll) {
373
- const bufferAndSlot = this.accountLoader.getBufferAndSlot(
374
- accountToPoll.publicKey
375
- );
376
-
377
- if (!bufferAndSlot) {
378
- continue;
379
- }
380
-
381
- const { buffer, slot } = bufferAndSlot;
382
-
383
- if (buffer) {
384
- const account = this.program.coder.accounts.decodeUnchecked(
385
- accountToPoll.key,
386
- buffer
387
- );
388
- this.storeDecodedAccount(accountToPoll, account, slot);
389
- }
390
- }
391
-
392
- for (const [_, oracleToPoll] of this.oraclesToPoll) {
393
- const bufferAndSlot = this.accountLoader.getBufferAndSlot(
394
- oracleToPoll.publicKey
395
- );
396
-
397
- if (!bufferAndSlot) {
398
- continue;
399
- }
400
-
401
- const { buffer, slot } = bufferAndSlot;
402
-
403
- if (buffer) {
404
- const oracleClient = this.oracleClientCache.get(
405
- oracleToPoll.source,
406
- this.program.provider.connection,
407
- this.program
408
- );
409
- if (!oracleClient) {
410
- continue;
411
- }
412
- const oraclePriceData =
413
- oracleClient.getOraclePriceDataFromBuffer(buffer);
414
- this.oracles.set(
415
- getOracleId(oracleToPoll.publicKey, oracleToPoll.source),
416
- {
417
- data: oraclePriceData,
418
- slot,
419
- }
420
- );
421
- }
422
- }
423
- }
424
-
425
- /** True once the `State` account has loaded, independent of `isSubscribed`. Market/oracle data is not required. */
426
- didSubscriptionSucceed(): boolean {
427
- if (this.state) return true;
428
-
429
- return false;
430
- }
431
-
432
- /** Removes every tracked state/market/oracle account and the error callback from the `BulkAccountLoader`, then clears internal maps. */
433
- public async unsubscribe(): Promise<void> {
434
- for (const [_, accountToPoll] of this.accountsToPoll) {
435
- this.accountLoader.removeAccount(
436
- accountToPoll.publicKey,
437
- accountToPoll.callbackId
438
- );
439
- }
440
-
441
- for (const [_, oracleToPoll] of this.oraclesToPoll) {
442
- this.accountLoader.removeAccount(
443
- oracleToPoll.publicKey,
444
- oracleToPoll.callbackId
445
- );
446
- }
447
-
448
- this.accountLoader.removeErrorCallbacks(this.errorCallbackId);
449
- this.errorCallbackId = undefined;
450
-
451
- this.accountsToPoll.clear();
452
- this.oraclesToPoll.clear();
453
- this.isSubscribed = false;
454
- }
455
-
456
- /**
457
- * Adds a spot market (and its oracle, via `setSpotOracleMap`) to be tracked, registering it
458
- * with the `BulkAccountLoader`. Idempotent: returns `true` immediately if already tracked.
459
- * @param marketIndex Spot market index to start tracking.
460
- */
461
- async addSpotMarket(marketIndex: number): Promise<boolean> {
462
- const marketPublicKey = await getSpotMarketPublicKey(
463
- this.program.programId,
464
- marketIndex
465
- );
466
-
467
- if (this.accountsToPoll.has(marketPublicKey.toString())) {
468
- return true;
469
- }
470
-
471
- await this.addSpotMarketAccountToPoll(marketIndex);
472
-
473
- const accountToPoll = this.accountsToPoll.get(marketPublicKey.toString());
474
- if (!accountToPoll) {
475
- return false;
476
- }
477
-
478
- await this.addAccountToAccountLoader(accountToPoll);
479
- await this.setSpotOracleMap();
480
- return true;
481
- }
482
-
483
- /**
484
- * Adds a perp market (and its oracle, via `setPerpOracleMap`) to be tracked, registering it
485
- * with the `BulkAccountLoader`. Idempotent: returns `true` immediately if already tracked.
486
- * @param marketIndex Perp market index to start tracking.
487
- */
488
- async addPerpMarket(marketIndex: number): Promise<boolean> {
489
- const marketPublicKey = await getPerpMarketPublicKey(
490
- this.program.programId,
491
- marketIndex
492
- );
493
-
494
- if (this.accountsToPoll.has(marketPublicKey.toString())) {
495
- return true;
496
- }
497
-
498
- await this.addPerpMarketAccountToPoll(marketIndex);
499
- const accountToPoll = this.accountsToPoll.get(marketPublicKey.toString());
500
- if (!accountToPoll) {
501
- return false;
502
- }
503
- await this.addAccountToAccountLoader(accountToPoll);
504
- await this.setPerpOracleMap();
505
- return true;
506
- }
507
-
508
- /**
509
- * Adds an oracle to be tracked, registering it with the `BulkAccountLoader` and waiting
510
- * (polling up to 3 times at `accountLoader.pollingFrequency` intervals) for it to appear in
511
- * the loader's buffer map before resolving. A no-op that resolves `true` immediately for the
512
- * `PublicKey.default` sentinel (quote-asset "no oracle") or an oracle already tracked.
513
- * @param oracleInfo Oracle pubkey and source to start tracking.
514
- */
515
- async addOracle(oracleInfo: OracleInfo): Promise<boolean> {
516
- const oracleId = getOracleId(oracleInfo.publicKey, oracleInfo.source);
517
- if (
518
- oracleInfo.publicKey.equals(PublicKey.default) ||
519
- this.oracles.has(oracleId)
520
- ) {
521
- return true;
522
- }
523
-
524
- // this func can be called multiple times before the first pauseForOracleToBeAdded finishes
525
- // avoid adding to oraclesToPoll multiple time
526
- if (!this.oraclesToPoll.has(oracleId)) {
527
- this.addOracleToPoll(oracleInfo);
528
- const oracleToPoll = this.oraclesToPoll.get(oracleId);
529
- if (oracleToPoll) {
530
- await this.addOracleToAccountLoader(oracleToPoll);
531
- }
532
- }
533
-
534
- await this.pauseForOracleToBeAdded(3, oracleInfo.publicKey.toBase58());
535
-
536
- return true;
537
- }
538
-
539
- private async pauseForOracleToBeAdded(
540
- tries: number,
541
- oracle: string
542
- ): Promise<void> {
543
- let i = 0;
544
- while (i < tries) {
545
- await new Promise((r) =>
546
- setTimeout(r, this.accountLoader.pollingFrequency)
547
- );
548
- if (this.accountLoader.bufferAndSlotMap.has(oracle)) {
549
- return;
550
- }
551
- i++;
552
- }
553
- console.log(`Pausing to find oracle ${oracle} failed`);
554
- }
555
-
556
- /** Rebuilds `perpOracleMap`/`perpOracleStringMap` from currently cached perp markets, calling `addOracle` for any oracle not yet tracked. */
557
- async setPerpOracleMap() {
558
- const perpMarkets = this.getMarketAccountsAndSlots();
559
- const oraclePromises = [];
560
- for (const perpMarket of perpMarkets) {
561
- const perpMarketAccount = perpMarket.data;
562
- const perpMarketIndex = perpMarketAccount.marketIndex;
563
- const oracle = perpMarketAccount.oracle;
564
- const oracleId = getOracleId(oracle, perpMarketAccount.oracleSource);
565
- if (!this.oracles.has(oracleId)) {
566
- oraclePromises.push(
567
- this.addOracle({
568
- publicKey: oracle,
569
- source: perpMarketAccount.oracleSource,
570
- })
571
- );
572
- }
573
- this.perpOracleMap.set(perpMarketIndex, oracle);
574
- this.perpOracleStringMap.set(perpMarketIndex, oracleId);
575
- }
576
- await Promise.all(oraclePromises);
577
- }
578
-
579
- /** Rebuilds `spotOracleMap`/`spotOracleStringMap` from currently cached spot markets, calling `addOracle` for any oracle not yet tracked. */
580
- async setSpotOracleMap() {
581
- const spotMarkets = this.getSpotMarketAccountsAndSlots();
582
- const oraclePromises = [];
583
- for (const spotMarket of spotMarkets) {
584
- const spotMarketAccount = spotMarket.data;
585
- const spotMarketIndex = spotMarketAccount.marketIndex;
586
- const oracle = spotMarketAccount.oracle;
587
- const oracleId = getOracleId(oracle, spotMarketAccount.oracleSource);
588
- if (!this.oracles.has(oracleId)) {
589
- oraclePromises.push(
590
- this.addOracle({
591
- publicKey: oracle,
592
- source: spotMarketAccount.oracleSource,
593
- })
594
- );
595
- }
596
- this.spotOracleMap.set(spotMarketIndex, oracle);
597
- this.spotOracleStringMap.set(spotMarketIndex, oracleId);
598
- }
599
- await Promise.all(oraclePromises);
600
- }
601
-
602
- /**
603
- * Applies `delistedMarketSetting` to any perp market currently `status: delisted` (and its
604
- * oracle, if not shared with a live spot market): removes the `BulkAccountLoader` registration,
605
- * and additionally drops the market/oracle from internal maps if the setting is `Discard`. A
606
- * no-op if the setting is `Subscribe`. Throws if internal bookkeeping is inconsistent (e.g. a
607
- * delisted market missing from `accountsToPoll`), which would indicate a bug rather than an
608
- * expected runtime condition.
609
- */
610
- handleDelistedMarkets(): void {
611
- if (this.delistedMarketSetting === DelistedMarketSetting.Subscribe) {
612
- return;
613
- }
614
-
615
- const { perpMarketIndexes, oracles } = findDelistedPerpMarketsAndOracles(
616
- this.getMarketAccountsAndSlots(),
617
- this.getSpotMarketAccountsAndSlots()
618
- );
619
-
620
- for (const perpMarketIndex of perpMarketIndexes) {
621
- const perpMarketData = this.perpMarket.get(perpMarketIndex);
622
- if (!perpMarketData) {
623
- throw new Error(
624
- `PollingVelocityClientAccountSubscriber: delisted perp market ${perpMarketIndex} not found in perpMarket map`
625
- );
626
- }
627
- const perpMarketPubkey = perpMarketData.data.pubkey;
628
- const accountToPoll = this.accountsToPoll.get(
629
- perpMarketPubkey.toBase58()
630
- );
631
- if (!accountToPoll) {
632
- throw new Error(
633
- `PollingVelocityClientAccountSubscriber: delisted perp market ${perpMarketIndex} not found in accountsToPoll map`
634
- );
635
- }
636
- const callbackId = accountToPoll.callbackId;
637
- this.accountLoader.removeAccount(perpMarketPubkey, callbackId);
638
- if (this.delistedMarketSetting === DelistedMarketSetting.Discard) {
639
- this.perpMarket.delete(perpMarketIndex);
640
- }
641
- }
642
-
643
- for (const oracle of oracles) {
644
- const oracleId = getOracleId(oracle.publicKey, oracle.source);
645
- const oracleToPoll = this.oraclesToPoll.get(oracleId);
646
- if (!oracleToPoll) {
647
- throw new Error(
648
- `PollingVelocityClientAccountSubscriber: delisted oracle ${oracleId} not found in oraclesToPoll map`
649
- );
650
- }
651
- const callbackId = oracleToPoll.callbackId;
652
- this.accountLoader.removeAccount(oracle.publicKey, callbackId);
653
- if (this.delistedMarketSetting === DelistedMarketSetting.Discard) {
654
- this.oracles.delete(oracleId);
655
- }
656
- }
657
- }
658
-
659
- /** Throws `NotSubscribedError` if `subscribe()` has not been called. */
660
- assertIsSubscribed(): void {
661
- if (!this.isSubscribed) {
662
- throw new NotSubscribedError(
663
- 'You must call `subscribe` before using this function'
664
- );
665
- }
666
- }
667
-
668
- /** Throws `NotSubscribedError` if not subscribed. */
669
- public getStateAccountAndSlot(): DataAndSlot<StateAccount> {
670
- this.assertIsSubscribed();
671
- return this.state!;
672
- }
673
-
674
- /** Returns the cached perp market, or undefined if `marketIndex` isn't tracked (or hasn't loaded yet). Does not throw `NotSubscribedError`. */
675
- public getMarketAccountAndSlot(
676
- marketIndex: number
677
- ): DataAndSlot<PerpMarketAccount> | undefined {
678
- return this.perpMarket.get(marketIndex);
679
- }
680
-
681
- /** Returns every currently cached perp market. Does not throw `NotSubscribedError`. */
682
- public getMarketAccountsAndSlots(): DataAndSlot<PerpMarketAccount>[] {
683
- return Array.from(this.perpMarket.values());
684
- }
685
-
686
- /** Returns the cached spot market, or undefined if `marketIndex` isn't tracked (or hasn't loaded yet). Does not throw `NotSubscribedError`. */
687
- public getSpotMarketAccountAndSlot(
688
- marketIndex: number
689
- ): DataAndSlot<SpotMarketAccount> | undefined {
690
- return this.spotMarket.get(marketIndex);
691
- }
692
-
693
- /** Returns every currently cached spot market. Does not throw `NotSubscribedError`. */
694
- public getSpotMarketAccountsAndSlots(): DataAndSlot<SpotMarketAccount>[] {
695
- return Array.from(this.spotMarket.values());
696
- }
697
-
698
- /**
699
- * Looks up cached oracle price data by oracle id (see `getOracleId`). Special-cases the
700
- * quote-asset default oracle id, returning the constant `QUOTE_ORACLE_PRICE_DATA` at slot 0
701
- * rather than a map lookup, since that oracle is never actually subscribed to.
702
- * @param oracleId Oracle id string from `getOracleId(publicKey, source)`.
703
- * @returns Cached price data/slot, or undefined if not tracked. Throws `NotSubscribedError` if not subscribed.
704
- */
705
- public getOraclePriceDataAndSlot(
706
- oracleId: string
707
- ): DataAndSlot<OraclePriceData> | undefined {
708
- this.assertIsSubscribed();
709
- if (oracleId === ORACLE_DEFAULT_ID) {
710
- return {
711
- data: QUOTE_ORACLE_PRICE_DATA,
712
- slot: 0,
713
- };
714
- }
715
-
716
- return this.oracles.get(oracleId);
717
- }
718
-
719
- /**
720
- * Convenience lookup: resolves the oracle price data currently mapped to a perp market's
721
- * oracle. If the cached market's oracle pubkey has drifted from `perpOracleMap` (e.g. an admin
722
- * changed it on-chain), triggers a background `setPerpOracleMap()` refresh and still returns
723
- * the (possibly stale) mapping for this call.
724
- * @param marketIndex Perp market index whose oracle price to look up.
725
- */
726
- public getOraclePriceDataAndSlotForPerpMarket(
727
- marketIndex: number
728
- ): DataAndSlot<OraclePriceData> | undefined {
729
- const perpMarketAccount = this.getMarketAccountAndSlot(marketIndex);
730
- const oracle = this.perpOracleMap.get(marketIndex);
731
- const oracleId = this.perpOracleStringMap.get(marketIndex);
732
-
733
- if (!perpMarketAccount || !oracle || !oracleId) {
734
- return undefined;
735
- }
736
-
737
- if (!perpMarketAccount.data.oracle.equals(oracle)) {
738
- // If the oracle has changed, we need to update the oracle map in background
739
- this.setPerpOracleMap();
740
- }
741
-
742
- return this.getOraclePriceDataAndSlot(oracleId);
743
- }
744
-
745
- /**
746
- * Convenience lookup: resolves the oracle price data currently mapped to a spot market's
747
- * oracle. If the cached market's oracle pubkey has drifted from `spotOracleMap`, triggers a
748
- * background `setSpotOracleMap()` refresh and still returns the (possibly stale) mapping for
749
- * this call.
750
- * @param marketIndex Spot market index whose oracle price to look up.
751
- */
752
- public getOraclePriceDataAndSlotForSpotMarket(
753
- marketIndex: number
754
- ): DataAndSlot<OraclePriceData> | undefined {
755
- const spotMarketAccount = this.getSpotMarketAccountAndSlot(marketIndex);
756
- const oracle = this.spotOracleMap.get(marketIndex);
757
- const oracleId = this.spotOracleStringMap.get(marketIndex);
758
- if (!spotMarketAccount || !oracle || !oracleId) {
759
- return undefined;
760
- }
761
-
762
- if (!spotMarketAccount.data.oracle.equals(oracle)) {
763
- // If the oracle has changed, we need to update the oracle map in background
764
- this.setSpotOracleMap();
765
- }
766
-
767
- return this.getOraclePriceDataAndSlot(oracleId);
768
- }
769
-
770
- /** Retunes the shared `BulkAccountLoader`'s poll interval (ms) for every account it batches (affects other subscribers sharing the same loader too). */
771
- public updateAccountLoaderPollingFrequency(pollingFrequency: number): void {
772
- this.accountLoader.updatePollingFrequency(pollingFrequency);
773
- }
774
- }