@drift-labs/sdk
Version:
SDK for Drift Protocol
116 lines (115 loc) • 4.83 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.OpenbookV2Subscriber = void 0;
const web3_js_1 = require("@solana/web3.js");
const numericConstants_1 = require("../constants/numericConstants");
const anchor_1 = require("@coral-xyz/anchor");
const openbook_v2_1 = require("@openbook-dex/openbook-v2");
const openbook_json_1 = __importDefault(require("../idl/openbook.json"));
class OpenbookV2Subscriber {
constructor(config) {
this.connection = config.connection;
this.programId = config.programId;
this.marketAddress = config.marketAddress;
this.subscribed = false;
if (config.accountSubscription.type === 'polling') {
this.subscriptionType = 'polling';
this.accountLoader = config.accountSubscription.accountLoader;
}
else {
this.subscriptionType = 'websocket';
}
}
async subscribe() {
if (this.subscribed === true) {
return;
}
const anchorProvider = new anchor_1.AnchorProvider(this.connection, new anchor_1.Wallet(web3_js_1.Keypair.generate()), {});
const openbookV2Program = new anchor_1.Program(openbook_json_1.default, this.programId, anchorProvider);
this.client = new openbook_v2_1.OpenBookV2Client(anchorProvider);
const market = await openbook_v2_1.Market.load(this.client, this.marketAddress);
this.market = await market.loadOrderBook();
if (this.subscriptionType === 'websocket') {
this.marketCallbackId = this.connection.onAccountChange(this.marketAddress, async (accountInfo, _) => {
const marketRaw = openbookV2Program.coder.accounts.decode('Market', accountInfo.data);
const market = new openbook_v2_1.Market(this.client, this.marketAddress, marketRaw);
await market.loadOrderBook();
this.market = market;
});
}
else {
this.marketCallbackId = await this.accountLoader.addAccount(this.marketAddress, async (buffer, _) => {
const marketRaw = openbookV2Program.coder.accounts.decode('Market', buffer);
const market = new openbook_v2_1.Market(this.client, this.marketAddress, marketRaw);
await market.loadOrderBook();
this.market = market;
});
}
this.subscribed = true;
}
getBestBid() {
var _a;
const bestBid = (_a = this.market.bids) === null || _a === void 0 ? void 0 : _a.best();
if (bestBid === undefined) {
return undefined;
}
return this.convertPriceInLotsToPricePrecision(bestBid.priceLots);
}
getBestAsk() {
var _a;
const bestAsk = (_a = this.market.asks) === null || _a === void 0 ? void 0 : _a.best();
if (bestAsk === undefined) {
return undefined;
}
return this.convertPriceInLotsToPricePrecision(bestAsk.priceLots);
}
getL2Bids() {
return this.getL2Levels('bids');
}
getL2Asks() {
return this.getL2Levels('asks');
}
convertSizeInBaseLotsToMarketPrecision(sizeInLots) {
return sizeInLots.mul(this.market.account.baseLotSize);
}
convertPriceInLotsToPricePrecision(priceInLots) {
const adjPrice = priceInLots
.mul(numericConstants_1.PRICE_PRECISION)
.muln(10 **
(this.market.account.baseDecimals - this.market.account.quoteDecimals))
.mul(this.market.account.quoteLotSize)
.div(this.market.account.baseLotSize);
return adjPrice;
}
*getL2Levels(side) {
var _a;
const levels = side === 'bids' ? this.market.bids : this.market.asks;
for (const order of (_a = levels === null || levels === void 0 ? void 0 : levels.items()) !== null && _a !== void 0 ? _a : []) {
const size = this.convertSizeInBaseLotsToMarketPrecision(order.sizeLots);
const price = this.convertPriceInLotsToPricePrecision(order.priceLots);
yield {
price,
size,
sources: {
openbook: size,
},
};
}
}
async unsubscribe() {
if (!this.subscribed) {
return;
}
if (this.subscriptionType === 'websocket') {
await this.connection.removeAccountChangeListener(this.marketCallbackId);
}
else {
this.accountLoader.removeAccount(this.marketAddress, this.marketCallbackId);
}
this.subscribed = false;
}
}
exports.OpenbookV2Subscriber = OpenbookV2Subscriber;