@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.mjs CHANGED
@@ -15,15 +15,25 @@ var HttpClient = class {
15
15
  baseUrl;
16
16
  apiKey;
17
17
  timeout;
18
+ validate;
18
19
  constructor(options) {
19
20
  this.baseUrl = options.baseUrl.replace(/\/$/, "");
20
21
  this.apiKey = options.apiKey;
21
22
  this.timeout = options.timeout;
23
+ this.validate = options.validate ?? false;
24
+ }
25
+ /** Whether validation is enabled */
26
+ get validationEnabled() {
27
+ return this.validate;
22
28
  }
23
29
  /**
24
30
  * Make a GET request to the API
31
+ *
32
+ * @param path - API endpoint path
33
+ * @param params - Query parameters
34
+ * @param schema - Optional Zod schema for validation (used when validation is enabled)
25
35
  */
26
- async get(path, params) {
36
+ async get(path, params, schema) {
27
37
  const url = new URL(`${this.baseUrl}${path}`);
28
38
  if (params) {
29
39
  for (const [key, value] of Object.entries(params)) {
@@ -53,6 +63,17 @@ var HttpClient = class {
53
63
  data.meta?.request_id
54
64
  );
55
65
  }
66
+ if (this.validate && schema) {
67
+ const result = schema.safeParse(data);
68
+ if (!result.success) {
69
+ throw new OxArchiveError(
70
+ `Response validation failed: ${result.error.message}`,
71
+ 422,
72
+ data.meta?.request_id
73
+ );
74
+ }
75
+ return result.data;
76
+ }
56
77
  return data;
57
78
  } catch (error) {
58
79
  clearTimeout(timeoutId);
@@ -70,6 +91,203 @@ var HttpClient = class {
70
91
  }
71
92
  };
72
93
 
94
+ // src/schemas.ts
95
+ import { z } from "zod";
96
+ var ApiMetaSchema = z.object({
97
+ count: z.number(),
98
+ next_cursor: z.string().optional(),
99
+ request_id: z.string()
100
+ });
101
+ var ApiResponseSchema = (dataSchema) => z.object({
102
+ success: z.boolean(),
103
+ data: dataSchema,
104
+ meta: ApiMetaSchema
105
+ });
106
+ var PriceLevelSchema = z.object({
107
+ px: z.string(),
108
+ sz: z.string(),
109
+ n: z.number()
110
+ });
111
+ var OrderBookSchema = z.object({
112
+ coin: z.string(),
113
+ timestamp: z.string(),
114
+ bids: z.array(PriceLevelSchema),
115
+ asks: z.array(PriceLevelSchema),
116
+ mid_price: z.string().optional(),
117
+ spread: z.string().optional(),
118
+ spread_bps: z.string().optional()
119
+ });
120
+ var TradeSideSchema = z.enum(["A", "B"]);
121
+ var TradeDirectionSchema = z.enum([
122
+ "Open Long",
123
+ "Open Short",
124
+ "Close Long",
125
+ "Close Short"
126
+ ]);
127
+ var DataSourceSchema = z.enum(["s3", "ws", "api", "live"]);
128
+ var TradeSchema = z.object({
129
+ coin: z.string(),
130
+ side: TradeSideSchema,
131
+ price: z.string(),
132
+ size: z.string(),
133
+ timestamp: z.string(),
134
+ tx_hash: z.string().optional(),
135
+ trade_id: z.number().optional(),
136
+ order_id: z.number().optional(),
137
+ crossed: z.boolean().optional(),
138
+ fee: z.string().optional(),
139
+ fee_token: z.string().optional(),
140
+ closed_pnl: z.string().optional(),
141
+ direction: TradeDirectionSchema.optional(),
142
+ start_position: z.string().optional(),
143
+ source: DataSourceSchema.optional(),
144
+ user_address: z.string().optional(),
145
+ maker_address: z.string().optional(),
146
+ taker_address: z.string().optional()
147
+ });
148
+ var InstrumentTypeSchema = z.enum(["perp", "spot"]);
149
+ var InstrumentSchema = z.object({
150
+ name: z.string(),
151
+ szDecimals: z.number(),
152
+ maxLeverage: z.number().optional(),
153
+ onlyIsolated: z.boolean().optional(),
154
+ instrumentType: InstrumentTypeSchema.optional(),
155
+ isActive: z.boolean()
156
+ });
157
+ var FundingRateSchema = z.object({
158
+ coin: z.string(),
159
+ timestamp: z.string(),
160
+ funding_rate: z.string(),
161
+ premium: z.string().optional()
162
+ });
163
+ var OpenInterestSchema = z.object({
164
+ coin: z.string(),
165
+ timestamp: z.string(),
166
+ open_interest: z.string(),
167
+ mark_price: z.string().optional(),
168
+ oracle_price: z.string().optional(),
169
+ day_ntl_volume: z.string().optional(),
170
+ prev_day_price: z.string().optional(),
171
+ mid_price: z.string().optional(),
172
+ impact_bid_price: z.string().optional(),
173
+ impact_ask_price: z.string().optional()
174
+ });
175
+ var WsChannelSchema = z.enum(["orderbook", "trades", "ticker", "all_tickers"]);
176
+ var WsConnectionStateSchema = z.enum(["connecting", "connected", "disconnected", "reconnecting"]);
177
+ var WsSubscribedSchema = z.object({
178
+ type: z.literal("subscribed"),
179
+ channel: WsChannelSchema,
180
+ coin: z.string().optional()
181
+ });
182
+ var WsUnsubscribedSchema = z.object({
183
+ type: z.literal("unsubscribed"),
184
+ channel: WsChannelSchema,
185
+ coin: z.string().optional()
186
+ });
187
+ var WsPongSchema = z.object({
188
+ type: z.literal("pong")
189
+ });
190
+ var WsErrorSchema = z.object({
191
+ type: z.literal("error"),
192
+ message: z.string()
193
+ });
194
+ var WsDataSchema = z.object({
195
+ type: z.literal("data"),
196
+ channel: WsChannelSchema,
197
+ coin: z.string(),
198
+ data: z.unknown()
199
+ });
200
+ var WsReplayStartedSchema = z.object({
201
+ type: z.literal("replay_started"),
202
+ channel: WsChannelSchema,
203
+ coin: z.string(),
204
+ start: z.number(),
205
+ end: z.number(),
206
+ speed: z.number()
207
+ });
208
+ var WsReplayPausedSchema = z.object({
209
+ type: z.literal("replay_paused"),
210
+ current_timestamp: z.number()
211
+ });
212
+ var WsReplayResumedSchema = z.object({
213
+ type: z.literal("replay_resumed"),
214
+ current_timestamp: z.number()
215
+ });
216
+ var WsReplayCompletedSchema = z.object({
217
+ type: z.literal("replay_completed"),
218
+ channel: WsChannelSchema,
219
+ coin: z.string(),
220
+ snapshots_sent: z.number()
221
+ });
222
+ var WsReplayStoppedSchema = z.object({
223
+ type: z.literal("replay_stopped")
224
+ });
225
+ var WsHistoricalDataSchema = z.object({
226
+ type: z.literal("historical_data"),
227
+ channel: WsChannelSchema,
228
+ coin: z.string(),
229
+ timestamp: z.number(),
230
+ data: z.unknown()
231
+ });
232
+ var WsStreamStartedSchema = z.object({
233
+ type: z.literal("stream_started"),
234
+ channel: WsChannelSchema,
235
+ coin: z.string(),
236
+ start: z.number(),
237
+ end: z.number()
238
+ });
239
+ var WsStreamProgressSchema = z.object({
240
+ type: z.literal("stream_progress"),
241
+ snapshots_sent: z.number()
242
+ });
243
+ var TimestampedRecordSchema = z.object({
244
+ timestamp: z.number(),
245
+ data: z.unknown()
246
+ });
247
+ var WsHistoricalBatchSchema = z.object({
248
+ type: z.literal("historical_batch"),
249
+ channel: WsChannelSchema,
250
+ coin: z.string(),
251
+ data: z.array(TimestampedRecordSchema)
252
+ });
253
+ var WsStreamCompletedSchema = z.object({
254
+ type: z.literal("stream_completed"),
255
+ channel: WsChannelSchema,
256
+ coin: z.string(),
257
+ snapshots_sent: z.number()
258
+ });
259
+ var WsStreamStoppedSchema = z.object({
260
+ type: z.literal("stream_stopped"),
261
+ snapshots_sent: z.number()
262
+ });
263
+ var WsServerMessageSchema = z.discriminatedUnion("type", [
264
+ WsSubscribedSchema,
265
+ WsUnsubscribedSchema,
266
+ WsPongSchema,
267
+ WsErrorSchema,
268
+ WsDataSchema,
269
+ WsReplayStartedSchema,
270
+ WsReplayPausedSchema,
271
+ WsReplayResumedSchema,
272
+ WsReplayCompletedSchema,
273
+ WsReplayStoppedSchema,
274
+ WsHistoricalDataSchema,
275
+ WsStreamStartedSchema,
276
+ WsStreamProgressSchema,
277
+ WsHistoricalBatchSchema,
278
+ WsStreamCompletedSchema,
279
+ WsStreamStoppedSchema
280
+ ]);
281
+ var OrderBookResponseSchema = ApiResponseSchema(OrderBookSchema);
282
+ var OrderBookArrayResponseSchema = ApiResponseSchema(z.array(OrderBookSchema));
283
+ var TradeArrayResponseSchema = ApiResponseSchema(z.array(TradeSchema));
284
+ var InstrumentResponseSchema = ApiResponseSchema(InstrumentSchema);
285
+ var InstrumentArrayResponseSchema = ApiResponseSchema(z.array(InstrumentSchema));
286
+ var FundingRateResponseSchema = ApiResponseSchema(FundingRateSchema);
287
+ var FundingRateArrayResponseSchema = ApiResponseSchema(z.array(FundingRateSchema));
288
+ var OpenInterestResponseSchema = ApiResponseSchema(OpenInterestSchema);
289
+ var OpenInterestArrayResponseSchema = ApiResponseSchema(z.array(OpenInterestSchema));
290
+
73
291
  // src/resources/orderbook.ts
74
292
  var OrderBookResource = class {
75
293
  constructor(http) {
@@ -85,7 +303,8 @@ var OrderBookResource = class {
85
303
  async get(coin, params) {
86
304
  const response = await this.http.get(
87
305
  `/v1/orderbook/${coin.toUpperCase()}`,
88
- params
306
+ params,
307
+ this.http.validationEnabled ? OrderBookResponseSchema : void 0
89
308
  );
90
309
  return response.data;
91
310
  }
@@ -99,7 +318,8 @@ var OrderBookResource = class {
99
318
  async history(coin, params) {
100
319
  const response = await this.http.get(
101
320
  `/v1/orderbook/${coin.toUpperCase()}/history`,
102
- params
321
+ params,
322
+ this.http.validationEnabled ? OrderBookArrayResponseSchema : void 0
103
323
  );
104
324
  return response.data;
105
325
  }
@@ -143,7 +363,8 @@ var TradesResource = class {
143
363
  async list(coin, params) {
144
364
  const response = await this.http.get(
145
365
  `/v1/trades/${coin.toUpperCase()}`,
146
- params
366
+ params,
367
+ this.http.validationEnabled ? TradeArrayResponseSchema : void 0
147
368
  );
148
369
  return {
149
370
  data: response.data,
@@ -160,7 +381,8 @@ var TradesResource = class {
160
381
  async recent(coin, limit) {
161
382
  const response = await this.http.get(
162
383
  `/v1/trades/${coin.toUpperCase()}/recent`,
163
- { limit }
384
+ { limit },
385
+ this.http.validationEnabled ? TradeArrayResponseSchema : void 0
164
386
  );
165
387
  return response.data;
166
388
  }
@@ -188,7 +410,8 @@ var TradesResource = class {
188
410
  async listWithOffset(coin, params) {
189
411
  const response = await this.http.get(
190
412
  `/v1/trades/${coin.toUpperCase()}`,
191
- params
413
+ params,
414
+ this.http.validationEnabled ? TradeArrayResponseSchema : void 0
192
415
  );
193
416
  return response.data;
194
417
  }
@@ -206,7 +429,9 @@ var InstrumentsResource = class {
206
429
  */
207
430
  async list() {
208
431
  const response = await this.http.get(
209
- "/v1/instruments"
432
+ "/v1/instruments",
433
+ void 0,
434
+ this.http.validationEnabled ? InstrumentArrayResponseSchema : void 0
210
435
  );
211
436
  return response.data;
212
437
  }
@@ -218,7 +443,9 @@ var InstrumentsResource = class {
218
443
  */
219
444
  async get(coin) {
220
445
  const response = await this.http.get(
221
- `/v1/instruments/${coin.toUpperCase()}`
446
+ `/v1/instruments/${coin.toUpperCase()}`,
447
+ void 0,
448
+ this.http.validationEnabled ? InstrumentResponseSchema : void 0
222
449
  );
223
450
  return response.data;
224
451
  }
@@ -239,7 +466,8 @@ var FundingResource = class {
239
466
  async history(coin, params) {
240
467
  const response = await this.http.get(
241
468
  `/v1/funding/${coin.toUpperCase()}`,
242
- params
469
+ params,
470
+ this.http.validationEnabled ? FundingRateArrayResponseSchema : void 0
243
471
  );
244
472
  return response.data;
245
473
  }
@@ -251,7 +479,9 @@ var FundingResource = class {
251
479
  */
252
480
  async current(coin) {
253
481
  const response = await this.http.get(
254
- `/v1/funding/${coin.toUpperCase()}/current`
482
+ `/v1/funding/${coin.toUpperCase()}/current`,
483
+ void 0,
484
+ this.http.validationEnabled ? FundingRateResponseSchema : void 0
255
485
  );
256
486
  return response.data;
257
487
  }
@@ -272,7 +502,8 @@ var OpenInterestResource = class {
272
502
  async history(coin, params) {
273
503
  const response = await this.http.get(
274
504
  `/v1/openinterest/${coin.toUpperCase()}`,
275
- params
505
+ params,
506
+ this.http.validationEnabled ? OpenInterestArrayResponseSchema : void 0
276
507
  );
277
508
  return response.data;
278
509
  }
@@ -284,7 +515,9 @@ var OpenInterestResource = class {
284
515
  */
285
516
  async current(coin) {
286
517
  const response = await this.http.get(
287
- `/v1/openinterest/${coin.toUpperCase()}/current`
518
+ `/v1/openinterest/${coin.toUpperCase()}/current`,
519
+ void 0,
520
+ this.http.validationEnabled ? OpenInterestResponseSchema : void 0
288
521
  );
289
522
  return response.data;
290
523
  }
@@ -327,7 +560,8 @@ var OxArchive = class {
327
560
  this.http = new HttpClient({
328
561
  baseUrl: options.baseUrl ?? DEFAULT_BASE_URL,
329
562
  apiKey: options.apiKey,
330
- timeout: options.timeout ?? DEFAULT_TIMEOUT
563
+ timeout: options.timeout ?? DEFAULT_TIMEOUT,
564
+ validate: options.validate ?? false
331
565
  });
332
566
  this.orderbook = new OrderBookResource(this.http);
333
567
  this.trades = new TradesResource(this.http);
@@ -342,6 +576,39 @@ var DEFAULT_WS_URL = "wss://api.0xarchive.io/ws";
342
576
  var DEFAULT_PING_INTERVAL = 3e4;
343
577
  var DEFAULT_RECONNECT_DELAY = 1e3;
344
578
  var DEFAULT_MAX_RECONNECT_ATTEMPTS = 10;
579
+ function transformTrade(coin, raw) {
580
+ if ("price" in raw && "size" in raw) {
581
+ return raw;
582
+ }
583
+ const px = raw.px;
584
+ const sz = raw.sz;
585
+ const side = raw.side;
586
+ const time = raw.time;
587
+ const hash = raw.hash;
588
+ const tid = raw.tid;
589
+ const users = raw.users;
590
+ const maker_address = users && users.length > 0 ? users[0] : void 0;
591
+ const taker_address = users && users.length > 1 ? users[1] : void 0;
592
+ const user_address = raw.userAddress ?? raw.user_address;
593
+ return {
594
+ coin,
595
+ side: side === "A" || side === "B" ? side : "B",
596
+ price: px ?? "0",
597
+ size: sz ?? "0",
598
+ timestamp: time ? new Date(time).toISOString() : (/* @__PURE__ */ new Date()).toISOString(),
599
+ tx_hash: hash,
600
+ trade_id: tid,
601
+ maker_address,
602
+ taker_address,
603
+ user_address
604
+ };
605
+ }
606
+ function transformTrades(coin, rawTrades) {
607
+ if (!Array.isArray(rawTrades)) {
608
+ return [transformTrade(coin, rawTrades)];
609
+ }
610
+ return rawTrades.map((raw) => transformTrade(coin, raw));
611
+ }
345
612
  function transformOrderbook(coin, raw) {
346
613
  if ("bids" in raw && "asks" in raw) {
347
614
  return raw;
@@ -797,8 +1064,9 @@ var OxArchiveWs = class {
797
1064
  handler(message.coin, orderbook);
798
1065
  }
799
1066
  } else if (message.channel === "trades") {
1067
+ const trades = transformTrades(message.coin, message.data);
800
1068
  for (const handler of this.tradesHandlers) {
801
- handler(message.coin, message.data);
1069
+ handler(message.coin, trades);
802
1070
  }
803
1071
  }
804
1072
  break;
@@ -807,9 +1075,50 @@ var OxArchiveWs = class {
807
1075
  }
808
1076
  };
809
1077
  export {
1078
+ ApiMetaSchema,
1079
+ ApiResponseSchema,
1080
+ DataSourceSchema,
1081
+ FundingRateArrayResponseSchema,
1082
+ FundingRateResponseSchema,
1083
+ FundingRateSchema,
1084
+ InstrumentArrayResponseSchema,
1085
+ InstrumentResponseSchema,
1086
+ InstrumentSchema,
1087
+ InstrumentTypeSchema,
1088
+ OpenInterestArrayResponseSchema,
1089
+ OpenInterestResponseSchema,
1090
+ OpenInterestSchema,
1091
+ OrderBookArrayResponseSchema,
1092
+ OrderBookResponseSchema,
1093
+ OrderBookSchema,
810
1094
  OxArchive,
811
1095
  OxArchiveError,
812
1096
  OxArchiveWs,
1097
+ PriceLevelSchema,
1098
+ TimestampedRecordSchema,
1099
+ TradeArrayResponseSchema,
1100
+ TradeDirectionSchema,
1101
+ TradeSchema,
1102
+ TradeSideSchema,
1103
+ WsChannelSchema,
1104
+ WsConnectionStateSchema,
1105
+ WsDataSchema,
1106
+ WsErrorSchema,
1107
+ WsHistoricalBatchSchema,
1108
+ WsHistoricalDataSchema,
1109
+ WsPongSchema,
1110
+ WsReplayCompletedSchema,
1111
+ WsReplayPausedSchema,
1112
+ WsReplayResumedSchema,
1113
+ WsReplayStartedSchema,
1114
+ WsReplayStoppedSchema,
1115
+ WsServerMessageSchema,
1116
+ WsStreamCompletedSchema,
1117
+ WsStreamProgressSchema,
1118
+ WsStreamStartedSchema,
1119
+ WsStreamStoppedSchema,
1120
+ WsSubscribedSchema,
1121
+ WsUnsubscribedSchema,
813
1122
  OxArchive as default
814
1123
  };
815
1124
  //# sourceMappingURL=index.mjs.map