import type { DslState } from "../types/dsl/index.js"; /** Age beyond which an unconfirmed intent-mint is considered abandoned (order never filled). */ export declare const PENDING_OPEN_STALE_MS: number; /** * Build the registry key for a position. Normalizes dex the same way the * position-tracker scanner's buildPositionKey does (empty/whitespace → "main"), * scoped by wallet so the map is correct under multi-wallet deployment. */ export declare function positionRegistryKey(wallet: string, dex: string, asset: string): string; export interface Entry { positionId: string; /** * Telemetry-only, per-call observation (NOT persisted/rehydrated, NOT entry state): on a * confirmed open, whether the id came from a pending intent-mint (`"runtime_opened"` — the * runtime submitted this open, so `mintOnIntent` ran at submit) or was minted fresh * (`"externally_detected"` — no prior runtime intent, an on-chain position opened manually or by * another tool). Surfaced by {@link mintOnOpened} only; absent on the early-return * already-confirmed path (a duplicate opened — source unknown) and on every other accessor. */ reconciliationSource?: "runtime_opened" | "externally_detected"; } /** One unit of boot-time state to restore: a confirmed entry (from a persisted DSL state). */ export interface RehydrateItem { key: string; entry: Entry; } export interface PositionIdRegistryOptions { now?: () => number; /** Override for {@link PENDING_OPEN_STALE_MS} (tests). */ staleMs?: number; } export declare class PositionIdRegistry { private readonly entries; /** Positions minted at intent, awaiting a confirmed open. */ private readonly pending; private readonly now; private readonly staleMs; constructor(opts?: PositionIdRegistryOptions); /** * Mint a position.id at the moment the runtime decides to open, before the position * is confirmed open. The id is returned immediately so callers can stamp it on the * `action.open` emit. Idempotent: a re-submit (or an already-confirmed entry) reuses * the existing id rather than minting a new one. */ mintOnIntent(key: string): Entry; /** * Confirm the open. Idempotent: if a confirmed entry already exists it is returned. * If the position was minted at intent (and the intent is not stale), that id is * promoted (reused, never re-minted) and the pending record dropped. Otherwise — an * externally-opened position with no prior runtime intent — a fresh id is minted. */ mintOnOpened(key: string): Entry; /** * Read the current entry for a key (INCREASED/DECREASED/FLIPPED, DSL start, telemetry * reads). Surfaces an intent-mint that has not yet been confirmed open, so reads in * the open window still resolve the position.id. */ get(key: string): Entry | undefined; /** Clear on confirmed close. The next open on this key mints a fresh id. */ clearOnClosed(key: string): void; /** Repopulate confirmed entries at boot from persisted DSL states. */ rehydrate(items: RehydrateItem[]): void; /** * The pending record for a key, unless it has gone stale — an intent whose order * never filled within the stale window is discarded on read (and a fresh mint * follows), so an abandoned submit's id never attaches to a later, unrelated open. */ private livePending; } /** * Build {@link RehydrateItem}s for the PositionIdRegistry at boot. * * One confirmed entry per active DSL state, keyed on (wallet, dex, asset), so a * re-observed OPENED after a restart does not re-mint. Pre-positionId state files fall * back to the legacy correlationId — the same fallback the DSL emit sites use, so every * consumer converges on one id for a pre-deploy position. * * Pure: takes the already-loaded states, returns the items. The runtime reads DSL * states from the StateManager. */ export declare function buildRehydrateItems(dslStates: DslState[]): RehydrateItem[]; //# sourceMappingURL=position-id-registry.d.ts.map