@liberfi.io/react-predict 0.3.65 → 0.3.67

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
@@ -143,8 +143,9 @@ var PredictClient = class {
143
143
  return await httpGet(url);
144
144
  }
145
145
  /** Maps to `GET /api/v1/markets/:slug/price-history?source=...&range=...`. */
146
- async getPriceHistory(slug, source, range) {
147
- const query = buildQuery({ source, range });
146
+ async getPriceHistory(slug, sourceOrParams, range) {
147
+ const params = typeof sourceOrParams === "string" ? { source: sourceOrParams, range } : sourceOrParams;
148
+ const query = buildQuery(params);
148
149
  const url = `${this.endpoint}/api/v1/markets/${encodeURIComponent(slug)}/price-history${query}`;
149
150
  return await httpGet(url);
150
151
  }
@@ -1317,8 +1318,8 @@ function useMarket(params, queryOptions = {}) {
1317
1318
  ...queryOptions
1318
1319
  });
1319
1320
  }
1320
- function priceHistoryQueryKey(slug, source, range) {
1321
- return ["predict", "price-history", slug, source, range];
1321
+ function priceHistoryQueryKey(slug, source, rangeOrParams) {
1322
+ return ["predict", "price-history", slug, source, rangeOrParams];
1322
1323
  }
1323
1324
  function usePriceHistory(params, queryOptions = {}) {
1324
1325
  const client = usePredictClient();
@@ -1333,57 +1334,145 @@ function usePriceHistory(params, queryOptions = {}) {
1333
1334
 
1334
1335
  // src/hooks/predict/useMarketHistory.ts
1335
1336
  var ChartRange = {
1337
+ ONE_HOUR: "1h",
1338
+ SIX_HOURS: "6h",
1336
1339
  ONE_DAY: "1d",
1337
- ONE_WEEK: "1w",
1338
1340
  ONE_MONTH: "1m",
1339
1341
  ALL: "all"
1340
1342
  };
1341
1343
  var RANGE_MAP = {
1344
+ [ChartRange.ONE_HOUR]: "1h",
1345
+ [ChartRange.SIX_HOURS]: "6h",
1342
1346
  [ChartRange.ONE_DAY]: "1d",
1343
- [ChartRange.ONE_WEEK]: "1w",
1344
1347
  [ChartRange.ONE_MONTH]: "1m",
1345
1348
  [ChartRange.ALL]: "all"
1346
1349
  };
1347
- function useMarketHistory(markets, range = ChartRange.ALL) {
1350
+ var RANGE_DURATION_SECONDS = {
1351
+ [ChartRange.ONE_HOUR]: 60 * 60,
1352
+ [ChartRange.SIX_HOURS]: 6 * 60 * 60,
1353
+ [ChartRange.ONE_DAY]: 24 * 60 * 60,
1354
+ [ChartRange.ONE_MONTH]: 30 * 24 * 60 * 60,
1355
+ [ChartRange.ALL]: null
1356
+ };
1357
+ var RANGE_FIDELITY_MINUTES = {
1358
+ [ChartRange.ONE_HOUR]: 1,
1359
+ [ChartRange.SIX_HOURS]: 1,
1360
+ [ChartRange.ONE_DAY]: 5,
1361
+ [ChartRange.ONE_MONTH]: 15,
1362
+ [ChartRange.ALL]: 15
1363
+ };
1364
+ var LONG_RANGE_FIDELITY_MINUTES = {
1365
+ SHORT: 15,
1366
+ MONTH: 4 * 60,
1367
+ LONG: 24 * 60
1368
+ };
1369
+ var LONG_RANGE_SPAN_SECONDS = {
1370
+ WEEK: 7 * 24 * 60 * 60,
1371
+ MONTH: 31 * 24 * 60 * 60
1372
+ };
1373
+ function unixSecondsFromIso(value) {
1374
+ if (!value) return void 0;
1375
+ const ms = Date.parse(value);
1376
+ return Number.isFinite(ms) ? Math.floor(ms / 1e3) : void 0;
1377
+ }
1378
+ function firstFinitePrice(market) {
1379
+ const yesOutcome = market.outcomes?.find((o) => o.label.toLowerCase() === "yes") ?? market.outcomes?.[0];
1380
+ const price = yesOutcome?.best_ask ?? yesOutcome?.best_bid ?? yesOutcome?.price;
1381
+ return price != null && Number.isFinite(price) ? price : 0.5;
1382
+ }
1383
+ function fidelityMinutesForRange(range, startTs, endTs) {
1384
+ if (range !== ChartRange.ONE_MONTH && range !== ChartRange.ALL) {
1385
+ return RANGE_FIDELITY_MINUTES[range];
1386
+ }
1387
+ const spanSeconds = startTs != null ? Math.max(0, endTs - startTs) : 0;
1388
+ if (spanSeconds <= LONG_RANGE_SPAN_SECONDS.WEEK) {
1389
+ return LONG_RANGE_FIDELITY_MINUTES.SHORT;
1390
+ }
1391
+ if (spanSeconds <= LONG_RANGE_SPAN_SECONDS.MONTH) {
1392
+ return LONG_RANGE_FIDELITY_MINUTES.MONTH;
1393
+ }
1394
+ return LONG_RANGE_FIDELITY_MINUTES.LONG;
1395
+ }
1396
+ function buildRangeParams(range, market, anchoredEndTs) {
1397
+ const endTs = anchoredEndTs;
1398
+ const duration = RANGE_DURATION_SECONDS[range];
1399
+ const createdAt = unixSecondsFromIso(market.created_at);
1400
+ const rangeStartTs = duration == null ? void 0 : Math.max(0, endTs - duration);
1401
+ const startTs = createdAt != null && rangeStartTs != null ? Math.max(createdAt, rangeStartTs) : createdAt ?? rangeStartTs;
1402
+ return {
1403
+ range: RANGE_MAP[range],
1404
+ startTs,
1405
+ endTs,
1406
+ fidelity: fidelityMinutesForRange(range, startTs, endTs)
1407
+ };
1408
+ }
1409
+ function normalizeHistoryPoints(points, params, fallbackPrice) {
1410
+ const startMs = params.startTs != null ? params.startTs * 1e3 : void 0;
1411
+ const endMs = params.endTs != null ? params.endTs * 1e3 : void 0;
1412
+ const sorted = points.filter((pt) => Number.isFinite(pt.t) && Number.isFinite(pt.p)).map((pt) => ({ timestamp: pt.t * 1e3, price: pt.p })).filter((pt) => {
1413
+ if (startMs != null && pt.timestamp < startMs) return false;
1414
+ if (endMs != null && pt.timestamp > endMs) return false;
1415
+ return true;
1416
+ }).sort((a, b) => a.timestamp - b.timestamp);
1417
+ if (sorted.length === 0) {
1418
+ const now = endMs ?? Date.now();
1419
+ const start = startMs ?? now - 7 * 864e5;
1420
+ return [
1421
+ { timestamp: start, price: fallbackPrice },
1422
+ { timestamp: now, price: fallbackPrice }
1423
+ ];
1424
+ }
1425
+ const result = [...sorted];
1426
+ if (endMs != null && result[result.length - 1].timestamp < endMs) {
1427
+ result.push({
1428
+ timestamp: endMs,
1429
+ price: result[result.length - 1].price
1430
+ });
1431
+ }
1432
+ return result;
1433
+ }
1434
+ function useMarketHistory(markets, range = ChartRange.ALL, options = {}) {
1348
1435
  const client = usePredictClient();
1349
- const apiRange = RANGE_MAP[range];
1436
+ const rangeAnchorRef = useRef(null);
1437
+ const requestedEndTs = options.endTs;
1438
+ if (rangeAnchorRef.current?.range !== range || requestedEndTs != null && rangeAnchorRef.current?.endTs !== requestedEndTs) {
1439
+ rangeAnchorRef.current = {
1440
+ range,
1441
+ endTs: requestedEndTs ?? Math.floor(Date.now() / 1e3)
1442
+ };
1443
+ }
1444
+ const anchoredEndTs = rangeAnchorRef.current.endTs;
1445
+ const marketParams = useMemo(
1446
+ () => markets.map((market) => ({
1447
+ market,
1448
+ params: buildRangeParams(range, market, anchoredEndTs)
1449
+ })),
1450
+ [markets, range, anchoredEndTs]
1451
+ );
1350
1452
  const queries = useQueries({
1351
- queries: markets.map((market) => ({
1352
- queryKey: priceHistoryQueryKey(market.slug, market.source, apiRange),
1353
- queryFn: () => client.getPriceHistory(market.slug, market.source, apiRange),
1453
+ queries: marketParams.map(({ market, params }) => ({
1454
+ queryKey: priceHistoryQueryKey(market.slug, market.source, params),
1455
+ queryFn: () => client.getPriceHistory(market.slug, {
1456
+ source: market.source,
1457
+ ...params
1458
+ }),
1354
1459
  staleTime: 6e4,
1355
1460
  enabled: Boolean(market.slug)
1356
1461
  }))
1357
1462
  });
1358
1463
  const isLoading = queries.some((q) => q.isLoading);
1359
1464
  const series = useMemo(() => {
1360
- return markets.map((market, idx) => {
1465
+ return marketParams.map(({ market, params }, idx) => {
1361
1466
  const result = queries[idx];
1362
1467
  const points = result?.data?.points ?? [];
1363
- if (points.length > 0) {
1364
- return {
1365
- marketSlug: market.slug,
1366
- label: market.outcomes?.[0]?.label ?? market.question,
1367
- data: points.map((pt) => ({
1368
- timestamp: pt.t * 1e3,
1369
- price: pt.p
1370
- }))
1371
- };
1372
- }
1373
- const yesOutcome = market.outcomes?.find((o) => o.label.toLowerCase() === "yes") ?? market.outcomes?.[0];
1374
- const currentPrice = yesOutcome?.price ?? 0.5;
1375
- const now = Date.now();
1376
- const dayMs = 864e5;
1468
+ const fallbackPrice = firstFinitePrice(market);
1377
1469
  return {
1378
1470
  marketSlug: market.slug,
1379
1471
  label: market.outcomes?.[0]?.label ?? market.question,
1380
- data: [
1381
- { timestamp: now - 7 * dayMs, price: currentPrice },
1382
- { timestamp: now, price: currentPrice }
1383
- ]
1472
+ data: normalizeHistoryPoints(points, params, fallbackPrice)
1384
1473
  };
1385
1474
  });
1386
- }, [markets, queries]);
1475
+ }, [marketParams, queries]);
1387
1476
  return { series, isLoading };
1388
1477
  }
1389
1478
  function orderbookQueryKey(slug, source, outcome = "yes") {