@0xarchive/sdk 0.3.0 → 0.3.2

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/dist/index.js CHANGED
@@ -20,9 +20,50 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
+ ApiMetaSchema: () => ApiMetaSchema,
24
+ ApiResponseSchema: () => ApiResponseSchema,
25
+ DataSourceSchema: () => DataSourceSchema,
26
+ FundingRateArrayResponseSchema: () => FundingRateArrayResponseSchema,
27
+ FundingRateResponseSchema: () => FundingRateResponseSchema,
28
+ FundingRateSchema: () => FundingRateSchema,
29
+ InstrumentArrayResponseSchema: () => InstrumentArrayResponseSchema,
30
+ InstrumentResponseSchema: () => InstrumentResponseSchema,
31
+ InstrumentSchema: () => InstrumentSchema,
32
+ InstrumentTypeSchema: () => InstrumentTypeSchema,
33
+ OpenInterestArrayResponseSchema: () => OpenInterestArrayResponseSchema,
34
+ OpenInterestResponseSchema: () => OpenInterestResponseSchema,
35
+ OpenInterestSchema: () => OpenInterestSchema,
36
+ OrderBookArrayResponseSchema: () => OrderBookArrayResponseSchema,
37
+ OrderBookResponseSchema: () => OrderBookResponseSchema,
38
+ OrderBookSchema: () => OrderBookSchema,
23
39
  OxArchive: () => OxArchive,
24
40
  OxArchiveError: () => OxArchiveError,
25
41
  OxArchiveWs: () => OxArchiveWs,
42
+ PriceLevelSchema: () => PriceLevelSchema,
43
+ TimestampedRecordSchema: () => TimestampedRecordSchema,
44
+ TradeArrayResponseSchema: () => TradeArrayResponseSchema,
45
+ TradeDirectionSchema: () => TradeDirectionSchema,
46
+ TradeSchema: () => TradeSchema,
47
+ TradeSideSchema: () => TradeSideSchema,
48
+ WsChannelSchema: () => WsChannelSchema,
49
+ WsConnectionStateSchema: () => WsConnectionStateSchema,
50
+ WsDataSchema: () => WsDataSchema,
51
+ WsErrorSchema: () => WsErrorSchema,
52
+ WsHistoricalBatchSchema: () => WsHistoricalBatchSchema,
53
+ WsHistoricalDataSchema: () => WsHistoricalDataSchema,
54
+ WsPongSchema: () => WsPongSchema,
55
+ WsReplayCompletedSchema: () => WsReplayCompletedSchema,
56
+ WsReplayPausedSchema: () => WsReplayPausedSchema,
57
+ WsReplayResumedSchema: () => WsReplayResumedSchema,
58
+ WsReplayStartedSchema: () => WsReplayStartedSchema,
59
+ WsReplayStoppedSchema: () => WsReplayStoppedSchema,
60
+ WsServerMessageSchema: () => WsServerMessageSchema,
61
+ WsStreamCompletedSchema: () => WsStreamCompletedSchema,
62
+ WsStreamProgressSchema: () => WsStreamProgressSchema,
63
+ WsStreamStartedSchema: () => WsStreamStartedSchema,
64
+ WsStreamStoppedSchema: () => WsStreamStoppedSchema,
65
+ WsSubscribedSchema: () => WsSubscribedSchema,
66
+ WsUnsubscribedSchema: () => WsUnsubscribedSchema,
26
67
  default: () => OxArchive
27
68
  });
28
69
  module.exports = __toCommonJS(index_exports);
@@ -44,15 +85,25 @@ var HttpClient = class {
44
85
  baseUrl;
45
86
  apiKey;
46
87
  timeout;
88
+ validate;
47
89
  constructor(options) {
48
90
  this.baseUrl = options.baseUrl.replace(/\/$/, "");
49
91
  this.apiKey = options.apiKey;
50
92
  this.timeout = options.timeout;
93
+ this.validate = options.validate ?? false;
94
+ }
95
+ /** Whether validation is enabled */
96
+ get validationEnabled() {
97
+ return this.validate;
51
98
  }
52
99
  /**
53
100
  * Make a GET request to the API
101
+ *
102
+ * @param path - API endpoint path
103
+ * @param params - Query parameters
104
+ * @param schema - Optional Zod schema for validation (used when validation is enabled)
54
105
  */
55
- async get(path, params) {
106
+ async get(path, params, schema) {
56
107
  const url = new URL(`${this.baseUrl}${path}`);
57
108
  if (params) {
58
109
  for (const [key, value] of Object.entries(params)) {
@@ -82,6 +133,17 @@ var HttpClient = class {
82
133
  data.meta?.request_id
83
134
  );
84
135
  }
136
+ if (this.validate && schema) {
137
+ const result = schema.safeParse(data);
138
+ if (!result.success) {
139
+ throw new OxArchiveError(
140
+ `Response validation failed: ${result.error.message}`,
141
+ 422,
142
+ data.meta?.request_id
143
+ );
144
+ }
145
+ return result.data;
146
+ }
85
147
  return data;
86
148
  } catch (error) {
87
149
  clearTimeout(timeoutId);
@@ -99,6 +161,203 @@ var HttpClient = class {
99
161
  }
100
162
  };
101
163
 
164
+ // src/schemas.ts
165
+ var import_zod = require("zod");
166
+ var ApiMetaSchema = import_zod.z.object({
167
+ count: import_zod.z.number(),
168
+ next_cursor: import_zod.z.string().optional(),
169
+ request_id: import_zod.z.string()
170
+ });
171
+ var ApiResponseSchema = (dataSchema) => import_zod.z.object({
172
+ success: import_zod.z.boolean(),
173
+ data: dataSchema,
174
+ meta: ApiMetaSchema
175
+ });
176
+ var PriceLevelSchema = import_zod.z.object({
177
+ px: import_zod.z.string(),
178
+ sz: import_zod.z.string(),
179
+ n: import_zod.z.number()
180
+ });
181
+ var OrderBookSchema = import_zod.z.object({
182
+ coin: import_zod.z.string(),
183
+ timestamp: import_zod.z.string(),
184
+ bids: import_zod.z.array(PriceLevelSchema),
185
+ asks: import_zod.z.array(PriceLevelSchema),
186
+ mid_price: import_zod.z.string().optional(),
187
+ spread: import_zod.z.string().optional(),
188
+ spread_bps: import_zod.z.string().optional()
189
+ });
190
+ var TradeSideSchema = import_zod.z.enum(["A", "B"]);
191
+ var TradeDirectionSchema = import_zod.z.enum([
192
+ "Open Long",
193
+ "Open Short",
194
+ "Close Long",
195
+ "Close Short"
196
+ ]);
197
+ var DataSourceSchema = import_zod.z.enum(["s3", "ws", "api", "live"]);
198
+ var TradeSchema = import_zod.z.object({
199
+ coin: import_zod.z.string(),
200
+ side: TradeSideSchema,
201
+ price: import_zod.z.string(),
202
+ size: import_zod.z.string(),
203
+ timestamp: import_zod.z.string(),
204
+ tx_hash: import_zod.z.string().optional(),
205
+ trade_id: import_zod.z.number().optional(),
206
+ order_id: import_zod.z.number().optional(),
207
+ crossed: import_zod.z.boolean().optional(),
208
+ fee: import_zod.z.string().optional(),
209
+ fee_token: import_zod.z.string().optional(),
210
+ closed_pnl: import_zod.z.string().optional(),
211
+ direction: TradeDirectionSchema.optional(),
212
+ start_position: import_zod.z.string().optional(),
213
+ source: DataSourceSchema.optional(),
214
+ user_address: import_zod.z.string().optional(),
215
+ maker_address: import_zod.z.string().optional(),
216
+ taker_address: import_zod.z.string().optional()
217
+ });
218
+ var InstrumentTypeSchema = import_zod.z.enum(["perp", "spot"]);
219
+ var InstrumentSchema = import_zod.z.object({
220
+ name: import_zod.z.string(),
221
+ szDecimals: import_zod.z.number(),
222
+ maxLeverage: import_zod.z.number().optional(),
223
+ onlyIsolated: import_zod.z.boolean().optional(),
224
+ instrumentType: InstrumentTypeSchema.optional(),
225
+ isActive: import_zod.z.boolean()
226
+ });
227
+ var FundingRateSchema = import_zod.z.object({
228
+ coin: import_zod.z.string(),
229
+ timestamp: import_zod.z.string(),
230
+ funding_rate: import_zod.z.string(),
231
+ premium: import_zod.z.string().optional()
232
+ });
233
+ var OpenInterestSchema = import_zod.z.object({
234
+ coin: import_zod.z.string(),
235
+ timestamp: import_zod.z.string(),
236
+ open_interest: import_zod.z.string(),
237
+ mark_price: import_zod.z.string().optional(),
238
+ oracle_price: import_zod.z.string().optional(),
239
+ day_ntl_volume: import_zod.z.string().optional(),
240
+ prev_day_price: import_zod.z.string().optional(),
241
+ mid_price: import_zod.z.string().optional(),
242
+ impact_bid_price: import_zod.z.string().optional(),
243
+ impact_ask_price: import_zod.z.string().optional()
244
+ });
245
+ var WsChannelSchema = import_zod.z.enum(["orderbook", "trades", "ticker", "all_tickers"]);
246
+ var WsConnectionStateSchema = import_zod.z.enum(["connecting", "connected", "disconnected", "reconnecting"]);
247
+ var WsSubscribedSchema = import_zod.z.object({
248
+ type: import_zod.z.literal("subscribed"),
249
+ channel: WsChannelSchema,
250
+ coin: import_zod.z.string().optional()
251
+ });
252
+ var WsUnsubscribedSchema = import_zod.z.object({
253
+ type: import_zod.z.literal("unsubscribed"),
254
+ channel: WsChannelSchema,
255
+ coin: import_zod.z.string().optional()
256
+ });
257
+ var WsPongSchema = import_zod.z.object({
258
+ type: import_zod.z.literal("pong")
259
+ });
260
+ var WsErrorSchema = import_zod.z.object({
261
+ type: import_zod.z.literal("error"),
262
+ message: import_zod.z.string()
263
+ });
264
+ var WsDataSchema = import_zod.z.object({
265
+ type: import_zod.z.literal("data"),
266
+ channel: WsChannelSchema,
267
+ coin: import_zod.z.string(),
268
+ data: import_zod.z.unknown()
269
+ });
270
+ var WsReplayStartedSchema = import_zod.z.object({
271
+ type: import_zod.z.literal("replay_started"),
272
+ channel: WsChannelSchema,
273
+ coin: import_zod.z.string(),
274
+ start: import_zod.z.number(),
275
+ end: import_zod.z.number(),
276
+ speed: import_zod.z.number()
277
+ });
278
+ var WsReplayPausedSchema = import_zod.z.object({
279
+ type: import_zod.z.literal("replay_paused"),
280
+ current_timestamp: import_zod.z.number()
281
+ });
282
+ var WsReplayResumedSchema = import_zod.z.object({
283
+ type: import_zod.z.literal("replay_resumed"),
284
+ current_timestamp: import_zod.z.number()
285
+ });
286
+ var WsReplayCompletedSchema = import_zod.z.object({
287
+ type: import_zod.z.literal("replay_completed"),
288
+ channel: WsChannelSchema,
289
+ coin: import_zod.z.string(),
290
+ snapshots_sent: import_zod.z.number()
291
+ });
292
+ var WsReplayStoppedSchema = import_zod.z.object({
293
+ type: import_zod.z.literal("replay_stopped")
294
+ });
295
+ var WsHistoricalDataSchema = import_zod.z.object({
296
+ type: import_zod.z.literal("historical_data"),
297
+ channel: WsChannelSchema,
298
+ coin: import_zod.z.string(),
299
+ timestamp: import_zod.z.number(),
300
+ data: import_zod.z.unknown()
301
+ });
302
+ var WsStreamStartedSchema = import_zod.z.object({
303
+ type: import_zod.z.literal("stream_started"),
304
+ channel: WsChannelSchema,
305
+ coin: import_zod.z.string(),
306
+ start: import_zod.z.number(),
307
+ end: import_zod.z.number()
308
+ });
309
+ var WsStreamProgressSchema = import_zod.z.object({
310
+ type: import_zod.z.literal("stream_progress"),
311
+ snapshots_sent: import_zod.z.number()
312
+ });
313
+ var TimestampedRecordSchema = import_zod.z.object({
314
+ timestamp: import_zod.z.number(),
315
+ data: import_zod.z.unknown()
316
+ });
317
+ var WsHistoricalBatchSchema = import_zod.z.object({
318
+ type: import_zod.z.literal("historical_batch"),
319
+ channel: WsChannelSchema,
320
+ coin: import_zod.z.string(),
321
+ data: import_zod.z.array(TimestampedRecordSchema)
322
+ });
323
+ var WsStreamCompletedSchema = import_zod.z.object({
324
+ type: import_zod.z.literal("stream_completed"),
325
+ channel: WsChannelSchema,
326
+ coin: import_zod.z.string(),
327
+ snapshots_sent: import_zod.z.number()
328
+ });
329
+ var WsStreamStoppedSchema = import_zod.z.object({
330
+ type: import_zod.z.literal("stream_stopped"),
331
+ snapshots_sent: import_zod.z.number()
332
+ });
333
+ var WsServerMessageSchema = import_zod.z.discriminatedUnion("type", [
334
+ WsSubscribedSchema,
335
+ WsUnsubscribedSchema,
336
+ WsPongSchema,
337
+ WsErrorSchema,
338
+ WsDataSchema,
339
+ WsReplayStartedSchema,
340
+ WsReplayPausedSchema,
341
+ WsReplayResumedSchema,
342
+ WsReplayCompletedSchema,
343
+ WsReplayStoppedSchema,
344
+ WsHistoricalDataSchema,
345
+ WsStreamStartedSchema,
346
+ WsStreamProgressSchema,
347
+ WsHistoricalBatchSchema,
348
+ WsStreamCompletedSchema,
349
+ WsStreamStoppedSchema
350
+ ]);
351
+ var OrderBookResponseSchema = ApiResponseSchema(OrderBookSchema);
352
+ var OrderBookArrayResponseSchema = ApiResponseSchema(import_zod.z.array(OrderBookSchema));
353
+ var TradeArrayResponseSchema = ApiResponseSchema(import_zod.z.array(TradeSchema));
354
+ var InstrumentResponseSchema = ApiResponseSchema(InstrumentSchema);
355
+ var InstrumentArrayResponseSchema = ApiResponseSchema(import_zod.z.array(InstrumentSchema));
356
+ var FundingRateResponseSchema = ApiResponseSchema(FundingRateSchema);
357
+ var FundingRateArrayResponseSchema = ApiResponseSchema(import_zod.z.array(FundingRateSchema));
358
+ var OpenInterestResponseSchema = ApiResponseSchema(OpenInterestSchema);
359
+ var OpenInterestArrayResponseSchema = ApiResponseSchema(import_zod.z.array(OpenInterestSchema));
360
+
102
361
  // src/resources/orderbook.ts
103
362
  var OrderBookResource = class {
104
363
  constructor(http) {
@@ -114,7 +373,8 @@ var OrderBookResource = class {
114
373
  async get(coin, params) {
115
374
  const response = await this.http.get(
116
375
  `/v1/orderbook/${coin.toUpperCase()}`,
117
- params
376
+ params,
377
+ this.http.validationEnabled ? OrderBookResponseSchema : void 0
118
378
  );
119
379
  return response.data;
120
380
  }
@@ -128,7 +388,8 @@ var OrderBookResource = class {
128
388
  async history(coin, params) {
129
389
  const response = await this.http.get(
130
390
  `/v1/orderbook/${coin.toUpperCase()}/history`,
131
- params
391
+ params,
392
+ this.http.validationEnabled ? OrderBookArrayResponseSchema : void 0
132
393
  );
133
394
  return response.data;
134
395
  }
@@ -172,7 +433,8 @@ var TradesResource = class {
172
433
  async list(coin, params) {
173
434
  const response = await this.http.get(
174
435
  `/v1/trades/${coin.toUpperCase()}`,
175
- params
436
+ params,
437
+ this.http.validationEnabled ? TradeArrayResponseSchema : void 0
176
438
  );
177
439
  return {
178
440
  data: response.data,
@@ -189,7 +451,8 @@ var TradesResource = class {
189
451
  async recent(coin, limit) {
190
452
  const response = await this.http.get(
191
453
  `/v1/trades/${coin.toUpperCase()}/recent`,
192
- { limit }
454
+ { limit },
455
+ this.http.validationEnabled ? TradeArrayResponseSchema : void 0
193
456
  );
194
457
  return response.data;
195
458
  }
@@ -217,7 +480,8 @@ var TradesResource = class {
217
480
  async listWithOffset(coin, params) {
218
481
  const response = await this.http.get(
219
482
  `/v1/trades/${coin.toUpperCase()}`,
220
- params
483
+ params,
484
+ this.http.validationEnabled ? TradeArrayResponseSchema : void 0
221
485
  );
222
486
  return response.data;
223
487
  }
@@ -235,7 +499,9 @@ var InstrumentsResource = class {
235
499
  */
236
500
  async list() {
237
501
  const response = await this.http.get(
238
- "/v1/instruments"
502
+ "/v1/instruments",
503
+ void 0,
504
+ this.http.validationEnabled ? InstrumentArrayResponseSchema : void 0
239
505
  );
240
506
  return response.data;
241
507
  }
@@ -247,7 +513,9 @@ var InstrumentsResource = class {
247
513
  */
248
514
  async get(coin) {
249
515
  const response = await this.http.get(
250
- `/v1/instruments/${coin.toUpperCase()}`
516
+ `/v1/instruments/${coin.toUpperCase()}`,
517
+ void 0,
518
+ this.http.validationEnabled ? InstrumentResponseSchema : void 0
251
519
  );
252
520
  return response.data;
253
521
  }
@@ -268,7 +536,8 @@ var FundingResource = class {
268
536
  async history(coin, params) {
269
537
  const response = await this.http.get(
270
538
  `/v1/funding/${coin.toUpperCase()}`,
271
- params
539
+ params,
540
+ this.http.validationEnabled ? FundingRateArrayResponseSchema : void 0
272
541
  );
273
542
  return response.data;
274
543
  }
@@ -280,7 +549,9 @@ var FundingResource = class {
280
549
  */
281
550
  async current(coin) {
282
551
  const response = await this.http.get(
283
- `/v1/funding/${coin.toUpperCase()}/current`
552
+ `/v1/funding/${coin.toUpperCase()}/current`,
553
+ void 0,
554
+ this.http.validationEnabled ? FundingRateResponseSchema : void 0
284
555
  );
285
556
  return response.data;
286
557
  }
@@ -301,7 +572,8 @@ var OpenInterestResource = class {
301
572
  async history(coin, params) {
302
573
  const response = await this.http.get(
303
574
  `/v1/openinterest/${coin.toUpperCase()}`,
304
- params
575
+ params,
576
+ this.http.validationEnabled ? OpenInterestArrayResponseSchema : void 0
305
577
  );
306
578
  return response.data;
307
579
  }
@@ -313,7 +585,9 @@ var OpenInterestResource = class {
313
585
  */
314
586
  async current(coin) {
315
587
  const response = await this.http.get(
316
- `/v1/openinterest/${coin.toUpperCase()}/current`
588
+ `/v1/openinterest/${coin.toUpperCase()}/current`,
589
+ void 0,
590
+ this.http.validationEnabled ? OpenInterestResponseSchema : void 0
317
591
  );
318
592
  return response.data;
319
593
  }
@@ -356,7 +630,8 @@ var OxArchive = class {
356
630
  this.http = new HttpClient({
357
631
  baseUrl: options.baseUrl ?? DEFAULT_BASE_URL,
358
632
  apiKey: options.apiKey,
359
- timeout: options.timeout ?? DEFAULT_TIMEOUT
633
+ timeout: options.timeout ?? DEFAULT_TIMEOUT,
634
+ validate: options.validate ?? false
360
635
  });
361
636
  this.orderbook = new OrderBookResource(this.http);
362
637
  this.trades = new TradesResource(this.http);
@@ -371,6 +646,39 @@ var DEFAULT_WS_URL = "wss://api.0xarchive.io/ws";
371
646
  var DEFAULT_PING_INTERVAL = 3e4;
372
647
  var DEFAULT_RECONNECT_DELAY = 1e3;
373
648
  var DEFAULT_MAX_RECONNECT_ATTEMPTS = 10;
649
+ function transformTrade(coin, raw) {
650
+ if ("price" in raw && "size" in raw) {
651
+ return raw;
652
+ }
653
+ const px = raw.px;
654
+ const sz = raw.sz;
655
+ const side = raw.side;
656
+ const time = raw.time;
657
+ const hash = raw.hash;
658
+ const tid = raw.tid;
659
+ const users = raw.users;
660
+ const maker_address = users && users.length > 0 ? users[0] : void 0;
661
+ const taker_address = users && users.length > 1 ? users[1] : void 0;
662
+ const user_address = raw.userAddress ?? raw.user_address;
663
+ return {
664
+ coin,
665
+ side: side === "A" || side === "B" ? side : "B",
666
+ price: px ?? "0",
667
+ size: sz ?? "0",
668
+ timestamp: time ? new Date(time).toISOString() : (/* @__PURE__ */ new Date()).toISOString(),
669
+ tx_hash: hash,
670
+ trade_id: tid,
671
+ maker_address,
672
+ taker_address,
673
+ user_address
674
+ };
675
+ }
676
+ function transformTrades(coin, rawTrades) {
677
+ if (!Array.isArray(rawTrades)) {
678
+ return [transformTrade(coin, rawTrades)];
679
+ }
680
+ return rawTrades.map((raw) => transformTrade(coin, raw));
681
+ }
374
682
  function transformOrderbook(coin, raw) {
375
683
  if ("bids" in raw && "asks" in raw) {
376
684
  return raw;
@@ -826,8 +1134,9 @@ var OxArchiveWs = class {
826
1134
  handler(message.coin, orderbook);
827
1135
  }
828
1136
  } else if (message.channel === "trades") {
1137
+ const trades = transformTrades(message.coin, message.data);
829
1138
  for (const handler of this.tradesHandlers) {
830
- handler(message.coin, message.data);
1139
+ handler(message.coin, trades);
831
1140
  }
832
1141
  }
833
1142
  break;
@@ -837,8 +1146,49 @@ var OxArchiveWs = class {
837
1146
  };
838
1147
  // Annotate the CommonJS export names for ESM import in node:
839
1148
  0 && (module.exports = {
1149
+ ApiMetaSchema,
1150
+ ApiResponseSchema,
1151
+ DataSourceSchema,
1152
+ FundingRateArrayResponseSchema,
1153
+ FundingRateResponseSchema,
1154
+ FundingRateSchema,
1155
+ InstrumentArrayResponseSchema,
1156
+ InstrumentResponseSchema,
1157
+ InstrumentSchema,
1158
+ InstrumentTypeSchema,
1159
+ OpenInterestArrayResponseSchema,
1160
+ OpenInterestResponseSchema,
1161
+ OpenInterestSchema,
1162
+ OrderBookArrayResponseSchema,
1163
+ OrderBookResponseSchema,
1164
+ OrderBookSchema,
840
1165
  OxArchive,
841
1166
  OxArchiveError,
842
- OxArchiveWs
1167
+ OxArchiveWs,
1168
+ PriceLevelSchema,
1169
+ TimestampedRecordSchema,
1170
+ TradeArrayResponseSchema,
1171
+ TradeDirectionSchema,
1172
+ TradeSchema,
1173
+ TradeSideSchema,
1174
+ WsChannelSchema,
1175
+ WsConnectionStateSchema,
1176
+ WsDataSchema,
1177
+ WsErrorSchema,
1178
+ WsHistoricalBatchSchema,
1179
+ WsHistoricalDataSchema,
1180
+ WsPongSchema,
1181
+ WsReplayCompletedSchema,
1182
+ WsReplayPausedSchema,
1183
+ WsReplayResumedSchema,
1184
+ WsReplayStartedSchema,
1185
+ WsReplayStoppedSchema,
1186
+ WsServerMessageSchema,
1187
+ WsStreamCompletedSchema,
1188
+ WsStreamProgressSchema,
1189
+ WsStreamStartedSchema,
1190
+ WsStreamStoppedSchema,
1191
+ WsSubscribedSchema,
1192
+ WsUnsubscribedSchema
843
1193
  });
844
1194
  //# sourceMappingURL=index.js.map