@drift-labs/sdk 2.124.0-beta.7 → 2.124.0-beta.8

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.
package/VERSION CHANGED
@@ -1 +1 @@
1
- 2.124.0-beta.7
1
+ 2.124.0-beta.8
@@ -4,13 +4,20 @@ import { BulkAccountLoader } from './bulkAccountLoader';
4
4
  import { Commitment, Connection, PublicKey } from '@solana/web3.js';
5
5
  export declare class CustomizedCadenceBulkAccountLoader extends BulkAccountLoader {
6
6
  private customIntervalId;
7
+ private currentPollingFrequency;
7
8
  private accountFrequencies;
8
- private lastPollingTime;
9
+ private lastPollingTimes;
9
10
  private defaultPollingFrequency;
10
11
  constructor(connection: Connection, commitment: Commitment, defaultPollingFrequency: number);
11
12
  private getAccountsToLoad;
12
13
  load(): Promise<void>;
13
14
  private handleAccountLoading;
15
+ /**
16
+ * Updates the polling frequency for an account. This affects all callbacks attached to this account.
17
+ *
18
+ * @param publicKey The public key of the account to set the custom polling frequency for
19
+ * @param newFrequency The new polling frequency in ms
20
+ */
14
21
  setCustomPollingFrequency(publicKey: PublicKey, newFrequency: number): void;
15
22
  private restartPollingIfNeeded;
16
23
  /**
@@ -22,13 +29,14 @@ export declare class CustomizedCadenceBulkAccountLoader extends BulkAccountLoade
22
29
  * @returns A unique callback ID that can be used to remove this specific callback later
23
30
  *
24
31
  * The method will:
25
- * 1. Create a new callback mapping for the account
26
- * 2. Set up polling frequency tracking for the account
27
- * 3. Reset last polling time to 0 to ensure immediate data fetch
32
+ * 1. Create a new callback mapping for the account if it doesn't exist already
33
+ * 2. Set up polling frequency tracking for the account if it doesn't exist already. If previous polling frequency is faster than the new one,
34
+ * we will use the previous frequency.
35
+ * 3. Reset last polling time to 0 to ensure data fetch is triggered on the next poll. Note that this does not mean the account will be fetched immediately.
28
36
  * 4. Automatically restart polling if this account needs a faster frequency than existing accounts
29
37
  */
30
38
  addAccount(publicKey: PublicKey, callback: (buffer: Buffer, slot: number) => void, customPollingFrequency?: number): Promise<string>;
31
- removeAccount(publicKey: PublicKey): void;
39
+ removeAccount(publicKey: PublicKey, callbackId: string): void;
32
40
  getAccountCadence(publicKey: PublicKey): number | null;
33
41
  startPolling(): void;
34
42
  stopPolling(): void;
@@ -8,20 +8,21 @@ class CustomizedCadenceBulkAccountLoader extends bulkAccountLoader_1.BulkAccount
8
8
  constructor(connection, commitment, defaultPollingFrequency) {
9
9
  super(connection, commitment, defaultPollingFrequency);
10
10
  this.customIntervalId = null;
11
+ this.currentPollingFrequency = null;
11
12
  this.accountFrequencies = new Map();
12
- this.lastPollingTime = new Map();
13
+ this.lastPollingTimes = new Map();
13
14
  this.defaultPollingFrequency = defaultPollingFrequency;
14
15
  }
15
16
  getAccountsToLoad() {
16
17
  const currentTime = Date.now();
17
18
  const accountsToLoad = [];
18
19
  for (const [key, frequency] of this.accountFrequencies.entries()) {
19
- const lastPollTime = this.lastPollingTime.get(key) || 0;
20
+ const lastPollTime = this.lastPollingTimes.get(key) || 0;
20
21
  if (currentTime - lastPollTime >= frequency) {
21
22
  const account = this.accountsToLoad.get(key);
22
23
  if (account) {
23
24
  accountsToLoad.push(account);
24
- this.lastPollingTime.set(key, currentTime);
25
+ this.lastPollingTimes.set(key, currentTime);
25
26
  }
26
27
  }
27
28
  }
@@ -39,15 +40,22 @@ class CustomizedCadenceBulkAccountLoader extends bulkAccountLoader_1.BulkAccount
39
40
  }));
40
41
  }
41
42
  }
43
+ /**
44
+ * Updates the polling frequency for an account. This affects all callbacks attached to this account.
45
+ *
46
+ * @param publicKey The public key of the account to set the custom polling frequency for
47
+ * @param newFrequency The new polling frequency in ms
48
+ */
42
49
  setCustomPollingFrequency(publicKey, newFrequency) {
43
50
  const key = publicKey.toBase58();
44
51
  this.accountFrequencies.set(key, newFrequency);
45
- this.lastPollingTime.set(key, 0); // Reset last polling time to ensure immediate load
52
+ this.lastPollingTimes.set(key, 0); // Reset last polling time to ensure immediate load
46
53
  this.restartPollingIfNeeded(newFrequency);
47
54
  }
48
55
  restartPollingIfNeeded(newFrequency) {
49
- const currentMinFrequency = Math.min(...Array.from(this.accountFrequencies.values()), this.defaultPollingFrequency);
50
- if (newFrequency < currentMinFrequency || !this.customIntervalId) {
56
+ if ((this.currentPollingFrequency &&
57
+ newFrequency < this.currentPollingFrequency) ||
58
+ !this.customIntervalId) {
51
59
  this.stopPolling();
52
60
  this.startPolling();
53
61
  }
@@ -61,31 +69,49 @@ class CustomizedCadenceBulkAccountLoader extends bulkAccountLoader_1.BulkAccount
61
69
  * @returns A unique callback ID that can be used to remove this specific callback later
62
70
  *
63
71
  * The method will:
64
- * 1. Create a new callback mapping for the account
65
- * 2. Set up polling frequency tracking for the account
66
- * 3. Reset last polling time to 0 to ensure immediate data fetch
72
+ * 1. Create a new callback mapping for the account if it doesn't exist already
73
+ * 2. Set up polling frequency tracking for the account if it doesn't exist already. If previous polling frequency is faster than the new one,
74
+ * we will use the previous frequency.
75
+ * 3. Reset last polling time to 0 to ensure data fetch is triggered on the next poll. Note that this does not mean the account will be fetched immediately.
67
76
  * 4. Automatically restart polling if this account needs a faster frequency than existing accounts
68
77
  */
69
78
  async addAccount(publicKey, callback, customPollingFrequency) {
70
79
  const callbackId = (0, uuid_1.v4)();
71
- const callbacks = new Map();
72
- callbacks.set(callbackId, callback);
73
- const newAccountToLoad = {
74
- publicKey,
75
- callbacks,
76
- };
77
- this.accountsToLoad.set(publicKey.toString(), newAccountToLoad);
80
+ const existingAccountToLoad = this.accountsToLoad.get(publicKey.toString());
81
+ if (existingAccountToLoad) {
82
+ existingAccountToLoad.callbacks.set(callbackId, callback);
83
+ }
84
+ else {
85
+ const callbacks = new Map();
86
+ callbacks.set(callbackId, callback);
87
+ const newAccountToLoad = {
88
+ publicKey,
89
+ callbacks,
90
+ };
91
+ this.accountsToLoad.set(publicKey.toString(), newAccountToLoad);
92
+ }
78
93
  const key = publicKey.toBase58();
79
- const frequency = customPollingFrequency || this.defaultPollingFrequency;
80
- this.accountFrequencies.set(key, frequency);
81
- this.lastPollingTime.set(key, 0); // Reset last polling time to ensure immediate load
82
- this.restartPollingIfNeeded(frequency);
94
+ const previousFrequency = this.accountFrequencies.get(key) || this.defaultPollingFrequency;
95
+ const updatedFrequency = customPollingFrequency && customPollingFrequency < previousFrequency
96
+ ? customPollingFrequency
97
+ : previousFrequency;
98
+ this.accountFrequencies.set(key, updatedFrequency);
99
+ this.lastPollingTimes.set(key, 0); // Reset last polling time to ensure immediate load
100
+ this.restartPollingIfNeeded(updatedFrequency);
83
101
  return callbackId;
84
102
  }
85
- removeAccount(publicKey) {
86
- const key = publicKey.toBase58();
87
- this.accountFrequencies.delete(key);
88
- this.lastPollingTime.delete(key);
103
+ removeAccount(publicKey, callbackId) {
104
+ const existingAccountToLoad = this.accountsToLoad.get(publicKey.toString());
105
+ if (existingAccountToLoad) {
106
+ existingAccountToLoad.callbacks.delete(callbackId);
107
+ if (existingAccountToLoad.callbacks.size === 0) {
108
+ this.bufferAndSlotMap.delete(publicKey.toString());
109
+ this.accountsToLoad.delete(existingAccountToLoad.publicKey.toString());
110
+ const key = publicKey.toBase58();
111
+ this.accountFrequencies.delete(key);
112
+ this.lastPollingTimes.delete(key);
113
+ }
114
+ }
89
115
  if (this.accountsToLoad.size === 0) {
90
116
  this.stopPolling();
91
117
  }
@@ -103,6 +129,7 @@ class CustomizedCadenceBulkAccountLoader extends bulkAccountLoader_1.BulkAccount
103
129
  return;
104
130
  }
105
131
  const minFrequency = Math.min(...Array.from(this.accountFrequencies.values()), this.defaultPollingFrequency);
132
+ this.currentPollingFrequency = minFrequency;
106
133
  this.customIntervalId = setInterval(() => {
107
134
  this.handleAccountLoading().catch((error) => {
108
135
  console.error('Error in account loading:', error);
@@ -114,8 +141,9 @@ class CustomizedCadenceBulkAccountLoader extends bulkAccountLoader_1.BulkAccount
114
141
  if (this.customIntervalId) {
115
142
  clearInterval(this.customIntervalId);
116
143
  this.customIntervalId = null;
144
+ this.currentPollingFrequency = null;
117
145
  }
118
- this.lastPollingTime.clear();
146
+ this.lastPollingTimes.clear();
119
147
  }
120
148
  clearAccountFrequencies() {
121
149
  this.accountFrequencies.clear();
@@ -4,13 +4,20 @@ import { BulkAccountLoader } from './bulkAccountLoader';
4
4
  import { Commitment, Connection, PublicKey } from '@solana/web3.js';
5
5
  export declare class CustomizedCadenceBulkAccountLoader extends BulkAccountLoader {
6
6
  private customIntervalId;
7
+ private currentPollingFrequency;
7
8
  private accountFrequencies;
8
- private lastPollingTime;
9
+ private lastPollingTimes;
9
10
  private defaultPollingFrequency;
10
11
  constructor(connection: Connection, commitment: Commitment, defaultPollingFrequency: number);
11
12
  private getAccountsToLoad;
12
13
  load(): Promise<void>;
13
14
  private handleAccountLoading;
15
+ /**
16
+ * Updates the polling frequency for an account. This affects all callbacks attached to this account.
17
+ *
18
+ * @param publicKey The public key of the account to set the custom polling frequency for
19
+ * @param newFrequency The new polling frequency in ms
20
+ */
14
21
  setCustomPollingFrequency(publicKey: PublicKey, newFrequency: number): void;
15
22
  private restartPollingIfNeeded;
16
23
  /**
@@ -22,13 +29,14 @@ export declare class CustomizedCadenceBulkAccountLoader extends BulkAccountLoade
22
29
  * @returns A unique callback ID that can be used to remove this specific callback later
23
30
  *
24
31
  * The method will:
25
- * 1. Create a new callback mapping for the account
26
- * 2. Set up polling frequency tracking for the account
27
- * 3. Reset last polling time to 0 to ensure immediate data fetch
32
+ * 1. Create a new callback mapping for the account if it doesn't exist already
33
+ * 2. Set up polling frequency tracking for the account if it doesn't exist already. If previous polling frequency is faster than the new one,
34
+ * we will use the previous frequency.
35
+ * 3. Reset last polling time to 0 to ensure data fetch is triggered on the next poll. Note that this does not mean the account will be fetched immediately.
28
36
  * 4. Automatically restart polling if this account needs a faster frequency than existing accounts
29
37
  */
30
38
  addAccount(publicKey: PublicKey, callback: (buffer: Buffer, slot: number) => void, customPollingFrequency?: number): Promise<string>;
31
- removeAccount(publicKey: PublicKey): void;
39
+ removeAccount(publicKey: PublicKey, callbackId: string): void;
32
40
  getAccountCadence(publicKey: PublicKey): number | null;
33
41
  startPolling(): void;
34
42
  stopPolling(): void;
@@ -1 +1 @@
1
- {"version":3,"file":"customizedCadenceBulkAccountLoader.d.ts","sourceRoot":"","sources":["../../../src/accounts/customizedCadenceBulkAccountLoader.ts"],"names":[],"mappings":";;AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAGpE,qBAAa,kCAAmC,SAAQ,iBAAiB;IACxE,OAAO,CAAC,gBAAgB,CAAwB;IAChD,OAAO,CAAC,kBAAkB,CAAsB;IAChD,OAAO,CAAC,eAAe,CAAsB;IAC7C,OAAO,CAAC,uBAAuB,CAAS;gBAGvC,UAAU,EAAE,UAAU,EACtB,UAAU,EAAE,UAAU,EACtB,uBAAuB,EAAE,MAAM;IAShC,OAAO,CAAC,iBAAiB;IAwBZ,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;YAIpB,oBAAoB;IAiB3B,yBAAyB,CAC/B,SAAS,EAAE,SAAS,EACpB,YAAY,EAAE,MAAM,GAClB,IAAI;IAOP,OAAO,CAAC,sBAAsB;IAY9B;;;;;;;;;;;;;OAaG;IACU,UAAU,CACtB,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,EAChD,sBAAsB,CAAC,EAAE,MAAM,GAC7B,OAAO,CAAC,MAAM,CAAC;IAoBX,aAAa,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI;IAazC,iBAAiB,CAAC,SAAS,EAAE,SAAS,GAAG,MAAM,GAAG,IAAI;IAKtD,YAAY,IAAI,IAAI;IAiBpB,WAAW,IAAI,IAAI;IAUnB,uBAAuB,IAAI,IAAI;CAGtC"}
1
+ {"version":3,"file":"customizedCadenceBulkAccountLoader.d.ts","sourceRoot":"","sources":["../../../src/accounts/customizedCadenceBulkAccountLoader.ts"],"names":[],"mappings":";;AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAGpE,qBAAa,kCAAmC,SAAQ,iBAAiB;IACxE,OAAO,CAAC,gBAAgB,CAAwB;IAChD,OAAO,CAAC,uBAAuB,CAAgB;IAC/C,OAAO,CAAC,kBAAkB,CAAsB;IAChD,OAAO,CAAC,gBAAgB,CAAsB;IAC9C,OAAO,CAAC,uBAAuB,CAAS;gBAGvC,UAAU,EAAE,UAAU,EACtB,UAAU,EAAE,UAAU,EACtB,uBAAuB,EAAE,MAAM;IAUhC,OAAO,CAAC,iBAAiB;IAwBZ,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;YAIpB,oBAAoB;IAiBlC;;;;;OAKG;IACI,yBAAyB,CAC/B,SAAS,EAAE,SAAS,EACpB,YAAY,EAAE,MAAM,GAClB,IAAI;IAOP,OAAO,CAAC,sBAAsB;IAW9B;;;;;;;;;;;;;;OAcG;IACU,UAAU,CACtB,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,EAChD,sBAAsB,CAAC,EAAE,MAAM,GAC7B,OAAO,CAAC,MAAM,CAAC;IAmCX,aAAa,CAAC,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI;IAuB7D,iBAAiB,CAAC,SAAS,EAAE,SAAS,GAAG,MAAM,GAAG,IAAI;IAKtD,YAAY,IAAI,IAAI;IAmBpB,WAAW,IAAI,IAAI;IAWnB,uBAAuB,IAAI,IAAI;CAGtC"}
@@ -8,20 +8,21 @@ class CustomizedCadenceBulkAccountLoader extends bulkAccountLoader_1.BulkAccount
8
8
  constructor(connection, commitment, defaultPollingFrequency) {
9
9
  super(connection, commitment, defaultPollingFrequency);
10
10
  this.customIntervalId = null;
11
+ this.currentPollingFrequency = null;
11
12
  this.accountFrequencies = new Map();
12
- this.lastPollingTime = new Map();
13
+ this.lastPollingTimes = new Map();
13
14
  this.defaultPollingFrequency = defaultPollingFrequency;
14
15
  }
15
16
  getAccountsToLoad() {
16
17
  const currentTime = Date.now();
17
18
  const accountsToLoad = [];
18
19
  for (const [key, frequency] of this.accountFrequencies.entries()) {
19
- const lastPollTime = this.lastPollingTime.get(key) || 0;
20
+ const lastPollTime = this.lastPollingTimes.get(key) || 0;
20
21
  if (currentTime - lastPollTime >= frequency) {
21
22
  const account = this.accountsToLoad.get(key);
22
23
  if (account) {
23
24
  accountsToLoad.push(account);
24
- this.lastPollingTime.set(key, currentTime);
25
+ this.lastPollingTimes.set(key, currentTime);
25
26
  }
26
27
  }
27
28
  }
@@ -39,15 +40,22 @@ class CustomizedCadenceBulkAccountLoader extends bulkAccountLoader_1.BulkAccount
39
40
  }));
40
41
  }
41
42
  }
43
+ /**
44
+ * Updates the polling frequency for an account. This affects all callbacks attached to this account.
45
+ *
46
+ * @param publicKey The public key of the account to set the custom polling frequency for
47
+ * @param newFrequency The new polling frequency in ms
48
+ */
42
49
  setCustomPollingFrequency(publicKey, newFrequency) {
43
50
  const key = publicKey.toBase58();
44
51
  this.accountFrequencies.set(key, newFrequency);
45
- this.lastPollingTime.set(key, 0); // Reset last polling time to ensure immediate load
52
+ this.lastPollingTimes.set(key, 0); // Reset last polling time to ensure immediate load
46
53
  this.restartPollingIfNeeded(newFrequency);
47
54
  }
48
55
  restartPollingIfNeeded(newFrequency) {
49
- const currentMinFrequency = Math.min(...Array.from(this.accountFrequencies.values()), this.defaultPollingFrequency);
50
- if (newFrequency < currentMinFrequency || !this.customIntervalId) {
56
+ if ((this.currentPollingFrequency &&
57
+ newFrequency < this.currentPollingFrequency) ||
58
+ !this.customIntervalId) {
51
59
  this.stopPolling();
52
60
  this.startPolling();
53
61
  }
@@ -61,31 +69,49 @@ class CustomizedCadenceBulkAccountLoader extends bulkAccountLoader_1.BulkAccount
61
69
  * @returns A unique callback ID that can be used to remove this specific callback later
62
70
  *
63
71
  * The method will:
64
- * 1. Create a new callback mapping for the account
65
- * 2. Set up polling frequency tracking for the account
66
- * 3. Reset last polling time to 0 to ensure immediate data fetch
72
+ * 1. Create a new callback mapping for the account if it doesn't exist already
73
+ * 2. Set up polling frequency tracking for the account if it doesn't exist already. If previous polling frequency is faster than the new one,
74
+ * we will use the previous frequency.
75
+ * 3. Reset last polling time to 0 to ensure data fetch is triggered on the next poll. Note that this does not mean the account will be fetched immediately.
67
76
  * 4. Automatically restart polling if this account needs a faster frequency than existing accounts
68
77
  */
69
78
  async addAccount(publicKey, callback, customPollingFrequency) {
70
79
  const callbackId = (0, uuid_1.v4)();
71
- const callbacks = new Map();
72
- callbacks.set(callbackId, callback);
73
- const newAccountToLoad = {
74
- publicKey,
75
- callbacks,
76
- };
77
- this.accountsToLoad.set(publicKey.toString(), newAccountToLoad);
80
+ const existingAccountToLoad = this.accountsToLoad.get(publicKey.toString());
81
+ if (existingAccountToLoad) {
82
+ existingAccountToLoad.callbacks.set(callbackId, callback);
83
+ }
84
+ else {
85
+ const callbacks = new Map();
86
+ callbacks.set(callbackId, callback);
87
+ const newAccountToLoad = {
88
+ publicKey,
89
+ callbacks,
90
+ };
91
+ this.accountsToLoad.set(publicKey.toString(), newAccountToLoad);
92
+ }
78
93
  const key = publicKey.toBase58();
79
- const frequency = customPollingFrequency || this.defaultPollingFrequency;
80
- this.accountFrequencies.set(key, frequency);
81
- this.lastPollingTime.set(key, 0); // Reset last polling time to ensure immediate load
82
- this.restartPollingIfNeeded(frequency);
94
+ const previousFrequency = this.accountFrequencies.get(key) || this.defaultPollingFrequency;
95
+ const updatedFrequency = customPollingFrequency && customPollingFrequency < previousFrequency
96
+ ? customPollingFrequency
97
+ : previousFrequency;
98
+ this.accountFrequencies.set(key, updatedFrequency);
99
+ this.lastPollingTimes.set(key, 0); // Reset last polling time to ensure immediate load
100
+ this.restartPollingIfNeeded(updatedFrequency);
83
101
  return callbackId;
84
102
  }
85
- removeAccount(publicKey) {
86
- const key = publicKey.toBase58();
87
- this.accountFrequencies.delete(key);
88
- this.lastPollingTime.delete(key);
103
+ removeAccount(publicKey, callbackId) {
104
+ const existingAccountToLoad = this.accountsToLoad.get(publicKey.toString());
105
+ if (existingAccountToLoad) {
106
+ existingAccountToLoad.callbacks.delete(callbackId);
107
+ if (existingAccountToLoad.callbacks.size === 0) {
108
+ this.bufferAndSlotMap.delete(publicKey.toString());
109
+ this.accountsToLoad.delete(existingAccountToLoad.publicKey.toString());
110
+ const key = publicKey.toBase58();
111
+ this.accountFrequencies.delete(key);
112
+ this.lastPollingTimes.delete(key);
113
+ }
114
+ }
89
115
  if (this.accountsToLoad.size === 0) {
90
116
  this.stopPolling();
91
117
  }
@@ -103,6 +129,7 @@ class CustomizedCadenceBulkAccountLoader extends bulkAccountLoader_1.BulkAccount
103
129
  return;
104
130
  }
105
131
  const minFrequency = Math.min(...Array.from(this.accountFrequencies.values()), this.defaultPollingFrequency);
132
+ this.currentPollingFrequency = minFrequency;
106
133
  this.customIntervalId = setInterval(() => {
107
134
  this.handleAccountLoading().catch((error) => {
108
135
  console.error('Error in account loading:', error);
@@ -114,8 +141,9 @@ class CustomizedCadenceBulkAccountLoader extends bulkAccountLoader_1.BulkAccount
114
141
  if (this.customIntervalId) {
115
142
  clearInterval(this.customIntervalId);
116
143
  this.customIntervalId = null;
144
+ this.currentPollingFrequency = null;
117
145
  }
118
- this.lastPollingTime.clear();
146
+ this.lastPollingTimes.clear();
119
147
  }
120
148
  clearAccountFrequencies() {
121
149
  this.accountFrequencies.clear();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drift-labs/sdk",
3
- "version": "2.124.0-beta.7",
3
+ "version": "2.124.0-beta.8",
4
4
  "main": "lib/node/index.js",
5
5
  "types": "lib/node/index.d.ts",
6
6
  "browser": "./lib/browser/index.js",
@@ -5,8 +5,9 @@ import { v4 as uuidv4 } from 'uuid';
5
5
 
6
6
  export class CustomizedCadenceBulkAccountLoader extends BulkAccountLoader {
7
7
  private customIntervalId: NodeJS.Timeout | null;
8
+ private currentPollingFrequency: number | null;
8
9
  private accountFrequencies: Map<string, number>;
9
- private lastPollingTime: Map<string, number>;
10
+ private lastPollingTimes: Map<string, number>;
10
11
  private defaultPollingFrequency: number;
11
12
 
12
13
  constructor(
@@ -16,8 +17,9 @@ export class CustomizedCadenceBulkAccountLoader extends BulkAccountLoader {
16
17
  ) {
17
18
  super(connection, commitment, defaultPollingFrequency);
18
19
  this.customIntervalId = null;
20
+ this.currentPollingFrequency = null;
19
21
  this.accountFrequencies = new Map();
20
- this.lastPollingTime = new Map();
22
+ this.lastPollingTimes = new Map();
21
23
  this.defaultPollingFrequency = defaultPollingFrequency;
22
24
  }
23
25
 
@@ -32,12 +34,12 @@ export class CustomizedCadenceBulkAccountLoader extends BulkAccountLoader {
32
34
  }> = [];
33
35
 
34
36
  for (const [key, frequency] of this.accountFrequencies.entries()) {
35
- const lastPollTime = this.lastPollingTime.get(key) || 0;
37
+ const lastPollTime = this.lastPollingTimes.get(key) || 0;
36
38
  if (currentTime - lastPollTime >= frequency) {
37
39
  const account = this.accountsToLoad.get(key);
38
40
  if (account) {
39
41
  accountsToLoad.push(account);
40
- this.lastPollingTime.set(key, currentTime);
42
+ this.lastPollingTimes.set(key, currentTime);
41
43
  }
42
44
  }
43
45
  }
@@ -66,23 +68,28 @@ export class CustomizedCadenceBulkAccountLoader extends BulkAccountLoader {
66
68
  }
67
69
  }
68
70
 
71
+ /**
72
+ * Updates the polling frequency for an account. This affects all callbacks attached to this account.
73
+ *
74
+ * @param publicKey The public key of the account to set the custom polling frequency for
75
+ * @param newFrequency The new polling frequency in ms
76
+ */
69
77
  public setCustomPollingFrequency(
70
78
  publicKey: PublicKey,
71
79
  newFrequency: number
72
80
  ): void {
73
81
  const key = publicKey.toBase58();
74
82
  this.accountFrequencies.set(key, newFrequency);
75
- this.lastPollingTime.set(key, 0); // Reset last polling time to ensure immediate load
83
+ this.lastPollingTimes.set(key, 0); // Reset last polling time to ensure immediate load
76
84
  this.restartPollingIfNeeded(newFrequency);
77
85
  }
78
86
 
79
87
  private restartPollingIfNeeded(newFrequency: number): void {
80
- const currentMinFrequency = Math.min(
81
- ...Array.from(this.accountFrequencies.values()),
82
- this.defaultPollingFrequency
83
- );
84
-
85
- if (newFrequency < currentMinFrequency || !this.customIntervalId) {
88
+ if (
89
+ (this.currentPollingFrequency &&
90
+ newFrequency < this.currentPollingFrequency) ||
91
+ !this.customIntervalId
92
+ ) {
86
93
  this.stopPolling();
87
94
  this.startPolling();
88
95
  }
@@ -97,9 +104,10 @@ export class CustomizedCadenceBulkAccountLoader extends BulkAccountLoader {
97
104
  * @returns A unique callback ID that can be used to remove this specific callback later
98
105
  *
99
106
  * The method will:
100
- * 1. Create a new callback mapping for the account
101
- * 2. Set up polling frequency tracking for the account
102
- * 3. Reset last polling time to 0 to ensure immediate data fetch
107
+ * 1. Create a new callback mapping for the account if it doesn't exist already
108
+ * 2. Set up polling frequency tracking for the account if it doesn't exist already. If previous polling frequency is faster than the new one,
109
+ * we will use the previous frequency.
110
+ * 3. Reset last polling time to 0 to ensure data fetch is triggered on the next poll. Note that this does not mean the account will be fetched immediately.
103
111
  * 4. Automatically restart polling if this account needs a faster frequency than existing accounts
104
112
  */
105
113
  public async addAccount(
@@ -108,28 +116,53 @@ export class CustomizedCadenceBulkAccountLoader extends BulkAccountLoader {
108
116
  customPollingFrequency?: number
109
117
  ): Promise<string> {
110
118
  const callbackId = uuidv4();
111
- const callbacks = new Map<string, (buffer: Buffer, slot: number) => void>();
112
- callbacks.set(callbackId, callback);
113
- const newAccountToLoad = {
114
- publicKey,
115
- callbacks,
116
- };
117
- this.accountsToLoad.set(publicKey.toString(), newAccountToLoad);
119
+ const existingAccountToLoad = this.accountsToLoad.get(publicKey.toString());
120
+
121
+ if (existingAccountToLoad) {
122
+ existingAccountToLoad.callbacks.set(callbackId, callback);
123
+ } else {
124
+ const callbacks = new Map<
125
+ string,
126
+ (buffer: Buffer, slot: number) => void
127
+ >();
128
+ callbacks.set(callbackId, callback);
129
+ const newAccountToLoad = {
130
+ publicKey,
131
+ callbacks,
132
+ };
133
+ this.accountsToLoad.set(publicKey.toString(), newAccountToLoad);
134
+ }
118
135
 
119
136
  const key = publicKey.toBase58();
120
- const frequency = customPollingFrequency || this.defaultPollingFrequency;
121
- this.accountFrequencies.set(key, frequency);
122
- this.lastPollingTime.set(key, 0); // Reset last polling time to ensure immediate load
137
+ const previousFrequency =
138
+ this.accountFrequencies.get(key) || this.defaultPollingFrequency;
139
+ const updatedFrequency =
140
+ customPollingFrequency && customPollingFrequency < previousFrequency
141
+ ? customPollingFrequency
142
+ : previousFrequency;
143
+
144
+ this.accountFrequencies.set(key, updatedFrequency);
145
+ this.lastPollingTimes.set(key, 0); // Reset last polling time to ensure immediate load
123
146
 
124
- this.restartPollingIfNeeded(frequency);
147
+ this.restartPollingIfNeeded(updatedFrequency);
125
148
 
126
149
  return callbackId;
127
150
  }
128
151
 
129
- public removeAccount(publicKey: PublicKey): void {
130
- const key = publicKey.toBase58();
131
- this.accountFrequencies.delete(key);
132
- this.lastPollingTime.delete(key);
152
+ public removeAccount(publicKey: PublicKey, callbackId: string): void {
153
+ const existingAccountToLoad = this.accountsToLoad.get(publicKey.toString());
154
+
155
+ if (existingAccountToLoad) {
156
+ existingAccountToLoad.callbacks.delete(callbackId);
157
+
158
+ if (existingAccountToLoad.callbacks.size === 0) {
159
+ this.bufferAndSlotMap.delete(publicKey.toString());
160
+ this.accountsToLoad.delete(existingAccountToLoad.publicKey.toString());
161
+ const key = publicKey.toBase58();
162
+ this.accountFrequencies.delete(key);
163
+ this.lastPollingTimes.delete(key);
164
+ }
165
+ }
133
166
 
134
167
  if (this.accountsToLoad.size === 0) {
135
168
  this.stopPolling();
@@ -154,6 +187,8 @@ export class CustomizedCadenceBulkAccountLoader extends BulkAccountLoader {
154
187
  this.defaultPollingFrequency
155
188
  );
156
189
 
190
+ this.currentPollingFrequency = minFrequency;
191
+
157
192
  this.customIntervalId = setInterval(() => {
158
193
  this.handleAccountLoading().catch((error) => {
159
194
  console.error('Error in account loading:', error);
@@ -167,8 +202,9 @@ export class CustomizedCadenceBulkAccountLoader extends BulkAccountLoader {
167
202
  if (this.customIntervalId) {
168
203
  clearInterval(this.customIntervalId);
169
204
  this.customIntervalId = null;
205
+ this.currentPollingFrequency = null;
170
206
  }
171
- this.lastPollingTime.clear();
207
+ this.lastPollingTimes.clear();
172
208
  }
173
209
 
174
210
  public clearAccountFrequencies(): void {