UNPKG

@drift-labs/sdk

Version:
108 lines (107 loc) 4.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SerumSubscriber = void 0; const serum_1 = require("@project-serum/serum"); const anchor_1 = require("@coral-xyz/anchor"); const numericConstants_1 = require("../constants/numericConstants"); class SerumSubscriber { constructor(config) { this.connection = config.connection; this.programId = config.programId; this.marketAddress = config.marketAddress; if (config.accountSubscription.type === 'polling') { this.subscriptionType = 'polling'; this.accountLoader = config.accountSubscription.accountLoader; } else { this.subscriptionType = 'websocket'; } } async subscribe() { if (this.subscribed) { return; } this.market = await serum_1.Market.load(this.connection, this.marketAddress, undefined, this.programId); this.asksAddress = this.market.asksAddress; this.asks = await this.market.loadAsks(this.connection); if (this.subscriptionType === 'websocket') { this.asksCallbackId = this.connection.onAccountChange(this.asksAddress, (accountInfo, ctx) => { this.lastAsksSlot = ctx.slot; this.asks = serum_1.Orderbook.decode(this.market, accountInfo.data); }); } else { this.asksCallbackId = await this.accountLoader.addAccount(this.asksAddress, (buffer, slot) => { this.lastAsksSlot = slot; this.asks = serum_1.Orderbook.decode(this.market, buffer); }); } this.bidsAddress = this.market.bidsAddress; this.bids = await this.market.loadBids(this.connection); if (this.subscriptionType === 'websocket') { this.bidsCallbackId = this.connection.onAccountChange(this.bidsAddress, (accountInfo, ctx) => { this.lastBidsSlot = ctx.slot; this.bids = serum_1.Orderbook.decode(this.market, accountInfo.data); }); } else { this.bidsCallbackId = await this.accountLoader.addAccount(this.bidsAddress, (buffer, slot) => { this.lastBidsSlot = slot; this.bids = serum_1.Orderbook.decode(this.market, buffer); }); } this.subscribed = true; } getBestBid() { const bestBid = this.bids.getL2(1)[0]; if (!bestBid) { return undefined; } return new anchor_1.BN(bestBid[0] * numericConstants_1.PRICE_PRECISION.toNumber()); } getBestAsk() { const bestAsk = this.asks.getL2(1)[0]; if (!bestAsk) { return undefined; } return new anchor_1.BN(bestAsk[0] * numericConstants_1.PRICE_PRECISION.toNumber()); } getL2Bids() { return this.getL2Levels('bids'); } getL2Asks() { return this.getL2Levels('asks'); } *getL2Levels(side) { // @ts-ignore const basePrecision = Math.pow(10, this.market._baseSplTokenDecimals); const pricePrecision = numericConstants_1.PRICE_PRECISION.toNumber(); for (const { price: priceNum, size: sizeNum } of this[side].items(side === 'bids')) { const price = new anchor_1.BN(priceNum * pricePrecision); const size = new anchor_1.BN(sizeNum * basePrecision); yield { price, size, sources: { serum: size, }, }; } } async unsubscribe() { if (!this.subscribed) { return; } // remove listeners if (this.subscriptionType === 'websocket') { await this.connection.removeAccountChangeListener(this.asksCallbackId); await this.connection.removeAccountChangeListener(this.bidsCallbackId); } else { this.accountLoader.removeAccount(this.asksAddress, this.asksCallbackId); this.accountLoader.removeAccount(this.bidsAddress, this.bidsCallbackId); } this.subscribed = false; } } exports.SerumSubscriber = SerumSubscriber;