@drift-labs/sdk
Version:
SDK for Drift Protocol
108 lines (107 loc) • 4.2 kB
JavaScript
"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;