UNPKG

@drift-labs/sdk

Version:
86 lines (85 loc) 3.41 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SlothashSubscriber = void 0; const web3_js_1 = require("@solana/web3.js"); const bytes_1 = require("@coral-xyz/anchor/dist/cjs/utils/bytes"); const anchor_1 = require("@coral-xyz/anchor"); class SlothashSubscriber { constructor(connection, config) { var _a; this.connection = connection; this.isUnsubscribing = false; this.receivingData = false; this.resubTimeoutMs = config === null || config === void 0 ? void 0 : config.resubTimeoutMs; this.commitment = (_a = config === null || config === void 0 ? void 0 : config.commitment) !== null && _a !== void 0 ? _a : 'processed'; if (this.resubTimeoutMs < 1000) { console.log('resubTimeoutMs should be at least 1000ms to avoid spamming resub'); } } async subscribe() { if (this.subscriptionId != null) { return; } const currentAccountData = await this.connection.getAccountInfo(web3_js_1.SYSVAR_SLOT_HASHES_PUBKEY, this.commitment); if (currentAccountData == null) { throw new Error('Failed to retrieve current slot hash'); } this.currentSlothash = deserializeSlothash(currentAccountData.data); this.subscriptionId = this.connection.onAccountChange(web3_js_1.SYSVAR_SLOT_HASHES_PUBKEY, (slothashInfo, context) => { if (!this.currentSlothash || this.currentSlothash.slot < context.slot) { if (this.resubTimeoutMs && !this.isUnsubscribing) { this.receivingData = true; clearTimeout(this.timeoutId); this.setTimeout(); } this.currentSlothash = deserializeSlothash(slothashInfo.data); } }, this.commitment); if (this.resubTimeoutMs) { this.receivingData = true; this.setTimeout(); } } setTimeout() { this.timeoutId = setTimeout(async () => { if (this.isUnsubscribing) { // If we are in the process of unsubscribing, do not attempt to resubscribe return; } if (this.receivingData) { console.log(`No new slot in ${this.resubTimeoutMs}ms, slot subscriber resubscribing`); await this.unsubscribe(true); this.receivingData = false; await this.subscribe(); } }, this.resubTimeoutMs); } getSlothash() { return this.currentSlothash; } async unsubscribe(onResub = false) { if (!onResub) { this.resubTimeoutMs = undefined; } this.isUnsubscribing = true; clearTimeout(this.timeoutId); this.timeoutId = undefined; if (this.subscriptionId != null) { await this.connection.removeSlotChangeListener(this.subscriptionId); this.subscriptionId = undefined; this.isUnsubscribing = false; } else { this.isUnsubscribing = false; } } } exports.SlothashSubscriber = SlothashSubscriber; function deserializeSlothash(data) { const slotNumber = new anchor_1.BN(data.subarray(8, 16), 10, 'le'); const hash = bytes_1.bs58.encode(data.subarray(16, 48)); return { slot: slotNumber.toNumber(), hash, }; }