@velocity-exchange/sdk 0.4.0 → 0.6.1

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 (325) hide show
  1. package/README.md +3 -3
  2. package/lib/browser/adminClient.d.ts +52 -0
  3. package/lib/browser/adminClient.js +97 -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 +191 -15
  9. package/lib/browser/idl/velocity.json +192 -16
  10. package/lib/browser/orderSubscriber/OrderSubscriber.d.ts +1 -0
  11. package/lib/browser/orderSubscriber/OrderSubscriber.js +10 -4
  12. package/lib/browser/pyth/pythLazerSubscriber.js +37 -27
  13. package/lib/browser/types.d.ts +6 -0
  14. package/lib/browser/user.d.ts +20 -3
  15. package/lib/browser/user.js +52 -4
  16. package/lib/browser/velocityClient.d.ts +46 -10
  17. package/lib/browser/velocityClient.js +107 -35
  18. package/lib/node/adminClient.d.ts +52 -0
  19. package/lib/node/adminClient.d.ts.map +1 -1
  20. package/lib/node/adminClient.js +97 -0
  21. package/lib/node/config.d.ts.map +1 -1
  22. package/lib/node/config.js +6 -7
  23. package/lib/node/constants/numericConstants.d.ts +1 -1
  24. package/lib/node/constants/numericConstants.d.ts.map +1 -1
  25. package/lib/node/constants/numericConstants.js +1 -1
  26. package/lib/node/decode/user.d.ts.map +1 -1
  27. package/lib/node/decode/user.js +5 -1
  28. package/lib/node/idl/velocity.d.ts +191 -15
  29. package/lib/node/idl/velocity.d.ts.map +1 -1
  30. package/lib/node/idl/velocity.json +192 -16
  31. package/lib/node/orderSubscriber/OrderSubscriber.d.ts +1 -0
  32. package/lib/node/orderSubscriber/OrderSubscriber.d.ts.map +1 -1
  33. package/lib/node/orderSubscriber/OrderSubscriber.js +10 -4
  34. package/lib/node/pyth/pythLazerSubscriber.d.ts.map +1 -1
  35. package/lib/node/pyth/pythLazerSubscriber.js +37 -27
  36. package/lib/node/types.d.ts +6 -0
  37. package/lib/node/types.d.ts.map +1 -1
  38. package/lib/node/user.d.ts +20 -3
  39. package/lib/node/user.d.ts.map +1 -1
  40. package/lib/node/user.js +52 -4
  41. package/lib/node/velocityClient.d.ts +46 -10
  42. package/lib/node/velocityClient.d.ts.map +1 -1
  43. package/lib/node/velocityClient.js +107 -35
  44. package/package.json +7 -3
  45. package/.prettierignore +0 -1
  46. package/CHANGELOG.md +0 -132
  47. package/build-browser.js +0 -58
  48. package/bunfig.toml +0 -3
  49. package/esbuild-shims.js +0 -12
  50. package/scripts/deposit-isolated-positions.ts +0 -110
  51. package/scripts/find-flagged-users.ts +0 -213
  52. package/scripts/grpc-client-test-comparison.ts +0 -372
  53. package/scripts/grpc-multiuser-client-test-comparison.ts +0 -158
  54. package/scripts/postbuild.js +0 -95
  55. package/scripts/single-grpc-client-test.ts +0 -284
  56. package/scripts/withdraw-isolated-positions.ts +0 -174
  57. package/src/accounts/README_WebSocketAccountSubscriberV2.md +0 -95
  58. package/src/accounts/README_WebSocketProgramAccountSubscriberV2.md +0 -135
  59. package/src/accounts/basicUserAccountSubscriber.ts +0 -79
  60. package/src/accounts/basicUserStatsAccountSubscriber.ts +0 -87
  61. package/src/accounts/bulkAccountLoader.ts +0 -358
  62. package/src/accounts/bulkUserStatsSubscription.ts +0 -40
  63. package/src/accounts/bulkUserSubscription.ts +0 -39
  64. package/src/accounts/customizedCadenceBulkAccountLoader.ts +0 -250
  65. package/src/accounts/fetch.ts +0 -200
  66. package/src/accounts/grpcAccountSubscriber.ts +0 -225
  67. package/src/accounts/grpcInsuranceFundStakeAccountSubscriber.ts +0 -73
  68. package/src/accounts/grpcMultiAccountSubscriber.ts +0 -566
  69. package/src/accounts/grpcMultiUserAccountSubscriber.ts +0 -328
  70. package/src/accounts/grpcProgramAccountSubscriber.ts +0 -264
  71. package/src/accounts/grpcUserAccountSubscriber.ts +0 -63
  72. package/src/accounts/grpcUserStatsAccountSubscriber.ts +0 -65
  73. package/src/accounts/grpcVelocityClientAccountSubscriber.ts +0 -257
  74. package/src/accounts/grpcVelocityClientAccountSubscriberV2.ts +0 -941
  75. package/src/accounts/laserProgramAccountSubscriber.ts +0 -266
  76. package/src/accounts/oneShotUserAccountSubscriber.ts +0 -88
  77. package/src/accounts/oneShotUserStatsAccountSubscriber.ts +0 -94
  78. package/src/accounts/pollingInsuranceFundStakeAccountSubscriber.ts +0 -223
  79. package/src/accounts/pollingOracleAccountSubscriber.ts +0 -151
  80. package/src/accounts/pollingTokenAccountSubscriber.ts +0 -147
  81. package/src/accounts/pollingUserAccountSubscriber.ts +0 -198
  82. package/src/accounts/pollingUserStatsAccountSubscriber.ts +0 -180
  83. package/src/accounts/pollingVelocityClientAccountSubscriber.ts +0 -774
  84. package/src/accounts/testBulkAccountLoader.ts +0 -59
  85. package/src/accounts/types.ts +0 -428
  86. package/src/accounts/utils.ts +0 -90
  87. package/src/accounts/webSocketAccountSubscriber.ts +0 -304
  88. package/src/accounts/webSocketAccountSubscriberV2.ts +0 -536
  89. package/src/accounts/webSocketInsuranceFundStakeAccountSubscriber.ts +0 -171
  90. package/src/accounts/webSocketProgramAccountSubscriber.ts +0 -244
  91. package/src/accounts/webSocketProgramAccountSubscriberV2.ts +0 -1048
  92. package/src/accounts/webSocketProgramAccountsSubscriberV2.ts +0 -1042
  93. package/src/accounts/webSocketUserAccountSubscriber.ts +0 -139
  94. package/src/accounts/webSocketUserStatsAccountSubsriber.ts +0 -131
  95. package/src/accounts/webSocketVelocityClientAccountSubscriber.ts +0 -865
  96. package/src/accounts/webSocketVelocityClientAccountSubscriberV2.ts +0 -897
  97. package/src/accounts/websocketProgramUserAccountSubscriber.ts +0 -127
  98. package/src/addresses/marketAddresses.ts +0 -28
  99. package/src/addresses/pda.ts +0 -620
  100. package/src/adminClient.ts +0 -8136
  101. package/src/assert/assert.ts +0 -5
  102. package/src/auctionSubscriber/auctionSubscriber.ts +0 -86
  103. package/src/auctionSubscriber/auctionSubscriberGrpc.ts +0 -99
  104. package/src/auctionSubscriber/index.ts +0 -9
  105. package/src/auctionSubscriber/types.ts +0 -30
  106. package/src/bankrun/bankrunConnection.ts +0 -630
  107. package/src/blockhashSubscriber/BlockhashSubscriber.ts +0 -160
  108. package/src/blockhashSubscriber/index.ts +0 -6
  109. package/src/blockhashSubscriber/types.ts +0 -13
  110. package/src/clock/clockSubscriber.ts +0 -146
  111. package/src/config.ts +0 -312
  112. package/src/constants/index.ts +0 -9
  113. package/src/constants/numericConstants.ts +0 -194
  114. package/src/constants/perpMarkets.ts +0 -127
  115. package/src/constants/spotMarkets.ts +0 -104
  116. package/src/constants/txConstants.ts +0 -2
  117. package/src/constituentMap/constituentMap.ts +0 -305
  118. package/src/constituentMap/pollingConstituentAccountSubscriber.ts +0 -99
  119. package/src/constituentMap/webSocketConstituentAccountSubscriber.ts +0 -121
  120. package/src/core/VelocityCore.ts +0 -606
  121. package/src/core/index.ts +0 -12
  122. package/src/core/instructions/deposit.ts +0 -64
  123. package/src/core/instructions/fill.ts +0 -51
  124. package/src/core/instructions/funding.ts +0 -33
  125. package/src/core/instructions/liquidation.ts +0 -55
  126. package/src/core/instructions/orders.ts +0 -84
  127. package/src/core/instructions/perpOrders.ts +0 -312
  128. package/src/core/instructions/settlement.ts +0 -40
  129. package/src/core/instructions/trigger.ts +0 -41
  130. package/src/core/instructions/withdraw.ts +0 -65
  131. package/src/core/remainingAccounts.ts +0 -320
  132. package/src/core/signedMsg.ts +0 -109
  133. package/src/decode/customCoder.ts +0 -148
  134. package/src/decode/user.ts +0 -401
  135. package/src/dlob/DLOB.ts +0 -2793
  136. package/src/dlob/DLOBNode.ts +0 -305
  137. package/src/dlob/DLOBSubscriber.ts +0 -269
  138. package/src/dlob/NodeList.ts +0 -244
  139. package/src/dlob/orderBookLevels.ts +0 -695
  140. package/src/dlob/types.ts +0 -37
  141. package/src/events/eventList.ts +0 -114
  142. package/src/events/eventSubscriber.ts +0 -521
  143. package/src/events/eventsServerLogProvider.ts +0 -189
  144. package/src/events/fetchLogs.ts +0 -219
  145. package/src/events/parse.ts +0 -271
  146. package/src/events/pollingLogProvider.ts +0 -113
  147. package/src/events/sort.ts +0 -51
  148. package/src/events/txEventCache.ts +0 -92
  149. package/src/events/types.ts +0 -337
  150. package/src/events/webSocketLogProvider.ts +0 -152
  151. package/src/factory/bigNum.ts +0 -709
  152. package/src/factory/oracleClient.ts +0 -73
  153. package/src/idl/pyth.json +0 -142
  154. package/src/idl/pyth.ts +0 -97
  155. package/src/idl/pyth_solana_receiver.json +0 -628
  156. package/src/idl/token_faucet.json +0 -229
  157. package/src/idl/token_faucet.ts +0 -197
  158. package/src/idl/velocity.json +0 -23974
  159. package/src/idl/velocity.ts +0 -23980
  160. package/src/index.ts +0 -150
  161. package/src/indicative-quotes/indicativeQuotesSender.ts +0 -233
  162. package/src/isomorphic/README.md +0 -19
  163. package/src/isomorphic/anchor.browser.ts +0 -44
  164. package/src/isomorphic/anchor.node.ts +0 -1
  165. package/src/isomorphic/anchor.ts +0 -1
  166. package/src/isomorphic/anchor29.browser.ts +0 -24
  167. package/src/isomorphic/anchor29.node.ts +0 -1
  168. package/src/isomorphic/anchor29.ts +0 -1
  169. package/src/isomorphic/grpc.browser.ts +0 -4
  170. package/src/isomorphic/grpc.node.ts +0 -130
  171. package/src/isomorphic/grpc.ts +0 -1
  172. package/src/jupiter/jupiterClient.ts +0 -502
  173. package/src/keypair.ts +0 -32
  174. package/src/margin/README.md +0 -138
  175. package/src/marginCalculation.ts +0 -407
  176. package/src/marinade/idl/idl.json +0 -1962
  177. package/src/marinade/index.ts +0 -73
  178. package/src/marinade/types.ts +0 -3925
  179. package/src/math/amm.ts +0 -1758
  180. package/src/math/auction.ts +0 -480
  181. package/src/math/bankruptcy.ts +0 -138
  182. package/src/math/builder.ts +0 -130
  183. package/src/math/conversion.ts +0 -45
  184. package/src/math/exchangeStatus.ts +0 -261
  185. package/src/math/funding.ts +0 -498
  186. package/src/math/insurance.ts +0 -171
  187. package/src/math/liquidation.ts +0 -433
  188. package/src/math/margin.ts +0 -327
  189. package/src/math/market.ts +0 -487
  190. package/src/math/oracles.ts +0 -477
  191. package/src/math/orders.ts +0 -500
  192. package/src/math/position.ts +0 -381
  193. package/src/math/repeg.ts +0 -223
  194. package/src/math/spotBalance.ts +0 -996
  195. package/src/math/spotMarket.ts +0 -115
  196. package/src/math/spotPosition.ts +0 -263
  197. package/src/math/state.ts +0 -71
  198. package/src/math/superStake.ts +0 -602
  199. package/src/math/tiers.ts +0 -73
  200. package/src/math/trade.ts +0 -879
  201. package/src/math/utils.ts +0 -183
  202. package/src/memcmp.ts +0 -279
  203. package/src/oracles/oracleClientCache.ts +0 -41
  204. package/src/oracles/oracleId.ts +0 -99
  205. package/src/oracles/prelaunchOracleClient.ts +0 -63
  206. package/src/oracles/pythClient.ts +0 -125
  207. package/src/oracles/pythLazerClient.ts +0 -141
  208. package/src/oracles/quoteAssetOracleClient.ts +0 -43
  209. package/src/oracles/strictOraclePrice.ts +0 -40
  210. package/src/oracles/types.ts +0 -82
  211. package/src/oracles/utils.ts +0 -45
  212. package/src/orderParams.ts +0 -117
  213. package/src/orderSubscriber/OrderSubscriber.ts +0 -378
  214. package/src/orderSubscriber/PollingSubscription.ts +0 -50
  215. package/src/orderSubscriber/WebsocketSubscription.ts +0 -137
  216. package/src/orderSubscriber/grpcSubscription.ts +0 -155
  217. package/src/orderSubscriber/index.ts +0 -7
  218. package/src/orderSubscriber/types.ts +0 -64
  219. package/src/priorityFee/averageOverSlotsStrategy.ts +0 -17
  220. package/src/priorityFee/averageStrategy.ts +0 -13
  221. package/src/priorityFee/ewmaStrategy.ts +0 -51
  222. package/src/priorityFee/heliusPriorityFeeMethod.ts +0 -68
  223. package/src/priorityFee/index.ts +0 -16
  224. package/src/priorityFee/maxOverSlotsStrategy.ts +0 -18
  225. package/src/priorityFee/maxStrategy.ts +0 -8
  226. package/src/priorityFee/priorityFeeSubscriber.ts +0 -328
  227. package/src/priorityFee/priorityFeeSubscriberMap.ts +0 -134
  228. package/src/priorityFee/solanaPriorityFeeMethod.ts +0 -46
  229. package/src/priorityFee/types.ts +0 -82
  230. package/src/priorityFee/velocityPriorityFeeMethod.ts +0 -53
  231. package/src/pyth/constants.ts +0 -9
  232. package/src/pyth/index.ts +0 -15
  233. package/src/pyth/pythLazerSubscriber.ts +0 -365
  234. package/src/pyth/types.ts +0 -4451
  235. package/src/pyth/utils.ts +0 -13
  236. package/src/slot/SlotSubscriber.ts +0 -126
  237. package/src/slot/SlothashSubscriber.ts +0 -163
  238. package/src/swap/UnifiedSwapClient.ts +0 -315
  239. package/src/swift/grpcSignedMsgUserAccountSubscriber.ts +0 -81
  240. package/src/swift/index.ts +0 -10
  241. package/src/swift/signedMsgUserAccountSubscriber.ts +0 -251
  242. package/src/swift/swiftOrderSubscriber.ts +0 -351
  243. package/src/testClient.ts +0 -42
  244. package/src/titan/titanClient.ts +0 -438
  245. package/src/token/index.ts +0 -13
  246. package/src/tokenFaucet.ts +0 -296
  247. package/src/tx/baseTxSender.ts +0 -651
  248. package/src/tx/blockhashFetcher/baseBlockhashFetcher.ts +0 -31
  249. package/src/tx/blockhashFetcher/cachedBlockhashFetcher.ts +0 -105
  250. package/src/tx/blockhashFetcher/types.ts +0 -9
  251. package/src/tx/fastSingleTxSender.ts +0 -200
  252. package/src/tx/forwardOnlyTxSender.ts +0 -193
  253. package/src/tx/priorityFeeCalculator.ts +0 -117
  254. package/src/tx/reportTransactionError.ts +0 -176
  255. package/src/tx/retryTxSender.ts +0 -177
  256. package/src/tx/txHandler.ts +0 -1009
  257. package/src/tx/txParamProcessor.ts +0 -225
  258. package/src/tx/types.ts +0 -117
  259. package/src/tx/utils.ts +0 -133
  260. package/src/tx/whileValidTxSender.ts +0 -377
  261. package/src/types.ts +0 -2575
  262. package/src/user.ts +0 -5316
  263. package/src/userConfig.ts +0 -38
  264. package/src/userMap/PollingSubscription.ts +0 -61
  265. package/src/userMap/WebsocketSubscription.ts +0 -93
  266. package/src/userMap/grpcSubscription.ts +0 -93
  267. package/src/userMap/referrerMap.ts +0 -360
  268. package/src/userMap/revenueShareEscrowMap.ts +0 -342
  269. package/src/userMap/userMap.ts +0 -784
  270. package/src/userMap/userMapConfig.ts +0 -82
  271. package/src/userMap/userStatsMap.ts +0 -393
  272. package/src/userName.ts +0 -37
  273. package/src/userStats.ts +0 -159
  274. package/src/userStatsConfig.ts +0 -35
  275. package/src/util/TransactionConfirmationManager.ts +0 -333
  276. package/src/util/chainClock.ts +0 -65
  277. package/src/util/computeUnits.ts +0 -101
  278. package/src/util/digest.ts +0 -33
  279. package/src/util/ed25519Utils.ts +0 -95
  280. package/src/util/promiseTimeout.ts +0 -23
  281. package/src/velocityClient.ts +0 -14802
  282. package/src/velocityClientConfig.ts +0 -119
  283. package/src/wallet.ts +0 -91
  284. package/tests/VelocityCore/builder_escrow.test.ts +0 -121
  285. package/tests/VelocityCore/decode.test.ts +0 -16
  286. package/tests/VelocityCore/fill_trigger.test.ts +0 -73
  287. package/tests/VelocityCore/instructions.test.ts +0 -46
  288. package/tests/VelocityCore/pdas.test.ts +0 -30
  289. package/tests/VelocityCore/perp_orders.test.ts +0 -205
  290. package/tests/VelocityCore/remainingAccounts.test.ts +0 -72
  291. package/tests/VelocityCore/settlement_liquidation.test.ts +0 -69
  292. package/tests/accounts/customizedCadenceBulkAccountLoader.test.ts +0 -211
  293. package/tests/amm/test.ts +0 -2402
  294. package/tests/auctions/test.ts +0 -81
  295. package/tests/bn/test.ts +0 -355
  296. package/tests/builder/builderFee.test.ts +0 -42
  297. package/tests/ci/verifyConstants.ts +0 -393
  298. package/tests/decode/test.ts +0 -262
  299. package/tests/decode/userAccountBufferStrings.ts +0 -102
  300. package/tests/dlob/helpers.ts +0 -748
  301. package/tests/dlob/test.ts +0 -6969
  302. package/tests/dlob/tickSizeStandardization.ts +0 -545
  303. package/tests/events/parseLogsForCuUsage.ts +0 -139
  304. package/tests/exchangeStatus/test.ts +0 -45
  305. package/tests/insurance/test.ts +0 -40
  306. package/tests/liquidation/test.ts +0 -125
  307. package/tests/oracles/mmOracleGate.test.ts +0 -379
  308. package/tests/oracles/pythPegSnap.test.ts +0 -76
  309. package/tests/sdkParity/enumParity.test.ts +0 -84
  310. package/tests/sdkParity/marginCategoryFill.test.ts +0 -143
  311. package/tests/sdkParity/memcmpOffsets.test.ts +0 -139
  312. package/tests/spot/test.ts +0 -281
  313. package/tests/tx/TransactionConfirmationManager.test.ts +0 -312
  314. package/tests/tx/cachedBlockhashFetcher.test.ts +0 -96
  315. package/tests/tx/priorityFeeCalculator.ts +0 -77
  316. package/tests/tx/priorityFeeStrategy.ts +0 -95
  317. package/tests/user/bankruptcy.ts +0 -165
  318. package/tests/user/feeAndWithdrawLimits.ts +0 -284
  319. package/tests/user/getMarginCalculation.ts +0 -586
  320. package/tests/user/helpers.ts +0 -184
  321. package/tests/user/liquidations.ts +0 -129
  322. package/tests/user/marginCalculations.test.ts +0 -321
  323. package/tests/user/test.ts +0 -833
  324. package/tsconfig.browser.json +0 -18
  325. package/tsconfig.json +0 -36
@@ -1,536 +0,0 @@
1
- import {
2
- DataAndSlot,
3
- AccountSubscriber,
4
- ResubOpts,
5
- BufferAndSlot,
6
- } from './types';
7
- import { AnchorProvider } from '../isomorphic/anchor';
8
- import { VelocityProgram } from '../config';
9
- import {
10
- AccountInfoBase,
11
- AccountInfoWithBase64EncodedData,
12
- AccountInfoWithBase58EncodedData,
13
- createSolanaClient,
14
- isAddress,
15
- Rpc,
16
- RpcSubscriptions,
17
- SolanaRpcSubscriptionsApi,
18
- Address,
19
- Commitment,
20
- } from 'gill';
21
- import { PublicKey } from '@solana/web3.js';
22
- import bs58 from 'bs58';
23
-
24
- /**
25
- * WebSocketAccountSubscriberV2
26
- *
27
- * High-level overview
28
- * - WebSocket-first subscriber for a single Solana account with optional
29
- * polling safeguards when the WS feed goes quiet.
30
- * - Emits decoded updates via `onChange` and maintains the latest
31
- * `{buffer, slot}` and decoded `{data, slot}` internally.
32
- *
33
- * Why polling if this is a WebSocket subscriber?
34
- * - Under real-world conditions, WS notifications can stall or get dropped.
35
- * - When `resubOpts.resubTimeoutMs` elapses without WS data, you can either:
36
- * - resubscribe to the WS stream (default), or
37
- * - enable `resubOpts.usePollingInsteadOfResub` to start polling this single
38
- * account via RPC to check for missed changes.
39
- * - Polling compares the fetched buffer to the last known buffer. If different
40
- * at an equal-or-later slot, it indicates a missed update and we resubscribe
41
- * to WS to restore a clean stream.
42
- *
43
- * Initial fetch (on subscribe)
44
- * - On `subscribe()`, we do a one-time RPC `fetch()` to seed internal state and
45
- * emit the latest account state, ensuring consumers start from ground truth
46
- * even before WS events arrive.
47
- *
48
- * Continuous polling (opt-in)
49
- * - If `usePollingInsteadOfResub` is set, the inactivity timeout triggers a
50
- * polling loop that periodically `fetch()`es the account and checks for
51
- * changes. On change, polling stops and we resubscribe to WS.
52
- * - If not set (default), the inactivity timeout immediately triggers a WS
53
- * resubscription (no polling loop).
54
- *
55
- * Account focus
56
- * - This class tracks exactly one account — the one passed to the constructor —
57
- * which is by definition the account the consumer cares about. The extra
58
- * logic is narrowly scoped to this account to minimize overhead.
59
- *
60
- * Tuning knobs
61
- * - `resubOpts.resubTimeoutMs`: WS inactivity threshold before fallback.
62
- * - `resubOpts.usePollingInsteadOfResub`: toggle polling vs immediate resub.
63
- * - `resubOpts.pollingIntervalMs`: polling cadence (default 30s).
64
- * - `resubOpts.logResubMessages`: verbose logs for diagnostics.
65
- * - `commitment`: WS/RPC commitment used for reads and notifications.
66
- * - `decodeBufferFn`: optional custom decode; defaults to Anchor coder.
67
- *
68
- * Implementation notes
69
- * - Uses `gill` for both WS (`rpcSubscriptions`) and RPC (`rpc`) to match the
70
- * program provider’s RPC endpoint. Handles base58/base64 encoded data.
71
- */
72
- export class WebSocketAccountSubscriberV2<T> implements AccountSubscriber<T> {
73
- dataAndSlot?: DataAndSlot<T>;
74
- bufferAndSlot?: BufferAndSlot;
75
- accountName: string;
76
- logAccountName: string;
77
- program: VelocityProgram;
78
- accountPublicKey: PublicKey;
79
- decodeBufferFn?: (buffer: Buffer) => T;
80
- private _onChange?: (data: T) => void;
81
- get onChange(): (data: T) => void {
82
- if (!this._onChange) {
83
- throw new Error('onChange callback function must be set');
84
- }
85
- return this._onChange;
86
- }
87
- set onChange(onChange: (data: T) => void) {
88
- this._onChange = onChange;
89
- }
90
- listenerId?: number;
91
-
92
- resubOpts: ResubOpts;
93
-
94
- commitment?: Commitment;
95
- isUnsubscribing = false;
96
-
97
- timeoutId?: ReturnType<typeof setTimeout>;
98
- pollingTimeoutId?: ReturnType<typeof setTimeout>;
99
-
100
- receivingData: boolean;
101
-
102
- // Gill client components
103
- private rpc: ReturnType<typeof createSolanaClient>['rpc'];
104
- private rpcSubscriptions: ReturnType<
105
- typeof createSolanaClient
106
- >['rpcSubscriptions'];
107
- private abortController?: AbortController;
108
-
109
- /**
110
- * Create a single-account WebSocket subscriber with optional polling fallback.
111
- *
112
- * @param accountName Name of the Anchor account type (used for default decode).
113
- * @param program Anchor `Program` used for decoding and provider access.
114
- * @param accountPublicKey Public key of the account to track.
115
- * @param decodeBuffer Optional custom decode function; if omitted, uses
116
- * program coder to decode `accountName`.
117
- * @param resubOpts Resubscription/polling options. See class docs.
118
- * @param commitment Commitment for WS and RPC operations.
119
- * @param rpcSubscriptions Optional override/injection for testing.
120
- * @param rpc Optional override/injection for testing.
121
- */
122
- public constructor(
123
- accountName: string,
124
- program: VelocityProgram,
125
- accountPublicKey: PublicKey,
126
- decodeBuffer?: (buffer: Buffer) => T,
127
- resubOpts?: ResubOpts,
128
- commitment?: Commitment,
129
- rpcSubscriptions?: RpcSubscriptions<SolanaRpcSubscriptionsApi> & string,
130
- rpc?: Rpc<any>
131
- ) {
132
- this.accountName = accountName;
133
- this.logAccountName = `${accountName}-${accountPublicKey.toBase58()}-ws-acct-subscriber-v2`;
134
- this.program = program;
135
- this.accountPublicKey = accountPublicKey;
136
- this.decodeBufferFn = decodeBuffer;
137
- this.resubOpts = resubOpts ?? {
138
- resubTimeoutMs: 30000,
139
- usePollingInsteadOfResub: true,
140
- logResubMessages: false,
141
- };
142
- if (
143
- this.resubOpts.resubTimeoutMs != null &&
144
- this.resubOpts.resubTimeoutMs < 1000
145
- ) {
146
- console.log(
147
- `resubTimeoutMs should be at least 1000ms to avoid spamming resub ${this.logAccountName}`
148
- );
149
- }
150
- this.receivingData = false;
151
- if (
152
- ['recent', 'single', 'singleGossip', 'root', 'max'].includes(
153
- (this.program.provider as AnchorProvider).opts.commitment ?? ''
154
- )
155
- ) {
156
- console.warn(
157
- `using commitment ${
158
- (this.program.provider as AnchorProvider).opts.commitment
159
- } that is not supported by gill, this may cause issues`
160
- );
161
- }
162
- this.commitment =
163
- commitment ??
164
- ((this.program.provider as AnchorProvider).opts.commitment as Commitment);
165
-
166
- // Initialize gill client using the same RPC URL as the program provider
167
-
168
- this.rpc = rpc
169
- ? rpc
170
- : (() => {
171
- const rpcUrl = (this.program.provider as AnchorProvider).connection
172
- .rpcEndpoint;
173
- const { rpc } = createSolanaClient({
174
- urlOrMoniker: rpcUrl,
175
- });
176
- return rpc;
177
- })();
178
- this.rpcSubscriptions = rpcSubscriptions
179
- ? rpcSubscriptions
180
- : (() => {
181
- const rpcUrl = (this.program.provider as AnchorProvider).connection
182
- .rpcEndpoint;
183
- const { rpcSubscriptions } = createSolanaClient({
184
- urlOrMoniker: rpcUrl,
185
- });
186
- return rpcSubscriptions;
187
- })();
188
- }
189
-
190
- private async handleNotificationLoop(
191
- subscriptionPromise: Promise<AsyncIterable<any>>
192
- ) {
193
- const subscription = await subscriptionPromise;
194
- for await (const notification of subscription) {
195
- // If we're currently polling and receive a WebSocket event, stop polling
196
- if (this.pollingTimeoutId) {
197
- if (this.resubOpts.logResubMessages) {
198
- console.log(
199
- `[${this.logAccountName}] Received WebSocket event while polling, stopping polling`
200
- );
201
- }
202
- this.stopPolling();
203
- }
204
-
205
- this.receivingData = true;
206
- clearTimeout(this.timeoutId);
207
- this.handleRpcResponse(notification.context, notification.value);
208
- this.setTimeout();
209
- }
210
- }
211
-
212
- /**
213
- * Seeds `dataAndSlot` with an initial `fetch()` (if not already set via `setData`), then opens
214
- * the `gill` `accountNotifications` WebSocket subscription and, if `resubOpts.resubTimeoutMs`
215
- * is set, arms the inactivity watchdog (`setTimeout`). Idempotent: a no-op if already
216
- * subscribed or mid-unsubscribe.
217
- * @param onChange Invoked with the newly decoded account data on each accepted update.
218
- * @throws Error if `accountPublicKey` is not a valid address per `gill`'s `isAddress`.
219
- */
220
- async subscribe(onChange: (data: T) => void): Promise<void> {
221
- if (this.listenerId != null || this.isUnsubscribing) {
222
- if (this.resubOpts.logResubMessages) {
223
- console.log(
224
- `[${this.logAccountName}] Subscribe returning early - listenerId=${this.listenerId}, isUnsubscribing=${this.isUnsubscribing}`
225
- );
226
- }
227
- return;
228
- }
229
-
230
- this.onChange = onChange;
231
- if (!this.dataAndSlot) {
232
- await this.fetch();
233
- }
234
-
235
- // Create abort controller for proper cleanup
236
- const abortController = new AbortController();
237
- this.abortController = abortController;
238
-
239
- this.listenerId = Math.random(); // Unique ID for logging purposes
240
-
241
- if (this.resubOpts.resubTimeoutMs) {
242
- this.receivingData = true;
243
- this.setTimeout();
244
- }
245
-
246
- // Subscribe to account changes using gill's rpcSubscriptions
247
- const pubkey = this.accountPublicKey.toBase58();
248
- if (isAddress(pubkey)) {
249
- const subscriptionPromise = this.rpcSubscriptions
250
- .accountNotifications(pubkey, {
251
- commitment: this.commitment,
252
- encoding: 'base64',
253
- })
254
- .subscribe({
255
- abortSignal: abortController.signal,
256
- });
257
-
258
- // Start notification loop with the subscription promise
259
- this.handleNotificationLoop(subscriptionPromise);
260
- } else {
261
- throw new Error('Invalid account public key');
262
- }
263
- }
264
-
265
- /**
266
- * Seeds or overwrites `dataAndSlot` directly, bypassing RPC. A no-op if the currently cached
267
- * slot is already newer than `slot`.
268
- * @param data Decoded account data to store.
269
- * @param slot Slot the data was observed at; defaults to 0 (the seeded sentinel) if omitted.
270
- */
271
- setData(data: T, slot?: number): void {
272
- const newSlot = slot || 0;
273
- if (this.dataAndSlot && this.dataAndSlot.slot > newSlot) {
274
- return;
275
- }
276
-
277
- this.dataAndSlot = {
278
- data,
279
- slot: newSlot,
280
- };
281
- }
282
-
283
- /**
284
- * Arms the inactivity watchdog: if no WS notification resets this timeout within
285
- * `resubOpts.resubTimeoutMs`, either starts the polling fallback (`usePollingInsteadOfResub`)
286
- * or tears down and recreates the WS subscription. Throws if `onChange` was never set (i.e.
287
- * called outside `subscribe()`'s flow).
288
- */
289
- protected setTimeout(): void {
290
- if (!this._onChange) {
291
- throw new Error('onChange callback function must be set');
292
- }
293
- this.timeoutId = setTimeout(async () => {
294
- if (this.isUnsubscribing) {
295
- // If we are in the process of unsubscribing, do not attempt to resubscribe
296
- if (this.resubOpts.logResubMessages) {
297
- console.log(
298
- `[${this.logAccountName}] Timeout fired but isUnsubscribing=true, skipping resubscribe`
299
- );
300
- }
301
- return;
302
- }
303
-
304
- if (this.receivingData) {
305
- if (this.resubOpts.usePollingInsteadOfResub) {
306
- // Use polling instead of resubscribing
307
- if (this.resubOpts.logResubMessages) {
308
- console.log(
309
- `[${this.logAccountName}] No ws data in ${this.resubOpts.resubTimeoutMs}ms, starting polling - listenerId=${this.listenerId}`
310
- );
311
- }
312
- this.startPolling();
313
- } else {
314
- // Original resubscribe behavior
315
- if (this.resubOpts.logResubMessages) {
316
- console.log(
317
- `No ws data from ${this.logAccountName} in ${this.resubOpts.resubTimeoutMs}ms, resubscribing - listenerId=${this.listenerId}, isUnsubscribing=${this.isUnsubscribing}`
318
- );
319
- }
320
- await this.unsubscribe(true);
321
- this.receivingData = false;
322
- await this.subscribe(this.onChange);
323
- if (this.resubOpts.logResubMessages) {
324
- console.log(
325
- `[${this.logAccountName}] Resubscribe completed - receivingData=${this.receivingData}, listenerId=${this.listenerId}, isUnsubscribing=${this.isUnsubscribing}`
326
- );
327
- }
328
- }
329
- } else {
330
- if (this.resubOpts.logResubMessages) {
331
- console.log(
332
- `[${this.logAccountName}] Timeout fired but receivingData=false, skipping resubscribe`
333
- );
334
- }
335
- }
336
- }, this.resubOpts.resubTimeoutMs);
337
- }
338
-
339
- /**
340
- * Start the polling loop (single-account).
341
- * - Periodically calls `fetch()` and compares buffers to detect changes.
342
- * - On detected change, stops polling and resubscribes to WS.
343
- */
344
- private startPolling(): void {
345
- const pollingInterval = this.resubOpts.pollingIntervalMs || 30000; // Default to 30s
346
-
347
- const poll = async () => {
348
- if (this.isUnsubscribing) {
349
- return;
350
- }
351
-
352
- try {
353
- // Store current data and buffer before polling
354
- const currentBuffer = this.bufferAndSlot?.buffer;
355
-
356
- // Fetch latest account data
357
- await this.fetch();
358
-
359
- // Check if we got new data by comparing buffers
360
- const newBuffer = this.bufferAndSlot?.buffer;
361
- const hasNewData =
362
- newBuffer && (!currentBuffer || !newBuffer.equals(currentBuffer));
363
-
364
- if (hasNewData) {
365
- // New data received, stop polling and resubscribe to websocket
366
- if (this.resubOpts.logResubMessages) {
367
- console.log(
368
- `[${this.logAccountName}] Polling detected account data change, resubscribing to websocket`
369
- );
370
- }
371
- await this.unsubscribe(true);
372
- this.receivingData = false;
373
- await this.subscribe(this.onChange);
374
- } else {
375
- // No new data, continue polling
376
- if (this.resubOpts.logResubMessages) {
377
- console.log(
378
- `[${this.logAccountName}] Polling found no account changes, continuing to poll every ${pollingInterval}ms`
379
- );
380
- }
381
- this.pollingTimeoutId = setTimeout(poll, pollingInterval);
382
- }
383
- } catch (error) {
384
- if (this.resubOpts.logResubMessages) {
385
- console.error(
386
- `[${this.logAccountName}] Error during polling:`,
387
- error
388
- );
389
- }
390
- // On error, continue polling
391
- this.pollingTimeoutId = setTimeout(poll, pollingInterval);
392
- }
393
- };
394
-
395
- // Start polling immediately
396
- poll();
397
- }
398
-
399
- private stopPolling(): void {
400
- if (this.pollingTimeoutId) {
401
- clearTimeout(this.pollingTimeoutId);
402
- this.pollingTimeoutId = undefined;
403
- }
404
- }
405
-
406
- /**
407
- * Fetch the current account state via RPC and process it through the same
408
- * decoding and update pathway as WS notifications.
409
- */
410
- async fetch(): Promise<void> {
411
- // Use gill's rpc for fetching account info
412
- const accountAddress = this.accountPublicKey.toBase58() as Address;
413
- const rpcResponse = await this.rpc
414
- .getAccountInfo(accountAddress, {
415
- commitment: this.commitment,
416
- encoding: 'base64',
417
- })
418
- .send();
419
-
420
- // Convert gill response to match the expected format
421
- const context = {
422
- slot: Number(rpcResponse.context.slot),
423
- };
424
-
425
- const accountInfo = rpcResponse.value;
426
-
427
- this.handleRpcResponse(
428
- { slot: BigInt(context.slot) },
429
- accountInfo ?? undefined
430
- );
431
- }
432
-
433
- /**
434
- * Applies a raw `gill` RPC/WS response: decodes (base58 or base64) and stores it (updating
435
- * `bufferAndSlot`/`dataAndSlot` and invoking `onChange`) only if the slot is not older than
436
- * the cached one and the buffer's bytes actually changed (or this is the first observation).
437
- */
438
- handleRpcResponse(
439
- context: { slot: bigint },
440
- accountInfo?: AccountInfoBase &
441
- (AccountInfoWithBase58EncodedData | AccountInfoWithBase64EncodedData)
442
- ): void {
443
- const newSlot = context.slot;
444
- let newBuffer: Buffer | undefined = undefined;
445
-
446
- if (accountInfo) {
447
- // Extract data from gill response
448
- if (accountInfo.data) {
449
- // Handle different data formats from gill
450
- if (Array.isArray(accountInfo.data)) {
451
- // If it's a tuple [data, encoding]
452
- const [data, encoding] = accountInfo.data;
453
-
454
- if (encoding === 'base58') {
455
- // we know encoding will be base58
456
- // Convert base58 to buffer using bs58
457
- newBuffer = Buffer.from(bs58.decode(data));
458
- } else {
459
- newBuffer = Buffer.from(data, 'base64');
460
- }
461
- }
462
- }
463
- }
464
-
465
- if (!this.bufferAndSlot) {
466
- this.bufferAndSlot = {
467
- buffer: newBuffer,
468
- slot: Number(newSlot),
469
- };
470
- if (newBuffer) {
471
- const account = this.decodeBuffer(newBuffer);
472
- this.dataAndSlot = {
473
- data: account,
474
- slot: Number(newSlot),
475
- };
476
- this.onChange(account);
477
- }
478
- return;
479
- }
480
-
481
- if (Number(newSlot) < this.bufferAndSlot.slot) {
482
- return;
483
- }
484
-
485
- const oldBuffer = this.bufferAndSlot.buffer;
486
- if (newBuffer && (!oldBuffer || !newBuffer.equals(oldBuffer))) {
487
- this.bufferAndSlot = {
488
- buffer: newBuffer,
489
- slot: Number(newSlot),
490
- };
491
- const account = this.decodeBuffer(newBuffer);
492
- this.dataAndSlot = {
493
- data: account,
494
- slot: Number(newSlot),
495
- };
496
- this.onChange(account);
497
- }
498
- }
499
-
500
- /** Decodes a raw account buffer using the constructor-supplied `decodeBufferFn`, or the program's Anchor coder for `accountName` if none was supplied. */
501
- decodeBuffer(buffer: Buffer): T {
502
- if (this.decodeBufferFn) {
503
- return this.decodeBufferFn(buffer);
504
- } else {
505
- return this.program.coder.accounts.decode(this.accountName, buffer);
506
- }
507
- }
508
-
509
- /**
510
- * Tears down the WebSocket subscription (via `abortController`) and cancels any pending resub
511
- * timeout and in-progress polling.
512
- * @param onResub Internal flag set to `true` when called as part of an automatic resubscribe cycle, which preserves `resubOpts.resubTimeoutMs` instead of clearing it. Callers should omit this.
513
- */
514
- unsubscribe(onResub = false): Promise<void> {
515
- if (!onResub && this.resubOpts) {
516
- this.resubOpts.resubTimeoutMs = undefined;
517
- }
518
- this.isUnsubscribing = true;
519
- clearTimeout(this.timeoutId);
520
- this.timeoutId = undefined;
521
-
522
- // Stop polling if active
523
- this.stopPolling();
524
-
525
- // Abort the WebSocket subscription
526
- if (this.abortController) {
527
- this.abortController.abort('unsubscribing');
528
- this.abortController = undefined;
529
- }
530
-
531
- this.listenerId = undefined;
532
- this.isUnsubscribing = false;
533
-
534
- return Promise.resolve();
535
- }
536
- }
@@ -1,171 +0,0 @@
1
- import {
2
- DataAndSlot,
3
- AccountSubscriber,
4
- NotSubscribedError,
5
- InsuranceFundStakeAccountEvents,
6
- InsuranceFundStakeAccountSubscriber,
7
- } from './types';
8
- import StrictEventEmitter from 'strict-event-emitter-types';
9
- import { EventEmitter } from 'events';
10
- import { Commitment, PublicKey } from '@solana/web3.js';
11
- import { WebSocketAccountSubscriber } from './webSocketAccountSubscriber';
12
- import { InsuranceFundStake } from '../types';
13
- import { VelocityProgram } from '../config';
14
-
15
- /**
16
- * Default `InsuranceFundStakeAccountSubscriber` implementation: wraps a single
17
- * `WebSocketAccountSubscriber` for the `InsuranceFundStake` account, mirroring
18
- * `WebSocketUserAccountSubscriber`. `insuranceFundStakeDataAccountSubscriber` throws if accessed
19
- * before `subscribe()` has run.
20
- */
21
- export class WebSocketInsuranceFundStakeAccountSubscriber
22
- implements InsuranceFundStakeAccountSubscriber
23
- {
24
- isSubscribed: boolean;
25
- resubTimeoutMs?: number;
26
- commitment?: Commitment;
27
- program: VelocityProgram;
28
- eventEmitter: StrictEventEmitter<
29
- EventEmitter,
30
- InsuranceFundStakeAccountEvents
31
- >;
32
- insuranceFundStakeAccountPublicKey: PublicKey;
33
-
34
- private _insuranceFundStakeDataAccountSubscriber?: AccountSubscriber<InsuranceFundStake>;
35
- get insuranceFundStakeDataAccountSubscriber(): AccountSubscriber<InsuranceFundStake> {
36
- if (!this._insuranceFundStakeDataAccountSubscriber) {
37
- throw new Error(
38
- 'insuranceFundStakeDataAccountSubscriber accessed before subscribe()'
39
- );
40
- }
41
- return this._insuranceFundStakeDataAccountSubscriber;
42
- }
43
- set insuranceFundStakeDataAccountSubscriber(
44
- subscriber: AccountSubscriber<InsuranceFundStake>
45
- ) {
46
- this._insuranceFundStakeDataAccountSubscriber = subscriber;
47
- }
48
-
49
- /**
50
- * @param program Anchor program providing the connection and coder.
51
- * @param insuranceFundStakeAccountPublicKey Address of the `InsuranceFundStake` account to track.
52
- * @param resubTimeoutMs Resub watchdog timeout (ms) passed through as `ResubOpts.resubTimeoutMs` to the underlying `WebSocketAccountSubscriber`. Unlike other subscribers here, only this single option is exposed (not the full `ResubOpts` shape).
53
- * @param commitment Commitment for the underlying subscription; defaults to the provider's configured commitment.
54
- */
55
- public constructor(
56
- program: VelocityProgram,
57
- insuranceFundStakeAccountPublicKey: PublicKey,
58
- resubTimeoutMs?: number,
59
- commitment?: Commitment
60
- ) {
61
- this.isSubscribed = false;
62
- this.program = program;
63
- this.insuranceFundStakeAccountPublicKey =
64
- insuranceFundStakeAccountPublicKey;
65
- this.eventEmitter = new EventEmitter();
66
- this.resubTimeoutMs = resubTimeoutMs;
67
- this.commitment = commitment;
68
- }
69
-
70
- /**
71
- * Creates the underlying `WebSocketAccountSubscriber` and subscribes it. Idempotent: a no-op
72
- * (returns `true`) if already subscribed.
73
- * @param insuranceFundStakeAccount Optional pre-fetched account data to seed the subscriber with, skipping the initial RPC fetch.
74
- */
75
- async subscribe(
76
- insuranceFundStakeAccount?: InsuranceFundStake
77
- ): Promise<boolean> {
78
- if (this.isSubscribed) {
79
- return true;
80
- }
81
-
82
- this.insuranceFundStakeDataAccountSubscriber =
83
- new WebSocketAccountSubscriber(
84
- 'insuranceFundStake',
85
- this.program,
86
- this.insuranceFundStakeAccountPublicKey,
87
- undefined,
88
- {
89
- resubTimeoutMs: this.resubTimeoutMs,
90
- },
91
- this.commitment
92
- );
93
-
94
- if (insuranceFundStakeAccount) {
95
- this.insuranceFundStakeDataAccountSubscriber.setData(
96
- insuranceFundStakeAccount
97
- );
98
- }
99
-
100
- await this.insuranceFundStakeDataAccountSubscriber.subscribe(
101
- (data: InsuranceFundStake) => {
102
- this.eventEmitter.emit('insuranceFundStakeAccountUpdate', data);
103
- this.eventEmitter.emit('update');
104
- }
105
- );
106
-
107
- this.eventEmitter.emit('update');
108
- this.isSubscribed = true;
109
- return true;
110
- }
111
-
112
- /** Fetches the account once via the underlying `WebSocketAccountSubscriber`. */
113
- async fetch(): Promise<void> {
114
- await Promise.all([this.insuranceFundStakeDataAccountSubscriber.fetch()]);
115
- }
116
-
117
- /** Tears down the underlying WebSocket subscription. A no-op if not subscribed. */
118
- async unsubscribe(): Promise<void> {
119
- if (!this.isSubscribed) {
120
- return;
121
- }
122
-
123
- await Promise.all([
124
- this.insuranceFundStakeDataAccountSubscriber.unsubscribe(),
125
- ]);
126
-
127
- this.isSubscribed = false;
128
- }
129
-
130
- /** Throws `NotSubscribedError` if `subscribe()` has not been called. */
131
- assertIsSubscribed(): void {
132
- if (!this.isSubscribed) {
133
- throw new NotSubscribedError(
134
- 'You must call `subscribe` before using this function'
135
- );
136
- }
137
- }
138
-
139
- /** Throws `NotSubscribedError` if not subscribed. Returns undefined only if subscribed but no data has loaded yet. */
140
- public getInsuranceFundStakeAccountAndSlot():
141
- | DataAndSlot<InsuranceFundStake>
142
- | undefined {
143
- this.assertIsSubscribed();
144
- return this.insuranceFundStakeDataAccountSubscriber.dataAndSlot;
145
- }
146
-
147
- /**
148
- * Applies an externally-obtained account update if `slot` is not older than the currently
149
- * cached slot.
150
- * @param insuranceFundStake Decoded account data to apply.
151
- * @param slot Slot the data was observed at.
152
- */
153
- public updateData(
154
- insuranceFundStake: InsuranceFundStake,
155
- slot: number
156
- ): void {
157
- const currentDataSlot =
158
- this.insuranceFundStakeDataAccountSubscriber.dataAndSlot?.slot || 0;
159
- if (currentDataSlot <= slot) {
160
- this.insuranceFundStakeDataAccountSubscriber.setData(
161
- insuranceFundStake,
162
- slot
163
- );
164
- this.eventEmitter.emit(
165
- 'insuranceFundStakeAccountUpdate',
166
- insuranceFundStake
167
- );
168
- this.eventEmitter.emit('update');
169
- }
170
- }
171
- }