@drift-labs/sdk 2.96.0-beta.1 → 2.96.0-beta.3

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 (66) hide show
  1. package/VERSION +1 -1
  2. package/lib/accounts/types.d.ts +0 -8
  3. package/lib/accounts/webSocketAccountSubscriber.d.ts +1 -1
  4. package/lib/accounts/webSocketDriftClientAccountSubscriber.d.ts +3 -3
  5. package/lib/accounts/webSocketProgramAccountSubscriber.d.ts +1 -1
  6. package/lib/driftClient.js +14 -35
  7. package/lib/driftClientConfig.d.ts +0 -6
  8. package/lib/events/eventSubscriber.d.ts +7 -0
  9. package/lib/events/eventSubscriber.js +69 -32
  10. package/lib/events/eventsServerLogProvider.d.ts +21 -0
  11. package/lib/events/eventsServerLogProvider.js +121 -0
  12. package/lib/events/pollingLogProvider.js +1 -1
  13. package/lib/events/types.d.ts +12 -5
  14. package/lib/events/types.js +5 -1
  15. package/lib/events/webSocketLogProvider.js +2 -2
  16. package/lib/orderSubscriber/OrderSubscriber.d.ts +1 -2
  17. package/lib/orderSubscriber/OrderSubscriber.js +4 -19
  18. package/lib/orderSubscriber/types.d.ts +0 -9
  19. package/lib/user.js +4 -11
  20. package/lib/userConfig.d.ts +1 -6
  21. package/lib/userMap/userMap.js +0 -14
  22. package/lib/userMap/userMapConfig.d.ts +0 -7
  23. package/lib/userStatsConfig.d.ts +0 -6
  24. package/package.json +1 -3
  25. package/src/accounts/types.ts +0 -9
  26. package/src/accounts/webSocketAccountSubscriber.ts +1 -1
  27. package/src/accounts/webSocketDriftClientAccountSubscriber.ts +3 -3
  28. package/src/accounts/webSocketProgramAccountSubscriber.ts +1 -1
  29. package/src/driftClient.ts +0 -28
  30. package/src/driftClientConfig.ts +0 -7
  31. package/src/events/eventSubscriber.ts +125 -54
  32. package/src/events/eventsServerLogProvider.ts +152 -0
  33. package/src/events/pollingLogProvider.ts +1 -1
  34. package/src/events/types.ts +29 -6
  35. package/src/events/webSocketLogProvider.ts +4 -4
  36. package/src/orderSubscriber/OrderSubscriber.ts +1 -15
  37. package/src/orderSubscriber/types.ts +0 -10
  38. package/src/user.ts +0 -11
  39. package/src/userConfig.ts +1 -7
  40. package/src/userMap/userMap.ts +1 -17
  41. package/src/userMap/userMapConfig.ts +0 -8
  42. package/src/userStatsConfig.ts +0 -7
  43. package/lib/accounts/grpcAccountSubscriber.d.ts +0 -16
  44. package/lib/accounts/grpcAccountSubscriber.js +0 -155
  45. package/lib/accounts/grpcDriftClientAccountSubscriber.d.ts +0 -13
  46. package/lib/accounts/grpcDriftClientAccountSubscriber.js +0 -96
  47. package/lib/accounts/grpcInsuranceFundStakeAccountSubscriber.d.ts +0 -10
  48. package/lib/accounts/grpcInsuranceFundStakeAccountSubscriber.js +0 -30
  49. package/lib/accounts/grpcProgramAccountSubscriber.d.ts +0 -19
  50. package/lib/accounts/grpcProgramAccountSubscriber.js +0 -161
  51. package/lib/accounts/grpcUserAccountSubscriber.d.ts +0 -10
  52. package/lib/accounts/grpcUserAccountSubscriber.js +0 -28
  53. package/lib/accounts/grpcUserStatsAccountSubscriber.d.ts +0 -10
  54. package/lib/accounts/grpcUserStatsAccountSubscriber.js +0 -28
  55. package/lib/orderSubscriber/grpcSubscription.d.ts +0 -25
  56. package/lib/orderSubscriber/grpcSubscription.js +0 -68
  57. package/lib/userMap/grpcSubscription.d.ts +0 -26
  58. package/lib/userMap/grpcSubscription.js +0 -42
  59. package/src/accounts/grpcAccountSubscriber.ts +0 -158
  60. package/src/accounts/grpcDriftClientAccountSubscriber.ts +0 -196
  61. package/src/accounts/grpcInsuranceFundStakeAccountSubscriber.ts +0 -62
  62. package/src/accounts/grpcProgramAccountSubscriber.ts +0 -181
  63. package/src/accounts/grpcUserAccountSubscriber.ts +0 -48
  64. package/src/accounts/grpcUserStatsAccountSubscriber.ts +0 -51
  65. package/src/orderSubscriber/grpcSubscription.ts +0 -126
  66. package/src/userMap/grpcSubscription.ts +0 -83
@@ -1,21 +1,12 @@
1
1
  import { Commitment, PublicKey } from '@solana/web3.js';
2
2
  import { Order, UserAccount } from '../types';
3
3
  import { DriftClient } from '../driftClient';
4
- import { GrpcConfigs } from '../accounts/types';
5
4
  export type OrderSubscriberConfig = {
6
5
  driftClient: DriftClient;
7
6
  subscriptionConfig: {
8
7
  type: 'polling';
9
8
  frequency: number;
10
9
  commitment?: Commitment;
11
- } | {
12
- type: 'grpc';
13
- skipInitialLoad?: boolean;
14
- resubTimeoutMs?: number;
15
- logResubMessages?: boolean;
16
- resyncIntervalMs?: number;
17
- configs: GrpcConfigs;
18
- commitment?: Commitment;
19
10
  } | {
20
11
  type: 'websocket';
21
12
  skipInitialLoad?: boolean;
package/lib/user.js CHANGED
@@ -15,7 +15,6 @@ const oracles_1 = require("./math/oracles");
15
15
  const tiers_1 = require("./math/tiers");
16
16
  const strictOraclePrice_1 = require("./oracles/strictOraclePrice");
17
17
  const fuel_1 = require("./math/fuel");
18
- const grpcUserAccountSubscriber_1 = require("./accounts/grpcUserAccountSubscriber");
19
18
  class User {
20
19
  get isSubscribed() {
21
20
  return this._isSubscribed && this.accountSubscriber.isSubscribed;
@@ -24,7 +23,7 @@ class User {
24
23
  this._isSubscribed = val;
25
24
  }
26
25
  constructor(config) {
27
- var _a, _b, _c, _d, _e, _f, _g, _h;
26
+ var _a, _b, _c, _d, _e;
28
27
  this._isSubscribed = false;
29
28
  this.driftClient = config.driftClient;
30
29
  this.userAccountPublicKey = config.userAccountPublicKey;
@@ -34,17 +33,11 @@ class User {
34
33
  else if (((_b = config.accountSubscription) === null || _b === void 0 ? void 0 : _b.type) === 'custom') {
35
34
  this.accountSubscriber = config.accountSubscription.userAccountSubscriber;
36
35
  }
37
- else if (((_c = config.accountSubscription) === null || _c === void 0 ? void 0 : _c.type) === 'grpc') {
38
- this.accountSubscriber = new grpcUserAccountSubscriber_1.grpcUserAccountSubscriber(config.accountSubscription.configs, config.driftClient.program, config.userAccountPublicKey, {
39
- resubTimeoutMs: (_d = config.accountSubscription) === null || _d === void 0 ? void 0 : _d.resubTimeoutMs,
40
- logResubMessages: (_e = config.accountSubscription) === null || _e === void 0 ? void 0 : _e.logResubMessages,
41
- });
42
- }
43
36
  else {
44
37
  this.accountSubscriber = new webSocketUserAccountSubscriber_1.WebSocketUserAccountSubscriber(config.driftClient.program, config.userAccountPublicKey, {
45
- resubTimeoutMs: (_f = config.accountSubscription) === null || _f === void 0 ? void 0 : _f.resubTimeoutMs,
46
- logResubMessages: (_g = config.accountSubscription) === null || _g === void 0 ? void 0 : _g.logResubMessages,
47
- }, (_h = config.accountSubscription) === null || _h === void 0 ? void 0 : _h.commitment);
38
+ resubTimeoutMs: (_c = config.accountSubscription) === null || _c === void 0 ? void 0 : _c.resubTimeoutMs,
39
+ logResubMessages: (_d = config.accountSubscription) === null || _d === void 0 ? void 0 : _d.logResubMessages,
40
+ }, (_e = config.accountSubscription) === null || _e === void 0 ? void 0 : _e.commitment);
48
41
  }
49
42
  this.eventEmitter = this.accountSubscriber.eventEmitter;
50
43
  }
@@ -1,7 +1,7 @@
1
1
  import { DriftClient } from './driftClient';
2
2
  import { Commitment, PublicKey } from '@solana/web3.js';
3
3
  import { BulkAccountLoader } from './accounts/bulkAccountLoader';
4
- import { GrpcConfigs, UserAccountSubscriber } from './accounts/types';
4
+ import { UserAccountSubscriber } from './accounts/types';
5
5
  export type UserConfig = {
6
6
  accountSubscription?: UserSubscriptionConfig;
7
7
  driftClient: DriftClient;
@@ -18,9 +18,4 @@ export type UserSubscriptionConfig = {
18
18
  } | {
19
19
  type: 'custom';
20
20
  userAccountSubscriber: UserAccountSubscriber;
21
- } | {
22
- type: 'grpc';
23
- resubTimeoutMs?: number;
24
- logResubMessages?: boolean;
25
- configs: GrpcConfigs;
26
21
  };
@@ -9,7 +9,6 @@ const memcmp_1 = require("../memcmp");
9
9
  const WebsocketSubscription_1 = require("./WebsocketSubscription");
10
10
  const PollingSubscription_1 = require("./PollingSubscription");
11
11
  const user_1 = require("../decode/user");
12
- const grpcSubscription_1 = require("./grpcSubscription");
13
12
  const MAX_USER_ACCOUNT_SIZE_BYTES = 4376;
14
13
  class UserMap {
15
14
  /**
@@ -53,19 +52,6 @@ class UserMap {
53
52
  skipInitialLoad: config.skipInitialLoad,
54
53
  });
55
54
  }
56
- else if (config.subscriptionConfig.type === 'grpc') {
57
- this.subscription = new grpcSubscription_1.grpcSubscription({
58
- configs: config.subscriptionConfig.configs,
59
- userMap: this,
60
- commitment: this.commitment,
61
- resubOpts: {
62
- resubTimeoutMs: config.subscriptionConfig.resubTimeoutMs,
63
- logResubMessages: config.subscriptionConfig.logResubMessages,
64
- },
65
- skipInitialLoad: config.skipInitialLoad,
66
- decodeFn,
67
- });
68
- }
69
55
  else {
70
56
  this.subscription = new WebsocketSubscription_1.WebsocketSubscription({
71
57
  userMap: this,
@@ -1,6 +1,5 @@
1
1
  import { Commitment, Connection } from '@solana/web3.js';
2
2
  import { DriftClient } from '../driftClient';
3
- import { GrpcConfigs } from '../accounts/types';
4
3
  export type UserAccountFilterCriteria = {
5
4
  hasOpenOrders: boolean;
6
5
  };
@@ -18,12 +17,6 @@ export type UserMapConfig = {
18
17
  type: 'polling';
19
18
  frequency: number;
20
19
  commitment?: Commitment;
21
- } | {
22
- type: 'grpc';
23
- configs: GrpcConfigs;
24
- resubTimeoutMs?: number;
25
- logResubMessages?: boolean;
26
- commitment?: Commitment;
27
20
  } | {
28
21
  type: 'websocket';
29
22
  resubTimeoutMs?: number;
@@ -1,7 +1,6 @@
1
1
  import { DriftClient } from './driftClient';
2
2
  import { Commitment, PublicKey } from '@solana/web3.js';
3
3
  import { BulkAccountLoader } from './accounts/bulkAccountLoader';
4
- import { GrpcConfigs } from './accounts/types';
5
4
  export type UserStatsConfig = {
6
5
  accountSubscription?: UserStatsSubscriptionConfig;
7
6
  driftClient: DriftClient;
@@ -17,9 +16,4 @@ export type UserStatsSubscriptionConfig = {
17
16
  accountLoader: BulkAccountLoader;
18
17
  } | {
19
18
  type: 'custom';
20
- } | {
21
- type: 'grpc';
22
- resubTimeoutMs?: number;
23
- logResubMessages?: boolean;
24
- configs: GrpcConfigs;
25
19
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drift-labs/sdk",
3
- "version": "2.96.0-beta.1",
3
+ "version": "2.96.0-beta.3",
4
4
  "main": "lib/index.js",
5
5
  "types": "lib/index.d.ts",
6
6
  "author": "crispheaney",
@@ -37,7 +37,6 @@
37
37
  "@coral-xyz/anchor": "0.28.0",
38
38
  "@coral-xyz/anchor-30": "npm:@coral-xyz/anchor@0.30.1",
39
39
  "@ellipsis-labs/phoenix-sdk": "^1.4.2",
40
- "@grpc/grpc-js": "^1.11.2",
41
40
  "@openbook-dex/openbook-v2": "^0.2.10",
42
41
  "@project-serum/serum": "^0.13.38",
43
42
  "@pythnetwork/client": "2.5.3",
@@ -46,7 +45,6 @@
46
45
  "@solana/spl-token": "0.3.7",
47
46
  "@solana/web3.js": "1.92.3",
48
47
  "@switchboard-xyz/on-demand": "1.2.32",
49
- "@triton-one/yellowstone-grpc": "^0.6.0",
50
48
  "anchor-bankrun": "^0.3.0",
51
49
  "node-cache": "^5.1.2",
52
50
  "rpc-websockets": "7.5.1",
@@ -12,8 +12,6 @@ import { EventEmitter } from 'events';
12
12
  import { Context, PublicKey } from '@solana/web3.js';
13
13
  import { Account } from '@solana/spl-token';
14
14
  import { OracleInfo, OraclePriceData } from '..';
15
- import { CommitmentLevel } from '@triton-one/yellowstone-grpc';
16
- import { ChannelOptions } from '@grpc/grpc-js';
17
15
 
18
16
  export interface AccountSubscriber<T> {
19
17
  dataAndSlot?: DataAndSlot<T>;
@@ -203,10 +201,3 @@ export interface UserStatsAccountSubscriber {
203
201
 
204
202
  getUserStatsAccountAndSlot(): DataAndSlot<UserStatsAccount>;
205
203
  }
206
-
207
- export type GrpcConfigs = {
208
- endpoint: string;
209
- token: string;
210
- commitmentLevel?: CommitmentLevel;
211
- channelOptions?: ChannelOptions;
212
- };
@@ -94,7 +94,7 @@ export class WebSocketAccountSubscriber<T> implements AccountSubscriber<T> {
94
94
  };
95
95
  }
96
96
 
97
- protected setTimeout(): void {
97
+ private setTimeout(): void {
98
98
  if (!this.onChange) {
99
99
  throw new Error('onChange callback function must be set');
100
100
  }
@@ -60,9 +60,9 @@ export class WebSocketDriftClientAccountSubscriber
60
60
  initialSpotMarketAccountData: Map<number, SpotMarketAccount>;
61
61
  initialOraclePriceData: Map<string, OraclePriceData>;
62
62
 
63
- protected isSubscribing = false;
64
- protected subscriptionPromise: Promise<boolean>;
65
- protected subscriptionPromiseResolver: (val: boolean) => void;
63
+ private isSubscribing = false;
64
+ private subscriptionPromise: Promise<boolean>;
65
+ private subscriptionPromiseResolver: (val: boolean) => void;
66
66
 
67
67
  public constructor(
68
68
  program: Program,
@@ -98,7 +98,7 @@ export class WebSocketProgramAccountSubscriber<T>
98
98
  }
99
99
  }
100
100
 
101
- protected setTimeout(): void {
101
+ private setTimeout(): void {
102
102
  if (!this.onChange) {
103
103
  throw new Error('onChange callback function must be set');
104
104
  }
@@ -152,7 +152,6 @@ import { isVersionedTransaction } from './tx/utils';
152
152
  import pythSolanaReceiverIdl from './idl/pyth_solana_receiver.json';
153
153
  import { asV0Tx, PullFeed } from '@switchboard-xyz/on-demand';
154
154
  import switchboardOnDemandIdl from './idl/switchboard_on_demand_30.json';
155
- import { gprcDriftClientAccountSubscriber } from './accounts/grpcDriftClientAccountSubscriber';
156
155
 
157
156
  type RemainingAccountParams = {
158
157
  userAccounts: UserAccount[];
@@ -293,19 +292,6 @@ export class DriftClient {
293
292
  type: 'polling',
294
293
  accountLoader: config.accountSubscription.accountLoader,
295
294
  };
296
- } else if (config.accountSubscription?.type === 'grpc') {
297
- this.userAccountSubscriptionConfig = {
298
- type: 'grpc',
299
- resubTimeoutMs: config.accountSubscription?.resubTimeoutMs,
300
- logResubMessages: config.accountSubscription?.logResubMessages,
301
- configs: config.accountSubscription?.configs,
302
- };
303
- this.userStatsAccountSubscriptionConfig = {
304
- type: 'grpc',
305
- resubTimeoutMs: config.accountSubscription?.resubTimeoutMs,
306
- logResubMessages: config.accountSubscription?.logResubMessages,
307
- configs: config.accountSubscription?.configs,
308
- };
309
295
  } else {
310
296
  this.userAccountSubscriptionConfig = {
311
297
  type: 'websocket',
@@ -352,19 +338,6 @@ export class DriftClient {
352
338
  config.oracleInfos ?? [],
353
339
  noMarketsAndOraclesSpecified
354
340
  );
355
- } else if (config.accountSubscription?.type === 'grpc') {
356
- this.accountSubscriber = new gprcDriftClientAccountSubscriber(
357
- config.accountSubscription.configs,
358
- this.program,
359
- config.perpMarketIndexes ?? [],
360
- config.spotMarketIndexes ?? [],
361
- config.oracleInfos ?? [],
362
- noMarketsAndOraclesSpecified,
363
- {
364
- resubTimeoutMs: config.accountSubscription?.resubTimeoutMs,
365
- logResubMessages: config.accountSubscription?.logResubMessages,
366
- }
367
- );
368
341
  } else {
369
342
  this.accountSubscriber = new WebSocketDriftClientAccountSubscriber(
370
343
  this.program,
@@ -379,7 +352,6 @@ export class DriftClient {
379
352
  config.accountSubscription?.commitment
380
353
  );
381
354
  }
382
-
383
355
  this.eventEmitter = this.accountSubscriber.eventEmitter;
384
356
 
385
357
  this.metricsEventEmitter = new EventEmitter();
@@ -11,7 +11,6 @@ import { BulkAccountLoader } from './accounts/bulkAccountLoader';
11
11
  import { DriftEnv } from './config';
12
12
  import { TxSender } from './tx/types';
13
13
  import { TxHandler, TxHandlerConfig } from './tx/txHandler';
14
- import { GrpcConfigs } from './accounts/types';
15
14
 
16
15
  export type DriftClientConfig = {
17
16
  connection: Connection;
@@ -49,10 +48,4 @@ export type DriftClientSubscriptionConfig =
49
48
  | {
50
49
  type: 'polling';
51
50
  accountLoader: BulkAccountLoader;
52
- }
53
- | {
54
- type: 'grpc';
55
- configs: GrpcConfigs;
56
- resubTimeoutMs?: number;
57
- logResubMessages?: boolean;
58
51
  };
@@ -9,6 +9,10 @@ import {
9
9
  LogProvider,
10
10
  EventSubscriberEvents,
11
11
  WebSocketLogProviderConfig,
12
+ PollingLogProviderConfig,
13
+ EventsServerLogProviderConfig,
14
+ LogProviderType,
15
+ StreamingLogProviderConfig,
12
16
  } from './types';
13
17
  import { TxEventCache } from './txEventCache';
14
18
  import { EventList } from './eventList';
@@ -19,6 +23,7 @@ import { EventEmitter } from 'events';
19
23
  import StrictEventEmitter from 'strict-event-emitter-types';
20
24
  import { getSortFn } from './sort';
21
25
  import { parseLogs } from './parse';
26
+ import { EventsServerLogProvider } from './eventsServerLogProvider';
22
27
 
23
28
  export class EventSubscriber {
24
29
  private address: PublicKey;
@@ -27,6 +32,7 @@ export class EventSubscriber {
27
32
  private awaitTxPromises = new Map<string, Promise<void>>();
28
33
  private awaitTxResolver = new Map<string, () => void>();
29
34
  private logProvider: LogProvider;
35
+ private currentProviderType: LogProviderType;
30
36
  public eventEmitter: StrictEventEmitter<EventEmitter, EventSubscriberEvents>;
31
37
  private lastSeenSlot: number;
32
38
  private lastSeenBlockTime: number | undefined;
@@ -43,22 +49,57 @@ export class EventSubscriber {
43
49
  this.eventListMap = new Map<EventType, EventList<EventType>>();
44
50
  this.eventEmitter = new EventEmitter();
45
51
 
46
- if (this.options.logProviderConfig.type === 'websocket') {
52
+ this.currentProviderType = this.options.logProviderConfig.type;
53
+ this.initializeLogProvider();
54
+ }
55
+
56
+ private initializeLogProvider(subscribe = false) {
57
+ if (this.currentProviderType === 'websocket') {
58
+ const logProviderConfig = this.options
59
+ .logProviderConfig as WebSocketLogProviderConfig;
47
60
  this.logProvider = new WebSocketLogProvider(
48
61
  // @ts-ignore
49
62
  this.connection,
50
63
  this.address,
51
64
  this.options.commitment,
52
- this.options.logProviderConfig.resubTimeoutMs
65
+ logProviderConfig.resubTimeoutMs
53
66
  );
54
- } else {
67
+ } else if (this.currentProviderType === 'polling') {
68
+ const logProviderConfig = this.options
69
+ .logProviderConfig as PollingLogProviderConfig;
55
70
  this.logProvider = new PollingLogProvider(
56
71
  // @ts-ignore
57
72
  this.connection,
58
73
  this.address,
59
- options.commitment,
60
- this.options.logProviderConfig.frequency,
61
- this.options.logProviderConfig.batchSize
74
+ this.options.commitment,
75
+ logProviderConfig.frequency,
76
+ logProviderConfig.batchSize
77
+ );
78
+ } else if (this.currentProviderType === 'events-server') {
79
+ const logProviderConfig = this.options
80
+ .logProviderConfig as EventsServerLogProviderConfig;
81
+ this.logProvider = new EventsServerLogProvider(
82
+ logProviderConfig.url,
83
+ this.options.eventTypes,
84
+ this.options.address ? this.options.address.toString() : undefined
85
+ );
86
+ } else {
87
+ throw new Error(`Invalid log provider type: ${this.currentProviderType}`);
88
+ }
89
+
90
+ if (subscribe) {
91
+ this.logProvider.subscribe(
92
+ (txSig, slot, logs, mostRecentBlockTime, txSigIndex) => {
93
+ this.handleTxLogs(
94
+ txSig,
95
+ slot,
96
+ logs,
97
+ mostRecentBlockTime,
98
+ this.currentProviderType === 'events-server',
99
+ txSigIndex
100
+ );
101
+ },
102
+ true
62
103
  );
63
104
  }
64
105
  }
@@ -77,6 +118,33 @@ export class EventSubscriber {
77
118
  }
78
119
  }
79
120
 
121
+ /**
122
+ * Implements fallback logic for reconnecting to LogProvider. Currently terminates at polling,
123
+ * could be improved to try the original type again after some cooldown.
124
+ */
125
+ private updateFallbackProviderType(
126
+ reconnectAttempts: number,
127
+ maxReconnectAttempts: number
128
+ ) {
129
+ if (reconnectAttempts < maxReconnectAttempts) {
130
+ return;
131
+ }
132
+
133
+ let nextProviderType = this.currentProviderType;
134
+ if (this.currentProviderType === 'events-server') {
135
+ nextProviderType = 'websocket';
136
+ } else if (this.currentProviderType === 'websocket') {
137
+ nextProviderType = 'polling';
138
+ } else if (this.currentProviderType === 'polling') {
139
+ nextProviderType = 'polling';
140
+ }
141
+
142
+ console.log(
143
+ `EventSubscriber: Failing over providerType ${this.currentProviderType} to ${nextProviderType}`
144
+ );
145
+ this.currentProviderType = nextProviderType;
146
+ }
147
+
80
148
  public async subscribe(): Promise<boolean> {
81
149
  try {
82
150
  if (this.logProvider.isSubscribed()) {
@@ -85,52 +153,46 @@ export class EventSubscriber {
85
153
 
86
154
  this.populateInitialEventListMap();
87
155
 
88
- if (this.options.logProviderConfig.type === 'websocket') {
89
- if (this.options.logProviderConfig.resubTimeoutMs) {
90
- if (
91
- this.options.logProviderConfig.maxReconnectAttempts &&
92
- this.options.logProviderConfig.maxReconnectAttempts > 0
93
- ) {
94
- const logProviderConfig = this.options
95
- .logProviderConfig as WebSocketLogProviderConfig;
96
- this.logProvider.eventEmitter.on(
97
- 'reconnect',
98
- (reconnectAttempts) => {
99
- if (
100
- reconnectAttempts > logProviderConfig.maxReconnectAttempts
101
- ) {
102
- console.log('Failing over to polling');
103
- this.logProvider.eventEmitter.removeAllListeners('reconnect');
104
- this.unsubscribe().then(() => {
105
- this.logProvider = new PollingLogProvider(
106
- // @ts-ignore
107
- this.connection,
108
- this.address,
109
- this.options.commitment,
110
- logProviderConfig.fallbackFrequency,
111
- logProviderConfig.fallbackBatchSize
112
- );
113
- this.logProvider.subscribe(
114
- (txSig, slot, logs, mostRecentBlockTime) => {
115
- this.handleTxLogs(
116
- txSig,
117
- slot,
118
- logs,
119
- mostRecentBlockTime
120
- );
121
- },
122
- true
123
- );
124
- });
125
- }
156
+ if (
157
+ this.options.logProviderConfig.type === 'websocket' ||
158
+ this.options.logProviderConfig.type === 'events-server'
159
+ ) {
160
+ const logProviderConfig = this.options
161
+ .logProviderConfig as StreamingLogProviderConfig;
162
+
163
+ if (this.logProvider.eventEmitter) {
164
+ this.logProvider.eventEmitter.on(
165
+ 'reconnect',
166
+ async (reconnectAttempts) => {
167
+ if (reconnectAttempts > logProviderConfig.maxReconnectAttempts) {
168
+ console.log(
169
+ `EventSubscriber: Reconnect attempts ${reconnectAttempts}/${logProviderConfig.maxReconnectAttempts}, reconnecting...`
170
+ );
171
+ this.logProvider.eventEmitter.removeAllListeners('reconnect');
172
+ await this.unsubscribe();
173
+ this.updateFallbackProviderType(
174
+ reconnectAttempts,
175
+ logProviderConfig.maxReconnectAttempts
176
+ );
177
+ this.initializeLogProvider(true);
126
178
  }
127
- );
128
- }
179
+ }
180
+ );
129
181
  }
130
182
  }
131
- this.logProvider.subscribe((txSig, slot, logs, mostRecentBlockTime) => {
132
- this.handleTxLogs(txSig, slot, logs, mostRecentBlockTime);
133
- }, true);
183
+ this.logProvider.subscribe(
184
+ (txSig, slot, logs, mostRecentBlockTime, txSigIndex) => {
185
+ this.handleTxLogs(
186
+ txSig,
187
+ slot,
188
+ logs,
189
+ mostRecentBlockTime,
190
+ this.currentProviderType === 'events-server',
191
+ txSigIndex
192
+ );
193
+ },
194
+ true
195
+ );
134
196
 
135
197
  return true;
136
198
  } catch (e) {
@@ -144,13 +206,20 @@ export class EventSubscriber {
144
206
  txSig: TransactionSignature,
145
207
  slot: number,
146
208
  logs: string[],
147
- mostRecentBlockTime: number | undefined
209
+ mostRecentBlockTime: number | undefined,
210
+ fromEventsServer = false,
211
+ txSigIndex: number | undefined = undefined
148
212
  ): void {
149
- if (this.txEventCache.has(txSig)) {
213
+ if (!fromEventsServer && this.txEventCache.has(txSig)) {
150
214
  return;
151
215
  }
152
216
 
153
- const wrappedEvents = this.parseEventsFromLogs(txSig, slot, logs);
217
+ const wrappedEvents = this.parseEventsFromLogs(
218
+ txSig,
219
+ slot,
220
+ logs,
221
+ txSigIndex
222
+ );
154
223
 
155
224
  for (const wrappedEvent of wrappedEvents) {
156
225
  this.eventListMap.get(wrappedEvent.eventType).insert(wrappedEvent);
@@ -225,7 +294,8 @@ export class EventSubscriber {
225
294
  private parseEventsFromLogs(
226
295
  txSig: TransactionSignature,
227
296
  slot: number,
228
- logs: string[]
297
+ logs: string[],
298
+ txSigIndex: number | undefined
229
299
  ): WrappedEvents {
230
300
  const records = [];
231
301
  // @ts-ignore
@@ -238,7 +308,8 @@ export class EventSubscriber {
238
308
  event.data.txSig = txSig;
239
309
  event.data.slot = slot;
240
310
  event.data.eventType = event.name;
241
- event.data.txSigIndex = runningEventIndex;
311
+ event.data.txSigIndex =
312
+ txSigIndex !== undefined ? txSigIndex : runningEventIndex;
242
313
  records.push(event.data);
243
314
  }
244
315
  runningEventIndex++;