@0xarchive/sdk 0.4.2 → 0.4.3
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 +38 -0
- package/dist/index.d.mts +19 -1
- package/dist/index.d.ts +19 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -77,6 +77,43 @@ const history = await client.hyperliquid.orderbook.history('BTC', {
|
|
|
77
77
|
});
|
|
78
78
|
```
|
|
79
79
|
|
|
80
|
+
#### Lighter Orderbook Granularity
|
|
81
|
+
|
|
82
|
+
Lighter.xyz orderbook history supports a `granularity` parameter for different data resolutions. Tier restrictions apply.
|
|
83
|
+
|
|
84
|
+
| Granularity | Interval | Tier Required | Credit Multiplier |
|
|
85
|
+
|-------------|----------|---------------|-------------------|
|
|
86
|
+
| `checkpoint` | ~60s | Free+ | 1x |
|
|
87
|
+
| `30s` | 30s | Build+ | 2x |
|
|
88
|
+
| `10s` | 10s | Build+ | 3x |
|
|
89
|
+
| `1s` | 1s | Pro+ | 10x |
|
|
90
|
+
| `tick` | tick-level | Enterprise | 20x |
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
// Get Lighter orderbook history with 10s resolution (Build+ tier)
|
|
94
|
+
const history = await client.lighter.orderbook.history('BTC', {
|
|
95
|
+
start: Date.now() - 86400000,
|
|
96
|
+
end: Date.now(),
|
|
97
|
+
granularity: '10s'
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
// Get 1-second resolution (Pro+ tier)
|
|
101
|
+
const history = await client.lighter.orderbook.history('BTC', {
|
|
102
|
+
start: Date.now() - 86400000,
|
|
103
|
+
end: Date.now(),
|
|
104
|
+
granularity: '1s'
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
// Tick-level data (Enterprise tier) - returns checkpoint + raw deltas
|
|
108
|
+
const history = await client.lighter.orderbook.history('BTC', {
|
|
109
|
+
start: Date.now() - 86400000,
|
|
110
|
+
end: Date.now(),
|
|
111
|
+
granularity: 'tick'
|
|
112
|
+
});
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
**Note:** The `granularity` parameter is ignored for Hyperliquid orderbook history.
|
|
116
|
+
|
|
80
117
|
### Trades
|
|
81
118
|
|
|
82
119
|
The trades API uses cursor-based pagination for efficient retrieval of large datasets.
|
|
@@ -377,6 +414,7 @@ import type {
|
|
|
377
414
|
Trade,
|
|
378
415
|
Instrument,
|
|
379
416
|
LighterInstrument,
|
|
417
|
+
LighterGranularity,
|
|
380
418
|
FundingRate,
|
|
381
419
|
OpenInterest,
|
|
382
420
|
CursorResponse,
|
package/dist/index.d.mts
CHANGED
|
@@ -68,9 +68,27 @@ interface GetOrderBookParams {
|
|
|
68
68
|
/** Number of price levels to return per side */
|
|
69
69
|
depth?: number;
|
|
70
70
|
}
|
|
71
|
+
/**
|
|
72
|
+
* Lighter orderbook data granularity levels.
|
|
73
|
+
* Controls the resolution of historical orderbook data (Lighter.xyz only).
|
|
74
|
+
*
|
|
75
|
+
* - 'checkpoint': ~60s intervals (default, all tiers)
|
|
76
|
+
* - '30s': 30 second intervals (Build+ tier)
|
|
77
|
+
* - '10s': 10 second intervals (Build+ tier)
|
|
78
|
+
* - '1s': 1 second intervals (Pro+ tier)
|
|
79
|
+
* - 'tick': Checkpoint + raw deltas (Enterprise tier only)
|
|
80
|
+
*/
|
|
81
|
+
type LighterGranularity = 'checkpoint' | '30s' | '10s' | '1s' | 'tick';
|
|
71
82
|
interface OrderBookHistoryParams extends CursorPaginationParams {
|
|
72
83
|
/** Number of price levels to return per side */
|
|
73
84
|
depth?: number;
|
|
85
|
+
/**
|
|
86
|
+
* Data resolution for Lighter orderbook history (Lighter.xyz only, ignored for Hyperliquid).
|
|
87
|
+
* Controls the granularity of returned snapshots. Tier restrictions apply.
|
|
88
|
+
* Credit multipliers: checkpoint=1x, 30s=2x, 10s=3x, 1s=10x, tick=20x.
|
|
89
|
+
* @default 'checkpoint'
|
|
90
|
+
*/
|
|
91
|
+
granularity?: LighterGranularity;
|
|
74
92
|
}
|
|
75
93
|
/** Trade side: 'A' (ask/sell) or 'B' (bid/buy) */
|
|
76
94
|
type TradeSide = 'A' | 'B';
|
|
@@ -2753,4 +2771,4 @@ type ValidatedFundingRate = z.infer<typeof FundingRateSchema>;
|
|
|
2753
2771
|
type ValidatedOpenInterest = z.infer<typeof OpenInterestSchema>;
|
|
2754
2772
|
type ValidatedWsServerMessage = z.infer<typeof WsServerMessageSchema>;
|
|
2755
2773
|
|
|
2756
|
-
export { type ApiError, type ApiMeta, ApiMetaSchema, type ApiResponse, ApiResponseSchema, type ClientOptions, type CursorResponse, type FundingRate, FundingRateArrayResponseSchema, FundingRateResponseSchema, FundingRateSchema, type GetOrderBookParams, type GetTradesCursorParams, HyperliquidClient, type Instrument, InstrumentArrayResponseSchema, InstrumentResponseSchema, InstrumentSchema, type InstrumentType, InstrumentTypeSchema, LighterClient, type LighterInstrument, type OpenInterest, OpenInterestArrayResponseSchema, OpenInterestResponseSchema, OpenInterestSchema, type OrderBook, OrderBookArrayResponseSchema, type OrderBookHistoryParams, OrderBookResponseSchema, OrderBookSchema, OxArchive, OxArchiveError, OxArchiveWs, type PriceLevel, PriceLevelSchema, type Timestamp, type TimestampedRecord, TimestampedRecordSchema, type Trade, TradeArrayResponseSchema, type TradeDirection, TradeDirectionSchema, TradeSchema, type TradeSide, TradeSideSchema, type ValidatedApiMeta, type ValidatedFundingRate, type ValidatedInstrument, type ValidatedOpenInterest, type ValidatedOrderBook, type ValidatedPriceLevel, type ValidatedTrade, type ValidatedWsServerMessage, type WsChannel, WsChannelSchema, type WsClientMessage, type WsConnectionState, WsConnectionStateSchema, type WsData, WsDataSchema, type WsError, WsErrorSchema, type WsEventHandlers, type WsHistoricalBatch, WsHistoricalBatchSchema, type WsHistoricalData, WsHistoricalDataSchema, type WsOptions, type WsPing, type WsPong, WsPongSchema, type WsReplay, type WsReplayCompleted, WsReplayCompletedSchema, type WsReplayPause, type WsReplayPaused, WsReplayPausedSchema, type WsReplayResume, type WsReplayResumed, WsReplayResumedSchema, type WsReplaySeek, type WsReplayStarted, WsReplayStartedSchema, type WsReplayStop, type WsReplayStopped, WsReplayStoppedSchema, type WsServerMessage, WsServerMessageSchema, type WsStream, type WsStreamCompleted, WsStreamCompletedSchema, type WsStreamProgress, WsStreamProgressSchema, type WsStreamStarted, WsStreamStartedSchema, type WsStreamStop, type WsStreamStopped, WsStreamStoppedSchema, type WsSubscribe, type WsSubscribed, WsSubscribedSchema, type WsUnsubscribe, type WsUnsubscribed, WsUnsubscribedSchema, OxArchive as default };
|
|
2774
|
+
export { type ApiError, type ApiMeta, ApiMetaSchema, type ApiResponse, ApiResponseSchema, type ClientOptions, type CursorResponse, type FundingRate, FundingRateArrayResponseSchema, FundingRateResponseSchema, FundingRateSchema, type GetOrderBookParams, type GetTradesCursorParams, HyperliquidClient, type Instrument, InstrumentArrayResponseSchema, InstrumentResponseSchema, InstrumentSchema, type InstrumentType, InstrumentTypeSchema, LighterClient, type LighterGranularity, type LighterInstrument, type OpenInterest, OpenInterestArrayResponseSchema, OpenInterestResponseSchema, OpenInterestSchema, type OrderBook, OrderBookArrayResponseSchema, type OrderBookHistoryParams, OrderBookResponseSchema, OrderBookSchema, OxArchive, OxArchiveError, OxArchiveWs, type PriceLevel, PriceLevelSchema, type Timestamp, type TimestampedRecord, TimestampedRecordSchema, type Trade, TradeArrayResponseSchema, type TradeDirection, TradeDirectionSchema, TradeSchema, type TradeSide, TradeSideSchema, type ValidatedApiMeta, type ValidatedFundingRate, type ValidatedInstrument, type ValidatedOpenInterest, type ValidatedOrderBook, type ValidatedPriceLevel, type ValidatedTrade, type ValidatedWsServerMessage, type WsChannel, WsChannelSchema, type WsClientMessage, type WsConnectionState, WsConnectionStateSchema, type WsData, WsDataSchema, type WsError, WsErrorSchema, type WsEventHandlers, type WsHistoricalBatch, WsHistoricalBatchSchema, type WsHistoricalData, WsHistoricalDataSchema, type WsOptions, type WsPing, type WsPong, WsPongSchema, type WsReplay, type WsReplayCompleted, WsReplayCompletedSchema, type WsReplayPause, type WsReplayPaused, WsReplayPausedSchema, type WsReplayResume, type WsReplayResumed, WsReplayResumedSchema, type WsReplaySeek, type WsReplayStarted, WsReplayStartedSchema, type WsReplayStop, type WsReplayStopped, WsReplayStoppedSchema, type WsServerMessage, WsServerMessageSchema, type WsStream, type WsStreamCompleted, WsStreamCompletedSchema, type WsStreamProgress, WsStreamProgressSchema, type WsStreamStarted, WsStreamStartedSchema, type WsStreamStop, type WsStreamStopped, WsStreamStoppedSchema, type WsSubscribe, type WsSubscribed, WsSubscribedSchema, type WsUnsubscribe, type WsUnsubscribed, WsUnsubscribedSchema, OxArchive as default };
|
package/dist/index.d.ts
CHANGED
|
@@ -68,9 +68,27 @@ interface GetOrderBookParams {
|
|
|
68
68
|
/** Number of price levels to return per side */
|
|
69
69
|
depth?: number;
|
|
70
70
|
}
|
|
71
|
+
/**
|
|
72
|
+
* Lighter orderbook data granularity levels.
|
|
73
|
+
* Controls the resolution of historical orderbook data (Lighter.xyz only).
|
|
74
|
+
*
|
|
75
|
+
* - 'checkpoint': ~60s intervals (default, all tiers)
|
|
76
|
+
* - '30s': 30 second intervals (Build+ tier)
|
|
77
|
+
* - '10s': 10 second intervals (Build+ tier)
|
|
78
|
+
* - '1s': 1 second intervals (Pro+ tier)
|
|
79
|
+
* - 'tick': Checkpoint + raw deltas (Enterprise tier only)
|
|
80
|
+
*/
|
|
81
|
+
type LighterGranularity = 'checkpoint' | '30s' | '10s' | '1s' | 'tick';
|
|
71
82
|
interface OrderBookHistoryParams extends CursorPaginationParams {
|
|
72
83
|
/** Number of price levels to return per side */
|
|
73
84
|
depth?: number;
|
|
85
|
+
/**
|
|
86
|
+
* Data resolution for Lighter orderbook history (Lighter.xyz only, ignored for Hyperliquid).
|
|
87
|
+
* Controls the granularity of returned snapshots. Tier restrictions apply.
|
|
88
|
+
* Credit multipliers: checkpoint=1x, 30s=2x, 10s=3x, 1s=10x, tick=20x.
|
|
89
|
+
* @default 'checkpoint'
|
|
90
|
+
*/
|
|
91
|
+
granularity?: LighterGranularity;
|
|
74
92
|
}
|
|
75
93
|
/** Trade side: 'A' (ask/sell) or 'B' (bid/buy) */
|
|
76
94
|
type TradeSide = 'A' | 'B';
|
|
@@ -2753,4 +2771,4 @@ type ValidatedFundingRate = z.infer<typeof FundingRateSchema>;
|
|
|
2753
2771
|
type ValidatedOpenInterest = z.infer<typeof OpenInterestSchema>;
|
|
2754
2772
|
type ValidatedWsServerMessage = z.infer<typeof WsServerMessageSchema>;
|
|
2755
2773
|
|
|
2756
|
-
export { type ApiError, type ApiMeta, ApiMetaSchema, type ApiResponse, ApiResponseSchema, type ClientOptions, type CursorResponse, type FundingRate, FundingRateArrayResponseSchema, FundingRateResponseSchema, FundingRateSchema, type GetOrderBookParams, type GetTradesCursorParams, HyperliquidClient, type Instrument, InstrumentArrayResponseSchema, InstrumentResponseSchema, InstrumentSchema, type InstrumentType, InstrumentTypeSchema, LighterClient, type LighterInstrument, type OpenInterest, OpenInterestArrayResponseSchema, OpenInterestResponseSchema, OpenInterestSchema, type OrderBook, OrderBookArrayResponseSchema, type OrderBookHistoryParams, OrderBookResponseSchema, OrderBookSchema, OxArchive, OxArchiveError, OxArchiveWs, type PriceLevel, PriceLevelSchema, type Timestamp, type TimestampedRecord, TimestampedRecordSchema, type Trade, TradeArrayResponseSchema, type TradeDirection, TradeDirectionSchema, TradeSchema, type TradeSide, TradeSideSchema, type ValidatedApiMeta, type ValidatedFundingRate, type ValidatedInstrument, type ValidatedOpenInterest, type ValidatedOrderBook, type ValidatedPriceLevel, type ValidatedTrade, type ValidatedWsServerMessage, type WsChannel, WsChannelSchema, type WsClientMessage, type WsConnectionState, WsConnectionStateSchema, type WsData, WsDataSchema, type WsError, WsErrorSchema, type WsEventHandlers, type WsHistoricalBatch, WsHistoricalBatchSchema, type WsHistoricalData, WsHistoricalDataSchema, type WsOptions, type WsPing, type WsPong, WsPongSchema, type WsReplay, type WsReplayCompleted, WsReplayCompletedSchema, type WsReplayPause, type WsReplayPaused, WsReplayPausedSchema, type WsReplayResume, type WsReplayResumed, WsReplayResumedSchema, type WsReplaySeek, type WsReplayStarted, WsReplayStartedSchema, type WsReplayStop, type WsReplayStopped, WsReplayStoppedSchema, type WsServerMessage, WsServerMessageSchema, type WsStream, type WsStreamCompleted, WsStreamCompletedSchema, type WsStreamProgress, WsStreamProgressSchema, type WsStreamStarted, WsStreamStartedSchema, type WsStreamStop, type WsStreamStopped, WsStreamStoppedSchema, type WsSubscribe, type WsSubscribed, WsSubscribedSchema, type WsUnsubscribe, type WsUnsubscribed, WsUnsubscribedSchema, OxArchive as default };
|
|
2774
|
+
export { type ApiError, type ApiMeta, ApiMetaSchema, type ApiResponse, ApiResponseSchema, type ClientOptions, type CursorResponse, type FundingRate, FundingRateArrayResponseSchema, FundingRateResponseSchema, FundingRateSchema, type GetOrderBookParams, type GetTradesCursorParams, HyperliquidClient, type Instrument, InstrumentArrayResponseSchema, InstrumentResponseSchema, InstrumentSchema, type InstrumentType, InstrumentTypeSchema, LighterClient, type LighterGranularity, type LighterInstrument, type OpenInterest, OpenInterestArrayResponseSchema, OpenInterestResponseSchema, OpenInterestSchema, type OrderBook, OrderBookArrayResponseSchema, type OrderBookHistoryParams, OrderBookResponseSchema, OrderBookSchema, OxArchive, OxArchiveError, OxArchiveWs, type PriceLevel, PriceLevelSchema, type Timestamp, type TimestampedRecord, TimestampedRecordSchema, type Trade, TradeArrayResponseSchema, type TradeDirection, TradeDirectionSchema, TradeSchema, type TradeSide, TradeSideSchema, type ValidatedApiMeta, type ValidatedFundingRate, type ValidatedInstrument, type ValidatedOpenInterest, type ValidatedOrderBook, type ValidatedPriceLevel, type ValidatedTrade, type ValidatedWsServerMessage, type WsChannel, WsChannelSchema, type WsClientMessage, type WsConnectionState, WsConnectionStateSchema, type WsData, WsDataSchema, type WsError, WsErrorSchema, type WsEventHandlers, type WsHistoricalBatch, WsHistoricalBatchSchema, type WsHistoricalData, WsHistoricalDataSchema, type WsOptions, type WsPing, type WsPong, WsPongSchema, type WsReplay, type WsReplayCompleted, WsReplayCompletedSchema, type WsReplayPause, type WsReplayPaused, WsReplayPausedSchema, type WsReplayResume, type WsReplayResumed, WsReplayResumedSchema, type WsReplaySeek, type WsReplayStarted, WsReplayStartedSchema, type WsReplayStop, type WsReplayStopped, WsReplayStoppedSchema, type WsServerMessage, WsServerMessageSchema, type WsStream, type WsStreamCompleted, WsStreamCompletedSchema, type WsStreamProgress, WsStreamProgressSchema, type WsStreamStarted, WsStreamStartedSchema, type WsStreamStop, type WsStreamStopped, WsStreamStoppedSchema, type WsSubscribe, type WsSubscribed, WsSubscribedSchema, type WsUnsubscribe, type WsUnsubscribed, WsUnsubscribedSchema, OxArchive as default };
|
package/dist/index.js
CHANGED
|
@@ -428,7 +428,7 @@ var OrderBookResource = class {
|
|
|
428
428
|
*/
|
|
429
429
|
async history(coin, params) {
|
|
430
430
|
const response = await this.http.get(
|
|
431
|
-
|
|
431
|
+
`${this.basePath}/orderbook/${coin.toUpperCase()}/history`,
|
|
432
432
|
params,
|
|
433
433
|
this.http.validationEnabled ? OrderBookArrayResponseSchema : void 0
|
|
434
434
|
);
|
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/resources/orderbook.ts","../src/resources/trades.ts","../src/resources/instruments.ts","../src/resources/funding.ts","../src/resources/openinterest.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 * - 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: 'ox_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, LighterClient } from './exchanges';\r\n\r\n// WebSocket client\r\nexport { OxArchiveWs } from './websocket';\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 // 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 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 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 // 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 InstrumentType,\r\n // Funding\r\n FundingRate,\r\n // Open Interest\r\n OpenInterest,\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 WsHistoricalData,\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 // 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\nexport interface OrderBookHistoryParams extends CursorPaginationParams {\r\n /** Number of price levels to return per side */\r\n depth?: number;\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// 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 * Parameters for getting funding rate history\r\n */\r\nexport interface FundingHistoryParams extends CursorPaginationParams {}\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\r\n// =============================================================================\r\n// WebSocket Types\r\n// =============================================================================\r\n\r\n/** WebSocket channel types. Note: ticker/all_tickers are real-time only. */\r\nexport type WsChannel = 'orderbook' | 'trades' | 'ticker' | 'all_tickers';\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 channel: 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}\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 channel: 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}\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/** 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/** 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 | WsHistoricalData\r\n | WsStreamStarted\r\n | WsStreamProgress\r\n | WsHistoricalBatch\r\n | WsStreamCompleted\r\n | WsStreamStopped;\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","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-z])/g, (_, letter) => letter.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// WebSocket Message Schemas\r\n// =============================================================================\r\n\r\nexport const WsChannelSchema = z.enum(['orderbook', 'trades', 'ticker', 'all_tickers']);\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 currentTimestamp: z.number(),\r\n});\r\n\r\nexport const WsReplayResumedSchema = z.object({\r\n type: z.literal('replay_resumed'),\r\n currentTimestamp: 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 snapshotsSent: 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\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 snapshotsSent: 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 snapshotsSent: z.number(),\r\n});\r\n\r\nexport const WsStreamStoppedSchema = z.object({\r\n type: z.literal('stream_stopped'),\r\n snapshotsSent: 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 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\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 ValidatedWsServerMessage = z.infer<typeof WsServerMessageSchema>;\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} from '../types';\r\nimport { OrderBookResponseSchema, OrderBookArrayResponseSchema } from '../schemas';\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 */\r\nexport class OrderBookResource {\r\n constructor(private http: HttpClient, private basePath: string = '/v1') {}\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/${coin.toUpperCase()}`,\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 `/v1/orderbook/${coin.toUpperCase()}/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","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 recent trades\r\n * const trades = await client.trades.recent('BTC');\r\n *\r\n * // Get trade history with cursor-based pagination (recommended)\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 * // Get all pages\r\n * const allTrades = [...result.data];\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 * allTrades.push(...result.data);\r\n * }\r\n * ```\r\n */\r\nexport class TradesResource {\r\n constructor(private http: HttpClient, private basePath: string = '/v1') {}\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/${coin.toUpperCase()}`,\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 * @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 `/v1/trades/${coin.toUpperCase()}/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, 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","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(private http: HttpClient, private basePath: string = '/v1') {}\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/${coin.toUpperCase()}`,\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 `/v1/funding/${coin.toUpperCase()}/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(private http: HttpClient, private basePath: string = '/v1') {}\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/${coin.toUpperCase()}`,\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 `/v1/openinterest/${coin.toUpperCase()}/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 {\r\n OrderBookResource,\r\n TradesResource,\r\n InstrumentsResource,\r\n LighterInstrumentsResource,\r\n FundingResource,\r\n OpenInterestResource,\r\n} from './resources';\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 constructor(http: HttpClient) {\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 }\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 constructor(http: HttpClient) {\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 }\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} 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: 'ox_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 * @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 // 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 PriceLevel,\r\n Trade,\r\n WsHistoricalData,\r\n WsHistoricalBatch,\r\n WsReplayStarted,\r\n WsReplayCompleted,\r\n WsStreamStarted,\r\n WsStreamCompleted,\r\n WsStreamProgress,\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 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 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\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 }\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 });\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 }\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 });\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 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 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 * 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_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 '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 '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/resources/orderbook.ts","../src/resources/trades.ts","../src/resources/instruments.ts","../src/resources/funding.ts","../src/resources/openinterest.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 * - 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: 'ox_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, LighterClient } from './exchanges';\r\n\r\n// WebSocket client\r\nexport { OxArchiveWs } from './websocket';\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 // 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 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 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 InstrumentType,\r\n // Funding\r\n FundingRate,\r\n // Open Interest\r\n OpenInterest,\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 WsHistoricalData,\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 // 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// 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 * Parameters for getting funding rate history\r\n */\r\nexport interface FundingHistoryParams extends CursorPaginationParams {}\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\r\n// =============================================================================\r\n// WebSocket Types\r\n// =============================================================================\r\n\r\n/** WebSocket channel types. Note: ticker/all_tickers are real-time only. */\r\nexport type WsChannel = 'orderbook' | 'trades' | 'ticker' | 'all_tickers';\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 channel: 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}\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 channel: 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}\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/** 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/** 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 | WsHistoricalData\r\n | WsStreamStarted\r\n | WsStreamProgress\r\n | WsHistoricalBatch\r\n | WsStreamCompleted\r\n | WsStreamStopped;\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","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-z])/g, (_, letter) => letter.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// WebSocket Message Schemas\r\n// =============================================================================\r\n\r\nexport const WsChannelSchema = z.enum(['orderbook', 'trades', 'ticker', 'all_tickers']);\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 currentTimestamp: z.number(),\r\n});\r\n\r\nexport const WsReplayResumedSchema = z.object({\r\n type: z.literal('replay_resumed'),\r\n currentTimestamp: 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 snapshotsSent: 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\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 snapshotsSent: 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 snapshotsSent: z.number(),\r\n});\r\n\r\nexport const WsStreamStoppedSchema = z.object({\r\n type: z.literal('stream_stopped'),\r\n snapshotsSent: 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 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\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 ValidatedWsServerMessage = z.infer<typeof WsServerMessageSchema>;\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} from '../types';\r\nimport { OrderBookResponseSchema, OrderBookArrayResponseSchema } from '../schemas';\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 */\r\nexport class OrderBookResource {\r\n constructor(private http: HttpClient, private basePath: string = '/v1') {}\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/${coin.toUpperCase()}`,\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/${coin.toUpperCase()}/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","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 recent trades\r\n * const trades = await client.trades.recent('BTC');\r\n *\r\n * // Get trade history with cursor-based pagination (recommended)\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 * // Get all pages\r\n * const allTrades = [...result.data];\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 * allTrades.push(...result.data);\r\n * }\r\n * ```\r\n */\r\nexport class TradesResource {\r\n constructor(private http: HttpClient, private basePath: string = '/v1') {}\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/${coin.toUpperCase()}`,\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 * @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 `/v1/trades/${coin.toUpperCase()}/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, 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","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(private http: HttpClient, private basePath: string = '/v1') {}\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/${coin.toUpperCase()}`,\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 `/v1/funding/${coin.toUpperCase()}/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(private http: HttpClient, private basePath: string = '/v1') {}\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/${coin.toUpperCase()}`,\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 `/v1/openinterest/${coin.toUpperCase()}/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 {\r\n OrderBookResource,\r\n TradesResource,\r\n InstrumentsResource,\r\n LighterInstrumentsResource,\r\n FundingResource,\r\n OpenInterestResource,\r\n} from './resources';\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 constructor(http: HttpClient) {\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 }\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 constructor(http: HttpClient) {\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 }\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} 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: 'ox_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 * @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 // 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 PriceLevel,\r\n Trade,\r\n WsHistoricalData,\r\n WsHistoricalBatch,\r\n WsReplayStarted,\r\n WsReplayCompleted,\r\n WsStreamStarted,\r\n WsStreamCompleted,\r\n WsStreamProgress,\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 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 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\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 }\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 });\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 }\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 });\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 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 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 * 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_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 '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 '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":[]}
|
package/dist/index.mjs
CHANGED
|
@@ -357,7 +357,7 @@ var OrderBookResource = class {
|
|
|
357
357
|
*/
|
|
358
358
|
async history(coin, params) {
|
|
359
359
|
const response = await this.http.get(
|
|
360
|
-
|
|
360
|
+
`${this.basePath}/orderbook/${coin.toUpperCase()}/history`,
|
|
361
361
|
params,
|
|
362
362
|
this.http.validationEnabled ? OrderBookArrayResponseSchema : void 0
|
|
363
363
|
);
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types.ts","../src/http.ts","../src/schemas.ts","../src/resources/orderbook.ts","../src/resources/trades.ts","../src/resources/instruments.ts","../src/resources/funding.ts","../src/resources/openinterest.ts","../src/exchanges.ts","../src/client.ts","../src/websocket.ts"],"sourcesContent":["/**\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\nexport interface OrderBookHistoryParams extends CursorPaginationParams {\r\n /** Number of price levels to return per side */\r\n depth?: number;\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// 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 * Parameters for getting funding rate history\r\n */\r\nexport interface FundingHistoryParams extends CursorPaginationParams {}\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\r\n// =============================================================================\r\n// WebSocket Types\r\n// =============================================================================\r\n\r\n/** WebSocket channel types. Note: ticker/all_tickers are real-time only. */\r\nexport type WsChannel = 'orderbook' | 'trades' | 'ticker' | 'all_tickers';\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 channel: 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}\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 channel: 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}\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/** 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/** 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 | WsHistoricalData\r\n | WsStreamStarted\r\n | WsStreamProgress\r\n | WsHistoricalBatch\r\n | WsStreamCompleted\r\n | WsStreamStopped;\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","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-z])/g, (_, letter) => letter.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// WebSocket Message Schemas\r\n// =============================================================================\r\n\r\nexport const WsChannelSchema = z.enum(['orderbook', 'trades', 'ticker', 'all_tickers']);\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 currentTimestamp: z.number(),\r\n});\r\n\r\nexport const WsReplayResumedSchema = z.object({\r\n type: z.literal('replay_resumed'),\r\n currentTimestamp: 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 snapshotsSent: 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\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 snapshotsSent: 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 snapshotsSent: z.number(),\r\n});\r\n\r\nexport const WsStreamStoppedSchema = z.object({\r\n type: z.literal('stream_stopped'),\r\n snapshotsSent: 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 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\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 ValidatedWsServerMessage = z.infer<typeof WsServerMessageSchema>;\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} from '../types';\r\nimport { OrderBookResponseSchema, OrderBookArrayResponseSchema } from '../schemas';\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 */\r\nexport class OrderBookResource {\r\n constructor(private http: HttpClient, private basePath: string = '/v1') {}\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/${coin.toUpperCase()}`,\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 `/v1/orderbook/${coin.toUpperCase()}/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","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 recent trades\r\n * const trades = await client.trades.recent('BTC');\r\n *\r\n * // Get trade history with cursor-based pagination (recommended)\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 * // Get all pages\r\n * const allTrades = [...result.data];\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 * allTrades.push(...result.data);\r\n * }\r\n * ```\r\n */\r\nexport class TradesResource {\r\n constructor(private http: HttpClient, private basePath: string = '/v1') {}\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/${coin.toUpperCase()}`,\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 * @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 `/v1/trades/${coin.toUpperCase()}/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, 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","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(private http: HttpClient, private basePath: string = '/v1') {}\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/${coin.toUpperCase()}`,\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 `/v1/funding/${coin.toUpperCase()}/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(private http: HttpClient, private basePath: string = '/v1') {}\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/${coin.toUpperCase()}`,\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 `/v1/openinterest/${coin.toUpperCase()}/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 {\r\n OrderBookResource,\r\n TradesResource,\r\n InstrumentsResource,\r\n LighterInstrumentsResource,\r\n FundingResource,\r\n OpenInterestResource,\r\n} from './resources';\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 constructor(http: HttpClient) {\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 }\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 constructor(http: HttpClient) {\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 }\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} 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: 'ox_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 * @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 // 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 PriceLevel,\r\n Trade,\r\n WsHistoricalData,\r\n WsHistoricalBatch,\r\n WsReplayStarted,\r\n WsReplayCompleted,\r\n WsStreamStarted,\r\n WsStreamCompleted,\r\n WsStreamProgress,\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 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 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\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 }\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 });\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 }\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 });\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 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 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 * 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_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 '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 '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/types.ts","../src/http.ts","../src/schemas.ts","../src/resources/orderbook.ts","../src/resources/trades.ts","../src/resources/instruments.ts","../src/resources/funding.ts","../src/resources/openinterest.ts","../src/exchanges.ts","../src/client.ts","../src/websocket.ts"],"sourcesContent":["/**\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// 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 * Parameters for getting funding rate history\r\n */\r\nexport interface FundingHistoryParams extends CursorPaginationParams {}\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\r\n// =============================================================================\r\n// WebSocket Types\r\n// =============================================================================\r\n\r\n/** WebSocket channel types. Note: ticker/all_tickers are real-time only. */\r\nexport type WsChannel = 'orderbook' | 'trades' | 'ticker' | 'all_tickers';\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 channel: 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}\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 channel: 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}\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/** 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/** 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 | WsHistoricalData\r\n | WsStreamStarted\r\n | WsStreamProgress\r\n | WsHistoricalBatch\r\n | WsStreamCompleted\r\n | WsStreamStopped;\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","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-z])/g, (_, letter) => letter.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// WebSocket Message Schemas\r\n// =============================================================================\r\n\r\nexport const WsChannelSchema = z.enum(['orderbook', 'trades', 'ticker', 'all_tickers']);\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 currentTimestamp: z.number(),\r\n});\r\n\r\nexport const WsReplayResumedSchema = z.object({\r\n type: z.literal('replay_resumed'),\r\n currentTimestamp: 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 snapshotsSent: 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\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 snapshotsSent: 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 snapshotsSent: z.number(),\r\n});\r\n\r\nexport const WsStreamStoppedSchema = z.object({\r\n type: z.literal('stream_stopped'),\r\n snapshotsSent: 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 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\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 ValidatedWsServerMessage = z.infer<typeof WsServerMessageSchema>;\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} from '../types';\r\nimport { OrderBookResponseSchema, OrderBookArrayResponseSchema } from '../schemas';\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 */\r\nexport class OrderBookResource {\r\n constructor(private http: HttpClient, private basePath: string = '/v1') {}\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/${coin.toUpperCase()}`,\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/${coin.toUpperCase()}/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","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 recent trades\r\n * const trades = await client.trades.recent('BTC');\r\n *\r\n * // Get trade history with cursor-based pagination (recommended)\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 * // Get all pages\r\n * const allTrades = [...result.data];\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 * allTrades.push(...result.data);\r\n * }\r\n * ```\r\n */\r\nexport class TradesResource {\r\n constructor(private http: HttpClient, private basePath: string = '/v1') {}\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/${coin.toUpperCase()}`,\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 * @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 `/v1/trades/${coin.toUpperCase()}/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, 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","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(private http: HttpClient, private basePath: string = '/v1') {}\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/${coin.toUpperCase()}`,\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 `/v1/funding/${coin.toUpperCase()}/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(private http: HttpClient, private basePath: string = '/v1') {}\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/${coin.toUpperCase()}`,\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 `/v1/openinterest/${coin.toUpperCase()}/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 {\r\n OrderBookResource,\r\n TradesResource,\r\n InstrumentsResource,\r\n LighterInstrumentsResource,\r\n FundingResource,\r\n OpenInterestResource,\r\n} from './resources';\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 constructor(http: HttpClient) {\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 }\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 constructor(http: HttpClient) {\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 }\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} 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: 'ox_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 * @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 // 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 PriceLevel,\r\n Trade,\r\n WsHistoricalData,\r\n WsHistoricalBatch,\r\n WsReplayStarted,\r\n WsReplayCompleted,\r\n WsStreamStarted,\r\n WsStreamCompleted,\r\n WsStreamProgress,\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 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 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\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 }\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 });\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 }\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 });\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 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 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 * 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_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 '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 '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":[]}
|
package/package.json
CHANGED