UNPKG

@drift-labs/sdk

Version:
116 lines (115 loc) 4.83 kB
"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;