From 6273f3b94a0fe81e58fe8348eff1aaada488b6df Mon Sep 17 00:00:00 2001 From: discountry Date: Fri, 3 Oct 2025 02:40:09 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=9C=A8=20Lighter=20=E9=80=82?= =?UTF-8?q?=E9=85=8D=E5=99=A8=E4=B8=AD=E6=B7=BB=E5=8A=A0=E8=AE=A2=E5=8D=95?= =?UTF-8?q?=E7=B0=BF=E5=BA=8F=E5=88=97=E8=B7=9F=E8=B8=AA=EF=BC=8C=E4=BC=98?= =?UTF-8?q?=E5=8C=96=20WebSocket=20=E6=B6=88=E6=81=AF=E5=A4=84=E7=90=86?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/exchanges/lighter/gateway.ts | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/exchanges/lighter/gateway.ts b/src/exchanges/lighter/gateway.ts index 4b2f630..d8bb8bb 100644 --- a/src/exchanges/lighter/gateway.ts +++ b/src/exchanges/lighter/gateway.ts @@ -184,6 +184,10 @@ export class LighterGateway { private readonly tickerPollMs: number; private readonly klinePollMs: number; + // Track last applied order book sequence to drop stale WS messages + private lastOrderBookOffset: number = 0; + private lastOrderBookTimestamp: number = 0; + constructor(options: LighterGatewayOptions) { this.displaySymbol = options.symbol; this.marketSymbol = (options.marketSymbol ?? options.symbol).toUpperCase(); @@ -514,6 +518,14 @@ export class LighterGateway { private handleOrderBookSnapshot(message: any): void { if (!message?.order_book) return; + const incomingOffset = Number(message.offset ?? message.order_book?.offset ?? 0); + const incomingTs = Number(message.timestamp ?? 0); + if (this.lastOrderBookOffset && incomingOffset && incomingOffset < this.lastOrderBookOffset) { + return; + } + if (incomingOffset === this.lastOrderBookOffset && incomingTs && incomingTs <= this.lastOrderBookTimestamp) { + return; + } const snapshot: LighterOrderBookSnapshot = { market_id: this.marketId ?? 0, offset: message.order_book.offset ?? Date.now(), @@ -521,11 +533,21 @@ export class LighterGateway { asks: normalizeLevels(message.order_book.asks ?? []), }; this.orderBook = snapshot; + this.lastOrderBookOffset = snapshot.offset ?? incomingOffset ?? this.lastOrderBookOffset; + this.lastOrderBookTimestamp = incomingTs || Date.now(); this.emitDepth(); } private handleOrderBookUpdate(message: any): void { if (!this.orderBook) return; + const incomingOffset = Number(message.offset ?? message.order_book?.offset ?? 0); + const incomingTs = Number(message.timestamp ?? 0); + if (this.lastOrderBookOffset && incomingOffset && incomingOffset < this.lastOrderBookOffset) { + return; + } + if (incomingOffset === this.lastOrderBookOffset && incomingTs && incomingTs <= this.lastOrderBookTimestamp) { + return; + } const update = message?.order_book; if (!update) return; if (Array.isArray(update.asks)) { @@ -537,6 +559,8 @@ export class LighterGateway { this.orderBook.bids = mergeLevels(this.orderBook.bids ?? [], bids); } this.orderBook.offset = update.offset ?? this.orderBook.offset; + this.lastOrderBookOffset = Number(this.orderBook.offset ?? incomingOffset ?? this.lastOrderBookOffset); + this.lastOrderBookTimestamp = incomingTs || Date.now(); this.emitDepth(); }