disable orders endpoint, add flag to disable gpa refresh

This commit is contained in:
wphan
2023-11-30 12:20:08 -08:00
parent 3497795a56
commit 9a371ce54e
2 changed files with 235 additions and 207 deletions

View File

@@ -46,6 +46,7 @@ import {
sleep,
validateDlobQuery,
} from './utils/utils';
import FEATURE_FLAGS from './utils/featureFlags';
import {
DLOBProvider,
getDLOBProviderFromOrderSubscriber,
@@ -174,7 +175,7 @@ const main = async () => {
const clearingHousePublicKey = new PublicKey(sdkConfig.DRIFT_PROGRAM_ID);
const connection = new Connection(endpoint, {
wsEndpoint: wsEndpoint,
wsEndpoint,
commitment: stateCommitment,
});
@@ -274,7 +275,8 @@ const main = async () => {
`dlob provider initialized in ${Date.now() - initDLOBProviderStart} ms`
);
logger.info(`dlob provider size ${dlobProvider.size()}`);
if (useWebsocket) {
if (useWebsocket && !FEATURE_FLAGS.DISABLE_GPA_REFRESH) {
const recursiveFetch = (delay = WS_FALLBACK_FETCH_INTERVAL) => {
setTimeout(() => {
dlobProvider.fetch().then(() => {
@@ -322,218 +324,234 @@ const main = async () => {
app.get('/startup', handleStartup);
app.get('/', handleHealthCheck(slotSource));
app.get('/orders/json/raw', async (_req, res, next) => {
try {
// object with userAccount key and orders object serialized
const orders: Array<any> = [];
const oracles: Array<any> = [];
const slot = slotSource.getSlot();
if (FEATURE_FLAGS.ENABLE_ORDERS_ENDPOINTS) {
app.get('/orders/json/raw', async (_req, res, next) => {
try {
// object with userAccount key and orders object serialized
const orders: Array<any> = [];
const oracles: Array<any> = [];
const slot = slotSource.getSlot();
for (const market of driftClient.getPerpMarketAccounts()) {
const oracle = driftClient.getOracleDataForPerpMarket(
market.marketIndex
);
oracles.push({
marketIndex: market.marketIndex,
...oracle,
});
}
for (const { userAccount, publicKey } of dlobProvider.getUserAccounts()) {
for (const order of userAccount.orders) {
if (isVariant(order.status, 'init')) {
continue;
}
orders.push({
user: publicKey.toBase58(),
order: order,
for (const market of driftClient.getPerpMarketAccounts()) {
const oracle = driftClient.getOracleDataForPerpMarket(
market.marketIndex
);
oracles.push({
marketIndex: market.marketIndex,
...oracle,
});
}
}
// respond with orders
res.writeHead(200);
res.end(
JSON.stringify({
slot,
oracles,
orders,
})
);
} catch (e) {
next(e);
}
});
app.get('/orders/json', async (_req, res, next) => {
try {
// object with userAccount key and orders object serialized
const slot = slotSource.getSlot();
const orders: Array<any> = [];
const oracles: Array<any> = [];
for (const market of driftClient.getPerpMarketAccounts()) {
const oracle = driftClient.getOracleDataForPerpMarket(
market.marketIndex
);
const oracleHuman = {
marketIndex: market.marketIndex,
price: oracle.price.toString(),
slot: oracle.slot.toString(),
confidence: oracle.confidence.toString(),
hasSufficientNumberOfDataPoints:
oracle.hasSufficientNumberOfDataPoints,
};
if (oracle.twap) {
oracleHuman['twap'] = oracle.twap.toString();
}
if (oracle.twapConfidence) {
oracleHuman['twapConfidence'] = oracle.twapConfidence.toString();
}
oracles.push(oracleHuman);
}
for (const { userAccount, publicKey } of dlobProvider.getUserAccounts()) {
for (const order of userAccount.orders) {
if (isVariant(order.status, 'init')) {
continue;
}
const orderHuman = {
status: getVariant(order.status),
orderType: getVariant(order.orderType),
marketType: getVariant(order.marketType),
slot: order.slot.toString(),
orderId: order.orderId,
userOrderId: order.userOrderId,
marketIndex: order.marketIndex,
price: order.price.toString(),
baseAssetAmount: order.baseAssetAmount.toString(),
baseAssetAmountFilled: order.baseAssetAmountFilled.toString(),
quoteAssetAmountFilled: order.quoteAssetAmountFilled.toString(),
direction: getVariant(order.direction),
reduceOnly: order.reduceOnly,
triggerPrice: order.triggerPrice.toString(),
triggerCondition: getVariant(order.triggerCondition),
existingPositionDirection: getVariant(
order.existingPositionDirection
),
postOnly: order.postOnly,
immediateOrCancel: order.immediateOrCancel,
oraclePriceOffset: order.oraclePriceOffset,
auctionDuration: order.auctionDuration,
auctionStartPrice: order.auctionStartPrice.toString(),
auctionEndPrice: order.auctionEndPrice.toString(),
maxTs: order.maxTs.toString(),
};
if (order.quoteAssetAmount) {
orderHuman['quoteAssetAmount'] = order.quoteAssetAmount.toString();
}
orders.push({
user: publicKey.toBase58(),
order: orderHuman,
});
}
}
// respond with orders
res.writeHead(200);
res.end(
JSON.stringify({
slot,
oracles,
orders,
})
);
} catch (err) {
next(err);
}
});
app.get('/orders/idl', async (_req, res, next) => {
try {
const dlobOrders: DLOBOrders = [];
for (const { userAccount, publicKey } of dlobProvider.getUserAccounts()) {
for (const order of userAccount.orders) {
if (isVariant(order.status, 'init')) {
continue;
}
dlobOrders.push({
user: publicKey,
order,
} as DLOBOrder);
}
}
res.writeHead(200);
res.end(dlobCoder.encode(dlobOrders));
} catch (err) {
next(err);
}
});
app.get('/orders/idlWithSlot', async (req, res, next) => {
try {
const { marketName, marketIndex, marketType } = req.query;
const { normedMarketType, normedMarketIndex, error } = validateDlobQuery(
driftClient,
driftEnv,
marketType as string,
marketIndex as string,
marketName as string
);
const useFilter =
marketName !== undefined ||
marketIndex !== undefined ||
marketType !== undefined;
if (useFilter) {
if (
error ||
normedMarketType === undefined ||
normedMarketIndex === undefined
) {
res.status(400).send(error);
return;
}
}
const dlobOrders: DLOBOrders = [];
for (const { userAccount, publicKey } of dlobProvider.getUserAccounts()) {
for (const order of userAccount.orders) {
if (isVariant(order.status, 'init')) {
continue;
}
if (useFilter) {
if (
getVariant(order.marketType) !== getVariant(normedMarketType) ||
order.marketIndex !== normedMarketIndex
) {
for (const {
userAccount,
publicKey,
} of dlobProvider.getUserAccounts()) {
for (const order of userAccount.orders) {
if (isVariant(order.status, 'init')) {
continue;
}
orders.push({
user: publicKey.toBase58(),
order: order,
});
}
dlobOrders.push({
user: publicKey,
order,
} as DLOBOrder);
}
}
res.end(
JSON.stringify({
slot: slotSource.getSlot(),
data: dlobCoder.encode(dlobOrders).toString('base64'),
})
);
} catch (err) {
next(err);
}
});
// respond with orders
res.writeHead(200);
res.end(
JSON.stringify({
slot,
oracles,
orders,
})
);
} catch (e) {
next(e);
}
});
app.get('/orders/json', async (_req, res, next) => {
try {
// object with userAccount key and orders object serialized
const slot = slotSource.getSlot();
const orders: Array<any> = [];
const oracles: Array<any> = [];
for (const market of driftClient.getPerpMarketAccounts()) {
const oracle = driftClient.getOracleDataForPerpMarket(
market.marketIndex
);
const oracleHuman = {
marketIndex: market.marketIndex,
price: oracle.price.toString(),
slot: oracle.slot.toString(),
confidence: oracle.confidence.toString(),
hasSufficientNumberOfDataPoints:
oracle.hasSufficientNumberOfDataPoints,
};
if (oracle.twap) {
oracleHuman['twap'] = oracle.twap.toString();
}
if (oracle.twapConfidence) {
oracleHuman['twapConfidence'] = oracle.twapConfidence.toString();
}
oracles.push(oracleHuman);
}
for (const {
userAccount,
publicKey,
} of dlobProvider.getUserAccounts()) {
for (const order of userAccount.orders) {
if (isVariant(order.status, 'init')) {
continue;
}
const orderHuman = {
status: getVariant(order.status),
orderType: getVariant(order.orderType),
marketType: getVariant(order.marketType),
slot: order.slot.toString(),
orderId: order.orderId,
userOrderId: order.userOrderId,
marketIndex: order.marketIndex,
price: order.price.toString(),
baseAssetAmount: order.baseAssetAmount.toString(),
baseAssetAmountFilled: order.baseAssetAmountFilled.toString(),
quoteAssetAmountFilled: order.quoteAssetAmountFilled.toString(),
direction: getVariant(order.direction),
reduceOnly: order.reduceOnly,
triggerPrice: order.triggerPrice.toString(),
triggerCondition: getVariant(order.triggerCondition),
existingPositionDirection: getVariant(
order.existingPositionDirection
),
postOnly: order.postOnly,
immediateOrCancel: order.immediateOrCancel,
oraclePriceOffset: order.oraclePriceOffset,
auctionDuration: order.auctionDuration,
auctionStartPrice: order.auctionStartPrice.toString(),
auctionEndPrice: order.auctionEndPrice.toString(),
maxTs: order.maxTs.toString(),
};
if (order.quoteAssetAmount) {
orderHuman['quoteAssetAmount'] =
order.quoteAssetAmount.toString();
}
orders.push({
user: publicKey.toBase58(),
order: orderHuman,
});
}
}
// respond with orders
res.writeHead(200);
res.end(
JSON.stringify({
slot,
oracles,
orders,
})
);
} catch (err) {
next(err);
}
});
app.get('/orders/idl', async (_req, res, next) => {
try {
const dlobOrders: DLOBOrders = [];
for (const {
userAccount,
publicKey,
} of dlobProvider.getUserAccounts()) {
for (const order of userAccount.orders) {
if (isVariant(order.status, 'init')) {
continue;
}
dlobOrders.push({
user: publicKey,
order,
} as DLOBOrder);
}
}
res.writeHead(200);
res.end(dlobCoder.encode(dlobOrders));
} catch (err) {
next(err);
}
});
app.get('/orders/idlWithSlot', async (req, res, next) => {
try {
const { marketName, marketIndex, marketType } = req.query;
const { normedMarketType, normedMarketIndex, error } =
validateDlobQuery(
driftClient,
driftEnv,
marketType as string,
marketIndex as string,
marketName as string
);
const useFilter =
marketName !== undefined ||
marketIndex !== undefined ||
marketType !== undefined;
if (useFilter) {
if (
error ||
normedMarketType === undefined ||
normedMarketIndex === undefined
) {
res.status(400).send(error);
return;
}
}
const dlobOrders: DLOBOrders = [];
for (const {
userAccount,
publicKey,
} of dlobProvider.getUserAccounts()) {
for (const order of userAccount.orders) {
if (isVariant(order.status, 'init')) {
continue;
}
if (useFilter) {
if (
getVariant(order.marketType) !== getVariant(normedMarketType) ||
order.marketIndex !== normedMarketIndex
) {
continue;
}
}
dlobOrders.push({
user: publicKey,
order,
} as DLOBOrder);
}
}
res.end(
JSON.stringify({
slot: slotSource.getSlot(),
data: dlobCoder.encode(dlobOrders).toString('base64'),
})
);
} catch (err) {
next(err);
}
});
}
app.get('/topMakers', async (req, res, next) => {
try {

View File

@@ -1,7 +1,17 @@
// 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
// TODO : Remove this once we're confident that NEW_ORACLE_DATA_IN_L2 works .. delete corresponding code
OLD_ORACLE_PRICE_IN_L2: true,
NEW_ORACLE_DATA_IN_L2: true,
// enables old orders endpoint, disabled by default since the response is too big now
ENABLE_ORDERS_ENDPOINTS: process.env.ENABLE_ORDERS_ENDPOINTS
? process.env.ENABLE_ORDERS_ENDPOINTS.toLowerCase()
: false,
// disables periodically refreshing userAccounts via gPA
DISABLE_GPA_REFRESH: process.env.DISABLE_GPA_REFRESH
? process.env.DISABLE_GPA_REFRESH.toLowerCase()
: false,
};
export default FEATURE_FLAGS;