/** * Cycles and the clearing window — the protocol's weekly clock, as numbers. * * Lifted verbatim from kasu-ui's `features/portfolio/lib/settlement-window.ts` * and `features/lending/lib/cycle-dates.ts`. The two formatters that live * beside `deriveCycleDates` there (`formatCycleDate`, `formatCycleCloseUtc`) * print words and stay in the applications; everything here is unix seconds in * and unix seconds out. * * The clearing window is the fixed 48 hours immediately preceding an epoch * end. Inside it, pending requests are being processed and cannot be modified, * and the countdown runs to the epoch end. Outside it, the countdown runs to * the next clearing-window start. * * The epoch end comes straight from the chain (`nextEpochStartTimestamp`, i.e. * the SDK's `getNextEpochDate`) — the same value the protocol's own * `getNextClearingPeriodDate` derives from — so the window always lines up * with the real weekly schedule (Tue 06:00 → Thu 06:00 UTC on Base) instead of * a projected subgraph timestamp that can drift off the grid. */ /** * Clearing-window length — a fixed 48h protocol constant. Exported so every * consumer derives the window from the same number this module runs on. */ export declare const CLEARING_WINDOW_SECONDS: number; export type SettlementWindowState = { phase: 'awaiting'; secondsUntilClearing: number; nextClearingStart: number; } | { phase: 'clearing'; secondsUntilEpochEnd: number; epochEnd: number; } | { phase: 'unknown'; }; export interface SettlementWindowInput { /** Now, in unix seconds. */ nowSeconds: number; /** * Authoritative epoch end, in unix seconds — the chain's * `nextEpochStartTimestamp` (SDK `getNextEpochDate`). During an epoch this * is in the future; it refetches to the next boundary once it rolls. */ nextEpochStart: number; /** Clearing-window length; defaults to the 48h protocol constant. */ clearingWindowSeconds?: number; } /** * Which phase of the weekly cycle `nowSeconds` falls in, and how long is left * of it. * * `'unknown'` when no epoch boundary has been loaded yet, or when the one on * hand is stale (it has already elapsed — the on-chain value refetches to the * next boundary shortly after rollover). A caller must render its "no cycle * loaded" state there, never a zeroed countdown. */ export declare function computeSettlementWindow({ nowSeconds, nextEpochStart, clearingWindowSeconds, }: SettlementWindowInput): SettlementWindowState; /** * The next cycle boundary strictly after `nowSeconds`, in unix seconds — the * cycle close (`nextEpochStart − 48h`) while the window is still open, the * epoch end once we are inside it. * * `undefined` when there is no boundary left to wait for: no epoch boundary * loaded, or a cached one that has already elapsed — the same staleness rule * `computeSettlementWindow` applies before it reports `'unknown'`. * * Split out of the state machine because some consumers need the INSTANT * rather than the phase: one to flush the cycle-dependent caches when the * clock crosses it, one to move a pre-commit screen's snapshot clock at the * same moment. */ export declare function nextCycleBoundary(nextEpochStart: number | undefined, nowSeconds: number, clearingWindowSeconds?: number): number | undefined; export interface CycleDates { /** Unix seconds — the next cycle close (clearing-window start). */ close: number; /** Unix seconds — the outcome-confirmed-by boundary (close + 48h). */ outcome: number; } /** * The cycle-close and outcome dates for a request submitted `now`. * * - The cycle "closes" (stops accepting requests, starts processing) at the * start of the 48h clearing window, i.e. 48h before the epoch end. * - Processing takes up to 48h, so the outcome is confirmed by the epoch end * (close + 48h). * * Returns `null` when the epoch boundary is not available or is stale — a * caller then omits the dates entirely (omit, don't stub). * * The common case is a request submitted OUTSIDE the clearing window: the * close is `nextEpochStart − 48h` and the outcome is `nextEpochStart`. When * the request lands INSIDE the current clearing window (that close is already * in the past), it queues for the NEXT weekly cycle, so the close is advanced * by whole weeks until it is in the future. */ export declare function deriveCycleDates(nextEpochStart: number | undefined, nowSeconds: number): CycleDates | null;