@0xarchive/sdk 0.9.1 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +296 -111
- package/dist/index.d.mts +446 -64
- package/dist/index.d.ts +446 -64
- package/dist/index.js +468 -84
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +468 -84
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/types.ts","../src/http.ts","../src/schemas.ts","../src/orderbook-reconstructor.ts","../src/resources/orderbook.ts","../src/resources/trades.ts","../src/resources/instruments.ts","../src/resources/funding.ts","../src/resources/openinterest.ts","../src/resources/candles.ts","../src/resources/liquidations.ts","../src/resources/data-quality.ts","../src/exchanges.ts","../src/client.ts","../src/websocket.ts"],"sourcesContent":["/**\r\n * @0xarchive/sdk - Official TypeScript SDK for 0xarchive\r\n *\r\n * Historical Market Data API for multiple exchanges:\r\n * - Hyperliquid (perpetuals data from April 2023)\r\n * - Hyperliquid HIP-3 builder perps (Pro+ only, February 2026+)\r\n * - Lighter.xyz (perpetuals data)\r\n *\r\n * @example\r\n * ```typescript\r\n * import { OxArchive } from '@0xarchive/sdk';\r\n *\r\n * const client = new OxArchive({ apiKey: '0xa_your_api_key' });\r\n *\r\n * // Hyperliquid data\r\n * const hlOrderbook = await client.hyperliquid.orderbook.get('BTC');\r\n *\r\n * // Lighter.xyz data\r\n * const lighterOrderbook = await client.lighter.orderbook.get('BTC');\r\n *\r\n * // Get historical snapshots\r\n * const history = await client.hyperliquid.orderbook.history('ETH', {\r\n * start: Date.now() - 86400000,\r\n * end: Date.now()\r\n * });\r\n * ```\r\n *\r\n * @packageDocumentation\r\n */\r\n\r\n// Main client\r\nexport { OxArchive } from './client';\r\n\r\n// Exchange clients\r\nexport { HyperliquidClient, Hip3Client, LighterClient } from './exchanges';\r\n\r\n// WebSocket client\r\nexport { OxArchiveWs } from './websocket';\r\n\r\n// Orderbook Reconstructor (for tick-level data)\r\nexport {\r\n OrderBookReconstructor,\r\n reconstructOrderBook,\r\n reconstructFinal,\r\n type TickData,\r\n type ReconstructedOrderBook,\r\n type ReconstructOptions,\r\n} from './orderbook-reconstructor';\r\n\r\n// Tick-level history params\r\nexport type { TickHistoryParams } from './resources/orderbook';\r\n\r\n// Zod schemas for runtime validation\r\nexport {\r\n // Base schemas\r\n ApiMetaSchema,\r\n ApiResponseSchema,\r\n // Order Book schemas\r\n PriceLevelSchema,\r\n OrderBookSchema,\r\n OrderBookResponseSchema,\r\n OrderBookArrayResponseSchema,\r\n // Trade schemas\r\n TradeSideSchema,\r\n TradeDirectionSchema,\r\n TradeSchema,\r\n TradeArrayResponseSchema,\r\n // Instrument schemas\r\n InstrumentTypeSchema,\r\n InstrumentSchema,\r\n InstrumentResponseSchema,\r\n InstrumentArrayResponseSchema,\r\n // Funding schemas\r\n FundingRateSchema,\r\n FundingRateResponseSchema,\r\n FundingRateArrayResponseSchema,\r\n // Open Interest schemas\r\n OpenInterestSchema,\r\n OpenInterestResponseSchema,\r\n OpenInterestArrayResponseSchema,\r\n // Candle schemas\r\n CandleIntervalSchema,\r\n CandleSchema,\r\n CandleArrayResponseSchema,\r\n // Liquidation schemas\r\n LiquidationSideSchema,\r\n LiquidationSchema,\r\n LiquidationArrayResponseSchema,\r\n LiquidationVolumeSchema,\r\n LiquidationVolumeArrayResponseSchema,\r\n // Coin Freshness schemas\r\n DataTypeFreshnessInfoSchema,\r\n CoinFreshnessSchema,\r\n CoinFreshnessResponseSchema,\r\n // Coin Summary schemas\r\n CoinSummarySchema,\r\n CoinSummaryResponseSchema,\r\n // Price Snapshot schemas\r\n PriceSnapshotSchema,\r\n PriceSnapshotArrayResponseSchema,\r\n // WebSocket schemas\r\n WsChannelSchema,\r\n WsConnectionStateSchema,\r\n WsServerMessageSchema,\r\n WsSubscribedSchema,\r\n WsUnsubscribedSchema,\r\n WsPongSchema,\r\n WsErrorSchema,\r\n WsDataSchema,\r\n WsReplayStartedSchema,\r\n WsReplayPausedSchema,\r\n WsReplayResumedSchema,\r\n WsReplayCompletedSchema,\r\n WsReplayStoppedSchema,\r\n WsReplaySnapshotSchema,\r\n WsHistoricalDataSchema,\r\n WsStreamStartedSchema,\r\n WsStreamProgressSchema,\r\n TimestampedRecordSchema,\r\n WsHistoricalBatchSchema,\r\n WsStreamCompletedSchema,\r\n WsStreamStoppedSchema,\r\n // Validated types (inferred from schemas)\r\n type ValidatedApiMeta,\r\n type ValidatedPriceLevel,\r\n type ValidatedOrderBook,\r\n type ValidatedTrade,\r\n type ValidatedInstrument,\r\n type ValidatedFundingRate,\r\n type ValidatedOpenInterest,\r\n type ValidatedCandle,\r\n type ValidatedLiquidation,\r\n type ValidatedWsServerMessage,\r\n} from './schemas';\r\n\r\n// Types\r\nexport type {\r\n ClientOptions,\r\n ApiMeta,\r\n ApiResponse,\r\n Timestamp,\r\n // Order Book\r\n PriceLevel,\r\n OrderBook,\r\n GetOrderBookParams,\r\n OrderBookHistoryParams,\r\n LighterGranularity,\r\n // Trades\r\n Trade,\r\n GetTradesCursorParams,\r\n CursorResponse,\r\n TradeSide,\r\n TradeDirection,\r\n // Instruments\r\n Instrument,\r\n LighterInstrument,\r\n Hip3Instrument,\r\n InstrumentType,\r\n // Funding\r\n FundingRate,\r\n FundingHistoryParams,\r\n // Open Interest\r\n OpenInterest,\r\n OpenInterestHistoryParams,\r\n OiFundingInterval,\r\n // Candles\r\n Candle,\r\n CandleInterval,\r\n CandleHistoryParams,\r\n // Liquidations\r\n Liquidation,\r\n LiquidationHistoryParams,\r\n LiquidationsByUserParams,\r\n LiquidationVolume,\r\n LiquidationVolumeParams,\r\n // Coin Freshness\r\n DataTypeFreshnessInfo,\r\n CoinFreshness,\r\n // Coin Summary\r\n CoinSummary,\r\n // Price History\r\n PriceSnapshot,\r\n PriceHistoryParams,\r\n // Data Quality\r\n SystemStatusValue,\r\n ExchangeStatus,\r\n DataTypeStatus,\r\n StatusResponse,\r\n DataTypeCoverage,\r\n ExchangeCoverage,\r\n CoverageResponse,\r\n CoverageGap,\r\n DataCadence,\r\n SymbolDataTypeCoverage,\r\n SymbolCoverageOptions,\r\n SymbolCoverageResponse,\r\n IncidentStatusValue,\r\n IncidentSeverityValue,\r\n Incident,\r\n Pagination,\r\n IncidentsResponse,\r\n WebSocketLatency,\r\n RestApiLatency,\r\n DataFreshness,\r\n ExchangeLatency,\r\n LatencyResponse,\r\n SlaTargets,\r\n CompletenessMetrics,\r\n SlaActual,\r\n SlaResponse,\r\n ListIncidentsParams,\r\n SlaParams,\r\n // WebSocket\r\n WsChannel,\r\n WsOptions,\r\n WsClientMessage,\r\n WsServerMessage,\r\n WsConnectionState,\r\n WsEventHandlers,\r\n WsSubscribe,\r\n WsUnsubscribe,\r\n WsPing,\r\n WsSubscribed,\r\n WsUnsubscribed,\r\n WsPong,\r\n WsError,\r\n WsData,\r\n // WebSocket Replay (Option B)\r\n WsReplay,\r\n WsReplayPause,\r\n WsReplayResume,\r\n WsReplaySeek,\r\n WsReplayStop,\r\n WsReplayStarted,\r\n WsReplayPaused,\r\n WsReplayResumed,\r\n WsReplayCompleted,\r\n WsReplayStopped,\r\n WsReplaySnapshot,\r\n WsHistoricalData,\r\n WsHistoricalTickData,\r\n OrderbookDelta,\r\n // WebSocket Bulk Stream (Option D)\r\n WsStream,\r\n WsStreamStop,\r\n WsStreamStarted,\r\n WsStreamProgress,\r\n TimestampedRecord,\r\n WsHistoricalBatch,\r\n WsStreamCompleted,\r\n WsStreamStopped,\r\n WsGapDetected,\r\n // Errors\r\n ApiError,\r\n} from './types';\r\n\r\nexport { OxArchiveError } from './types';\r\n\r\n// Default export for convenience\r\nexport { OxArchive as default } from './client';\r\n","/**\r\n * Configuration options for the 0xarchive client\r\n */\r\nexport interface ClientOptions {\r\n /** Your 0xarchive API key */\r\n apiKey: string;\r\n /** Base URL for the API (defaults to https://api.0xarchive.io) */\r\n baseUrl?: string;\r\n /** Request timeout in milliseconds (defaults to 30000) */\r\n timeout?: number;\r\n /** Enable runtime validation of API responses using Zod schemas (defaults to false) */\r\n validate?: boolean;\r\n}\r\n\r\n/**\r\n * Response metadata\r\n */\r\nexport interface ApiMeta {\r\n /** Number of records returned */\r\n count: number;\r\n /** Cursor for next page (if available) */\r\n nextCursor?: string;\r\n /** Unique request ID for debugging */\r\n requestId: string;\r\n}\r\n\r\n/**\r\n * Standard API response wrapper\r\n */\r\nexport interface ApiResponse<T> {\r\n success: boolean;\r\n data: T;\r\n meta: ApiMeta;\r\n}\r\n\r\n\r\n// =============================================================================\r\n// Order Book Types\r\n// =============================================================================\r\n\r\n/**\r\n * A price level in the order book\r\n */\r\nexport interface PriceLevel {\r\n /** Price at this level */\r\n px: string;\r\n /** Total size at this price level */\r\n sz: string;\r\n /** Number of orders at this level */\r\n n: number;\r\n}\r\n\r\n/**\r\n * Order book snapshot\r\n */\r\nexport interface OrderBook {\r\n /** Trading pair symbol (e.g., BTC, ETH) */\r\n coin: string;\r\n /** Snapshot timestamp (UTC) */\r\n timestamp: string;\r\n /** Bid price levels (best bid first) */\r\n bids: PriceLevel[];\r\n /** Ask price levels (best ask first) */\r\n asks: PriceLevel[];\r\n /** Mid price (best bid + best ask) / 2 */\r\n midPrice?: string;\r\n /** Spread in absolute terms (best ask - best bid) */\r\n spread?: string;\r\n /** Spread in basis points */\r\n spreadBps?: string;\r\n}\r\n\r\nexport interface GetOrderBookParams {\r\n /** Timestamp to get order book at (Unix ms or ISO string) */\r\n timestamp?: number | string;\r\n /** Number of price levels to return per side */\r\n depth?: number;\r\n}\r\n\r\n/**\r\n * Lighter orderbook data granularity levels.\r\n * Controls the resolution of historical orderbook data (Lighter.xyz only).\r\n *\r\n * - 'checkpoint': ~60s intervals (default, all tiers)\r\n * - '30s': 30 second intervals (Build+ tier)\r\n * - '10s': 10 second intervals (Build+ tier)\r\n * - '1s': 1 second intervals (Pro+ tier)\r\n * - 'tick': Checkpoint + raw deltas (Enterprise tier only)\r\n */\r\nexport type LighterGranularity = 'checkpoint' | '30s' | '10s' | '1s' | 'tick';\r\n\r\nexport interface OrderBookHistoryParams extends CursorPaginationParams {\r\n /** Number of price levels to return per side */\r\n depth?: number;\r\n /**\r\n * Data resolution for Lighter orderbook history (Lighter.xyz only, ignored for Hyperliquid).\r\n * Controls the granularity of returned snapshots. Tier restrictions apply.\r\n * Credit multipliers: checkpoint=1x, 30s=2x, 10s=3x, 1s=10x, tick=20x.\r\n * @default 'checkpoint'\r\n */\r\n granularity?: LighterGranularity;\r\n}\r\n\r\n// =============================================================================\r\n// Trade/Fill Types\r\n// =============================================================================\r\n\r\n/** Trade side: 'A' (ask/sell) or 'B' (bid/buy) */\r\nexport type TradeSide = 'A' | 'B';\r\n\r\n/** Position direction (can include 'Open Long', 'Close Short', 'Long > Short', etc.) */\r\nexport type TradeDirection = string;\r\n\r\n/**\r\n * Trade/fill record with full execution details\r\n */\r\nexport interface Trade {\r\n /** Trading pair symbol */\r\n coin: string;\r\n /** Trade side: 'A' (ask/sell) or 'B' (bid/buy) */\r\n side: TradeSide;\r\n /** Execution price */\r\n price: string;\r\n /** Trade size */\r\n size: string;\r\n /** Execution timestamp (UTC) */\r\n timestamp: string;\r\n /** Blockchain transaction hash */\r\n txHash?: string;\r\n /** Unique trade ID */\r\n tradeId?: number;\r\n /** Associated order ID */\r\n orderId?: number;\r\n /** True if taker (crossed the spread), false if maker */\r\n crossed?: boolean;\r\n /** Trading fee amount */\r\n fee?: string;\r\n /** Fee denomination (e.g., USDC) */\r\n feeToken?: string;\r\n /** Realized PnL if closing a position */\r\n closedPnl?: string;\r\n /** Position direction */\r\n direction?: TradeDirection;\r\n /** Position size before this trade */\r\n startPosition?: string;\r\n /** User's wallet address (for fill-level data from REST API) */\r\n userAddress?: string;\r\n /** Maker's wallet address (for market-level WebSocket trades) */\r\n makerAddress?: string;\r\n /** Taker's wallet address (for market-level WebSocket trades) */\r\n takerAddress?: string;\r\n}\r\n\r\n/**\r\n * Cursor-based pagination parameters (recommended)\r\n * More efficient than offset-based pagination for large datasets.\r\n * The cursor is a timestamp - use the `nextCursor` from the response to get the next page.\r\n */\r\nexport interface CursorPaginationParams {\r\n /** Start timestamp (Unix ms or ISO string) - REQUIRED */\r\n start: number | string;\r\n /** End timestamp (Unix ms or ISO string) - REQUIRED */\r\n end: number | string;\r\n /** Cursor from previous response's nextCursor (timestamp). If not provided, starts from the beginning of the range. */\r\n cursor?: number | string;\r\n /** Maximum number of results to return (default: 100, max: 1000) */\r\n limit?: number;\r\n}\r\n\r\n/**\r\n * Parameters for getting trades with cursor-based pagination (recommended)\r\n */\r\nexport interface GetTradesCursorParams extends CursorPaginationParams {\r\n /** Filter by side */\r\n side?: TradeSide;\r\n}\r\n\r\n/**\r\n * Response with cursor for pagination\r\n */\r\nexport interface CursorResponse<T> {\r\n data: T;\r\n /** Cursor for next page (use as cursor parameter) */\r\n nextCursor?: string;\r\n}\r\n\r\n// =============================================================================\r\n// Instruments Types\r\n// =============================================================================\r\n\r\n/** Instrument type */\r\nexport type InstrumentType = 'perp' | 'spot';\r\n\r\n/**\r\n * Trading instrument metadata (Hyperliquid)\r\n */\r\nexport interface Instrument {\r\n /** Instrument symbol (e.g., BTC) */\r\n name: string;\r\n /** Size decimal precision */\r\n szDecimals: number;\r\n /** Maximum leverage allowed */\r\n maxLeverage?: number;\r\n /** If true, only isolated margin mode is allowed */\r\n onlyIsolated?: boolean;\r\n /** Type of instrument */\r\n instrumentType?: InstrumentType;\r\n /** Whether the instrument is currently tradeable */\r\n isActive: boolean;\r\n}\r\n\r\n/**\r\n * Trading instrument metadata (Lighter.xyz)\r\n *\r\n * Lighter instruments have a different schema than Hyperliquid with more\r\n * detailed market configuration including fees and minimum amounts.\r\n */\r\nexport interface LighterInstrument {\r\n /** Instrument symbol (e.g., BTC, ETH) */\r\n symbol: string;\r\n /** Unique market identifier */\r\n marketId: number;\r\n /** Market type (e.g., 'perp') */\r\n marketType: string;\r\n /** Market status (e.g., 'active') */\r\n status: string;\r\n /** Taker fee rate (e.g., 0.0005 = 0.05%) */\r\n takerFee: number;\r\n /** Maker fee rate (e.g., 0.0002 = 0.02%) */\r\n makerFee: number;\r\n /** Liquidation fee rate */\r\n liquidationFee: number;\r\n /** Minimum order size in base currency */\r\n minBaseAmount: number;\r\n /** Minimum order size in quote currency */\r\n minQuoteAmount: number;\r\n /** Size decimal precision */\r\n sizeDecimals: number;\r\n /** Price decimal precision */\r\n priceDecimals: number;\r\n /** Quote currency decimal precision */\r\n quoteDecimals: number;\r\n /** Whether the instrument is currently tradeable */\r\n isActive: boolean;\r\n}\r\n\r\n/**\r\n * HIP-3 Builder Perps instrument with latest market data.\r\n * Derived from live open interest data.\r\n */\r\nexport interface Hip3Instrument {\r\n /** Full coin name (e.g., km:US500, xyz:XYZ100) */\r\n coin: string;\r\n /** Builder namespace (e.g., km, xyz) */\r\n namespace: string;\r\n /** Ticker within the namespace (e.g., US500, XYZ100) */\r\n ticker: string;\r\n /** Latest mark price */\r\n markPrice?: number;\r\n /** Latest open interest */\r\n openInterest?: number;\r\n /** Latest mid price */\r\n midPrice?: number;\r\n /** Timestamp of latest data point */\r\n latestTimestamp?: string;\r\n}\r\n\r\n// =============================================================================\r\n// Funding Types\r\n// =============================================================================\r\n\r\n/**\r\n * Funding rate record\r\n */\r\nexport interface FundingRate {\r\n /** Trading pair symbol */\r\n coin: string;\r\n /** Funding timestamp (UTC) */\r\n timestamp: string;\r\n /** Funding rate as decimal (e.g., 0.0001 = 0.01%) */\r\n fundingRate: string;\r\n /** Premium component of funding rate */\r\n premium?: string;\r\n}\r\n\r\n/**\r\n * Aggregation interval for OI and funding history.\r\n * When omitted, raw ~1 min data is returned.\r\n */\r\nexport type OiFundingInterval = '5m' | '15m' | '30m' | '1h' | '4h' | '1d';\r\n\r\n/**\r\n * Parameters for getting funding rate history\r\n */\r\nexport interface FundingHistoryParams extends CursorPaginationParams {\r\n /** Aggregation interval. When omitted, raw ~1 min data is returned. */\r\n interval?: OiFundingInterval;\r\n}\r\n\r\n// =============================================================================\r\n// Open Interest Types\r\n// =============================================================================\r\n\r\n/**\r\n * Open interest snapshot with market context\r\n */\r\nexport interface OpenInterest {\r\n /** Trading pair symbol */\r\n coin: string;\r\n /** Snapshot timestamp (UTC) */\r\n timestamp: string;\r\n /** Total open interest in contracts */\r\n openInterest: string;\r\n /** Mark price used for liquidations */\r\n markPrice?: string;\r\n /** Oracle price from external feed */\r\n oraclePrice?: string;\r\n /** 24-hour notional volume */\r\n dayNtlVolume?: string;\r\n /** Price 24 hours ago */\r\n prevDayPrice?: string;\r\n /** Current mid price */\r\n midPrice?: string;\r\n /** Impact bid price for liquidations */\r\n impactBidPrice?: string;\r\n /** Impact ask price for liquidations */\r\n impactAskPrice?: string;\r\n}\r\n\r\n/**\r\n * Parameters for getting open interest history\r\n */\r\nexport interface OpenInterestHistoryParams extends CursorPaginationParams {\r\n /** Aggregation interval. When omitted, raw ~1 min data is returned. */\r\n interval?: OiFundingInterval;\r\n}\r\n\r\n// =============================================================================\r\n// Liquidation Types\r\n// =============================================================================\r\n\r\n/**\r\n * Liquidation event record\r\n */\r\nexport interface Liquidation {\r\n /** Trading pair symbol */\r\n coin: string;\r\n /** Liquidation timestamp (UTC) */\r\n timestamp: string;\r\n /** Address of the liquidated user */\r\n liquidatedUser: string;\r\n /** Address of the liquidator */\r\n liquidatorUser: string;\r\n /** Liquidation execution price */\r\n price: string;\r\n /** Liquidation size */\r\n size: string;\r\n /** Side: 'B' (buy) or 'S' (sell) */\r\n side: 'B' | 'S';\r\n /** Mark price at time of liquidation */\r\n markPrice?: string;\r\n /** Realized PnL from the liquidation */\r\n closedPnl?: string;\r\n /** Position direction (e.g., 'Open Long', 'Close Short') */\r\n direction?: string;\r\n /** Unique trade ID */\r\n tradeId?: number;\r\n /** Blockchain transaction hash */\r\n txHash?: string;\r\n}\r\n\r\n/**\r\n * Parameters for getting liquidation history\r\n */\r\nexport interface LiquidationHistoryParams extends CursorPaginationParams {}\r\n\r\n/**\r\n * Parameters for getting liquidations by user\r\n */\r\nexport interface LiquidationsByUserParams extends CursorPaginationParams {\r\n /** Optional coin filter */\r\n coin?: string;\r\n}\r\n\r\n// =============================================================================\r\n// Candle Types\r\n// =============================================================================\r\n\r\n/** Candle interval for OHLCV data */\r\nexport type CandleInterval = '1m' | '5m' | '15m' | '30m' | '1h' | '4h' | '1d' | '1w';\r\n\r\n/**\r\n * OHLCV candle data\r\n */\r\nexport interface Candle {\r\n /** Candle open timestamp (UTC) */\r\n timestamp: string;\r\n /** Opening price */\r\n open: number;\r\n /** Highest price during the interval */\r\n high: number;\r\n /** Lowest price during the interval */\r\n low: number;\r\n /** Closing price */\r\n close: number;\r\n /** Total volume traded during the interval */\r\n volume: number;\r\n /** Total quote volume (volume * price) */\r\n quoteVolume?: number;\r\n /** Number of trades during the interval */\r\n tradeCount?: number;\r\n}\r\n\r\n/**\r\n * Parameters for getting candle history\r\n */\r\nexport interface CandleHistoryParams extends CursorPaginationParams {\r\n /** Candle interval (default: 1h) */\r\n interval?: CandleInterval;\r\n /** Maximum number of results to return (default: 100, max: 10000 for candles) */\r\n limit?: number;\r\n}\r\n\r\n// =============================================================================\r\n// Aggregated Liquidation Volume Types\r\n// =============================================================================\r\n\r\n/** Pre-aggregated liquidation volume bucket */\r\nexport interface LiquidationVolume {\r\n /** Trading pair symbol */\r\n coin: string;\r\n /** Bucket timestamp (UTC) */\r\n timestamp: string;\r\n /** Total liquidation volume in USD (price * size) */\r\n totalUsd: number;\r\n /** Long liquidations volume */\r\n longUsd: number;\r\n /** Short liquidations volume */\r\n shortUsd: number;\r\n /** Total liquidation count */\r\n count: number;\r\n /** Long liquidation count */\r\n longCount: number;\r\n /** Short liquidation count */\r\n shortCount: number;\r\n}\r\n\r\n/** Parameters for getting aggregated liquidation volume */\r\nexport interface LiquidationVolumeParams extends CursorPaginationParams {\r\n /** Aggregation interval (default: 1h). Valid: 5m, 15m, 30m, 1h, 4h, 1d */\r\n interval?: OiFundingInterval;\r\n}\r\n\r\n// =============================================================================\r\n// Per-Coin Freshness Types\r\n// =============================================================================\r\n\r\n/** Freshness data for a single data type */\r\nexport interface DataTypeFreshnessInfo {\r\n /** Last update timestamp */\r\n lastUpdated?: string;\r\n /** Lag in milliseconds */\r\n lagMs?: number;\r\n}\r\n\r\n/** Per-coin freshness across all data types */\r\nexport interface CoinFreshness {\r\n /** Coin symbol */\r\n coin: string;\r\n /** Exchange name */\r\n exchange: string;\r\n /** When this measurement was taken */\r\n measuredAt: string;\r\n /** Orderbook freshness */\r\n orderbook: DataTypeFreshnessInfo;\r\n /** Trades freshness */\r\n trades: DataTypeFreshnessInfo;\r\n /** Funding freshness */\r\n funding: DataTypeFreshnessInfo;\r\n /** Open interest freshness */\r\n openInterest: DataTypeFreshnessInfo;\r\n /** Liquidations freshness (Hyperliquid only) */\r\n liquidations?: DataTypeFreshnessInfo;\r\n}\r\n\r\n// =============================================================================\r\n// Coin Summary Types\r\n// =============================================================================\r\n\r\n/** Combined market summary for a coin */\r\nexport interface CoinSummary {\r\n /** Trading pair symbol */\r\n coin: string;\r\n /** Timestamp (UTC) */\r\n timestamp: string;\r\n /** Latest mark price */\r\n markPrice?: string;\r\n /** Latest oracle price */\r\n oraclePrice?: string;\r\n /** Latest mid price */\r\n midPrice?: string;\r\n /** Current funding rate */\r\n fundingRate?: string;\r\n /** Funding premium */\r\n premium?: string;\r\n /** Current open interest */\r\n openInterest?: string;\r\n /** 24h notional trading volume */\r\n volume24h?: string;\r\n /** 24h total liquidation volume in USD */\r\n liquidationVolume24h?: number;\r\n /** 24h long liquidation volume in USD */\r\n longLiquidationVolume24h?: number;\r\n /** 24h short liquidation volume in USD */\r\n shortLiquidationVolume24h?: number;\r\n}\r\n\r\n// =============================================================================\r\n// Price History Types\r\n// =============================================================================\r\n\r\n/** Price snapshot from OI data */\r\nexport interface PriceSnapshot {\r\n /** Timestamp (UTC) */\r\n timestamp: string;\r\n /** Mark price */\r\n markPrice?: string;\r\n /** Oracle price */\r\n oraclePrice?: string;\r\n /** Mid price */\r\n midPrice?: string;\r\n}\r\n\r\n/** Parameters for price history */\r\nexport interface PriceHistoryParams extends CursorPaginationParams {\r\n /** Aggregation interval. When omitted, raw ~1 min data is returned. */\r\n interval?: OiFundingInterval;\r\n}\r\n\r\n// =============================================================================\r\n// WebSocket Types\r\n// =============================================================================\r\n\r\n/**\r\n * WebSocket channel types.\r\n *\r\n * - ticker/all_tickers: real-time only\r\n * - liquidations: historical only (May 2025+)\r\n * - open_interest, funding, lighter_open_interest, lighter_funding,\r\n * hip3_open_interest, hip3_funding: historical only (replay/stream)\r\n */\r\nexport type WsChannel =\r\n | 'orderbook' | 'trades' | 'candles' | 'liquidations' | 'ticker' | 'all_tickers'\r\n | 'open_interest' | 'funding'\r\n | 'lighter_orderbook' | 'lighter_trades' | 'lighter_candles'\r\n | 'lighter_open_interest' | 'lighter_funding'\r\n | 'hip3_orderbook' | 'hip3_trades' | 'hip3_candles'\r\n | 'hip3_open_interest' | 'hip3_funding';\r\n\r\n/** Subscribe message from client */\r\nexport interface WsSubscribe {\r\n op: 'subscribe';\r\n channel: WsChannel;\r\n coin?: string;\r\n}\r\n\r\n/** Unsubscribe message from client */\r\nexport interface WsUnsubscribe {\r\n op: 'unsubscribe';\r\n channel: WsChannel;\r\n coin?: string;\r\n}\r\n\r\n/** Ping message from client */\r\nexport interface WsPing {\r\n op: 'ping';\r\n}\r\n\r\n/** Replay message from client - replays historical data with timing preserved */\r\nexport interface WsReplay {\r\n op: 'replay';\r\n /** Single channel for replay. Mutually exclusive with `channels`. */\r\n channel?: WsChannel;\r\n /** Multiple channels for multi-channel replay. Mutually exclusive with `channel`. */\r\n channels?: WsChannel[];\r\n coin?: string;\r\n /** Start timestamp (Unix ms) */\r\n start: number;\r\n /** End timestamp (Unix ms, defaults to now) */\r\n end?: number;\r\n /** Playback speed multiplier (1 = real-time, 10 = 10x faster) */\r\n speed?: number;\r\n /** Data resolution for Lighter orderbook ('checkpoint', '30s', '10s', '1s', 'tick') */\r\n granularity?: string;\r\n /** Candle interval for candles channel ('1m', '5m', '15m', '30m', '1h', '4h', '1d', '1w') */\r\n interval?: string;\r\n}\r\n\r\n/** Replay control messages */\r\nexport interface WsReplayPause { op: 'replay.pause'; }\r\nexport interface WsReplayResume { op: 'replay.resume'; }\r\nexport interface WsReplaySeek { op: 'replay.seek'; timestamp: number; }\r\nexport interface WsReplayStop { op: 'replay.stop'; }\r\n\r\n/** Stream message from client - bulk download historical data */\r\nexport interface WsStream {\r\n op: 'stream';\r\n /** Single channel for streaming. Mutually exclusive with `channels`. */\r\n channel?: WsChannel;\r\n /** Multiple channels for multi-channel streaming. Mutually exclusive with `channel`. */\r\n channels?: WsChannel[];\r\n coin?: string;\r\n /** Start timestamp (Unix ms) */\r\n start: number;\r\n /** End timestamp (Unix ms) */\r\n end: number;\r\n /** Batch size (records per message) */\r\n batch_size?: number;\r\n /** Data resolution for Lighter orderbook ('checkpoint', '30s', '10s', '1s', 'tick') */\r\n granularity?: string;\r\n /** Candle interval for candles channel ('1m', '5m', '15m', '30m', '1h', '4h', '1d', '1w') */\r\n interval?: string;\r\n}\r\n\r\n/** Stream control messages */\r\nexport interface WsStreamStop { op: 'stream.stop'; }\r\n\r\n/** Client message union type */\r\nexport type WsClientMessage =\r\n | WsSubscribe\r\n | WsUnsubscribe\r\n | WsPing\r\n | WsReplay\r\n | WsReplayPause\r\n | WsReplayResume\r\n | WsReplaySeek\r\n | WsReplayStop\r\n | WsStream\r\n | WsStreamStop;\r\n\r\n/** Subscription confirmed from server */\r\nexport interface WsSubscribed {\r\n type: 'subscribed';\r\n channel: WsChannel;\r\n coin?: string;\r\n}\r\n\r\n/** Unsubscription confirmed from server */\r\nexport interface WsUnsubscribed {\r\n type: 'unsubscribed';\r\n channel: WsChannel;\r\n coin?: string;\r\n}\r\n\r\n/** Pong response from server */\r\nexport interface WsPong {\r\n type: 'pong';\r\n}\r\n\r\n/** Error from server */\r\nexport interface WsError {\r\n type: 'error';\r\n message: string;\r\n}\r\n\r\n/** Data message from server (real-time) */\r\nexport interface WsData<T = unknown> {\r\n type: 'data';\r\n channel: WsChannel;\r\n coin: string;\r\n data: T;\r\n}\r\n\r\n/** Replay started response */\r\nexport interface WsReplayStarted {\r\n type: 'replay_started';\r\n channel: WsChannel;\r\n coin: string;\r\n /** Start timestamp in milliseconds */\r\n start: number;\r\n /** End timestamp in milliseconds */\r\n end: number;\r\n /** Playback speed multiplier */\r\n speed: number;\r\n}\r\n\r\n/** Replay paused response */\r\nexport interface WsReplayPaused {\r\n type: 'replay_paused';\r\n current_timestamp: number;\r\n}\r\n\r\n/** Replay resumed response */\r\nexport interface WsReplayResumed {\r\n type: 'replay_resumed';\r\n current_timestamp: number;\r\n}\r\n\r\n/** Replay completed response */\r\nexport interface WsReplayCompleted {\r\n type: 'replay_completed';\r\n channel: WsChannel;\r\n coin: string;\r\n snapshots_sent: number;\r\n}\r\n\r\n/** Replay stopped response */\r\nexport interface WsReplayStopped {\r\n type: 'replay_stopped';\r\n}\r\n\r\n/** Historical data point (replay mode) */\r\nexport interface WsHistoricalData<T = unknown> {\r\n type: 'historical_data';\r\n channel: WsChannel;\r\n coin: string;\r\n timestamp: number;\r\n data: T;\r\n}\r\n\r\n/**\r\n * Replay snapshot providing initial state for a channel before the timeline starts.\r\n * Sent in multi-channel replay/stream mode to provide the most recent data point\r\n * for each channel at the replay start time. This allows clients to initialize\r\n * their state (e.g., current orderbook, latest funding rate) before timeline\r\n * data begins arriving via `historical_data` messages.\r\n */\r\nexport interface WsReplaySnapshot<T = unknown> {\r\n type: 'replay_snapshot';\r\n channel: WsChannel;\r\n coin: string;\r\n timestamp: number;\r\n data: T;\r\n}\r\n\r\n/** Orderbook delta for tick-level data */\r\nexport interface OrderbookDelta {\r\n /** Timestamp in milliseconds */\r\n timestamp: number;\r\n /** Side: 'bid' or 'ask' */\r\n side: 'bid' | 'ask';\r\n /** Price level */\r\n price: number;\r\n /** New size (0 = level removed) */\r\n size: number;\r\n /** Sequence number for ordering */\r\n sequence: number;\r\n}\r\n\r\n/** Historical tick data (granularity='tick' mode) - checkpoint + deltas */\r\nexport interface WsHistoricalTickData {\r\n type: 'historical_tick_data';\r\n channel: WsChannel;\r\n coin: string;\r\n /** Initial checkpoint (full orderbook snapshot) */\r\n checkpoint: OrderBook;\r\n /** Incremental deltas to apply after checkpoint */\r\n deltas: OrderbookDelta[];\r\n}\r\n\r\n/** Stream started response */\r\nexport interface WsStreamStarted {\r\n type: 'stream_started';\r\n channel: WsChannel;\r\n coin: string;\r\n /** Start timestamp in milliseconds */\r\n start: number;\r\n /** End timestamp in milliseconds */\r\n end: number;\r\n}\r\n\r\n/** Stream progress response (sent periodically during streaming) */\r\nexport interface WsStreamProgress {\r\n type: 'stream_progress';\r\n snapshots_sent: number;\r\n}\r\n\r\n/** A record with timestamp for batched data */\r\nexport interface TimestampedRecord<T = unknown> {\r\n timestamp: number;\r\n data: T;\r\n}\r\n\r\n/** Batch of historical data (bulk streaming) */\r\nexport interface WsHistoricalBatch<T = unknown> {\r\n type: 'historical_batch';\r\n channel: WsChannel;\r\n coin: string;\r\n data: TimestampedRecord<T>[];\r\n}\r\n\r\n/** Stream completed response */\r\nexport interface WsStreamCompleted {\r\n type: 'stream_completed';\r\n channel: WsChannel;\r\n coin: string;\r\n snapshots_sent: number;\r\n}\r\n\r\n/** Stream stopped response */\r\nexport interface WsStreamStopped {\r\n type: 'stream_stopped';\r\n snapshots_sent: number;\r\n}\r\n\r\n/**\r\n * Gap detected in historical data stream.\r\n * Sent when there's a gap exceeding the threshold between consecutive data points.\r\n * Thresholds: 2 minutes for orderbook/candles/liquidations, 60 minutes for trades.\r\n */\r\nexport interface WsGapDetected {\r\n type: 'gap_detected';\r\n channel: WsChannel;\r\n coin: string;\r\n /** Start of the gap (last data point timestamp in ms) */\r\n gap_start: number;\r\n /** End of the gap (next data point timestamp in ms) */\r\n gap_end: number;\r\n /** Gap duration in minutes */\r\n duration_minutes: number;\r\n}\r\n\r\n/** Server message union type */\r\nexport type WsServerMessage =\r\n | WsSubscribed\r\n | WsUnsubscribed\r\n | WsPong\r\n | WsError\r\n | WsData\r\n | WsReplayStarted\r\n | WsReplayPaused\r\n | WsReplayResumed\r\n | WsReplayCompleted\r\n | WsReplayStopped\r\n | WsReplaySnapshot\r\n | WsHistoricalData\r\n | WsHistoricalTickData\r\n | WsStreamStarted\r\n | WsStreamProgress\r\n | WsHistoricalBatch\r\n | WsStreamCompleted\r\n | WsStreamStopped\r\n | WsGapDetected;\r\n\r\n/**\r\n * WebSocket connection options.\r\n *\r\n * The server sends WebSocket ping frames every 30 seconds and will disconnect\r\n * idle connections after 60 seconds. The SDK automatically handles keep-alive\r\n * by sending application-level pings at the configured interval.\r\n */\r\nexport interface WsOptions {\r\n /** API key for authentication */\r\n apiKey: string;\r\n /** WebSocket URL (defaults to wss://api.0xarchive.io/ws) */\r\n wsUrl?: string;\r\n /** Auto-reconnect on disconnect (defaults to true) */\r\n autoReconnect?: boolean;\r\n /** Reconnect delay in ms (defaults to 1000) */\r\n reconnectDelay?: number;\r\n /** Maximum reconnect attempts (defaults to 10) */\r\n maxReconnectAttempts?: number;\r\n /** Ping interval in ms to keep connection alive (defaults to 30000). Server disconnects after 60s idle. */\r\n pingInterval?: number;\r\n}\r\n\r\n/** WebSocket connection state */\r\nexport type WsConnectionState = 'connecting' | 'connected' | 'disconnected' | 'reconnecting';\r\n\r\n/** WebSocket event handlers */\r\nexport interface WsEventHandlers {\r\n onOpen?: () => void;\r\n onClose?: (code: number, reason: string) => void;\r\n onError?: (error: Error) => void;\r\n onMessage?: (message: WsServerMessage) => void;\r\n onStateChange?: (state: WsConnectionState) => void;\r\n}\r\n\r\n// =============================================================================\r\n// Error Types\r\n// =============================================================================\r\n\r\n/**\r\n * API error response\r\n */\r\nexport interface ApiError {\r\n code: number;\r\n error: string;\r\n}\r\n\r\n/**\r\n * SDK error class\r\n */\r\nexport class OxArchiveError extends Error {\r\n code: number;\r\n requestId?: string;\r\n\r\n constructor(message: string, code: number, requestId?: string) {\r\n super(message);\r\n this.name = 'OxArchiveError';\r\n this.code = code;\r\n this.requestId = requestId;\r\n }\r\n}\r\n\r\n/** Timestamp can be Unix ms (number), ISO string, or Date object */\r\nexport type Timestamp = number | string | Date;\r\n\r\n// =============================================================================\r\n// Data Quality Types\r\n// =============================================================================\r\n\r\n/** System status values */\r\nexport type SystemStatusValue = 'operational' | 'degraded' | 'outage' | 'maintenance';\r\n\r\n/** Status of a single exchange */\r\nexport interface ExchangeStatus {\r\n /** Current status */\r\n status: SystemStatusValue;\r\n /** Timestamp of last received data */\r\n lastDataAt?: string;\r\n /** Current latency in milliseconds */\r\n latencyMs?: number;\r\n}\r\n\r\n/** Status of a data type (orderbook, fills, etc.) */\r\nexport interface DataTypeStatus {\r\n /** Current status */\r\n status: SystemStatusValue;\r\n /** Data completeness over last 24 hours (0-100) */\r\n completeness24h: number;\r\n}\r\n\r\n/** Overall system status response */\r\nexport interface StatusResponse {\r\n /** Overall system status */\r\n status: SystemStatusValue;\r\n /** When this status was computed */\r\n updatedAt: string;\r\n /** Per-exchange status */\r\n exchanges: Record<string, ExchangeStatus>;\r\n /** Per-data-type status */\r\n dataTypes: Record<string, DataTypeStatus>;\r\n /** Number of active incidents */\r\n activeIncidents: number;\r\n}\r\n\r\n/** Coverage information for a specific data type */\r\nexport interface DataTypeCoverage {\r\n /** Earliest available data timestamp */\r\n earliest: string;\r\n /** Latest available data timestamp */\r\n latest: string;\r\n /** Total number of records */\r\n totalRecords: number;\r\n /** Number of symbols with data */\r\n symbols: number;\r\n /** Data resolution (e.g., '1.2s', '1m') */\r\n resolution?: string;\r\n /** Current data lag */\r\n lag?: string;\r\n /** Completeness percentage (0-100) */\r\n completeness: number;\r\n}\r\n\r\n/** Coverage for a single exchange */\r\nexport interface ExchangeCoverage {\r\n /** Exchange name */\r\n exchange: string;\r\n /** Coverage per data type */\r\n dataTypes: Record<string, DataTypeCoverage>;\r\n}\r\n\r\n/** Overall coverage response */\r\nexport interface CoverageResponse {\r\n /** Coverage for all exchanges */\r\n exchanges: ExchangeCoverage[];\r\n}\r\n\r\n/** Gap information for per-symbol coverage */\r\nexport interface CoverageGap {\r\n /** Start of the gap (last data before gap) */\r\n start: string;\r\n /** End of the gap (first data after gap) */\r\n end: string;\r\n /** Duration of the gap in minutes */\r\n durationMinutes: number;\r\n}\r\n\r\n/** Empirical data cadence measurement based on last 7 days of data */\r\nexport interface DataCadence {\r\n /** Median interval between consecutive records in seconds */\r\n medianIntervalSeconds: number;\r\n /** 95th percentile interval between consecutive records in seconds */\r\n p95IntervalSeconds: number;\r\n /** Number of intervals sampled for this measurement */\r\n sampleCount: number;\r\n}\r\n\r\n/** Coverage for a specific symbol and data type */\r\nexport interface SymbolDataTypeCoverage {\r\n /** Earliest available data timestamp */\r\n earliest: string;\r\n /** Latest available data timestamp */\r\n latest: string;\r\n /** Total number of records */\r\n totalRecords: number;\r\n /** 24-hour completeness percentage (0-100) */\r\n completeness: number;\r\n /** Historical coverage percentage (0-100) based on hours with data / total hours */\r\n historicalCoverage?: number;\r\n /** Detected data gaps within the requested time window */\r\n gaps: CoverageGap[];\r\n /** Empirical data cadence (present when sufficient data exists) */\r\n cadence?: DataCadence;\r\n}\r\n\r\n/** Options for symbol coverage query */\r\nexport interface SymbolCoverageOptions {\r\n /** Start of gap detection window (Unix milliseconds). Default: now - 30 days */\r\n from?: number;\r\n /** End of gap detection window (Unix milliseconds). Default: now */\r\n to?: number;\r\n}\r\n\r\n/** Per-symbol coverage response */\r\nexport interface SymbolCoverageResponse {\r\n /** Exchange name */\r\n exchange: string;\r\n /** Symbol name */\r\n symbol: string;\r\n /** Coverage per data type */\r\n dataTypes: Record<string, SymbolDataTypeCoverage>;\r\n}\r\n\r\n/** Incident status values */\r\nexport type IncidentStatusValue = 'open' | 'investigating' | 'identified' | 'monitoring' | 'resolved';\r\n\r\n/** Incident severity values */\r\nexport type IncidentSeverityValue = 'minor' | 'major' | 'critical';\r\n\r\n/** Data quality incident */\r\nexport interface Incident {\r\n /** Unique incident ID */\r\n id: string;\r\n /** Status: open, investigating, identified, monitoring, resolved */\r\n status: string;\r\n /** Severity: minor, major, critical */\r\n severity: string;\r\n /** Affected exchange (if specific to one) */\r\n exchange?: string;\r\n /** Affected data types */\r\n dataTypes: string[];\r\n /** Affected symbols */\r\n symbolsAffected: string[];\r\n /** When the incident started */\r\n startedAt: string;\r\n /** When the incident was resolved */\r\n resolvedAt?: string;\r\n /** Total duration in minutes */\r\n durationMinutes?: number;\r\n /** Incident title */\r\n title: string;\r\n /** Detailed description */\r\n description?: string;\r\n /** Root cause analysis */\r\n rootCause?: string;\r\n /** Resolution details */\r\n resolution?: string;\r\n /** Number of records affected */\r\n recordsAffected?: number;\r\n /** Number of records recovered */\r\n recordsRecovered?: number;\r\n}\r\n\r\n/** Pagination info for incident list */\r\nexport interface Pagination {\r\n /** Total number of incidents */\r\n total: number;\r\n /** Page size limit */\r\n limit: number;\r\n /** Current offset */\r\n offset: number;\r\n}\r\n\r\n/** Incidents list response */\r\nexport interface IncidentsResponse {\r\n /** List of incidents */\r\n incidents: Incident[];\r\n /** Pagination info */\r\n pagination: Pagination;\r\n}\r\n\r\n/** WebSocket latency metrics */\r\nexport interface WebSocketLatency {\r\n /** Current latency */\r\n currentMs: number;\r\n /** 1-hour average latency */\r\n avg1hMs: number;\r\n /** 24-hour average latency */\r\n avg24hMs: number;\r\n /** 24-hour P99 latency */\r\n p9924hMs?: number;\r\n}\r\n\r\n/** REST API latency metrics */\r\nexport interface RestApiLatency {\r\n /** Current latency */\r\n currentMs: number;\r\n /** 1-hour average latency */\r\n avg1hMs: number;\r\n /** 24-hour average latency */\r\n avg24hMs: number;\r\n}\r\n\r\n/** Data freshness metrics (lag from source) */\r\nexport interface DataFreshness {\r\n /** Orderbook data lag */\r\n orderbookLagMs?: number;\r\n /** Fills/trades data lag */\r\n fillsLagMs?: number;\r\n /** Funding rate data lag */\r\n fundingLagMs?: number;\r\n /** Open interest data lag */\r\n oiLagMs?: number;\r\n}\r\n\r\n/** Latency metrics for a single exchange */\r\nexport interface ExchangeLatency {\r\n /** WebSocket latency metrics */\r\n websocket?: WebSocketLatency;\r\n /** REST API latency metrics */\r\n restApi?: RestApiLatency;\r\n /** Data freshness metrics */\r\n dataFreshness: DataFreshness;\r\n}\r\n\r\n/** Overall latency response */\r\nexport interface LatencyResponse {\r\n /** When these metrics were measured */\r\n measuredAt: string;\r\n /** Per-exchange latency metrics */\r\n exchanges: Record<string, ExchangeLatency>;\r\n}\r\n\r\n/** SLA targets */\r\nexport interface SlaTargets {\r\n /** Uptime target percentage */\r\n uptime: number;\r\n /** Data completeness target percentage */\r\n dataCompleteness: number;\r\n /** API P99 latency target in milliseconds */\r\n apiLatencyP99Ms: number;\r\n}\r\n\r\n/** Completeness metrics per data type */\r\nexport interface CompletenessMetrics {\r\n /** Orderbook completeness percentage */\r\n orderbook: number;\r\n /** Fills completeness percentage */\r\n fills: number;\r\n /** Funding rate completeness percentage */\r\n funding: number;\r\n /** Overall completeness percentage */\r\n overall: number;\r\n}\r\n\r\n/** Actual SLA metrics */\r\nexport interface SlaActual {\r\n /** Actual uptime percentage */\r\n uptime: number;\r\n /** 'met' or 'missed' */\r\n uptimeStatus: string;\r\n /** Actual completeness metrics */\r\n dataCompleteness: CompletenessMetrics;\r\n /** 'met' or 'missed' */\r\n completenessStatus: string;\r\n /** Actual API P99 latency */\r\n apiLatencyP99Ms: number;\r\n /** 'met' or 'missed' */\r\n latencyStatus: string;\r\n}\r\n\r\n/** SLA compliance response */\r\nexport interface SlaResponse {\r\n /** Period covered (e.g., '2026-01') */\r\n period: string;\r\n /** Target SLA metrics */\r\n slaTargets: SlaTargets;\r\n /** Actual SLA metrics */\r\n actual: SlaActual;\r\n /** Number of incidents in this period */\r\n incidentsThisPeriod: number;\r\n /** Total downtime in minutes */\r\n totalDowntimeMinutes: number;\r\n}\r\n\r\n/** Parameters for listing incidents */\r\nexport interface ListIncidentsParams {\r\n /** Filter by incident status */\r\n status?: IncidentStatusValue;\r\n /** Filter by exchange */\r\n exchange?: string;\r\n /** Only show incidents starting after this timestamp (Unix ms) */\r\n since?: number | string;\r\n /** Maximum results per page (default: 20, max: 100) */\r\n limit?: number;\r\n /** Pagination offset */\r\n offset?: number;\r\n}\r\n\r\n/** Parameters for getting SLA metrics */\r\nexport interface SlaParams {\r\n /** Year (defaults to current year) */\r\n year?: number;\r\n /** Month 1-12 (defaults to current month) */\r\n month?: number;\r\n}\r\n","import type { z } from 'zod';\r\nimport type { ApiResponse, ApiError } from './types';\r\nimport { OxArchiveError } from './types';\r\n\r\n/**\r\n * Convert a snake_case string to camelCase\r\n * @internal Exported for testing\r\n */\r\nexport function snakeToCamel(str: string): string {\r\n return str.replace(/_([a-z0-9])/g, (_, char) => char.toUpperCase());\r\n}\r\n\r\n/**\r\n * Recursively transform all object keys from snake_case to camelCase\r\n * @internal Exported for testing\r\n */\r\nexport function transformKeys(obj: unknown): unknown {\r\n if (obj === null || obj === undefined) {\r\n return obj;\r\n }\r\n\r\n if (Array.isArray(obj)) {\r\n return obj.map(transformKeys);\r\n }\r\n\r\n if (typeof obj === 'object') {\r\n const result: Record<string, unknown> = {};\r\n for (const [key, value] of Object.entries(obj as Record<string, unknown>)) {\r\n result[snakeToCamel(key)] = transformKeys(value);\r\n }\r\n return result;\r\n }\r\n\r\n return obj;\r\n}\r\n\r\nexport interface HttpClientOptions {\r\n baseUrl: string;\r\n apiKey: string;\r\n timeout: number;\r\n /** Enable runtime validation of API responses using Zod schemas (default: false) */\r\n validate?: boolean;\r\n}\r\n\r\n/**\r\n * Internal HTTP client for making API requests\r\n */\r\nexport class HttpClient {\r\n private baseUrl: string;\r\n private apiKey: string;\r\n private timeout: number;\r\n private validate: boolean;\r\n\r\n constructor(options: HttpClientOptions) {\r\n this.baseUrl = options.baseUrl.replace(/\\/$/, '');\r\n this.apiKey = options.apiKey;\r\n this.timeout = options.timeout;\r\n this.validate = options.validate ?? false;\r\n }\r\n\r\n /** Whether validation is enabled */\r\n get validationEnabled(): boolean {\r\n return this.validate;\r\n }\r\n\r\n /**\r\n * Make a GET request to the API\r\n *\r\n * @param path - API endpoint path\r\n * @param params - Query parameters\r\n * @param schema - Optional Zod schema for validation (used when validation is enabled)\r\n */\r\n async get<T>(\r\n path: string,\r\n params?: Record<string, unknown>,\r\n schema?: z.ZodType<T>\r\n ): Promise<T> {\r\n const url = new URL(`${this.baseUrl}${path}`);\r\n\r\n if (params) {\r\n for (const [key, value] of Object.entries(params)) {\r\n if (value !== undefined && value !== null) {\r\n // Convert Date objects to Unix milliseconds\r\n if (value instanceof Date) {\r\n url.searchParams.set(key, String(value.getTime()));\r\n } else {\r\n url.searchParams.set(key, String(value));\r\n }\r\n }\r\n }\r\n }\r\n\r\n const controller = new AbortController();\r\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\r\n\r\n try {\r\n const response = await fetch(url.toString(), {\r\n method: 'GET',\r\n headers: {\r\n 'X-API-Key': this.apiKey,\r\n 'Content-Type': 'application/json',\r\n },\r\n signal: controller.signal,\r\n });\r\n\r\n clearTimeout(timeoutId);\r\n\r\n const rawData = await response.json();\r\n // Transform snake_case keys to camelCase for JavaScript conventions\r\n const data = transformKeys(rawData) as Record<string, unknown>;\r\n\r\n if (!response.ok) {\r\n const error = data as unknown as ApiError;\r\n const apiResponse = data as unknown as ApiResponse<unknown>;\r\n throw new OxArchiveError(\r\n error.error || `Request failed with status ${response.status}`,\r\n response.status,\r\n apiResponse.meta?.requestId\r\n );\r\n }\r\n\r\n // Validate response if validation is enabled and schema is provided\r\n if (this.validate && schema) {\r\n const result = schema.safeParse(data);\r\n if (!result.success) {\r\n const apiResponse = data as unknown as ApiResponse<unknown>;\r\n throw new OxArchiveError(\r\n `Response validation failed: ${result.error.message}`,\r\n 422,\r\n apiResponse.meta?.requestId\r\n );\r\n }\r\n return result.data;\r\n }\r\n\r\n return data as T;\r\n } catch (error) {\r\n clearTimeout(timeoutId);\r\n\r\n if (error instanceof OxArchiveError) {\r\n throw error;\r\n }\r\n\r\n if (error instanceof Error && error.name === 'AbortError') {\r\n throw new OxArchiveError(`Request timeout after ${this.timeout}ms`, 408);\r\n }\r\n\r\n throw new OxArchiveError(\r\n error instanceof Error ? error.message : 'Unknown error',\r\n 500\r\n );\r\n }\r\n }\r\n}\r\n","/**\r\n * Zod schemas for runtime validation of API responses\r\n *\r\n * @example\r\n * ```typescript\r\n * import { OrderBookSchema, TradeSchema } from '@0xarchive/sdk';\r\n *\r\n * // Validate data manually\r\n * const result = OrderBookSchema.safeParse(data);\r\n * if (result.success) {\r\n * console.log(result.data.midPrice);\r\n * } else {\r\n * console.error(result.error);\r\n * }\r\n * ```\r\n */\r\n\r\nimport { z } from 'zod';\r\n\r\n// =============================================================================\r\n// Base Schemas\r\n// =============================================================================\r\n\r\nexport const ApiMetaSchema = z.object({\r\n count: z.number(),\r\n nextCursor: z.string().optional(),\r\n requestId: z.string(),\r\n});\r\n\r\nexport const ApiResponseSchema = <T extends z.ZodTypeAny>(dataSchema: T) =>\r\n z.object({\r\n success: z.boolean(),\r\n data: dataSchema,\r\n meta: ApiMetaSchema,\r\n });\r\n\r\n// =============================================================================\r\n// Order Book Schemas\r\n// =============================================================================\r\n\r\nexport const PriceLevelSchema = z.object({\r\n px: z.string(),\r\n sz: z.string(),\r\n n: z.number(),\r\n});\r\n\r\nexport const OrderBookSchema = z.object({\r\n coin: z.string(),\r\n timestamp: z.string(),\r\n bids: z.array(PriceLevelSchema),\r\n asks: z.array(PriceLevelSchema),\r\n midPrice: z.string().optional(),\r\n spread: z.string().optional(),\r\n spreadBps: z.string().optional(),\r\n});\r\n\r\n// =============================================================================\r\n// Trade/Fill Schemas\r\n// =============================================================================\r\n\r\nexport const TradeSideSchema = z.enum(['A', 'B']);\r\n\r\n// Direction can include 'Open Long', 'Close Short', 'Long > Short', etc.\r\nexport const TradeDirectionSchema = z.string();\r\n\r\nexport const TradeSchema = z.object({\r\n coin: z.string(),\r\n side: TradeSideSchema,\r\n price: z.string(),\r\n size: z.string(),\r\n timestamp: z.string(),\r\n txHash: z.string().optional(),\r\n tradeId: z.number().optional(),\r\n orderId: z.number().optional(),\r\n crossed: z.boolean().optional(),\r\n fee: z.string().optional(),\r\n feeToken: z.string().optional(),\r\n closedPnl: z.string().optional(),\r\n direction: TradeDirectionSchema.optional(),\r\n startPosition: z.string().optional(),\r\n userAddress: z.string().optional(),\r\n makerAddress: z.string().optional(),\r\n takerAddress: z.string().optional(),\r\n});\r\n\r\n// =============================================================================\r\n// Instrument Schemas\r\n// =============================================================================\r\n\r\nexport const InstrumentTypeSchema = z.enum(['perp', 'spot']);\r\n\r\nexport const InstrumentSchema = z.object({\r\n name: z.string(),\r\n szDecimals: z.number(),\r\n maxLeverage: z.number().optional(),\r\n onlyIsolated: z.boolean().optional(),\r\n instrumentType: InstrumentTypeSchema.optional(),\r\n isActive: z.boolean(),\r\n});\r\n\r\n// =============================================================================\r\n// Funding Schemas\r\n// =============================================================================\r\n\r\nexport const FundingRateSchema = z.object({\r\n coin: z.string(),\r\n timestamp: z.string(),\r\n fundingRate: z.string(),\r\n premium: z.string().optional(),\r\n});\r\n\r\n// =============================================================================\r\n// Open Interest Schemas\r\n// =============================================================================\r\n\r\nexport const OpenInterestSchema = z.object({\r\n coin: z.string(),\r\n timestamp: z.string(),\r\n openInterest: z.string(),\r\n markPrice: z.string().optional(),\r\n oraclePrice: z.string().optional(),\r\n dayNtlVolume: z.string().optional(),\r\n prevDayPrice: z.string().optional(),\r\n midPrice: z.string().optional(),\r\n impactBidPrice: z.string().optional(),\r\n impactAskPrice: z.string().optional(),\r\n});\r\n\r\n// =============================================================================\r\n// Liquidation Schemas\r\n// =============================================================================\r\n\r\nexport const LiquidationSideSchema = z.enum(['B', 'S']);\r\n\r\nexport const LiquidationSchema = z.object({\r\n coin: z.string(),\r\n timestamp: z.string(),\r\n liquidatedUser: z.string(),\r\n liquidatorUser: z.string(),\r\n price: z.string(),\r\n size: z.string(),\r\n side: LiquidationSideSchema,\r\n markPrice: z.string().optional(),\r\n closedPnl: z.string().optional(),\r\n direction: z.string().optional(),\r\n tradeId: z.number().optional(),\r\n txHash: z.string().optional(),\r\n});\r\n\r\n// =============================================================================\r\n// Candle Schemas\r\n// =============================================================================\r\n\r\nexport const CandleIntervalSchema = z.enum(['1m', '5m', '15m', '30m', '1h', '4h', '1d', '1w']);\r\n\r\nexport const CandleSchema = z.object({\r\n timestamp: z.string(),\r\n open: z.number(),\r\n high: z.number(),\r\n low: z.number(),\r\n close: z.number(),\r\n volume: z.number(),\r\n quoteVolume: z.number().optional(),\r\n tradeCount: z.number().optional(),\r\n});\r\n\r\n// =============================================================================\r\n// WebSocket Message Schemas\r\n// =============================================================================\r\n\r\nexport const WsChannelSchema = z.enum([\r\n 'orderbook', 'trades', 'candles', 'liquidations', 'ticker', 'all_tickers',\r\n 'open_interest', 'funding',\r\n 'lighter_orderbook', 'lighter_trades', 'lighter_candles',\r\n 'lighter_open_interest', 'lighter_funding',\r\n 'hip3_orderbook', 'hip3_trades', 'hip3_candles',\r\n 'hip3_open_interest', 'hip3_funding',\r\n]);\r\n\r\nexport const WsConnectionStateSchema = z.enum(['connecting', 'connected', 'disconnected', 'reconnecting']);\r\n\r\n// Server -> Client messages\r\nexport const WsSubscribedSchema = z.object({\r\n type: z.literal('subscribed'),\r\n channel: WsChannelSchema,\r\n coin: z.string().optional(),\r\n});\r\n\r\nexport const WsUnsubscribedSchema = z.object({\r\n type: z.literal('unsubscribed'),\r\n channel: WsChannelSchema,\r\n coin: z.string().optional(),\r\n});\r\n\r\nexport const WsPongSchema = z.object({\r\n type: z.literal('pong'),\r\n});\r\n\r\nexport const WsErrorSchema = z.object({\r\n type: z.literal('error'),\r\n message: z.string(),\r\n});\r\n\r\nexport const WsDataSchema = z.object({\r\n type: z.literal('data'),\r\n channel: WsChannelSchema,\r\n coin: z.string(),\r\n data: z.unknown(),\r\n});\r\n\r\n// Replay messages\r\nexport const WsReplayStartedSchema = z.object({\r\n type: z.literal('replay_started'),\r\n channel: WsChannelSchema,\r\n coin: z.string(),\r\n start: z.number(),\r\n end: z.number(),\r\n speed: z.number(),\r\n});\r\n\r\nexport const WsReplayPausedSchema = z.object({\r\n type: z.literal('replay_paused'),\r\n current_timestamp: z.number(),\r\n});\r\n\r\nexport const WsReplayResumedSchema = z.object({\r\n type: z.literal('replay_resumed'),\r\n current_timestamp: z.number(),\r\n});\r\n\r\nexport const WsReplayCompletedSchema = z.object({\r\n type: z.literal('replay_completed'),\r\n channel: WsChannelSchema,\r\n coin: z.string(),\r\n snapshots_sent: z.number(),\r\n});\r\n\r\nexport const WsReplayStoppedSchema = z.object({\r\n type: z.literal('replay_stopped'),\r\n});\r\n\r\nexport const WsHistoricalDataSchema = z.object({\r\n type: z.literal('historical_data'),\r\n channel: WsChannelSchema,\r\n coin: z.string(),\r\n timestamp: z.number(),\r\n data: z.unknown(),\r\n});\r\n\r\nexport const WsReplaySnapshotSchema = z.object({\r\n type: z.literal('replay_snapshot'),\r\n channel: WsChannelSchema,\r\n coin: z.string(),\r\n timestamp: z.number(),\r\n data: z.unknown(),\r\n});\r\n\r\n// Stream messages\r\nexport const WsStreamStartedSchema = z.object({\r\n type: z.literal('stream_started'),\r\n channel: WsChannelSchema,\r\n coin: z.string(),\r\n start: z.number(),\r\n end: z.number(),\r\n});\r\n\r\nexport const WsStreamProgressSchema = z.object({\r\n type: z.literal('stream_progress'),\r\n snapshots_sent: z.number(),\r\n});\r\n\r\nexport const TimestampedRecordSchema = z.object({\r\n timestamp: z.number(),\r\n data: z.unknown(),\r\n});\r\n\r\nexport const WsHistoricalBatchSchema = z.object({\r\n type: z.literal('historical_batch'),\r\n channel: WsChannelSchema,\r\n coin: z.string(),\r\n data: z.array(TimestampedRecordSchema),\r\n});\r\n\r\nexport const WsStreamCompletedSchema = z.object({\r\n type: z.literal('stream_completed'),\r\n channel: WsChannelSchema,\r\n coin: z.string(),\r\n snapshots_sent: z.number(),\r\n});\r\n\r\nexport const WsStreamStoppedSchema = z.object({\r\n type: z.literal('stream_stopped'),\r\n snapshots_sent: z.number(),\r\n});\r\n\r\n// Union of all server messages\r\nexport const WsServerMessageSchema = z.discriminatedUnion('type', [\r\n WsSubscribedSchema,\r\n WsUnsubscribedSchema,\r\n WsPongSchema,\r\n WsErrorSchema,\r\n WsDataSchema,\r\n WsReplayStartedSchema,\r\n WsReplayPausedSchema,\r\n WsReplayResumedSchema,\r\n WsReplayCompletedSchema,\r\n WsReplayStoppedSchema,\r\n WsReplaySnapshotSchema,\r\n WsHistoricalDataSchema,\r\n WsStreamStartedSchema,\r\n WsStreamProgressSchema,\r\n WsHistoricalBatchSchema,\r\n WsStreamCompletedSchema,\r\n WsStreamStoppedSchema,\r\n]);\r\n\r\n// =============================================================================\r\n// API Response Schemas (pre-built for common endpoints)\r\n// =============================================================================\r\n\r\nexport const OrderBookResponseSchema = ApiResponseSchema(OrderBookSchema);\r\nexport const OrderBookArrayResponseSchema = ApiResponseSchema(z.array(OrderBookSchema));\r\nexport const TradeArrayResponseSchema = ApiResponseSchema(z.array(TradeSchema));\r\nexport const InstrumentResponseSchema = ApiResponseSchema(InstrumentSchema);\r\nexport const InstrumentArrayResponseSchema = ApiResponseSchema(z.array(InstrumentSchema));\r\nexport const FundingRateResponseSchema = ApiResponseSchema(FundingRateSchema);\r\nexport const FundingRateArrayResponseSchema = ApiResponseSchema(z.array(FundingRateSchema));\r\nexport const OpenInterestResponseSchema = ApiResponseSchema(OpenInterestSchema);\r\nexport const OpenInterestArrayResponseSchema = ApiResponseSchema(z.array(OpenInterestSchema));\r\nexport const CandleArrayResponseSchema = ApiResponseSchema(z.array(CandleSchema));\r\nexport const LiquidationArrayResponseSchema = ApiResponseSchema(z.array(LiquidationSchema));\r\n\r\n// =============================================================================\r\n// Liquidation Volume Schemas\r\n// =============================================================================\r\n\r\nexport const LiquidationVolumeSchema = z.object({\r\n coin: z.string(),\r\n timestamp: z.string(),\r\n totalUsd: z.number(),\r\n longUsd: z.number(),\r\n shortUsd: z.number(),\r\n count: z.number(),\r\n longCount: z.number(),\r\n shortCount: z.number(),\r\n});\r\n\r\nexport const LiquidationVolumeArrayResponseSchema = z.object({\r\n success: z.boolean().optional(),\r\n data: z.array(LiquidationVolumeSchema),\r\n meta: ApiMetaSchema.optional(),\r\n});\r\n\r\n// =============================================================================\r\n// Coin Freshness Schemas\r\n// =============================================================================\r\n\r\nexport const DataTypeFreshnessInfoSchema = z.object({\r\n lastUpdated: z.string().nullable().optional(),\r\n lagMs: z.number().nullable().optional(),\r\n});\r\n\r\nexport const CoinFreshnessSchema = z.object({\r\n coin: z.string(),\r\n exchange: z.string(),\r\n measuredAt: z.string(),\r\n orderbook: DataTypeFreshnessInfoSchema,\r\n trades: DataTypeFreshnessInfoSchema,\r\n funding: DataTypeFreshnessInfoSchema,\r\n openInterest: DataTypeFreshnessInfoSchema,\r\n liquidations: DataTypeFreshnessInfoSchema.optional(),\r\n});\r\n\r\nexport const CoinFreshnessResponseSchema = z.object({\r\n success: z.boolean().optional(),\r\n data: CoinFreshnessSchema,\r\n meta: ApiMetaSchema.optional(),\r\n});\r\n\r\n// =============================================================================\r\n// Coin Summary Schemas\r\n// =============================================================================\r\n\r\nexport const CoinSummarySchema = z.object({\r\n coin: z.string(),\r\n timestamp: z.string(),\r\n markPrice: z.string().nullable().optional(),\r\n oraclePrice: z.string().nullable().optional(),\r\n midPrice: z.string().nullable().optional(),\r\n fundingRate: z.string().nullable().optional(),\r\n premium: z.string().nullable().optional(),\r\n openInterest: z.string().nullable().optional(),\r\n volume24h: z.string().nullable().optional(),\r\n liquidationVolume24h: z.number().nullable().optional(),\r\n longLiquidationVolume24h: z.number().nullable().optional(),\r\n shortLiquidationVolume24h: z.number().nullable().optional(),\r\n});\r\n\r\nexport const CoinSummaryResponseSchema = z.object({\r\n success: z.boolean().optional(),\r\n data: CoinSummarySchema,\r\n meta: ApiMetaSchema.optional(),\r\n});\r\n\r\n// =============================================================================\r\n// Price Snapshot Schemas\r\n// =============================================================================\r\n\r\nexport const PriceSnapshotSchema = z.object({\r\n timestamp: z.string(),\r\n markPrice: z.string().nullable().optional(),\r\n oraclePrice: z.string().nullable().optional(),\r\n midPrice: z.string().nullable().optional(),\r\n});\r\n\r\nexport const PriceSnapshotArrayResponseSchema = z.object({\r\n success: z.boolean().optional(),\r\n data: z.array(PriceSnapshotSchema),\r\n meta: ApiMetaSchema.optional(),\r\n});\r\n\r\n// =============================================================================\r\n// Type exports (inferred from schemas)\r\n// =============================================================================\r\n\r\nexport type ValidatedApiMeta = z.infer<typeof ApiMetaSchema>;\r\nexport type ValidatedPriceLevel = z.infer<typeof PriceLevelSchema>;\r\nexport type ValidatedOrderBook = z.infer<typeof OrderBookSchema>;\r\nexport type ValidatedTrade = z.infer<typeof TradeSchema>;\r\nexport type ValidatedInstrument = z.infer<typeof InstrumentSchema>;\r\nexport type ValidatedFundingRate = z.infer<typeof FundingRateSchema>;\r\nexport type ValidatedOpenInterest = z.infer<typeof OpenInterestSchema>;\r\nexport type ValidatedCandle = z.infer<typeof CandleSchema>;\r\nexport type ValidatedLiquidation = z.infer<typeof LiquidationSchema>;\r\nexport type ValidatedWsServerMessage = z.infer<typeof WsServerMessageSchema>;\r\n","/**\r\n * Orderbook Reconstructor for tick-level delta data.\r\n *\r\n * Efficiently reconstructs full orderbook state from checkpoint + deltas.\r\n * All reconstruction happens client-side for optimal server performance.\r\n *\r\n * @example\r\n * ```typescript\r\n * // Get raw tick data\r\n * const tickData = await client.lighter.orderbook.historyTick('BTC', { start, end });\r\n *\r\n * // Reconstruct to get snapshots at each delta\r\n * const reconstructor = new OrderBookReconstructor();\r\n * const snapshots = reconstructor.reconstructAll(tickData.checkpoint, tickData.deltas);\r\n *\r\n * // Or iterate efficiently (memory-friendly for large datasets)\r\n * for (const snapshot of reconstructor.iterate(tickData.checkpoint, tickData.deltas)) {\r\n * console.log(snapshot.timestamp, snapshot.bids[0], snapshot.asks[0]);\r\n * }\r\n * ```\r\n */\r\n\r\nimport type { OrderBook, PriceLevel, OrderbookDelta } from './types';\r\n\r\n/**\r\n * Price level stored internally with numeric values for efficient computation\r\n */\r\ninterface InternalLevel {\r\n price: number;\r\n size: number;\r\n orders: number;\r\n}\r\n\r\n/**\r\n * Reconstructed orderbook snapshot with timestamp\r\n */\r\nexport interface ReconstructedOrderBook extends OrderBook {\r\n /** Sequence number of the last applied delta */\r\n sequence?: number;\r\n}\r\n\r\n/**\r\n * Raw tick data from the API (checkpoint + deltas)\r\n */\r\nexport interface TickData {\r\n /** Initial orderbook state */\r\n checkpoint: OrderBook;\r\n /** Incremental changes to apply */\r\n deltas: OrderbookDelta[];\r\n}\r\n\r\n/**\r\n * Options for reconstruction\r\n */\r\nexport interface ReconstructOptions {\r\n /** Maximum depth (price levels) to include in output. Default: all levels */\r\n depth?: number;\r\n /** If true, yield a snapshot after every delta. If false, only return final state. Default: true */\r\n emitAll?: boolean;\r\n}\r\n\r\n/**\r\n * Orderbook Reconstructor\r\n *\r\n * Maintains orderbook state and efficiently applies delta updates.\r\n * Uses sorted arrays with binary search for O(log n) insertions.\r\n *\r\n * Thread-safe for single-threaded JavaScript; for worker threads,\r\n * create a separate instance per thread.\r\n */\r\nexport class OrderBookReconstructor {\r\n private bids: Map<number, InternalLevel> = new Map();\r\n private asks: Map<number, InternalLevel> = new Map();\r\n private coin: string = '';\r\n private lastTimestamp: string = '';\r\n private lastSequence: number = 0;\r\n\r\n /**\r\n * Initialize or reset the reconstructor with a checkpoint\r\n */\r\n initialize(checkpoint: OrderBook): void {\r\n this.bids.clear();\r\n this.asks.clear();\r\n this.coin = checkpoint.coin;\r\n this.lastTimestamp = checkpoint.timestamp;\r\n this.lastSequence = 0;\r\n\r\n // Parse checkpoint bids\r\n for (const level of checkpoint.bids) {\r\n const price = parseFloat(level.px);\r\n this.bids.set(price, {\r\n price,\r\n size: parseFloat(level.sz),\r\n orders: level.n,\r\n });\r\n }\r\n\r\n // Parse checkpoint asks\r\n for (const level of checkpoint.asks) {\r\n const price = parseFloat(level.px);\r\n this.asks.set(price, {\r\n price,\r\n size: parseFloat(level.sz),\r\n orders: level.n,\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Apply a single delta to the current state\r\n */\r\n applyDelta(delta: OrderbookDelta): void {\r\n const book = delta.side === 'bid' ? this.bids : this.asks;\r\n\r\n if (delta.size === 0) {\r\n // Remove level\r\n book.delete(delta.price);\r\n } else {\r\n // Insert or update level\r\n book.set(delta.price, {\r\n price: delta.price,\r\n size: delta.size,\r\n orders: 1, // Deltas don't include order count, assume 1\r\n });\r\n }\r\n\r\n this.lastTimestamp = new Date(delta.timestamp).toISOString();\r\n this.lastSequence = delta.sequence;\r\n }\r\n\r\n /**\r\n * Get the current orderbook state as a snapshot\r\n */\r\n getSnapshot(depth?: number): ReconstructedOrderBook {\r\n // Sort bids descending (best bid first)\r\n const sortedBids = Array.from(this.bids.values())\r\n .sort((a, b) => b.price - a.price);\r\n\r\n // Sort asks ascending (best ask first)\r\n const sortedAsks = Array.from(this.asks.values())\r\n .sort((a, b) => a.price - b.price);\r\n\r\n // Apply depth limit\r\n const bidsOutput = (depth ? sortedBids.slice(0, depth) : sortedBids)\r\n .map(this.toLevel);\r\n const asksOutput = (depth ? sortedAsks.slice(0, depth) : sortedAsks)\r\n .map(this.toLevel);\r\n\r\n // Calculate mid price and spread\r\n const bestBid = sortedBids[0]?.price;\r\n const bestAsk = sortedAsks[0]?.price;\r\n const midPrice = bestBid && bestAsk ? (bestBid + bestAsk) / 2 : undefined;\r\n const spread = bestBid && bestAsk ? bestAsk - bestBid : undefined;\r\n const spreadBps = midPrice && spread ? (spread / midPrice) * 10000 : undefined;\r\n\r\n return {\r\n coin: this.coin,\r\n timestamp: this.lastTimestamp,\r\n bids: bidsOutput,\r\n asks: asksOutput,\r\n midPrice: midPrice?.toString(),\r\n spread: spread?.toString(),\r\n spreadBps: spreadBps?.toFixed(2),\r\n sequence: this.lastSequence,\r\n };\r\n }\r\n\r\n /**\r\n * Convert internal level to API format\r\n */\r\n private toLevel = (level: InternalLevel): PriceLevel => ({\r\n px: level.price.toString(),\r\n sz: level.size.toString(),\r\n n: level.orders,\r\n });\r\n\r\n /**\r\n * Reconstruct all orderbook states from checkpoint + deltas.\r\n * Returns an array of snapshots, one after each delta.\r\n *\r\n * For large datasets, prefer `iterate()` to avoid memory issues.\r\n *\r\n * @param checkpoint - Initial orderbook state\r\n * @param deltas - Array of delta updates\r\n * @param options - Reconstruction options\r\n * @returns Array of reconstructed orderbook snapshots\r\n */\r\n reconstructAll(\r\n checkpoint: OrderBook,\r\n deltas: OrderbookDelta[],\r\n options: ReconstructOptions = {}\r\n ): ReconstructedOrderBook[] {\r\n const { depth, emitAll = true } = options;\r\n const snapshots: ReconstructedOrderBook[] = [];\r\n\r\n this.initialize(checkpoint);\r\n\r\n // Sort deltas by sequence to ensure correct order\r\n const sortedDeltas = [...deltas].sort((a, b) => a.sequence - b.sequence);\r\n\r\n if (emitAll) {\r\n // Emit initial state\r\n snapshots.push(this.getSnapshot(depth));\r\n }\r\n\r\n for (const delta of sortedDeltas) {\r\n this.applyDelta(delta);\r\n if (emitAll) {\r\n snapshots.push(this.getSnapshot(depth));\r\n }\r\n }\r\n\r\n if (!emitAll) {\r\n // Only return final state\r\n snapshots.push(this.getSnapshot(depth));\r\n }\r\n\r\n return snapshots;\r\n }\r\n\r\n /**\r\n * Iterate over reconstructed orderbook states (memory-efficient).\r\n * Yields a snapshot after each delta is applied.\r\n *\r\n * @param checkpoint - Initial orderbook state\r\n * @param deltas - Array of delta updates\r\n * @param options - Reconstruction options\r\n * @yields Reconstructed orderbook snapshots\r\n */\r\n *iterate(\r\n checkpoint: OrderBook,\r\n deltas: OrderbookDelta[],\r\n options: ReconstructOptions = {}\r\n ): Generator<ReconstructedOrderBook> {\r\n const { depth } = options;\r\n\r\n this.initialize(checkpoint);\r\n\r\n // Yield initial state\r\n yield this.getSnapshot(depth);\r\n\r\n // Sort deltas by sequence\r\n const sortedDeltas = [...deltas].sort((a, b) => a.sequence - b.sequence);\r\n\r\n for (const delta of sortedDeltas) {\r\n this.applyDelta(delta);\r\n yield this.getSnapshot(depth);\r\n }\r\n }\r\n\r\n /**\r\n * Get the final reconstructed state without intermediate snapshots.\r\n * Most efficient when you only need the end result.\r\n *\r\n * @param checkpoint - Initial orderbook state\r\n * @param deltas - Array of delta updates\r\n * @param depth - Maximum price levels to include\r\n * @returns Final orderbook state after all deltas applied\r\n */\r\n reconstructFinal(\r\n checkpoint: OrderBook,\r\n deltas: OrderbookDelta[],\r\n depth?: number\r\n ): ReconstructedOrderBook {\r\n this.initialize(checkpoint);\r\n\r\n // Sort and apply all deltas\r\n const sortedDeltas = [...deltas].sort((a, b) => a.sequence - b.sequence);\r\n for (const delta of sortedDeltas) {\r\n this.applyDelta(delta);\r\n }\r\n\r\n return this.getSnapshot(depth);\r\n }\r\n\r\n /**\r\n * Check for sequence gaps in deltas.\r\n * Returns array of missing sequence numbers.\r\n *\r\n * @param deltas - Array of delta updates\r\n * @returns Array of [expectedSeq, actualSeq] tuples where gaps exist\r\n */\r\n static detectGaps(deltas: OrderbookDelta[]): Array<[number, number]> {\r\n if (deltas.length < 2) return [];\r\n\r\n const sorted = [...deltas].sort((a, b) => a.sequence - b.sequence);\r\n const gaps: Array<[number, number]> = [];\r\n\r\n for (let i = 1; i < sorted.length; i++) {\r\n const expected = sorted[i - 1].sequence + 1;\r\n const actual = sorted[i].sequence;\r\n if (actual !== expected) {\r\n gaps.push([expected, actual]);\r\n }\r\n }\r\n\r\n return gaps;\r\n }\r\n}\r\n\r\n/**\r\n * Convenience function for one-shot reconstruction.\r\n * Creates a new reconstructor, processes data, and returns snapshots.\r\n *\r\n * @param tickData - Checkpoint and deltas from API\r\n * @param options - Reconstruction options\r\n * @returns Array of reconstructed orderbook snapshots\r\n */\r\nexport function reconstructOrderBook(\r\n tickData: TickData,\r\n options: ReconstructOptions = {}\r\n): ReconstructedOrderBook[] {\r\n const reconstructor = new OrderBookReconstructor();\r\n return reconstructor.reconstructAll(tickData.checkpoint, tickData.deltas, options);\r\n}\r\n\r\n/**\r\n * Convenience function to get final orderbook state.\r\n *\r\n * @param tickData - Checkpoint and deltas from API\r\n * @param depth - Maximum price levels\r\n * @returns Final orderbook state\r\n */\r\nexport function reconstructFinal(\r\n tickData: TickData,\r\n depth?: number\r\n): ReconstructedOrderBook {\r\n const reconstructor = new OrderBookReconstructor();\r\n return reconstructor.reconstructFinal(tickData.checkpoint, tickData.deltas, depth);\r\n}\r\n","import type { HttpClient } from '../http';\r\nimport type {\r\n ApiResponse,\r\n CursorResponse,\r\n OrderBook,\r\n GetOrderBookParams,\r\n OrderBookHistoryParams,\r\n OrderbookDelta,\r\n} from '../types';\r\nimport { OrderBookResponseSchema, OrderBookArrayResponseSchema } from '../schemas';\r\nimport {\r\n OrderBookReconstructor,\r\n type TickData,\r\n type ReconstructedOrderBook,\r\n type ReconstructOptions,\r\n} from '../orderbook-reconstructor';\r\n\r\n/**\r\n * Parameters for tick-level orderbook history (Enterprise tier only)\r\n */\r\nexport interface TickHistoryParams {\r\n /** Start timestamp (Unix ms or ISO string) - REQUIRED */\r\n start: number | string;\r\n /** End timestamp (Unix ms or ISO string) - REQUIRED */\r\n end: number | string;\r\n /** Number of price levels in checkpoint (default: all) */\r\n depth?: number;\r\n}\r\n\r\n/**\r\n * Order book API resource\r\n *\r\n * @example\r\n * ```typescript\r\n * // Get current order book\r\n * const orderbook = await client.orderbook.get('BTC');\r\n *\r\n * // Get order book at specific timestamp\r\n * const historical = await client.orderbook.get('ETH', {\r\n * timestamp: 1704067200000,\r\n * depth: 10\r\n * });\r\n *\r\n * // Get order book history\r\n * const history = await client.orderbook.history('BTC', {\r\n * start: Date.now() - 86400000,\r\n * end: Date.now(),\r\n * limit: 100\r\n * });\r\n *\r\n * // Enterprise: Get tick-level data with reconstruction\r\n * const snapshots = await client.lighter.orderbook.historyReconstructed('BTC', {\r\n * start: Date.now() - 3600000,\r\n * end: Date.now()\r\n * });\r\n *\r\n * // Enterprise: Get raw tick data for custom reconstruction\r\n * const tickData = await client.lighter.orderbook.historyTick('BTC', {\r\n * start: Date.now() - 3600000,\r\n * end: Date.now()\r\n * });\r\n * ```\r\n */\r\nexport class OrderBookResource {\r\n constructor(\r\n private http: HttpClient,\r\n private basePath: string = '/v1',\r\n private coinTransform: (coin: string) => string = (c) => c.toUpperCase()\r\n ) {}\r\n\r\n /**\r\n * Get order book snapshot for a coin\r\n *\r\n * @param coin - The coin symbol (e.g., 'BTC', 'ETH')\r\n * @param params - Optional parameters\r\n * @returns Order book snapshot\r\n */\r\n async get(coin: string, params?: GetOrderBookParams): Promise<OrderBook> {\r\n const response = await this.http.get<ApiResponse<OrderBook>>(\r\n `${this.basePath}/orderbook/${this.coinTransform(coin)}`,\r\n params as Record<string, unknown>,\r\n this.http.validationEnabled ? OrderBookResponseSchema : undefined\r\n );\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Get historical order book snapshots with cursor-based pagination\r\n *\r\n * @param coin - The coin symbol (e.g., 'BTC', 'ETH')\r\n * @param params - Time range and cursor pagination parameters (start and end are required)\r\n * @returns CursorResponse with order book snapshots and nextCursor for pagination\r\n *\r\n * @example\r\n * ```typescript\r\n * // First page\r\n * let result = await client.orderbook.history('BTC', {\r\n * start: Date.now() - 86400000,\r\n * end: Date.now(),\r\n * limit: 1000\r\n * });\r\n *\r\n * // Subsequent pages\r\n * while (result.nextCursor) {\r\n * result = await client.orderbook.history('BTC', {\r\n * start: Date.now() - 86400000,\r\n * end: Date.now(),\r\n * cursor: result.nextCursor,\r\n * limit: 1000\r\n * });\r\n * }\r\n * ```\r\n */\r\n async history(\r\n coin: string,\r\n params: OrderBookHistoryParams\r\n ): Promise<CursorResponse<OrderBook[]>> {\r\n const response = await this.http.get<ApiResponse<OrderBook[]>>(\r\n `${this.basePath}/orderbook/${this.coinTransform(coin)}/history`,\r\n params as unknown as Record<string, unknown>,\r\n this.http.validationEnabled ? OrderBookArrayResponseSchema : undefined\r\n );\r\n return {\r\n data: response.data,\r\n nextCursor: response.meta.nextCursor,\r\n };\r\n }\r\n\r\n /**\r\n * Get raw tick-level orderbook data (Enterprise tier only).\r\n *\r\n * Returns a checkpoint (full orderbook state) and array of deltas.\r\n * Use this when you want to implement custom reconstruction logic\r\n * (e.g., in Rust for maximum performance).\r\n *\r\n * For automatic reconstruction, use `historyReconstructed()` instead.\r\n *\r\n * @param coin - The coin symbol (e.g., 'BTC', 'ETH')\r\n * @param params - Time range parameters\r\n * @returns Tick data with checkpoint and deltas\r\n *\r\n * @example\r\n * ```typescript\r\n * const tickData = await client.lighter.orderbook.historyTick('BTC', {\r\n * start: Date.now() - 3600000,\r\n * end: Date.now()\r\n * });\r\n *\r\n * console.log('Checkpoint:', tickData.checkpoint);\r\n * console.log('Deltas:', tickData.deltas.length);\r\n *\r\n * // Implement your own reconstruction...\r\n * for (const delta of tickData.deltas) {\r\n * // delta: { timestamp, side, price, size, sequence }\r\n * }\r\n * ```\r\n */\r\n async historyTick(\r\n coin: string,\r\n params: TickHistoryParams\r\n ): Promise<TickData> {\r\n const response = await this.http.get<{\r\n success: boolean;\r\n data?: {\r\n checkpoint?: OrderBook;\r\n deltas?: OrderbookDelta[];\r\n };\r\n granularity?: string;\r\n error?: string;\r\n message?: string;\r\n }>(\r\n `${this.basePath}/orderbook/${this.coinTransform(coin)}/history`,\r\n {\r\n ...params,\r\n granularity: 'tick',\r\n } as Record<string, unknown>\r\n );\r\n\r\n // Check if tick-level data was returned (nested inside data wrapper)\r\n const tickData = response.data;\r\n if (!tickData?.checkpoint || !tickData?.deltas) {\r\n const errorMsg = response.error || response.message ||\r\n 'Tick-level orderbook data requires Enterprise tier. ' +\r\n 'Upgrade your subscription or use a different granularity.';\r\n throw new Error(errorMsg);\r\n }\r\n\r\n return {\r\n checkpoint: tickData.checkpoint,\r\n deltas: tickData.deltas,\r\n };\r\n }\r\n\r\n /**\r\n * Get reconstructed tick-level orderbook history (Enterprise tier only).\r\n *\r\n * Fetches raw tick data and reconstructs full orderbook state at each delta.\r\n * All reconstruction happens client-side for optimal server performance.\r\n *\r\n * For large time ranges, consider using `historyTick()` with the\r\n * `OrderBookReconstructor.iterate()` method for memory efficiency.\r\n *\r\n * @param coin - The coin symbol (e.g., 'BTC', 'ETH')\r\n * @param params - Time range parameters\r\n * @param options - Reconstruction options\r\n * @returns Array of reconstructed orderbook snapshots\r\n *\r\n * @example\r\n * ```typescript\r\n * // Get all snapshots\r\n * const snapshots = await client.lighter.orderbook.historyReconstructed('BTC', {\r\n * start: Date.now() - 3600000,\r\n * end: Date.now()\r\n * });\r\n *\r\n * for (const ob of snapshots) {\r\n * console.log(ob.timestamp, 'Best bid:', ob.bids[0]?.px, 'Best ask:', ob.asks[0]?.px);\r\n * }\r\n *\r\n * // Get only final state\r\n * const [final] = await client.lighter.orderbook.historyReconstructed('BTC',\r\n * { start, end },\r\n * { emitAll: false }\r\n * );\r\n * ```\r\n */\r\n async historyReconstructed(\r\n coin: string,\r\n params: TickHistoryParams,\r\n options: ReconstructOptions = {}\r\n ): Promise<ReconstructedOrderBook[]> {\r\n const tickData = await this.historyTick(coin, params);\r\n const reconstructor = new OrderBookReconstructor();\r\n return reconstructor.reconstructAll(tickData.checkpoint, tickData.deltas, options);\r\n }\r\n\r\n /**\r\n * Create a reconstructor for streaming tick-level data.\r\n *\r\n * Returns an OrderBookReconstructor instance that you can use\r\n * to process tick data incrementally or with custom logic.\r\n *\r\n * @returns A new OrderBookReconstructor instance\r\n *\r\n * @example\r\n * ```typescript\r\n * const reconstructor = client.lighter.orderbook.createReconstructor();\r\n * const tickData = await client.lighter.orderbook.historyTick('BTC', { start, end });\r\n *\r\n * // Memory-efficient iteration\r\n * for (const snapshot of reconstructor.iterate(tickData.checkpoint, tickData.deltas)) {\r\n * // Process each snapshot\r\n * if (someCondition(snapshot)) break; // Early exit if needed\r\n * }\r\n *\r\n * // Check for gaps\r\n * const gaps = OrderBookReconstructor.detectGaps(tickData.deltas);\r\n * if (gaps.length > 0) {\r\n * console.warn('Sequence gaps detected:', gaps);\r\n * }\r\n * ```\r\n */\r\n createReconstructor(): OrderBookReconstructor {\r\n return new OrderBookReconstructor();\r\n }\r\n\r\n /**\r\n * Iterate over tick-level orderbook history with automatic pagination (Enterprise tier only).\r\n *\r\n * This async generator automatically handles pagination, fetching up to 1,000 deltas\r\n * per API request and yielding reconstructed orderbook snapshots one at a time.\r\n * Memory-efficient for processing large time ranges.\r\n *\r\n * @param coin - The coin symbol (e.g., 'BTC', 'ETH')\r\n * @param params - Time range parameters\r\n * @param depth - Maximum price levels to include in output snapshots\r\n * @yields Reconstructed orderbook snapshots\r\n *\r\n * @example\r\n * ```typescript\r\n * // Process 24 hours of tick data with automatic pagination\r\n * for await (const snapshot of client.lighter.orderbook.iterateTickHistory('BTC', {\r\n * start: Date.now() - 86400000,\r\n * end: Date.now()\r\n * })) {\r\n * console.log(snapshot.timestamp, 'Mid:', snapshot.midPrice);\r\n * if (someCondition) break; // Early exit supported\r\n * }\r\n *\r\n * // Collect all snapshots (caution: may use significant memory for large ranges)\r\n * const allSnapshots: ReconstructedOrderBook[] = [];\r\n * for await (const snapshot of client.lighter.orderbook.iterateTickHistory('BTC', { start, end })) {\r\n * allSnapshots.push(snapshot);\r\n * }\r\n * ```\r\n */\r\n async *iterateTickHistory(\r\n coin: string,\r\n params: TickHistoryParams,\r\n depth?: number\r\n ): AsyncGenerator<ReconstructedOrderBook, void, undefined> {\r\n const startTs = typeof params.start === 'string' ? new Date(params.start).getTime() : params.start;\r\n const endTs = typeof params.end === 'string' ? new Date(params.end).getTime() : params.end;\r\n\r\n let cursor = startTs;\r\n const reconstructor = new OrderBookReconstructor();\r\n const MAX_DELTAS_PER_PAGE = 1000;\r\n let isFirstPage = true;\r\n\r\n while (cursor < endTs) {\r\n const tickData = await this.historyTick(coin, {\r\n start: cursor,\r\n end: endTs,\r\n depth: params.depth,\r\n });\r\n\r\n if (tickData.deltas.length === 0) {\r\n // No deltas - yield checkpoint only on first page if no data\r\n if (isFirstPage) {\r\n reconstructor.initialize(tickData.checkpoint);\r\n yield reconstructor.getSnapshot(depth);\r\n }\r\n break;\r\n }\r\n\r\n // Yield each reconstructed snapshot\r\n // Skip initial checkpoint on subsequent pages to avoid duplicates\r\n let skipFirst = !isFirstPage;\r\n for (const snapshot of reconstructor.iterate(tickData.checkpoint, tickData.deltas, { depth })) {\r\n if (skipFirst) {\r\n skipFirst = false;\r\n continue;\r\n }\r\n yield snapshot;\r\n }\r\n\r\n isFirstPage = false;\r\n\r\n // Move cursor past the last delta\r\n const lastDelta = tickData.deltas[tickData.deltas.length - 1];\r\n cursor = lastDelta.timestamp + 1;\r\n\r\n // If we got fewer than max deltas, we've reached the end\r\n if (tickData.deltas.length < MAX_DELTAS_PER_PAGE) {\r\n break;\r\n }\r\n }\r\n }\r\n}\r\n","import type { HttpClient } from '../http';\r\nimport type { ApiResponse, Trade, GetTradesCursorParams, CursorResponse } from '../types';\r\nimport { TradeArrayResponseSchema } from '../schemas';\r\n\r\n/**\r\n * Trades API resource\r\n *\r\n * @example\r\n * ```typescript\r\n * // Get trade history with cursor-based pagination (recommended)\r\n * let result = await client.hyperliquid.trades.list('BTC', {\r\n * start: Date.now() - 86400000,\r\n * end: Date.now(),\r\n * limit: 1000\r\n * });\r\n *\r\n * // Get all pages\r\n * const allTrades = [...result.data];\r\n * while (result.nextCursor) {\r\n * result = await client.hyperliquid.trades.list('BTC', {\r\n * start: Date.now() - 86400000,\r\n * end: Date.now(),\r\n * cursor: result.nextCursor,\r\n * limit: 1000\r\n * });\r\n * allTrades.push(...result.data);\r\n * }\r\n *\r\n * // Get recent trades (Lighter only - has real-time data)\r\n * const recent = await client.lighter.trades.recent('BTC');\r\n * ```\r\n */\r\nexport class TradesResource {\r\n constructor(\r\n private http: HttpClient,\r\n private basePath: string = '/v1',\r\n private coinTransform: (coin: string) => string = (c) => c.toUpperCase()\r\n ) {}\r\n\r\n /**\r\n * Get trade history for a coin using cursor-based pagination\r\n *\r\n * Uses cursor-based pagination by default, which is more efficient for large datasets.\r\n * Use the `nextCursor` from the response as the `cursor` parameter to get the next page.\r\n *\r\n * @param coin - The coin symbol (e.g., 'BTC', 'ETH')\r\n * @param params - Time range and cursor pagination parameters (start and end are required)\r\n * @returns Object with trades array and nextCursor for pagination\r\n *\r\n * @example\r\n * ```typescript\r\n * // First page\r\n * let result = await client.trades.list('BTC', {\r\n * start: Date.now() - 86400000,\r\n * end: Date.now(),\r\n * limit: 1000\r\n * });\r\n *\r\n * // Subsequent pages\r\n * while (result.nextCursor) {\r\n * result = await client.trades.list('BTC', {\r\n * start: Date.now() - 86400000,\r\n * end: Date.now(),\r\n * cursor: result.nextCursor,\r\n * limit: 1000\r\n * });\r\n * }\r\n * ```\r\n */\r\n async list(coin: string, params: GetTradesCursorParams): Promise<CursorResponse<Trade[]>> {\r\n const response = await this.http.get<ApiResponse<Trade[]>>(\r\n `${this.basePath}/trades/${this.coinTransform(coin)}`,\r\n params as unknown as Record<string, unknown>,\r\n this.http.validationEnabled ? TradeArrayResponseSchema : undefined\r\n );\r\n return {\r\n data: response.data,\r\n nextCursor: response.meta.nextCursor,\r\n };\r\n }\r\n\r\n /**\r\n * Get most recent trades for a coin.\r\n *\r\n * Note: This method is available for Lighter (client.lighter.trades.recent())\r\n * and HIP-3 (client.hyperliquid.hip3.trades.recent()) which have real-time data\r\n * ingestion. Hyperliquid uses hourly backfill so this endpoint is not available\r\n * for Hyperliquid.\r\n *\r\n * @param coin - The coin symbol (e.g., 'BTC', 'ETH')\r\n * @param limit - Number of trades to return (default: 100)\r\n * @returns Array of recent trades\r\n */\r\n async recent(coin: string, limit?: number): Promise<Trade[]> {\r\n const response = await this.http.get<ApiResponse<Trade[]>>(\r\n `${this.basePath}/trades/${this.coinTransform(coin)}/recent`,\r\n { limit },\r\n this.http.validationEnabled ? TradeArrayResponseSchema : undefined\r\n );\r\n return response.data;\r\n }\r\n\r\n}\r\n","import type { HttpClient } from '../http';\r\nimport type { ApiResponse, Hip3Instrument, Instrument, LighterInstrument } from '../types';\r\nimport { InstrumentResponseSchema, InstrumentArrayResponseSchema } from '../schemas';\r\n\r\n/**\r\n * Instruments API resource\r\n *\r\n * @example\r\n * ```typescript\r\n * // List all instruments\r\n * const instruments = await client.instruments.list();\r\n *\r\n * // Get specific instrument\r\n * const btc = await client.instruments.get('BTC');\r\n * ```\r\n */\r\nexport class InstrumentsResource {\r\n constructor(private http: HttpClient, private basePath: string = '/v1') {}\r\n\r\n /**\r\n * List all available trading instruments\r\n *\r\n * @returns Array of instruments\r\n */\r\n async list(): Promise<Instrument[]> {\r\n const response = await this.http.get<ApiResponse<Instrument[]>>(\r\n `${this.basePath}/instruments`,\r\n undefined,\r\n this.http.validationEnabled ? InstrumentArrayResponseSchema : undefined\r\n );\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Get a specific instrument by coin symbol\r\n *\r\n * @param coin - The coin symbol (e.g., 'BTC', 'ETH')\r\n * @returns Instrument details\r\n */\r\n async get(coin: string): Promise<Instrument> {\r\n const response = await this.http.get<ApiResponse<Instrument>>(\r\n `${this.basePath}/instruments/${coin.toUpperCase()}`,\r\n undefined,\r\n this.http.validationEnabled ? InstrumentResponseSchema : undefined\r\n );\r\n return response.data;\r\n }\r\n}\r\n\r\n/**\r\n * Lighter.xyz Instruments API resource\r\n *\r\n * Lighter instruments have a different schema than Hyperliquid with more\r\n * detailed market configuration including fees and minimum amounts.\r\n *\r\n * @example\r\n * ```typescript\r\n * // List all Lighter instruments\r\n * const instruments = await client.lighter.instruments.list();\r\n *\r\n * // Get specific instrument\r\n * const btc = await client.lighter.instruments.get('BTC');\r\n * console.log(`Taker fee: ${btc.takerFee}`);\r\n * ```\r\n */\r\nexport class LighterInstrumentsResource {\r\n constructor(private http: HttpClient, private basePath: string = '/v1/lighter') {}\r\n\r\n /**\r\n * List all available Lighter trading instruments\r\n *\r\n * @returns Array of Lighter instruments with full market configuration\r\n */\r\n async list(): Promise<LighterInstrument[]> {\r\n const response = await this.http.get<ApiResponse<LighterInstrument[]>>(\r\n `${this.basePath}/instruments`\r\n );\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Get a specific Lighter instrument by coin symbol\r\n *\r\n * @param coin - The coin symbol (e.g., 'BTC', 'ETH')\r\n * @returns Lighter instrument details with full market configuration\r\n */\r\n async get(coin: string): Promise<LighterInstrument> {\r\n const response = await this.http.get<ApiResponse<LighterInstrument>>(\r\n `${this.basePath}/instruments/${coin.toUpperCase()}`\r\n );\r\n return response.data;\r\n }\r\n}\r\n\r\n/**\r\n * HIP-3 Builder Perps Instruments API resource\r\n *\r\n * HIP-3 instruments are derived from live market data and include\r\n * mark price, open interest, and mid price context.\r\n *\r\n * @example\r\n * ```typescript\r\n * // List all HIP-3 instruments\r\n * const instruments = await client.hyperliquid.hip3.instruments.list();\r\n *\r\n * // Get specific instrument\r\n * const us500 = await client.hyperliquid.hip3.instruments.get('km:US500');\r\n * console.log(`Mark price: ${us500.markPrice}`);\r\n * ```\r\n */\r\nexport class Hip3InstrumentsResource {\r\n private coinTransform: (c: string) => string;\r\n\r\n constructor(\r\n private http: HttpClient,\r\n private basePath: string = '/v1/hyperliquid/hip3',\r\n coinTransform?: (c: string) => string\r\n ) {\r\n this.coinTransform = coinTransform || ((c) => c);\r\n }\r\n\r\n /**\r\n * List all available HIP-3 instruments with latest market data\r\n *\r\n * @returns Array of HIP-3 instruments\r\n */\r\n async list(): Promise<Hip3Instrument[]> {\r\n const response = await this.http.get<ApiResponse<Hip3Instrument[]>>(\r\n `${this.basePath}/instruments`\r\n );\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Get a specific HIP-3 instrument by coin name\r\n *\r\n * @param coin - The coin name (e.g., 'km:US500', 'xyz:XYZ100'). Case-sensitive.\r\n * @returns HIP-3 instrument details with latest market data\r\n */\r\n async get(coin: string): Promise<Hip3Instrument> {\r\n coin = this.coinTransform(coin);\r\n const response = await this.http.get<ApiResponse<Hip3Instrument>>(\r\n `${this.basePath}/instruments/${coin}`\r\n );\r\n return response.data;\r\n }\r\n}\r\n","import type { HttpClient } from '../http';\r\nimport type { ApiResponse, CursorResponse, FundingRate, FundingHistoryParams } from '../types';\r\nimport { FundingRateResponseSchema, FundingRateArrayResponseSchema } from '../schemas';\r\n\r\n/**\r\n * Funding rates API resource\r\n *\r\n * @example\r\n * ```typescript\r\n * // Get current funding rate\r\n * const current = await client.funding.current('BTC');\r\n *\r\n * // Get funding rate history with cursor-based pagination\r\n * let result = await client.funding.history('ETH', {\r\n * start: Date.now() - 86400000 * 7,\r\n * end: Date.now(),\r\n * limit: 1000\r\n * });\r\n *\r\n * // Get all pages\r\n * const allRates = [...result.data];\r\n * while (result.nextCursor) {\r\n * result = await client.funding.history('ETH', {\r\n * start: Date.now() - 86400000 * 7,\r\n * end: Date.now(),\r\n * cursor: result.nextCursor,\r\n * limit: 1000\r\n * });\r\n * allRates.push(...result.data);\r\n * }\r\n * ```\r\n */\r\nexport class FundingResource {\r\n constructor(\r\n private http: HttpClient,\r\n private basePath: string = '/v1',\r\n private coinTransform: (coin: string) => string = (c) => c.toUpperCase()\r\n ) {}\r\n\r\n /**\r\n * Get funding rate history for a coin with cursor-based pagination\r\n *\r\n * @param coin - The coin symbol (e.g., 'BTC', 'ETH')\r\n * @param params - Time range and cursor pagination parameters (start and end are required)\r\n * @returns CursorResponse with funding rate records and nextCursor for pagination\r\n */\r\n async history(coin: string, params: FundingHistoryParams): Promise<CursorResponse<FundingRate[]>> {\r\n const response = await this.http.get<ApiResponse<FundingRate[]>>(\r\n `${this.basePath}/funding/${this.coinTransform(coin)}`,\r\n params as unknown as Record<string, unknown>,\r\n this.http.validationEnabled ? FundingRateArrayResponseSchema : undefined\r\n );\r\n return {\r\n data: response.data,\r\n nextCursor: response.meta.nextCursor,\r\n };\r\n }\r\n\r\n /**\r\n * Get current funding rate for a coin\r\n *\r\n * @param coin - The coin symbol (e.g., 'BTC', 'ETH')\r\n * @returns Current funding rate\r\n */\r\n async current(coin: string): Promise<FundingRate> {\r\n const response = await this.http.get<ApiResponse<FundingRate>>(\r\n `${this.basePath}/funding/${this.coinTransform(coin)}/current`,\r\n undefined,\r\n this.http.validationEnabled ? FundingRateResponseSchema : undefined\r\n );\r\n return response.data;\r\n }\r\n}\r\n","import type { HttpClient } from '../http';\r\nimport type { ApiResponse, CursorResponse, OpenInterest, OpenInterestHistoryParams } from '../types';\r\nimport { OpenInterestResponseSchema, OpenInterestArrayResponseSchema } from '../schemas';\r\n\r\n/**\r\n * Open interest API resource\r\n *\r\n * @example\r\n * ```typescript\r\n * // Get current open interest\r\n * const current = await client.openInterest.current('BTC');\r\n *\r\n * // Get open interest history with cursor-based pagination\r\n * let result = await client.openInterest.history('ETH', {\r\n * start: Date.now() - 86400000,\r\n * end: Date.now(),\r\n * limit: 1000\r\n * });\r\n *\r\n * // Get all pages\r\n * const allRecords = [...result.data];\r\n * while (result.nextCursor) {\r\n * result = await client.openInterest.history('ETH', {\r\n * start: Date.now() - 86400000,\r\n * end: Date.now(),\r\n * cursor: result.nextCursor,\r\n * limit: 1000\r\n * });\r\n * allRecords.push(...result.data);\r\n * }\r\n * ```\r\n */\r\nexport class OpenInterestResource {\r\n constructor(\r\n private http: HttpClient,\r\n private basePath: string = '/v1',\r\n private coinTransform: (coin: string) => string = (c) => c.toUpperCase()\r\n ) {}\r\n\r\n /**\r\n * Get open interest history for a coin with cursor-based pagination\r\n *\r\n * @param coin - The coin symbol (e.g., 'BTC', 'ETH')\r\n * @param params - Time range and cursor pagination parameters (start and end are required)\r\n * @returns CursorResponse with open interest records and nextCursor for pagination\r\n */\r\n async history(coin: string, params: OpenInterestHistoryParams): Promise<CursorResponse<OpenInterest[]>> {\r\n const response = await this.http.get<ApiResponse<OpenInterest[]>>(\r\n `${this.basePath}/openinterest/${this.coinTransform(coin)}`,\r\n params as unknown as Record<string, unknown>,\r\n this.http.validationEnabled ? OpenInterestArrayResponseSchema : undefined\r\n );\r\n return {\r\n data: response.data,\r\n nextCursor: response.meta.nextCursor,\r\n };\r\n }\r\n\r\n /**\r\n * Get current open interest for a coin\r\n *\r\n * @param coin - The coin symbol (e.g., 'BTC', 'ETH')\r\n * @returns Current open interest\r\n */\r\n async current(coin: string): Promise<OpenInterest> {\r\n const response = await this.http.get<ApiResponse<OpenInterest>>(\r\n `${this.basePath}/openinterest/${this.coinTransform(coin)}/current`,\r\n undefined,\r\n this.http.validationEnabled ? OpenInterestResponseSchema : undefined\r\n );\r\n return response.data;\r\n }\r\n}\r\n","import type { HttpClient } from '../http';\r\nimport type { ApiResponse, Candle, CandleHistoryParams, CursorResponse } from '../types';\r\nimport { CandleArrayResponseSchema } from '../schemas';\r\n\r\n/**\r\n * Candles (OHLCV) API resource\r\n *\r\n * @example\r\n * ```typescript\r\n * // Get candle history with cursor-based pagination\r\n * let result = await client.hyperliquid.candles.history('BTC', {\r\n * start: Date.now() - 86400000,\r\n * end: Date.now(),\r\n * interval: '1h',\r\n * limit: 10000\r\n * });\r\n *\r\n * // Get all pages\r\n * const allCandles = [...result.data];\r\n * while (result.nextCursor) {\r\n * result = await client.hyperliquid.candles.history('BTC', {\r\n * start: Date.now() - 86400000,\r\n * end: Date.now(),\r\n * interval: '1h',\r\n * cursor: result.nextCursor,\r\n * limit: 10000\r\n * });\r\n * allCandles.push(...result.data);\r\n * }\r\n *\r\n * // Iterate through candles\r\n * for (const candle of allCandles) {\r\n * console.log(`${candle.timestamp}: O=${candle.open} H=${candle.high} L=${candle.low} C=${candle.close}`);\r\n * }\r\n * ```\r\n */\r\nexport class CandlesResource {\r\n constructor(\r\n private http: HttpClient,\r\n private basePath: string = '/v1',\r\n private coinTransform: (coin: string) => string = (c) => c.toUpperCase()\r\n ) {}\r\n\r\n /**\r\n * Get historical OHLCV candle data with cursor-based pagination\r\n *\r\n * @param coin - The coin symbol (e.g., 'BTC', 'ETH')\r\n * @param params - Time range, interval, and cursor pagination parameters (start and end are required)\r\n * @returns CursorResponse with candle records and nextCursor for pagination\r\n */\r\n async history(coin: string, params: CandleHistoryParams): Promise<CursorResponse<Candle[]>> {\r\n const response = await this.http.get<ApiResponse<Candle[]>>(\r\n `${this.basePath}/candles/${this.coinTransform(coin)}`,\r\n params as unknown as Record<string, unknown>,\r\n this.http.validationEnabled ? CandleArrayResponseSchema : undefined\r\n );\r\n return {\r\n data: response.data,\r\n nextCursor: response.meta.nextCursor,\r\n };\r\n }\r\n}\r\n","import type { HttpClient } from '../http';\r\nimport type { ApiResponse, CursorResponse, Liquidation, LiquidationHistoryParams, LiquidationsByUserParams, LiquidationVolume, LiquidationVolumeParams } from '../types';\r\nimport { LiquidationArrayResponseSchema, LiquidationVolumeArrayResponseSchema } from '../schemas';\r\n\r\n/**\r\n * Liquidations API resource\r\n *\r\n * Retrieve historical liquidation events from Hyperliquid.\r\n *\r\n * Note: Liquidation data is available from May 25, 2025 onwards.\r\n *\r\n * @example\r\n * ```typescript\r\n * // Get recent liquidations for a coin\r\n * let result = await client.hyperliquid.liquidations.history('BTC', {\r\n * start: Date.now() - 86400000,\r\n * end: Date.now(),\r\n * limit: 1000\r\n * });\r\n *\r\n * // Get all pages\r\n * const allLiquidations = [...result.data];\r\n * while (result.nextCursor) {\r\n * result = await client.hyperliquid.liquidations.history('BTC', {\r\n * start: Date.now() - 86400000,\r\n * end: Date.now(),\r\n * cursor: result.nextCursor,\r\n * limit: 1000\r\n * });\r\n * allLiquidations.push(...result.data);\r\n * }\r\n *\r\n * // Get liquidations for a specific user\r\n * const userLiquidations = await client.hyperliquid.liquidations.byUser('0x1234...', {\r\n * start: Date.now() - 86400000 * 7,\r\n * end: Date.now()\r\n * });\r\n * ```\r\n */\r\nexport class LiquidationsResource {\r\n constructor(private http: HttpClient, private basePath: string = '/v1') {}\r\n\r\n /**\r\n * Get liquidation history for a coin with cursor-based pagination\r\n *\r\n * @param coin - The coin symbol (e.g., 'BTC', 'ETH')\r\n * @param params - Time range and cursor pagination parameters (start and end are required)\r\n * @returns CursorResponse with liquidation records and nextCursor for pagination\r\n */\r\n async history(coin: string, params: LiquidationHistoryParams): Promise<CursorResponse<Liquidation[]>> {\r\n const response = await this.http.get<ApiResponse<Liquidation[]>>(\r\n `${this.basePath}/liquidations/${coin.toUpperCase()}`,\r\n params as unknown as Record<string, unknown>,\r\n this.http.validationEnabled ? LiquidationArrayResponseSchema : undefined\r\n );\r\n return {\r\n data: response.data,\r\n nextCursor: response.meta.nextCursor,\r\n };\r\n }\r\n\r\n /**\r\n * Get liquidation history for a specific user\r\n *\r\n * This returns liquidations where the user was either:\r\n * - The liquidated party (their position was liquidated)\r\n * - The liquidator (they executed the liquidation)\r\n *\r\n * @param userAddress - User's wallet address (e.g., '0x1234...')\r\n * @param params - Time range and cursor pagination parameters (start and end are required)\r\n * @returns CursorResponse with liquidation records and nextCursor for pagination\r\n */\r\n async byUser(userAddress: string, params: LiquidationsByUserParams): Promise<CursorResponse<Liquidation[]>> {\r\n const response = await this.http.get<ApiResponse<Liquidation[]>>(\r\n `${this.basePath}/liquidations/user/${userAddress}`,\r\n params as unknown as Record<string, unknown>,\r\n this.http.validationEnabled ? LiquidationArrayResponseSchema : undefined\r\n );\r\n return {\r\n data: response.data,\r\n nextCursor: response.meta.nextCursor,\r\n };\r\n }\r\n\r\n /**\r\n * Get aggregated liquidation volume in time-bucketed intervals\r\n *\r\n * Returns pre-aggregated data with total/long/short USD volumes per bucket,\r\n * reducing data transfer by 100-1000x compared to individual liquidation records.\r\n *\r\n * @param coin - The coin symbol (e.g., 'BTC', 'ETH')\r\n * @param params - Time range, cursor, and interval parameters\r\n * @returns CursorResponse with liquidation volume buckets\r\n */\r\n async volume(coin: string, params: LiquidationVolumeParams): Promise<CursorResponse<LiquidationVolume[]>> {\r\n const response = await this.http.get<ApiResponse<LiquidationVolume[]>>(\r\n `${this.basePath}/liquidations/${coin.toUpperCase()}/volume`,\r\n params as unknown as Record<string, unknown>,\r\n this.http.validationEnabled ? LiquidationVolumeArrayResponseSchema as any : undefined\r\n );\r\n return {\r\n data: response.data,\r\n nextCursor: response.meta.nextCursor,\r\n };\r\n }\r\n}\r\n","import type { HttpClient } from '../http';\r\nimport type {\r\n CoverageResponse,\r\n ExchangeCoverage,\r\n Incident,\r\n IncidentsResponse,\r\n LatencyResponse,\r\n ListIncidentsParams,\r\n SlaParams,\r\n SlaResponse,\r\n StatusResponse,\r\n SymbolCoverageOptions,\r\n SymbolCoverageResponse,\r\n} from '../types';\r\n\r\n/**\r\n * Data quality API resource\r\n *\r\n * Provides endpoints for monitoring data quality, coverage, incidents, and SLA metrics.\r\n *\r\n * @example\r\n * ```typescript\r\n * // Get system status\r\n * const status = await client.dataQuality.status();\r\n * console.log(`System status: ${status.status}`);\r\n *\r\n * // Get coverage for all exchanges\r\n * const coverage = await client.dataQuality.coverage();\r\n *\r\n * // Get symbol-specific coverage with gap detection\r\n * const btc = await client.dataQuality.symbolCoverage('hyperliquid', 'BTC');\r\n * console.log(`BTC OI completeness: ${btc.dataTypes.open_interest.completeness}%`);\r\n * for (const gap of btc.dataTypes.open_interest.gaps.slice(0, 5)) {\r\n * console.log(`Gap: ${gap.start} - ${gap.end} (${gap.durationMinutes} min)`);\r\n * }\r\n * ```\r\n */\r\nexport class DataQualityResource {\r\n constructor(private http: HttpClient, private basePath: string = '/v1/data-quality') {}\r\n\r\n // ===========================================================================\r\n // Status Endpoints\r\n // ===========================================================================\r\n\r\n /**\r\n * Get overall system health status\r\n *\r\n * @returns StatusResponse with overall status, per-exchange status,\r\n * per-data-type status, and active incident count\r\n *\r\n * @example\r\n * ```typescript\r\n * const status = await client.dataQuality.status();\r\n * console.log(`Overall: ${status.status}`);\r\n * for (const [exchange, info] of Object.entries(status.exchanges)) {\r\n * console.log(`${exchange}: ${info.status}`);\r\n * }\r\n * ```\r\n */\r\n async status(): Promise<StatusResponse> {\r\n return this.http.get<StatusResponse>(`${this.basePath}/status`);\r\n }\r\n\r\n // ===========================================================================\r\n // Coverage Endpoints\r\n // ===========================================================================\r\n\r\n /**\r\n * Get data coverage summary for all exchanges\r\n *\r\n * @returns CoverageResponse with coverage info for all exchanges and data types\r\n *\r\n * @example\r\n * ```typescript\r\n * const coverage = await client.dataQuality.coverage();\r\n * for (const exchange of coverage.exchanges) {\r\n * console.log(`${exchange.exchange}:`);\r\n * for (const [dtype, info] of Object.entries(exchange.dataTypes)) {\r\n * console.log(` ${dtype}: ${info.totalRecords} records`);\r\n * }\r\n * }\r\n * ```\r\n */\r\n async coverage(): Promise<CoverageResponse> {\r\n return this.http.get<CoverageResponse>(`${this.basePath}/coverage`);\r\n }\r\n\r\n /**\r\n * Get data coverage for a specific exchange\r\n *\r\n * @param exchange - Exchange name ('hyperliquid', 'lighter', or 'hip3')\r\n * @returns ExchangeCoverage with coverage info for all data types on this exchange\r\n *\r\n * @example\r\n * ```typescript\r\n * const hl = await client.dataQuality.exchangeCoverage('hyperliquid');\r\n * console.log(`Orderbook earliest: ${hl.dataTypes.orderbook.earliest}`);\r\n * ```\r\n */\r\n async exchangeCoverage(exchange: string): Promise<ExchangeCoverage> {\r\n return this.http.get<ExchangeCoverage>(\r\n `${this.basePath}/coverage/${exchange.toLowerCase()}`\r\n );\r\n }\r\n\r\n /**\r\n * Get data coverage for a specific symbol on an exchange\r\n *\r\n * Includes gap detection, empirical data cadence, and hour-level historical coverage.\r\n * Supports optional time bounds for gap detection (default: last 30 days).\r\n *\r\n * @param exchange - Exchange name ('hyperliquid', 'lighter', or 'hip3')\r\n * @param symbol - Symbol name (e.g., 'BTC', 'ETH', or HIP3 coins like 'xyz:XYZ100')\r\n * @param options - Optional time bounds for gap detection window\r\n * @returns SymbolCoverageResponse with per-data-type coverage including gaps, cadence, and historical coverage\r\n *\r\n * @example\r\n * ```typescript\r\n * const btc = await client.dataQuality.symbolCoverage('hyperliquid', 'BTC');\r\n * const oi = btc.dataTypes.open_interest;\r\n * console.log(`OI completeness: ${oi.completeness}%`);\r\n * console.log(`Gaps found: ${oi.gaps.length}`);\r\n * for (const gap of oi.gaps.slice(0, 3)) {\r\n * console.log(` ${gap.durationMinutes} min gap at ${gap.start}`);\r\n * }\r\n *\r\n * // Check cadence\r\n * if (btc.dataTypes.orderbook.cadence) {\r\n * console.log(`Cadence: ~${btc.dataTypes.orderbook.cadence.medianIntervalSeconds}s`);\r\n * }\r\n *\r\n * // Time-bounded (last 7 days)\r\n * const weekAgo = Date.now() - 7 * 24 * 60 * 60 * 1000;\r\n * const btc7d = await client.dataQuality.symbolCoverage('hyperliquid', 'BTC', {\r\n * from: weekAgo,\r\n * to: Date.now(),\r\n * });\r\n * ```\r\n */\r\n async symbolCoverage(\r\n exchange: string,\r\n symbol: string,\r\n options?: SymbolCoverageOptions,\r\n ): Promise<SymbolCoverageResponse> {\r\n return this.http.get<SymbolCoverageResponse>(\r\n `${this.basePath}/coverage/${exchange.toLowerCase()}/${symbol}`,\r\n options as unknown as Record<string, unknown>\r\n );\r\n }\r\n\r\n // ===========================================================================\r\n // Incidents Endpoints\r\n // ===========================================================================\r\n\r\n /**\r\n * List incidents with filtering and pagination\r\n *\r\n * @param params - Filter and pagination options\r\n * @returns IncidentsResponse with list of incidents and pagination info\r\n *\r\n * @example\r\n * ```typescript\r\n * // Get all open incidents\r\n * const result = await client.dataQuality.listIncidents({ status: 'open' });\r\n * for (const incident of result.incidents) {\r\n * console.log(`${incident.severity}: ${incident.title}`);\r\n * }\r\n * ```\r\n */\r\n async listIncidents(params?: ListIncidentsParams): Promise<IncidentsResponse> {\r\n return this.http.get<IncidentsResponse>(\r\n `${this.basePath}/incidents`,\r\n params as unknown as Record<string, unknown>\r\n );\r\n }\r\n\r\n /**\r\n * Get a specific incident by ID\r\n *\r\n * @param incidentId - The incident ID\r\n * @returns Incident details\r\n *\r\n * @example\r\n * ```typescript\r\n * const incident = await client.dataQuality.getIncident('inc_123');\r\n * console.log(`Status: ${incident.status}`);\r\n * console.log(`Root cause: ${incident.rootCause}`);\r\n * ```\r\n */\r\n async getIncident(incidentId: string): Promise<Incident> {\r\n return this.http.get<Incident>(`${this.basePath}/incidents/${incidentId}`);\r\n }\r\n\r\n // ===========================================================================\r\n // Latency Endpoints\r\n // ===========================================================================\r\n\r\n /**\r\n * Get current latency metrics for all exchanges\r\n *\r\n * @returns LatencyResponse with WebSocket, REST API, and data freshness metrics\r\n *\r\n * @example\r\n * ```typescript\r\n * const latency = await client.dataQuality.latency();\r\n * for (const [exchange, metrics] of Object.entries(latency.exchanges)) {\r\n * console.log(`${exchange}:`);\r\n * if (metrics.websocket) {\r\n * console.log(` WS current: ${metrics.websocket.currentMs}ms`);\r\n * }\r\n * console.log(` OB lag: ${metrics.dataFreshness.orderbookLagMs}ms`);\r\n * }\r\n * ```\r\n */\r\n async latency(): Promise<LatencyResponse> {\r\n return this.http.get<LatencyResponse>(`${this.basePath}/latency`);\r\n }\r\n\r\n // ===========================================================================\r\n // SLA Endpoints\r\n // ===========================================================================\r\n\r\n /**\r\n * Get SLA compliance metrics for a specific month\r\n *\r\n * @param params - Optional year and month (defaults to current month)\r\n * @returns SlaResponse with SLA targets, actual metrics, and compliance status\r\n *\r\n * @example\r\n * ```typescript\r\n * const sla = await client.dataQuality.sla({ year: 2026, month: 1 });\r\n * console.log(`Period: ${sla.period}`);\r\n * console.log(`Uptime: ${sla.actual.uptime}% (${sla.actual.uptimeStatus})`);\r\n * console.log(`Completeness: ${sla.actual.dataCompleteness.overall}%`);\r\n * console.log(`API P99: ${sla.actual.apiLatencyP99Ms}ms`);\r\n * ```\r\n */\r\n async sla(params?: SlaParams): Promise<SlaResponse> {\r\n return this.http.get<SlaResponse>(\r\n `${this.basePath}/sla`,\r\n params as unknown as Record<string, unknown>\r\n );\r\n }\r\n}\r\n","import type { HttpClient } from './http';\r\nimport type { ApiResponse, CursorResponse, CoinFreshness, CoinSummary, PriceSnapshot, PriceHistoryParams } from './types';\r\nimport {\r\n OrderBookResource,\r\n TradesResource,\r\n InstrumentsResource,\r\n LighterInstrumentsResource,\r\n Hip3InstrumentsResource,\r\n FundingResource,\r\n OpenInterestResource,\r\n CandlesResource,\r\n LiquidationsResource,\r\n} from './resources';\r\nimport {\r\n CoinFreshnessResponseSchema,\r\n CoinSummaryResponseSchema,\r\n PriceSnapshotArrayResponseSchema,\r\n} from './schemas';\r\n\r\n/**\r\n * Hyperliquid exchange client\r\n *\r\n * Access Hyperliquid market data through the 0xarchive API.\r\n *\r\n * @example\r\n * ```typescript\r\n * const client = new OxArchive({ apiKey: '...' });\r\n * const orderbook = await client.hyperliquid.orderbook.get('BTC');\r\n * const trades = await client.hyperliquid.trades.list('ETH', { start, end });\r\n * ```\r\n */\r\nexport class HyperliquidClient {\r\n /**\r\n * Order book data (L2 snapshots from April 2023)\r\n */\r\n public readonly orderbook: OrderBookResource;\r\n\r\n /**\r\n * Trade/fill history\r\n */\r\n public readonly trades: TradesResource;\r\n\r\n /**\r\n * Trading instruments metadata\r\n */\r\n public readonly instruments: InstrumentsResource;\r\n\r\n /**\r\n * Funding rates\r\n */\r\n public readonly funding: FundingResource;\r\n\r\n /**\r\n * Open interest\r\n */\r\n public readonly openInterest: OpenInterestResource;\r\n\r\n /**\r\n * OHLCV candle data\r\n */\r\n public readonly candles: CandlesResource;\r\n\r\n /**\r\n * Liquidation events (May 2025+)\r\n */\r\n public readonly liquidations: LiquidationsResource;\r\n\r\n /**\r\n * HIP-3 builder-deployed perpetuals (February 2026+)\r\n */\r\n public readonly hip3: Hip3Client;\r\n\r\n private http: HttpClient;\r\n\r\n constructor(http: HttpClient) {\r\n this.http = http;\r\n const basePath = '/v1/hyperliquid';\r\n this.orderbook = new OrderBookResource(http, basePath);\r\n this.trades = new TradesResource(http, basePath);\r\n this.instruments = new InstrumentsResource(http, basePath);\r\n this.funding = new FundingResource(http, basePath);\r\n this.openInterest = new OpenInterestResource(http, basePath);\r\n this.candles = new CandlesResource(http, basePath);\r\n this.liquidations = new LiquidationsResource(http, basePath);\r\n this.hip3 = new Hip3Client(http);\r\n }\r\n\r\n /**\r\n * Get per-coin data freshness across all data types\r\n *\r\n * @param coin - The coin symbol (e.g., 'BTC', 'ETH')\r\n * @returns Per-coin freshness with last_updated and lag_ms for each data type\r\n */\r\n async freshness(coin: string): Promise<CoinFreshness> {\r\n const response = await this.http.get<ApiResponse<CoinFreshness>>(\r\n `/v1/hyperliquid/freshness/${coin.toUpperCase()}`,\r\n undefined,\r\n this.http.validationEnabled ? CoinFreshnessResponseSchema as any : undefined\r\n );\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Get combined market summary (price, funding, OI, volume, liquidations) in one call\r\n *\r\n * @param coin - The coin symbol (e.g., 'BTC', 'ETH')\r\n * @returns Combined market summary\r\n */\r\n async summary(coin: string): Promise<CoinSummary> {\r\n const response = await this.http.get<ApiResponse<CoinSummary>>(\r\n `/v1/hyperliquid/summary/${coin.toUpperCase()}`,\r\n undefined,\r\n this.http.validationEnabled ? CoinSummaryResponseSchema as any : undefined\r\n );\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Get mark/oracle/mid price history (projected from OI data)\r\n *\r\n * @param coin - The coin symbol (e.g., 'BTC', 'ETH')\r\n * @param params - Time range, cursor, and interval parameters\r\n * @returns CursorResponse with price snapshots\r\n */\r\n async priceHistory(coin: string, params: PriceHistoryParams): Promise<CursorResponse<PriceSnapshot[]>> {\r\n const response = await this.http.get<ApiResponse<PriceSnapshot[]>>(\r\n `/v1/hyperliquid/prices/${coin.toUpperCase()}`,\r\n params as unknown as Record<string, unknown>,\r\n this.http.validationEnabled ? PriceSnapshotArrayResponseSchema as any : undefined\r\n );\r\n return {\r\n data: response.data,\r\n nextCursor: response.meta.nextCursor,\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * HIP-3 builder-deployed perpetuals client\r\n *\r\n * Access Hyperliquid HIP-3 builder perps data through the 0xarchive API.\r\n * Free: km:US500 only. Build+: all coins. Orderbook: Pro+.\r\n *\r\n * @example\r\n * ```typescript\r\n * const client = new OxArchive({ apiKey: '...' });\r\n * const orderbook = await client.hyperliquid.hip3.orderbook.get('xyz:XYZ100');\r\n * const trades = await client.hyperliquid.hip3.trades.recent('xyz:XYZ100');\r\n * ```\r\n */\r\nexport class Hip3Client {\r\n /**\r\n * HIP-3 instruments with latest market data\r\n */\r\n public readonly instruments: Hip3InstrumentsResource;\r\n\r\n /**\r\n * Order book snapshots (February 2026+)\r\n */\r\n public readonly orderbook: OrderBookResource;\r\n\r\n /**\r\n * Trade/fill history\r\n */\r\n public readonly trades: TradesResource;\r\n\r\n /**\r\n * Funding rates\r\n */\r\n public readonly funding: FundingResource;\r\n\r\n /**\r\n * Open interest\r\n */\r\n public readonly openInterest: OpenInterestResource;\r\n\r\n /**\r\n * OHLCV candle data\r\n */\r\n public readonly candles: CandlesResource;\r\n\r\n private http: HttpClient;\r\n\r\n constructor(http: HttpClient) {\r\n this.http = http;\r\n const basePath = '/v1/hyperliquid/hip3';\r\n // HIP-3 coins use case-sensitive symbols like 'xyz:XYZ100' — do not uppercase\r\n const coinTransform = (c: string) => c;\r\n this.instruments = new Hip3InstrumentsResource(http, basePath, coinTransform);\r\n this.orderbook = new OrderBookResource(http, basePath, coinTransform);\r\n this.trades = new TradesResource(http, basePath, coinTransform);\r\n this.funding = new FundingResource(http, basePath, coinTransform);\r\n this.openInterest = new OpenInterestResource(http, basePath, coinTransform);\r\n this.candles = new CandlesResource(http, basePath, coinTransform);\r\n }\r\n\r\n /**\r\n * Get per-coin data freshness across all data types\r\n *\r\n * @param coin - The coin symbol (case-sensitive, e.g., 'km:US500')\r\n * @returns Per-coin freshness with last_updated and lag_ms for each data type\r\n */\r\n async freshness(coin: string): Promise<CoinFreshness> {\r\n const response = await this.http.get<ApiResponse<CoinFreshness>>(\r\n `/v1/hyperliquid/hip3/freshness/${coin}`,\r\n undefined,\r\n this.http.validationEnabled ? CoinFreshnessResponseSchema as any : undefined\r\n );\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Get combined market summary (price, funding, OI) in one call\r\n *\r\n * @param coin - The coin symbol (case-sensitive, e.g., 'km:US500')\r\n * @returns Combined market summary\r\n */\r\n async summary(coin: string): Promise<CoinSummary> {\r\n const response = await this.http.get<ApiResponse<CoinSummary>>(\r\n `/v1/hyperliquid/hip3/summary/${coin}`,\r\n undefined,\r\n this.http.validationEnabled ? CoinSummaryResponseSchema as any : undefined\r\n );\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Get mark/oracle/mid price history (projected from OI data)\r\n *\r\n * @param coin - The coin symbol (case-sensitive, e.g., 'km:US500')\r\n * @param params - Time range, cursor, and interval parameters\r\n * @returns CursorResponse with price snapshots\r\n */\r\n async priceHistory(coin: string, params: PriceHistoryParams): Promise<CursorResponse<PriceSnapshot[]>> {\r\n const response = await this.http.get<ApiResponse<PriceSnapshot[]>>(\r\n `/v1/hyperliquid/hip3/prices/${coin}`,\r\n params as unknown as Record<string, unknown>,\r\n this.http.validationEnabled ? PriceSnapshotArrayResponseSchema as any : undefined\r\n );\r\n return {\r\n data: response.data,\r\n nextCursor: response.meta.nextCursor,\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Lighter.xyz exchange client\r\n *\r\n * Access Lighter.xyz market data through the 0xarchive API.\r\n *\r\n * @example\r\n * ```typescript\r\n * const client = new OxArchive({ apiKey: '...' });\r\n * const orderbook = await client.lighter.orderbook.get('BTC');\r\n * const trades = await client.lighter.trades.list('ETH', { start, end });\r\n * const instruments = await client.lighter.instruments.list();\r\n * console.log(`ETH taker fee: ${instruments[0].takerFee}`);\r\n * ```\r\n */\r\nexport class LighterClient {\r\n /**\r\n * Order book data (L2 snapshots)\r\n */\r\n public readonly orderbook: OrderBookResource;\r\n\r\n /**\r\n * Trade/fill history\r\n */\r\n public readonly trades: TradesResource;\r\n\r\n /**\r\n * Trading instruments metadata (returns LighterInstrument with fees, min amounts, etc.)\r\n */\r\n public readonly instruments: LighterInstrumentsResource;\r\n\r\n /**\r\n * Funding rates\r\n */\r\n public readonly funding: FundingResource;\r\n\r\n /**\r\n * Open interest\r\n */\r\n public readonly openInterest: OpenInterestResource;\r\n\r\n /**\r\n * OHLCV candle data\r\n */\r\n public readonly candles: CandlesResource;\r\n\r\n private http: HttpClient;\r\n\r\n constructor(http: HttpClient) {\r\n this.http = http;\r\n const basePath = '/v1/lighter';\r\n this.orderbook = new OrderBookResource(http, basePath);\r\n this.trades = new TradesResource(http, basePath);\r\n this.instruments = new LighterInstrumentsResource(http, basePath);\r\n this.funding = new FundingResource(http, basePath);\r\n this.openInterest = new OpenInterestResource(http, basePath);\r\n this.candles = new CandlesResource(http, basePath);\r\n }\r\n\r\n /**\r\n * Get per-coin data freshness across all data types\r\n *\r\n * @param coin - The coin symbol (e.g., 'BTC', 'ETH')\r\n * @returns Per-coin freshness with last_updated and lag_ms for each data type\r\n */\r\n async freshness(coin: string): Promise<CoinFreshness> {\r\n const response = await this.http.get<ApiResponse<CoinFreshness>>(\r\n `/v1/lighter/freshness/${coin.toUpperCase()}`,\r\n undefined,\r\n this.http.validationEnabled ? CoinFreshnessResponseSchema as any : undefined\r\n );\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Get combined market summary (price, funding, OI) in one call\r\n *\r\n * @param coin - The coin symbol (e.g., 'BTC', 'ETH')\r\n * @returns Combined market summary\r\n */\r\n async summary(coin: string): Promise<CoinSummary> {\r\n const response = await this.http.get<ApiResponse<CoinSummary>>(\r\n `/v1/lighter/summary/${coin.toUpperCase()}`,\r\n undefined,\r\n this.http.validationEnabled ? CoinSummaryResponseSchema as any : undefined\r\n );\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Get mark/oracle price history (projected from OI data)\r\n *\r\n * @param coin - The coin symbol (e.g., 'BTC', 'ETH')\r\n * @param params - Time range, cursor, and interval parameters\r\n * @returns CursorResponse with price snapshots\r\n */\r\n async priceHistory(coin: string, params: PriceHistoryParams): Promise<CursorResponse<PriceSnapshot[]>> {\r\n const response = await this.http.get<ApiResponse<PriceSnapshot[]>>(\r\n `/v1/lighter/prices/${coin.toUpperCase()}`,\r\n params as unknown as Record<string, unknown>,\r\n this.http.validationEnabled ? PriceSnapshotArrayResponseSchema as any : undefined\r\n );\r\n return {\r\n data: response.data,\r\n nextCursor: response.meta.nextCursor,\r\n };\r\n }\r\n}\r\n","import type { ClientOptions } from './types';\r\nimport { HttpClient } from './http';\r\nimport { HyperliquidClient, LighterClient } from './exchanges';\r\nimport {\r\n OrderBookResource,\r\n TradesResource,\r\n InstrumentsResource,\r\n FundingResource,\r\n OpenInterestResource,\r\n DataQualityResource,\r\n} from './resources';\r\n\r\nconst DEFAULT_BASE_URL = 'https://api.0xarchive.io';\r\nconst DEFAULT_TIMEOUT = 30000;\r\n\r\n/**\r\n * 0xarchive API client\r\n *\r\n * Supports multiple exchanges:\r\n * - `client.hyperliquid` - Hyperliquid perpetuals (April 2023+)\r\n * - `client.lighter` - Lighter.xyz perpetuals\r\n *\r\n * @example\r\n * ```typescript\r\n * import { OxArchive } from '@0xarchive/sdk';\r\n *\r\n * const client = new OxArchive({ apiKey: '0xa_your_api_key' });\r\n *\r\n * // Hyperliquid data\r\n * const hlOrderbook = await client.hyperliquid.orderbook.get('BTC');\r\n * console.log(`BTC mid price: ${hlOrderbook.mid_price}`);\r\n *\r\n * // Lighter.xyz data\r\n * const lighterOrderbook = await client.lighter.orderbook.get('BTC');\r\n *\r\n * // Get historical data\r\n * const history = await client.hyperliquid.orderbook.history('ETH', {\r\n * start: Date.now() - 86400000,\r\n * end: Date.now(),\r\n * limit: 100\r\n * });\r\n *\r\n * // List all instruments\r\n * const instruments = await client.hyperliquid.instruments.list();\r\n * ```\r\n *\r\n * Legacy usage (deprecated, will be removed in v2.0):\r\n * ```typescript\r\n * // These still work but use client.hyperliquid.* instead\r\n * const orderbook = await client.orderbook.get('BTC'); // deprecated\r\n * ```\r\n */\r\nexport class OxArchive {\r\n private http: HttpClient;\r\n\r\n /**\r\n * Hyperliquid exchange data (orderbook, trades, funding, OI from April 2023)\r\n */\r\n public readonly hyperliquid: HyperliquidClient;\r\n\r\n /**\r\n * Lighter.xyz exchange data (August 2025+)\r\n */\r\n public readonly lighter: LighterClient;\r\n\r\n /**\r\n * Data quality metrics: status, coverage, incidents, latency, SLA\r\n */\r\n public readonly dataQuality: DataQualityResource;\r\n\r\n /**\r\n * @deprecated Use client.hyperliquid.orderbook instead\r\n */\r\n public readonly orderbook: OrderBookResource;\r\n\r\n /**\r\n * @deprecated Use client.hyperliquid.trades instead\r\n */\r\n public readonly trades: TradesResource;\r\n\r\n /**\r\n * @deprecated Use client.hyperliquid.instruments instead\r\n */\r\n public readonly instruments: InstrumentsResource;\r\n\r\n /**\r\n * @deprecated Use client.hyperliquid.funding instead\r\n */\r\n public readonly funding: FundingResource;\r\n\r\n /**\r\n * @deprecated Use client.hyperliquid.openInterest instead\r\n */\r\n public readonly openInterest: OpenInterestResource;\r\n\r\n /**\r\n * Create a new 0xarchive client\r\n *\r\n * @param options - Client configuration options\r\n */\r\n constructor(options: ClientOptions) {\r\n if (!options.apiKey) {\r\n throw new Error('API key is required. Get one at https://0xarchive.io/signup');\r\n }\r\n\r\n this.http = new HttpClient({\r\n baseUrl: options.baseUrl ?? DEFAULT_BASE_URL,\r\n apiKey: options.apiKey,\r\n timeout: options.timeout ?? DEFAULT_TIMEOUT,\r\n validate: options.validate ?? false,\r\n });\r\n\r\n // Exchange-specific clients (recommended)\r\n this.hyperliquid = new HyperliquidClient(this.http);\r\n this.lighter = new LighterClient(this.http);\r\n\r\n // Data quality monitoring (cross-exchange)\r\n this.dataQuality = new DataQualityResource(this.http);\r\n\r\n // Legacy resource namespaces (deprecated - use client.hyperliquid.* instead)\r\n // These will be removed in v2.0\r\n // Note: Using /v1/hyperliquid base path for backward compatibility\r\n const legacyBase = '/v1/hyperliquid';\r\n this.orderbook = new OrderBookResource(this.http, legacyBase);\r\n this.trades = new TradesResource(this.http, legacyBase);\r\n this.instruments = new InstrumentsResource(this.http, legacyBase);\r\n this.funding = new FundingResource(this.http, legacyBase);\r\n this.openInterest = new OpenInterestResource(this.http, legacyBase);\r\n }\r\n}\r\n","/**\r\n * WebSocket client for 0xarchive real-time streaming, replay, and bulk download\r\n *\r\n * @example Real-time streaming\r\n * ```typescript\r\n * const ws = new OxArchiveWs({ apiKey: 'ox_...' });\r\n * await ws.connect();\r\n * ws.onOrderbook((coin, ob) => console.log(`${coin}: ${ob.midPrice}`));\r\n * ws.subscribeOrderbook('BTC');\r\n * ```\r\n *\r\n * @example Historical replay (like Tardis.dev)\r\n * ```typescript\r\n * const ws = new OxArchiveWs({ apiKey: 'ox_...' });\r\n * ws.onHistoricalData((coin, timestamp, data) => {\r\n * console.log(`${new Date(timestamp)}: ${data.mid_price}`);\r\n * });\r\n * await ws.connect();\r\n * ws.replay('orderbook', 'BTC', {\r\n * start: Date.now() - 86400000,\r\n * speed: 10 // 10x speed\r\n * });\r\n * ```\r\n *\r\n * @example Bulk streaming (like Databento)\r\n * ```typescript\r\n * const ws = new OxArchiveWs({ apiKey: 'ox_...' });\r\n * const batches: OrderBook[] = [];\r\n * ws.onBatch((coin, records) => {\r\n * batches.push(...records.map(r => r.data));\r\n * });\r\n * ws.onStreamComplete((channel, coin, count) => {\r\n * console.log(`Downloaded ${count} records`);\r\n * });\r\n * await ws.connect();\r\n * ws.stream('orderbook', 'ETH', {\r\n * start: Date.now() - 3600000,\r\n * end: Date.now(),\r\n * batchSize: 1000\r\n * });\r\n * ```\r\n */\r\n\r\nimport type {\r\n WsOptions,\r\n WsChannel,\r\n WsClientMessage,\r\n WsServerMessage,\r\n WsConnectionState,\r\n WsEventHandlers,\r\n OrderBook,\r\n OrderbookDelta,\r\n PriceLevel,\r\n Trade,\r\n WsHistoricalData,\r\n WsHistoricalTickData,\r\n WsHistoricalBatch,\r\n WsReplayStarted,\r\n WsReplayCompleted,\r\n WsReplaySnapshot,\r\n WsStreamStarted,\r\n WsStreamCompleted,\r\n WsStreamProgress,\r\n WsGapDetected,\r\n} from './types';\r\n\r\nconst DEFAULT_WS_URL = 'wss://api.0xarchive.io/ws';\r\nconst DEFAULT_PING_INTERVAL = 30000; // 30 seconds\r\nconst DEFAULT_RECONNECT_DELAY = 1000;\r\nconst DEFAULT_MAX_RECONNECT_ATTEMPTS = 10;\r\n\r\n// Server idle timeout is 60 seconds. The SDK sends pings every 30 seconds\r\n// to keep the connection alive. Browser WebSocket API automatically responds\r\n// to WebSocket protocol-level ping frames from the server.\r\n\r\n/**\r\n * Transform raw Hyperliquid trade format to SDK Trade type.\r\n * Raw format: { px, sz, side, time, hash, tid, users: [maker, taker] }\r\n * SDK format: { coin, side, price, size, timestamp, tx_hash, trade_id, maker_address, taker_address }\r\n */\r\nfunction transformTrade(coin: string, raw: Record<string, unknown>): Trade {\r\n // Check if already in SDK format (from REST API or historical replay)\r\n if ('price' in raw && 'size' in raw) {\r\n return raw as unknown as Trade;\r\n }\r\n\r\n // Transform from Hyperliquid raw format\r\n const px = raw.px as string | undefined;\r\n const sz = raw.sz as string | undefined;\r\n const side = raw.side as string | undefined;\r\n const time = raw.time as number | undefined;\r\n const hash = raw.hash as string | undefined;\r\n const tid = raw.tid as number | undefined;\r\n\r\n // Extract user addresses from the users array (market-level WebSocket trades)\r\n // users[0] = maker address, users[1] = taker address\r\n const users = raw.users as string[] | undefined;\r\n const maker_address = users && users.length > 0 ? users[0] : undefined;\r\n const taker_address = users && users.length > 1 ? users[1] : undefined;\r\n\r\n // Also check for user_address field (for historical replay data)\r\n const user_address = raw.userAddress as string | undefined ?? raw.user_address as string | undefined;\r\n\r\n return {\r\n coin,\r\n side: (side === 'A' || side === 'B' ? side : 'B') as 'A' | 'B',\r\n price: px ?? '0',\r\n size: sz ?? '0',\r\n timestamp: time ? new Date(time).toISOString() : new Date().toISOString(),\r\n txHash: hash,\r\n tradeId: tid,\r\n makerAddress: maker_address,\r\n takerAddress: taker_address,\r\n userAddress: user_address,\r\n };\r\n}\r\n\r\n/**\r\n * Transform an array of raw Hyperliquid trades to SDK Trade types.\r\n */\r\nfunction transformTrades(coin: string, rawTrades: unknown): Trade[] {\r\n if (!Array.isArray(rawTrades)) {\r\n // Single trade object\r\n return [transformTrade(coin, rawTrades as Record<string, unknown>)];\r\n }\r\n return rawTrades.map((raw) => transformTrade(coin, raw as Record<string, unknown>));\r\n}\r\n\r\n/**\r\n * Transform raw Hyperliquid orderbook format to SDK OrderBook type.\r\n * Raw format: { coin, levels: [[{px, sz, n}, ...], [{px, sz, n}, ...]], time }\r\n * SDK format: { coin, timestamp, bids: [{px, sz, n}], asks: [{px, sz, n}], mid_price, spread, spread_bps }\r\n */\r\nfunction transformOrderbook(coin: string, raw: Record<string, unknown>): OrderBook {\r\n // Check if already in SDK format (from REST API or historical replay)\r\n if ('bids' in raw && 'asks' in raw) {\r\n return raw as unknown as OrderBook;\r\n }\r\n\r\n // Transform from Hyperliquid raw format\r\n // levels is [[{px, sz, n}, ...], [{px, sz, n}, ...]] where [0]=bids, [1]=asks\r\n const levels = raw.levels as Array<Array<{ px: string; sz: string; n: number }>> | undefined;\r\n const time = raw.time as number | undefined;\r\n\r\n const bids: PriceLevel[] = [];\r\n const asks: PriceLevel[] = [];\r\n\r\n if (levels && levels.length >= 2) {\r\n // levels[0] = bids, levels[1] = asks\r\n // Each level is already {px, sz, n} object\r\n for (const level of levels[0] || []) {\r\n bids.push({ px: level.px, sz: level.sz, n: level.n });\r\n }\r\n for (const level of levels[1] || []) {\r\n asks.push({ px: level.px, sz: level.sz, n: level.n });\r\n }\r\n }\r\n\r\n // Calculate mid price and spread\r\n let midPrice: string | undefined;\r\n let spread: string | undefined;\r\n let spreadBps: string | undefined;\r\n\r\n if (bids.length > 0 && asks.length > 0) {\r\n const bestBid = parseFloat(bids[0].px);\r\n const bestAsk = parseFloat(asks[0].px);\r\n const mid = (bestBid + bestAsk) / 2;\r\n midPrice = mid.toString();\r\n spread = (bestAsk - bestBid).toString();\r\n spreadBps = ((bestAsk - bestBid) / mid * 10000).toFixed(2);\r\n }\r\n\r\n return {\r\n coin,\r\n timestamp: time ? new Date(time).toISOString() : new Date().toISOString(),\r\n bids,\r\n asks,\r\n midPrice,\r\n spread,\r\n spreadBps,\r\n };\r\n}\r\n\r\n/**\r\n * WebSocket client for real-time data streaming.\r\n *\r\n * **Keep-Alive:** The server sends WebSocket ping frames every 30 seconds\r\n * and will disconnect idle connections after 60 seconds. This SDK automatically\r\n * handles keep-alive by sending application-level pings at the configured interval\r\n * (default: 30 seconds). The browser WebSocket API automatically responds to\r\n * server ping frames.\r\n */\r\nexport class OxArchiveWs {\r\n private ws: WebSocket | null = null;\r\n private options: Required<WsOptions>;\r\n private handlers: WsEventHandlers = {};\r\n private subscriptions: Set<string> = new Set();\r\n private state: WsConnectionState = 'disconnected';\r\n private reconnectAttempts = 0;\r\n private pingTimer: ReturnType<typeof setInterval> | null = null;\r\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\r\n\r\n // Typed event handlers (separate from WsEventHandlers to avoid wrapping issues)\r\n private historicalDataHandlers: Array<(coin: string, timestamp: number, data: unknown) => void> = [];\r\n private historicalTickDataHandlers: Array<(coin: string, checkpoint: OrderBook, deltas: OrderbookDelta[]) => void> = [];\r\n private batchHandlers: Array<(coin: string, records: Array<{ timestamp: number; data: unknown }>) => void> = [];\r\n private replayStartHandlers: Array<(channel: WsChannel, coin: string, start: number, end: number, speed: number) => void> = [];\r\n private replayCompleteHandlers: Array<(channel: WsChannel, coin: string, snapshotsSent: number) => void> = [];\r\n private replaySnapshotHandlers: Array<(channel: WsChannel, coin: string, timestamp: number, data: unknown) => void> = [];\r\n private streamStartHandlers: Array<(channel: WsChannel, coin: string, start: number, end: number) => void> = [];\r\n private streamProgressHandlers: Array<(snapshotsSent: number) => void> = [];\r\n private streamCompleteHandlers: Array<(channel: WsChannel, coin: string, snapshotsSent: number) => void> = [];\r\n private orderbookHandlers: Array<(coin: string, data: OrderBook) => void> = [];\r\n private tradesHandlers: Array<(coin: string, data: Trade[]) => void> = [];\r\n private gapHandlers: Array<(channel: WsChannel, coin: string, gapStart: number, gapEnd: number, durationMinutes: number) => void> = [];\r\n\r\n constructor(options: WsOptions) {\r\n this.options = {\r\n apiKey: options.apiKey,\r\n wsUrl: options.wsUrl ?? DEFAULT_WS_URL,\r\n autoReconnect: options.autoReconnect ?? true,\r\n reconnectDelay: options.reconnectDelay ?? DEFAULT_RECONNECT_DELAY,\r\n maxReconnectAttempts: options.maxReconnectAttempts ?? DEFAULT_MAX_RECONNECT_ATTEMPTS,\r\n pingInterval: options.pingInterval ?? DEFAULT_PING_INTERVAL,\r\n };\r\n }\r\n\r\n /**\r\n * Connect to the WebSocket server\r\n *\r\n * @returns Promise that resolves when connected\r\n * @example\r\n * ```typescript\r\n * await ws.connect();\r\n * ws.subscribeOrderbook('BTC');\r\n * ```\r\n */\r\n connect(handlers?: WsEventHandlers): Promise<void> {\r\n if (handlers) {\r\n this.handlers = handlers;\r\n }\r\n\r\n this.setState('connecting');\r\n\r\n return new Promise((resolve, reject) => {\r\n const url = `${this.options.wsUrl}?apiKey=${encodeURIComponent(this.options.apiKey)}`;\r\n this.ws = new WebSocket(url);\r\n\r\n this.ws.onopen = () => {\r\n this.reconnectAttempts = 0;\r\n this.setState('connected');\r\n this.startPing();\r\n this.resubscribe();\r\n this.handlers.onOpen?.();\r\n resolve();\r\n };\r\n\r\n this.ws.onclose = (event) => {\r\n this.stopPing();\r\n const wasConnecting = this.state === 'connecting';\r\n this.handlers.onClose?.(event.code, event.reason);\r\n\r\n // If initial connection failed, reject and don't auto-reconnect\r\n if (wasConnecting) {\r\n this.setState('disconnected');\r\n reject(new Error(`WebSocket closed before connecting (code: ${event.code})`));\r\n return;\r\n }\r\n\r\n // Only auto-reconnect if we were previously connected\r\n if (this.options.autoReconnect && this.state !== 'disconnected') {\r\n this.scheduleReconnect();\r\n } else {\r\n this.setState('disconnected');\r\n }\r\n };\r\n\r\n this.ws.onerror = () => {\r\n const error = new Error('WebSocket connection error');\r\n this.handlers.onError?.(error);\r\n // Note: onerror is usually followed by onclose, which will reject the promise\r\n };\r\n\r\n this.ws.onmessage = (event) => {\r\n try {\r\n const message = JSON.parse(event.data) as WsServerMessage;\r\n this.handleMessage(message);\r\n } catch {\r\n // Ignore parse errors for malformed messages\r\n }\r\n };\r\n });\r\n }\r\n\r\n /**\r\n * Disconnect from the WebSocket server\r\n */\r\n disconnect(): void {\r\n this.setState('disconnected');\r\n this.stopPing();\r\n this.clearReconnectTimer();\r\n\r\n if (this.ws) {\r\n this.ws.close(1000, 'Client disconnect');\r\n this.ws = null;\r\n }\r\n }\r\n\r\n /**\r\n * Subscribe to a channel\r\n */\r\n subscribe(channel: WsChannel, coin?: string): void {\r\n const key = this.subscriptionKey(channel, coin);\r\n this.subscriptions.add(key);\r\n\r\n if (this.isConnected()) {\r\n this.send({ op: 'subscribe', channel, coin });\r\n }\r\n }\r\n\r\n /**\r\n * Subscribe to order book updates for a coin\r\n */\r\n subscribeOrderbook(coin: string): void {\r\n this.subscribe('orderbook', coin);\r\n }\r\n\r\n /**\r\n * Subscribe to trades for a coin\r\n */\r\n subscribeTrades(coin: string): void {\r\n this.subscribe('trades', coin);\r\n }\r\n\r\n /**\r\n * Subscribe to ticker updates for a coin\r\n */\r\n subscribeTicker(coin: string): void {\r\n this.subscribe('ticker', coin);\r\n }\r\n\r\n /**\r\n * Subscribe to all tickers\r\n */\r\n subscribeAllTickers(): void {\r\n this.subscribe('all_tickers');\r\n }\r\n\r\n /**\r\n * Unsubscribe from a channel\r\n */\r\n unsubscribe(channel: WsChannel, coin?: string): void {\r\n const key = this.subscriptionKey(channel, coin);\r\n this.subscriptions.delete(key);\r\n\r\n if (this.isConnected()) {\r\n this.send({ op: 'unsubscribe', channel, coin });\r\n }\r\n }\r\n\r\n /**\r\n * Unsubscribe from order book updates for a coin\r\n */\r\n unsubscribeOrderbook(coin: string): void {\r\n this.unsubscribe('orderbook', coin);\r\n }\r\n\r\n /**\r\n * Unsubscribe from trades for a coin\r\n */\r\n unsubscribeTrades(coin: string): void {\r\n this.unsubscribe('trades', coin);\r\n }\r\n\r\n /**\r\n * Unsubscribe from ticker updates for a coin\r\n */\r\n unsubscribeTicker(coin: string): void {\r\n this.unsubscribe('ticker', coin);\r\n }\r\n\r\n /**\r\n * Unsubscribe from all tickers\r\n */\r\n unsubscribeAllTickers(): void {\r\n this.unsubscribe('all_tickers');\r\n }\r\n\r\n // ==========================================================================\r\n // Historical Replay (Option B) - Like Tardis.dev\r\n // ==========================================================================\r\n\r\n /**\r\n * Start historical replay with timing preserved\r\n *\r\n * @param channel - Data channel to replay\r\n * @param coin - Trading pair (e.g., 'BTC', 'ETH')\r\n * @param options - Replay options\r\n *\r\n * @example\r\n * ```typescript\r\n * ws.replay('orderbook', 'BTC', {\r\n * start: Date.now() - 86400000, // 24 hours ago\r\n * speed: 10 // 10x faster than real-time\r\n * });\r\n * ```\r\n */\r\n replay(\r\n channel: WsChannel,\r\n coin: string,\r\n options: {\r\n start: number;\r\n end?: number;\r\n speed?: number;\r\n granularity?: string;\r\n /** Candle interval for candles channel (1m, 5m, 15m, 30m, 1h, 4h, 1d, 1w) */\r\n interval?: string;\r\n }\r\n ): void {\r\n this.send({\r\n op: 'replay',\r\n channel,\r\n coin,\r\n start: options.start,\r\n end: options.end,\r\n speed: options.speed ?? 1,\r\n granularity: options.granularity,\r\n interval: options.interval,\r\n });\r\n }\r\n\r\n /**\r\n * Start a multi-channel historical replay with timing preserved.\r\n * Data from all channels is interleaved chronologically. Before the timeline\r\n * begins, `replay_snapshot` messages provide initial state for each channel.\r\n *\r\n * @param channels - Array of data channels to replay simultaneously\r\n * @param coin - Trading pair (e.g., 'BTC', 'ETH')\r\n * @param options - Replay options\r\n *\r\n * @example\r\n * ```typescript\r\n * ws.onReplaySnapshot((channel, coin, timestamp, data) => {\r\n * console.log(`Initial ${channel} state at ${new Date(timestamp).toISOString()}`);\r\n * });\r\n * ws.onHistoricalData((coin, timestamp, data) => {\r\n * // Interleaved data from all channels\r\n * });\r\n * ws.multiReplay(['orderbook', 'trades', 'funding'], 'BTC', {\r\n * start: Date.now() - 86400000,\r\n * speed: 10\r\n * });\r\n * ```\r\n */\r\n multiReplay(\r\n channels: WsChannel[],\r\n coin: string,\r\n options: {\r\n start: number;\r\n end?: number;\r\n speed?: number;\r\n granularity?: string;\r\n interval?: string;\r\n }\r\n ): void {\r\n this.send({\r\n op: 'replay',\r\n channels,\r\n coin,\r\n start: options.start,\r\n end: options.end,\r\n speed: options.speed ?? 1,\r\n granularity: options.granularity,\r\n interval: options.interval,\r\n });\r\n }\r\n\r\n /**\r\n * Pause the current replay\r\n */\r\n replayPause(): void {\r\n this.send({ op: 'replay.pause' });\r\n }\r\n\r\n /**\r\n * Resume a paused replay\r\n */\r\n replayResume(): void {\r\n this.send({ op: 'replay.resume' });\r\n }\r\n\r\n /**\r\n * Seek to a specific timestamp in the replay\r\n * @param timestamp - Unix timestamp in milliseconds\r\n */\r\n replaySeek(timestamp: number): void {\r\n this.send({ op: 'replay.seek', timestamp });\r\n }\r\n\r\n /**\r\n * Stop the current replay\r\n */\r\n replayStop(): void {\r\n this.send({ op: 'replay.stop' });\r\n }\r\n\r\n // ==========================================================================\r\n // Bulk Streaming (Option D) - Like Databento\r\n // ==========================================================================\r\n\r\n /**\r\n * Start bulk streaming for fast data download\r\n *\r\n * @param channel - Data channel to stream\r\n * @param coin - Trading pair (e.g., 'BTC', 'ETH')\r\n * @param options - Stream options\r\n *\r\n * @example\r\n * ```typescript\r\n * ws.stream('orderbook', 'ETH', {\r\n * start: Date.now() - 3600000, // 1 hour ago\r\n * end: Date.now(),\r\n * batchSize: 1000\r\n * });\r\n * ```\r\n */\r\n stream(\r\n channel: WsChannel,\r\n coin: string,\r\n options: {\r\n start: number;\r\n end: number;\r\n batchSize?: number;\r\n granularity?: string;\r\n /** Candle interval for candles channel (1m, 5m, 15m, 30m, 1h, 4h, 1d, 1w) */\r\n interval?: string;\r\n }\r\n ): void {\r\n this.send({\r\n op: 'stream',\r\n channel,\r\n coin,\r\n start: options.start,\r\n end: options.end,\r\n batch_size: options.batchSize ?? 1000,\r\n granularity: options.granularity,\r\n interval: options.interval,\r\n });\r\n }\r\n\r\n /**\r\n * Start a multi-channel bulk stream for fast data download.\r\n * Data from all channels arrives in batches without timing delays.\r\n * Before batches begin, `replay_snapshot` messages provide initial state\r\n * for each channel.\r\n *\r\n * @param channels - Array of data channels to stream simultaneously\r\n * @param coin - Trading pair (e.g., 'BTC', 'ETH')\r\n * @param options - Stream options\r\n *\r\n * @example\r\n * ```typescript\r\n * ws.onReplaySnapshot((channel, coin, timestamp, data) => {\r\n * console.log(`Initial ${channel} state`);\r\n * });\r\n * ws.onBatch((coin, records) => {\r\n * // Batches contain data from all requested channels\r\n * });\r\n * ws.multiStream(['orderbook', 'trades', 'open_interest'], 'BTC', {\r\n * start: Date.now() - 3600000,\r\n * end: Date.now(),\r\n * batchSize: 1000\r\n * });\r\n * ```\r\n */\r\n multiStream(\r\n channels: WsChannel[],\r\n coin: string,\r\n options: {\r\n start: number;\r\n end: number;\r\n batchSize?: number;\r\n granularity?: string;\r\n interval?: string;\r\n }\r\n ): void {\r\n this.send({\r\n op: 'stream',\r\n channels,\r\n coin,\r\n start: options.start,\r\n end: options.end,\r\n batch_size: options.batchSize ?? 1000,\r\n granularity: options.granularity,\r\n interval: options.interval,\r\n });\r\n }\r\n\r\n /**\r\n * Stop the current bulk stream\r\n */\r\n streamStop(): void {\r\n this.send({ op: 'stream.stop' });\r\n }\r\n\r\n // ==========================================================================\r\n // Event Handlers for Replay/Stream\r\n // ==========================================================================\r\n\r\n /**\r\n * Handle historical data points (replay mode)\r\n */\r\n onHistoricalData<T = unknown>(\r\n handler: (coin: string, timestamp: number, data: T) => void\r\n ): void {\r\n this.historicalDataHandlers.push(handler as (coin: string, timestamp: number, data: unknown) => void);\r\n }\r\n\r\n /**\r\n * Handle historical tick data (granularity='tick' mode)\r\n * Receives a checkpoint (full orderbook) followed by incremental deltas.\r\n * This is for tick-level granularity on Lighter.xyz orderbook data.\r\n */\r\n onHistoricalTickData(\r\n handler: (coin: string, checkpoint: OrderBook, deltas: OrderbookDelta[]) => void\r\n ): void {\r\n this.historicalTickDataHandlers.push(handler);\r\n }\r\n\r\n /**\r\n * Handle batched data (bulk stream mode)\r\n */\r\n onBatch<T = unknown>(\r\n handler: (coin: string, records: Array<{ timestamp: number; data: T }>) => void\r\n ): void {\r\n this.batchHandlers.push(handler as (coin: string, records: Array<{ timestamp: number; data: unknown }>) => void);\r\n }\r\n\r\n /**\r\n * Handle replay started event\r\n */\r\n onReplayStart(\r\n handler: (channel: WsChannel, coin: string, start: number, end: number, speed: number) => void\r\n ): void {\r\n this.replayStartHandlers.push(handler);\r\n }\r\n\r\n /**\r\n * Handle replay completed event\r\n */\r\n onReplayComplete(\r\n handler: (channel: WsChannel, coin: string, snapshotsSent: number) => void\r\n ): void {\r\n this.replayCompleteHandlers.push(handler);\r\n }\r\n\r\n /**\r\n * Handle replay snapshot events (multi-channel mode).\r\n * Called with the initial state for each channel before the replay/stream\r\n * timeline begins. Use this to initialize local state (e.g., set the current\r\n * orderbook or latest funding rate) before `historical_data` messages start\r\n * arriving.\r\n *\r\n * @param handler - Callback receiving channel, coin, timestamp (ms), and data payload\r\n *\r\n * @example\r\n * ```typescript\r\n * ws.onReplaySnapshot((channel, coin, timestamp, data) => {\r\n * if (channel === 'orderbook') {\r\n * currentOrderbook = data;\r\n * } else if (channel === 'funding') {\r\n * currentFundingRate = data;\r\n * }\r\n * });\r\n * ```\r\n */\r\n onReplaySnapshot<T = unknown>(\r\n handler: (channel: WsChannel, coin: string, timestamp: number, data: T) => void\r\n ): void {\r\n this.replaySnapshotHandlers.push(handler as (channel: WsChannel, coin: string, timestamp: number, data: unknown) => void);\r\n }\r\n\r\n /**\r\n * Handle stream started event\r\n */\r\n onStreamStart(\r\n handler: (channel: WsChannel, coin: string, start: number, end: number) => void\r\n ): void {\r\n this.streamStartHandlers.push(handler);\r\n }\r\n\r\n /**\r\n * Handle stream progress event\r\n */\r\n onStreamProgress(\r\n handler: (snapshotsSent: number) => void\r\n ): void {\r\n this.streamProgressHandlers.push(handler);\r\n }\r\n\r\n /**\r\n * Handle stream completed event\r\n */\r\n onStreamComplete(\r\n handler: (channel: WsChannel, coin: string, snapshotsSent: number) => void\r\n ): void {\r\n this.streamCompleteHandlers.push(handler);\r\n }\r\n\r\n /**\r\n * Handle gap detected events during replay or streaming.\r\n * Called when there's a gap in the historical data exceeding the threshold.\r\n * Thresholds: 2 minutes for orderbook/candles/liquidations, 60 minutes for trades.\r\n *\r\n * @param handler - Callback receiving channel, coin, gap start/end timestamps (ms), and duration (minutes)\r\n *\r\n * @example\r\n * ```typescript\r\n * ws.onGap((channel, coin, gapStart, gapEnd, durationMinutes) => {\r\n * console.warn(`Gap detected in ${channel} ${coin}: ${durationMinutes} minutes`);\r\n * console.warn(` From: ${new Date(gapStart).toISOString()}`);\r\n * console.warn(` To: ${new Date(gapEnd).toISOString()}`);\r\n * });\r\n * ```\r\n */\r\n onGap(\r\n handler: (channel: WsChannel, coin: string, gapStart: number, gapEnd: number, durationMinutes: number) => void\r\n ): void {\r\n this.gapHandlers.push(handler);\r\n }\r\n\r\n /**\r\n * Get current connection state\r\n */\r\n getState(): WsConnectionState {\r\n return this.state;\r\n }\r\n\r\n /**\r\n * Check if connected\r\n */\r\n isConnected(): boolean {\r\n return this.ws?.readyState === WebSocket.OPEN;\r\n }\r\n\r\n /**\r\n * Set event handlers after construction\r\n */\r\n on<K extends keyof WsEventHandlers>(event: K, handler: WsEventHandlers[K]): void {\r\n this.handlers[event] = handler;\r\n }\r\n\r\n /**\r\n * Helper to handle typed orderbook data\r\n */\r\n onOrderbook(handler: (coin: string, data: OrderBook) => void): void {\r\n this.orderbookHandlers.push(handler);\r\n }\r\n\r\n /**\r\n * Helper to handle typed trade data\r\n */\r\n onTrades(handler: (coin: string, data: Trade[]) => void): void {\r\n this.tradesHandlers.push(handler);\r\n }\r\n\r\n // Private methods\r\n\r\n private send(message: WsClientMessage): void {\r\n if (this.ws?.readyState === WebSocket.OPEN) {\r\n this.ws.send(JSON.stringify(message));\r\n }\r\n }\r\n\r\n private setState(state: WsConnectionState): void {\r\n this.state = state;\r\n this.handlers.onStateChange?.(state);\r\n }\r\n\r\n private startPing(): void {\r\n this.stopPing();\r\n this.pingTimer = setInterval(() => {\r\n this.send({ op: 'ping' });\r\n }, this.options.pingInterval);\r\n }\r\n\r\n private stopPing(): void {\r\n if (this.pingTimer) {\r\n clearInterval(this.pingTimer);\r\n this.pingTimer = null;\r\n }\r\n }\r\n\r\n private subscriptionKey(channel: WsChannel, coin?: string): string {\r\n return coin ? `${channel}:${coin}` : channel;\r\n }\r\n\r\n private resubscribe(): void {\r\n for (const key of this.subscriptions) {\r\n const [channel, coin] = key.split(':') as [WsChannel, string | undefined];\r\n this.send({ op: 'subscribe', channel, coin });\r\n }\r\n }\r\n\r\n private scheduleReconnect(): void {\r\n if (this.reconnectAttempts >= this.options.maxReconnectAttempts) {\r\n this.setState('disconnected');\r\n return;\r\n }\r\n\r\n this.setState('reconnecting');\r\n this.reconnectAttempts++;\r\n\r\n const delay = this.options.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1);\r\n\r\n this.reconnectTimer = setTimeout(() => {\r\n this.connect().catch(() => {\r\n // Reconnect attempt failed, schedule another attempt\r\n // (reconnectAttempts is already incremented, so this will eventually stop)\r\n if (this.reconnectAttempts < this.options.maxReconnectAttempts) {\r\n this.scheduleReconnect();\r\n }\r\n });\r\n }, delay);\r\n }\r\n\r\n private clearReconnectTimer(): void {\r\n if (this.reconnectTimer) {\r\n clearTimeout(this.reconnectTimer);\r\n this.reconnectTimer = null;\r\n }\r\n }\r\n\r\n private handleMessage(message: WsServerMessage): void {\r\n // Call the generic onMessage handler first\r\n this.handlers.onMessage?.(message);\r\n\r\n // Dispatch to typed handlers based on message type\r\n switch (message.type) {\r\n case 'historical_data': {\r\n const msg = message as WsHistoricalData;\r\n for (const handler of this.historicalDataHandlers) {\r\n handler(msg.coin, msg.timestamp, msg.data);\r\n }\r\n break;\r\n }\r\n case 'historical_tick_data': {\r\n const msg = message as WsHistoricalTickData;\r\n for (const handler of this.historicalTickDataHandlers) {\r\n handler(msg.coin, msg.checkpoint, msg.deltas);\r\n }\r\n break;\r\n }\r\n case 'historical_batch': {\r\n const msg = message as WsHistoricalBatch;\r\n for (const handler of this.batchHandlers) {\r\n handler(msg.coin, msg.data as Array<{ timestamp: number; data: unknown }>);\r\n }\r\n break;\r\n }\r\n case 'replay_started': {\r\n const msg = message as WsReplayStarted;\r\n for (const handler of this.replayStartHandlers) {\r\n handler(msg.channel, msg.coin, msg.start, msg.end, msg.speed);\r\n }\r\n break;\r\n }\r\n case 'replay_completed': {\r\n const msg = message as WsReplayCompleted;\r\n for (const handler of this.replayCompleteHandlers) {\r\n handler(msg.channel, msg.coin, msg.snapshots_sent);\r\n }\r\n break;\r\n }\r\n case 'replay_snapshot': {\r\n const msg = message as WsReplaySnapshot;\r\n for (const handler of this.replaySnapshotHandlers) {\r\n handler(msg.channel, msg.coin, msg.timestamp, msg.data);\r\n }\r\n break;\r\n }\r\n case 'stream_started': {\r\n const msg = message as WsStreamStarted;\r\n for (const handler of this.streamStartHandlers) {\r\n handler(msg.channel, msg.coin, msg.start, msg.end);\r\n }\r\n break;\r\n }\r\n case 'stream_progress': {\r\n const msg = message as WsStreamProgress;\r\n for (const handler of this.streamProgressHandlers) {\r\n handler(msg.snapshots_sent);\r\n }\r\n break;\r\n }\r\n case 'stream_completed': {\r\n const msg = message as WsStreamCompleted;\r\n for (const handler of this.streamCompleteHandlers) {\r\n handler(msg.channel, msg.coin, msg.snapshots_sent);\r\n }\r\n break;\r\n }\r\n case 'gap_detected': {\r\n const msg = message as WsGapDetected;\r\n for (const handler of this.gapHandlers) {\r\n handler(msg.channel, msg.coin, msg.gap_start, msg.gap_end, msg.duration_minutes);\r\n }\r\n break;\r\n }\r\n case 'data': {\r\n if (message.channel === 'orderbook') {\r\n // Transform raw Hyperliquid format to SDK OrderBook type\r\n const orderbook = transformOrderbook(message.coin, message.data as Record<string, unknown>);\r\n for (const handler of this.orderbookHandlers) {\r\n handler(message.coin, orderbook);\r\n }\r\n } else if (message.channel === 'trades') {\r\n // Transform raw Hyperliquid format to SDK Trade type\r\n const trades = transformTrades(message.coin, message.data);\r\n for (const handler of this.tradesHandlers) {\r\n handler(message.coin, trades);\r\n }\r\n }\r\n break;\r\n }\r\n }\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/types.ts","../src/http.ts","../src/schemas.ts","../src/orderbook-reconstructor.ts","../src/resources/orderbook.ts","../src/resources/trades.ts","../src/resources/instruments.ts","../src/resources/funding.ts","../src/resources/openinterest.ts","../src/resources/candles.ts","../src/resources/liquidations.ts","../src/resources/data-quality.ts","../src/resources/web3.ts","../src/resources/orders.ts","../src/resources/l4-orderbook.ts","../src/resources/l3-orderbook.ts","../src/exchanges.ts","../src/client.ts","../src/websocket.ts"],"sourcesContent":["/**\r\n * @0xarchive/sdk - Official TypeScript SDK for 0xarchive\r\n *\r\n * Historical Market Data API for multiple exchanges:\r\n * - Hyperliquid (perpetuals data from April 2023)\r\n * - Hyperliquid HIP-3 builder perps (Pro+ only, February 2026+)\r\n * - Lighter.xyz (perpetuals data)\r\n *\r\n * @example\r\n * ```typescript\r\n * import { OxArchive } from '@0xarchive/sdk';\r\n *\r\n * const client = new OxArchive({ apiKey: '0xa_your_api_key' });\r\n *\r\n * // Hyperliquid data\r\n * const hlOrderbook = await client.hyperliquid.orderbook.get('BTC');\r\n *\r\n * // Lighter.xyz data\r\n * const lighterOrderbook = await client.lighter.orderbook.get('BTC');\r\n *\r\n * // Get historical snapshots\r\n * const history = await client.hyperliquid.orderbook.history('ETH', {\r\n * start: Date.now() - 86400000,\r\n * end: Date.now()\r\n * });\r\n * ```\r\n *\r\n * @packageDocumentation\r\n */\r\n\r\n// Main client\r\nexport { OxArchive } from './client';\r\n\r\n// Exchange clients\r\nexport { HyperliquidClient, Hip3Client, LighterClient } from './exchanges';\r\n\r\n// WebSocket client\r\nexport { OxArchiveWs } from './websocket';\r\n\r\n// Orderbook Reconstructor (for tick-level data)\r\nexport {\r\n OrderBookReconstructor,\r\n reconstructOrderBook,\r\n reconstructFinal,\r\n type TickData,\r\n type ReconstructedOrderBook,\r\n type ReconstructOptions,\r\n} from './orderbook-reconstructor';\r\n\r\n// Tick-level history params\r\nexport type { TickHistoryParams } from './resources/orderbook';\r\n\r\n// Zod schemas for runtime validation\r\nexport {\r\n // Base schemas\r\n ApiMetaSchema,\r\n ApiResponseSchema,\r\n // Order Book schemas\r\n PriceLevelSchema,\r\n OrderBookSchema,\r\n OrderBookResponseSchema,\r\n OrderBookArrayResponseSchema,\r\n // Trade schemas\r\n TradeSideSchema,\r\n TradeDirectionSchema,\r\n TradeSchema,\r\n TradeArrayResponseSchema,\r\n // Instrument schemas\r\n InstrumentTypeSchema,\r\n InstrumentSchema,\r\n InstrumentResponseSchema,\r\n InstrumentArrayResponseSchema,\r\n // Funding schemas\r\n FundingRateSchema,\r\n FundingRateResponseSchema,\r\n FundingRateArrayResponseSchema,\r\n // Open Interest schemas\r\n OpenInterestSchema,\r\n OpenInterestResponseSchema,\r\n OpenInterestArrayResponseSchema,\r\n // Candle schemas\r\n CandleIntervalSchema,\r\n CandleSchema,\r\n CandleArrayResponseSchema,\r\n // Liquidation schemas\r\n LiquidationSideSchema,\r\n LiquidationSchema,\r\n LiquidationArrayResponseSchema,\r\n LiquidationVolumeSchema,\r\n LiquidationVolumeArrayResponseSchema,\r\n // Coin Freshness schemas\r\n DataTypeFreshnessInfoSchema,\r\n CoinFreshnessSchema,\r\n CoinFreshnessResponseSchema,\r\n // Coin Summary schemas\r\n CoinSummarySchema,\r\n CoinSummaryResponseSchema,\r\n // Price Snapshot schemas\r\n PriceSnapshotSchema,\r\n PriceSnapshotArrayResponseSchema,\r\n // WebSocket schemas\r\n WsChannelSchema,\r\n WsConnectionStateSchema,\r\n WsServerMessageSchema,\r\n WsSubscribedSchema,\r\n WsUnsubscribedSchema,\r\n WsPongSchema,\r\n WsErrorSchema,\r\n WsDataSchema,\r\n WsReplayStartedSchema,\r\n WsReplayPausedSchema,\r\n WsReplayResumedSchema,\r\n WsReplayCompletedSchema,\r\n WsReplayStoppedSchema,\r\n WsReplaySnapshotSchema,\r\n WsHistoricalDataSchema,\r\n WsStreamStartedSchema,\r\n WsStreamProgressSchema,\r\n TimestampedRecordSchema,\r\n WsHistoricalBatchSchema,\r\n WsStreamCompletedSchema,\r\n WsStreamStoppedSchema,\r\n // Validated types (inferred from schemas)\r\n type ValidatedApiMeta,\r\n type ValidatedPriceLevel,\r\n type ValidatedOrderBook,\r\n type ValidatedTrade,\r\n type ValidatedInstrument,\r\n type ValidatedFundingRate,\r\n type ValidatedOpenInterest,\r\n type ValidatedCandle,\r\n type ValidatedLiquidation,\r\n type ValidatedWsServerMessage,\r\n} from './schemas';\r\n\r\n// Types\r\nexport type {\r\n ClientOptions,\r\n ApiMeta,\r\n ApiResponse,\r\n Timestamp,\r\n // Order Book\r\n PriceLevel,\r\n OrderBook,\r\n GetOrderBookParams,\r\n OrderBookHistoryParams,\r\n LighterGranularity,\r\n // Trades\r\n Trade,\r\n GetTradesCursorParams,\r\n CursorResponse,\r\n TradeSide,\r\n TradeDirection,\r\n // Instruments\r\n Instrument,\r\n LighterInstrument,\r\n Hip3Instrument,\r\n InstrumentType,\r\n // Funding\r\n FundingRate,\r\n FundingHistoryParams,\r\n // Open Interest\r\n OpenInterest,\r\n OpenInterestHistoryParams,\r\n OiFundingInterval,\r\n // Candles\r\n Candle,\r\n CandleInterval,\r\n CandleHistoryParams,\r\n // Liquidations\r\n Liquidation,\r\n LiquidationHistoryParams,\r\n LiquidationsByUserParams,\r\n LiquidationVolume,\r\n LiquidationVolumeParams,\r\n // Coin Freshness\r\n DataTypeFreshnessInfo,\r\n CoinFreshness,\r\n // Coin Summary\r\n CoinSummary,\r\n // Price History\r\n PriceSnapshot,\r\n PriceHistoryParams,\r\n // Data Quality\r\n SystemStatusValue,\r\n ExchangeStatus,\r\n DataTypeStatus,\r\n StatusResponse,\r\n DataTypeCoverage,\r\n ExchangeCoverage,\r\n CoverageResponse,\r\n CoverageGap,\r\n DataCadence,\r\n SymbolDataTypeCoverage,\r\n SymbolCoverageOptions,\r\n SymbolCoverageResponse,\r\n IncidentStatusValue,\r\n IncidentSeverityValue,\r\n Incident,\r\n Pagination,\r\n IncidentsResponse,\r\n WebSocketLatency,\r\n RestApiLatency,\r\n DataFreshness,\r\n ExchangeLatency,\r\n LatencyResponse,\r\n SlaTargets,\r\n CompletenessMetrics,\r\n SlaActual,\r\n SlaResponse,\r\n ListIncidentsParams,\r\n SlaParams,\r\n // Web3 Auth\r\n SiweChallenge,\r\n Web3SignupResult,\r\n Web3ApiKey,\r\n Web3KeysList,\r\n Web3RevokeResult,\r\n Web3PaymentRequired,\r\n Web3SubscribeResult,\r\n // WebSocket\r\n WsChannel,\r\n WsOptions,\r\n WsClientMessage,\r\n WsServerMessage,\r\n WsConnectionState,\r\n WsEventHandlers,\r\n WsSubscribe,\r\n WsUnsubscribe,\r\n WsPing,\r\n WsSubscribed,\r\n WsUnsubscribed,\r\n WsPong,\r\n WsError,\r\n WsData,\r\n // WebSocket Replay (Option B)\r\n WsReplay,\r\n WsReplayPause,\r\n WsReplayResume,\r\n WsReplaySeek,\r\n WsReplayStop,\r\n WsReplayStarted,\r\n WsReplayPaused,\r\n WsReplayResumed,\r\n WsReplayCompleted,\r\n WsReplayStopped,\r\n WsReplaySnapshot,\r\n WsHistoricalData,\r\n WsHistoricalTickData,\r\n OrderbookDelta,\r\n // WebSocket Bulk Stream (Option D)\r\n WsStream,\r\n WsStreamStop,\r\n WsStreamStarted,\r\n WsStreamProgress,\r\n TimestampedRecord,\r\n WsHistoricalBatch,\r\n WsStreamCompleted,\r\n WsStreamStopped,\r\n WsGapDetected,\r\n // L4 WebSocket types\r\n WsL4Snapshot,\r\n WsL4Batch,\r\n // Errors\r\n ApiError,\r\n} from './types';\r\n\r\nexport { OxArchiveError } from './types';\r\n\r\n// Default export for convenience\r\nexport { OxArchive as default } from './client';\r\n","/**\r\n * Configuration options for the 0xarchive client\r\n */\r\nexport interface ClientOptions {\r\n /** Your 0xarchive API key */\r\n apiKey: string;\r\n /** Base URL for the API (defaults to https://api.0xarchive.io) */\r\n baseUrl?: string;\r\n /** Request timeout in milliseconds (defaults to 30000) */\r\n timeout?: number;\r\n /** Enable runtime validation of API responses using Zod schemas (defaults to false) */\r\n validate?: boolean;\r\n}\r\n\r\n/**\r\n * Response metadata\r\n */\r\nexport interface ApiMeta {\r\n /** Number of records returned */\r\n count: number;\r\n /** Cursor for next page (if available) */\r\n nextCursor?: string;\r\n /** Unique request ID for debugging */\r\n requestId: string;\r\n}\r\n\r\n/**\r\n * Standard API response wrapper\r\n */\r\nexport interface ApiResponse<T> {\r\n success: boolean;\r\n data: T;\r\n meta: ApiMeta;\r\n}\r\n\r\n\r\n// =============================================================================\r\n// Order Book Types\r\n// =============================================================================\r\n\r\n/**\r\n * A price level in the order book\r\n */\r\nexport interface PriceLevel {\r\n /** Price at this level */\r\n px: string;\r\n /** Total size at this price level */\r\n sz: string;\r\n /** Number of orders at this level */\r\n n: number;\r\n}\r\n\r\n/**\r\n * Order book snapshot\r\n */\r\nexport interface OrderBook {\r\n /** Trading pair symbol (e.g., BTC, ETH) */\r\n coin: string;\r\n /** Snapshot timestamp (UTC) */\r\n timestamp: string;\r\n /** Bid price levels (best bid first) */\r\n bids: PriceLevel[];\r\n /** Ask price levels (best ask first) */\r\n asks: PriceLevel[];\r\n /** Mid price (best bid + best ask) / 2 */\r\n midPrice?: string;\r\n /** Spread in absolute terms (best ask - best bid) */\r\n spread?: string;\r\n /** Spread in basis points */\r\n spreadBps?: string;\r\n}\r\n\r\nexport interface GetOrderBookParams {\r\n /** Timestamp to get order book at (Unix ms or ISO string) */\r\n timestamp?: number | string;\r\n /** Number of price levels to return per side */\r\n depth?: number;\r\n}\r\n\r\n/**\r\n * Lighter orderbook data granularity levels.\r\n * Controls the resolution of historical orderbook data (Lighter.xyz only).\r\n *\r\n * - 'checkpoint': ~60s intervals (default, all tiers)\r\n * - '30s': 30 second intervals (Build+ tier)\r\n * - '10s': 10 second intervals (Build+ tier)\r\n * - '1s': 1 second intervals (Pro+ tier)\r\n * - 'tick': Checkpoint + raw deltas (Enterprise tier only)\r\n */\r\nexport type LighterGranularity = 'checkpoint' | '30s' | '10s' | '1s' | 'tick';\r\n\r\nexport interface OrderBookHistoryParams extends CursorPaginationParams {\r\n /** Number of price levels to return per side */\r\n depth?: number;\r\n /**\r\n * Data resolution for Lighter orderbook history (Lighter.xyz only, ignored for Hyperliquid).\r\n * Controls the granularity of returned snapshots. Tier restrictions apply.\r\n * Credit multipliers: checkpoint=1x, 30s=2x, 10s=3x, 1s=10x, tick=20x.\r\n * @default 'checkpoint'\r\n */\r\n granularity?: LighterGranularity;\r\n}\r\n\r\n// =============================================================================\r\n// Trade/Fill Types\r\n// =============================================================================\r\n\r\n/** Trade side: 'A' (ask/sell) or 'B' (bid/buy) */\r\nexport type TradeSide = 'A' | 'B';\r\n\r\n/** Position direction (can include 'Open Long', 'Close Short', 'Long > Short', etc.) */\r\nexport type TradeDirection = string;\r\n\r\n/**\r\n * Trade/fill record with full execution details\r\n */\r\nexport interface Trade {\r\n /** Trading pair symbol */\r\n coin: string;\r\n /** Trade side: 'A' (ask/sell) or 'B' (bid/buy) */\r\n side: TradeSide;\r\n /** Execution price */\r\n price: string;\r\n /** Trade size */\r\n size: string;\r\n /** Execution timestamp (UTC) */\r\n timestamp: string;\r\n /** Blockchain transaction hash */\r\n txHash?: string;\r\n /** Unique trade ID */\r\n tradeId?: number;\r\n /** Associated order ID */\r\n orderId?: number;\r\n /** True if taker (crossed the spread), false if maker */\r\n crossed?: boolean;\r\n /** Trading fee amount */\r\n fee?: string;\r\n /** Fee denomination (e.g., USDC) */\r\n feeToken?: string;\r\n /** Realized PnL if closing a position */\r\n closedPnl?: string;\r\n /** Position direction */\r\n direction?: TradeDirection;\r\n /** Position size before this trade */\r\n startPosition?: string;\r\n /** User's wallet address (for fill-level data from REST API) */\r\n userAddress?: string;\r\n /** Maker's wallet address (for market-level WebSocket trades) */\r\n makerAddress?: string;\r\n /** Taker's wallet address (for market-level WebSocket trades) */\r\n takerAddress?: string;\r\n}\r\n\r\n/**\r\n * Cursor-based pagination parameters (recommended)\r\n * More efficient than offset-based pagination for large datasets.\r\n * The cursor is a timestamp - use the `nextCursor` from the response to get the next page.\r\n */\r\nexport interface CursorPaginationParams {\r\n /** Start timestamp (Unix ms or ISO string) - REQUIRED */\r\n start: number | string;\r\n /** End timestamp (Unix ms or ISO string) - REQUIRED */\r\n end: number | string;\r\n /** Cursor from previous response's nextCursor (timestamp). If not provided, starts from the beginning of the range. */\r\n cursor?: number | string;\r\n /** Maximum number of results to return (default: 100, max: 1000) */\r\n limit?: number;\r\n}\r\n\r\n/**\r\n * Parameters for getting trades with cursor-based pagination (recommended)\r\n */\r\nexport interface GetTradesCursorParams extends CursorPaginationParams {\r\n /** Filter by side */\r\n side?: TradeSide;\r\n}\r\n\r\n/**\r\n * Response with cursor for pagination\r\n */\r\nexport interface CursorResponse<T> {\r\n data: T;\r\n /** Cursor for next page (use as cursor parameter) */\r\n nextCursor?: string;\r\n}\r\n\r\n// =============================================================================\r\n// Instruments Types\r\n// =============================================================================\r\n\r\n/** Instrument type */\r\nexport type InstrumentType = 'perp' | 'spot';\r\n\r\n/**\r\n * Trading instrument metadata (Hyperliquid)\r\n */\r\nexport interface Instrument {\r\n /** Instrument symbol (e.g., BTC) */\r\n name: string;\r\n /** Size decimal precision */\r\n szDecimals: number;\r\n /** Maximum leverage allowed */\r\n maxLeverage?: number;\r\n /** If true, only isolated margin mode is allowed */\r\n onlyIsolated?: boolean;\r\n /** Type of instrument */\r\n instrumentType?: InstrumentType;\r\n /** Whether the instrument is currently tradeable */\r\n isActive: boolean;\r\n}\r\n\r\n/**\r\n * Trading instrument metadata (Lighter.xyz)\r\n *\r\n * Lighter instruments have a different schema than Hyperliquid with more\r\n * detailed market configuration including fees and minimum amounts.\r\n */\r\nexport interface LighterInstrument {\r\n /** Instrument symbol (e.g., BTC, ETH) */\r\n symbol: string;\r\n /** Unique market identifier */\r\n marketId: number;\r\n /** Market type (e.g., 'perp') */\r\n marketType: string;\r\n /** Market status (e.g., 'active') */\r\n status: string;\r\n /** Taker fee rate (e.g., 0.0005 = 0.05%) */\r\n takerFee: number;\r\n /** Maker fee rate (e.g., 0.0002 = 0.02%) */\r\n makerFee: number;\r\n /** Liquidation fee rate */\r\n liquidationFee: number;\r\n /** Minimum order size in base currency */\r\n minBaseAmount: number;\r\n /** Minimum order size in quote currency */\r\n minQuoteAmount: number;\r\n /** Size decimal precision */\r\n sizeDecimals: number;\r\n /** Price decimal precision */\r\n priceDecimals: number;\r\n /** Quote currency decimal precision */\r\n quoteDecimals: number;\r\n /** Whether the instrument is currently tradeable */\r\n isActive: boolean;\r\n}\r\n\r\n/**\r\n * HIP-3 Builder Perps instrument with latest market data.\r\n * Derived from live open interest data.\r\n */\r\nexport interface Hip3Instrument {\r\n /** Full coin name (e.g., km:US500, xyz:XYZ100) */\r\n coin: string;\r\n /** Builder namespace (e.g., km, xyz) */\r\n namespace: string;\r\n /** Ticker within the namespace (e.g., US500, XYZ100) */\r\n ticker: string;\r\n /** Latest mark price */\r\n markPrice?: number;\r\n /** Latest open interest */\r\n openInterest?: number;\r\n /** Latest mid price */\r\n midPrice?: number;\r\n /** Timestamp of latest data point */\r\n latestTimestamp?: string;\r\n}\r\n\r\n// =============================================================================\r\n// Funding Types\r\n// =============================================================================\r\n\r\n/**\r\n * Funding rate record\r\n */\r\nexport interface FundingRate {\r\n /** Trading pair symbol */\r\n coin: string;\r\n /** Funding timestamp (UTC) */\r\n timestamp: string;\r\n /** Funding rate as decimal (e.g., 0.0001 = 0.01%) */\r\n fundingRate: string;\r\n /** Premium component of funding rate */\r\n premium?: string;\r\n}\r\n\r\n/**\r\n * Aggregation interval for OI and funding history.\r\n * When omitted, raw ~1 min data is returned.\r\n */\r\nexport type OiFundingInterval = '5m' | '15m' | '30m' | '1h' | '4h' | '1d';\r\n\r\n/**\r\n * Parameters for getting funding rate history\r\n */\r\nexport interface FundingHistoryParams extends CursorPaginationParams {\r\n /** Aggregation interval. When omitted, raw ~1 min data is returned. */\r\n interval?: OiFundingInterval;\r\n}\r\n\r\n// =============================================================================\r\n// Open Interest Types\r\n// =============================================================================\r\n\r\n/**\r\n * Open interest snapshot with market context\r\n */\r\nexport interface OpenInterest {\r\n /** Trading pair symbol */\r\n coin: string;\r\n /** Snapshot timestamp (UTC) */\r\n timestamp: string;\r\n /** Total open interest in contracts */\r\n openInterest: string;\r\n /** Mark price used for liquidations */\r\n markPrice?: string;\r\n /** Oracle price from external feed */\r\n oraclePrice?: string;\r\n /** 24-hour notional volume */\r\n dayNtlVolume?: string;\r\n /** Price 24 hours ago */\r\n prevDayPrice?: string;\r\n /** Current mid price */\r\n midPrice?: string;\r\n /** Impact bid price for liquidations */\r\n impactBidPrice?: string;\r\n /** Impact ask price for liquidations */\r\n impactAskPrice?: string;\r\n}\r\n\r\n/**\r\n * Parameters for getting open interest history\r\n */\r\nexport interface OpenInterestHistoryParams extends CursorPaginationParams {\r\n /** Aggregation interval. When omitted, raw ~1 min data is returned. */\r\n interval?: OiFundingInterval;\r\n}\r\n\r\n// =============================================================================\r\n// Liquidation Types\r\n// =============================================================================\r\n\r\n/**\r\n * Liquidation event record\r\n */\r\nexport interface Liquidation {\r\n /** Trading pair symbol */\r\n coin: string;\r\n /** Liquidation timestamp (UTC) */\r\n timestamp: string;\r\n /** Address of the liquidated user */\r\n liquidatedUser: string;\r\n /** Address of the liquidator */\r\n liquidatorUser: string;\r\n /** Liquidation execution price */\r\n price: string;\r\n /** Liquidation size */\r\n size: string;\r\n /** Side: 'B' (buy) or 'S' (sell) */\r\n side: 'B' | 'S';\r\n /** Mark price at time of liquidation */\r\n markPrice?: string;\r\n /** Realized PnL from the liquidation */\r\n closedPnl?: string;\r\n /** Position direction (e.g., 'Open Long', 'Close Short') */\r\n direction?: string;\r\n /** Unique trade ID */\r\n tradeId?: number;\r\n /** Blockchain transaction hash */\r\n txHash?: string;\r\n}\r\n\r\n/**\r\n * Parameters for getting liquidation history\r\n */\r\nexport interface LiquidationHistoryParams extends CursorPaginationParams {}\r\n\r\n/**\r\n * Parameters for getting liquidations by user\r\n */\r\nexport interface LiquidationsByUserParams extends CursorPaginationParams {\r\n /** Optional coin filter */\r\n coin?: string;\r\n}\r\n\r\n// =============================================================================\r\n// Candle Types\r\n// =============================================================================\r\n\r\n/** Candle interval for OHLCV data */\r\nexport type CandleInterval = '1m' | '5m' | '15m' | '30m' | '1h' | '4h' | '1d' | '1w';\r\n\r\n/**\r\n * OHLCV candle data\r\n */\r\nexport interface Candle {\r\n /** Candle open timestamp (UTC) */\r\n timestamp: string;\r\n /** Opening price */\r\n open: number;\r\n /** Highest price during the interval */\r\n high: number;\r\n /** Lowest price during the interval */\r\n low: number;\r\n /** Closing price */\r\n close: number;\r\n /** Total volume traded during the interval */\r\n volume: number;\r\n /** Total quote volume (volume * price) */\r\n quoteVolume?: number;\r\n /** Number of trades during the interval */\r\n tradeCount?: number;\r\n}\r\n\r\n/**\r\n * Parameters for getting candle history\r\n */\r\nexport interface CandleHistoryParams extends CursorPaginationParams {\r\n /** Candle interval (default: 1h) */\r\n interval?: CandleInterval;\r\n /** Maximum number of results to return (default: 100, max: 10000 for candles) */\r\n limit?: number;\r\n}\r\n\r\n// =============================================================================\r\n// Aggregated Liquidation Volume Types\r\n// =============================================================================\r\n\r\n/** Pre-aggregated liquidation volume bucket */\r\nexport interface LiquidationVolume {\r\n /** Trading pair symbol */\r\n coin: string;\r\n /** Bucket timestamp (UTC) */\r\n timestamp: string;\r\n /** Total liquidation volume in USD (price * size) */\r\n totalUsd: number;\r\n /** Long liquidations volume */\r\n longUsd: number;\r\n /** Short liquidations volume */\r\n shortUsd: number;\r\n /** Total liquidation count */\r\n count: number;\r\n /** Long liquidation count */\r\n longCount: number;\r\n /** Short liquidation count */\r\n shortCount: number;\r\n}\r\n\r\n/** Parameters for getting aggregated liquidation volume */\r\nexport interface LiquidationVolumeParams extends CursorPaginationParams {\r\n /** Aggregation interval (default: 1h). Valid: 5m, 15m, 30m, 1h, 4h, 1d */\r\n interval?: OiFundingInterval;\r\n}\r\n\r\n// =============================================================================\r\n// Per-Coin Freshness Types\r\n// =============================================================================\r\n\r\n/** Freshness data for a single data type */\r\nexport interface DataTypeFreshnessInfo {\r\n /** Last update timestamp */\r\n lastUpdated?: string;\r\n /** Lag in milliseconds */\r\n lagMs?: number;\r\n}\r\n\r\n/** Per-coin freshness across all data types */\r\nexport interface CoinFreshness {\r\n /** Coin symbol */\r\n coin: string;\r\n /** Exchange name */\r\n exchange: string;\r\n /** When this measurement was taken */\r\n measuredAt: string;\r\n /** Orderbook freshness */\r\n orderbook: DataTypeFreshnessInfo;\r\n /** Trades freshness */\r\n trades: DataTypeFreshnessInfo;\r\n /** Funding freshness */\r\n funding: DataTypeFreshnessInfo;\r\n /** Open interest freshness */\r\n openInterest: DataTypeFreshnessInfo;\r\n /** Liquidations freshness (Hyperliquid only) */\r\n liquidations?: DataTypeFreshnessInfo;\r\n}\r\n\r\n// =============================================================================\r\n// Coin Summary Types\r\n// =============================================================================\r\n\r\n/** Combined market summary for a coin */\r\nexport interface CoinSummary {\r\n /** Trading pair symbol */\r\n coin: string;\r\n /** Timestamp (UTC) */\r\n timestamp: string;\r\n /** Latest mark price */\r\n markPrice?: string;\r\n /** Latest oracle price */\r\n oraclePrice?: string;\r\n /** Latest mid price */\r\n midPrice?: string;\r\n /** Current funding rate */\r\n fundingRate?: string;\r\n /** Funding premium */\r\n premium?: string;\r\n /** Current open interest */\r\n openInterest?: string;\r\n /** 24h notional trading volume */\r\n volume24h?: string;\r\n /** 24h total liquidation volume in USD */\r\n liquidationVolume24h?: number;\r\n /** 24h long liquidation volume in USD */\r\n longLiquidationVolume24h?: number;\r\n /** 24h short liquidation volume in USD */\r\n shortLiquidationVolume24h?: number;\r\n}\r\n\r\n// =============================================================================\r\n// Price History Types\r\n// =============================================================================\r\n\r\n/** Price snapshot from OI data */\r\nexport interface PriceSnapshot {\r\n /** Timestamp (UTC) */\r\n timestamp: string;\r\n /** Mark price */\r\n markPrice?: string;\r\n /** Oracle price */\r\n oraclePrice?: string;\r\n /** Mid price */\r\n midPrice?: string;\r\n}\r\n\r\n/** Parameters for price history */\r\nexport interface PriceHistoryParams extends CursorPaginationParams {\r\n /** Aggregation interval. When omitted, raw ~1 min data is returned. */\r\n interval?: OiFundingInterval;\r\n}\r\n\r\n// =============================================================================\r\n// WebSocket Types\r\n// =============================================================================\r\n\r\n/**\r\n * WebSocket channel types.\r\n *\r\n * - ticker/all_tickers: real-time only\r\n * - liquidations: historical only (May 2025+)\r\n * - hip3_liquidations: historical only (Feb 2026+)\r\n * - open_interest, funding, lighter_open_interest, lighter_funding,\r\n * hip3_open_interest, hip3_funding: historical only (replay/stream)\r\n */\r\nexport type WsChannel =\r\n | 'orderbook' | 'trades' | 'candles' | 'liquidations' | 'ticker' | 'all_tickers'\r\n | 'open_interest' | 'funding'\r\n | 'lighter_orderbook' | 'lighter_trades' | 'lighter_candles'\r\n | 'lighter_open_interest' | 'lighter_funding' | 'lighter_l3_orderbook'\r\n | 'hip3_orderbook' | 'hip3_trades' | 'hip3_candles'\r\n | 'hip3_open_interest' | 'hip3_funding' | 'hip3_liquidations'\r\n | 'l4_diffs' | 'l4_orders' | 'hip3_l4_diffs' | 'hip3_l4_orders';\r\n\r\n/** Subscribe message from client */\r\nexport interface WsSubscribe {\r\n op: 'subscribe';\r\n channel: WsChannel;\r\n coin?: string;\r\n}\r\n\r\n/** Unsubscribe message from client */\r\nexport interface WsUnsubscribe {\r\n op: 'unsubscribe';\r\n channel: WsChannel;\r\n coin?: string;\r\n}\r\n\r\n/** Ping message from client */\r\nexport interface WsPing {\r\n op: 'ping';\r\n}\r\n\r\n/** Replay message from client - replays historical data with timing preserved */\r\nexport interface WsReplay {\r\n op: 'replay';\r\n /** Single channel for replay. Mutually exclusive with `channels`. */\r\n channel?: WsChannel;\r\n /** Multiple channels for multi-channel replay. Mutually exclusive with `channel`. */\r\n channels?: WsChannel[];\r\n coin?: string;\r\n /** Start timestamp (Unix ms) */\r\n start: number;\r\n /** End timestamp (Unix ms, defaults to now) */\r\n end?: number;\r\n /** Playback speed multiplier (1 = real-time, 10 = 10x faster) */\r\n speed?: number;\r\n /** Data resolution for Lighter orderbook ('checkpoint', '30s', '10s', '1s', 'tick') */\r\n granularity?: string;\r\n /** Candle interval for candles channel ('1m', '5m', '15m', '30m', '1h', '4h', '1d', '1w') */\r\n interval?: string;\r\n}\r\n\r\n/** Replay control messages */\r\nexport interface WsReplayPause { op: 'replay.pause'; }\r\nexport interface WsReplayResume { op: 'replay.resume'; }\r\nexport interface WsReplaySeek { op: 'replay.seek'; timestamp: number; }\r\nexport interface WsReplayStop { op: 'replay.stop'; }\r\n\r\n/** Stream message from client - bulk download historical data */\r\nexport interface WsStream {\r\n op: 'stream';\r\n /** Single channel for streaming. Mutually exclusive with `channels`. */\r\n channel?: WsChannel;\r\n /** Multiple channels for multi-channel streaming. Mutually exclusive with `channel`. */\r\n channels?: WsChannel[];\r\n coin?: string;\r\n /** Start timestamp (Unix ms) */\r\n start: number;\r\n /** End timestamp (Unix ms) */\r\n end: number;\r\n /** Batch size (records per message) */\r\n batch_size?: number;\r\n /** Data resolution for Lighter orderbook ('checkpoint', '30s', '10s', '1s', 'tick') */\r\n granularity?: string;\r\n /** Candle interval for candles channel ('1m', '5m', '15m', '30m', '1h', '4h', '1d', '1w') */\r\n interval?: string;\r\n}\r\n\r\n/** Stream control messages */\r\nexport interface WsStreamStop { op: 'stream.stop'; }\r\n\r\n/** Client message union type */\r\nexport type WsClientMessage =\r\n | WsSubscribe\r\n | WsUnsubscribe\r\n | WsPing\r\n | WsReplay\r\n | WsReplayPause\r\n | WsReplayResume\r\n | WsReplaySeek\r\n | WsReplayStop\r\n | WsStream\r\n | WsStreamStop;\r\n\r\n/** Subscription confirmed from server */\r\nexport interface WsSubscribed {\r\n type: 'subscribed';\r\n channel: WsChannel;\r\n coin?: string;\r\n}\r\n\r\n/** Unsubscription confirmed from server */\r\nexport interface WsUnsubscribed {\r\n type: 'unsubscribed';\r\n channel: WsChannel;\r\n coin?: string;\r\n}\r\n\r\n/** Pong response from server */\r\nexport interface WsPong {\r\n type: 'pong';\r\n}\r\n\r\n/** Error from server */\r\nexport interface WsError {\r\n type: 'error';\r\n message: string;\r\n}\r\n\r\n/** Data message from server (real-time) */\r\nexport interface WsData<T = unknown> {\r\n type: 'data';\r\n channel: WsChannel;\r\n coin: string;\r\n data: T;\r\n}\r\n\r\n/** Replay started response */\r\nexport interface WsReplayStarted {\r\n type: 'replay_started';\r\n channel: WsChannel;\r\n coin: string;\r\n /** Start timestamp in milliseconds */\r\n start: number;\r\n /** End timestamp in milliseconds */\r\n end: number;\r\n /** Playback speed multiplier */\r\n speed: number;\r\n}\r\n\r\n/** Replay paused response */\r\nexport interface WsReplayPaused {\r\n type: 'replay_paused';\r\n current_timestamp: number;\r\n}\r\n\r\n/** Replay resumed response */\r\nexport interface WsReplayResumed {\r\n type: 'replay_resumed';\r\n current_timestamp: number;\r\n}\r\n\r\n/** Replay completed response */\r\nexport interface WsReplayCompleted {\r\n type: 'replay_completed';\r\n channel: WsChannel;\r\n coin: string;\r\n snapshots_sent: number;\r\n}\r\n\r\n/** Replay stopped response */\r\nexport interface WsReplayStopped {\r\n type: 'replay_stopped';\r\n}\r\n\r\n/** Historical data point (replay mode) */\r\nexport interface WsHistoricalData<T = unknown> {\r\n type: 'historical_data';\r\n channel: WsChannel;\r\n coin: string;\r\n timestamp: number;\r\n data: T;\r\n}\r\n\r\n/**\r\n * Replay snapshot providing initial state for a channel before the timeline starts.\r\n * Sent in multi-channel replay/stream mode to provide the most recent data point\r\n * for each channel at the replay start time. This allows clients to initialize\r\n * their state (e.g., current orderbook, latest funding rate) before timeline\r\n * data begins arriving via `historical_data` messages.\r\n */\r\nexport interface WsReplaySnapshot<T = unknown> {\r\n type: 'replay_snapshot';\r\n channel: WsChannel;\r\n coin: string;\r\n timestamp: number;\r\n data: T;\r\n}\r\n\r\n/** Orderbook delta for tick-level data */\r\nexport interface OrderbookDelta {\r\n /** Timestamp in milliseconds */\r\n timestamp: number;\r\n /** Side: 'bid' or 'ask' */\r\n side: 'bid' | 'ask';\r\n /** Price level */\r\n price: number;\r\n /** New size (0 = level removed) */\r\n size: number;\r\n /** Sequence number for ordering */\r\n sequence: number;\r\n}\r\n\r\n/** Historical tick data (granularity='tick' mode) - checkpoint + deltas */\r\nexport interface WsHistoricalTickData {\r\n type: 'historical_tick_data';\r\n channel: WsChannel;\r\n coin: string;\r\n /** Initial checkpoint (full orderbook snapshot) */\r\n checkpoint: OrderBook;\r\n /** Incremental deltas to apply after checkpoint */\r\n deltas: OrderbookDelta[];\r\n}\r\n\r\n/** Stream started response */\r\nexport interface WsStreamStarted {\r\n type: 'stream_started';\r\n channel: WsChannel;\r\n coin: string;\r\n /** Start timestamp in milliseconds */\r\n start: number;\r\n /** End timestamp in milliseconds */\r\n end: number;\r\n}\r\n\r\n/** Stream progress response (sent periodically during streaming) */\r\nexport interface WsStreamProgress {\r\n type: 'stream_progress';\r\n snapshots_sent: number;\r\n}\r\n\r\n/** A record with timestamp for batched data */\r\nexport interface TimestampedRecord<T = unknown> {\r\n timestamp: number;\r\n data: T;\r\n}\r\n\r\n/** Batch of historical data (bulk streaming) */\r\nexport interface WsHistoricalBatch<T = unknown> {\r\n type: 'historical_batch';\r\n channel: WsChannel;\r\n coin: string;\r\n data: TimestampedRecord<T>[];\r\n}\r\n\r\n/** Stream completed response */\r\nexport interface WsStreamCompleted {\r\n type: 'stream_completed';\r\n channel: WsChannel;\r\n coin: string;\r\n snapshots_sent: number;\r\n}\r\n\r\n/** Stream stopped response */\r\nexport interface WsStreamStopped {\r\n type: 'stream_stopped';\r\n snapshots_sent: number;\r\n}\r\n\r\n/**\r\n * Gap detected in historical data stream.\r\n * Sent when there's a gap exceeding the threshold between consecutive data points.\r\n * Thresholds: 2 minutes for orderbook/candles/liquidations, 60 minutes for trades.\r\n */\r\nexport interface WsGapDetected {\r\n type: 'gap_detected';\r\n channel: WsChannel;\r\n coin: string;\r\n /** Start of the gap (last data point timestamp in ms) */\r\n gap_start: number;\r\n /** End of the gap (next data point timestamp in ms) */\r\n gap_end: number;\r\n /** Gap duration in minutes */\r\n duration_minutes: number;\r\n}\r\n\r\n/** L4 snapshot (sent on l4_diffs/hip3_l4_diffs subscription) */\r\nexport interface WsL4Snapshot {\r\n type: 'l4_snapshot';\r\n channel: WsChannel;\r\n coin: string;\r\n last_block_number: number;\r\n timestamp: number;\r\n data: any;\r\n}\r\n\r\n/** L4 batched data (all L4 channels) */\r\nexport interface WsL4Batch {\r\n type: 'l4_batch';\r\n channel: WsChannel;\r\n coin: string;\r\n data: any[];\r\n}\r\n\r\n/** Server message union type */\r\nexport type WsServerMessage =\r\n | WsSubscribed\r\n | WsUnsubscribed\r\n | WsPong\r\n | WsError\r\n | WsData\r\n | WsReplayStarted\r\n | WsReplayPaused\r\n | WsReplayResumed\r\n | WsReplayCompleted\r\n | WsReplayStopped\r\n | WsReplaySnapshot\r\n | WsHistoricalData\r\n | WsHistoricalTickData\r\n | WsStreamStarted\r\n | WsStreamProgress\r\n | WsHistoricalBatch\r\n | WsStreamCompleted\r\n | WsStreamStopped\r\n | WsGapDetected\r\n | WsL4Snapshot\r\n | WsL4Batch;\r\n\r\n/**\r\n * WebSocket connection options.\r\n *\r\n * The server sends WebSocket ping frames every 30 seconds and will disconnect\r\n * idle connections after 60 seconds. The SDK automatically handles keep-alive\r\n * by sending application-level pings at the configured interval.\r\n */\r\nexport interface WsOptions {\r\n /** API key for authentication */\r\n apiKey: string;\r\n /** WebSocket URL (defaults to wss://api.0xarchive.io/ws) */\r\n wsUrl?: string;\r\n /** Auto-reconnect on disconnect (defaults to true) */\r\n autoReconnect?: boolean;\r\n /** Reconnect delay in ms (defaults to 1000) */\r\n reconnectDelay?: number;\r\n /** Maximum reconnect attempts (defaults to 10) */\r\n maxReconnectAttempts?: number;\r\n /** Ping interval in ms to keep connection alive (defaults to 30000). Server disconnects after 60s idle. */\r\n pingInterval?: number;\r\n}\r\n\r\n/** WebSocket connection state */\r\nexport type WsConnectionState = 'connecting' | 'connected' | 'disconnected' | 'reconnecting';\r\n\r\n/** WebSocket event handlers */\r\nexport interface WsEventHandlers {\r\n onOpen?: () => void;\r\n onClose?: (code: number, reason: string) => void;\r\n onError?: (error: Error) => void;\r\n onMessage?: (message: WsServerMessage) => void;\r\n onStateChange?: (state: WsConnectionState) => void;\r\n}\r\n\r\n// =============================================================================\r\n// Web3 Authentication Types\r\n// =============================================================================\r\n\r\n/** SIWE challenge message returned by the challenge endpoint */\r\nexport interface SiweChallenge {\r\n /** The SIWE message to sign with personal_sign (EIP-191) */\r\n message: string;\r\n /** Single-use nonce (expires after 10 minutes) */\r\n nonce: string;\r\n}\r\n\r\n/** Result of creating a free-tier account via wallet signature */\r\nexport interface Web3SignupResult {\r\n /** The generated API key */\r\n apiKey: string;\r\n /** Account tier (e.g., 'free') */\r\n tier: string;\r\n /** The wallet address that owns this key */\r\n walletAddress: string;\r\n}\r\n\r\n/** An API key record returned by the keys endpoint */\r\nexport interface Web3ApiKey {\r\n /** Unique key ID (UUID) */\r\n id: string;\r\n /** Key name */\r\n name: string;\r\n /** First characters of the key for identification */\r\n keyPrefix: string;\r\n /** Whether the key is currently active */\r\n isActive: boolean;\r\n /** Last usage timestamp (ISO 8601) */\r\n lastUsedAt?: string;\r\n /** Creation timestamp (ISO 8601) */\r\n createdAt: string;\r\n}\r\n\r\n/** List of API keys for a wallet */\r\nexport interface Web3KeysList {\r\n /** All API keys belonging to this wallet */\r\n keys: Web3ApiKey[];\r\n /** The wallet address */\r\n walletAddress: string;\r\n}\r\n\r\n/** Result of revoking an API key */\r\nexport interface Web3RevokeResult {\r\n /** Confirmation message */\r\n message: string;\r\n /** The wallet address that owned the key */\r\n walletAddress: string;\r\n}\r\n\r\n/** x402 payment details returned by subscribe (402 response) */\r\nexport interface Web3PaymentRequired {\r\n /** Amount in smallest unit (e.g., \"49000000\" for $49 USDC) */\r\n amount: string;\r\n /** Payment asset (e.g., \"USDC\") */\r\n asset: string;\r\n /** Blockchain network (e.g., \"base\") */\r\n network: string;\r\n /** Address to send payment to */\r\n payTo: string;\r\n /** Token contract address */\r\n assetAddress: string;\r\n}\r\n\r\n/** Result of a successful x402 subscription */\r\nexport interface Web3SubscribeResult {\r\n /** The generated API key */\r\n apiKey: string;\r\n /** Subscription tier */\r\n tier: string;\r\n /** Expiration timestamp (ISO 8601) */\r\n expiresAt: string;\r\n /** The wallet address that owns the subscription */\r\n walletAddress: string;\r\n /** On-chain transaction hash */\r\n txHash?: string;\r\n}\r\n\r\n// =============================================================================\r\n// Error Types\r\n// =============================================================================\r\n\r\n/**\r\n * API error response\r\n */\r\nexport interface ApiError {\r\n code: number;\r\n error: string;\r\n}\r\n\r\n/**\r\n * SDK error class\r\n */\r\nexport class OxArchiveError extends Error {\r\n code: number;\r\n requestId?: string;\r\n\r\n constructor(message: string, code: number, requestId?: string) {\r\n super(message);\r\n this.name = 'OxArchiveError';\r\n this.code = code;\r\n this.requestId = requestId;\r\n }\r\n}\r\n\r\n/** Timestamp can be Unix ms (number), ISO string, or Date object */\r\nexport type Timestamp = number | string | Date;\r\n\r\n// =============================================================================\r\n// Data Quality Types\r\n// =============================================================================\r\n\r\n/** System status values */\r\nexport type SystemStatusValue = 'operational' | 'degraded' | 'outage' | 'maintenance';\r\n\r\n/** Status of a single exchange */\r\nexport interface ExchangeStatus {\r\n /** Current status */\r\n status: SystemStatusValue;\r\n /** Timestamp of last received data */\r\n lastDataAt?: string;\r\n /** Current latency in milliseconds */\r\n latencyMs?: number;\r\n}\r\n\r\n/** Status of a data type (orderbook, fills, etc.) */\r\nexport interface DataTypeStatus {\r\n /** Current status */\r\n status: SystemStatusValue;\r\n /** Data completeness over last 24 hours (0-100) */\r\n completeness24h: number;\r\n}\r\n\r\n/** Overall system status response */\r\nexport interface StatusResponse {\r\n /** Overall system status */\r\n status: SystemStatusValue;\r\n /** When this status was computed */\r\n updatedAt: string;\r\n /** Per-exchange status */\r\n exchanges: Record<string, ExchangeStatus>;\r\n /** Per-data-type status */\r\n dataTypes: Record<string, DataTypeStatus>;\r\n /** Number of active incidents */\r\n activeIncidents: number;\r\n}\r\n\r\n/** Coverage information for a specific data type */\r\nexport interface DataTypeCoverage {\r\n /** Earliest available data timestamp */\r\n earliest: string;\r\n /** Latest available data timestamp */\r\n latest: string;\r\n /** Total number of records */\r\n totalRecords: number;\r\n /** Number of symbols with data */\r\n symbols: number;\r\n /** Data resolution (e.g., '1.2s', '1m') */\r\n resolution?: string;\r\n /** Current data lag */\r\n lag?: string;\r\n /** Completeness percentage (0-100) */\r\n completeness: number;\r\n}\r\n\r\n/** Coverage for a single exchange */\r\nexport interface ExchangeCoverage {\r\n /** Exchange name */\r\n exchange: string;\r\n /** Coverage per data type */\r\n dataTypes: Record<string, DataTypeCoverage>;\r\n}\r\n\r\n/** Overall coverage response */\r\nexport interface CoverageResponse {\r\n /** Coverage for all exchanges */\r\n exchanges: ExchangeCoverage[];\r\n}\r\n\r\n/** Gap information for per-symbol coverage */\r\nexport interface CoverageGap {\r\n /** Start of the gap (last data before gap) */\r\n start: string;\r\n /** End of the gap (first data after gap) */\r\n end: string;\r\n /** Duration of the gap in minutes */\r\n durationMinutes: number;\r\n}\r\n\r\n/** Empirical data cadence measurement based on last 7 days of data */\r\nexport interface DataCadence {\r\n /** Median interval between consecutive records in seconds */\r\n medianIntervalSeconds: number;\r\n /** 95th percentile interval between consecutive records in seconds */\r\n p95IntervalSeconds: number;\r\n /** Number of intervals sampled for this measurement */\r\n sampleCount: number;\r\n}\r\n\r\n/** Coverage for a specific symbol and data type */\r\nexport interface SymbolDataTypeCoverage {\r\n /** Earliest available data timestamp */\r\n earliest: string;\r\n /** Latest available data timestamp */\r\n latest: string;\r\n /** Total number of records */\r\n totalRecords: number;\r\n /** 24-hour completeness percentage (0-100) */\r\n completeness: number;\r\n /** Historical coverage percentage (0-100) based on hours with data / total hours */\r\n historicalCoverage?: number;\r\n /** Detected data gaps within the requested time window */\r\n gaps: CoverageGap[];\r\n /** Empirical data cadence (present when sufficient data exists) */\r\n cadence?: DataCadence;\r\n}\r\n\r\n/** Options for symbol coverage query */\r\nexport interface SymbolCoverageOptions {\r\n /** Start of gap detection window (Unix milliseconds). Default: now - 30 days */\r\n from?: number;\r\n /** End of gap detection window (Unix milliseconds). Default: now */\r\n to?: number;\r\n}\r\n\r\n/** Per-symbol coverage response */\r\nexport interface SymbolCoverageResponse {\r\n /** Exchange name */\r\n exchange: string;\r\n /** Symbol name */\r\n symbol: string;\r\n /** Coverage per data type */\r\n dataTypes: Record<string, SymbolDataTypeCoverage>;\r\n}\r\n\r\n/** Incident status values */\r\nexport type IncidentStatusValue = 'open' | 'investigating' | 'identified' | 'monitoring' | 'resolved';\r\n\r\n/** Incident severity values */\r\nexport type IncidentSeverityValue = 'minor' | 'major' | 'critical';\r\n\r\n/** Data quality incident */\r\nexport interface Incident {\r\n /** Unique incident ID */\r\n id: string;\r\n /** Status: open, investigating, identified, monitoring, resolved */\r\n status: string;\r\n /** Severity: minor, major, critical */\r\n severity: string;\r\n /** Affected exchange (if specific to one) */\r\n exchange?: string;\r\n /** Affected data types */\r\n dataTypes: string[];\r\n /** Affected symbols */\r\n symbolsAffected: string[];\r\n /** When the incident started */\r\n startedAt: string;\r\n /** When the incident was resolved */\r\n resolvedAt?: string;\r\n /** Total duration in minutes */\r\n durationMinutes?: number;\r\n /** Incident title */\r\n title: string;\r\n /** Detailed description */\r\n description?: string;\r\n /** Root cause analysis */\r\n rootCause?: string;\r\n /** Resolution details */\r\n resolution?: string;\r\n /** Number of records affected */\r\n recordsAffected?: number;\r\n /** Number of records recovered */\r\n recordsRecovered?: number;\r\n}\r\n\r\n/** Pagination info for incident list */\r\nexport interface Pagination {\r\n /** Total number of incidents */\r\n total: number;\r\n /** Page size limit */\r\n limit: number;\r\n /** Current offset */\r\n offset: number;\r\n}\r\n\r\n/** Incidents list response */\r\nexport interface IncidentsResponse {\r\n /** List of incidents */\r\n incidents: Incident[];\r\n /** Pagination info */\r\n pagination: Pagination;\r\n}\r\n\r\n/** WebSocket latency metrics */\r\nexport interface WebSocketLatency {\r\n /** Current latency */\r\n currentMs: number;\r\n /** 1-hour average latency */\r\n avg1hMs: number;\r\n /** 24-hour average latency */\r\n avg24hMs: number;\r\n /** 24-hour P99 latency */\r\n p9924hMs?: number;\r\n}\r\n\r\n/** REST API latency metrics */\r\nexport interface RestApiLatency {\r\n /** Current latency */\r\n currentMs: number;\r\n /** 1-hour average latency */\r\n avg1hMs: number;\r\n /** 24-hour average latency */\r\n avg24hMs: number;\r\n}\r\n\r\n/** Data freshness metrics (lag from source) */\r\nexport interface DataFreshness {\r\n /** Orderbook data lag */\r\n orderbookLagMs?: number;\r\n /** Fills/trades data lag */\r\n fillsLagMs?: number;\r\n /** Funding rate data lag */\r\n fundingLagMs?: number;\r\n /** Open interest data lag */\r\n oiLagMs?: number;\r\n}\r\n\r\n/** Latency metrics for a single exchange */\r\nexport interface ExchangeLatency {\r\n /** WebSocket latency metrics */\r\n websocket?: WebSocketLatency;\r\n /** REST API latency metrics */\r\n restApi?: RestApiLatency;\r\n /** Data freshness metrics */\r\n dataFreshness: DataFreshness;\r\n}\r\n\r\n/** Overall latency response */\r\nexport interface LatencyResponse {\r\n /** When these metrics were measured */\r\n measuredAt: string;\r\n /** Per-exchange latency metrics */\r\n exchanges: Record<string, ExchangeLatency>;\r\n}\r\n\r\n/** SLA targets */\r\nexport interface SlaTargets {\r\n /** Uptime target percentage */\r\n uptime: number;\r\n /** Data completeness target percentage */\r\n dataCompleteness: number;\r\n /** API P99 latency target in milliseconds */\r\n apiLatencyP99Ms: number;\r\n}\r\n\r\n/** Completeness metrics per data type */\r\nexport interface CompletenessMetrics {\r\n /** Orderbook completeness percentage */\r\n orderbook: number;\r\n /** Fills completeness percentage */\r\n fills: number;\r\n /** Funding rate completeness percentage */\r\n funding: number;\r\n /** Overall completeness percentage */\r\n overall: number;\r\n}\r\n\r\n/** Actual SLA metrics */\r\nexport interface SlaActual {\r\n /** Actual uptime percentage */\r\n uptime: number;\r\n /** 'met' or 'missed' */\r\n uptimeStatus: string;\r\n /** Actual completeness metrics */\r\n dataCompleteness: CompletenessMetrics;\r\n /** 'met' or 'missed' */\r\n completenessStatus: string;\r\n /** Actual API P99 latency */\r\n apiLatencyP99Ms: number;\r\n /** 'met' or 'missed' */\r\n latencyStatus: string;\r\n}\r\n\r\n/** SLA compliance response */\r\nexport interface SlaResponse {\r\n /** Period covered (e.g., '2026-01') */\r\n period: string;\r\n /** Target SLA metrics */\r\n slaTargets: SlaTargets;\r\n /** Actual SLA metrics */\r\n actual: SlaActual;\r\n /** Number of incidents in this period */\r\n incidentsThisPeriod: number;\r\n /** Total downtime in minutes */\r\n totalDowntimeMinutes: number;\r\n}\r\n\r\n/** Parameters for listing incidents */\r\nexport interface ListIncidentsParams {\r\n /** Filter by incident status */\r\n status?: IncidentStatusValue;\r\n /** Filter by exchange */\r\n exchange?: string;\r\n /** Only show incidents starting after this timestamp (Unix ms) */\r\n since?: number | string;\r\n /** Maximum results per page (default: 20, max: 100) */\r\n limit?: number;\r\n /** Pagination offset */\r\n offset?: number;\r\n}\r\n\r\n/** Parameters for getting SLA metrics */\r\nexport interface SlaParams {\r\n /** Year (defaults to current year) */\r\n year?: number;\r\n /** Month 1-12 (defaults to current month) */\r\n month?: number;\r\n}\r\n","import type { z } from 'zod';\r\nimport type { ApiResponse, ApiError } from './types';\r\nimport { OxArchiveError } from './types';\r\n\r\n/**\r\n * Convert a snake_case string to camelCase\r\n * @internal Exported for testing\r\n */\r\nexport function snakeToCamel(str: string): string {\r\n return str.replace(/_([a-z0-9])/g, (_, char) => char.toUpperCase());\r\n}\r\n\r\n/**\r\n * Recursively transform all object keys from snake_case to camelCase\r\n * @internal Exported for testing\r\n */\r\nexport function transformKeys(obj: unknown): unknown {\r\n if (obj === null || obj === undefined) {\r\n return obj;\r\n }\r\n\r\n if (Array.isArray(obj)) {\r\n return obj.map(transformKeys);\r\n }\r\n\r\n if (typeof obj === 'object') {\r\n const result: Record<string, unknown> = {};\r\n for (const [key, value] of Object.entries(obj as Record<string, unknown>)) {\r\n result[snakeToCamel(key)] = transformKeys(value);\r\n }\r\n return result;\r\n }\r\n\r\n return obj;\r\n}\r\n\r\nexport interface HttpClientOptions {\r\n baseUrl: string;\r\n apiKey: string;\r\n timeout: number;\r\n /** Enable runtime validation of API responses using Zod schemas (default: false) */\r\n validate?: boolean;\r\n}\r\n\r\n/**\r\n * Internal HTTP client for making API requests\r\n */\r\nexport class HttpClient {\r\n private baseUrl: string;\r\n private apiKey: string;\r\n private timeout: number;\r\n private validate: boolean;\r\n\r\n constructor(options: HttpClientOptions) {\r\n this.baseUrl = options.baseUrl.replace(/\\/$/, '');\r\n this.apiKey = options.apiKey;\r\n this.timeout = options.timeout;\r\n this.validate = options.validate ?? false;\r\n }\r\n\r\n /** Whether validation is enabled */\r\n get validationEnabled(): boolean {\r\n return this.validate;\r\n }\r\n\r\n /** Base URL for raw requests (used by web3 subscribe) */\r\n getBaseUrl(): string {\r\n return this.baseUrl;\r\n }\r\n\r\n /** Timeout in ms for raw requests (used by web3 subscribe) */\r\n getTimeout(): number {\r\n return this.timeout;\r\n }\r\n\r\n /**\r\n * Make a GET request to the API\r\n *\r\n * @param path - API endpoint path\r\n * @param params - Query parameters\r\n * @param schema - Optional Zod schema for validation (used when validation is enabled)\r\n */\r\n async get<T>(\r\n path: string,\r\n params?: Record<string, unknown>,\r\n schema?: z.ZodType<T>\r\n ): Promise<T> {\r\n const url = new URL(`${this.baseUrl}${path}`);\r\n\r\n if (params) {\r\n for (const [key, value] of Object.entries(params)) {\r\n if (value !== undefined && value !== null) {\r\n // Convert Date objects to Unix milliseconds\r\n if (value instanceof Date) {\r\n url.searchParams.set(key, String(value.getTime()));\r\n } else {\r\n url.searchParams.set(key, String(value));\r\n }\r\n }\r\n }\r\n }\r\n\r\n const controller = new AbortController();\r\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\r\n\r\n try {\r\n const response = await fetch(url.toString(), {\r\n method: 'GET',\r\n headers: {\r\n 'X-API-Key': this.apiKey,\r\n 'Content-Type': 'application/json',\r\n },\r\n signal: controller.signal,\r\n });\r\n\r\n clearTimeout(timeoutId);\r\n\r\n const rawData = await response.json();\r\n // Transform snake_case keys to camelCase for JavaScript conventions\r\n const data = transformKeys(rawData) as Record<string, unknown>;\r\n\r\n if (!response.ok) {\r\n const error = data as unknown as ApiError;\r\n const apiResponse = data as unknown as ApiResponse<unknown>;\r\n throw new OxArchiveError(\r\n error.error || `Request failed with status ${response.status}`,\r\n response.status,\r\n apiResponse.meta?.requestId\r\n );\r\n }\r\n\r\n // Validate response if validation is enabled and schema is provided\r\n if (this.validate && schema) {\r\n const result = schema.safeParse(data);\r\n if (!result.success) {\r\n const apiResponse = data as unknown as ApiResponse<unknown>;\r\n throw new OxArchiveError(\r\n `Response validation failed: ${result.error.message}`,\r\n 422,\r\n apiResponse.meta?.requestId\r\n );\r\n }\r\n return result.data;\r\n }\r\n\r\n return data as T;\r\n } catch (error) {\r\n clearTimeout(timeoutId);\r\n\r\n if (error instanceof OxArchiveError) {\r\n throw error;\r\n }\r\n\r\n if (error instanceof Error && error.name === 'AbortError') {\r\n throw new OxArchiveError(`Request timeout after ${this.timeout}ms`, 408);\r\n }\r\n\r\n throw new OxArchiveError(\r\n error instanceof Error ? error.message : 'Unknown error',\r\n 500\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Make a POST request to the API\r\n *\r\n * @param path - API endpoint path\r\n * @param body - JSON request body\r\n * @param schema - Optional Zod schema for validation (used when validation is enabled)\r\n */\r\n async post<T>(\r\n path: string,\r\n body?: Record<string, unknown>,\r\n schema?: z.ZodType<T>\r\n ): Promise<T> {\r\n const url = `${this.baseUrl}${path}`;\r\n\r\n const controller = new AbortController();\r\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\r\n\r\n try {\r\n const response = await fetch(url, {\r\n method: 'POST',\r\n headers: {\r\n 'X-API-Key': this.apiKey,\r\n 'Content-Type': 'application/json',\r\n },\r\n body: body ? JSON.stringify(body) : undefined,\r\n signal: controller.signal,\r\n });\r\n\r\n clearTimeout(timeoutId);\r\n\r\n const rawData = await response.json();\r\n const data = transformKeys(rawData) as Record<string, unknown>;\r\n\r\n if (!response.ok) {\r\n const error = data as unknown as ApiError;\r\n const apiResponse = data as unknown as ApiResponse<unknown>;\r\n throw new OxArchiveError(\r\n error.error || `Request failed with status ${response.status}`,\r\n response.status,\r\n apiResponse.meta?.requestId\r\n );\r\n }\r\n\r\n if (this.validate && schema) {\r\n const result = schema.safeParse(data);\r\n if (!result.success) {\r\n const apiResponse = data as unknown as ApiResponse<unknown>;\r\n throw new OxArchiveError(\r\n `Response validation failed: ${result.error.message}`,\r\n 422,\r\n apiResponse.meta?.requestId\r\n );\r\n }\r\n return result.data;\r\n }\r\n\r\n return data as T;\r\n } catch (error) {\r\n clearTimeout(timeoutId);\r\n\r\n if (error instanceof OxArchiveError) {\r\n throw error;\r\n }\r\n\r\n if (error instanceof Error && error.name === 'AbortError') {\r\n throw new OxArchiveError(`Request timeout after ${this.timeout}ms`, 408);\r\n }\r\n\r\n throw new OxArchiveError(\r\n error instanceof Error ? error.message : 'Unknown error',\r\n 500\r\n );\r\n }\r\n }\r\n}\r\n","/**\r\n * Zod schemas for runtime validation of API responses\r\n *\r\n * @example\r\n * ```typescript\r\n * import { OrderBookSchema, TradeSchema } from '@0xarchive/sdk';\r\n *\r\n * // Validate data manually\r\n * const result = OrderBookSchema.safeParse(data);\r\n * if (result.success) {\r\n * console.log(result.data.midPrice);\r\n * } else {\r\n * console.error(result.error);\r\n * }\r\n * ```\r\n */\r\n\r\nimport { z } from 'zod';\r\n\r\n// =============================================================================\r\n// Base Schemas\r\n// =============================================================================\r\n\r\nexport const ApiMetaSchema = z.object({\r\n count: z.number(),\r\n nextCursor: z.string().optional(),\r\n requestId: z.string(),\r\n});\r\n\r\nexport const ApiResponseSchema = <T extends z.ZodTypeAny>(dataSchema: T) =>\r\n z.object({\r\n success: z.boolean(),\r\n data: dataSchema,\r\n meta: ApiMetaSchema,\r\n });\r\n\r\n// =============================================================================\r\n// Order Book Schemas\r\n// =============================================================================\r\n\r\nexport const PriceLevelSchema = z.object({\r\n px: z.string(),\r\n sz: z.string(),\r\n n: z.number(),\r\n});\r\n\r\nexport const OrderBookSchema = z.object({\r\n coin: z.string(),\r\n timestamp: z.string(),\r\n bids: z.array(PriceLevelSchema),\r\n asks: z.array(PriceLevelSchema),\r\n midPrice: z.string().optional(),\r\n spread: z.string().optional(),\r\n spreadBps: z.string().optional(),\r\n});\r\n\r\n// =============================================================================\r\n// Trade/Fill Schemas\r\n// =============================================================================\r\n\r\nexport const TradeSideSchema = z.enum(['A', 'B']);\r\n\r\n// Direction can include 'Open Long', 'Close Short', 'Long > Short', etc.\r\nexport const TradeDirectionSchema = z.string();\r\n\r\nexport const TradeSchema = z.object({\r\n coin: z.string(),\r\n side: TradeSideSchema,\r\n price: z.string(),\r\n size: z.string(),\r\n timestamp: z.string(),\r\n txHash: z.string().optional(),\r\n tradeId: z.number().optional(),\r\n orderId: z.number().optional(),\r\n crossed: z.boolean().optional(),\r\n fee: z.string().optional(),\r\n feeToken: z.string().optional(),\r\n closedPnl: z.string().optional(),\r\n direction: TradeDirectionSchema.optional(),\r\n startPosition: z.string().optional(),\r\n userAddress: z.string().optional(),\r\n makerAddress: z.string().optional(),\r\n takerAddress: z.string().optional(),\r\n});\r\n\r\n// =============================================================================\r\n// Instrument Schemas\r\n// =============================================================================\r\n\r\nexport const InstrumentTypeSchema = z.enum(['perp', 'spot']);\r\n\r\nexport const InstrumentSchema = z.object({\r\n name: z.string(),\r\n szDecimals: z.number(),\r\n maxLeverage: z.number().optional(),\r\n onlyIsolated: z.boolean().optional(),\r\n instrumentType: InstrumentTypeSchema.optional(),\r\n isActive: z.boolean(),\r\n});\r\n\r\n// =============================================================================\r\n// Funding Schemas\r\n// =============================================================================\r\n\r\nexport const FundingRateSchema = z.object({\r\n coin: z.string(),\r\n timestamp: z.string(),\r\n fundingRate: z.string(),\r\n premium: z.string().optional(),\r\n});\r\n\r\n// =============================================================================\r\n// Open Interest Schemas\r\n// =============================================================================\r\n\r\nexport const OpenInterestSchema = z.object({\r\n coin: z.string(),\r\n timestamp: z.string(),\r\n openInterest: z.string(),\r\n markPrice: z.string().optional(),\r\n oraclePrice: z.string().optional(),\r\n dayNtlVolume: z.string().optional(),\r\n prevDayPrice: z.string().optional(),\r\n midPrice: z.string().optional(),\r\n impactBidPrice: z.string().optional(),\r\n impactAskPrice: z.string().optional(),\r\n});\r\n\r\n// =============================================================================\r\n// Liquidation Schemas\r\n// =============================================================================\r\n\r\nexport const LiquidationSideSchema = z.enum(['B', 'S']);\r\n\r\nexport const LiquidationSchema = z.object({\r\n coin: z.string(),\r\n timestamp: z.string(),\r\n liquidatedUser: z.string(),\r\n liquidatorUser: z.string(),\r\n price: z.string(),\r\n size: z.string(),\r\n side: LiquidationSideSchema,\r\n markPrice: z.string().optional(),\r\n closedPnl: z.string().optional(),\r\n direction: z.string().optional(),\r\n tradeId: z.number().optional(),\r\n txHash: z.string().optional(),\r\n});\r\n\r\n// =============================================================================\r\n// Candle Schemas\r\n// =============================================================================\r\n\r\nexport const CandleIntervalSchema = z.enum(['1m', '5m', '15m', '30m', '1h', '4h', '1d', '1w']);\r\n\r\nexport const CandleSchema = z.object({\r\n timestamp: z.string(),\r\n open: z.number(),\r\n high: z.number(),\r\n low: z.number(),\r\n close: z.number(),\r\n volume: z.number(),\r\n quoteVolume: z.number().optional(),\r\n tradeCount: z.number().optional(),\r\n});\r\n\r\n// =============================================================================\r\n// WebSocket Message Schemas\r\n// =============================================================================\r\n\r\nexport const WsChannelSchema = z.enum([\r\n 'orderbook', 'trades', 'candles', 'liquidations', 'ticker', 'all_tickers',\r\n 'open_interest', 'funding',\r\n 'lighter_orderbook', 'lighter_trades', 'lighter_candles',\r\n 'lighter_open_interest', 'lighter_funding',\r\n 'hip3_orderbook', 'hip3_trades', 'hip3_candles',\r\n 'hip3_open_interest', 'hip3_funding',\r\n]);\r\n\r\nexport const WsConnectionStateSchema = z.enum(['connecting', 'connected', 'disconnected', 'reconnecting']);\r\n\r\n// Server -> Client messages\r\nexport const WsSubscribedSchema = z.object({\r\n type: z.literal('subscribed'),\r\n channel: WsChannelSchema,\r\n coin: z.string().optional(),\r\n});\r\n\r\nexport const WsUnsubscribedSchema = z.object({\r\n type: z.literal('unsubscribed'),\r\n channel: WsChannelSchema,\r\n coin: z.string().optional(),\r\n});\r\n\r\nexport const WsPongSchema = z.object({\r\n type: z.literal('pong'),\r\n});\r\n\r\nexport const WsErrorSchema = z.object({\r\n type: z.literal('error'),\r\n message: z.string(),\r\n});\r\n\r\nexport const WsDataSchema = z.object({\r\n type: z.literal('data'),\r\n channel: WsChannelSchema,\r\n coin: z.string(),\r\n data: z.unknown(),\r\n});\r\n\r\n// Replay messages\r\nexport const WsReplayStartedSchema = z.object({\r\n type: z.literal('replay_started'),\r\n channel: WsChannelSchema,\r\n coin: z.string(),\r\n start: z.number(),\r\n end: z.number(),\r\n speed: z.number(),\r\n});\r\n\r\nexport const WsReplayPausedSchema = z.object({\r\n type: z.literal('replay_paused'),\r\n current_timestamp: z.number(),\r\n});\r\n\r\nexport const WsReplayResumedSchema = z.object({\r\n type: z.literal('replay_resumed'),\r\n current_timestamp: z.number(),\r\n});\r\n\r\nexport const WsReplayCompletedSchema = z.object({\r\n type: z.literal('replay_completed'),\r\n channel: WsChannelSchema,\r\n coin: z.string(),\r\n snapshots_sent: z.number(),\r\n});\r\n\r\nexport const WsReplayStoppedSchema = z.object({\r\n type: z.literal('replay_stopped'),\r\n});\r\n\r\nexport const WsHistoricalDataSchema = z.object({\r\n type: z.literal('historical_data'),\r\n channel: WsChannelSchema,\r\n coin: z.string(),\r\n timestamp: z.number(),\r\n data: z.unknown(),\r\n});\r\n\r\nexport const WsReplaySnapshotSchema = z.object({\r\n type: z.literal('replay_snapshot'),\r\n channel: WsChannelSchema,\r\n coin: z.string(),\r\n timestamp: z.number(),\r\n data: z.unknown(),\r\n});\r\n\r\n// Stream messages\r\nexport const WsStreamStartedSchema = z.object({\r\n type: z.literal('stream_started'),\r\n channel: WsChannelSchema,\r\n coin: z.string(),\r\n start: z.number(),\r\n end: z.number(),\r\n});\r\n\r\nexport const WsStreamProgressSchema = z.object({\r\n type: z.literal('stream_progress'),\r\n snapshots_sent: z.number(),\r\n});\r\n\r\nexport const TimestampedRecordSchema = z.object({\r\n timestamp: z.number(),\r\n data: z.unknown(),\r\n});\r\n\r\nexport const WsHistoricalBatchSchema = z.object({\r\n type: z.literal('historical_batch'),\r\n channel: WsChannelSchema,\r\n coin: z.string(),\r\n data: z.array(TimestampedRecordSchema),\r\n});\r\n\r\nexport const WsStreamCompletedSchema = z.object({\r\n type: z.literal('stream_completed'),\r\n channel: WsChannelSchema,\r\n coin: z.string(),\r\n snapshots_sent: z.number(),\r\n});\r\n\r\nexport const WsStreamStoppedSchema = z.object({\r\n type: z.literal('stream_stopped'),\r\n snapshots_sent: z.number(),\r\n});\r\n\r\n// Union of all server messages\r\nexport const WsServerMessageSchema = z.discriminatedUnion('type', [\r\n WsSubscribedSchema,\r\n WsUnsubscribedSchema,\r\n WsPongSchema,\r\n WsErrorSchema,\r\n WsDataSchema,\r\n WsReplayStartedSchema,\r\n WsReplayPausedSchema,\r\n WsReplayResumedSchema,\r\n WsReplayCompletedSchema,\r\n WsReplayStoppedSchema,\r\n WsReplaySnapshotSchema,\r\n WsHistoricalDataSchema,\r\n WsStreamStartedSchema,\r\n WsStreamProgressSchema,\r\n WsHistoricalBatchSchema,\r\n WsStreamCompletedSchema,\r\n WsStreamStoppedSchema,\r\n]);\r\n\r\n// =============================================================================\r\n// API Response Schemas (pre-built for common endpoints)\r\n// =============================================================================\r\n\r\nexport const OrderBookResponseSchema = ApiResponseSchema(OrderBookSchema);\r\nexport const OrderBookArrayResponseSchema = ApiResponseSchema(z.array(OrderBookSchema));\r\nexport const TradeArrayResponseSchema = ApiResponseSchema(z.array(TradeSchema));\r\nexport const InstrumentResponseSchema = ApiResponseSchema(InstrumentSchema);\r\nexport const InstrumentArrayResponseSchema = ApiResponseSchema(z.array(InstrumentSchema));\r\nexport const FundingRateResponseSchema = ApiResponseSchema(FundingRateSchema);\r\nexport const FundingRateArrayResponseSchema = ApiResponseSchema(z.array(FundingRateSchema));\r\nexport const OpenInterestResponseSchema = ApiResponseSchema(OpenInterestSchema);\r\nexport const OpenInterestArrayResponseSchema = ApiResponseSchema(z.array(OpenInterestSchema));\r\nexport const CandleArrayResponseSchema = ApiResponseSchema(z.array(CandleSchema));\r\nexport const LiquidationArrayResponseSchema = ApiResponseSchema(z.array(LiquidationSchema));\r\n\r\n// =============================================================================\r\n// Liquidation Volume Schemas\r\n// =============================================================================\r\n\r\nexport const LiquidationVolumeSchema = z.object({\r\n coin: z.string(),\r\n timestamp: z.string(),\r\n totalUsd: z.number(),\r\n longUsd: z.number(),\r\n shortUsd: z.number(),\r\n count: z.number(),\r\n longCount: z.number(),\r\n shortCount: z.number(),\r\n});\r\n\r\nexport const LiquidationVolumeArrayResponseSchema = z.object({\r\n success: z.boolean().optional(),\r\n data: z.array(LiquidationVolumeSchema),\r\n meta: ApiMetaSchema.optional(),\r\n});\r\n\r\n// =============================================================================\r\n// Coin Freshness Schemas\r\n// =============================================================================\r\n\r\nexport const DataTypeFreshnessInfoSchema = z.object({\r\n lastUpdated: z.string().nullable().optional(),\r\n lagMs: z.number().nullable().optional(),\r\n});\r\n\r\nexport const CoinFreshnessSchema = z.object({\r\n coin: z.string(),\r\n exchange: z.string(),\r\n measuredAt: z.string(),\r\n orderbook: DataTypeFreshnessInfoSchema,\r\n trades: DataTypeFreshnessInfoSchema,\r\n funding: DataTypeFreshnessInfoSchema,\r\n openInterest: DataTypeFreshnessInfoSchema,\r\n liquidations: DataTypeFreshnessInfoSchema.optional(),\r\n});\r\n\r\nexport const CoinFreshnessResponseSchema = z.object({\r\n success: z.boolean().optional(),\r\n data: CoinFreshnessSchema,\r\n meta: ApiMetaSchema.optional(),\r\n});\r\n\r\n// =============================================================================\r\n// Coin Summary Schemas\r\n// =============================================================================\r\n\r\nexport const CoinSummarySchema = z.object({\r\n coin: z.string(),\r\n timestamp: z.string(),\r\n markPrice: z.string().nullable().optional(),\r\n oraclePrice: z.string().nullable().optional(),\r\n midPrice: z.string().nullable().optional(),\r\n fundingRate: z.string().nullable().optional(),\r\n premium: z.string().nullable().optional(),\r\n openInterest: z.string().nullable().optional(),\r\n volume24h: z.string().nullable().optional(),\r\n liquidationVolume24h: z.number().nullable().optional(),\r\n longLiquidationVolume24h: z.number().nullable().optional(),\r\n shortLiquidationVolume24h: z.number().nullable().optional(),\r\n});\r\n\r\nexport const CoinSummaryResponseSchema = z.object({\r\n success: z.boolean().optional(),\r\n data: CoinSummarySchema,\r\n meta: ApiMetaSchema.optional(),\r\n});\r\n\r\n// =============================================================================\r\n// Price Snapshot Schemas\r\n// =============================================================================\r\n\r\nexport const PriceSnapshotSchema = z.object({\r\n timestamp: z.string(),\r\n markPrice: z.string().nullable().optional(),\r\n oraclePrice: z.string().nullable().optional(),\r\n midPrice: z.string().nullable().optional(),\r\n});\r\n\r\nexport const PriceSnapshotArrayResponseSchema = z.object({\r\n success: z.boolean().optional(),\r\n data: z.array(PriceSnapshotSchema),\r\n meta: ApiMetaSchema.optional(),\r\n});\r\n\r\n// =============================================================================\r\n// Type exports (inferred from schemas)\r\n// =============================================================================\r\n\r\nexport type ValidatedApiMeta = z.infer<typeof ApiMetaSchema>;\r\nexport type ValidatedPriceLevel = z.infer<typeof PriceLevelSchema>;\r\nexport type ValidatedOrderBook = z.infer<typeof OrderBookSchema>;\r\nexport type ValidatedTrade = z.infer<typeof TradeSchema>;\r\nexport type ValidatedInstrument = z.infer<typeof InstrumentSchema>;\r\nexport type ValidatedFundingRate = z.infer<typeof FundingRateSchema>;\r\nexport type ValidatedOpenInterest = z.infer<typeof OpenInterestSchema>;\r\nexport type ValidatedCandle = z.infer<typeof CandleSchema>;\r\nexport type ValidatedLiquidation = z.infer<typeof LiquidationSchema>;\r\nexport type ValidatedWsServerMessage = z.infer<typeof WsServerMessageSchema>;\r\n","/**\r\n * Orderbook Reconstructor for tick-level delta data.\r\n *\r\n * Efficiently reconstructs full orderbook state from checkpoint + deltas.\r\n * All reconstruction happens client-side for optimal server performance.\r\n *\r\n * @example\r\n * ```typescript\r\n * // Get raw tick data\r\n * const tickData = await client.lighter.orderbook.historyTick('BTC', { start, end });\r\n *\r\n * // Reconstruct to get snapshots at each delta\r\n * const reconstructor = new OrderBookReconstructor();\r\n * const snapshots = reconstructor.reconstructAll(tickData.checkpoint, tickData.deltas);\r\n *\r\n * // Or iterate efficiently (memory-friendly for large datasets)\r\n * for (const snapshot of reconstructor.iterate(tickData.checkpoint, tickData.deltas)) {\r\n * console.log(snapshot.timestamp, snapshot.bids[0], snapshot.asks[0]);\r\n * }\r\n * ```\r\n */\r\n\r\nimport type { OrderBook, PriceLevel, OrderbookDelta } from './types';\r\n\r\n/**\r\n * Price level stored internally with numeric values for efficient computation\r\n */\r\ninterface InternalLevel {\r\n price: number;\r\n size: number;\r\n orders: number;\r\n}\r\n\r\n/**\r\n * Reconstructed orderbook snapshot with timestamp\r\n */\r\nexport interface ReconstructedOrderBook extends OrderBook {\r\n /** Sequence number of the last applied delta */\r\n sequence?: number;\r\n}\r\n\r\n/**\r\n * Raw tick data from the API (checkpoint + deltas)\r\n */\r\nexport interface TickData {\r\n /** Initial orderbook state */\r\n checkpoint: OrderBook;\r\n /** Incremental changes to apply */\r\n deltas: OrderbookDelta[];\r\n}\r\n\r\n/**\r\n * Options for reconstruction\r\n */\r\nexport interface ReconstructOptions {\r\n /** Maximum depth (price levels) to include in output. Default: all levels */\r\n depth?: number;\r\n /** If true, yield a snapshot after every delta. If false, only return final state. Default: true */\r\n emitAll?: boolean;\r\n}\r\n\r\n/**\r\n * Orderbook Reconstructor\r\n *\r\n * Maintains orderbook state and efficiently applies delta updates.\r\n * Uses sorted arrays with binary search for O(log n) insertions.\r\n *\r\n * Thread-safe for single-threaded JavaScript; for worker threads,\r\n * create a separate instance per thread.\r\n */\r\nexport class OrderBookReconstructor {\r\n private bids: Map<number, InternalLevel> = new Map();\r\n private asks: Map<number, InternalLevel> = new Map();\r\n private coin: string = '';\r\n private lastTimestamp: string = '';\r\n private lastSequence: number = 0;\r\n\r\n /**\r\n * Initialize or reset the reconstructor with a checkpoint\r\n */\r\n initialize(checkpoint: OrderBook): void {\r\n this.bids.clear();\r\n this.asks.clear();\r\n this.coin = checkpoint.coin;\r\n this.lastTimestamp = checkpoint.timestamp;\r\n this.lastSequence = 0;\r\n\r\n // Parse checkpoint bids\r\n for (const level of checkpoint.bids) {\r\n const price = parseFloat(level.px);\r\n this.bids.set(price, {\r\n price,\r\n size: parseFloat(level.sz),\r\n orders: level.n,\r\n });\r\n }\r\n\r\n // Parse checkpoint asks\r\n for (const level of checkpoint.asks) {\r\n const price = parseFloat(level.px);\r\n this.asks.set(price, {\r\n price,\r\n size: parseFloat(level.sz),\r\n orders: level.n,\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Apply a single delta to the current state\r\n */\r\n applyDelta(delta: OrderbookDelta): void {\r\n const book = delta.side === 'bid' ? this.bids : this.asks;\r\n\r\n if (delta.size === 0) {\r\n // Remove level\r\n book.delete(delta.price);\r\n } else {\r\n // Insert or update level\r\n book.set(delta.price, {\r\n price: delta.price,\r\n size: delta.size,\r\n orders: 1, // Deltas don't include order count, assume 1\r\n });\r\n }\r\n\r\n this.lastTimestamp = new Date(delta.timestamp).toISOString();\r\n this.lastSequence = delta.sequence;\r\n }\r\n\r\n /**\r\n * Get the current orderbook state as a snapshot\r\n */\r\n getSnapshot(depth?: number): ReconstructedOrderBook {\r\n // Sort bids descending (best bid first)\r\n const sortedBids = Array.from(this.bids.values())\r\n .sort((a, b) => b.price - a.price);\r\n\r\n // Sort asks ascending (best ask first)\r\n const sortedAsks = Array.from(this.asks.values())\r\n .sort((a, b) => a.price - b.price);\r\n\r\n // Apply depth limit\r\n const bidsOutput = (depth ? sortedBids.slice(0, depth) : sortedBids)\r\n .map(this.toLevel);\r\n const asksOutput = (depth ? sortedAsks.slice(0, depth) : sortedAsks)\r\n .map(this.toLevel);\r\n\r\n // Calculate mid price and spread\r\n const bestBid = sortedBids[0]?.price;\r\n const bestAsk = sortedAsks[0]?.price;\r\n const midPrice = bestBid && bestAsk ? (bestBid + bestAsk) / 2 : undefined;\r\n const spread = bestBid && bestAsk ? bestAsk - bestBid : undefined;\r\n const spreadBps = midPrice && spread ? (spread / midPrice) * 10000 : undefined;\r\n\r\n return {\r\n coin: this.coin,\r\n timestamp: this.lastTimestamp,\r\n bids: bidsOutput,\r\n asks: asksOutput,\r\n midPrice: midPrice?.toString(),\r\n spread: spread?.toString(),\r\n spreadBps: spreadBps?.toFixed(2),\r\n sequence: this.lastSequence,\r\n };\r\n }\r\n\r\n /**\r\n * Convert internal level to API format\r\n */\r\n private toLevel = (level: InternalLevel): PriceLevel => ({\r\n px: level.price.toString(),\r\n sz: level.size.toString(),\r\n n: level.orders,\r\n });\r\n\r\n /**\r\n * Reconstruct all orderbook states from checkpoint + deltas.\r\n * Returns an array of snapshots, one after each delta.\r\n *\r\n * For large datasets, prefer `iterate()` to avoid memory issues.\r\n *\r\n * @param checkpoint - Initial orderbook state\r\n * @param deltas - Array of delta updates\r\n * @param options - Reconstruction options\r\n * @returns Array of reconstructed orderbook snapshots\r\n */\r\n reconstructAll(\r\n checkpoint: OrderBook,\r\n deltas: OrderbookDelta[],\r\n options: ReconstructOptions = {}\r\n ): ReconstructedOrderBook[] {\r\n const { depth, emitAll = true } = options;\r\n const snapshots: ReconstructedOrderBook[] = [];\r\n\r\n this.initialize(checkpoint);\r\n\r\n // Sort deltas by sequence to ensure correct order\r\n const sortedDeltas = [...deltas].sort((a, b) => a.sequence - b.sequence);\r\n\r\n if (emitAll) {\r\n // Emit initial state\r\n snapshots.push(this.getSnapshot(depth));\r\n }\r\n\r\n for (const delta of sortedDeltas) {\r\n this.applyDelta(delta);\r\n if (emitAll) {\r\n snapshots.push(this.getSnapshot(depth));\r\n }\r\n }\r\n\r\n if (!emitAll) {\r\n // Only return final state\r\n snapshots.push(this.getSnapshot(depth));\r\n }\r\n\r\n return snapshots;\r\n }\r\n\r\n /**\r\n * Iterate over reconstructed orderbook states (memory-efficient).\r\n * Yields a snapshot after each delta is applied.\r\n *\r\n * @param checkpoint - Initial orderbook state\r\n * @param deltas - Array of delta updates\r\n * @param options - Reconstruction options\r\n * @yields Reconstructed orderbook snapshots\r\n */\r\n *iterate(\r\n checkpoint: OrderBook,\r\n deltas: OrderbookDelta[],\r\n options: ReconstructOptions = {}\r\n ): Generator<ReconstructedOrderBook> {\r\n const { depth } = options;\r\n\r\n this.initialize(checkpoint);\r\n\r\n // Yield initial state\r\n yield this.getSnapshot(depth);\r\n\r\n // Sort deltas by sequence\r\n const sortedDeltas = [...deltas].sort((a, b) => a.sequence - b.sequence);\r\n\r\n for (const delta of sortedDeltas) {\r\n this.applyDelta(delta);\r\n yield this.getSnapshot(depth);\r\n }\r\n }\r\n\r\n /**\r\n * Get the final reconstructed state without intermediate snapshots.\r\n * Most efficient when you only need the end result.\r\n *\r\n * @param checkpoint - Initial orderbook state\r\n * @param deltas - Array of delta updates\r\n * @param depth - Maximum price levels to include\r\n * @returns Final orderbook state after all deltas applied\r\n */\r\n reconstructFinal(\r\n checkpoint: OrderBook,\r\n deltas: OrderbookDelta[],\r\n depth?: number\r\n ): ReconstructedOrderBook {\r\n this.initialize(checkpoint);\r\n\r\n // Sort and apply all deltas\r\n const sortedDeltas = [...deltas].sort((a, b) => a.sequence - b.sequence);\r\n for (const delta of sortedDeltas) {\r\n this.applyDelta(delta);\r\n }\r\n\r\n return this.getSnapshot(depth);\r\n }\r\n\r\n /**\r\n * Check for sequence gaps in deltas.\r\n * Returns array of missing sequence numbers.\r\n *\r\n * @param deltas - Array of delta updates\r\n * @returns Array of [expectedSeq, actualSeq] tuples where gaps exist\r\n */\r\n static detectGaps(deltas: OrderbookDelta[]): Array<[number, number]> {\r\n if (deltas.length < 2) return [];\r\n\r\n const sorted = [...deltas].sort((a, b) => a.sequence - b.sequence);\r\n const gaps: Array<[number, number]> = [];\r\n\r\n for (let i = 1; i < sorted.length; i++) {\r\n const expected = sorted[i - 1].sequence + 1;\r\n const actual = sorted[i].sequence;\r\n if (actual !== expected) {\r\n gaps.push([expected, actual]);\r\n }\r\n }\r\n\r\n return gaps;\r\n }\r\n}\r\n\r\n/**\r\n * Convenience function for one-shot reconstruction.\r\n * Creates a new reconstructor, processes data, and returns snapshots.\r\n *\r\n * @param tickData - Checkpoint and deltas from API\r\n * @param options - Reconstruction options\r\n * @returns Array of reconstructed orderbook snapshots\r\n */\r\nexport function reconstructOrderBook(\r\n tickData: TickData,\r\n options: ReconstructOptions = {}\r\n): ReconstructedOrderBook[] {\r\n const reconstructor = new OrderBookReconstructor();\r\n return reconstructor.reconstructAll(tickData.checkpoint, tickData.deltas, options);\r\n}\r\n\r\n/**\r\n * Convenience function to get final orderbook state.\r\n *\r\n * @param tickData - Checkpoint and deltas from API\r\n * @param depth - Maximum price levels\r\n * @returns Final orderbook state\r\n */\r\nexport function reconstructFinal(\r\n tickData: TickData,\r\n depth?: number\r\n): ReconstructedOrderBook {\r\n const reconstructor = new OrderBookReconstructor();\r\n return reconstructor.reconstructFinal(tickData.checkpoint, tickData.deltas, depth);\r\n}\r\n","import type { HttpClient } from '../http';\r\nimport type {\r\n ApiResponse,\r\n CursorResponse,\r\n OrderBook,\r\n GetOrderBookParams,\r\n OrderBookHistoryParams,\r\n OrderbookDelta,\r\n} from '../types';\r\nimport { OrderBookResponseSchema, OrderBookArrayResponseSchema } from '../schemas';\r\nimport {\r\n OrderBookReconstructor,\r\n type TickData,\r\n type ReconstructedOrderBook,\r\n type ReconstructOptions,\r\n} from '../orderbook-reconstructor';\r\n\r\n/**\r\n * Parameters for tick-level orderbook history (Enterprise tier only)\r\n */\r\nexport interface TickHistoryParams {\r\n /** Start timestamp (Unix ms or ISO string) - REQUIRED */\r\n start: number | string;\r\n /** End timestamp (Unix ms or ISO string) - REQUIRED */\r\n end: number | string;\r\n /** Number of price levels in checkpoint (default: all) */\r\n depth?: number;\r\n}\r\n\r\n/**\r\n * Order book API resource\r\n *\r\n * @example\r\n * ```typescript\r\n * // Get current order book\r\n * const orderbook = await client.orderbook.get('BTC');\r\n *\r\n * // Get order book at specific timestamp\r\n * const historical = await client.orderbook.get('ETH', {\r\n * timestamp: 1704067200000,\r\n * depth: 10\r\n * });\r\n *\r\n * // Get order book history\r\n * const history = await client.orderbook.history('BTC', {\r\n * start: Date.now() - 86400000,\r\n * end: Date.now(),\r\n * limit: 100\r\n * });\r\n *\r\n * // Enterprise: Get tick-level data with reconstruction\r\n * const snapshots = await client.lighter.orderbook.historyReconstructed('BTC', {\r\n * start: Date.now() - 3600000,\r\n * end: Date.now()\r\n * });\r\n *\r\n * // Enterprise: Get raw tick data for custom reconstruction\r\n * const tickData = await client.lighter.orderbook.historyTick('BTC', {\r\n * start: Date.now() - 3600000,\r\n * end: Date.now()\r\n * });\r\n * ```\r\n */\r\nexport class OrderBookResource {\r\n constructor(\r\n private http: HttpClient,\r\n private basePath: string = '/v1',\r\n private coinTransform: (coin: string) => string = (c) => c.toUpperCase()\r\n ) {}\r\n\r\n /**\r\n * Get order book snapshot for a symbol\r\n *\r\n * @param symbol - The symbol (e.g., 'BTC', 'ETH')\r\n * @param params - Optional parameters\r\n * @returns Order book snapshot\r\n */\r\n async get(symbol: string, params?: GetOrderBookParams): Promise<OrderBook> {\r\n const response = await this.http.get<ApiResponse<OrderBook>>(\r\n `${this.basePath}/orderbook/${this.coinTransform(symbol)}`,\r\n params as Record<string, unknown>,\r\n this.http.validationEnabled ? OrderBookResponseSchema : undefined\r\n );\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Get historical order book snapshots with cursor-based pagination\r\n *\r\n * @param symbol - The symbol (e.g., 'BTC', 'ETH')\r\n * @param params - Time range and cursor pagination parameters (start and end are required)\r\n * @returns CursorResponse with order book snapshots and nextCursor for pagination\r\n *\r\n * @example\r\n * ```typescript\r\n * // First page\r\n * let result = await client.orderbook.history('BTC', {\r\n * start: Date.now() - 86400000,\r\n * end: Date.now(),\r\n * limit: 1000\r\n * });\r\n *\r\n * // Subsequent pages\r\n * while (result.nextCursor) {\r\n * result = await client.orderbook.history('BTC', {\r\n * start: Date.now() - 86400000,\r\n * end: Date.now(),\r\n * cursor: result.nextCursor,\r\n * limit: 1000\r\n * });\r\n * }\r\n * ```\r\n */\r\n async history(\r\n symbol: string,\r\n params: OrderBookHistoryParams\r\n ): Promise<CursorResponse<OrderBook[]>> {\r\n const response = await this.http.get<ApiResponse<OrderBook[]>>(\r\n `${this.basePath}/orderbook/${this.coinTransform(symbol)}/history`,\r\n params as unknown as Record<string, unknown>,\r\n this.http.validationEnabled ? OrderBookArrayResponseSchema : undefined\r\n );\r\n return {\r\n data: response.data,\r\n nextCursor: response.meta.nextCursor,\r\n };\r\n }\r\n\r\n /**\r\n * Get raw tick-level orderbook data (Enterprise tier only).\r\n *\r\n * Returns a checkpoint (full orderbook state) and array of deltas.\r\n * Use this when you want to implement custom reconstruction logic\r\n * (e.g., in Rust for maximum performance).\r\n *\r\n * For automatic reconstruction, use `historyReconstructed()` instead.\r\n *\r\n * @param symbol - The symbol (e.g., 'BTC', 'ETH')\r\n * @param params - Time range parameters\r\n * @returns Tick data with checkpoint and deltas\r\n *\r\n * @example\r\n * ```typescript\r\n * const tickData = await client.lighter.orderbook.historyTick('BTC', {\r\n * start: Date.now() - 3600000,\r\n * end: Date.now()\r\n * });\r\n *\r\n * console.log('Checkpoint:', tickData.checkpoint);\r\n * console.log('Deltas:', tickData.deltas.length);\r\n *\r\n * // Implement your own reconstruction...\r\n * for (const delta of tickData.deltas) {\r\n * // delta: { timestamp, side, price, size, sequence }\r\n * }\r\n * ```\r\n */\r\n async historyTick(\r\n symbol: string,\r\n params: TickHistoryParams\r\n ): Promise<TickData> {\r\n const response = await this.http.get<{\r\n success: boolean;\r\n data?: {\r\n checkpoint?: OrderBook;\r\n deltas?: OrderbookDelta[];\r\n };\r\n granularity?: string;\r\n error?: string;\r\n message?: string;\r\n }>(\r\n `${this.basePath}/orderbook/${this.coinTransform(symbol)}/history`,\r\n {\r\n ...params,\r\n granularity: 'tick',\r\n } as Record<string, unknown>\r\n );\r\n\r\n // Check if tick-level data was returned (nested inside data wrapper)\r\n const tickData = response.data;\r\n if (!tickData?.checkpoint || !tickData?.deltas) {\r\n const errorMsg = response.error || response.message ||\r\n 'Tick-level orderbook data requires Enterprise tier. ' +\r\n 'Upgrade your subscription or use a different granularity.';\r\n throw new Error(errorMsg);\r\n }\r\n\r\n return {\r\n checkpoint: tickData.checkpoint,\r\n deltas: tickData.deltas,\r\n };\r\n }\r\n\r\n /**\r\n * Get reconstructed tick-level orderbook history (Enterprise tier only).\r\n *\r\n * Fetches raw tick data and reconstructs full orderbook state at each delta.\r\n * All reconstruction happens client-side for optimal server performance.\r\n *\r\n * For large time ranges, consider using `historyTick()` with the\r\n * `OrderBookReconstructor.iterate()` method for memory efficiency.\r\n *\r\n * @param symbol - The symbol (e.g., 'BTC', 'ETH')\r\n * @param params - Time range parameters\r\n * @param options - Reconstruction options\r\n * @returns Array of reconstructed orderbook snapshots\r\n *\r\n * @example\r\n * ```typescript\r\n * // Get all snapshots\r\n * const snapshots = await client.lighter.orderbook.historyReconstructed('BTC', {\r\n * start: Date.now() - 3600000,\r\n * end: Date.now()\r\n * });\r\n *\r\n * for (const ob of snapshots) {\r\n * console.log(ob.timestamp, 'Best bid:', ob.bids[0]?.px, 'Best ask:', ob.asks[0]?.px);\r\n * }\r\n *\r\n * // Get only final state\r\n * const [final] = await client.lighter.orderbook.historyReconstructed('BTC',\r\n * { start, end },\r\n * { emitAll: false }\r\n * );\r\n * ```\r\n */\r\n async historyReconstructed(\r\n symbol: string,\r\n params: TickHistoryParams,\r\n options: ReconstructOptions = {}\r\n ): Promise<ReconstructedOrderBook[]> {\r\n const tickData = await this.historyTick(symbol, params);\r\n const reconstructor = new OrderBookReconstructor();\r\n return reconstructor.reconstructAll(tickData.checkpoint, tickData.deltas, options);\r\n }\r\n\r\n /**\r\n * Create a reconstructor for streaming tick-level data.\r\n *\r\n * Returns an OrderBookReconstructor instance that you can use\r\n * to process tick data incrementally or with custom logic.\r\n *\r\n * @returns A new OrderBookReconstructor instance\r\n *\r\n * @example\r\n * ```typescript\r\n * const reconstructor = client.lighter.orderbook.createReconstructor();\r\n * const tickData = await client.lighter.orderbook.historyTick('BTC', { start, end });\r\n *\r\n * // Memory-efficient iteration\r\n * for (const snapshot of reconstructor.iterate(tickData.checkpoint, tickData.deltas)) {\r\n * // Process each snapshot\r\n * if (someCondition(snapshot)) break; // Early exit if needed\r\n * }\r\n *\r\n * // Check for gaps\r\n * const gaps = OrderBookReconstructor.detectGaps(tickData.deltas);\r\n * if (gaps.length > 0) {\r\n * console.warn('Sequence gaps detected:', gaps);\r\n * }\r\n * ```\r\n */\r\n createReconstructor(): OrderBookReconstructor {\r\n return new OrderBookReconstructor();\r\n }\r\n\r\n /**\r\n * Iterate over tick-level orderbook history with automatic pagination (Enterprise tier only).\r\n *\r\n * This async generator automatically handles pagination, fetching up to 1,000 deltas\r\n * per API request and yielding reconstructed orderbook snapshots one at a time.\r\n * Memory-efficient for processing large time ranges.\r\n *\r\n * @param symbol - The symbol (e.g., 'BTC', 'ETH')\r\n * @param params - Time range parameters\r\n * @param depth - Maximum price levels to include in output snapshots\r\n * @yields Reconstructed orderbook snapshots\r\n *\r\n * @example\r\n * ```typescript\r\n * // Process 24 hours of tick data with automatic pagination\r\n * for await (const snapshot of client.lighter.orderbook.iterateTickHistory('BTC', {\r\n * start: Date.now() - 86400000,\r\n * end: Date.now()\r\n * })) {\r\n * console.log(snapshot.timestamp, 'Mid:', snapshot.midPrice);\r\n * if (someCondition) break; // Early exit supported\r\n * }\r\n *\r\n * // Collect all snapshots (caution: may use significant memory for large ranges)\r\n * const allSnapshots: ReconstructedOrderBook[] = [];\r\n * for await (const snapshot of client.lighter.orderbook.iterateTickHistory('BTC', { start, end })) {\r\n * allSnapshots.push(snapshot);\r\n * }\r\n * ```\r\n */\r\n async *iterateTickHistory(\r\n symbol: string,\r\n params: TickHistoryParams,\r\n depth?: number\r\n ): AsyncGenerator<ReconstructedOrderBook, void, undefined> {\r\n const startTs = typeof params.start === 'string' ? new Date(params.start).getTime() : params.start;\r\n const endTs = typeof params.end === 'string' ? new Date(params.end).getTime() : params.end;\r\n\r\n let cursor = startTs;\r\n const reconstructor = new OrderBookReconstructor();\r\n const MAX_DELTAS_PER_PAGE = 1000;\r\n let isFirstPage = true;\r\n\r\n while (cursor < endTs) {\r\n const tickData = await this.historyTick(symbol, {\r\n start: cursor,\r\n end: endTs,\r\n depth: params.depth,\r\n });\r\n\r\n if (tickData.deltas.length === 0) {\r\n // No deltas - yield checkpoint only on first page if no data\r\n if (isFirstPage) {\r\n reconstructor.initialize(tickData.checkpoint);\r\n yield reconstructor.getSnapshot(depth);\r\n }\r\n break;\r\n }\r\n\r\n // Yield each reconstructed snapshot\r\n // Skip initial checkpoint on subsequent pages to avoid duplicates\r\n let skipFirst = !isFirstPage;\r\n for (const snapshot of reconstructor.iterate(tickData.checkpoint, tickData.deltas, { depth })) {\r\n if (skipFirst) {\r\n skipFirst = false;\r\n continue;\r\n }\r\n yield snapshot;\r\n }\r\n\r\n isFirstPage = false;\r\n\r\n // Move cursor past the last delta\r\n const lastDelta = tickData.deltas[tickData.deltas.length - 1];\r\n cursor = lastDelta.timestamp + 1;\r\n\r\n // If we got fewer than max deltas, we've reached the end\r\n if (tickData.deltas.length < MAX_DELTAS_PER_PAGE) {\r\n break;\r\n }\r\n }\r\n }\r\n}\r\n","import type { HttpClient } from '../http';\r\nimport type { ApiResponse, Trade, GetTradesCursorParams, CursorResponse } from '../types';\r\nimport { TradeArrayResponseSchema } from '../schemas';\r\n\r\n/**\r\n * Trades API resource\r\n *\r\n * @example\r\n * ```typescript\r\n * // Get trade history with cursor-based pagination (recommended)\r\n * let result = await client.hyperliquid.trades.list('BTC', {\r\n * start: Date.now() - 86400000,\r\n * end: Date.now(),\r\n * limit: 1000\r\n * });\r\n *\r\n * // Get all pages\r\n * const allTrades = [...result.data];\r\n * while (result.nextCursor) {\r\n * result = await client.hyperliquid.trades.list('BTC', {\r\n * start: Date.now() - 86400000,\r\n * end: Date.now(),\r\n * cursor: result.nextCursor,\r\n * limit: 1000\r\n * });\r\n * allTrades.push(...result.data);\r\n * }\r\n *\r\n * // Get recent trades (Lighter only - has real-time data)\r\n * const recent = await client.lighter.trades.recent('BTC');\r\n * ```\r\n */\r\nexport class TradesResource {\r\n constructor(\r\n private http: HttpClient,\r\n private basePath: string = '/v1',\r\n private coinTransform: (coin: string) => string = (c) => c.toUpperCase()\r\n ) {}\r\n\r\n /**\r\n * Get trade history for a symbol using cursor-based pagination\r\n *\r\n * Uses cursor-based pagination by default, which is more efficient for large datasets.\r\n * Use the `nextCursor` from the response as the `cursor` parameter to get the next page.\r\n *\r\n * @param symbol - The symbol (e.g., 'BTC', 'ETH')\r\n * @param params - Time range and cursor pagination parameters (start and end are required)\r\n * @returns Object with trades array and nextCursor for pagination\r\n *\r\n * @example\r\n * ```typescript\r\n * // First page\r\n * let result = await client.trades.list('BTC', {\r\n * start: Date.now() - 86400000,\r\n * end: Date.now(),\r\n * limit: 1000\r\n * });\r\n *\r\n * // Subsequent pages\r\n * while (result.nextCursor) {\r\n * result = await client.trades.list('BTC', {\r\n * start: Date.now() - 86400000,\r\n * end: Date.now(),\r\n * cursor: result.nextCursor,\r\n * limit: 1000\r\n * });\r\n * }\r\n * ```\r\n */\r\n async list(symbol: string, params: GetTradesCursorParams): Promise<CursorResponse<Trade[]>> {\r\n const response = await this.http.get<ApiResponse<Trade[]>>(\r\n `${this.basePath}/trades/${this.coinTransform(symbol)}`,\r\n params as unknown as Record<string, unknown>,\r\n this.http.validationEnabled ? TradeArrayResponseSchema : undefined\r\n );\r\n return {\r\n data: response.data,\r\n nextCursor: response.meta.nextCursor,\r\n };\r\n }\r\n\r\n /**\r\n * Get most recent trades for a symbol.\r\n *\r\n * Note: This method is available for Lighter (client.lighter.trades.recent())\r\n * and HIP-3 (client.hyperliquid.hip3.trades.recent()) which have real-time data\r\n * ingestion. Hyperliquid uses hourly backfill so this endpoint is not available\r\n * for Hyperliquid.\r\n *\r\n * @param symbol - The symbol (e.g., 'BTC', 'ETH')\r\n * @param limit - Number of trades to return (default: 100)\r\n * @returns Array of recent trades\r\n */\r\n async recent(symbol: string, limit?: number): Promise<Trade[]> {\r\n const response = await this.http.get<ApiResponse<Trade[]>>(\r\n `${this.basePath}/trades/${this.coinTransform(symbol)}/recent`,\r\n { limit },\r\n this.http.validationEnabled ? TradeArrayResponseSchema : undefined\r\n );\r\n return response.data;\r\n }\r\n\r\n}\r\n","import type { HttpClient } from '../http';\r\nimport type { ApiResponse, Hip3Instrument, Instrument, LighterInstrument } from '../types';\r\nimport { InstrumentResponseSchema, InstrumentArrayResponseSchema } from '../schemas';\r\n\r\n/**\r\n * Instruments API resource\r\n *\r\n * @example\r\n * ```typescript\r\n * // List all instruments\r\n * const instruments = await client.instruments.list();\r\n *\r\n * // Get specific instrument\r\n * const btc = await client.instruments.get('BTC');\r\n * ```\r\n */\r\nexport class InstrumentsResource {\r\n constructor(private http: HttpClient, private basePath: string = '/v1') {}\r\n\r\n /**\r\n * List all available trading instruments\r\n *\r\n * @returns Array of instruments\r\n */\r\n async list(): Promise<Instrument[]> {\r\n const response = await this.http.get<ApiResponse<Instrument[]>>(\r\n `${this.basePath}/instruments`,\r\n undefined,\r\n this.http.validationEnabled ? InstrumentArrayResponseSchema : undefined\r\n );\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Get a specific instrument by coin symbol\r\n *\r\n * @param coin - The coin symbol (e.g., 'BTC', 'ETH')\r\n * @returns Instrument details\r\n */\r\n async get(coin: string): Promise<Instrument> {\r\n const response = await this.http.get<ApiResponse<Instrument>>(\r\n `${this.basePath}/instruments/${coin.toUpperCase()}`,\r\n undefined,\r\n this.http.validationEnabled ? InstrumentResponseSchema : undefined\r\n );\r\n return response.data;\r\n }\r\n}\r\n\r\n/**\r\n * Lighter.xyz Instruments API resource\r\n *\r\n * Lighter instruments have a different schema than Hyperliquid with more\r\n * detailed market configuration including fees and minimum amounts.\r\n *\r\n * @example\r\n * ```typescript\r\n * // List all Lighter instruments\r\n * const instruments = await client.lighter.instruments.list();\r\n *\r\n * // Get specific instrument\r\n * const btc = await client.lighter.instruments.get('BTC');\r\n * console.log(`Taker fee: ${btc.takerFee}`);\r\n * ```\r\n */\r\nexport class LighterInstrumentsResource {\r\n constructor(private http: HttpClient, private basePath: string = '/v1/lighter') {}\r\n\r\n /**\r\n * List all available Lighter trading instruments\r\n *\r\n * @returns Array of Lighter instruments with full market configuration\r\n */\r\n async list(): Promise<LighterInstrument[]> {\r\n const response = await this.http.get<ApiResponse<LighterInstrument[]>>(\r\n `${this.basePath}/instruments`\r\n );\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Get a specific Lighter instrument by coin symbol\r\n *\r\n * @param coin - The coin symbol (e.g., 'BTC', 'ETH')\r\n * @returns Lighter instrument details with full market configuration\r\n */\r\n async get(coin: string): Promise<LighterInstrument> {\r\n const response = await this.http.get<ApiResponse<LighterInstrument>>(\r\n `${this.basePath}/instruments/${coin.toUpperCase()}`\r\n );\r\n return response.data;\r\n }\r\n}\r\n\r\n/**\r\n * HIP-3 Builder Perps Instruments API resource\r\n *\r\n * HIP-3 instruments are derived from live market data and include\r\n * mark price, open interest, and mid price context.\r\n *\r\n * @example\r\n * ```typescript\r\n * // List all HIP-3 instruments\r\n * const instruments = await client.hyperliquid.hip3.instruments.list();\r\n *\r\n * // Get specific instrument\r\n * const us500 = await client.hyperliquid.hip3.instruments.get('km:US500');\r\n * console.log(`Mark price: ${us500.markPrice}`);\r\n * ```\r\n */\r\nexport class Hip3InstrumentsResource {\r\n private coinTransform: (c: string) => string;\r\n\r\n constructor(\r\n private http: HttpClient,\r\n private basePath: string = '/v1/hyperliquid/hip3',\r\n coinTransform?: (c: string) => string\r\n ) {\r\n this.coinTransform = coinTransform || ((c) => c);\r\n }\r\n\r\n /**\r\n * List all available HIP-3 instruments with latest market data\r\n *\r\n * @returns Array of HIP-3 instruments\r\n */\r\n async list(): Promise<Hip3Instrument[]> {\r\n const response = await this.http.get<ApiResponse<Hip3Instrument[]>>(\r\n `${this.basePath}/instruments`\r\n );\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Get a specific HIP-3 instrument by coin name\r\n *\r\n * @param coin - The coin name (e.g., 'km:US500', 'xyz:XYZ100'). Case-sensitive.\r\n * @returns HIP-3 instrument details with latest market data\r\n */\r\n async get(coin: string): Promise<Hip3Instrument> {\r\n coin = this.coinTransform(coin);\r\n const response = await this.http.get<ApiResponse<Hip3Instrument>>(\r\n `${this.basePath}/instruments/${coin}`\r\n );\r\n return response.data;\r\n }\r\n}\r\n","import type { HttpClient } from '../http';\r\nimport type { ApiResponse, CursorResponse, FundingRate, FundingHistoryParams } from '../types';\r\nimport { FundingRateResponseSchema, FundingRateArrayResponseSchema } from '../schemas';\r\n\r\n/**\r\n * Funding rates API resource\r\n *\r\n * @example\r\n * ```typescript\r\n * // Get current funding rate\r\n * const current = await client.funding.current('BTC');\r\n *\r\n * // Get funding rate history with cursor-based pagination\r\n * let result = await client.funding.history('ETH', {\r\n * start: Date.now() - 86400000 * 7,\r\n * end: Date.now(),\r\n * limit: 1000\r\n * });\r\n *\r\n * // Get all pages\r\n * const allRates = [...result.data];\r\n * while (result.nextCursor) {\r\n * result = await client.funding.history('ETH', {\r\n * start: Date.now() - 86400000 * 7,\r\n * end: Date.now(),\r\n * cursor: result.nextCursor,\r\n * limit: 1000\r\n * });\r\n * allRates.push(...result.data);\r\n * }\r\n * ```\r\n */\r\nexport class FundingResource {\r\n constructor(\r\n private http: HttpClient,\r\n private basePath: string = '/v1',\r\n private coinTransform: (coin: string) => string = (c) => c.toUpperCase()\r\n ) {}\r\n\r\n /**\r\n * Get funding rate history for a symbol with cursor-based pagination\r\n *\r\n * @param symbol - The symbol (e.g., 'BTC', 'ETH')\r\n * @param params - Time range and cursor pagination parameters (start and end are required)\r\n * @returns CursorResponse with funding rate records and nextCursor for pagination\r\n */\r\n async history(symbol: string, params: FundingHistoryParams): Promise<CursorResponse<FundingRate[]>> {\r\n const response = await this.http.get<ApiResponse<FundingRate[]>>(\r\n `${this.basePath}/funding/${this.coinTransform(symbol)}`,\r\n params as unknown as Record<string, unknown>,\r\n this.http.validationEnabled ? FundingRateArrayResponseSchema : undefined\r\n );\r\n return {\r\n data: response.data,\r\n nextCursor: response.meta.nextCursor,\r\n };\r\n }\r\n\r\n /**\r\n * Get current funding rate for a symbol\r\n *\r\n * @param symbol - The symbol (e.g., 'BTC', 'ETH')\r\n * @returns Current funding rate\r\n */\r\n async current(symbol: string): Promise<FundingRate> {\r\n const response = await this.http.get<ApiResponse<FundingRate>>(\r\n `${this.basePath}/funding/${this.coinTransform(symbol)}/current`,\r\n undefined,\r\n this.http.validationEnabled ? FundingRateResponseSchema : undefined\r\n );\r\n return response.data;\r\n }\r\n}\r\n","import type { HttpClient } from '../http';\r\nimport type { ApiResponse, CursorResponse, OpenInterest, OpenInterestHistoryParams } from '../types';\r\nimport { OpenInterestResponseSchema, OpenInterestArrayResponseSchema } from '../schemas';\r\n\r\n/**\r\n * Open interest API resource\r\n *\r\n * @example\r\n * ```typescript\r\n * // Get current open interest\r\n * const current = await client.openInterest.current('BTC');\r\n *\r\n * // Get open interest history with cursor-based pagination\r\n * let result = await client.openInterest.history('ETH', {\r\n * start: Date.now() - 86400000,\r\n * end: Date.now(),\r\n * limit: 1000\r\n * });\r\n *\r\n * // Get all pages\r\n * const allRecords = [...result.data];\r\n * while (result.nextCursor) {\r\n * result = await client.openInterest.history('ETH', {\r\n * start: Date.now() - 86400000,\r\n * end: Date.now(),\r\n * cursor: result.nextCursor,\r\n * limit: 1000\r\n * });\r\n * allRecords.push(...result.data);\r\n * }\r\n * ```\r\n */\r\nexport class OpenInterestResource {\r\n constructor(\r\n private http: HttpClient,\r\n private basePath: string = '/v1',\r\n private coinTransform: (coin: string) => string = (c) => c.toUpperCase()\r\n ) {}\r\n\r\n /**\r\n * Get open interest history for a symbol with cursor-based pagination\r\n *\r\n * @param symbol - The symbol (e.g., 'BTC', 'ETH')\r\n * @param params - Time range and cursor pagination parameters (start and end are required)\r\n * @returns CursorResponse with open interest records and nextCursor for pagination\r\n */\r\n async history(symbol: string, params: OpenInterestHistoryParams): Promise<CursorResponse<OpenInterest[]>> {\r\n const response = await this.http.get<ApiResponse<OpenInterest[]>>(\r\n `${this.basePath}/openinterest/${this.coinTransform(symbol)}`,\r\n params as unknown as Record<string, unknown>,\r\n this.http.validationEnabled ? OpenInterestArrayResponseSchema : undefined\r\n );\r\n return {\r\n data: response.data,\r\n nextCursor: response.meta.nextCursor,\r\n };\r\n }\r\n\r\n /**\r\n * Get current open interest for a symbol\r\n *\r\n * @param symbol - The symbol (e.g., 'BTC', 'ETH')\r\n * @returns Current open interest\r\n */\r\n async current(symbol: string): Promise<OpenInterest> {\r\n const response = await this.http.get<ApiResponse<OpenInterest>>(\r\n `${this.basePath}/openinterest/${this.coinTransform(symbol)}/current`,\r\n undefined,\r\n this.http.validationEnabled ? OpenInterestResponseSchema : undefined\r\n );\r\n return response.data;\r\n }\r\n}\r\n","import type { HttpClient } from '../http';\r\nimport type { ApiResponse, Candle, CandleHistoryParams, CursorResponse } from '../types';\r\nimport { CandleArrayResponseSchema } from '../schemas';\r\n\r\n/**\r\n * Candles (OHLCV) API resource\r\n *\r\n * @example\r\n * ```typescript\r\n * // Get candle history with cursor-based pagination\r\n * let result = await client.hyperliquid.candles.history('BTC', {\r\n * start: Date.now() - 86400000,\r\n * end: Date.now(),\r\n * interval: '1h',\r\n * limit: 10000\r\n * });\r\n *\r\n * // Get all pages\r\n * const allCandles = [...result.data];\r\n * while (result.nextCursor) {\r\n * result = await client.hyperliquid.candles.history('BTC', {\r\n * start: Date.now() - 86400000,\r\n * end: Date.now(),\r\n * interval: '1h',\r\n * cursor: result.nextCursor,\r\n * limit: 10000\r\n * });\r\n * allCandles.push(...result.data);\r\n * }\r\n *\r\n * // Iterate through candles\r\n * for (const candle of allCandles) {\r\n * console.log(`${candle.timestamp}: O=${candle.open} H=${candle.high} L=${candle.low} C=${candle.close}`);\r\n * }\r\n * ```\r\n */\r\nexport class CandlesResource {\r\n constructor(\r\n private http: HttpClient,\r\n private basePath: string = '/v1',\r\n private coinTransform: (coin: string) => string = (c) => c.toUpperCase()\r\n ) {}\r\n\r\n /**\r\n * Get historical OHLCV candle data with cursor-based pagination\r\n *\r\n * @param symbol - The symbol (e.g., 'BTC', 'ETH')\r\n * @param params - Time range, interval, and cursor pagination parameters (start and end are required)\r\n * @returns CursorResponse with candle records and nextCursor for pagination\r\n */\r\n async history(symbol: string, params: CandleHistoryParams): Promise<CursorResponse<Candle[]>> {\r\n const response = await this.http.get<ApiResponse<Candle[]>>(\r\n `${this.basePath}/candles/${this.coinTransform(symbol)}`,\r\n params as unknown as Record<string, unknown>,\r\n this.http.validationEnabled ? CandleArrayResponseSchema : undefined\r\n );\r\n return {\r\n data: response.data,\r\n nextCursor: response.meta.nextCursor,\r\n };\r\n }\r\n}\r\n","import type { HttpClient } from '../http';\r\nimport type { ApiResponse, CursorResponse, Liquidation, LiquidationHistoryParams, LiquidationsByUserParams, LiquidationVolume, LiquidationVolumeParams } from '../types';\r\nimport { LiquidationArrayResponseSchema, LiquidationVolumeArrayResponseSchema } from '../schemas';\r\n\r\n/**\r\n * Liquidations API resource\r\n *\r\n * Retrieve historical liquidation events from Hyperliquid.\r\n *\r\n * Note: Liquidation data is available from May 25, 2025 onwards.\r\n *\r\n * @example\r\n * ```typescript\r\n * // Get recent liquidations for a coin\r\n * let result = await client.hyperliquid.liquidations.history('BTC', {\r\n * start: Date.now() - 86400000,\r\n * end: Date.now(),\r\n * limit: 1000\r\n * });\r\n *\r\n * // Get all pages\r\n * const allLiquidations = [...result.data];\r\n * while (result.nextCursor) {\r\n * result = await client.hyperliquid.liquidations.history('BTC', {\r\n * start: Date.now() - 86400000,\r\n * end: Date.now(),\r\n * cursor: result.nextCursor,\r\n * limit: 1000\r\n * });\r\n * allLiquidations.push(...result.data);\r\n * }\r\n *\r\n * // Get liquidations for a specific user\r\n * const userLiquidations = await client.hyperliquid.liquidations.byUser('0x1234...', {\r\n * start: Date.now() - 86400000 * 7,\r\n * end: Date.now()\r\n * });\r\n * ```\r\n */\r\nexport class LiquidationsResource {\r\n constructor(\r\n private http: HttpClient,\r\n private basePath: string = '/v1',\r\n private coinTransform: (coin: string) => string = (c) => c.toUpperCase()\r\n ) {}\r\n\r\n /**\r\n * Get liquidation history for a symbol with cursor-based pagination\r\n *\r\n * @param symbol - The symbol (e.g., 'BTC', 'ETH')\r\n * @param params - Time range and cursor pagination parameters (start and end are required)\r\n * @returns CursorResponse with liquidation records and nextCursor for pagination\r\n */\r\n async history(symbol: string, params: LiquidationHistoryParams): Promise<CursorResponse<Liquidation[]>> {\r\n const response = await this.http.get<ApiResponse<Liquidation[]>>(\r\n `${this.basePath}/liquidations/${this.coinTransform(symbol)}`,\r\n params as unknown as Record<string, unknown>,\r\n this.http.validationEnabled ? LiquidationArrayResponseSchema : undefined\r\n );\r\n return {\r\n data: response.data,\r\n nextCursor: response.meta.nextCursor,\r\n };\r\n }\r\n\r\n /**\r\n * Get liquidation history for a specific user\r\n *\r\n * This returns liquidations where the user was either:\r\n * - The liquidated party (their position was liquidated)\r\n * - The liquidator (they executed the liquidation)\r\n *\r\n * @param userAddress - User's wallet address (e.g., '0x1234...')\r\n * @param params - Time range and cursor pagination parameters (start and end are required)\r\n * @returns CursorResponse with liquidation records and nextCursor for pagination\r\n */\r\n async byUser(userAddress: string, params: LiquidationsByUserParams): Promise<CursorResponse<Liquidation[]>> {\r\n const response = await this.http.get<ApiResponse<Liquidation[]>>(\r\n `${this.basePath}/liquidations/user/${userAddress}`,\r\n params as unknown as Record<string, unknown>,\r\n this.http.validationEnabled ? LiquidationArrayResponseSchema : undefined\r\n );\r\n return {\r\n data: response.data,\r\n nextCursor: response.meta.nextCursor,\r\n };\r\n }\r\n\r\n /**\r\n * Get aggregated liquidation volume in time-bucketed intervals\r\n *\r\n * Returns pre-aggregated data with total/long/short USD volumes per bucket,\r\n * reducing data transfer by 100-1000x compared to individual liquidation records.\r\n *\r\n * @param symbol - The symbol (e.g., 'BTC', 'ETH')\r\n * @param params - Time range, cursor, and interval parameters\r\n * @returns CursorResponse with liquidation volume buckets\r\n */\r\n async volume(symbol: string, params: LiquidationVolumeParams): Promise<CursorResponse<LiquidationVolume[]>> {\r\n const response = await this.http.get<ApiResponse<LiquidationVolume[]>>(\r\n `${this.basePath}/liquidations/${this.coinTransform(symbol)}/volume`,\r\n params as unknown as Record<string, unknown>,\r\n this.http.validationEnabled ? LiquidationVolumeArrayResponseSchema as any : undefined\r\n );\r\n return {\r\n data: response.data,\r\n nextCursor: response.meta.nextCursor,\r\n };\r\n }\r\n}\r\n","import type { HttpClient } from '../http';\r\nimport type {\r\n CoverageResponse,\r\n ExchangeCoverage,\r\n Incident,\r\n IncidentsResponse,\r\n LatencyResponse,\r\n ListIncidentsParams,\r\n SlaParams,\r\n SlaResponse,\r\n StatusResponse,\r\n SymbolCoverageOptions,\r\n SymbolCoverageResponse,\r\n} from '../types';\r\n\r\n/**\r\n * Data quality API resource\r\n *\r\n * Provides endpoints for monitoring data quality, coverage, incidents, and SLA metrics.\r\n *\r\n * @example\r\n * ```typescript\r\n * // Get system status\r\n * const status = await client.dataQuality.status();\r\n * console.log(`System status: ${status.status}`);\r\n *\r\n * // Get coverage for all exchanges\r\n * const coverage = await client.dataQuality.coverage();\r\n *\r\n * // Get symbol-specific coverage with gap detection\r\n * const btc = await client.dataQuality.symbolCoverage('hyperliquid', 'BTC');\r\n * console.log(`BTC OI completeness: ${btc.dataTypes.open_interest.completeness}%`);\r\n * for (const gap of btc.dataTypes.open_interest.gaps.slice(0, 5)) {\r\n * console.log(`Gap: ${gap.start} - ${gap.end} (${gap.durationMinutes} min)`);\r\n * }\r\n * ```\r\n */\r\nexport class DataQualityResource {\r\n constructor(private http: HttpClient, private basePath: string = '/v1/data-quality') {}\r\n\r\n // ===========================================================================\r\n // Status Endpoints\r\n // ===========================================================================\r\n\r\n /**\r\n * Get overall system health status\r\n *\r\n * @returns StatusResponse with overall status, per-exchange status,\r\n * per-data-type status, and active incident count\r\n *\r\n * @example\r\n * ```typescript\r\n * const status = await client.dataQuality.status();\r\n * console.log(`Overall: ${status.status}`);\r\n * for (const [exchange, info] of Object.entries(status.exchanges)) {\r\n * console.log(`${exchange}: ${info.status}`);\r\n * }\r\n * ```\r\n */\r\n async status(): Promise<StatusResponse> {\r\n return this.http.get<StatusResponse>(`${this.basePath}/status`);\r\n }\r\n\r\n // ===========================================================================\r\n // Coverage Endpoints\r\n // ===========================================================================\r\n\r\n /**\r\n * Get data coverage summary for all exchanges\r\n *\r\n * @returns CoverageResponse with coverage info for all exchanges and data types\r\n *\r\n * @example\r\n * ```typescript\r\n * const coverage = await client.dataQuality.coverage();\r\n * for (const exchange of coverage.exchanges) {\r\n * console.log(`${exchange.exchange}:`);\r\n * for (const [dtype, info] of Object.entries(exchange.dataTypes)) {\r\n * console.log(` ${dtype}: ${info.totalRecords} records`);\r\n * }\r\n * }\r\n * ```\r\n */\r\n async coverage(): Promise<CoverageResponse> {\r\n return this.http.get<CoverageResponse>(`${this.basePath}/coverage`);\r\n }\r\n\r\n /**\r\n * Get data coverage for a specific exchange\r\n *\r\n * @param exchange - Exchange name ('hyperliquid', 'lighter', or 'hip3')\r\n * @returns ExchangeCoverage with coverage info for all data types on this exchange\r\n *\r\n * @example\r\n * ```typescript\r\n * const hl = await client.dataQuality.exchangeCoverage('hyperliquid');\r\n * console.log(`Orderbook earliest: ${hl.dataTypes.orderbook.earliest}`);\r\n * ```\r\n */\r\n async exchangeCoverage(exchange: string): Promise<ExchangeCoverage> {\r\n return this.http.get<ExchangeCoverage>(\r\n `${this.basePath}/coverage/${exchange.toLowerCase()}`\r\n );\r\n }\r\n\r\n /**\r\n * Get data coverage for a specific symbol on an exchange\r\n *\r\n * Includes gap detection, empirical data cadence, and hour-level historical coverage.\r\n * Supports optional time bounds for gap detection (default: last 30 days).\r\n *\r\n * @param exchange - Exchange name ('hyperliquid', 'lighter', or 'hip3')\r\n * @param symbol - Symbol name (e.g., 'BTC', 'ETH', or HIP3 coins like 'xyz:XYZ100')\r\n * @param options - Optional time bounds for gap detection window\r\n * @returns SymbolCoverageResponse with per-data-type coverage including gaps, cadence, and historical coverage\r\n *\r\n * @example\r\n * ```typescript\r\n * const btc = await client.dataQuality.symbolCoverage('hyperliquid', 'BTC');\r\n * const oi = btc.dataTypes.open_interest;\r\n * console.log(`OI completeness: ${oi.completeness}%`);\r\n * console.log(`Gaps found: ${oi.gaps.length}`);\r\n * for (const gap of oi.gaps.slice(0, 3)) {\r\n * console.log(` ${gap.durationMinutes} min gap at ${gap.start}`);\r\n * }\r\n *\r\n * // Check cadence\r\n * if (btc.dataTypes.orderbook.cadence) {\r\n * console.log(`Cadence: ~${btc.dataTypes.orderbook.cadence.medianIntervalSeconds}s`);\r\n * }\r\n *\r\n * // Time-bounded (last 7 days)\r\n * const weekAgo = Date.now() - 7 * 24 * 60 * 60 * 1000;\r\n * const btc7d = await client.dataQuality.symbolCoverage('hyperliquid', 'BTC', {\r\n * from: weekAgo,\r\n * to: Date.now(),\r\n * });\r\n * ```\r\n */\r\n async symbolCoverage(\r\n exchange: string,\r\n symbol: string,\r\n options?: SymbolCoverageOptions,\r\n ): Promise<SymbolCoverageResponse> {\r\n return this.http.get<SymbolCoverageResponse>(\r\n `${this.basePath}/coverage/${exchange.toLowerCase()}/${symbol}`,\r\n options as unknown as Record<string, unknown>\r\n );\r\n }\r\n\r\n // ===========================================================================\r\n // Incidents Endpoints\r\n // ===========================================================================\r\n\r\n /**\r\n * List incidents with filtering and pagination\r\n *\r\n * @param params - Filter and pagination options\r\n * @returns IncidentsResponse with list of incidents and pagination info\r\n *\r\n * @example\r\n * ```typescript\r\n * // Get all open incidents\r\n * const result = await client.dataQuality.listIncidents({ status: 'open' });\r\n * for (const incident of result.incidents) {\r\n * console.log(`${incident.severity}: ${incident.title}`);\r\n * }\r\n * ```\r\n */\r\n async listIncidents(params?: ListIncidentsParams): Promise<IncidentsResponse> {\r\n return this.http.get<IncidentsResponse>(\r\n `${this.basePath}/incidents`,\r\n params as unknown as Record<string, unknown>\r\n );\r\n }\r\n\r\n /**\r\n * Get a specific incident by ID\r\n *\r\n * @param incidentId - The incident ID\r\n * @returns Incident details\r\n *\r\n * @example\r\n * ```typescript\r\n * const incident = await client.dataQuality.getIncident('inc_123');\r\n * console.log(`Status: ${incident.status}`);\r\n * console.log(`Root cause: ${incident.rootCause}`);\r\n * ```\r\n */\r\n async getIncident(incidentId: string): Promise<Incident> {\r\n return this.http.get<Incident>(`${this.basePath}/incidents/${incidentId}`);\r\n }\r\n\r\n // ===========================================================================\r\n // Latency Endpoints\r\n // ===========================================================================\r\n\r\n /**\r\n * Get current latency metrics for all exchanges\r\n *\r\n * @returns LatencyResponse with WebSocket, REST API, and data freshness metrics\r\n *\r\n * @example\r\n * ```typescript\r\n * const latency = await client.dataQuality.latency();\r\n * for (const [exchange, metrics] of Object.entries(latency.exchanges)) {\r\n * console.log(`${exchange}:`);\r\n * if (metrics.websocket) {\r\n * console.log(` WS current: ${metrics.websocket.currentMs}ms`);\r\n * }\r\n * console.log(` OB lag: ${metrics.dataFreshness.orderbookLagMs}ms`);\r\n * }\r\n * ```\r\n */\r\n async latency(): Promise<LatencyResponse> {\r\n return this.http.get<LatencyResponse>(`${this.basePath}/latency`);\r\n }\r\n\r\n // ===========================================================================\r\n // SLA Endpoints\r\n // ===========================================================================\r\n\r\n /**\r\n * Get SLA compliance metrics for a specific month\r\n *\r\n * @param params - Optional year and month (defaults to current month)\r\n * @returns SlaResponse with SLA targets, actual metrics, and compliance status\r\n *\r\n * @example\r\n * ```typescript\r\n * const sla = await client.dataQuality.sla({ year: 2026, month: 1 });\r\n * console.log(`Period: ${sla.period}`);\r\n * console.log(`Uptime: ${sla.actual.uptime}% (${sla.actual.uptimeStatus})`);\r\n * console.log(`Completeness: ${sla.actual.dataCompleteness.overall}%`);\r\n * console.log(`API P99: ${sla.actual.apiLatencyP99Ms}ms`);\r\n * ```\r\n */\r\n async sla(params?: SlaParams): Promise<SlaResponse> {\r\n return this.http.get<SlaResponse>(\r\n `${this.basePath}/sla`,\r\n params as unknown as Record<string, unknown>\r\n );\r\n }\r\n}\r\n","import { type HttpClient, transformKeys } from '../http';\r\nimport {\r\n type SiweChallenge,\r\n type Web3SignupResult,\r\n type Web3KeysList,\r\n type Web3RevokeResult,\r\n type Web3PaymentRequired,\r\n type Web3SubscribeResult,\r\n OxArchiveError,\r\n} from '../types';\r\n\r\n/**\r\n * Wallet-based authentication: get API keys via SIWE signature.\r\n *\r\n * No API key is required for these endpoints. Use an Ethereum wallet to\r\n * create a free-tier account, list keys, or revoke keys — all programmatically.\r\n *\r\n * @example\r\n * ```typescript\r\n * const client = new OxArchive({ apiKey: 'placeholder' });\r\n *\r\n * // Step 1: Get a challenge\r\n * const challenge = await client.web3.challenge('0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18');\r\n *\r\n * // Step 2: Sign the message with your wallet, then submit\r\n * const result = await client.web3.signup(challenge.message, signature);\r\n * console.log(`API key: ${result.apiKey}`);\r\n * ```\r\n */\r\nexport class Web3Resource {\r\n constructor(private http: HttpClient) {}\r\n\r\n /**\r\n * Get a SIWE challenge message to sign.\r\n *\r\n * @param address - Ethereum wallet address\r\n * @returns SIWE message and nonce. Sign the message with personal_sign (EIP-191).\r\n */\r\n async challenge(address: string): Promise<SiweChallenge> {\r\n return this.http.post<SiweChallenge>('/v1/auth/web3/challenge', { address });\r\n }\r\n\r\n /**\r\n * Create a free-tier account and get an API key.\r\n *\r\n * @param message - The SIWE message from {@link challenge}\r\n * @param signature - Hex-encoded signature from personal_sign\r\n * @returns API key, tier, and wallet address\r\n */\r\n async signup(message: string, signature: string): Promise<Web3SignupResult> {\r\n return this.http.post<Web3SignupResult>('/v1/web3/signup', { message, signature });\r\n }\r\n\r\n /**\r\n * List all API keys for the authenticated wallet.\r\n *\r\n * @param message - The SIWE message from {@link challenge}\r\n * @param signature - Hex-encoded signature from personal_sign\r\n * @returns List of API keys and wallet address\r\n */\r\n async listKeys(message: string, signature: string): Promise<Web3KeysList> {\r\n return this.http.post<Web3KeysList>('/v1/web3/keys', { message, signature });\r\n }\r\n\r\n /**\r\n * Revoke a specific API key.\r\n *\r\n * @param message - The SIWE message from {@link challenge}\r\n * @param signature - Hex-encoded signature from personal_sign\r\n * @param keyId - UUID of the key to revoke\r\n * @returns Confirmation message and wallet address\r\n */\r\n async revokeKey(message: string, signature: string, keyId: string): Promise<Web3RevokeResult> {\r\n return this.http.post<Web3RevokeResult>('/v1/web3/keys/revoke', {\r\n message,\r\n signature,\r\n key_id: keyId,\r\n });\r\n }\r\n\r\n /**\r\n * Get pricing info for a paid subscription (x402 flow, step 1).\r\n *\r\n * Returns the payment details needed to sign a USDC transfer on Base.\r\n * After signing, pass the payment signature to {@link subscribe}.\r\n *\r\n * @param tier - Subscription tier: 'build' ($49/mo) or 'pro' ($199/mo)\r\n * @returns Payment details (amount, asset, network, pay-to address)\r\n */\r\n async subscribeQuote(tier: 'build' | 'pro'): Promise<Web3PaymentRequired> {\r\n const url = `${this.http.getBaseUrl()}/v1/web3/subscribe`;\r\n const timeout = this.http.getTimeout();\r\n const controller = new AbortController();\r\n const timeoutId = setTimeout(() => controller.abort(), timeout);\r\n\r\n try {\r\n const response = await fetch(url, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ tier }),\r\n signal: controller.signal,\r\n });\r\n\r\n clearTimeout(timeoutId);\r\n\r\n const rawData = await response.json();\r\n const data = transformKeys(rawData) as Record<string, unknown>;\r\n if (response.status === 402) {\r\n return (data as Record<string, unknown>).payment as unknown as Web3PaymentRequired;\r\n }\r\n throw new OxArchiveError(\r\n (data as Record<string, unknown>).error as string || `Unexpected status ${response.status}`,\r\n response.status\r\n );\r\n } catch (error) {\r\n clearTimeout(timeoutId);\r\n if (error instanceof OxArchiveError) throw error;\r\n if (error instanceof Error && error.name === 'AbortError') {\r\n throw new OxArchiveError(`Request timeout after ${timeout}ms`, 408);\r\n }\r\n throw new OxArchiveError(\r\n error instanceof Error ? error.message : 'Unknown error', 500\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Complete a paid subscription with a signed x402 payment (step 2).\r\n *\r\n * Requires a payment signature from signing a USDC transfer (EIP-3009)\r\n * for the amount returned by {@link subscribeQuote}.\r\n *\r\n * @param tier - Subscription tier: 'build' or 'pro'\r\n * @param paymentSignature - Signed x402 payment (from EIP-3009 USDC transfer on Base)\r\n * @returns API key, tier, expiration, and wallet address\r\n */\r\n async subscribe(tier: 'build' | 'pro', paymentSignature: string): Promise<Web3SubscribeResult> {\r\n const url = `${this.http.getBaseUrl()}/v1/web3/subscribe`;\r\n const timeout = this.http.getTimeout();\r\n const controller = new AbortController();\r\n const timeoutId = setTimeout(() => controller.abort(), timeout);\r\n\r\n try {\r\n const response = await fetch(url, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'payment-signature': paymentSignature,\r\n },\r\n body: JSON.stringify({ tier }),\r\n signal: controller.signal,\r\n });\r\n\r\n clearTimeout(timeoutId);\r\n\r\n const rawData = await response.json();\r\n const data = transformKeys(rawData) as Record<string, unknown>;\r\n if (!response.ok) {\r\n throw new OxArchiveError(\r\n (data as Record<string, unknown>).error as string || 'Subscribe failed',\r\n response.status\r\n );\r\n }\r\n return data as unknown as Web3SubscribeResult;\r\n } catch (error) {\r\n clearTimeout(timeoutId);\r\n if (error instanceof OxArchiveError) throw error;\r\n if (error instanceof Error && error.name === 'AbortError') {\r\n throw new OxArchiveError(`Request timeout after ${timeout}ms`, 408);\r\n }\r\n throw new OxArchiveError(\r\n error instanceof Error ? error.message : 'Unknown error', 500\r\n );\r\n }\r\n }\r\n}\r\n","import type { HttpClient } from '../http';\r\nimport type { ApiResponse, CursorResponse, CursorPaginationParams } from '../types';\r\n\r\nexport interface OrderHistoryParams extends CursorPaginationParams {\r\n user?: string;\r\n status?: string;\r\n order_type?: string;\r\n}\r\n\r\nexport interface OrderFlowParams {\r\n start: number | string;\r\n end: number | string;\r\n interval?: string;\r\n limit?: number;\r\n}\r\n\r\nexport interface TpslParams extends CursorPaginationParams {\r\n user?: string;\r\n triggered?: boolean;\r\n}\r\n\r\n/**\r\n * Orders API resource\r\n *\r\n * @example\r\n * ```typescript\r\n * // Get order history\r\n * const result = await client.hyperliquid.orders.history('BTC', {\r\n * start: Date.now() - 86400000,\r\n * end: Date.now(),\r\n * limit: 1000\r\n * });\r\n *\r\n * // Get order flow\r\n * const flow = await client.hyperliquid.orders.flow('BTC', {\r\n * start: Date.now() - 86400000,\r\n * end: Date.now(),\r\n * interval: '1h'\r\n * });\r\n *\r\n * // Get TP/SL orders\r\n * const tpsl = await client.hyperliquid.orders.tpsl('BTC', {\r\n * start: Date.now() - 86400000,\r\n * end: Date.now()\r\n * });\r\n * ```\r\n */\r\nexport class OrdersResource {\r\n constructor(\r\n private http: HttpClient,\r\n private basePath: string = '/v1',\r\n private coinTransform: (s: string) => string = (c) => c.toUpperCase()\r\n ) {}\r\n\r\n /**\r\n * Get order history for a symbol with cursor-based pagination\r\n *\r\n * @param symbol - The symbol (e.g., 'BTC', 'ETH')\r\n * @param params - Time range, cursor pagination, and filter parameters\r\n * @returns CursorResponse with order records and nextCursor for pagination\r\n */\r\n async history(symbol: string, params: OrderHistoryParams): Promise<CursorResponse<any[]>> {\r\n const response = await this.http.get<ApiResponse<any[]>>(\r\n `${this.basePath}/orders/${this.coinTransform(symbol)}/history`,\r\n params as unknown as Record<string, unknown>\r\n );\r\n return { data: response.data, nextCursor: response.meta.nextCursor };\r\n }\r\n\r\n /**\r\n * Get order flow for a symbol\r\n *\r\n * @param symbol - The symbol (e.g., 'BTC', 'ETH')\r\n * @param params - Time range and interval parameters\r\n * @returns CursorResponse with order flow records\r\n */\r\n async flow(symbol: string, params: OrderFlowParams): Promise<CursorResponse<any[]>> {\r\n const response = await this.http.get<ApiResponse<any[]>>(\r\n `${this.basePath}/orders/${this.coinTransform(symbol)}/flow`,\r\n params as unknown as Record<string, unknown>\r\n );\r\n return { data: response.data, nextCursor: response.meta.nextCursor };\r\n }\r\n\r\n /**\r\n * Get TP/SL orders for a symbol with cursor-based pagination\r\n *\r\n * @param symbol - The symbol (e.g., 'BTC', 'ETH')\r\n * @param params - Time range, cursor pagination, and filter parameters\r\n * @returns CursorResponse with TP/SL order records\r\n */\r\n async tpsl(symbol: string, params: TpslParams): Promise<CursorResponse<any[]>> {\r\n const response = await this.http.get<ApiResponse<any[]>>(\r\n `${this.basePath}/orders/${this.coinTransform(symbol)}/tpsl`,\r\n params as unknown as Record<string, unknown>\r\n );\r\n return { data: response.data, nextCursor: response.meta.nextCursor };\r\n }\r\n}\r\n","import type { HttpClient } from '../http';\r\nimport type { ApiResponse, CursorResponse, CursorPaginationParams } from '../types';\r\n\r\nexport interface L4OrderBookParams {\r\n timestamp?: number | string;\r\n depth?: number;\r\n}\r\n\r\n/**\r\n * L4 Order Book API resource\r\n *\r\n * Access L4 orderbook snapshots, diffs, and history.\r\n *\r\n * @example\r\n * ```typescript\r\n * // Get current L4 orderbook\r\n * const orderbook = await client.hyperliquid.l4Orderbook.get('BTC');\r\n *\r\n * // Get L4 orderbook diffs\r\n * const diffs = await client.hyperliquid.l4Orderbook.diffs('BTC', {\r\n * start: Date.now() - 86400000,\r\n * end: Date.now(),\r\n * limit: 1000\r\n * });\r\n *\r\n * // Get L4 orderbook history\r\n * const history = await client.hyperliquid.l4Orderbook.history('BTC', {\r\n * start: Date.now() - 86400000,\r\n * end: Date.now(),\r\n * limit: 1000\r\n * });\r\n * ```\r\n */\r\nexport class L4OrderBookResource {\r\n constructor(\r\n private http: HttpClient,\r\n private basePath: string = '/v1',\r\n private coinTransform: (s: string) => string = (c) => c.toUpperCase()\r\n ) {}\r\n\r\n /**\r\n * Get L4 order book snapshot for a symbol\r\n *\r\n * @param symbol - The symbol (e.g., 'BTC', 'ETH')\r\n * @param params - Optional parameters (timestamp, depth)\r\n * @returns L4 order book snapshot\r\n */\r\n async get(symbol: string, params?: L4OrderBookParams): Promise<any> {\r\n const response = await this.http.get<ApiResponse<any>>(\r\n `${this.basePath}/orderbook/${this.coinTransform(symbol)}/l4`,\r\n params as Record<string, unknown>\r\n );\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Get L4 order book diffs with cursor-based pagination\r\n *\r\n * @param symbol - The symbol (e.g., 'BTC', 'ETH')\r\n * @param params - Time range and cursor pagination parameters\r\n * @returns CursorResponse with L4 orderbook diffs and nextCursor for pagination\r\n */\r\n async diffs(symbol: string, params: CursorPaginationParams): Promise<CursorResponse<any[]>> {\r\n const response = await this.http.get<ApiResponse<any[]>>(\r\n `${this.basePath}/orderbook/${this.coinTransform(symbol)}/l4/diffs`,\r\n params as unknown as Record<string, unknown>\r\n );\r\n return { data: response.data, nextCursor: response.meta.nextCursor };\r\n }\r\n\r\n /**\r\n * Get L4 order book history with cursor-based pagination\r\n *\r\n * @param symbol - The symbol (e.g., 'BTC', 'ETH')\r\n * @param params - Time range and cursor pagination parameters\r\n * @returns CursorResponse with L4 orderbook snapshots and nextCursor for pagination\r\n */\r\n async history(symbol: string, params: CursorPaginationParams): Promise<CursorResponse<any[]>> {\r\n const response = await this.http.get<ApiResponse<any[]>>(\r\n `${this.basePath}/orderbook/${this.coinTransform(symbol)}/l4/history`,\r\n params as unknown as Record<string, unknown>\r\n );\r\n return { data: response.data, nextCursor: response.meta.nextCursor };\r\n }\r\n}\r\n","import type { HttpClient } from '../http';\r\nimport type { ApiResponse, CursorResponse, CursorPaginationParams } from '../types';\r\n\r\nexport interface L3OrderBookParams {\r\n timestamp?: number | string;\r\n depth?: number;\r\n}\r\n\r\n/**\r\n * L3 Order Book API resource (Lighter only)\r\n *\r\n * Access L3 orderbook snapshots and history from Lighter.xyz.\r\n *\r\n * @example\r\n * ```typescript\r\n * // Get current L3 orderbook\r\n * const orderbook = await client.lighter.l3Orderbook.get('BTC');\r\n *\r\n * // Get L3 orderbook history\r\n * const history = await client.lighter.l3Orderbook.history('BTC', {\r\n * start: Date.now() - 86400000,\r\n * end: Date.now(),\r\n * limit: 1000\r\n * });\r\n * ```\r\n */\r\nexport class L3OrderBookResource {\r\n constructor(\r\n private http: HttpClient,\r\n private basePath: string = '/v1',\r\n private coinTransform: (s: string) => string = (c) => c.toUpperCase()\r\n ) {}\r\n\r\n /**\r\n * Get L3 order book snapshot for a symbol\r\n *\r\n * @param symbol - The symbol (e.g., 'BTC', 'ETH')\r\n * @param params - Optional parameters (timestamp, depth)\r\n * @returns L3 order book snapshot\r\n */\r\n async get(symbol: string, params?: L3OrderBookParams): Promise<any> {\r\n const response = await this.http.get<ApiResponse<any>>(\r\n `${this.basePath}/l3orderbook/${this.coinTransform(symbol)}`,\r\n params as Record<string, unknown>\r\n );\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Get L3 order book history with cursor-based pagination\r\n *\r\n * @param symbol - The symbol (e.g., 'BTC', 'ETH')\r\n * @param params - Time range and cursor pagination parameters\r\n * @returns CursorResponse with L3 orderbook snapshots and nextCursor for pagination\r\n */\r\n async history(symbol: string, params: CursorPaginationParams): Promise<CursorResponse<any[]>> {\r\n const response = await this.http.get<ApiResponse<any[]>>(\r\n `${this.basePath}/l3orderbook/${this.coinTransform(symbol)}/history`,\r\n params as unknown as Record<string, unknown>\r\n );\r\n return { data: response.data, nextCursor: response.meta.nextCursor };\r\n }\r\n}\r\n","import type { HttpClient } from './http';\r\nimport type { ApiResponse, CursorResponse, CoinFreshness, CoinSummary, PriceSnapshot, PriceHistoryParams } from './types';\r\nimport {\r\n OrderBookResource,\r\n TradesResource,\r\n InstrumentsResource,\r\n LighterInstrumentsResource,\r\n Hip3InstrumentsResource,\r\n FundingResource,\r\n OpenInterestResource,\r\n CandlesResource,\r\n LiquidationsResource,\r\n OrdersResource,\r\n L4OrderBookResource,\r\n L3OrderBookResource,\r\n} from './resources';\r\nimport {\r\n CoinFreshnessResponseSchema,\r\n CoinSummaryResponseSchema,\r\n PriceSnapshotArrayResponseSchema,\r\n} from './schemas';\r\n\r\n/**\r\n * Hyperliquid exchange client\r\n *\r\n * Access Hyperliquid market data through the 0xarchive API.\r\n *\r\n * @example\r\n * ```typescript\r\n * const client = new OxArchive({ apiKey: '...' });\r\n * const orderbook = await client.hyperliquid.orderbook.get('BTC');\r\n * const trades = await client.hyperliquid.trades.list('ETH', { start, end });\r\n * ```\r\n */\r\nexport class HyperliquidClient {\r\n /**\r\n * Order book data (L2 snapshots from April 2023)\r\n */\r\n public readonly orderbook: OrderBookResource;\r\n\r\n /**\r\n * Trade/fill history\r\n */\r\n public readonly trades: TradesResource;\r\n\r\n /**\r\n * Trading instruments metadata\r\n */\r\n public readonly instruments: InstrumentsResource;\r\n\r\n /**\r\n * Funding rates\r\n */\r\n public readonly funding: FundingResource;\r\n\r\n /**\r\n * Open interest\r\n */\r\n public readonly openInterest: OpenInterestResource;\r\n\r\n /**\r\n * OHLCV candle data\r\n */\r\n public readonly candles: CandlesResource;\r\n\r\n /**\r\n * Liquidation events (May 2025+)\r\n */\r\n public readonly liquidations: LiquidationsResource;\r\n\r\n /**\r\n * Order history, flow, and TP/SL\r\n */\r\n public readonly orders: OrdersResource;\r\n\r\n /**\r\n * L4 order book (snapshots, diffs, history)\r\n */\r\n public readonly l4Orderbook: L4OrderBookResource;\r\n\r\n /**\r\n * HIP-3 builder-deployed perpetuals (February 2026+)\r\n */\r\n public readonly hip3: Hip3Client;\r\n\r\n private http: HttpClient;\r\n\r\n constructor(http: HttpClient) {\r\n this.http = http;\r\n const basePath = '/v1/hyperliquid';\r\n this.orderbook = new OrderBookResource(http, basePath);\r\n this.trades = new TradesResource(http, basePath);\r\n this.instruments = new InstrumentsResource(http, basePath);\r\n this.funding = new FundingResource(http, basePath);\r\n this.openInterest = new OpenInterestResource(http, basePath);\r\n this.candles = new CandlesResource(http, basePath);\r\n this.liquidations = new LiquidationsResource(http, basePath);\r\n this.orders = new OrdersResource(http, basePath);\r\n this.l4Orderbook = new L4OrderBookResource(http, basePath);\r\n this.hip3 = new Hip3Client(http);\r\n }\r\n\r\n /**\r\n * Get per-symbol data freshness across all data types\r\n *\r\n * @param symbol - The symbol (e.g., 'BTC', 'ETH')\r\n * @returns Per-symbol freshness with last_updated and lag_ms for each data type\r\n */\r\n async freshness(symbol: string): Promise<CoinFreshness> {\r\n const response = await this.http.get<ApiResponse<CoinFreshness>>(\r\n `/v1/hyperliquid/freshness/${symbol.toUpperCase()}`,\r\n undefined,\r\n this.http.validationEnabled ? CoinFreshnessResponseSchema as any : undefined\r\n );\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Get combined market summary (price, funding, OI, volume, liquidations) in one call\r\n *\r\n * @param symbol - The symbol (e.g., 'BTC', 'ETH')\r\n * @returns Combined market summary\r\n */\r\n async summary(symbol: string): Promise<CoinSummary> {\r\n const response = await this.http.get<ApiResponse<CoinSummary>>(\r\n `/v1/hyperliquid/summary/${symbol.toUpperCase()}`,\r\n undefined,\r\n this.http.validationEnabled ? CoinSummaryResponseSchema as any : undefined\r\n );\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Get mark/oracle/mid price history (projected from OI data)\r\n *\r\n * @param symbol - The symbol (e.g., 'BTC', 'ETH')\r\n * @param params - Time range, cursor, and interval parameters\r\n * @returns CursorResponse with price snapshots\r\n */\r\n async priceHistory(symbol: string, params: PriceHistoryParams): Promise<CursorResponse<PriceSnapshot[]>> {\r\n const response = await this.http.get<ApiResponse<PriceSnapshot[]>>(\r\n `/v1/hyperliquid/prices/${symbol.toUpperCase()}`,\r\n params as unknown as Record<string, unknown>,\r\n this.http.validationEnabled ? PriceSnapshotArrayResponseSchema as any : undefined\r\n );\r\n return {\r\n data: response.data,\r\n nextCursor: response.meta.nextCursor,\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * HIP-3 builder-deployed perpetuals client\r\n *\r\n * Access Hyperliquid HIP-3 builder perps data through the 0xarchive API.\r\n * Free: km:US500 only. Build+: all coins. Orderbook: Pro+.\r\n *\r\n * @example\r\n * ```typescript\r\n * const client = new OxArchive({ apiKey: '...' });\r\n * const orderbook = await client.hyperliquid.hip3.orderbook.get('xyz:XYZ100');\r\n * const trades = await client.hyperliquid.hip3.trades.recent('xyz:XYZ100');\r\n * ```\r\n */\r\nexport class Hip3Client {\r\n /**\r\n * HIP-3 instruments with latest market data\r\n */\r\n public readonly instruments: Hip3InstrumentsResource;\r\n\r\n /**\r\n * Order book snapshots (February 2026+)\r\n */\r\n public readonly orderbook: OrderBookResource;\r\n\r\n /**\r\n * Trade/fill history\r\n */\r\n public readonly trades: TradesResource;\r\n\r\n /**\r\n * Funding rates\r\n */\r\n public readonly funding: FundingResource;\r\n\r\n /**\r\n * Open interest\r\n */\r\n public readonly openInterest: OpenInterestResource;\r\n\r\n /**\r\n * OHLCV candle data\r\n */\r\n public readonly candles: CandlesResource;\r\n\r\n /**\r\n * Liquidation events\r\n */\r\n public readonly liquidations: LiquidationsResource;\r\n\r\n /**\r\n * Order history, flow, and TP/SL\r\n */\r\n public readonly orders: OrdersResource;\r\n\r\n /**\r\n * L4 order book (snapshots, diffs, history)\r\n */\r\n public readonly l4Orderbook: L4OrderBookResource;\r\n\r\n private http: HttpClient;\r\n\r\n constructor(http: HttpClient) {\r\n this.http = http;\r\n const basePath = '/v1/hyperliquid/hip3';\r\n // HIP-3 coins use case-sensitive symbols like 'xyz:XYZ100' — do not uppercase\r\n const coinTransform = (c: string) => c;\r\n this.instruments = new Hip3InstrumentsResource(http, basePath, coinTransform);\r\n this.orderbook = new OrderBookResource(http, basePath, coinTransform);\r\n this.trades = new TradesResource(http, basePath, coinTransform);\r\n this.funding = new FundingResource(http, basePath, coinTransform);\r\n this.openInterest = new OpenInterestResource(http, basePath, coinTransform);\r\n this.candles = new CandlesResource(http, basePath, coinTransform);\r\n this.liquidations = new LiquidationsResource(http, basePath, coinTransform);\r\n this.orders = new OrdersResource(http, basePath, coinTransform);\r\n this.l4Orderbook = new L4OrderBookResource(http, basePath, coinTransform);\r\n }\r\n\r\n /**\r\n * Get per-symbol data freshness across all data types\r\n *\r\n * @param symbol - The symbol (case-sensitive, e.g., 'km:US500')\r\n * @returns Per-symbol freshness with last_updated and lag_ms for each data type\r\n */\r\n async freshness(symbol: string): Promise<CoinFreshness> {\r\n const response = await this.http.get<ApiResponse<CoinFreshness>>(\r\n `/v1/hyperliquid/hip3/freshness/${symbol}`,\r\n undefined,\r\n this.http.validationEnabled ? CoinFreshnessResponseSchema as any : undefined\r\n );\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Get combined market summary (price, funding, OI) in one call\r\n *\r\n * @param symbol - The symbol (case-sensitive, e.g., 'km:US500')\r\n * @returns Combined market summary\r\n */\r\n async summary(symbol: string): Promise<CoinSummary> {\r\n const response = await this.http.get<ApiResponse<CoinSummary>>(\r\n `/v1/hyperliquid/hip3/summary/${symbol}`,\r\n undefined,\r\n this.http.validationEnabled ? CoinSummaryResponseSchema as any : undefined\r\n );\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Get mark/oracle/mid price history (projected from OI data)\r\n *\r\n * @param symbol - The symbol (case-sensitive, e.g., 'km:US500')\r\n * @param params - Time range, cursor, and interval parameters\r\n * @returns CursorResponse with price snapshots\r\n */\r\n async priceHistory(symbol: string, params: PriceHistoryParams): Promise<CursorResponse<PriceSnapshot[]>> {\r\n const response = await this.http.get<ApiResponse<PriceSnapshot[]>>(\r\n `/v1/hyperliquid/hip3/prices/${symbol}`,\r\n params as unknown as Record<string, unknown>,\r\n this.http.validationEnabled ? PriceSnapshotArrayResponseSchema as any : undefined\r\n );\r\n return {\r\n data: response.data,\r\n nextCursor: response.meta.nextCursor,\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Lighter.xyz exchange client\r\n *\r\n * Access Lighter.xyz market data through the 0xarchive API.\r\n *\r\n * @example\r\n * ```typescript\r\n * const client = new OxArchive({ apiKey: '...' });\r\n * const orderbook = await client.lighter.orderbook.get('BTC');\r\n * const trades = await client.lighter.trades.list('ETH', { start, end });\r\n * const instruments = await client.lighter.instruments.list();\r\n * console.log(`ETH taker fee: ${instruments[0].takerFee}`);\r\n * ```\r\n */\r\nexport class LighterClient {\r\n /**\r\n * Order book data (L2 snapshots)\r\n */\r\n public readonly orderbook: OrderBookResource;\r\n\r\n /**\r\n * Trade/fill history\r\n */\r\n public readonly trades: TradesResource;\r\n\r\n /**\r\n * Trading instruments metadata (returns LighterInstrument with fees, min amounts, etc.)\r\n */\r\n public readonly instruments: LighterInstrumentsResource;\r\n\r\n /**\r\n * Funding rates\r\n */\r\n public readonly funding: FundingResource;\r\n\r\n /**\r\n * Open interest\r\n */\r\n public readonly openInterest: OpenInterestResource;\r\n\r\n /**\r\n * OHLCV candle data\r\n */\r\n public readonly candles: CandlesResource;\r\n\r\n /**\r\n * L3 order book (Lighter only)\r\n */\r\n public readonly l3Orderbook: L3OrderBookResource;\r\n\r\n private http: HttpClient;\r\n\r\n constructor(http: HttpClient) {\r\n this.http = http;\r\n const basePath = '/v1/lighter';\r\n this.orderbook = new OrderBookResource(http, basePath);\r\n this.trades = new TradesResource(http, basePath);\r\n this.instruments = new LighterInstrumentsResource(http, basePath);\r\n this.funding = new FundingResource(http, basePath);\r\n this.openInterest = new OpenInterestResource(http, basePath);\r\n this.candles = new CandlesResource(http, basePath);\r\n this.l3Orderbook = new L3OrderBookResource(http, basePath);\r\n }\r\n\r\n /**\r\n * Get per-symbol data freshness across all data types\r\n *\r\n * @param symbol - The symbol (e.g., 'BTC', 'ETH')\r\n * @returns Per-symbol freshness with last_updated and lag_ms for each data type\r\n */\r\n async freshness(symbol: string): Promise<CoinFreshness> {\r\n const response = await this.http.get<ApiResponse<CoinFreshness>>(\r\n `/v1/lighter/freshness/${symbol.toUpperCase()}`,\r\n undefined,\r\n this.http.validationEnabled ? CoinFreshnessResponseSchema as any : undefined\r\n );\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Get combined market summary (price, funding, OI) in one call\r\n *\r\n * @param symbol - The symbol (e.g., 'BTC', 'ETH')\r\n * @returns Combined market summary\r\n */\r\n async summary(symbol: string): Promise<CoinSummary> {\r\n const response = await this.http.get<ApiResponse<CoinSummary>>(\r\n `/v1/lighter/summary/${symbol.toUpperCase()}`,\r\n undefined,\r\n this.http.validationEnabled ? CoinSummaryResponseSchema as any : undefined\r\n );\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Get mark/oracle price history (projected from OI data)\r\n *\r\n * @param symbol - The symbol (e.g., 'BTC', 'ETH')\r\n * @param params - Time range, cursor, and interval parameters\r\n * @returns CursorResponse with price snapshots\r\n */\r\n async priceHistory(symbol: string, params: PriceHistoryParams): Promise<CursorResponse<PriceSnapshot[]>> {\r\n const response = await this.http.get<ApiResponse<PriceSnapshot[]>>(\r\n `/v1/lighter/prices/${symbol.toUpperCase()}`,\r\n params as unknown as Record<string, unknown>,\r\n this.http.validationEnabled ? PriceSnapshotArrayResponseSchema as any : undefined\r\n );\r\n return {\r\n data: response.data,\r\n nextCursor: response.meta.nextCursor,\r\n };\r\n }\r\n}\r\n","import type { ClientOptions } from './types';\r\nimport { HttpClient } from './http';\r\nimport { HyperliquidClient, LighterClient } from './exchanges';\r\nimport {\r\n OrderBookResource,\r\n TradesResource,\r\n InstrumentsResource,\r\n FundingResource,\r\n OpenInterestResource,\r\n DataQualityResource,\r\n Web3Resource,\r\n} from './resources';\r\n\r\nconst DEFAULT_BASE_URL = 'https://api.0xarchive.io';\r\nconst DEFAULT_TIMEOUT = 30000;\r\n\r\n/**\r\n * 0xarchive API client\r\n *\r\n * Supports multiple exchanges:\r\n * - `client.hyperliquid` - Hyperliquid perpetuals (April 2023+)\r\n * - `client.lighter` - Lighter.xyz perpetuals\r\n *\r\n * @example\r\n * ```typescript\r\n * import { OxArchive } from '@0xarchive/sdk';\r\n *\r\n * const client = new OxArchive({ apiKey: '0xa_your_api_key' });\r\n *\r\n * // Hyperliquid data\r\n * const hlOrderbook = await client.hyperliquid.orderbook.get('BTC');\r\n * console.log(`BTC mid price: ${hlOrderbook.mid_price}`);\r\n *\r\n * // Lighter.xyz data\r\n * const lighterOrderbook = await client.lighter.orderbook.get('BTC');\r\n *\r\n * // Get historical data\r\n * const history = await client.hyperliquid.orderbook.history('ETH', {\r\n * start: Date.now() - 86400000,\r\n * end: Date.now(),\r\n * limit: 100\r\n * });\r\n *\r\n * // List all instruments\r\n * const instruments = await client.hyperliquid.instruments.list();\r\n * ```\r\n *\r\n * Legacy usage (deprecated, will be removed in v2.0):\r\n * ```typescript\r\n * // These still work but use client.hyperliquid.* instead\r\n * const orderbook = await client.orderbook.get('BTC'); // deprecated\r\n * ```\r\n */\r\nexport class OxArchive {\r\n private http: HttpClient;\r\n\r\n /**\r\n * Hyperliquid exchange data (orderbook, trades, funding, OI from April 2023)\r\n */\r\n public readonly hyperliquid: HyperliquidClient;\r\n\r\n /**\r\n * Lighter.xyz exchange data (August 2025+)\r\n */\r\n public readonly lighter: LighterClient;\r\n\r\n /**\r\n * Data quality metrics: status, coverage, incidents, latency, SLA\r\n */\r\n public readonly dataQuality: DataQualityResource;\r\n\r\n /**\r\n * Wallet-based auth: get API keys via SIWE signature\r\n */\r\n public readonly web3: Web3Resource;\r\n\r\n /**\r\n * @deprecated Use client.hyperliquid.orderbook instead\r\n */\r\n public readonly orderbook: OrderBookResource;\r\n\r\n /**\r\n * @deprecated Use client.hyperliquid.trades instead\r\n */\r\n public readonly trades: TradesResource;\r\n\r\n /**\r\n * @deprecated Use client.hyperliquid.instruments instead\r\n */\r\n public readonly instruments: InstrumentsResource;\r\n\r\n /**\r\n * @deprecated Use client.hyperliquid.funding instead\r\n */\r\n public readonly funding: FundingResource;\r\n\r\n /**\r\n * @deprecated Use client.hyperliquid.openInterest instead\r\n */\r\n public readonly openInterest: OpenInterestResource;\r\n\r\n /**\r\n * Create a new 0xarchive client\r\n *\r\n * @param options - Client configuration options\r\n */\r\n constructor(options: ClientOptions) {\r\n if (!options.apiKey) {\r\n throw new Error('API key is required. Get one at https://0xarchive.io/signup');\r\n }\r\n\r\n this.http = new HttpClient({\r\n baseUrl: options.baseUrl ?? DEFAULT_BASE_URL,\r\n apiKey: options.apiKey,\r\n timeout: options.timeout ?? DEFAULT_TIMEOUT,\r\n validate: options.validate ?? false,\r\n });\r\n\r\n // Exchange-specific clients (recommended)\r\n this.hyperliquid = new HyperliquidClient(this.http);\r\n this.lighter = new LighterClient(this.http);\r\n\r\n // Data quality monitoring (cross-exchange)\r\n this.dataQuality = new DataQualityResource(this.http);\r\n\r\n // Web3 wallet-based authentication\r\n this.web3 = new Web3Resource(this.http);\r\n\r\n // Legacy resource namespaces (deprecated - use client.hyperliquid.* instead)\r\n // These will be removed in v2.0\r\n // Note: Using /v1/hyperliquid base path for backward compatibility\r\n const legacyBase = '/v1/hyperliquid';\r\n this.orderbook = new OrderBookResource(this.http, legacyBase);\r\n this.trades = new TradesResource(this.http, legacyBase);\r\n this.instruments = new InstrumentsResource(this.http, legacyBase);\r\n this.funding = new FundingResource(this.http, legacyBase);\r\n this.openInterest = new OpenInterestResource(this.http, legacyBase);\r\n }\r\n}\r\n","/**\r\n * WebSocket client for 0xarchive real-time streaming, replay, and bulk download\r\n *\r\n * @example Real-time streaming\r\n * ```typescript\r\n * const ws = new OxArchiveWs({ apiKey: 'ox_...' });\r\n * await ws.connect();\r\n * ws.onOrderbook((coin, ob) => console.log(`${coin}: ${ob.midPrice}`));\r\n * ws.subscribeOrderbook('BTC');\r\n * ```\r\n *\r\n * @example Historical replay (like Tardis.dev)\r\n * ```typescript\r\n * const ws = new OxArchiveWs({ apiKey: 'ox_...' });\r\n * ws.onHistoricalData((coin, timestamp, data) => {\r\n * console.log(`${new Date(timestamp)}: ${data.mid_price}`);\r\n * });\r\n * await ws.connect();\r\n * ws.replay('orderbook', 'BTC', {\r\n * start: Date.now() - 86400000,\r\n * speed: 10 // 10x speed\r\n * });\r\n * ```\r\n *\r\n * @example Bulk streaming (like Databento)\r\n * ```typescript\r\n * const ws = new OxArchiveWs({ apiKey: 'ox_...' });\r\n * const batches: OrderBook[] = [];\r\n * ws.onBatch((coin, records) => {\r\n * batches.push(...records.map(r => r.data));\r\n * });\r\n * ws.onStreamComplete((channel, coin, count) => {\r\n * console.log(`Downloaded ${count} records`);\r\n * });\r\n * await ws.connect();\r\n * ws.stream('orderbook', 'ETH', {\r\n * start: Date.now() - 3600000,\r\n * end: Date.now(),\r\n * batchSize: 1000\r\n * });\r\n * ```\r\n */\r\n\r\nimport type {\r\n WsOptions,\r\n WsChannel,\r\n WsClientMessage,\r\n WsServerMessage,\r\n WsConnectionState,\r\n WsEventHandlers,\r\n OrderBook,\r\n OrderbookDelta,\r\n PriceLevel,\r\n Trade,\r\n WsHistoricalData,\r\n WsHistoricalTickData,\r\n WsHistoricalBatch,\r\n WsReplayStarted,\r\n WsReplayCompleted,\r\n WsReplaySnapshot,\r\n WsStreamStarted,\r\n WsStreamCompleted,\r\n WsStreamProgress,\r\n WsGapDetected,\r\n} from './types';\r\n\r\nconst DEFAULT_WS_URL = 'wss://api.0xarchive.io/ws';\r\nconst DEFAULT_PING_INTERVAL = 30000; // 30 seconds\r\nconst DEFAULT_RECONNECT_DELAY = 1000;\r\nconst DEFAULT_MAX_RECONNECT_ATTEMPTS = 10;\r\n\r\n// Server idle timeout is 60 seconds. The SDK sends pings every 30 seconds\r\n// to keep the connection alive. Browser WebSocket API automatically responds\r\n// to WebSocket protocol-level ping frames from the server.\r\n\r\n/**\r\n * Transform raw Hyperliquid trade format to SDK Trade type.\r\n * Raw format: { px, sz, side, time, hash, tid, users: [maker, taker] }\r\n * SDK format: { coin, side, price, size, timestamp, tx_hash, trade_id, maker_address, taker_address }\r\n */\r\nfunction transformTrade(coin: string, raw: Record<string, unknown>): Trade {\r\n // Check if already in SDK format (from REST API or historical replay)\r\n if ('price' in raw && 'size' in raw) {\r\n return raw as unknown as Trade;\r\n }\r\n\r\n // Transform from Hyperliquid raw format\r\n const px = raw.px as string | undefined;\r\n const sz = raw.sz as string | undefined;\r\n const side = raw.side as string | undefined;\r\n const time = raw.time as number | undefined;\r\n const hash = raw.hash as string | undefined;\r\n const tid = raw.tid as number | undefined;\r\n\r\n // Extract user addresses from the users array (market-level WebSocket trades)\r\n // users[0] = maker address, users[1] = taker address\r\n const users = raw.users as string[] | undefined;\r\n const maker_address = users && users.length > 0 ? users[0] : undefined;\r\n const taker_address = users && users.length > 1 ? users[1] : undefined;\r\n\r\n // Also check for user_address field (for historical replay data)\r\n const user_address = raw.userAddress as string | undefined ?? raw.user_address as string | undefined;\r\n\r\n return {\r\n coin,\r\n side: (side === 'A' || side === 'B' ? side : 'B') as 'A' | 'B',\r\n price: px ?? '0',\r\n size: sz ?? '0',\r\n timestamp: time ? new Date(time).toISOString() : new Date().toISOString(),\r\n txHash: hash,\r\n tradeId: tid,\r\n makerAddress: maker_address,\r\n takerAddress: taker_address,\r\n userAddress: user_address,\r\n };\r\n}\r\n\r\n/**\r\n * Transform an array of raw Hyperliquid trades to SDK Trade types.\r\n */\r\nfunction transformTrades(coin: string, rawTrades: unknown): Trade[] {\r\n if (!Array.isArray(rawTrades)) {\r\n // Single trade object\r\n return [transformTrade(coin, rawTrades as Record<string, unknown>)];\r\n }\r\n return rawTrades.map((raw) => transformTrade(coin, raw as Record<string, unknown>));\r\n}\r\n\r\n/**\r\n * Transform raw Hyperliquid orderbook format to SDK OrderBook type.\r\n * Raw format: { coin, levels: [[{px, sz, n}, ...], [{px, sz, n}, ...]], time }\r\n * SDK format: { coin, timestamp, bids: [{px, sz, n}], asks: [{px, sz, n}], mid_price, spread, spread_bps }\r\n */\r\nfunction transformOrderbook(coin: string, raw: Record<string, unknown>): OrderBook {\r\n // Check if already in SDK format (from REST API or historical replay)\r\n if ('bids' in raw && 'asks' in raw) {\r\n return raw as unknown as OrderBook;\r\n }\r\n\r\n // Transform from Hyperliquid raw format\r\n // levels is [[{px, sz, n}, ...], [{px, sz, n}, ...]] where [0]=bids, [1]=asks\r\n const levels = raw.levels as Array<Array<{ px: string; sz: string; n: number }>> | undefined;\r\n const time = raw.time as number | undefined;\r\n\r\n const bids: PriceLevel[] = [];\r\n const asks: PriceLevel[] = [];\r\n\r\n if (levels && levels.length >= 2) {\r\n // levels[0] = bids, levels[1] = asks\r\n // Each level is already {px, sz, n} object\r\n for (const level of levels[0] || []) {\r\n bids.push({ px: level.px, sz: level.sz, n: level.n });\r\n }\r\n for (const level of levels[1] || []) {\r\n asks.push({ px: level.px, sz: level.sz, n: level.n });\r\n }\r\n }\r\n\r\n // Calculate mid price and spread\r\n let midPrice: string | undefined;\r\n let spread: string | undefined;\r\n let spreadBps: string | undefined;\r\n\r\n if (bids.length > 0 && asks.length > 0) {\r\n const bestBid = parseFloat(bids[0].px);\r\n const bestAsk = parseFloat(asks[0].px);\r\n const mid = (bestBid + bestAsk) / 2;\r\n midPrice = mid.toString();\r\n spread = (bestAsk - bestBid).toString();\r\n spreadBps = ((bestAsk - bestBid) / mid * 10000).toFixed(2);\r\n }\r\n\r\n return {\r\n coin,\r\n timestamp: time ? new Date(time).toISOString() : new Date().toISOString(),\r\n bids,\r\n asks,\r\n midPrice,\r\n spread,\r\n spreadBps,\r\n };\r\n}\r\n\r\n/**\r\n * WebSocket client for real-time data streaming.\r\n *\r\n * **Keep-Alive:** The server sends WebSocket ping frames every 30 seconds\r\n * and will disconnect idle connections after 60 seconds. This SDK automatically\r\n * handles keep-alive by sending application-level pings at the configured interval\r\n * (default: 30 seconds). The browser WebSocket API automatically responds to\r\n * server ping frames.\r\n */\r\nexport class OxArchiveWs {\r\n private ws: WebSocket | null = null;\r\n private options: Required<WsOptions>;\r\n private handlers: WsEventHandlers = {};\r\n private subscriptions: Set<string> = new Set();\r\n private state: WsConnectionState = 'disconnected';\r\n private reconnectAttempts = 0;\r\n private pingTimer: ReturnType<typeof setInterval> | null = null;\r\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\r\n\r\n // Typed event handlers (separate from WsEventHandlers to avoid wrapping issues)\r\n private historicalDataHandlers: Array<(coin: string, timestamp: number, data: unknown) => void> = [];\r\n private historicalTickDataHandlers: Array<(coin: string, checkpoint: OrderBook, deltas: OrderbookDelta[]) => void> = [];\r\n private batchHandlers: Array<(coin: string, records: Array<{ timestamp: number; data: unknown }>) => void> = [];\r\n private replayStartHandlers: Array<(channel: WsChannel, coin: string, start: number, end: number, speed: number) => void> = [];\r\n private replayCompleteHandlers: Array<(channel: WsChannel, coin: string, snapshotsSent: number) => void> = [];\r\n private replaySnapshotHandlers: Array<(channel: WsChannel, coin: string, timestamp: number, data: unknown) => void> = [];\r\n private streamStartHandlers: Array<(channel: WsChannel, coin: string, start: number, end: number) => void> = [];\r\n private streamProgressHandlers: Array<(snapshotsSent: number) => void> = [];\r\n private streamCompleteHandlers: Array<(channel: WsChannel, coin: string, snapshotsSent: number) => void> = [];\r\n private orderbookHandlers: Array<(coin: string, data: OrderBook) => void> = [];\r\n private tradesHandlers: Array<(coin: string, data: Trade[]) => void> = [];\r\n private gapHandlers: Array<(channel: WsChannel, coin: string, gapStart: number, gapEnd: number, durationMinutes: number) => void> = [];\r\n\r\n constructor(options: WsOptions) {\r\n this.options = {\r\n apiKey: options.apiKey,\r\n wsUrl: options.wsUrl ?? DEFAULT_WS_URL,\r\n autoReconnect: options.autoReconnect ?? true,\r\n reconnectDelay: options.reconnectDelay ?? DEFAULT_RECONNECT_DELAY,\r\n maxReconnectAttempts: options.maxReconnectAttempts ?? DEFAULT_MAX_RECONNECT_ATTEMPTS,\r\n pingInterval: options.pingInterval ?? DEFAULT_PING_INTERVAL,\r\n };\r\n }\r\n\r\n /**\r\n * Connect to the WebSocket server\r\n *\r\n * @returns Promise that resolves when connected\r\n * @example\r\n * ```typescript\r\n * await ws.connect();\r\n * ws.subscribeOrderbook('BTC');\r\n * ```\r\n */\r\n connect(handlers?: WsEventHandlers): Promise<void> {\r\n if (handlers) {\r\n this.handlers = handlers;\r\n }\r\n\r\n this.setState('connecting');\r\n\r\n return new Promise((resolve, reject) => {\r\n const url = `${this.options.wsUrl}?apiKey=${encodeURIComponent(this.options.apiKey)}`;\r\n this.ws = new WebSocket(url);\r\n\r\n this.ws.onopen = () => {\r\n this.reconnectAttempts = 0;\r\n this.setState('connected');\r\n this.startPing();\r\n this.resubscribe();\r\n this.handlers.onOpen?.();\r\n resolve();\r\n };\r\n\r\n this.ws.onclose = (event) => {\r\n this.stopPing();\r\n const wasConnecting = this.state === 'connecting';\r\n this.handlers.onClose?.(event.code, event.reason);\r\n\r\n // If initial connection failed, reject and don't auto-reconnect\r\n if (wasConnecting) {\r\n this.setState('disconnected');\r\n reject(new Error(`WebSocket closed before connecting (code: ${event.code})`));\r\n return;\r\n }\r\n\r\n // Only auto-reconnect if we were previously connected\r\n if (this.options.autoReconnect && this.state !== 'disconnected') {\r\n this.scheduleReconnect();\r\n } else {\r\n this.setState('disconnected');\r\n }\r\n };\r\n\r\n this.ws.onerror = () => {\r\n const error = new Error('WebSocket connection error');\r\n this.handlers.onError?.(error);\r\n // Note: onerror is usually followed by onclose, which will reject the promise\r\n };\r\n\r\n this.ws.onmessage = (event) => {\r\n try {\r\n const message = JSON.parse(event.data) as WsServerMessage;\r\n this.handleMessage(message);\r\n } catch {\r\n // Ignore parse errors for malformed messages\r\n }\r\n };\r\n });\r\n }\r\n\r\n /**\r\n * Disconnect from the WebSocket server\r\n */\r\n disconnect(): void {\r\n this.setState('disconnected');\r\n this.stopPing();\r\n this.clearReconnectTimer();\r\n\r\n if (this.ws) {\r\n this.ws.close(1000, 'Client disconnect');\r\n this.ws = null;\r\n }\r\n }\r\n\r\n /**\r\n * Subscribe to a channel\r\n */\r\n subscribe(channel: WsChannel, coin?: string): void {\r\n const key = this.subscriptionKey(channel, coin);\r\n this.subscriptions.add(key);\r\n\r\n if (this.isConnected()) {\r\n this.send({ op: 'subscribe', channel, coin });\r\n }\r\n }\r\n\r\n /**\r\n * Subscribe to order book updates for a coin\r\n */\r\n subscribeOrderbook(coin: string): void {\r\n this.subscribe('orderbook', coin);\r\n }\r\n\r\n /**\r\n * Subscribe to trades for a coin\r\n */\r\n subscribeTrades(coin: string): void {\r\n this.subscribe('trades', coin);\r\n }\r\n\r\n /**\r\n * Subscribe to ticker updates for a coin\r\n */\r\n subscribeTicker(coin: string): void {\r\n this.subscribe('ticker', coin);\r\n }\r\n\r\n /**\r\n * Subscribe to all tickers\r\n */\r\n subscribeAllTickers(): void {\r\n this.subscribe('all_tickers');\r\n }\r\n\r\n /**\r\n * Unsubscribe from a channel\r\n */\r\n unsubscribe(channel: WsChannel, coin?: string): void {\r\n const key = this.subscriptionKey(channel, coin);\r\n this.subscriptions.delete(key);\r\n\r\n if (this.isConnected()) {\r\n this.send({ op: 'unsubscribe', channel, coin });\r\n }\r\n }\r\n\r\n /**\r\n * Unsubscribe from order book updates for a coin\r\n */\r\n unsubscribeOrderbook(coin: string): void {\r\n this.unsubscribe('orderbook', coin);\r\n }\r\n\r\n /**\r\n * Unsubscribe from trades for a coin\r\n */\r\n unsubscribeTrades(coin: string): void {\r\n this.unsubscribe('trades', coin);\r\n }\r\n\r\n /**\r\n * Unsubscribe from ticker updates for a coin\r\n */\r\n unsubscribeTicker(coin: string): void {\r\n this.unsubscribe('ticker', coin);\r\n }\r\n\r\n /**\r\n * Unsubscribe from all tickers\r\n */\r\n unsubscribeAllTickers(): void {\r\n this.unsubscribe('all_tickers');\r\n }\r\n\r\n // ==========================================================================\r\n // Historical Replay (Option B) - Like Tardis.dev\r\n // ==========================================================================\r\n\r\n /**\r\n * Start historical replay with timing preserved\r\n *\r\n * @param channel - Data channel to replay\r\n * @param coin - Trading pair (e.g., 'BTC', 'ETH')\r\n * @param options - Replay options\r\n *\r\n * @example\r\n * ```typescript\r\n * ws.replay('orderbook', 'BTC', {\r\n * start: Date.now() - 86400000, // 24 hours ago\r\n * speed: 10 // 10x faster than real-time\r\n * });\r\n * ```\r\n */\r\n replay(\r\n channel: WsChannel,\r\n coin: string,\r\n options: {\r\n start: number;\r\n end?: number;\r\n speed?: number;\r\n granularity?: string;\r\n /** Candle interval for candles channel (1m, 5m, 15m, 30m, 1h, 4h, 1d, 1w) */\r\n interval?: string;\r\n }\r\n ): void {\r\n this.send({\r\n op: 'replay',\r\n channel,\r\n coin,\r\n start: options.start,\r\n end: options.end,\r\n speed: options.speed ?? 1,\r\n granularity: options.granularity,\r\n interval: options.interval,\r\n });\r\n }\r\n\r\n /**\r\n * Start a multi-channel historical replay with timing preserved.\r\n * Data from all channels is interleaved chronologically. Before the timeline\r\n * begins, `replay_snapshot` messages provide initial state for each channel.\r\n *\r\n * @param channels - Array of data channels to replay simultaneously\r\n * @param coin - Trading pair (e.g., 'BTC', 'ETH')\r\n * @param options - Replay options\r\n *\r\n * @example\r\n * ```typescript\r\n * ws.onReplaySnapshot((channel, coin, timestamp, data) => {\r\n * console.log(`Initial ${channel} state at ${new Date(timestamp).toISOString()}`);\r\n * });\r\n * ws.onHistoricalData((coin, timestamp, data) => {\r\n * // Interleaved data from all channels\r\n * });\r\n * ws.multiReplay(['orderbook', 'trades', 'funding'], 'BTC', {\r\n * start: Date.now() - 86400000,\r\n * speed: 10\r\n * });\r\n * ```\r\n */\r\n multiReplay(\r\n channels: WsChannel[],\r\n coin: string,\r\n options: {\r\n start: number;\r\n end?: number;\r\n speed?: number;\r\n granularity?: string;\r\n interval?: string;\r\n }\r\n ): void {\r\n this.send({\r\n op: 'replay',\r\n channels,\r\n coin,\r\n start: options.start,\r\n end: options.end,\r\n speed: options.speed ?? 1,\r\n granularity: options.granularity,\r\n interval: options.interval,\r\n });\r\n }\r\n\r\n /**\r\n * Pause the current replay\r\n */\r\n replayPause(): void {\r\n this.send({ op: 'replay.pause' });\r\n }\r\n\r\n /**\r\n * Resume a paused replay\r\n */\r\n replayResume(): void {\r\n this.send({ op: 'replay.resume' });\r\n }\r\n\r\n /**\r\n * Seek to a specific timestamp in the replay\r\n * @param timestamp - Unix timestamp in milliseconds\r\n */\r\n replaySeek(timestamp: number): void {\r\n this.send({ op: 'replay.seek', timestamp });\r\n }\r\n\r\n /**\r\n * Stop the current replay\r\n */\r\n replayStop(): void {\r\n this.send({ op: 'replay.stop' });\r\n }\r\n\r\n // ==========================================================================\r\n // Bulk Streaming (Option D) - Like Databento\r\n // ==========================================================================\r\n\r\n /**\r\n * Start bulk streaming for fast data download\r\n *\r\n * @param channel - Data channel to stream\r\n * @param coin - Trading pair (e.g., 'BTC', 'ETH')\r\n * @param options - Stream options\r\n *\r\n * @example\r\n * ```typescript\r\n * ws.stream('orderbook', 'ETH', {\r\n * start: Date.now() - 3600000, // 1 hour ago\r\n * end: Date.now(),\r\n * batchSize: 1000\r\n * });\r\n * ```\r\n */\r\n stream(\r\n channel: WsChannel,\r\n coin: string,\r\n options: {\r\n start: number;\r\n end: number;\r\n batchSize?: number;\r\n granularity?: string;\r\n /** Candle interval for candles channel (1m, 5m, 15m, 30m, 1h, 4h, 1d, 1w) */\r\n interval?: string;\r\n }\r\n ): void {\r\n this.send({\r\n op: 'stream',\r\n channel,\r\n coin,\r\n start: options.start,\r\n end: options.end,\r\n batch_size: options.batchSize ?? 1000,\r\n granularity: options.granularity,\r\n interval: options.interval,\r\n });\r\n }\r\n\r\n /**\r\n * Start a multi-channel bulk stream for fast data download.\r\n * Data from all channels arrives in batches without timing delays.\r\n * Before batches begin, `replay_snapshot` messages provide initial state\r\n * for each channel.\r\n *\r\n * @param channels - Array of data channels to stream simultaneously\r\n * @param coin - Trading pair (e.g., 'BTC', 'ETH')\r\n * @param options - Stream options\r\n *\r\n * @example\r\n * ```typescript\r\n * ws.onReplaySnapshot((channel, coin, timestamp, data) => {\r\n * console.log(`Initial ${channel} state`);\r\n * });\r\n * ws.onBatch((coin, records) => {\r\n * // Batches contain data from all requested channels\r\n * });\r\n * ws.multiStream(['orderbook', 'trades', 'open_interest'], 'BTC', {\r\n * start: Date.now() - 3600000,\r\n * end: Date.now(),\r\n * batchSize: 1000\r\n * });\r\n * ```\r\n */\r\n multiStream(\r\n channels: WsChannel[],\r\n coin: string,\r\n options: {\r\n start: number;\r\n end: number;\r\n batchSize?: number;\r\n granularity?: string;\r\n interval?: string;\r\n }\r\n ): void {\r\n this.send({\r\n op: 'stream',\r\n channels,\r\n coin,\r\n start: options.start,\r\n end: options.end,\r\n batch_size: options.batchSize ?? 1000,\r\n granularity: options.granularity,\r\n interval: options.interval,\r\n });\r\n }\r\n\r\n /**\r\n * Stop the current bulk stream\r\n */\r\n streamStop(): void {\r\n this.send({ op: 'stream.stop' });\r\n }\r\n\r\n // ==========================================================================\r\n // Event Handlers for Replay/Stream\r\n // ==========================================================================\r\n\r\n /**\r\n * Handle historical data points (replay mode)\r\n */\r\n onHistoricalData<T = unknown>(\r\n handler: (coin: string, timestamp: number, data: T) => void\r\n ): void {\r\n this.historicalDataHandlers.push(handler as (coin: string, timestamp: number, data: unknown) => void);\r\n }\r\n\r\n /**\r\n * Handle historical tick data (granularity='tick' mode)\r\n * Receives a checkpoint (full orderbook) followed by incremental deltas.\r\n * This is for tick-level granularity on Lighter.xyz orderbook data.\r\n */\r\n onHistoricalTickData(\r\n handler: (coin: string, checkpoint: OrderBook, deltas: OrderbookDelta[]) => void\r\n ): void {\r\n this.historicalTickDataHandlers.push(handler);\r\n }\r\n\r\n /**\r\n * Handle batched data (bulk stream mode)\r\n */\r\n onBatch<T = unknown>(\r\n handler: (coin: string, records: Array<{ timestamp: number; data: T }>) => void\r\n ): void {\r\n this.batchHandlers.push(handler as (coin: string, records: Array<{ timestamp: number; data: unknown }>) => void);\r\n }\r\n\r\n /**\r\n * Handle replay started event\r\n */\r\n onReplayStart(\r\n handler: (channel: WsChannel, coin: string, start: number, end: number, speed: number) => void\r\n ): void {\r\n this.replayStartHandlers.push(handler);\r\n }\r\n\r\n /**\r\n * Handle replay completed event\r\n */\r\n onReplayComplete(\r\n handler: (channel: WsChannel, coin: string, snapshotsSent: number) => void\r\n ): void {\r\n this.replayCompleteHandlers.push(handler);\r\n }\r\n\r\n /**\r\n * Handle replay snapshot events (multi-channel mode).\r\n * Called with the initial state for each channel before the replay/stream\r\n * timeline begins. Use this to initialize local state (e.g., set the current\r\n * orderbook or latest funding rate) before `historical_data` messages start\r\n * arriving.\r\n *\r\n * @param handler - Callback receiving channel, coin, timestamp (ms), and data payload\r\n *\r\n * @example\r\n * ```typescript\r\n * ws.onReplaySnapshot((channel, coin, timestamp, data) => {\r\n * if (channel === 'orderbook') {\r\n * currentOrderbook = data;\r\n * } else if (channel === 'funding') {\r\n * currentFundingRate = data;\r\n * }\r\n * });\r\n * ```\r\n */\r\n onReplaySnapshot<T = unknown>(\r\n handler: (channel: WsChannel, coin: string, timestamp: number, data: T) => void\r\n ): void {\r\n this.replaySnapshotHandlers.push(handler as (channel: WsChannel, coin: string, timestamp: number, data: unknown) => void);\r\n }\r\n\r\n /**\r\n * Handle stream started event\r\n */\r\n onStreamStart(\r\n handler: (channel: WsChannel, coin: string, start: number, end: number) => void\r\n ): void {\r\n this.streamStartHandlers.push(handler);\r\n }\r\n\r\n /**\r\n * Handle stream progress event\r\n */\r\n onStreamProgress(\r\n handler: (snapshotsSent: number) => void\r\n ): void {\r\n this.streamProgressHandlers.push(handler);\r\n }\r\n\r\n /**\r\n * Handle stream completed event\r\n */\r\n onStreamComplete(\r\n handler: (channel: WsChannel, coin: string, snapshotsSent: number) => void\r\n ): void {\r\n this.streamCompleteHandlers.push(handler);\r\n }\r\n\r\n /**\r\n * Handle gap detected events during replay or streaming.\r\n * Called when there's a gap in the historical data exceeding the threshold.\r\n * Thresholds: 2 minutes for orderbook/candles/liquidations, 60 minutes for trades.\r\n *\r\n * @param handler - Callback receiving channel, coin, gap start/end timestamps (ms), and duration (minutes)\r\n *\r\n * @example\r\n * ```typescript\r\n * ws.onGap((channel, coin, gapStart, gapEnd, durationMinutes) => {\r\n * console.warn(`Gap detected in ${channel} ${coin}: ${durationMinutes} minutes`);\r\n * console.warn(` From: ${new Date(gapStart).toISOString()}`);\r\n * console.warn(` To: ${new Date(gapEnd).toISOString()}`);\r\n * });\r\n * ```\r\n */\r\n onGap(\r\n handler: (channel: WsChannel, coin: string, gapStart: number, gapEnd: number, durationMinutes: number) => void\r\n ): void {\r\n this.gapHandlers.push(handler);\r\n }\r\n\r\n /**\r\n * Get current connection state\r\n */\r\n getState(): WsConnectionState {\r\n return this.state;\r\n }\r\n\r\n /**\r\n * Check if connected\r\n */\r\n isConnected(): boolean {\r\n return this.ws?.readyState === WebSocket.OPEN;\r\n }\r\n\r\n /**\r\n * Set event handlers after construction\r\n */\r\n on<K extends keyof WsEventHandlers>(event: K, handler: WsEventHandlers[K]): void {\r\n this.handlers[event] = handler;\r\n }\r\n\r\n /**\r\n * Helper to handle typed orderbook data\r\n */\r\n onOrderbook(handler: (coin: string, data: OrderBook) => void): void {\r\n this.orderbookHandlers.push(handler);\r\n }\r\n\r\n /**\r\n * Helper to handle typed trade data\r\n */\r\n onTrades(handler: (coin: string, data: Trade[]) => void): void {\r\n this.tradesHandlers.push(handler);\r\n }\r\n\r\n // Private methods\r\n\r\n private send(message: WsClientMessage): void {\r\n if (this.ws?.readyState === WebSocket.OPEN) {\r\n this.ws.send(JSON.stringify(message));\r\n }\r\n }\r\n\r\n private setState(state: WsConnectionState): void {\r\n this.state = state;\r\n this.handlers.onStateChange?.(state);\r\n }\r\n\r\n private startPing(): void {\r\n this.stopPing();\r\n this.pingTimer = setInterval(() => {\r\n this.send({ op: 'ping' });\r\n }, this.options.pingInterval);\r\n }\r\n\r\n private stopPing(): void {\r\n if (this.pingTimer) {\r\n clearInterval(this.pingTimer);\r\n this.pingTimer = null;\r\n }\r\n }\r\n\r\n private subscriptionKey(channel: WsChannel, coin?: string): string {\r\n return coin ? `${channel}:${coin}` : channel;\r\n }\r\n\r\n private resubscribe(): void {\r\n for (const key of this.subscriptions) {\r\n const [channel, coin] = key.split(':') as [WsChannel, string | undefined];\r\n this.send({ op: 'subscribe', channel, coin });\r\n }\r\n }\r\n\r\n private scheduleReconnect(): void {\r\n if (this.reconnectAttempts >= this.options.maxReconnectAttempts) {\r\n this.setState('disconnected');\r\n return;\r\n }\r\n\r\n this.setState('reconnecting');\r\n this.reconnectAttempts++;\r\n\r\n const delay = this.options.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1);\r\n\r\n this.reconnectTimer = setTimeout(() => {\r\n this.connect().catch(() => {\r\n // Reconnect attempt failed, schedule another attempt\r\n // (reconnectAttempts is already incremented, so this will eventually stop)\r\n if (this.reconnectAttempts < this.options.maxReconnectAttempts) {\r\n this.scheduleReconnect();\r\n }\r\n });\r\n }, delay);\r\n }\r\n\r\n private clearReconnectTimer(): void {\r\n if (this.reconnectTimer) {\r\n clearTimeout(this.reconnectTimer);\r\n this.reconnectTimer = null;\r\n }\r\n }\r\n\r\n private handleMessage(message: WsServerMessage): void {\r\n // Call the generic onMessage handler first\r\n this.handlers.onMessage?.(message);\r\n\r\n // Dispatch to typed handlers based on message type\r\n switch (message.type) {\r\n case 'historical_data': {\r\n const msg = message as WsHistoricalData;\r\n for (const handler of this.historicalDataHandlers) {\r\n handler(msg.coin, msg.timestamp, msg.data);\r\n }\r\n break;\r\n }\r\n case 'historical_tick_data': {\r\n const msg = message as WsHistoricalTickData;\r\n for (const handler of this.historicalTickDataHandlers) {\r\n handler(msg.coin, msg.checkpoint, msg.deltas);\r\n }\r\n break;\r\n }\r\n case 'historical_batch': {\r\n const msg = message as WsHistoricalBatch;\r\n for (const handler of this.batchHandlers) {\r\n handler(msg.coin, msg.data as Array<{ timestamp: number; data: unknown }>);\r\n }\r\n break;\r\n }\r\n case 'replay_started': {\r\n const msg = message as WsReplayStarted;\r\n for (const handler of this.replayStartHandlers) {\r\n handler(msg.channel, msg.coin, msg.start, msg.end, msg.speed);\r\n }\r\n break;\r\n }\r\n case 'replay_completed': {\r\n const msg = message as WsReplayCompleted;\r\n for (const handler of this.replayCompleteHandlers) {\r\n handler(msg.channel, msg.coin, msg.snapshots_sent);\r\n }\r\n break;\r\n }\r\n case 'replay_snapshot': {\r\n const msg = message as WsReplaySnapshot;\r\n for (const handler of this.replaySnapshotHandlers) {\r\n handler(msg.channel, msg.coin, msg.timestamp, msg.data);\r\n }\r\n break;\r\n }\r\n case 'stream_started': {\r\n const msg = message as WsStreamStarted;\r\n for (const handler of this.streamStartHandlers) {\r\n handler(msg.channel, msg.coin, msg.start, msg.end);\r\n }\r\n break;\r\n }\r\n case 'stream_progress': {\r\n const msg = message as WsStreamProgress;\r\n for (const handler of this.streamProgressHandlers) {\r\n handler(msg.snapshots_sent);\r\n }\r\n break;\r\n }\r\n case 'stream_completed': {\r\n const msg = message as WsStreamCompleted;\r\n for (const handler of this.streamCompleteHandlers) {\r\n handler(msg.channel, msg.coin, msg.snapshots_sent);\r\n }\r\n break;\r\n }\r\n case 'gap_detected': {\r\n const msg = message as WsGapDetected;\r\n for (const handler of this.gapHandlers) {\r\n handler(msg.channel, msg.coin, msg.gap_start, msg.gap_end, msg.duration_minutes);\r\n }\r\n break;\r\n }\r\n case 'data': {\r\n if (message.channel === 'orderbook') {\r\n // Transform raw Hyperliquid format to SDK OrderBook type\r\n const orderbook = transformOrderbook(message.coin, message.data as Record<string, unknown>);\r\n for (const handler of this.orderbookHandlers) {\r\n handler(message.coin, orderbook);\r\n }\r\n } else if (message.channel === 'trades') {\r\n // Transform raw Hyperliquid format to SDK Trade type\r\n const trades = transformTrades(message.coin, message.data);\r\n for (const handler of this.tradesHandlers) {\r\n handler(message.coin, trades);\r\n }\r\n }\r\n break;\r\n }\r\n }\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
|