UNPKG

@drift-labs/sdk-browser

Version:
153 lines (152 loc) 6.85 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CustomizedCadenceBulkAccountLoader = void 0; const numericConstants_1 = require("../constants/numericConstants"); const bulkAccountLoader_1 = require("./bulkAccountLoader"); const uuid_1 = require("uuid"); class CustomizedCadenceBulkAccountLoader extends bulkAccountLoader_1.BulkAccountLoader { constructor(connection, commitment, defaultPollingFrequency) { super(connection, commitment, defaultPollingFrequency); this.customIntervalId = null; this.currentPollingFrequency = null; this.accountFrequencies = new Map(); this.lastPollingTimes = new Map(); this.defaultPollingFrequency = defaultPollingFrequency; } getAccountsToLoad() { const currentTime = Date.now(); const accountsToLoad = []; for (const [key, frequency] of this.accountFrequencies.entries()) { const lastPollTime = this.lastPollingTimes.get(key) || 0; if (currentTime - lastPollTime >= frequency) { const account = this.accountsToLoad.get(key); if (account) { accountsToLoad.push(account); this.lastPollingTimes.set(key, currentTime); } } } return accountsToLoad; } async load() { return this.handleAccountLoading(); } async handleAccountLoading() { const accounts = this.getAccountsToLoad(); if (accounts.length > 0) { const chunks = this.chunks(this.chunks(accounts, numericConstants_1.GET_MULTIPLE_ACCOUNTS_CHUNK_SIZE), 10); await Promise.all(chunks.map((chunk) => { return this.loadChunk(chunk); })); } } /** * Updates the polling frequency for an account. This affects all callbacks attached to this account. * * @param publicKey The public key of the account to set the custom polling frequency for * @param newFrequency The new polling frequency in ms */ setCustomPollingFrequency(publicKey, newFrequency) { const key = publicKey.toBase58(); this.accountFrequencies.set(key, newFrequency); this.lastPollingTimes.set(key, 0); // Reset last polling time to ensure immediate load this.restartPollingIfNeeded(newFrequency); } restartPollingIfNeeded(newFrequency) { if ((this.currentPollingFrequency && newFrequency < this.currentPollingFrequency) || !this.customIntervalId) { this.stopPolling(); this.startPolling(); } } /** * Adds an account to be monitored by the bulk account loader * @param publicKey The public key of the account to monitor * @param callback Function to be called when account data is received * @param customPollingFrequency Optional custom polling frequency in ms for this specific account. * If not provided, will use the default polling frequency * @returns A unique callback ID that can be used to remove this specific callback later * * The method will: * 1. Create a new callback mapping for the account if it doesn't exist already * 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, * we will use the previous frequency. * 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. * 4. Automatically restart polling if this account needs a faster frequency than existing accounts */ async addAccount(publicKey, callback, customPollingFrequency) { const callbackId = (0, uuid_1.v4)(); const existingAccountToLoad = this.accountsToLoad.get(publicKey.toString()); if (existingAccountToLoad) { existingAccountToLoad.callbacks.set(callbackId, callback); } else { const callbacks = new Map(); callbacks.set(callbackId, callback); const newAccountToLoad = { publicKey, callbacks, }; this.accountsToLoad.set(publicKey.toString(), newAccountToLoad); } const key = publicKey.toBase58(); const previousFrequency = this.accountFrequencies.get(key) || this.defaultPollingFrequency; const updatedFrequency = customPollingFrequency && customPollingFrequency < previousFrequency ? customPollingFrequency : previousFrequency; this.accountFrequencies.set(key, updatedFrequency); this.lastPollingTimes.set(key, 0); // Reset last polling time to ensure immediate load this.restartPollingIfNeeded(updatedFrequency); return callbackId; } removeAccount(publicKey, callbackId) { const existingAccountToLoad = this.accountsToLoad.get(publicKey.toString()); if (existingAccountToLoad) { existingAccountToLoad.callbacks.delete(callbackId); if (existingAccountToLoad.callbacks.size === 0) { this.bufferAndSlotMap.delete(publicKey.toString()); this.accountsToLoad.delete(existingAccountToLoad.publicKey.toString()); const key = publicKey.toBase58(); this.accountFrequencies.delete(key); this.lastPollingTimes.delete(key); } } if (this.accountsToLoad.size === 0) { this.stopPolling(); } else { // Restart polling in case we removed the account with the smallest frequency this.restartPollingIfNeeded(this.defaultPollingFrequency); } } getAccountCadence(publicKey) { const key = publicKey.toBase58(); return this.accountFrequencies.get(key) || null; } startPolling() { if (this.customIntervalId) { return; } const minFrequency = Math.min(...Array.from(this.accountFrequencies.values()), this.defaultPollingFrequency); this.currentPollingFrequency = minFrequency; this.customIntervalId = setInterval(() => { this.handleAccountLoading().catch((error) => { console.error('Error in account loading:', error); }); }, minFrequency); } stopPolling() { super.stopPolling(); if (this.customIntervalId) { clearInterval(this.customIntervalId); this.customIntervalId = null; this.currentPollingFrequency = null; } this.lastPollingTimes.clear(); } clearAccountFrequencies() { this.accountFrequencies.clear(); } } exports.CustomizedCadenceBulkAccountLoader = CustomizedCadenceBulkAccountLoader;