From b0f0034a236a27e7c002d1618856aeeedfc0d58f Mon Sep 17 00:00:00 2001 From: Chee Chyuan Ang Date: Wed, 17 Dec 2025 16:40:20 +0800 Subject: [PATCH] ably push latest auction round --- shared/ablyConstants.ts | 1 + websocket/index.ts | 17 +++++++- .../services/auctionRoundNumberService.ts | 42 +++++++++++++++++++ websocket/services/expressLaneService.ts | 6 +-- 4 files changed, 61 insertions(+), 5 deletions(-) create mode 100644 websocket/services/auctionRoundNumberService.ts diff --git a/shared/ablyConstants.ts b/shared/ablyConstants.ts index 959826a..62ed26a 100644 --- a/shared/ablyConstants.ts +++ b/shared/ablyConstants.ts @@ -1,4 +1,5 @@ export const ABLY_CHANNELS = { EXPRESS_LANE_TRANSACTIONS: 'express_lane_transactions', + AUCTION_ROUND_NUMBER: 'auction_round_number', } as const; diff --git a/websocket/index.ts b/websocket/index.ts index dd7601b..9bbb0e3 100644 --- a/websocket/index.ts +++ b/websocket/index.ts @@ -4,8 +4,18 @@ import { initClickHouseClient } from '@mevscan/shared/clickhouse'; import { getAbly } from '@mevscan/shared/ably'; import { publishExpressLaneTransactions } from './services/expressLaneService'; import { config } from '@mevscan/shared/config'; +import { publishAuctionRoundNumber } from './services/auctionRoundNumberService'; + +interface ChannelState { + expressLane: [number, number] | null; + auctionRoundNumber: number | null; +} + +const channelState: ChannelState = { + expressLane: null, + auctionRoundNumber: null, +}; -let channelLastStoredBlockNumberTxIndex: Record = {}; interface InitResult { clickhouseClient: ClickHouseClient; ably: Ably.Realtime; @@ -39,7 +49,10 @@ async function init(): Promise { const { clickhouseClient, ably } = await init(); while (true) { - await publishExpressLaneTransactions(ably, clickhouseClient, channelLastStoredBlockNumberTxIndex); + await Promise.all([ + publishExpressLaneTransactions(ably, clickhouseClient, channelState), + publishAuctionRoundNumber(ably, clickhouseClient, channelState) + ]); await new Promise(resolve => setTimeout(resolve, config.ably.refreshIntervalMs)); } })(); \ No newline at end of file diff --git a/websocket/services/auctionRoundNumberService.ts b/websocket/services/auctionRoundNumberService.ts new file mode 100644 index 0000000..35cd042 --- /dev/null +++ b/websocket/services/auctionRoundNumberService.ts @@ -0,0 +1,42 @@ +import { ClickHouseClient } from "@clickhouse/client"; +import { ABLY_CHANNELS } from "@mevscan/shared/ablyConstants"; +import { config, NodeEnv } from "@mevscan/shared/config"; +import Ably from 'ably'; + +async function getAuctionRoundNumber(clickhouseClient: ClickHouseClient): Promise { + const query = ` + SELECT + MAX(round) as auctionRoundNumber + from timeboost.auction + `; + + const result = await clickhouseClient.query({ + query, + format: 'JSONEachRow', + }); + + const data = await result.json>(); + return data[0]?.auctionRoundNumber ?? null; +} + +export async function publishAuctionRoundNumber(ably: Ably.Realtime, clickhouseClient: ClickHouseClient, state: { auctionRoundNumber: number | null }) { + let ablyChannel = ably.channels.get(ABLY_CHANNELS.AUCTION_ROUND_NUMBER); + let previousAuctionRoundNumber = state.auctionRoundNumber || 0; + + const auctionRoundNumber = await getAuctionRoundNumber(clickhouseClient); + if (auctionRoundNumber === null) { + return; + } + + if (previousAuctionRoundNumber >= auctionRoundNumber) { + return; + } + + if (config.nodeEnv === NodeEnv.TEST) { + console.log('Publishing Auction Round Number data:', auctionRoundNumber); + } else { + await ablyChannel.publish(ABLY_CHANNELS.AUCTION_ROUND_NUMBER, auctionRoundNumber); + } + + state.auctionRoundNumber = auctionRoundNumber; +} \ No newline at end of file diff --git a/websocket/services/expressLaneService.ts b/websocket/services/expressLaneService.ts index 6a2b434..b62e9ee 100644 --- a/websocket/services/expressLaneService.ts +++ b/websocket/services/expressLaneService.ts @@ -59,9 +59,9 @@ async function getLastStoredBlockNumberTxIndex(clickhouseClient: ClickHouseClien return data[0]?.blockNumber ?? 0; } -export async function publishExpressLaneTransactions(ably: Ably.Realtime, clickhouseClient: ClickHouseClient, lastStoredBlockNumberTxIndex: Record) { +export async function publishExpressLaneTransactions(ably: Ably.Realtime, clickhouseClient: ClickHouseClient, state: { expressLane: [number, number] | null }) { let ablyChannel = ably.channels.get(ABLY_CHANNELS.EXPRESS_LANE_TRANSACTIONS); - let [lastStoredBlockNumber, lastStoredTxIndex] = lastStoredBlockNumberTxIndex[ABLY_CHANNELS.EXPRESS_LANE_TRANSACTIONS] || [null, null]; + let [lastStoredBlockNumber, lastStoredTxIndex] = state.expressLane || [null, null]; if (lastStoredBlockNumber === null || lastStoredTxIndex === null) { const history = await ablyChannel.history({ limit: 1 }); @@ -86,5 +86,5 @@ export async function publishExpressLaneTransactions(ably: Ably.Realtime, clickh } else { await ablyChannel.publish(ABLY_CHANNELS.EXPRESS_LANE_TRANSACTIONS, transactions); } - lastStoredBlockNumberTxIndex[ABLY_CHANNELS.EXPRESS_LANE_TRANSACTIONS] = [transactions[transactions.length - 1]!.blockNumber, transactions[transactions.length - 1]!.txIndex]; + state.expressLane = [transactions[transactions.length - 1]!.blockNumber, transactions[transactions.length - 1]!.txIndex]; } \ No newline at end of file