feat(dlob): support two sources + per-user switch

- Add "source" column + composite PKs for DLOB tables\n- Filter public Hasura selects by X-Hasura-Dlob-Source\n- Run parallel workers for mevnode + dlob.drift.trade\n- Frontend proxy sets x-hasura-dlob-source from cookie and injects UI switch
This commit is contained in:
u1
2026-02-13 10:48:20 +01:00
parent 9e7d7b88ac
commit 57433c7e75
17 changed files with 501 additions and 54 deletions

View File

@@ -0,0 +1,50 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: dlob-slippage-worker-drift
annotations:
argocd.argoproj.io/sync-wave: "6"
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: dlob-slippage-worker-drift
template:
metadata:
labels:
app.kubernetes.io/name: dlob-slippage-worker-drift
spec:
containers:
- name: worker
image: node:20-slim
imagePullPolicy: IfNotPresent
env:
- name: HASURA_GRAPHQL_URL
value: http://hasura:8080/v1/graphql
- name: HASURA_ADMIN_SECRET
valueFrom:
secretKeyRef:
name: trade-hasura
key: HASURA_GRAPHQL_ADMIN_SECRET
- name: DLOB_SOURCE
value: drift
- name: DLOB_MARKETS
value: PUMP-PERP,SOL-PERP,1MBONK-PERP,BTC-PERP,ETH-PERP
- name: DLOB_POLL_MS
value: "1000"
- name: DLOB_SLIPPAGE_SIZES_USD
value: "0.1,0.2,0.5,1,2,5,10,25,50,100,250,500,1000,5000,10000,50000"
- name: PRICE_PRECISION
value: "1000000"
- name: BASE_PRECISION
value: "1000000000"
command: ["node", "/app/worker.mjs"]
volumeMounts:
- name: script
mountPath: /app/worker.mjs
subPath: worker.mjs
readOnly: true
volumes:
- name: script
configMap:
name: dlob-slippage-worker-script

View File

@@ -26,6 +26,8 @@ spec:
secretKeyRef:
name: trade-hasura
key: HASURA_GRAPHQL_ADMIN_SECRET
- name: DLOB_SOURCE
value: mevnode
- name: DLOB_MARKETS
value: PUMP-PERP,SOL-PERP,1MBONK-PERP,BTC-PERP,ETH-PERP
- name: DLOB_POLL_MS

View File

@@ -55,6 +55,7 @@ function resolveConfig() {
tokens.hasuraAdminSecret;
const hasuraAuthToken = process.env.HASURA_AUTH_TOKEN || process.env.HASURA_JWT || undefined;
const dlobSource = String(process.env.DLOB_SOURCE || 'mevnode').trim() || 'mevnode';
const markets = envList('DLOB_MARKETS', 'PUMP-PERP,SOL-PERP,1MBONK-PERP,BTC-PERP,ETH-PERP');
const pollMs = clampInt(process.env.DLOB_POLL_MS, 250, 60_000, 1000);
@@ -77,6 +78,7 @@ function resolveConfig() {
hasuraUrl,
hasuraAdminSecret,
hasuraAuthToken,
dlobSource,
markets,
pollMs,
sizesUsd,
@@ -209,6 +211,7 @@ async function main() {
startedAt: getIsoNow(),
hasuraUrl: cfg.hasuraUrl,
hasuraAuth: cfg.hasuraAuthToken ? 'bearer' : cfg.hasuraAdminSecret ? 'admin-secret' : 'none',
dlobSource: cfg.dlobSource,
markets: cfg.markets,
pollMs: cfg.pollMs,
sizesUsd: cfg.sizesUsd,
@@ -226,8 +229,9 @@ async function main() {
try {
const query = `
query DlobL2Latest($markets: [String!]!) {
dlob_l2_latest(where: { market_name: { _in: $markets } }) {
query DlobL2Latest($source: String!, $markets: [String!]!) {
dlob_l2_latest(where: { source: { _eq: $source }, market_name: { _in: $markets } }) {
source
market_name
market_type
market_index
@@ -242,7 +246,7 @@ async function main() {
}
`;
const data = await graphqlRequest(cfg, query, { markets: cfg.markets });
const data = await graphqlRequest(cfg, query, { source: cfg.dlobSource, markets: cfg.markets });
const rows = Array.isArray(data?.dlob_l2_latest) ? data.dlob_l2_latest : [];
const objectsV1 = [];
@@ -277,6 +281,7 @@ async function main() {
{
const sim = simulateFill(asks, sizeUsd);
const baseObj = {
source: cfg.dlobSource,
market_name: market,
side: 'buy',
market_type: row?.market_type ?? 'perp',
@@ -302,6 +307,7 @@ async function main() {
{
const sim = simulateFill(bids, sizeUsd);
const baseObj = {
source: cfg.dlobSource,
market_name: market,
side: 'sell',
market_type: row?.market_type ?? 'perp',