@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,79 +0,0 @@
1
- import { DataAndSlot, UserAccountEvents, UserAccountSubscriber } from './types';
2
- import { PublicKey } from '@solana/web3.js';
3
- import StrictEventEmitter from 'strict-event-emitter-types';
4
- import { EventEmitter } from 'events';
5
- import { UserAccount } from '../types';
6
-
7
- /**
8
- * Basic implementation of UserAccountSubscriber. It will only take in UserAccount
9
- * data during initialization and will not fetch or subscribe to updates.
10
- */
11
- export class BasicUserAccountSubscriber implements UserAccountSubscriber {
12
- isSubscribed: boolean;
13
- eventEmitter: StrictEventEmitter<EventEmitter, UserAccountEvents>;
14
- userAccountPublicKey: PublicKey;
15
-
16
- callbackId?: string;
17
- errorCallbackId?: string;
18
-
19
- user?: DataAndSlot<UserAccount>;
20
-
21
- /**
22
- * @param userAccountPublicKey Address of the `UserAccount` this subscriber represents (not fetched — used only for identity).
23
- * @param data Optional decoded account data to seed with; if omitted, `getUserAccountAndSlot()` returns undefined until `updateData` is called.
24
- * @param slot Slot `data` was observed at; defaults to 0 (the seeded sentinel) if omitted.
25
- */
26
- public constructor(
27
- userAccountPublicKey: PublicKey,
28
- data?: UserAccount,
29
- slot?: number
30
- ) {
31
- this.isSubscribed = true;
32
- this.eventEmitter = new EventEmitter();
33
- this.userAccountPublicKey = userAccountPublicKey;
34
- // `slot ?? 0` keeps {data, slot} atomic: a seeded account always carries a
35
- // slot (0 = oldest-possible sentinel, overwritten by the first real fetch).
36
- this.user = data ? { data, slot: slot ?? 0 } : undefined;
37
- }
38
-
39
- /** No-op; this subscriber never performs network I/O. Always resolves `true` since `isSubscribed` is already `true` from construction. */
40
- async subscribe(_userAccount?: UserAccount): Promise<boolean> {
41
- return true;
42
- }
43
-
44
- async addToAccountLoader(): Promise<void> {}
45
-
46
- /** No-op; this subscriber never fetches. Data only changes via `updateData`. */
47
- async fetch(): Promise<void> {}
48
-
49
- /** Type predicate: true once `user` has been seeded or set via `updateData`, narrowing `this.user` to non-undefined. */
50
- doesAccountExist(): this is { user: DataAndSlot<UserAccount> } {
51
- return this.user !== undefined;
52
- }
53
-
54
- /** No-op; there is no live subscription to tear down. */
55
- async unsubscribe(): Promise<void> {}
56
-
57
- /** No-op; this subscriber is always considered subscribed and never throws `NotSubscribedError`. */
58
- assertIsSubscribed(): void {}
59
-
60
- /** Returns the currently cached data/slot, or undefined if never seeded/updated. Never throws (unlike other implementations, this subscriber has no "not subscribed" state). */
61
- public getUserAccountAndSlot(): DataAndSlot<UserAccount> | undefined {
62
- return this.user;
63
- }
64
-
65
- /**
66
- * Applies an externally-obtained account update if `slot` is not older than the currently
67
- * cached slot, emitting `userAccountUpdate`/`update` on acceptance. This is the only way this
68
- * subscriber's data changes after construction.
69
- * @param userAccount Decoded account data to apply.
70
- * @param slot Slot the data was observed at.
71
- */
72
- public updateData(userAccount: UserAccount, slot: number): void {
73
- if (!this.user || slot >= this.user.slot) {
74
- this.user = { data: userAccount, slot };
75
- this.eventEmitter.emit('userAccountUpdate', userAccount);
76
- this.eventEmitter.emit('update');
77
- }
78
- }
79
- }
@@ -1,87 +0,0 @@
1
- import {
2
- DataAndSlot,
3
- UserStatsAccountEvents,
4
- UserStatsAccountSubscriber,
5
- } from './types';
6
- import { PublicKey } from '@solana/web3.js';
7
- import StrictEventEmitter from 'strict-event-emitter-types';
8
- import { EventEmitter } from 'events';
9
- import { UserStatsAccount } from '../types';
10
-
11
- /**
12
- * Basic implementation of UserStatsAccountSubscriber. It will only take in UserStatsAccount
13
- * data during initialization and will not fetch or subscribe to updates.
14
- */
15
- export class BasicUserStatsAccountSubscriber
16
- implements UserStatsAccountSubscriber
17
- {
18
- isSubscribed: boolean;
19
- eventEmitter: StrictEventEmitter<EventEmitter, UserStatsAccountEvents>;
20
- userStatsAccountPublicKey: PublicKey;
21
-
22
- callbackId?: string;
23
- errorCallbackId?: string;
24
-
25
- userStats?: DataAndSlot<UserStatsAccount>;
26
-
27
- /**
28
- * @param userStatsAccountPublicKey Address of the `UserStatsAccount` this subscriber represents (not fetched — used only for identity).
29
- * @param data Optional decoded account data to seed with; if omitted, `getUserStatsAccountAndSlot()` returns undefined until `updateData` is called.
30
- * @param slot Slot `data` was observed at; defaults to 0 (the seeded sentinel) if omitted.
31
- */
32
- public constructor(
33
- userStatsAccountPublicKey: PublicKey,
34
- data?: UserStatsAccount,
35
- slot?: number
36
- ) {
37
- this.isSubscribed = true;
38
- this.eventEmitter = new EventEmitter();
39
- this.userStatsAccountPublicKey = userStatsAccountPublicKey;
40
- // `slot ?? 0` keeps {data, slot} atomic: a seeded account always carries a
41
- // slot (0 = oldest-possible sentinel, overwritten by the first real fetch).
42
- this.userStats = data ? { data, slot: slot ?? 0 } : undefined;
43
- }
44
-
45
- /** No-op; this subscriber never performs network I/O. Always resolves `true` since `isSubscribed` is already `true` from construction. */
46
- async subscribe(_userStatsAccount?: UserStatsAccount): Promise<boolean> {
47
- return true;
48
- }
49
-
50
- async addToAccountLoader(): Promise<void> {}
51
-
52
- /** No-op; this subscriber never fetches. Data only changes via `updateData`. */
53
- async fetch(): Promise<void> {}
54
-
55
- /** Type predicate: true once `userStats` has been seeded or set via `updateData`, narrowing `this.userStats` to non-undefined. */
56
- doesAccountExist(): this is { userStats: DataAndSlot<UserStatsAccount> } {
57
- return this.userStats !== undefined;
58
- }
59
-
60
- /** No-op; there is no live subscription to tear down. */
61
- async unsubscribe(): Promise<void> {}
62
-
63
- /** No-op; this subscriber is always considered subscribed and never throws `NotSubscribedError`. */
64
- assertIsSubscribed(): void {}
65
-
66
- /** Returns the currently cached data/slot, or undefined if never seeded/updated. Never throws (unlike other implementations, this subscriber has no "not subscribed" state). */
67
- public getUserStatsAccountAndSlot():
68
- | DataAndSlot<UserStatsAccount>
69
- | undefined {
70
- return this.userStats;
71
- }
72
-
73
- /**
74
- * Applies an externally-obtained account update if `slot` is not older than the currently
75
- * cached slot, emitting `userStatsAccountUpdate`/`update` on acceptance. This is the only way
76
- * this subscriber's data changes after construction.
77
- * @param userStatsAccount Decoded account data to apply.
78
- * @param slot Slot the data was observed at.
79
- */
80
- public updateData(userStatsAccount: UserStatsAccount, slot: number): void {
81
- if (!this.userStats || slot >= this.userStats.slot) {
82
- this.userStats = { data: userStatsAccount, slot };
83
- this.eventEmitter.emit('userStatsAccountUpdate', userStatsAccount);
84
- this.eventEmitter.emit('update');
85
- }
86
- }
87
- }
@@ -1,358 +0,0 @@
1
- import { Commitment, PublicKey } from '@solana/web3.js';
2
- import { v4 as uuidv4 } from 'uuid';
3
- import { BufferAndSlot } from './types';
4
- import { promiseTimeout } from '../util/promiseTimeout';
5
- import { Connection } from '../bankrun/bankrunConnection';
6
- import { GET_MULTIPLE_ACCOUNTS_CHUNK_SIZE } from '../constants/numericConstants';
7
-
8
- /** An account registered with a `BulkAccountLoader`, along with every callback subscribed to its updates (keyed by callback id). */
9
- export type AccountToLoad = {
10
- publicKey: PublicKey;
11
- callbacks: Map<string, (buffer: Buffer, slot: number) => void>;
12
- };
13
-
14
- const oneMinute = 60 * 1000;
15
-
16
- /**
17
- * Batches many accounts behind a single periodic `getMultipleAccounts` RPC poll instead of one
18
- * WebSocket subscription per account. Multiple independent callbacks (e.g. from different
19
- * `PollingUserAccountSubscriber`/`PollingVelocityClientAccountSubscriber` instances) can register
20
- * against the same `publicKey`; polling starts automatically on the first `addAccount` and stops
21
- * when the last callback for the last account is removed. A buffer is only re-delivered to
22
- * callbacks when its slot is not older than the last-seen slot for that account and its bytes
23
- * actually changed, so a callback never observes a stale or duplicate update. `load()` calls are
24
- * coalesced: concurrent callers share one in-flight RPC batch rather than issuing redundant
25
- * requests.
26
- */
27
- export class BulkAccountLoader {
28
- connection: Connection;
29
- commitment: Commitment;
30
- pollingFrequency: number;
31
- accountsToLoad = new Map<string, AccountToLoad>();
32
- bufferAndSlotMap = new Map<string, BufferAndSlot>();
33
- errorCallbacks = new Map<string, (e: Error) => void>();
34
- intervalId?: ReturnType<typeof setTimeout>;
35
- // to handle clients spamming load
36
- loadPromise?: Promise<void>;
37
- private loadPromiseResolver: () => void = () => {};
38
- lastTimeLoadingPromiseCleared = Date.now();
39
- mostRecentSlot = 0;
40
-
41
- /**
42
- * @param connection Connection (or bankrun-compatible shim) used for the batched `getMultipleAccounts` polls.
43
- * @param commitment Commitment level applied to every poll.
44
- * @param pollingFrequency Poll interval in ms; `0` disables automatic polling (`startPolling` becomes a no-op), useful when the loader is driven manually via `load()`.
45
- */
46
- public constructor(
47
- connection: Connection,
48
- commitment: Commitment,
49
- pollingFrequency: number
50
- ) {
51
- this.connection = connection;
52
- this.commitment = commitment;
53
- this.pollingFrequency = pollingFrequency;
54
- }
55
-
56
- /**
57
- * Registers a callback to be invoked whenever `publicKey`'s account data changes on a poll.
58
- * Multiple callbacks may be registered for the same account. Starts polling automatically if
59
- * this is the loader's first account. Awaits any in-flight `load()` before returning so a
60
- * caller can immediately follow with its own `load()` without racing the poll interval.
61
- * @param publicKey Account to track.
62
- * @param callback Invoked with the raw account buffer and the slot it was fetched at whenever the buffer changes at a non-decreasing slot.
63
- * @returns A callback id to pass to `removeAccount` later.
64
- */
65
- public async addAccount(
66
- publicKey: PublicKey,
67
- callback: (buffer: Buffer, slot: number) => void
68
- ): Promise<string> {
69
- if (!publicKey) {
70
- console.trace(`Caught adding blank publickey to bulkAccountLoader`);
71
- }
72
-
73
- const existingSize = this.accountsToLoad.size;
74
-
75
- const callbackId = uuidv4();
76
- const existingAccountToLoad = this.accountsToLoad.get(publicKey.toString());
77
- if (existingAccountToLoad) {
78
- existingAccountToLoad.callbacks.set(callbackId, callback);
79
- } else {
80
- const callbacks = new Map<
81
- string,
82
- (buffer: Buffer, slot: number) => void
83
- >();
84
- callbacks.set(callbackId, callback);
85
- const newAccountToLoad = {
86
- publicKey,
87
- callbacks,
88
- };
89
- this.accountsToLoad.set(publicKey.toString(), newAccountToLoad);
90
- }
91
-
92
- if (existingSize === 0) {
93
- this.startPolling();
94
- }
95
-
96
- // resolve the current loadPromise in case client wants to call load
97
- await this.loadPromise;
98
-
99
- return callbackId;
100
- }
101
-
102
- /**
103
- * Unregisters a callback previously returned by `addAccount`. Once an account has no
104
- * remaining callbacks, its cached buffer/slot is dropped and it stops being polled; if no
105
- * accounts remain at all, polling stops entirely. A no-op if `callbackId` is undefined.
106
- * @param publicKey Account the callback was registered against.
107
- * @param callbackId Id returned by `addAccount`.
108
- */
109
- public removeAccount(
110
- publicKey: PublicKey,
111
- callbackId: string | undefined
112
- ): void {
113
- if (callbackId === undefined) {
114
- return;
115
- }
116
- const existingAccountToLoad = this.accountsToLoad.get(publicKey.toString());
117
- if (existingAccountToLoad) {
118
- existingAccountToLoad.callbacks.delete(callbackId);
119
- if (existingAccountToLoad.callbacks.size === 0) {
120
- this.bufferAndSlotMap.delete(publicKey.toString());
121
- this.accountsToLoad.delete(existingAccountToLoad.publicKey.toString());
122
- }
123
- }
124
-
125
- if (this.accountsToLoad.size === 0) {
126
- this.stopPolling();
127
- }
128
- }
129
-
130
- /**
131
- * Registers a callback invoked whenever a `load()` batch throws (e.g. RPC failure or timeout).
132
- * The loader continues polling afterward; errors do not stop the interval.
133
- * @returns A callback id to pass to `removeErrorCallbacks` later.
134
- */
135
- public addErrorCallbacks(callback: (error: Error) => void): string {
136
- const callbackId = uuidv4();
137
- this.errorCallbacks.set(callbackId, callback);
138
- return callbackId;
139
- }
140
-
141
- /** Unregisters an error callback previously returned by `addErrorCallbacks`. A no-op if `callbackId` is undefined. */
142
- public removeErrorCallbacks(callbackId: string | undefined): void {
143
- if (callbackId === undefined) {
144
- return;
145
- }
146
- this.errorCallbacks.delete(callbackId);
147
- }
148
-
149
- chunks<T>(array: readonly T[], size: number): T[][] {
150
- return new Array(Math.ceil(array.length / size))
151
- .fill(null)
152
- .map((_, index) => index * size)
153
- .map((begin) => array.slice(begin, begin + size));
154
- }
155
-
156
- /**
157
- * Fetches every registered account in one or more chunked, concurrent `getMultipleAccounts`
158
- * batches (via `loadChunk`) and dispatches changed accounts to their callbacks. Concurrent
159
- * calls while a load is already in flight share that same in-flight promise rather than
160
- * issuing a duplicate RPC batch, unless the previous load has been running for over a minute
161
- * (treated as stuck and restarted). On failure, invokes every registered error callback
162
- * instead of throwing.
163
- */
164
- public async load(): Promise<void> {
165
- if (this.loadPromise) {
166
- const now = Date.now();
167
- if (now - this.lastTimeLoadingPromiseCleared > oneMinute) {
168
- this.loadPromise = undefined;
169
- } else {
170
- return this.loadPromise;
171
- }
172
- }
173
-
174
- this.loadPromise = new Promise((resolver) => {
175
- this.loadPromiseResolver = resolver;
176
- });
177
- this.lastTimeLoadingPromiseCleared = Date.now();
178
-
179
- try {
180
- const chunks = this.chunks(
181
- this.chunks(
182
- Array.from(this.accountsToLoad.values()),
183
- GET_MULTIPLE_ACCOUNTS_CHUNK_SIZE
184
- ),
185
- 10
186
- );
187
-
188
- await Promise.all(
189
- chunks.map((chunk) => {
190
- return this.loadChunk(chunk);
191
- })
192
- );
193
- } catch (e) {
194
- console.error(`Error in bulkAccountLoader.load()`);
195
- console.error(e);
196
- const error = e instanceof Error ? e : new Error(String(e));
197
- for (const [_, callback] of this.errorCallbacks) {
198
- callback(error);
199
- }
200
- } finally {
201
- this.loadPromiseResolver();
202
- this.loadPromise = undefined;
203
- }
204
- }
205
-
206
- async loadChunk(accountsToLoadChunks: AccountToLoad[][]): Promise<void> {
207
- if (accountsToLoadChunks.length === 0) {
208
- return;
209
- }
210
-
211
- const requests = new Array<{ methodName: string; args: any }>();
212
- for (const accountsToLoadChunk of accountsToLoadChunks) {
213
- const args = [
214
- accountsToLoadChunk
215
- .filter((accountToLoad) => accountToLoad.callbacks.size > 0)
216
- .map((accountToLoad) => {
217
- return accountToLoad.publicKey.toBase58();
218
- }),
219
- { commitment: this.commitment },
220
- ];
221
-
222
- requests.push({
223
- methodName: 'getMultipleAccounts',
224
- args,
225
- });
226
- }
227
-
228
- const rpcResponses: any | null = await promiseTimeout(
229
- // @ts-ignore
230
- this.connection._rpcBatchRequest(requests),
231
- 10 * 1000 // 30 second timeout
232
- );
233
-
234
- if (rpcResponses === null) {
235
- this.log('request to rpc timed out');
236
- return;
237
- }
238
-
239
- rpcResponses.forEach((rpcResponse: any, i: number) => {
240
- if (!rpcResponse.result) {
241
- console.error('rpc response missing result:');
242
- console.log(JSON.stringify(rpcResponse));
243
- return;
244
- }
245
- const newSlot = rpcResponse.result.context.slot;
246
-
247
- if (newSlot > this.mostRecentSlot) {
248
- this.mostRecentSlot = newSlot;
249
- }
250
-
251
- const accountsToLoad = accountsToLoadChunks[i];
252
- accountsToLoad.forEach((accountToLoad, j) => {
253
- if (accountToLoad.callbacks.size === 0) {
254
- return;
255
- }
256
-
257
- const key = accountToLoad.publicKey.toBase58();
258
- const oldRPCResponse = this.bufferAndSlotMap.get(key);
259
-
260
- if (oldRPCResponse && newSlot < oldRPCResponse.slot) {
261
- return;
262
- }
263
-
264
- let newBuffer: Buffer | undefined = undefined;
265
- if (rpcResponse.result.value[j]) {
266
- const raw: string = rpcResponse.result.value[j].data[0];
267
- const dataType = rpcResponse.result.value[j].data[1];
268
- newBuffer = Buffer.from(raw, dataType);
269
- }
270
-
271
- if (!oldRPCResponse) {
272
- this.bufferAndSlotMap.set(key, {
273
- slot: newSlot,
274
- buffer: newBuffer,
275
- });
276
- this.handleAccountCallbacks(accountToLoad, newBuffer, newSlot);
277
- return;
278
- }
279
-
280
- const oldBuffer = oldRPCResponse.buffer;
281
- if (newBuffer && (!oldBuffer || !newBuffer.equals(oldBuffer))) {
282
- this.bufferAndSlotMap.set(key, {
283
- slot: newSlot,
284
- buffer: newBuffer,
285
- });
286
- this.handleAccountCallbacks(accountToLoad, newBuffer, newSlot);
287
- }
288
- });
289
- });
290
- }
291
-
292
- handleAccountCallbacks(
293
- accountToLoad: AccountToLoad,
294
- buffer: Buffer | undefined,
295
- slot: number
296
- ): void {
297
- if (buffer === undefined) {
298
- return;
299
- }
300
- for (const [_, callback] of accountToLoad.callbacks) {
301
- try {
302
- callback(buffer, slot);
303
- } catch (e) {
304
- console.log('Bulk account load: error in account callback');
305
- console.log('accounto to load', accountToLoad.publicKey.toString());
306
- console.log('buffer', buffer.toString('base64'));
307
- for (const callback of accountToLoad.callbacks.values()) {
308
- console.log('account to load cb', callback);
309
- }
310
- throw e;
311
- }
312
- }
313
- }
314
-
315
- /** Returns the last-fetched raw buffer/slot for `publicKey`, or undefined if it has never been loaded. */
316
- public getBufferAndSlot(publicKey: PublicKey): BufferAndSlot | undefined {
317
- return this.bufferAndSlotMap.get(publicKey.toString());
318
- }
319
-
320
- /** Returns the highest slot number observed across any account fetched by this loader so far. */
321
- public getSlot(): number {
322
- return this.mostRecentSlot;
323
- }
324
-
325
- /** Starts the polling interval if not already running and `pollingFrequency !== 0`. Called automatically by `addAccount`. */
326
- public startPolling(): void {
327
- if (this.intervalId) {
328
- return;
329
- }
330
-
331
- if (this.pollingFrequency !== 0)
332
- this.intervalId = setInterval(
333
- this.load.bind(this),
334
- this.pollingFrequency
335
- );
336
- }
337
-
338
- /** Stops the polling interval, if running. Called automatically by `removeAccount` once no accounts remain. */
339
- public stopPolling(): void {
340
- if (this.intervalId) {
341
- clearInterval(this.intervalId);
342
- this.intervalId = undefined;
343
- }
344
- }
345
-
346
- public log(msg: string): void {
347
- console.log(msg);
348
- }
349
-
350
- /** Restarts polling at a new interval (ms), preserving all registered accounts and callbacks. */
351
- public updatePollingFrequency(pollingFrequency: number): void {
352
- this.stopPolling();
353
- this.pollingFrequency = pollingFrequency;
354
- if (this.accountsToLoad.size > 0) {
355
- this.startPolling();
356
- }
357
- }
358
- }
@@ -1,40 +0,0 @@
1
- import { UserStats } from '../userStats';
2
- import { BulkAccountLoader } from './bulkAccountLoader';
3
- import { PollingUserStatsAccountSubscriber } from './pollingUserStatsAccountSubscriber';
4
-
5
- /**
6
- * Subscribes many `UserStats`s that share a single `BulkAccountLoader` in one batched round trip,
7
- * instead of each `UserStats.subscribe()` triggering its own `addAccount`/`load()`. Registers
8
- * every account's `PollingUserStatsAccountSubscriber` with the loader first, issues one `load()`
9
- * to seed all of them from a single batched `getMultipleAccounts` call, and only then calls
10
- * `userStat.subscribe()` (which becomes a fast no-op fetch since data is already cached). If
11
- * `userStats` is empty, still calls `accountLoader.load()` so any other accounts already
12
- * registered on the loader get polled.
13
- * @param userStats `UserStats` instances to subscribe; each must already be constructed with a `PollingUserStatsAccountSubscriber`.
14
- * @param accountLoader Shared `BulkAccountLoader` batching the underlying RPC polls.
15
- */
16
- export async function bulkPollingUserStatsSubscribe(
17
- userStats: UserStats[],
18
- accountLoader: BulkAccountLoader
19
- ): Promise<void> {
20
- if (userStats.length === 0) {
21
- await accountLoader.load();
22
- return;
23
- }
24
-
25
- await Promise.all(
26
- userStats.map((userStat) => {
27
- return (
28
- userStat.accountSubscriber as PollingUserStatsAccountSubscriber
29
- ).addToAccountLoader();
30
- })
31
- );
32
-
33
- await accountLoader.load();
34
-
35
- await Promise.all(
36
- userStats.map(async (userStat) => {
37
- return userStat.subscribe();
38
- })
39
- );
40
- }
@@ -1,39 +0,0 @@
1
- import { User } from '../user';
2
- import { BulkAccountLoader } from './bulkAccountLoader';
3
- import { PollingUserAccountSubscriber } from './pollingUserAccountSubscriber';
4
-
5
- /**
6
- * Subscribes many `User`s that share a single `BulkAccountLoader` in one batched round trip,
7
- * instead of each `User.subscribe()` triggering its own `addAccount`/`load()`. Registers every
8
- * user's `PollingUserAccountSubscriber` with the loader first, issues one `load()` to seed all of
9
- * them from a single batched `getMultipleAccounts` call, and only then calls `user.subscribe()`
10
- * (which becomes a fast no-op fetch since data is already cached). If `users` is empty, still
11
- * calls `accountLoader.load()` so any other accounts already registered on the loader get polled.
12
- * @param users Users to subscribe; each must already be constructed with a `PollingUserAccountSubscriber`.
13
- * @param accountLoader Shared `BulkAccountLoader` batching the underlying RPC polls.
14
- */
15
- export async function bulkPollingUserSubscribe(
16
- users: User[],
17
- accountLoader: BulkAccountLoader
18
- ): Promise<void> {
19
- if (users.length === 0) {
20
- await accountLoader.load();
21
- return;
22
- }
23
-
24
- await Promise.all(
25
- users.map((user) => {
26
- return (
27
- user.accountSubscriber as PollingUserAccountSubscriber
28
- ).addToAccountLoader();
29
- })
30
- );
31
-
32
- await accountLoader.load();
33
-
34
- await Promise.all(
35
- users.map(async (user) => {
36
- return user.subscribe();
37
- })
38
- );
39
- }