diff --git a/package.json b/package.json index c613d86..13043b6 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "main": "lib/index.js", "license": "Apache-2.0", "dependencies": { - "@drift-labs/sdk": "2.48.0-beta.0", + "@drift-labs/sdk": "2.48.0-beta.2", "@opentelemetry/api": "^1.1.0", "@opentelemetry/auto-instrumentations-node": "^0.31.1", "@opentelemetry/exporter-prometheus": "^0.31.0", diff --git a/src/dlob-subscriber/DLOBSubscriberIO.ts b/src/dlob-subscriber/DLOBSubscriberIO.ts index 9d2e200..039c738 100644 --- a/src/dlob-subscriber/DLOBSubscriberIO.ts +++ b/src/dlob-subscriber/DLOBSubscriberIO.ts @@ -11,9 +11,9 @@ import { groupL2, isVariant, } from '@drift-labs/sdk'; -import { getOracleForMarket, l2WithBNToStrings } from '../utils/utils'; -import { RedisClient } from '../utils/redisClient'; import { driftEnv } from '../publishers/dlobPublisher'; +import { RedisClient } from '../utils/redisClient'; +import { addOracletoResponse, l2WithBNToStrings } from '../utils/utils'; type wsMarketL2Args = { marketIndex: number; @@ -106,7 +106,8 @@ export class DLOBSubscriberIO extends DLOBSubscriber { l2Formatted['marketName'] = marketName?.toUpperCase(); l2Formatted['marketType'] = marketType?.toLowerCase(); l2Formatted['marketIndex'] = l2Args.marketIndex; - l2Formatted['oracle'] = getOracleForMarket( + addOracletoResponse( + l2Formatted, this.driftClient, l2Args.marketType, l2Args.marketIndex diff --git a/src/index.ts b/src/index.ts index 2b3aab3..c3775e5 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,51 +1,48 @@ import { program } from 'commander'; +import compression from 'compression'; +import cors from 'cors'; import express from 'express'; import rateLimit from 'express-rate-limit'; -import compression from 'compression'; import morgan from 'morgan'; -import cors from 'cors'; -import { Connection, Commitment, PublicKey, Keypair } from '@solana/web3.js'; +import { Commitment, Connection, Keypair, PublicKey } from '@solana/web3.js'; import { - getVariant, - DriftClient, - initialize, - DriftEnv, - UserMap, + BN, + BulkAccountLoader, + DLOBNode, DLOBOrder, DLOBOrders, DLOBOrdersCoder, - DLOBNode, - isVariant, - BN, - groupL2, - Wallet, - UserStatsMap, DLOBSubscriber, - BulkAccountLoader, - DriftClientSubscriptionConfig, - SlotSubscriber, - SlotSource, + DriftClient, + DriftEnv, + UserMap, + UserStatsMap, + Wallet, + getVariant, + groupL2, + initialize, + isVariant, } from '@drift-labs/sdk'; import { logger, setLogLevel } from './utils/logger'; +import { Mutex } from 'async-mutex'; import * as http from 'http'; +import { handleHealthCheck } from './core/metrics'; +import { handleResponseTime } from './core/middleware'; import { - l2WithBNToStrings, - sleep, - getOracleForMarket, - normalizeBatchQueryParams, SubscriberLookup, + addOracletoResponse, errorHandler, getPhoenixSubscriber, getSerumSubscriber, + l2WithBNToStrings, + normalizeBatchQueryParams, + sleep, validateDlobQuery, } from './utils/utils'; -import { handleResponseTime } from './core/middleware'; -import { handleHealthCheck } from './core/metrics'; -import { Mutex } from 'async-mutex'; require('dotenv').config(); const driftEnv = (process.env.ENV || 'devnet') as DriftEnv; @@ -674,7 +671,8 @@ const main = async () => { groupL2(l2, groupingBN, finalDepth) ); if (`${includeOracle}`.toLowerCase() === 'true') { - l2Formatted['oracle'] = getOracleForMarket( + addOracletoResponse( + l2Formatted, driftClient, normedMarketType, normedMarketIndex @@ -687,7 +685,8 @@ const main = async () => { // make the BNs into strings const l2Formatted = l2WithBNToStrings(l2); if (`${includeOracle}`.toLowerCase() === 'true') { - l2Formatted['oracle'] = getOracleForMarket( + addOracletoResponse( + l2Formatted, driftClient, normedMarketType, normedMarketIndex @@ -795,7 +794,8 @@ const main = async () => { groupL2(l2, groupingBN, finalDepth) ); if (`${normedParam['includeOracle']}`.toLowerCase() === 'true') { - l2Formatted['oracle'] = getOracleForMarket( + addOracletoResponse( + l2Formatted, driftClient, normedMarketType, normedMarketIndex @@ -806,7 +806,8 @@ const main = async () => { // make the BNs into strings const l2Formatted = l2WithBNToStrings(l2); if (`${normedParam['includeOracle']}`.toLowerCase() === 'true') { - l2Formatted['oracle'] = getOracleForMarket( + addOracletoResponse( + l2Formatted, driftClient, normedMarketType, normedMarketIndex @@ -856,7 +857,8 @@ const main = async () => { } if (`${includeOracle}`.toLowerCase() === 'true') { - l3['oracle'] = getOracleForMarket( + addOracletoResponse( + l3, driftClient, normedMarketType, normedMarketIndex @@ -887,4 +889,4 @@ async function recursiveTryCatch(f: () => void) { recursiveTryCatch(() => main()); -export { sdkConfig, endpoint, wsEndpoint, driftEnv, commitHash, driftClient }; +export { commitHash, driftClient, driftEnv, endpoint, sdkConfig, wsEndpoint }; diff --git a/src/utils/featureFlags.ts b/src/utils/featureFlags.ts new file mode 100644 index 0000000..d5bfb19 --- /dev/null +++ b/src/utils/featureFlags.ts @@ -0,0 +1,7 @@ +// TODO : Is it worth adding proper infrastructure for feature flags? .. Would allow more powerful things like toggling them at runtime rather than being hardcoded +export const FEATURE_FLAGS = { + OLD_ORACLE_PRICE_IN_L2: true, // TODO : Remove this once we're confident that NEW_ORACLE_DATA_IN_L2 works .. delete corresponding code + NEW_ORACLE_DATA_IN_L2: true, +}; + +export default FEATURE_FLAGS; diff --git a/src/utils/utils.ts b/src/utils/utils.ts index 848de31..4105eba 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -2,7 +2,9 @@ import { DriftClient, DriftEnv, L2OrderBook, + L3OrderBook, MarketType, + OraclePriceData, PerpMarkets, PhoenixSubscriber, PublicKey, @@ -13,6 +15,7 @@ import { } from '@drift-labs/sdk'; import { logger } from './logger'; import { NextFunction, Request, Response } from 'express'; +import FEATURE_FLAGS from './featureFlags'; export const l2WithBNToStrings = (l2: L2OrderBook): any => { for (const key of Object.keys(l2)) { @@ -48,6 +51,67 @@ export const getOracleForMarket = ( } }; +type SerializableOraclePriceData = { + price: string; + slot: string; + confidence: string; + hasSufficientNumberOfDataPoints: boolean; + twap?: string; + twapConfidence?: string; +}; + +const getSerializableOraclePriceData = ( + oraclePriceData: OraclePriceData +): SerializableOraclePriceData => { + return { + price: oraclePriceData.price?.toString?.(), + slot: oraclePriceData.slot?.toString?.(), + confidence: oraclePriceData.confidence?.toString?.(), + hasSufficientNumberOfDataPoints: + oraclePriceData.hasSufficientNumberOfDataPoints, + twap: oraclePriceData.twap?.toString?.(), + twapConfidence: oraclePriceData.twapConfidence?.toString?.(), + }; +}; + +export const getOracleDataForMarket = ( + driftClient: DriftClient, + marketType: MarketType, + marketIndex: number +): SerializableOraclePriceData => { + if (isVariant(marketType, 'spot')) { + return getSerializableOraclePriceData( + driftClient.getOracleDataForSpotMarket(marketIndex) + ); + } else if (isVariant(marketType, 'perp')) { + return getSerializableOraclePriceData( + driftClient.getOracleDataForPerpMarket(marketIndex) + ); + } +}; + +export const addOracletoResponse = ( + response: L2OrderBook | L3OrderBook, + driftClient: DriftClient, + marketType: MarketType, + marketIndex: number +): void => { + if (FEATURE_FLAGS.OLD_ORACLE_PRICE_IN_L2) { + response['oracle'] = getOracleForMarket( + driftClient, + marketType, + marketIndex + ); + } + if (FEATURE_FLAGS.NEW_ORACLE_DATA_IN_L2) { + response['oracleData'] = getOracleDataForMarket( + driftClient, + marketType, + marketIndex + ); + } +}; + /** * Takes in a req.query like: `{ * marketName: 'SOL-PERP,BTC-PERP,ETH-PERP', diff --git a/yarn.lock b/yarn.lock index 4c93c7b..cd8e73d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -80,10 +80,10 @@ enabled "2.0.x" kuler "^2.0.0" -"@drift-labs/sdk@2.48.0-beta.0": - version "2.48.0-beta.0" - resolved "https://registry.yarnpkg.com/@drift-labs/sdk/-/sdk-2.48.0-beta.0.tgz#dcda51d878bf458cc5e070528f8b0714f9c53589" - integrity sha512-okRb3ErrApZvks24AFMwLrmsdrcntLAUTRNcSfutg/Ri10hjMAIaiRdsYSbMZcDGWgjRq/+sozKIqiqfd7xfpg== +"@drift-labs/sdk@2.48.0-beta.2": + version "2.48.0-beta.2" + resolved "https://registry.yarnpkg.com/@drift-labs/sdk/-/sdk-2.48.0-beta.2.tgz#447cdd132e99e7283eecb96adbce6709724f4e3f" + integrity sha512-zp0OxvuwDDLoqN1GfknPuEDCwPVzLRvRVpnrJFzeTNgBS1ish0ZmqtM5URFMHuXJ9ZaEt3gezqhhlqRID917rQ== dependencies: "@coral-xyz/anchor" "0.28.1-beta.2" "@ellipsis-labs/phoenix-sdk" "^1.4.2"