@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,378 +0,0 @@
1
- import { VelocityClient } from '../velocityClient';
2
- import { UserAccount } from '../types';
3
- import {
4
- getNonIdleUserFilter,
5
- getUserFilter,
6
- getUserWithOrderFilter,
7
- } from '../memcmp';
8
- import { Commitment, PublicKey, RpcResponseAndContext } from '@solana/web3.js';
9
- import { Buffer } from 'buffer';
10
- import { DLOB } from '../dlob/DLOB';
11
- import { OrderSubscriberConfig, OrderSubscriberEvents } from './types';
12
- import { PollingSubscription } from './PollingSubscription';
13
- import { WebsocketSubscription } from './WebsocketSubscription';
14
- import StrictEventEmitter from 'strict-event-emitter-types';
15
- import { EventEmitter } from 'events';
16
- import { BN } from '../isomorphic/anchor';
17
- import { decodeUser } from '../decode/user';
18
- import { grpcSubscription } from './grpcSubscription';
19
- import { calculateOrderBaseAssetAmount } from '../math/orders';
20
- import { ZERO } from '../constants/numericConstants';
21
-
22
- /*
23
- * Byte offset of `lastActiveSlot` (u64) in the `User` account, used here to
24
- * cheaply detect stale updates without fully decoding the buffer. Must match
25
- * the on-chain `User` layout (see `decode/user.ts`). The previous value (4328)
26
- * was for the older 4376-byte layout; the current Velocity layout is 4496
27
- * bytes, shifting this field +120 bytes. With the wrong offset this read 8
28
- * zero-padding bytes, so the staleness guard rejected every post-load update.
29
- */
30
- const USER_LAST_ACTIVE_SLOT_OFFSET = 4448;
31
-
32
- /**
33
- * OrderSubscriber — maintains a live, in-memory map of every `User` account
34
- * (and therefore every open order) on the program, refreshed via polling,
35
- * websocket program-account subscription, or gRPC/Laserstream, depending on
36
- * `config.subscriptionConfig.type`. Used by keeper bots and `DLOBSubscriber`
37
- * to build a full DLOB without individually subscribing to each trader's
38
- * `User` account. Emits `orderCreated`/`userUpdated`/`updateReceived` on
39
- * `eventEmitter` as updates arrive; see `OrderSubscriberEvents`.
40
- */
41
- export class OrderSubscriber {
42
- velocityClient: VelocityClient;
43
- usersAccounts = new Map<string, { slot: number; userAccount: UserAccount }>();
44
- subscription: PollingSubscription | WebsocketSubscription | grpcSubscription;
45
- commitment: Commitment;
46
- eventEmitter: StrictEventEmitter<EventEmitter, OrderSubscriberEvents>;
47
-
48
- fetchPromise?: Promise<void>;
49
- private fetchPromiseResolver: () => void = () => {};
50
-
51
- mostRecentSlot = 0;
52
- decodeFn: (name: string, data: Buffer) => UserAccount;
53
- decodeData?: boolean;
54
-
55
- fetchAllNonIdleUsers?: boolean;
56
-
57
- /**
58
- * @param config Subscription config. `subscriptionConfig.type` selects the transport (`'polling'`, `'websocket'`, or `'grpc'`); `fastDecode` (default `true`) uses the hand-written `decodeUser` fast path instead of the Anchor coder; `fetchAllNonIdleUsers` (default `false`) widens the account filter from "has at least one order" to "any non-idle user", useful for consumers that need idle-but-active accounts too.
59
- * @throws If `config.velocityClient` is not provided.
60
- */
61
- constructor(config: OrderSubscriberConfig) {
62
- const velocityClient = config.velocityClient;
63
- if (!velocityClient) {
64
- throw new Error('OrderSubscriber: velocityClient must be provided');
65
- }
66
- this.velocityClient = velocityClient;
67
- this.commitment = config.subscriptionConfig.commitment || 'processed';
68
- if (config.subscriptionConfig.type === 'polling') {
69
- this.subscription = new PollingSubscription({
70
- orderSubscriber: this,
71
- frequency: config.subscriptionConfig.frequency,
72
- });
73
- } else if (config.subscriptionConfig.type === 'grpc') {
74
- this.subscription = new grpcSubscription({
75
- orderSubscriber: this,
76
- grpcConfigs: config.subscriptionConfig.grpcConfigs,
77
- skipInitialLoad: config.subscriptionConfig.skipInitialLoad,
78
- resubOpts: {
79
- resubTimeoutMs: config.subscriptionConfig?.resubTimeoutMs,
80
- logResubMessages: config.subscriptionConfig?.logResubMessages,
81
- },
82
- resyncIntervalMs: config.subscriptionConfig.resyncIntervalMs,
83
- decoded: config.decodeData,
84
- });
85
- } else {
86
- this.subscription = new WebsocketSubscription({
87
- orderSubscriber: this,
88
- commitment: this.commitment,
89
- skipInitialLoad: config.subscriptionConfig.skipInitialLoad,
90
- resubOpts: {
91
- resubTimeoutMs: config.subscriptionConfig?.resubTimeoutMs,
92
- logResubMessages: config.subscriptionConfig?.logResubMessages,
93
- },
94
- resyncIntervalMs: config.subscriptionConfig.resyncIntervalMs,
95
- decoded: config.decodeData,
96
- });
97
- }
98
- if (config.fastDecode ?? true) {
99
- this.decodeFn = (name, data) => decodeUser(data);
100
- } else {
101
- this.decodeFn = (
102
- this.velocityClient.program.account as any
103
- ).user.coder.accounts.decodeUnchecked.bind(
104
- (this.velocityClient.program.account as any).user.coder.accounts
105
- );
106
- }
107
- this.eventEmitter = new EventEmitter();
108
- this.fetchAllNonIdleUsers = config.fetchAllNonIdleUsers;
109
- }
110
-
111
- /** Starts the underlying transport (polling interval, websocket program-account subscription, or gRPC stream) chosen at construction time. */
112
- public async subscribe(): Promise<void> {
113
- await this.subscription.subscribe();
114
- }
115
-
116
- /**
117
- * One-shot full refresh: fetches every `User` account matching the
118
- * configured filters via `getProgramAccounts` and feeds each through
119
- * `tryUpdateUserAccount`. Concurrent calls share the in-flight promise
120
- * rather than issuing a second `getProgramAccounts` request. Errors are
121
- * caught and logged, not thrown — the promise still resolves.
122
- */
123
- async fetch(): Promise<void> {
124
- if (this.fetchPromise) {
125
- return this.fetchPromise;
126
- }
127
-
128
- this.fetchPromise = new Promise((resolver) => {
129
- this.fetchPromiseResolver = resolver;
130
- });
131
-
132
- const filters = this.fetchAllNonIdleUsers
133
- ? [getUserFilter(), getNonIdleUserFilter()]
134
- : [getUserFilter(), getUserWithOrderFilter()];
135
-
136
- try {
137
- const rpcRequestArgs = [
138
- this.velocityClient.program.programId.toBase58(),
139
- {
140
- commitment: this.commitment,
141
- filters,
142
- encoding: 'base64',
143
- withContext: true,
144
- },
145
- ];
146
-
147
- const rpcJSONResponse: any =
148
- // @ts-ignore
149
- await this.velocityClient.connection._rpcRequest(
150
- 'getProgramAccounts',
151
- rpcRequestArgs
152
- );
153
-
154
- const rpcResponseAndContext: RpcResponseAndContext<
155
- Array<{
156
- pubkey: PublicKey;
157
- account: {
158
- data: [string, string];
159
- };
160
- }>
161
- > = rpcJSONResponse.result;
162
-
163
- const slot: number = rpcResponseAndContext.context.slot;
164
-
165
- for (const programAccount of rpcResponseAndContext.value) {
166
- const key = programAccount.pubkey.toString();
167
- this.tryUpdateUserAccount(
168
- key,
169
- 'raw',
170
- programAccount.account.data,
171
- slot
172
- );
173
- // give event loop a chance to breathe
174
- await new Promise((resolve) => setTimeout(resolve, 0));
175
- }
176
- } catch (e) {
177
- console.error(e);
178
- } finally {
179
- this.fetchPromiseResolver();
180
- this.fetchPromise = undefined;
181
- }
182
- }
183
-
184
- /**
185
- * Applies an incoming update for the `User` account `key`, called by
186
- * `fetch`, `addPubkey`, and each subscription transport
187
- * (`PollingSubscription`/`WebsocketSubscription`/`grpcSubscription`).
188
- * Advances `mostRecentSlot` and always emits `updateReceived`. The stored
189
- * account is only replaced if `slot` is >= the currently cached slot for
190
- * that key; for `'raw'`/`'buffer'` inputs, before decoding it also cheaply
191
- * peeks the account's `lastActiveSlot` field at a fixed byte offset and
192
- * discards the update if that's older than what's cached, without paying
193
- * the cost of a full decode. On acceptance, emits `userUpdated`, and
194
- * `orderCreated` for any orders in the account whose `order.slot` falls in
195
- * `(previousSlot, slot]`.
196
- * @param key Base58 pubkey of the `User` account.
197
- * @param dataType `'raw'` (base64/base58 tuple from `getProgramAccounts`), `'decoded'` (already an Anchor-decoded `UserAccount`), or `'buffer'` (raw account bytes) — determines how `data` is interpreted/decoded.
198
- * @param data The account payload, shaped per `dataType`.
199
- * @param slot Slot the update was observed at.
200
- */
201
- tryUpdateUserAccount(
202
- key: string,
203
- dataType: 'raw' | 'decoded' | 'buffer',
204
- data: string[] | UserAccount | Buffer,
205
- slot: number
206
- ): void {
207
- if (!this.mostRecentSlot || slot > this.mostRecentSlot) {
208
- this.mostRecentSlot = slot;
209
- }
210
-
211
- this.eventEmitter.emit(
212
- 'updateReceived',
213
- new PublicKey(key),
214
- slot,
215
- dataType
216
- );
217
-
218
- const slotAndUserAccount = this.usersAccounts.get(key);
219
- if (!slotAndUserAccount || slotAndUserAccount.slot <= slot) {
220
- let userAccount: UserAccount;
221
- // Polling leads to a lot of redundant decoding, so we only decode if data is from a fresh slot
222
- if (dataType === 'raw') {
223
- // @ts-ignore
224
- const buffer = Buffer.from(data[0], data[1]);
225
-
226
- const newLastActiveSlot = new BN(
227
- buffer.subarray(
228
- USER_LAST_ACTIVE_SLOT_OFFSET,
229
- USER_LAST_ACTIVE_SLOT_OFFSET + 8
230
- ),
231
- undefined,
232
- 'le'
233
- );
234
- if (
235
- slotAndUserAccount &&
236
- slotAndUserAccount.userAccount.lastActiveSlot.gt(newLastActiveSlot)
237
- ) {
238
- return;
239
- }
240
-
241
- userAccount = this.decodeFn('user', buffer) as UserAccount;
242
- } else if (dataType === 'buffer') {
243
- const buffer: Buffer = data as Buffer;
244
- const newLastActiveSlot = new BN(
245
- buffer.subarray(
246
- USER_LAST_ACTIVE_SLOT_OFFSET,
247
- USER_LAST_ACTIVE_SLOT_OFFSET + 8
248
- ),
249
- undefined,
250
- 'le'
251
- );
252
- if (
253
- slotAndUserAccount &&
254
- slotAndUserAccount.userAccount.lastActiveSlot.gt(newLastActiveSlot)
255
- ) {
256
- return;
257
- }
258
-
259
- userAccount = this.decodeFn('user', data as Buffer) as UserAccount;
260
- } else {
261
- userAccount = data as UserAccount;
262
- }
263
-
264
- this.eventEmitter.emit(
265
- 'userUpdated',
266
- userAccount,
267
- new PublicKey(key),
268
- slot,
269
- dataType
270
- );
271
-
272
- const newOrders = userAccount.orders.filter(
273
- (order) =>
274
- order.slot.toNumber() > (slotAndUserAccount?.slot ?? 0) &&
275
- order.slot.toNumber() <= slot
276
- );
277
- if (newOrders.length > 0) {
278
- this.eventEmitter.emit(
279
- 'orderCreated',
280
- userAccount,
281
- newOrders,
282
- new PublicKey(key),
283
- slot,
284
- dataType
285
- );
286
- }
287
-
288
- this.usersAccounts.set(key, { slot, userAccount });
289
- }
290
- }
291
-
292
- /**
293
- * Creates a new DLOB for the order subscriber to fill. This will allow a
294
- * caller to extend the DLOB Subscriber with a custom DLOB type.
295
- * @returns New, empty DLOB object.
296
- */
297
- protected createDLOB(): DLOB {
298
- return new DLOB();
299
- }
300
-
301
- /**
302
- * Builds a fresh `DLOB` from the currently cached `User` accounts. For
303
- * reduce-only orders, resolves the base asset amount against the trader's
304
- * existing perp position (via `calculateOrderBaseAssetAmount`, `BASE_PRECISION`,
305
- * 1e9) rather than trusting the order's own `baseAssetAmount` field, since a
306
- * reduce-only order's fillable size is capped by the position it reduces.
307
- * @param slot Slot to stamp onto inserted orders (used by the DLOB for auction/expiry timing, not for filtering which accounts are included).
308
- * @returns A new `DLOB` populated with every order across all cached users.
309
- */
310
- public async getDLOB(slot: number): Promise<DLOB> {
311
- const dlob = this.createDLOB();
312
- for (const [key, { userAccount }] of this.usersAccounts.entries()) {
313
- for (const order of userAccount.orders) {
314
- let baseAssetAmount = order.baseAssetAmount;
315
- if (order.reduceOnly) {
316
- const existingBaseAmount =
317
- userAccount.perpPositions.find(
318
- (pos) =>
319
- pos.marketIndex === order.marketIndex && pos.openOrders > 0
320
- )?.baseAssetAmount || ZERO;
321
- baseAssetAmount = calculateOrderBaseAssetAmount(
322
- order,
323
- existingBaseAmount
324
- );
325
- }
326
- dlob.insertOrder(order, key, slot, baseAssetAmount);
327
- }
328
- }
329
- return dlob;
330
- }
331
-
332
- /** @returns The highest slot observed across all account updates so far, or 0 if none have arrived yet. */
333
- public getSlot(): number {
334
- return this.mostRecentSlot ?? 0;
335
- }
336
-
337
- /** Fetches a single `User` account directly (bypassing the subscription's filters) and applies it via `tryUpdateUserAccount`. Useful to backfill an account this subscriber's filters would otherwise exclude (e.g. an idle user with no orders). No-ops if the account doesn't exist. */
338
- public async addPubkey(userAccountPublicKey: PublicKey): Promise<void> {
339
- const accountInfo =
340
- await this.velocityClient.connection.getAccountInfoAndContext(
341
- userAccountPublicKey,
342
- this.commitment
343
- );
344
- if (accountInfo.value) {
345
- this.tryUpdateUserAccount(
346
- userAccountPublicKey.toString(),
347
- 'buffer',
348
- accountInfo.value.data,
349
- accountInfo.context.slot
350
- );
351
- }
352
- }
353
-
354
- /**
355
- * Returns the cached `UserAccount` for `key`, fetching it on demand via
356
- * `addPubkey` if not already cached.
357
- * @param key Base58 pubkey of the `User` account.
358
- * @throws If the account still isn't present after `addPubkey` (e.g. it doesn't exist on-chain).
359
- */
360
- public async mustGetUserAccount(key: string): Promise<UserAccount> {
361
- if (!this.usersAccounts.has(key)) {
362
- await this.addPubkey(new PublicKey(key));
363
- }
364
- const slotAndUserAccount = this.usersAccounts.get(key);
365
- if (!slotAndUserAccount) {
366
- throw new Error(
367
- `OrderSubscriber: user account ${key} not found after addPubkey`
368
- );
369
- }
370
- return slotAndUserAccount.userAccount;
371
- }
372
-
373
- /** Stops the underlying transport and clears the entire cached `User` account map. */
374
- public async unsubscribe(): Promise<void> {
375
- this.usersAccounts.clear();
376
- await this.subscription.unsubscribe();
377
- }
378
- }
@@ -1,50 +0,0 @@
1
- import { OrderSubscriber } from './OrderSubscriber';
2
-
3
- /**
4
- * `OrderSubscriber` transport that repeatedly calls `OrderSubscriber.fetch()`
5
- * (a full `getProgramAccounts` snapshot) on a fixed interval. Simplest and
6
- * most RPC-expensive transport; prefer websocket or grpc for large user sets.
7
- */
8
- export class PollingSubscription {
9
- private orderSubscriber: OrderSubscriber;
10
- private frequency: number;
11
-
12
- intervalId?: ReturnType<typeof setTimeout>;
13
-
14
- /**
15
- * @param orderSubscriber The `OrderSubscriber` to feed with each poll.
16
- * @param frequency Poll interval in milliseconds.
17
- */
18
- constructor({
19
- orderSubscriber,
20
- frequency,
21
- }: {
22
- orderSubscriber: OrderSubscriber;
23
- frequency: number;
24
- }) {
25
- this.orderSubscriber = orderSubscriber;
26
- this.frequency = frequency;
27
- }
28
-
29
- /** Starts the polling interval and performs one immediate `fetch()` before returning. Idempotent while already subscribed. */
30
- public async subscribe(): Promise<void> {
31
- if (this.intervalId) {
32
- return;
33
- }
34
-
35
- this.intervalId = setInterval(
36
- this.orderSubscriber.fetch.bind(this.orderSubscriber),
37
- this.frequency
38
- );
39
-
40
- await this.orderSubscriber.fetch();
41
- }
42
-
43
- /** Stops the polling interval. */
44
- public async unsubscribe(): Promise<void> {
45
- if (this.intervalId) {
46
- clearInterval(this.intervalId);
47
- this.intervalId = undefined;
48
- }
49
- }
50
- }
@@ -1,137 +0,0 @@
1
- import { OrderSubscriber } from './OrderSubscriber';
2
- import { getNonIdleUserFilter, getUserFilter } from '../memcmp';
3
- import { UserAccount } from '../types';
4
- import { Commitment, Context, PublicKey } from '@solana/web3.js';
5
- import { ResubOpts } from '../accounts/types';
6
- import { WebSocketProgramAccountSubscriber } from '../accounts/webSocketProgramAccountSubscriber';
7
-
8
- /**
9
- * `OrderSubscriber` transport backed by a websocket `WebSocketProgramAccountSubscriber`
10
- * filtered to non-idle `User` accounts. On subscribe, optionally performs an
11
- * initial full `fetch()` snapshot (unless `skipInitialLoad`), then applies
12
- * live updates as they arrive; if `resyncIntervalMs` is set, also runs a
13
- * periodic full `fetch()` resync alongside the subscription to self-heal any
14
- * missed program-account notifications.
15
- */
16
- export class WebsocketSubscription {
17
- private orderSubscriber: OrderSubscriber;
18
- private commitment: Commitment;
19
- private skipInitialLoad: boolean;
20
- private resubOpts?: ResubOpts;
21
- private resyncIntervalMs?: number;
22
-
23
- private subscriber?: WebSocketProgramAccountSubscriber<UserAccount>;
24
- private resyncTimeoutId?: ReturnType<typeof setTimeout>;
25
-
26
- private decoded?: boolean;
27
-
28
- /**
29
- * @param orderSubscriber The `OrderSubscriber` to feed with updates.
30
- * @param commitment Commitment level for the program-account subscription.
31
- * @param skipInitialLoad Skip the initial full `fetch()` snapshot after subscribing; defaults to `false`.
32
- * @param resubOpts Reconnect behavior for the underlying `WebSocketProgramAccountSubscriber`.
33
- * @param resyncIntervalMs If set, runs a periodic full `fetch()` resync at this interval.
34
- * @param decoded Whether updates are delivered already Anchor-decoded (`true`, default) or as raw buffers for `OrderSubscriber` to decode itself.
35
- */
36
- constructor({
37
- orderSubscriber,
38
- commitment,
39
- skipInitialLoad = false,
40
- resubOpts,
41
- resyncIntervalMs,
42
- decoded = true,
43
- }: {
44
- orderSubscriber: OrderSubscriber;
45
- commitment: Commitment;
46
- skipInitialLoad?: boolean;
47
- resubOpts?: ResubOpts;
48
- resyncIntervalMs?: number;
49
- decoded?: boolean;
50
- }) {
51
- this.orderSubscriber = orderSubscriber;
52
- this.commitment = commitment;
53
- this.skipInitialLoad = skipInitialLoad;
54
- this.resubOpts = resubOpts;
55
- this.resyncIntervalMs = resyncIntervalMs;
56
- this.decoded = decoded;
57
- }
58
-
59
- /** Establishes the websocket program-account subscription (idempotent — no-op if already subscribed), optionally backfills with `fetch()`, and starts the resync timer if configured. */
60
- public async subscribe(): Promise<void> {
61
- if (this.subscriber) {
62
- return;
63
- }
64
-
65
- this.subscriber = new WebSocketProgramAccountSubscriber<UserAccount>(
66
- 'OrderSubscriber',
67
- 'user',
68
- this.orderSubscriber.velocityClient.program,
69
- this.orderSubscriber.decodeFn,
70
- {
71
- filters: [getUserFilter(), getNonIdleUserFilter()],
72
- commitment: this.commitment,
73
- },
74
- this.resubOpts
75
- );
76
-
77
- await this.subscriber.subscribe(
78
- (
79
- accountId: PublicKey,
80
- account: UserAccount,
81
- context: Context,
82
- buffer: Buffer
83
- ) => {
84
- const userKey = accountId.toBase58();
85
- if (this.decoded ?? true) {
86
- this.orderSubscriber.tryUpdateUserAccount(
87
- userKey,
88
- 'decoded',
89
- account,
90
- context.slot
91
- );
92
- } else {
93
- this.orderSubscriber.tryUpdateUserAccount(
94
- userKey,
95
- 'buffer',
96
- buffer,
97
- context.slot
98
- );
99
- }
100
- }
101
- );
102
-
103
- if (!this.skipInitialLoad) {
104
- await this.orderSubscriber.fetch();
105
- }
106
-
107
- if (this.resyncIntervalMs) {
108
- const recursiveResync = () => {
109
- this.resyncTimeoutId = setTimeout(() => {
110
- this.orderSubscriber
111
- .fetch()
112
- .catch((e) => {
113
- console.error('Failed to resync in OrderSubscriber');
114
- console.log(e);
115
- })
116
- .finally(() => {
117
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
118
- if (!this.resyncTimeoutId) return;
119
- recursiveResync();
120
- });
121
- }, this.resyncIntervalMs);
122
- };
123
- recursiveResync();
124
- }
125
- }
126
-
127
- /** Tears down the program-account subscription and cancels the resync timer, if any. No-op if not subscribed. */
128
- public async unsubscribe(): Promise<void> {
129
- if (!this.subscriber) return;
130
- await this.subscriber.unsubscribe();
131
- this.subscriber = undefined;
132
- if (this.resyncTimeoutId !== undefined) {
133
- clearTimeout(this.resyncTimeoutId);
134
- this.resyncTimeoutId = undefined;
135
- }
136
- }
137
- }