import type { Subscription, SubscriptionEvent } from '@lifi/perps-types'; import type { ProviderGetQuoteParams, QuoteListener } from '../types/provider.js'; import type { ReconnectingWebSocket } from './ReconnectingWebSocket.js'; import type { SubscriptionListener, WsProvider, WsStatusListener } from './types.js'; /** * Linger before tearing a channel off the wire after its last listener * releases. A re-subscribe to the same key within this window cancels the * pending teardown, so React StrictMode's synchronous unmount→remount (ref * count 1→0→1) and fast route flips collapse to one wire subscription rather * than a subscribe→unsubscribe→subscribe churn the venue would reject. * * @public */ export declare const WS_CHANNEL_TEARDOWN_LINGER_MS = 250; /** * Base for per-provider realtime transports. Owns the {@link * ReconnectingWebSocket}, the fan-out lifecycle — ref-counted multi-listener * subscription per channel key, deferred teardown, status fan-out — so any * number of consumers (and StrictMode double-mounts) collapse to exactly one * wire subscribe/unsubscribe per key, and the wire-subscription registry: * subs recorded via {@link WsProviderBase.registerSub} are sent only while * connected and replayed (failure-isolated) on every (re)open. Subclasses own * everything wire-specific via {@link WsProviderBase.openChannel}, {@link * WsProviderBase.sendSubscribe} and {@link WsProviderBase.handleMessage}: * payload framing, frame validation and dispatch. * * `TSub` is the per-subscription state {@link WsProviderBase.sendSubscribe} * needs to (re)build one subscribe frame. * * @public */ export declare abstract class WsProviderBase implements WsProvider { protected readonly rws: ReconnectingWebSocket; protected readonly providerKey: string; private readonly channels; private readonly statusListeners; private readonly wireSubs; constructor(rws: ReconnectingWebSocket, providerKey: string); subscribe(sub: Subscription, listener: SubscriptionListener, onStatus?: WsStatusListener): Promise<() => void>; reconnect(): void; close(): void; /** Deliver an event to every listener on `key`. */ protected emit(key: string, event: SubscriptionEvent): void; /** * Tear `key` off the wire immediately if no listener holds it — i.e. it is * lingering in the deferred-teardown window (or its open is still * unwinding). Returns `true` when the key is free (absent or just torn * down), `false` — leaving the channel untouched — while live listeners * hold it. Lets a subclass that enforces an exclusivity invariant across * keys reclaim a released channel without waiting out the linger. */ protected closeChannelIfIdle(key: string): boolean; /** * Record a wire subscription for replay-on-(re)open and, when the socket is * already connected, send its subscribe frame via {@link sendSubscribe}. * While the socket is down the replay loop on the next open is the sole * sender — sending in both places would double-subscribe. A failed send * removes the sub again so a rejected open leaves no registry entry behind. */ protected registerSub(key: string, state: TSub): Promise; /** Forget a wire subscription so the next (re)open no longer replays it. */ protected unregisterSub(key: string): void; private replaySubs; /** Venue-specific {@link WsProvider.subscribeQuote}; see `resolveSubscribeQuote`. */ abstract subscribeQuote(params: ProviderGetQuoteParams, onQuote: QuoteListener): Promise<() => void>; /** Canonical fan-out key for `sub`; must match the key the subclass emits to. */ protected abstract toKey(sub: Subscription): string; /** * Open the channel on the wire (0→1 transition only). Record the wire * sub(s) via {@link registerSub} and return a closure that unregisters them * and sends the unsubscribe frame(s). */ protected abstract openChannel(sub: Subscription): Promise<() => void>; /** * Encode and send the subscribe frame for one registered sub. Called by the * base while connected — once on register and again on every (re)open — so * it must be safe to invoke repeatedly with the same state (e.g. re-fetch a * fresh auth token per call rather than embedding one in `state`). */ protected abstract sendSubscribe(state: TSub): void | Promise; /** Parse one inbound frame and route it via {@link emit}. */ protected abstract handleMessage(raw: string): void; /** Release subclass-only resources on {@link close} (keep-alive, cached state). */ protected onClose(): void; private callListener; private acquireChannel; private releaseChannel; } //# sourceMappingURL=WsProviderBase.d.ts.map