import { MarketState } from "../types.js"; import { isTimestampPassed } from "../math.js"; /** * SettlementChecker - Monitors market expiry and triggers settlement * * Responsibilities: * - Checks if market has expired (timestamp passed) * - Detects when settlement is needed * - Triggers settlement callback when ready */ export class SettlementChecker { private checkInterval: number; private verbose: boolean; private timer: NodeJS.Timeout | null = null; private isRunning = false; constructor(checkInterval: number = 10000, verbose: boolean = false) { this.checkInterval = checkInterval; this.verbose = verbose; } /** * Start settlement checking * * @param market - Current market state * @param onSettlementNeeded - Callback when settlement is needed * @param onBothSettled - Callback when both pools are settled (stop signal) */ start( market: MarketState, onSettlementNeeded: () => Promise, onBothSettled?: () => void ): void { if (this.isRunning) { throw new Error("SettlementChecker is already running"); } this.isRunning = true; const checkSettlement = async () => { if (!this.isRunning) return; // Check if market has expired if (!isTimestampPassed(market.endTimestamp)) { return; // Market not yet expired } try { // Settle both pools if either is unsettled if (!market.highPool.isSettled || !market.lowPool.isSettled) { this.log("Market expired, settlement needed"); await onSettlementNeeded(); } // Check if both pools are now settled if (market.highPool.isSettled && market.lowPool.isSettled) { this.log("Both pools settled"); if (onBothSettled) { onBothSettled(); } this.stop(); } } catch (err) { this.log(`Settlement check error: ${(err as Error).message}`); throw err; } }; this.timer = setInterval(checkSettlement, this.checkInterval); } /** * Stop settlement checking */ stop(): void { this.isRunning = false; if (this.timer) { clearInterval(this.timer); this.timer = null; } } private log(message: string): void { if (this.verbose) { console.log(`[SettlementChecker] ${message}`); } } }