diff --git a/src/dlob-subscriber/DLOBSubscriberIO.ts b/src/dlob-subscriber/DLOBSubscriberIO.ts index f59ff4b..f59ea2f 100644 --- a/src/dlob-subscriber/DLOBSubscriberIO.ts +++ b/src/dlob-subscriber/DLOBSubscriberIO.ts @@ -109,6 +109,7 @@ export class DLOBSubscriberIO extends DLOBSubscriber { updateOnChange: false, fallbackL2Generators: [ config.spotMarketSubscribers[market.marketIndex].phoenix, + config.spotMarketSubscribers[market.marketIndex].openbook, ].filter((a) => !!a), }); } diff --git a/src/index.ts b/src/index.ts index b4cc151..1a7abb9 100644 --- a/src/index.ts +++ b/src/index.ts @@ -45,6 +45,7 @@ import { validateDlobQuery, getAccountFromId, getRawAccountFromId, + getOpenbookSubscriber, } from './utils/utils'; import FEATURE_FLAGS from './utils/featureFlags'; import { getDLOBProviderFromOrderSubscriber } from './dlobProvider'; @@ -144,6 +145,7 @@ const initializeAllMarketSubscribers = async (driftClient: DriftClient) => { for (const market of sdkConfig.SPOT_MARKETS) { markets[market.marketIndex] = { phoenix: undefined, + openbook: undefined, }; if (market.phoenixMarket) { @@ -177,6 +179,28 @@ const initializeAllMarketSubscribers = async (driftClient: DriftClient) => { } } } + + if (market.openbookMarket) { + const openbookConfigAccount = + await driftClient.getOpenbookV2FulfillmentConfig(market.openbookMarket); + if (isVariant(openbookConfigAccount.status, 'enabled')) { + const openbookSubscriber = getOpenbookSubscriber( + driftClient, + market, + sdkConfig + ); + await openbookSubscriber.subscribe(); + try { + openbookSubscriber.getL2Asks(); + openbookSubscriber.getL2Bids(); + markets[market.marketIndex].openbook = openbookSubscriber; + } catch (e) { + logger.info( + `Excluding openbook for ${market.marketIndex}, error: ${e}` + ); + } + } + } } return markets; @@ -633,6 +657,7 @@ const main = async (): Promise => { numVammOrders, includeVamm, includePhoenix, + includeOpenbook, includeOracle, } = req.query; @@ -676,7 +701,11 @@ const main = async (): Promise => { } } } - } else if (isSpot && `${includePhoenix}`?.toLowerCase() === 'true') { + } else if ( + isSpot && + `${includePhoenix}`?.toLowerCase() === 'true' && + `${includeOpenbook}`?.toLowerCase() === 'true' + ) { const redisClient = spotMarketRedisMap.get(normedMarketIndex).client; const redisL2 = await redisClient.get( `last_update_orderbook_spot_${normedMarketIndex}` @@ -720,6 +749,8 @@ const main = async (): Promise => { ? [ `${includePhoenix}`.toLowerCase() === 'true' && MARKET_SUBSCRIBERS[normedMarketIndex].phoenix, + `${includeOpenbook}`.toLowerCase() === 'true' && + MARKET_SUBSCRIBERS[normedMarketIndex].openbook, ].filter((a) => !!a) : [], }); @@ -755,6 +786,7 @@ const main = async (): Promise => { depth, includeVamm, includePhoenix, + includeOpenbook, includeOracle, } = req.query; @@ -765,6 +797,7 @@ const main = async (): Promise => { depth: depth as string | undefined, includeVamm: includeVamm as string | undefined, includePhoenix: includePhoenix as string | undefined, + includeOpenbook: includeOpenbook as string | undefined, includeOracle: includeOracle as string | undefined, }); @@ -831,7 +864,8 @@ const main = async (): Promise => { } } else if ( isSpot && - normedParam['includePhoenix']?.toLowerCase() === 'true' + normedParam['includePhoenix']?.toLowerCase() === 'true' && + normedParam['includeOpenbook']?.toLowerCase() === 'true' ) { const redisClient = spotMarketRedisMap.get(normedMarketIndex).client; @@ -880,6 +914,8 @@ const main = async (): Promise => { ? [ `${normedParam['includePhoenix']}`.toLowerCase() === 'true' && MARKET_SUBSCRIBERS[normedMarketIndex].phoenix, + `${normedParam['includeOpenbook']}`.toLowerCase() === + 'true' && MARKET_SUBSCRIBERS[normedMarketIndex].openbook, ].filter((a) => !!a) : [], }); diff --git a/src/publishers/dlobPublisher.ts b/src/publishers/dlobPublisher.ts index 80b0a44..7e024b9 100644 --- a/src/publishers/dlobPublisher.ts +++ b/src/publishers/dlobPublisher.ts @@ -22,7 +22,12 @@ import { import { RedisClient, RedisClientPrefix } from '@drift/common'; import { logger, setLogLevel } from '../utils/logger'; -import { SubscriberLookup, parsePositiveIntArray, sleep } from '../utils/utils'; +import { + SubscriberLookup, + getOpenbookSubscriber, + parsePositiveIntArray, + sleep, +} from '../utils/utils'; import { DLOBSubscriberIO, wsMarketInfo, @@ -233,6 +238,34 @@ const initializeAllMarketSubscribers = async (driftClient: DriftClient) => { } } } + + if (marketConfig.openbookMarket) { + const openbookMarketAccount = + await driftClient.getOpenbookV2FulfillmentConfig( + marketConfig.openbookMarket + ); + + if (isVariant(openbookMarketAccount.status, 'enabled')) { + logger.info( + `Loading openbook subscriber for spot market ${market.marketIndex}` + ); + const openbookSubscriber = getOpenbookSubscriber( + driftClient, + marketConfig, + sdkConfig + ); + await openbookSubscriber.subscribe(); + try { + openbookSubscriber.getL2Asks(); + openbookSubscriber.getL2Bids(); + markets[market.marketIndex].openbook = openbookSubscriber; + } catch (e) { + logger.info( + `Excluding openbook for ${market.marketIndex}, error: ${e}` + ); + } + } + } } return markets; diff --git a/src/publishers/priorityFeesPublisher.ts b/src/publishers/priorityFeesPublisher.ts index e5ac810..0b142b6 100644 --- a/src/publishers/priorityFeesPublisher.ts +++ b/src/publishers/priorityFeesPublisher.ts @@ -212,6 +212,10 @@ const main = async () => { pubkeysForMarket.push(market.phoenixMarket.toString()); } + if (market.openbookMarket) { + pubkeysForMarket.push(market.openbookMarket.toString()); + } + spotMarketPubkeys.push({ marketIndex: market.marketIndex, pubkeys: pubkeysForMarket, diff --git a/src/utils/utils.ts b/src/utils/utils.ts index 1a7c16a..a579df6 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -4,6 +4,7 @@ import { L2OrderBook, L3OrderBook, MarketType, + OpenbookV2Subscriber, OraclePriceData, PerpMarkets, PhoenixSubscriber, @@ -436,9 +437,25 @@ export const getSerumSubscriber = ( }); }; +export const getOpenbookSubscriber = ( + driftClient: DriftClient, + marketConfig: SpotMarketConfig, + sdkConfig +): OpenbookV2Subscriber => { + return new OpenbookV2Subscriber({ + connection: driftClient.connection, + programId: new PublicKey(sdkConfig.OPENBOOK), + marketAddress: marketConfig.openbookMarket, + accountSubscription: { + type: 'websocket', + }, + }); +}; + export type SubscriberLookup = { [marketIndex: number]: { phoenix?: PhoenixSubscriber; serum?: SerumSubscriber; + openbook?: OpenbookV2Subscriber; }; };