/** * Post-hydrate reconciliation: align StateManager DSL state with backend (Senpi/MCP) open positions. * Best-effort: on backend failure for an address, we skip that address entirely (do not archive). */ import type { StateManager } from "../state/index.js"; import type { SenpiClient } from "../senpi/client.js"; import type { StrategyConfig, StrategyState } from "../types/strategy.js"; import type { SenpiEventBus } from "../types/event-bus.js"; import type { DslState } from "../types/dsl/index.js"; export interface ReconcileOptions { /** If provided, emit POSITION_CLOSED when a position is archived (e.g. from DSL monitor). */ bus?: SenpiEventBus; /** * When set, open positions per address are read from StrategyState.getOpenPositions() instead of * listOpenPositions (unless {@link strategyStateOnly} is false and an address is missing from the map). * Caller must refresh via fetchClearinghouseState before reconcile when using cached positions. */ strategyStates?: Map; /** * When true (DSL monitor tick), reconciliation uses only StrategyState: no SenpiClient.listOpenPositions * or getOrderStatus fallbacks. Addresses without a map entry are skipped (no archive for that wallet). */ strategyStateOnly?: boolean; /** * The monitor tick driving this reconcile, when one is. Stamped on the archive's POSITION_CLOSED * so the event names the tick that observed the position was gone. Absent on the boot reconcile, * which runs outside any tick. */ tickId?: string; } /** * Archive DSL states for positions that are no longer live (not in livePositionKeys). * * Iterates all active DSL keys for the given address and archives any state whose position * key is absent from livePositionKeys. Each archive is wrapped in a per-key lock to prevent * concurrent double-archive. * * @param stateManager - StateManager instance * @param senpi - SenpiClient for order status lookups * @param address - the wallet address whose DSL keys to scan * @param livePositionKeys - set of positionKey strings currently live on the exchange * @param opts - optional bus, strategyState, strategyStateOnly * @returns number of DSL states archived */ /** * Archive a single DSL state that is known to be gone (no matching exchange position). * * Resolves the close reason (SL-hit vs closed-externally), acquires the per-position * key lock, persists the archived state, and optionally emits POSITION_CLOSED on the bus. * * Extracted from the loop inside {@link archiveGonePositions} so that the reconcile * executor ({@link runReconcile}) can archive exactly the states identified by * {@link decideReconcile} without recomputing the gone-set independently. * * @returns * "archived" — state was successfully archived; * "skipped" — by-design no-op (a different live position now holds this key, or the * state is already gone) — NOT a failure; * "failed" — an error prevented archival (left state intact). */ export type ArchiveGoneOutcome = "archived" | "skipped" | "failed"; export declare function archiveGoneState(stateManager: StateManager, senpi: SenpiClient, state: DslState, opts?: { bus?: SenpiEventBus; strategyState?: StrategyState; strategyStateOnly?: boolean; tickId?: string; }): Promise; export declare function archiveGonePositions(stateManager: StateManager, senpi: SenpiClient, address: string, livePositionKeys: Set, opts?: { bus?: SenpiEventBus; strategyState?: StrategyState; strategyStateOnly?: boolean; tickId?: string; }): Promise<{ gonesArchived: number; }>; /** * Reconcile state with backend: fetch open positions per address via `SenpiClient.listOpenPositions` * (parses `strategy_get_clearinghouse_state`, not `list_open_positions`) and archive local DSL state * for positions that are no longer on the exchange (e.g. closed manually externally). * Only archives positions for addresses where clearing-house fetch succeeded; if the API throws * or is unavailable for an address, we do not archive any position for that address. * * Call after hydrate() in Runtime.start() and periodically from the DSL monitor tick. * * @param addresses - strategy addresses to reconcile * @param options - optional bus to emit POSITION_CLOSED when archiving (e.g. from monitor) */ export declare function reconcileStateWithBackend(stateManager: StateManager, senpi: SenpiClient, addressesOrStrategiesMap: string[] | Map, options?: ReconcileOptions): Promise; //# sourceMappingURL=reconcile-state.d.ts.map