@drift-labs/sdk
Version:
SDK for Drift Protocol
86 lines (85 loc) • 3.41 kB
JavaScript
"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,
};
}