@liberfi.io/react-predict 0.3.66 → 0.3.68

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
@@ -84,6 +84,67 @@ var PredictClient = class {
84
84
  const url = `${this.endpoint}/api/v1/events/${encodeURIComponent(slug)}/similar${query}`;
85
85
  return await utils.httpGet(url);
86
86
  }
87
+ // -------------------------------------------------------------------------
88
+ // Sports / esports
89
+ // -------------------------------------------------------------------------
90
+ /** Maps to `GET /api/v1/sports/taxonomy`. */
91
+ async getSportsTaxonomy(params) {
92
+ const query = buildQuery(params ?? {});
93
+ const url = `${this.endpoint}/api/v1/sports/taxonomy${query}`;
94
+ return await utils.httpGet(url, this.requestOptions());
95
+ }
96
+ /** Maps to `GET /api/v1/sports/matches`. */
97
+ async getSportsMatches(params) {
98
+ const query = buildQuery(params ?? {});
99
+ const url = `${this.endpoint}/api/v1/sports/matches${query}`;
100
+ return await utils.httpGet(url, this.requestOptions());
101
+ }
102
+ /** Maps to `GET /api/v1/sports/props`. */
103
+ async getSportsProps(params) {
104
+ const query = buildQuery(params ?? {});
105
+ const url = `${this.endpoint}/api/v1/sports/props${query}`;
106
+ return await utils.httpGet(url, this.requestOptions());
107
+ }
108
+ /** Maps to `GET /api/v1/esports/taxonomy`. */
109
+ async getEsportsTaxonomy(params) {
110
+ const query = buildQuery(params ?? {});
111
+ const url = `${this.endpoint}/api/v1/esports/taxonomy${query}`;
112
+ return await utils.httpGet(url, this.requestOptions());
113
+ }
114
+ /** Maps to `GET /api/v1/esports/matches`. */
115
+ async getEsportsMatches(params) {
116
+ const query = buildQuery(params ?? {});
117
+ const url = `${this.endpoint}/api/v1/esports/matches${query}`;
118
+ return await utils.httpGet(url, this.requestOptions());
119
+ }
120
+ /** Maps to `GET /api/v1/esports/props`. */
121
+ async getEsportsProps(params) {
122
+ const query = buildQuery(params ?? {});
123
+ const url = `${this.endpoint}/api/v1/esports/props${query}`;
124
+ return await utils.httpGet(url, this.requestOptions());
125
+ }
126
+ /** Maps to `GET /api/v1/sports/routing/:slug`. */
127
+ async getSportsRouting(slug, params) {
128
+ const query = buildQuery(params ?? {});
129
+ const url = `${this.endpoint}/api/v1/sports/routing/${encodeURIComponent(slug)}${query}`;
130
+ return await utils.httpGet(url, this.requestOptions());
131
+ }
132
+ /** Maps to `GET /api/v1/sports/matches/:match_group_slug`. */
133
+ async getSportsMatchDetail(section, matchGroupSlug, params) {
134
+ const query = buildQuery(params ?? {});
135
+ const url = `${this.endpoint}/api/v1/${encodeURIComponent(section)}/matches/${encodeURIComponent(matchGroupSlug)}${query}`;
136
+ return await utils.httpGet(url, this.requestOptions());
137
+ }
138
+ /** Convenience wrapper for `GET /api/v1/esports/matches/:match_group_slug`. */
139
+ async getEsportsMatchDetail(matchGroupSlug, params) {
140
+ return this.getSportsMatchDetail("esports", matchGroupSlug, params);
141
+ }
142
+ /** Maps to `GET /api/v1/search`. */
143
+ async search(params) {
144
+ const query = buildQuery(params ?? {});
145
+ const url = `${this.endpoint}/api/v1/search${query}`;
146
+ return await utils.httpGet(url, this.requestOptions());
147
+ }
87
148
  /**
88
149
  * List comments for a prediction event.
89
150
  *
@@ -145,8 +206,9 @@ var PredictClient = class {
145
206
  return await utils.httpGet(url);
146
207
  }
147
208
  /** Maps to `GET /api/v1/markets/:slug/price-history?source=...&range=...`. */
148
- async getPriceHistory(slug, source, range) {
149
- const query = buildQuery({ source, range });
209
+ async getPriceHistory(slug, sourceOrParams, range) {
210
+ const params = typeof sourceOrParams === "string" ? { source: sourceOrParams, range } : sourceOrParams;
211
+ const query = buildQuery(params);
150
212
  const url = `${this.endpoint}/api/v1/markets/${encodeURIComponent(slug)}/price-history${query}`;
151
213
  return await utils.httpGet(url);
152
214
  }
@@ -1221,6 +1283,355 @@ function useEvent(params, queryOptions = {}) {
1221
1283
  ...queryOptions
1222
1284
  });
1223
1285
  }
1286
+
1287
+ // src/hooks/predict/search.params.ts
1288
+ function predictSearchQueryKey(params) {
1289
+ return ["predict", "search-documents", params];
1290
+ }
1291
+ function resolvePredictSearchParams(params = {}) {
1292
+ const q = params.q ?? "";
1293
+ return {
1294
+ ...params,
1295
+ q,
1296
+ sort_by: params.sort_by ?? (q ? "relevance" : "volume"),
1297
+ sort_asc: params.sort_asc ?? (q ? void 0 : false)
1298
+ };
1299
+ }
1300
+ async function fetchPredictSearch(client, params) {
1301
+ return client.search(resolvePredictSearchParams(params));
1302
+ }
1303
+
1304
+ // src/hooks/predict/usePredictSearch.ts
1305
+ function usePredictSearch(params = {}, queryOptions) {
1306
+ const client = usePredictClient();
1307
+ const resolved = resolvePredictSearchParams(params);
1308
+ return reactQuery.useQuery({
1309
+ queryKey: predictSearchQueryKey(resolved),
1310
+ queryFn: () => fetchPredictSearch(client, resolved),
1311
+ enabled: queryOptions?.enabled ?? true
1312
+ });
1313
+ }
1314
+ function useInfinitePredictSearch(params = {}, queryOptions) {
1315
+ const client = usePredictClient();
1316
+ const resolved = resolvePredictSearchParams(params);
1317
+ return reactQuery.useInfiniteQuery({
1318
+ queryKey: predictSearchQueryKey(resolved),
1319
+ queryFn: ({ pageParam }) => fetchPredictSearch(client, {
1320
+ ...resolved,
1321
+ ...pageParam !== void 0 ? { cursor: pageParam } : {}
1322
+ }),
1323
+ initialPageParam: void 0,
1324
+ getNextPageParam: (lastPage) => lastPage.has_more && lastPage.next_cursor ? lastPage.next_cursor : void 0,
1325
+ enabled: queryOptions?.enabled ?? true
1326
+ });
1327
+ }
1328
+
1329
+ // src/hooks/predict/sports.params.ts
1330
+ function sportsTaxonomyQueryKey(params) {
1331
+ return ["predict", "sports", "taxonomy", params];
1332
+ }
1333
+ function sportsMatchesQueryKey(params) {
1334
+ return ["predict", "sports", "matches", params];
1335
+ }
1336
+ function sportsPropsQueryKey(params) {
1337
+ return ["predict", "sports", "props", params];
1338
+ }
1339
+ function resolveSportsTaxonomyParams(params = {}) {
1340
+ return { ...params, section: "sports" };
1341
+ }
1342
+ function resolveSportsMatchesParams(params = {}) {
1343
+ return params;
1344
+ }
1345
+ function resolveSportsPropsParams(params = {}) {
1346
+ return params;
1347
+ }
1348
+ async function fetchSportsTaxonomy(client, params) {
1349
+ return client.getSportsTaxonomy(resolveSportsTaxonomyParams(params));
1350
+ }
1351
+ async function fetchSportsMatches(client, params) {
1352
+ return client.getSportsMatches(resolveSportsMatchesParams(params));
1353
+ }
1354
+ async function fetchSportsProps(client, params) {
1355
+ return client.getSportsProps(resolveSportsPropsParams(params));
1356
+ }
1357
+
1358
+ // src/hooks/predict/useSportsTaxonomy.ts
1359
+ function useSportsTaxonomy(params = {}, queryOptions = {}) {
1360
+ const client = usePredictClient();
1361
+ const resolved = resolveSportsTaxonomyParams(params);
1362
+ return reactQuery.useQuery({
1363
+ queryKey: sportsTaxonomyQueryKey(resolved),
1364
+ queryFn: () => fetchSportsTaxonomy(client, resolved),
1365
+ ...queryOptions
1366
+ });
1367
+ }
1368
+ function useSportsMatches(params = {}, queryOptions) {
1369
+ const client = usePredictClient();
1370
+ const resolved = resolveSportsMatchesParams(params);
1371
+ return reactQuery.useInfiniteQuery({
1372
+ queryKey: sportsMatchesQueryKey(resolved),
1373
+ queryFn: ({ pageParam }) => fetchSportsMatches(client, {
1374
+ ...resolved,
1375
+ ...pageParam !== void 0 ? { cursor: pageParam } : {}
1376
+ }),
1377
+ initialPageParam: void 0,
1378
+ getNextPageParam: (lastPage) => lastPage.has_more && lastPage.next_cursor ? lastPage.next_cursor : void 0,
1379
+ enabled: queryOptions?.enabled ?? true
1380
+ });
1381
+ }
1382
+ function useSportsProps(params = {}, queryOptions) {
1383
+ const client = usePredictClient();
1384
+ const resolved = resolveSportsPropsParams(params);
1385
+ return reactQuery.useInfiniteQuery({
1386
+ queryKey: sportsPropsQueryKey(resolved),
1387
+ queryFn: ({ pageParam }) => fetchSportsProps(client, {
1388
+ ...resolved,
1389
+ ...pageParam !== void 0 ? { cursor: pageParam } : {}
1390
+ }),
1391
+ initialPageParam: void 0,
1392
+ getNextPageParam: (lastPage) => lastPage.has_more && lastPage.next_cursor ? lastPage.next_cursor : void 0,
1393
+ enabled: queryOptions?.enabled ?? true
1394
+ });
1395
+ }
1396
+
1397
+ // src/hooks/predict/esports.params.ts
1398
+ function esportsTaxonomyQueryKey(params) {
1399
+ return ["predict", "esports", "taxonomy", params];
1400
+ }
1401
+ function esportsMatchesQueryKey(params) {
1402
+ return ["predict", "esports", "matches", params];
1403
+ }
1404
+ function esportsPropsQueryKey(params) {
1405
+ return ["predict", "esports", "props", params];
1406
+ }
1407
+ function resolveEsportsTaxonomyParams(params = {}) {
1408
+ return params;
1409
+ }
1410
+ function resolveEsportsMatchesParams(params = {}) {
1411
+ return params;
1412
+ }
1413
+ function resolveEsportsPropsParams(params = {}) {
1414
+ return params;
1415
+ }
1416
+ async function fetchEsportsTaxonomy(client, params) {
1417
+ return client.getEsportsTaxonomy(resolveEsportsTaxonomyParams(params));
1418
+ }
1419
+ async function fetchEsportsMatches(client, params) {
1420
+ return client.getEsportsMatches(resolveEsportsMatchesParams(params));
1421
+ }
1422
+ async function fetchEsportsProps(client, params) {
1423
+ return client.getEsportsProps(resolveEsportsPropsParams(params));
1424
+ }
1425
+
1426
+ // src/hooks/predict/useEsportsTaxonomy.ts
1427
+ function useEsportsTaxonomy(params = {}, queryOptions = {}) {
1428
+ const client = usePredictClient();
1429
+ const resolved = resolveEsportsTaxonomyParams(params);
1430
+ return reactQuery.useQuery({
1431
+ queryKey: esportsTaxonomyQueryKey(resolved),
1432
+ queryFn: () => fetchEsportsTaxonomy(client, resolved),
1433
+ ...queryOptions
1434
+ });
1435
+ }
1436
+ function useEsportsMatches(params = {}, queryOptions) {
1437
+ const client = usePredictClient();
1438
+ const resolved = resolveEsportsMatchesParams(params);
1439
+ return reactQuery.useInfiniteQuery({
1440
+ queryKey: esportsMatchesQueryKey(resolved),
1441
+ queryFn: ({ pageParam }) => fetchEsportsMatches(client, {
1442
+ ...resolved,
1443
+ ...pageParam !== void 0 ? { cursor: pageParam } : {}
1444
+ }),
1445
+ initialPageParam: void 0,
1446
+ getNextPageParam: (lastPage) => lastPage.has_more && lastPage.next_cursor ? lastPage.next_cursor : void 0,
1447
+ enabled: queryOptions?.enabled ?? true
1448
+ });
1449
+ }
1450
+ function useEsportsProps(params = {}, queryOptions) {
1451
+ const client = usePredictClient();
1452
+ const resolved = resolveEsportsPropsParams(params);
1453
+ return reactQuery.useInfiniteQuery({
1454
+ queryKey: esportsPropsQueryKey(resolved),
1455
+ queryFn: ({ pageParam }) => fetchEsportsProps(client, {
1456
+ ...resolved,
1457
+ ...pageParam !== void 0 ? { cursor: pageParam } : {}
1458
+ }),
1459
+ initialPageParam: void 0,
1460
+ getNextPageParam: (lastPage) => lastPage.has_more && lastPage.next_cursor ? lastPage.next_cursor : void 0,
1461
+ enabled: queryOptions?.enabled ?? true
1462
+ });
1463
+ }
1464
+
1465
+ // src/hooks/predict/sports-routing.params.ts
1466
+ function sportsRoutingQueryKey(slug, params) {
1467
+ return ["predict", "sports", "routing", slug, params];
1468
+ }
1469
+ function resolveSportsRoutingParams(params = {}) {
1470
+ return params;
1471
+ }
1472
+ async function fetchSportsRouting(client, slug, params) {
1473
+ return client.getSportsRouting(slug, resolveSportsRoutingParams(params));
1474
+ }
1475
+
1476
+ // src/hooks/predict/useSportsRouting.ts
1477
+ function useSportsRouting(slug, params = {}, queryOptions = {}) {
1478
+ const client = usePredictClient();
1479
+ const resolved = resolveSportsRoutingParams(params);
1480
+ return reactQuery.useQuery({
1481
+ queryKey: sportsRoutingQueryKey(slug, resolved),
1482
+ queryFn: () => fetchSportsRouting(client, slug, resolved),
1483
+ enabled: Boolean(slug),
1484
+ ...queryOptions
1485
+ });
1486
+ }
1487
+
1488
+ // src/hooks/predict/sports-match-detail.params.ts
1489
+ function sportsMatchDetailQueryKey(section, matchGroupSlug, params) {
1490
+ return ["predict", section, "match-detail", matchGroupSlug, params];
1491
+ }
1492
+ function resolveSportsMatchDetailParams(params = {}) {
1493
+ return params;
1494
+ }
1495
+ async function fetchSportsMatchDetail(client, section, matchGroupSlug, params) {
1496
+ return client.getSportsMatchDetail(
1497
+ section,
1498
+ matchGroupSlug,
1499
+ resolveSportsMatchDetailParams(params)
1500
+ );
1501
+ }
1502
+
1503
+ // src/hooks/predict/useSportsMatchDetail.ts
1504
+ function useSportsMatchDetail(section, matchGroupSlug, params = {}, queryOptions = {}) {
1505
+ const client = usePredictClient();
1506
+ const resolved = resolveSportsMatchDetailParams(params);
1507
+ return reactQuery.useQuery({
1508
+ queryKey: sportsMatchDetailQueryKey(section, matchGroupSlug, resolved),
1509
+ queryFn: () => fetchSportsMatchDetail(client, section, matchGroupSlug, resolved),
1510
+ enabled: Boolean(section && matchGroupSlug),
1511
+ ...queryOptions
1512
+ });
1513
+ }
1514
+ function orderbookQueryKey(slug, source, outcome = "yes") {
1515
+ return ["predict", "orderbook", slug, source, outcome];
1516
+ }
1517
+ function useOrderbook(params, queryOptions = {}) {
1518
+ const client = usePredictClient();
1519
+ const outcome = params.outcome ?? "yes";
1520
+ return reactQuery.useQuery({
1521
+ queryKey: orderbookQueryKey(params.slug, params.source, outcome),
1522
+ queryFn: () => client.getOrderbook(params.slug, params.source, outcome),
1523
+ enabled: Boolean(params.slug),
1524
+ refetchInterval: 3e4,
1525
+ ...queryOptions
1526
+ });
1527
+ }
1528
+ function useOrderbookSubscription({
1529
+ wsClient,
1530
+ slug,
1531
+ enabled = true,
1532
+ outcome,
1533
+ onUpdate
1534
+ }) {
1535
+ const [orderbook, setOrderbook] = react.useState(null);
1536
+ const [isSubscribed, setIsSubscribed] = react.useState(false);
1537
+ const onUpdateRef = react.useRef(onUpdate);
1538
+ onUpdateRef.current = onUpdate;
1539
+ const handleUpdate = react.useCallback(
1540
+ (msg) => {
1541
+ if (msg.data.market_slug === slug) {
1542
+ if (!outcome || msg.data.outcome === outcome) {
1543
+ setOrderbook(msg.data);
1544
+ }
1545
+ onUpdateRef.current?.(msg);
1546
+ }
1547
+ },
1548
+ [slug, outcome]
1549
+ );
1550
+ react.useEffect(() => {
1551
+ if (!wsClient || !enabled || !slug) {
1552
+ setIsSubscribed(false);
1553
+ return;
1554
+ }
1555
+ setOrderbook(null);
1556
+ const unsub = wsClient.subscribeOrderbook([slug], handleUpdate);
1557
+ setIsSubscribed(true);
1558
+ return () => {
1559
+ unsub();
1560
+ setIsSubscribed(false);
1561
+ };
1562
+ }, [wsClient, enabled, slug, handleUpdate]);
1563
+ return { orderbook, isSubscribed };
1564
+ }
1565
+ function usePredictWsClient() {
1566
+ const context = react.useContext(PredictContext);
1567
+ if (!context) {
1568
+ throw new Error("usePredictWsClient must be used within a PredictProvider");
1569
+ }
1570
+ const { wsClient } = context;
1571
+ const [wsStatus, setWsStatus] = react.useState(
1572
+ wsClient?.getStatus() ?? "disconnected"
1573
+ );
1574
+ react.useEffect(() => {
1575
+ if (!wsClient) {
1576
+ setWsStatus("disconnected");
1577
+ return;
1578
+ }
1579
+ setWsStatus(wsClient.getStatus());
1580
+ return wsClient.onStatusChange(setWsStatus);
1581
+ }, [wsClient]);
1582
+ return {
1583
+ wsClient,
1584
+ wsStatus,
1585
+ isWsConnected: wsStatus === "connected"
1586
+ };
1587
+ }
1588
+
1589
+ // src/hooks/predict/useRealtimeOrderbook.ts
1590
+ var REST_POLL_INTERVAL = 5e3;
1591
+ function useRealtimeOrderbook(params, queryOptions = {}) {
1592
+ const { wsClient } = usePredictWsClient();
1593
+ const queryClient = reactQuery.useQueryClient();
1594
+ const outcome = params.outcome ?? "yes";
1595
+ const handleUpdate = react.useCallback(
1596
+ (msg) => {
1597
+ if (msg.data.market_slug !== params.slug) return;
1598
+ if (msg.data.outcome !== "yes" && msg.data.outcome !== "no") return;
1599
+ const ob = {
1600
+ market_id: msg.data.market_slug,
1601
+ outcome: msg.data.outcome,
1602
+ bids: msg.data.bids,
1603
+ asks: msg.data.asks,
1604
+ spread: msg.data.spread
1605
+ };
1606
+ queryClient.setQueryData(
1607
+ orderbookQueryKey(params.slug, params.source, msg.data.outcome),
1608
+ ob
1609
+ );
1610
+ },
1611
+ [params.slug, params.source, queryClient]
1612
+ );
1613
+ const subParams = {
1614
+ wsClient,
1615
+ slug: params.slug,
1616
+ enabled: Boolean(params.slug),
1617
+ outcome,
1618
+ onUpdate: handleUpdate
1619
+ };
1620
+ const { isSubscribed } = useOrderbookSubscription(subParams);
1621
+ return useOrderbook(params, {
1622
+ refetchInterval: isSubscribed ? false : REST_POLL_INTERVAL,
1623
+ ...queryOptions
1624
+ });
1625
+ }
1626
+
1627
+ // src/hooks/predict/useSportsOrderbook.ts
1628
+ function useSportsOrderbook(key) {
1629
+ return useRealtimeOrderbook({
1630
+ slug: key.market_slug,
1631
+ source: key.source,
1632
+ outcome: key.outcome
1633
+ });
1634
+ }
1224
1635
  function useInfiniteEvents(params, queryOptions = {}) {
1225
1636
  const client = usePredictClient();
1226
1637
  return reactQuery.useInfiniteQuery({
@@ -1319,8 +1730,8 @@ function useMarket(params, queryOptions = {}) {
1319
1730
  ...queryOptions
1320
1731
  });
1321
1732
  }
1322
- function priceHistoryQueryKey(slug, source, range) {
1323
- return ["predict", "price-history", slug, source, range];
1733
+ function priceHistoryQueryKey(slug, source, rangeOrParams) {
1734
+ return ["predict", "price-history", slug, source, rangeOrParams];
1324
1735
  }
1325
1736
  function usePriceHistory(params, queryOptions = {}) {
1326
1737
  const client = usePredictClient();
@@ -1335,73 +1746,147 @@ function usePriceHistory(params, queryOptions = {}) {
1335
1746
 
1336
1747
  // src/hooks/predict/useMarketHistory.ts
1337
1748
  var ChartRange = {
1749
+ ONE_HOUR: "1h",
1750
+ SIX_HOURS: "6h",
1338
1751
  ONE_DAY: "1d",
1339
- ONE_WEEK: "1w",
1340
1752
  ONE_MONTH: "1m",
1341
1753
  ALL: "all"
1342
1754
  };
1343
1755
  var RANGE_MAP = {
1756
+ [ChartRange.ONE_HOUR]: "1h",
1757
+ [ChartRange.SIX_HOURS]: "6h",
1344
1758
  [ChartRange.ONE_DAY]: "1d",
1345
- [ChartRange.ONE_WEEK]: "1w",
1346
1759
  [ChartRange.ONE_MONTH]: "1m",
1347
1760
  [ChartRange.ALL]: "all"
1348
1761
  };
1349
- function useMarketHistory(markets, range = ChartRange.ALL) {
1762
+ var RANGE_DURATION_SECONDS = {
1763
+ [ChartRange.ONE_HOUR]: 60 * 60,
1764
+ [ChartRange.SIX_HOURS]: 6 * 60 * 60,
1765
+ [ChartRange.ONE_DAY]: 24 * 60 * 60,
1766
+ [ChartRange.ONE_MONTH]: 30 * 24 * 60 * 60,
1767
+ [ChartRange.ALL]: null
1768
+ };
1769
+ var RANGE_FIDELITY_MINUTES = {
1770
+ [ChartRange.ONE_HOUR]: 1,
1771
+ [ChartRange.SIX_HOURS]: 1,
1772
+ [ChartRange.ONE_DAY]: 5,
1773
+ [ChartRange.ONE_MONTH]: 15,
1774
+ [ChartRange.ALL]: 15
1775
+ };
1776
+ var LONG_RANGE_FIDELITY_MINUTES = {
1777
+ SHORT: 15,
1778
+ MONTH: 4 * 60,
1779
+ LONG: 24 * 60
1780
+ };
1781
+ var LONG_RANGE_SPAN_SECONDS = {
1782
+ WEEK: 7 * 24 * 60 * 60,
1783
+ MONTH: 31 * 24 * 60 * 60
1784
+ };
1785
+ function unixSecondsFromIso(value) {
1786
+ if (!value) return void 0;
1787
+ const ms = Date.parse(value);
1788
+ return Number.isFinite(ms) ? Math.floor(ms / 1e3) : void 0;
1789
+ }
1790
+ function firstFinitePrice(market) {
1791
+ const yesOutcome = market.outcomes?.find((o) => o.label.toLowerCase() === "yes") ?? market.outcomes?.[0];
1792
+ const price = yesOutcome?.best_ask ?? yesOutcome?.best_bid ?? yesOutcome?.price;
1793
+ return price != null && Number.isFinite(price) ? price : 0.5;
1794
+ }
1795
+ function fidelityMinutesForRange(range, startTs, endTs) {
1796
+ if (range !== ChartRange.ONE_MONTH && range !== ChartRange.ALL) {
1797
+ return RANGE_FIDELITY_MINUTES[range];
1798
+ }
1799
+ const spanSeconds = startTs != null ? Math.max(0, endTs - startTs) : 0;
1800
+ if (spanSeconds <= LONG_RANGE_SPAN_SECONDS.WEEK) {
1801
+ return LONG_RANGE_FIDELITY_MINUTES.SHORT;
1802
+ }
1803
+ if (spanSeconds <= LONG_RANGE_SPAN_SECONDS.MONTH) {
1804
+ return LONG_RANGE_FIDELITY_MINUTES.MONTH;
1805
+ }
1806
+ return LONG_RANGE_FIDELITY_MINUTES.LONG;
1807
+ }
1808
+ function buildRangeParams(range, market, anchoredEndTs) {
1809
+ const endTs = anchoredEndTs;
1810
+ const duration = RANGE_DURATION_SECONDS[range];
1811
+ const createdAt = unixSecondsFromIso(market.created_at);
1812
+ const rangeStartTs = duration == null ? void 0 : Math.max(0, endTs - duration);
1813
+ const startTs = createdAt != null && rangeStartTs != null ? Math.max(createdAt, rangeStartTs) : createdAt ?? rangeStartTs;
1814
+ return {
1815
+ range: RANGE_MAP[range],
1816
+ startTs,
1817
+ endTs,
1818
+ fidelity: fidelityMinutesForRange(range, startTs, endTs)
1819
+ };
1820
+ }
1821
+ function normalizeHistoryPoints(points, params, fallbackPrice) {
1822
+ const startMs = params.startTs != null ? params.startTs * 1e3 : void 0;
1823
+ const endMs = params.endTs != null ? params.endTs * 1e3 : void 0;
1824
+ const sorted = points.filter((pt) => Number.isFinite(pt.t) && Number.isFinite(pt.p)).map((pt) => ({ timestamp: pt.t * 1e3, price: pt.p })).filter((pt) => {
1825
+ if (startMs != null && pt.timestamp < startMs) return false;
1826
+ if (endMs != null && pt.timestamp > endMs) return false;
1827
+ return true;
1828
+ }).sort((a, b) => a.timestamp - b.timestamp);
1829
+ if (sorted.length === 0) {
1830
+ const now = endMs ?? Date.now();
1831
+ const start = startMs ?? now - 7 * 864e5;
1832
+ return [
1833
+ { timestamp: start, price: fallbackPrice },
1834
+ { timestamp: now, price: fallbackPrice }
1835
+ ];
1836
+ }
1837
+ const result = [...sorted];
1838
+ if (endMs != null && result[result.length - 1].timestamp < endMs) {
1839
+ result.push({
1840
+ timestamp: endMs,
1841
+ price: result[result.length - 1].price
1842
+ });
1843
+ }
1844
+ return result;
1845
+ }
1846
+ function useMarketHistory(markets, range = ChartRange.ALL, options = {}) {
1350
1847
  const client = usePredictClient();
1351
- const apiRange = RANGE_MAP[range];
1848
+ const rangeAnchorRef = react.useRef(null);
1849
+ const requestedEndTs = options.endTs;
1850
+ if (rangeAnchorRef.current?.range !== range || requestedEndTs != null && rangeAnchorRef.current?.endTs !== requestedEndTs) {
1851
+ rangeAnchorRef.current = {
1852
+ range,
1853
+ endTs: requestedEndTs ?? Math.floor(Date.now() / 1e3)
1854
+ };
1855
+ }
1856
+ const anchoredEndTs = rangeAnchorRef.current.endTs;
1857
+ const marketParams = react.useMemo(
1858
+ () => markets.map((market) => ({
1859
+ market,
1860
+ params: buildRangeParams(range, market, anchoredEndTs)
1861
+ })),
1862
+ [markets, range, anchoredEndTs]
1863
+ );
1352
1864
  const queries = reactQuery.useQueries({
1353
- queries: markets.map((market) => ({
1354
- queryKey: priceHistoryQueryKey(market.slug, market.source, apiRange),
1355
- queryFn: () => client.getPriceHistory(market.slug, market.source, apiRange),
1865
+ queries: marketParams.map(({ market, params }) => ({
1866
+ queryKey: priceHistoryQueryKey(market.slug, market.source, params),
1867
+ queryFn: () => client.getPriceHistory(market.slug, {
1868
+ source: market.source,
1869
+ ...params
1870
+ }),
1356
1871
  staleTime: 6e4,
1357
1872
  enabled: Boolean(market.slug)
1358
1873
  }))
1359
1874
  });
1360
1875
  const isLoading = queries.some((q) => q.isLoading);
1361
1876
  const series = react.useMemo(() => {
1362
- return markets.map((market, idx) => {
1877
+ return marketParams.map(({ market, params }, idx) => {
1363
1878
  const result = queries[idx];
1364
1879
  const points = result?.data?.points ?? [];
1365
- if (points.length > 0) {
1366
- return {
1367
- marketSlug: market.slug,
1368
- label: market.outcomes?.[0]?.label ?? market.question,
1369
- data: points.map((pt) => ({
1370
- timestamp: pt.t * 1e3,
1371
- price: pt.p
1372
- }))
1373
- };
1374
- }
1375
- const yesOutcome = market.outcomes?.find((o) => o.label.toLowerCase() === "yes") ?? market.outcomes?.[0];
1376
- const currentPrice = yesOutcome?.price ?? 0.5;
1377
- const now = Date.now();
1378
- const dayMs = 864e5;
1880
+ const fallbackPrice = firstFinitePrice(market);
1379
1881
  return {
1380
1882
  marketSlug: market.slug,
1381
1883
  label: market.outcomes?.[0]?.label ?? market.question,
1382
- data: [
1383
- { timestamp: now - 7 * dayMs, price: currentPrice },
1384
- { timestamp: now, price: currentPrice }
1385
- ]
1884
+ data: normalizeHistoryPoints(points, params, fallbackPrice)
1386
1885
  };
1387
1886
  });
1388
- }, [markets, queries]);
1887
+ }, [marketParams, queries]);
1389
1888
  return { series, isLoading };
1390
1889
  }
1391
- function orderbookQueryKey(slug, source, outcome = "yes") {
1392
- return ["predict", "orderbook", slug, source, outcome];
1393
- }
1394
- function useOrderbook(params, queryOptions = {}) {
1395
- const client = usePredictClient();
1396
- const outcome = params.outcome ?? "yes";
1397
- return reactQuery.useQuery({
1398
- queryKey: orderbookQueryKey(params.slug, params.source, outcome),
1399
- queryFn: () => client.getOrderbook(params.slug, params.source, outcome),
1400
- enabled: Boolean(params.slug),
1401
- refetchInterval: 3e4,
1402
- ...queryOptions
1403
- });
1404
- }
1405
1890
  function marketTradesQueryKey(slug, params) {
1406
1891
  return ["predict", "market-trades", slug, params];
1407
1892
  }
@@ -2595,29 +3080,6 @@ function useRebateConfig(queryOptions = {}) {
2595
3080
  ...queryOptions
2596
3081
  });
2597
3082
  }
2598
- function usePredictWsClient() {
2599
- const context = react.useContext(PredictContext);
2600
- if (!context) {
2601
- throw new Error("usePredictWsClient must be used within a PredictProvider");
2602
- }
2603
- const { wsClient } = context;
2604
- const [wsStatus, setWsStatus] = react.useState(
2605
- wsClient?.getStatus() ?? "disconnected"
2606
- );
2607
- react.useEffect(() => {
2608
- if (!wsClient) {
2609
- setWsStatus("disconnected");
2610
- return;
2611
- }
2612
- setWsStatus(wsClient.getStatus());
2613
- return wsClient.onStatusChange(setWsStatus);
2614
- }, [wsClient]);
2615
- return {
2616
- wsClient,
2617
- wsStatus,
2618
- isWsConnected: wsStatus === "connected"
2619
- };
2620
- }
2621
3083
  function usePricesSubscription({
2622
3084
  wsClient,
2623
3085
  slugs,
@@ -2653,43 +3115,6 @@ function usePricesSubscription({
2653
3115
  }, [wsClient, enabled, slugsKey, handleUpdate]);
2654
3116
  return { prices, isSubscribed };
2655
3117
  }
2656
- function useOrderbookSubscription({
2657
- wsClient,
2658
- slug,
2659
- enabled = true,
2660
- outcome,
2661
- onUpdate
2662
- }) {
2663
- const [orderbook, setOrderbook] = react.useState(null);
2664
- const [isSubscribed, setIsSubscribed] = react.useState(false);
2665
- const onUpdateRef = react.useRef(onUpdate);
2666
- onUpdateRef.current = onUpdate;
2667
- const handleUpdate = react.useCallback(
2668
- (msg) => {
2669
- if (msg.data.market_slug === slug) {
2670
- if (!outcome || msg.data.outcome === outcome) {
2671
- setOrderbook(msg.data);
2672
- }
2673
- onUpdateRef.current?.(msg);
2674
- }
2675
- },
2676
- [slug, outcome]
2677
- );
2678
- react.useEffect(() => {
2679
- if (!wsClient || !enabled || !slug) {
2680
- setIsSubscribed(false);
2681
- return;
2682
- }
2683
- setOrderbook(null);
2684
- const unsub = wsClient.subscribeOrderbook([slug], handleUpdate);
2685
- setIsSubscribed(true);
2686
- return () => {
2687
- unsub();
2688
- setIsSubscribed(false);
2689
- };
2690
- }, [wsClient, enabled, slug, handleUpdate]);
2691
- return { orderbook, isSubscribed };
2692
- }
2693
3118
  var DEFAULT_MAX_HISTORY = 100;
2694
3119
  function useTradesSubscription({
2695
3120
  wsClient,
@@ -2734,42 +3159,6 @@ function useTradesSubscription({
2734
3159
  }, [wsClient, enabled, slug, handleUpdate]);
2735
3160
  return { trades, isSubscribed, clearHistory };
2736
3161
  }
2737
- var REST_POLL_INTERVAL = 5e3;
2738
- function useRealtimeOrderbook(params, queryOptions = {}) {
2739
- const { wsClient } = usePredictWsClient();
2740
- const queryClient = reactQuery.useQueryClient();
2741
- const outcome = params.outcome ?? "yes";
2742
- const handleUpdate = react.useCallback(
2743
- (msg) => {
2744
- if (msg.data.market_slug !== params.slug) return;
2745
- if (msg.data.outcome !== "yes" && msg.data.outcome !== "no") return;
2746
- const ob = {
2747
- market_id: msg.data.market_slug,
2748
- outcome: msg.data.outcome,
2749
- bids: msg.data.bids,
2750
- asks: msg.data.asks,
2751
- spread: msg.data.spread
2752
- };
2753
- queryClient.setQueryData(
2754
- orderbookQueryKey(params.slug, params.source, msg.data.outcome),
2755
- ob
2756
- );
2757
- },
2758
- [params.slug, params.source, queryClient]
2759
- );
2760
- const subParams = {
2761
- wsClient,
2762
- slug: params.slug,
2763
- enabled: Boolean(params.slug),
2764
- outcome,
2765
- onUpdate: handleUpdate
2766
- };
2767
- const { isSubscribed } = useOrderbookSubscription(subParams);
2768
- return useOrderbook(params, {
2769
- refetchInterval: isSubscribed ? false : REST_POLL_INTERVAL,
2770
- ...queryOptions
2771
- });
2772
- }
2773
3162
 
2774
3163
  // src/hooks/predict/useRealtimePrices.ts
2775
3164
  function useRealtimePrices({
@@ -3318,16 +3707,28 @@ exports.createPredictWsClient = createPredictWsClient;
3318
3707
  exports.derivePolymarketApiKey = derivePolymarketApiKey;
3319
3708
  exports.dflowKYCQueryKey = dflowKYCQueryKey;
3320
3709
  exports.dflowQuoteQueryKey = dflowQuoteQueryKey;
3710
+ exports.esportsMatchesQueryKey = esportsMatchesQueryKey;
3711
+ exports.esportsPropsQueryKey = esportsPropsQueryKey;
3712
+ exports.esportsTaxonomyQueryKey = esportsTaxonomyQueryKey;
3321
3713
  exports.eventQueryKey = eventQueryKey;
3322
3714
  exports.eventStatsQueryKey = eventStatsQueryKey;
3323
3715
  exports.eventsQueryKey = eventsQueryKey;
3324
3716
  exports.feeRateQueryKey = feeRateQueryKey;
3717
+ exports.fetchEsportsMatches = fetchEsportsMatches;
3718
+ exports.fetchEsportsProps = fetchEsportsProps;
3719
+ exports.fetchEsportsTaxonomy = fetchEsportsTaxonomy;
3325
3720
  exports.fetchEvent = fetchEvent;
3326
3721
  exports.fetchEvents = fetchEvents;
3327
3722
  exports.fetchEventsPage = fetchEventsPage;
3328
3723
  exports.fetchMarket = fetchMarket;
3329
3724
  exports.fetchMatchMarketsPage = fetchMatchMarketsPage;
3330
3725
  exports.fetchMatchesPage = fetchMatchesPage;
3726
+ exports.fetchPredictSearch = fetchPredictSearch;
3727
+ exports.fetchSportsMatchDetail = fetchSportsMatchDetail;
3728
+ exports.fetchSportsMatches = fetchSportsMatches;
3729
+ exports.fetchSportsProps = fetchSportsProps;
3730
+ exports.fetchSportsRouting = fetchSportsRouting;
3731
+ exports.fetchSportsTaxonomy = fetchSportsTaxonomy;
3331
3732
  exports.getPolymarketSharesPrecision = getPolymarketSharesPrecision;
3332
3733
  exports.hmacSha256Base64 = hmacSha256Base64;
3333
3734
  exports.infiniteCommentsQueryKey = infiniteCommentsQueryKey;
@@ -3355,11 +3756,17 @@ exports.positionValueMultiQueryKey = positionValueMultiQueryKey;
3355
3756
  exports.positionValueQueryKey = positionValueQueryKey;
3356
3757
  exports.positionsMultiQueryKey = positionsMultiQueryKey;
3357
3758
  exports.positionsQueryKey = positionsQueryKey;
3759
+ exports.predictSearchQueryKey = predictSearchQueryKey;
3358
3760
  exports.priceHistoryQueryKey = priceHistoryQueryKey;
3359
3761
  exports.rebateConfigQueryKey = rebateConfigQueryKey;
3360
3762
  exports.resolveEventsParams = resolveEventsParams;
3361
3763
  exports.resolveTagSlug = resolveTagSlug;
3362
3764
  exports.similarEventsQueryKey = similarEventsQueryKey;
3765
+ exports.sportsMatchDetailQueryKey = sportsMatchDetailQueryKey;
3766
+ exports.sportsMatchesQueryKey = sportsMatchesQueryKey;
3767
+ exports.sportsPropsQueryKey = sportsPropsQueryKey;
3768
+ exports.sportsRoutingQueryKey = sportsRoutingQueryKey;
3769
+ exports.sportsTaxonomyQueryKey = sportsTaxonomyQueryKey;
3363
3770
  exports.tickSizeQueryKey = tickSizeQueryKey;
3364
3771
  exports.tradesQueryKey = tradesQueryKey;
3365
3772
  exports.updatePolymarketBalanceAllowance = updatePolymarketBalanceAllowance;
@@ -3372,6 +3779,9 @@ exports.useDFlowKYC = useDFlowKYC;
3372
3779
  exports.useDFlowQuote = useDFlowQuote;
3373
3780
  exports.useDFlowSubmit = useDFlowSubmit;
3374
3781
  exports.useDeployPolymarketDepositWallet = useDeployPolymarketDepositWallet;
3782
+ exports.useEsportsMatches = useEsportsMatches;
3783
+ exports.useEsportsProps = useEsportsProps;
3784
+ exports.useEsportsTaxonomy = useEsportsTaxonomy;
3375
3785
  exports.useEvent = useEvent;
3376
3786
  exports.useEventStats = useEventStats;
3377
3787
  exports.useEvents = useEvents;
@@ -3381,6 +3791,7 @@ exports.useInfiniteEvents = useInfiniteEvents;
3381
3791
  exports.useInfiniteMatchMarkets = useInfiniteMatchMarkets;
3382
3792
  exports.useInfiniteMatches = useInfiniteMatches;
3383
3793
  exports.useInfiniteOrders = useInfiniteOrders;
3794
+ exports.useInfinitePredictSearch = useInfinitePredictSearch;
3384
3795
  exports.useInfiniteTrades = useInfiniteTrades;
3385
3796
  exports.useInfiniteTradesMulti = useInfiniteTradesMulti;
3386
3797
  exports.useMarket = useMarket;
@@ -3408,6 +3819,7 @@ exports.usePositionValueMulti = usePositionValueMulti;
3408
3819
  exports.usePositions = usePositions;
3409
3820
  exports.usePositionsMulti = usePositionsMulti;
3410
3821
  exports.usePredictClient = usePredictClient;
3822
+ exports.usePredictSearch = usePredictSearch;
3411
3823
  exports.usePredictWsClient = usePredictWsClient;
3412
3824
  exports.usePriceHistory = usePriceHistory;
3413
3825
  exports.usePricesSubscription = usePricesSubscription;
@@ -3419,6 +3831,12 @@ exports.useRedeemPosition = useRedeemPosition;
3419
3831
  exports.useRunPolymarketSetup = useRunPolymarketSetup;
3420
3832
  exports.useSearchEvents = useSearchEvents;
3421
3833
  exports.useSimilarEvents = useSimilarEvents;
3834
+ exports.useSportsMatchDetail = useSportsMatchDetail;
3835
+ exports.useSportsMatches = useSportsMatches;
3836
+ exports.useSportsOrderbook = useSportsOrderbook;
3837
+ exports.useSportsProps = useSportsProps;
3838
+ exports.useSportsRouting = useSportsRouting;
3839
+ exports.useSportsTaxonomy = useSportsTaxonomy;
3422
3840
  exports.useTickSize = useTickSize;
3423
3841
  exports.useTradeResultConfirmation = useTradeResultConfirmation;
3424
3842
  exports.useTrades = useTrades;