@liberfi.io/react-predict 0.3.69 → 0.3.71

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/server.mjs CHANGED
@@ -197,6 +197,21 @@ function resolvePredictSearchParams(params = {}) {
197
197
  async function fetchPredictSearch(client, params) {
198
198
  return client.search(resolvePredictSearchParams(params));
199
199
  }
200
+
201
+ // src/client/types.ts
202
+ var MARKET_STRUCTURE_MEDIA_TYPE_V1 = "application/vnd.liberfi.market-structure+json;v=1";
203
+
204
+ // src/client/client.ts
205
+ var MarketDataHttpError = class extends Error {
206
+ constructor(message, status, code, retryAfter, body) {
207
+ super(message);
208
+ this.status = status;
209
+ this.code = code;
210
+ this.retryAfter = retryAfter;
211
+ this.body = body;
212
+ }
213
+ name = "MarketDataHttpError";
214
+ };
200
215
  function buildQuery(params) {
201
216
  const qs = new URLSearchParams();
202
217
  for (const [key, value] of Object.entries(params)) {
@@ -223,6 +238,26 @@ var PredictClient = class {
223
238
  }
224
239
  };
225
240
  }
241
+ async marketDataRequest(path, options) {
242
+ const response = await fetch(
243
+ `${this.endpoint}${path}`,
244
+ this.requestOptions(options)
245
+ );
246
+ if (response.ok) {
247
+ return await response.json();
248
+ }
249
+ const body = await parseMarketDataResponseBody(response);
250
+ const record = isRecord(body) ? body : void 0;
251
+ const code = typeof record?.error === "string" ? record.error : typeof record?.code === "string" ? record.code : void 0;
252
+ const message = typeof record?.message === "string" ? record.message : code ?? response.statusText ?? `HTTP ${response.status}`;
253
+ throw new MarketDataHttpError(
254
+ message,
255
+ response.status,
256
+ code,
257
+ response.headers.get("Retry-After") ?? void 0,
258
+ body
259
+ );
260
+ }
226
261
  // -------------------------------------------------------------------------
227
262
  // Events
228
263
  // -------------------------------------------------------------------------
@@ -357,6 +392,85 @@ var PredictClient = class {
357
392
  // -------------------------------------------------------------------------
358
393
  // Markets
359
394
  // -------------------------------------------------------------------------
395
+ /** Register or refresh the complete provider-neutral market-data demand set. */
396
+ async watchMarketData(request) {
397
+ return await this.marketDataRequest(
398
+ "/api/v1/market-data/watch",
399
+ {
400
+ method: "POST",
401
+ headers: { "Content-Type": "application/json" },
402
+ body: JSON.stringify(request)
403
+ }
404
+ );
405
+ }
406
+ /** Read cache-only quote snapshots for at most 500 provider-neutral keys. */
407
+ async getMarketDataQuotes(markets) {
408
+ if (markets.length > 500) {
409
+ throw new RangeError(
410
+ "market data quote request accepts at most 500 markets"
411
+ );
412
+ }
413
+ return await this.marketDataRequest(
414
+ "/api/v1/markets/quotes",
415
+ {
416
+ method: "POST",
417
+ cache: "no-store",
418
+ headers: { "Content-Type": "application/json" },
419
+ body: JSON.stringify({ markets })
420
+ }
421
+ );
422
+ }
423
+ /** Read all cached Top20 outcome books for one provider-neutral market. */
424
+ async getMarketDataOrderbooks(slug, source) {
425
+ const path = `/api/v1/markets/${encodeURIComponent(slug)}/orderbooks` + buildQuery({ source });
426
+ return await this.marketDataRequest(path, {
427
+ method: "GET",
428
+ cache: "no-store"
429
+ });
430
+ }
431
+ /**
432
+ * Revalidate a page's allowlist-only structure representation.
433
+ *
434
+ * The path must remain inside the prediction API so callers cannot turn a
435
+ * configured authenticated client into a cross-origin request primitive.
436
+ */
437
+ async getMarketStructure(path, ifNoneMatch) {
438
+ if (!path.startsWith("/api/v1/")) {
439
+ throw new TypeError("market structure path must start with /api/v1/");
440
+ }
441
+ const response = await fetch(
442
+ `${this.endpoint}${path}`,
443
+ this.requestOptions({
444
+ method: "GET",
445
+ cache: "no-store",
446
+ headers: {
447
+ Accept: MARKET_STRUCTURE_MEDIA_TYPE_V1,
448
+ ...ifNoneMatch ? { "If-None-Match": ifNoneMatch } : {}
449
+ }
450
+ })
451
+ );
452
+ const etag = response.headers.get("ETag") ?? "";
453
+ if (response.status === 304) {
454
+ return { status: 304, etag };
455
+ }
456
+ if (response.ok) {
457
+ return {
458
+ status: 200,
459
+ etag,
460
+ body: await response.json()
461
+ };
462
+ }
463
+ const body = await parseMarketDataResponseBody(response);
464
+ const record = isRecord(body) ? body : void 0;
465
+ const code = typeof record?.error === "string" ? record.error : void 0;
466
+ throw new MarketDataHttpError(
467
+ typeof record?.message === "string" ? record.message : code ?? response.statusText,
468
+ response.status,
469
+ code,
470
+ response.headers.get("Retry-After") ?? void 0,
471
+ body
472
+ );
473
+ }
360
474
  /**
361
475
  * Fetch a single prediction market by its slug.
362
476
  *
@@ -826,6 +940,18 @@ var PredictClient = class {
826
940
  function createPredictClient(endpoint, options) {
827
941
  return new PredictClient(endpoint, options);
828
942
  }
943
+ async function parseMarketDataResponseBody(response) {
944
+ const text = await response.text().catch(() => "");
945
+ if (!text) return void 0;
946
+ try {
947
+ return JSON.parse(text);
948
+ } catch {
949
+ return void 0;
950
+ }
951
+ }
952
+ function isRecord(value) {
953
+ return typeof value === "object" && value !== null && !Array.isArray(value);
954
+ }
829
955
 
830
956
  // src/client/ws.ts
831
957
  var DEFAULT_RECONNECT_BASE = 1e3;