@agg-build/hooks 2.1.2 → 2.2.0

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
@@ -196,7 +196,6 @@ __export(src_exports, {
196
196
  useSearch: () => useSearch,
197
197
  useSmartRoute: () => useSmartRoute,
198
198
  useSyncBalances: () => useSyncBalances,
199
- useTradableVenues: () => useTradableVenues,
200
199
  useUserActivity: () => useUserActivity,
201
200
  useUserHoldings: () => useUserHoldings,
202
201
  useVenueEvent: () => useVenueEvent,
@@ -985,6 +984,8 @@ var enUsLabels = {
985
984
  showOutcomeAria: (label) => `Show ${label} outcome`,
986
985
  viewResolved: "View resolved",
987
986
  hideResolved: "Hide resolved",
987
+ resolvingTitle: "Resolving market\u2026",
988
+ resolvingDescription: "This market has closed. We're waiting for final settlement data and will update the result once it's confirmed on-chain.",
988
989
  volumeUnavailable: "Volume unavailable",
989
990
  tabs: {
990
991
  orderBook: "Order Book",
@@ -1303,7 +1304,51 @@ var enUsLabels = {
1303
1304
  winningOutcome: (label) => `Winning outcome: ${label}`,
1304
1305
  resolvedOutcome: (label) => `Resolved: ${label}`,
1305
1306
  marketDetailsAriaByDate: (dateLabel) => `Market details for ${dateLabel}`,
1306
- marketDetailsAriaByQuestion: (question) => `Market details for ${question}`
1307
+ marketDetailsAriaByQuestion: (question) => `Market details for ${question}`,
1308
+ sports: {
1309
+ summaryAria: "Sports event summary",
1310
+ sectionTabsAria: "Sports market sections",
1311
+ lineSelectorAria: (marketTitle) => `Select line for ${marketTitle}`,
1312
+ previousLineAria: (marketTitle) => `Show previous lines for ${marketTitle}`,
1313
+ nextLineAria: (marketTitle) => `Show next lines for ${marketTitle}`,
1314
+ comparisonToggleAria: (marketTitle, expanded) => `${expanded ? "Hide" : "Show"} venue comparison for ${marketTitle}`,
1315
+ comparisonTitle: "Venue alternatives",
1316
+ compareVenues: (count) => `Compare ${count} venues`,
1317
+ marketCount: (count) => `${count} markets`,
1318
+ venueCount: (count) => `${count} venues`,
1319
+ volumeShort: "Vol.",
1320
+ totalVolumeShort: "Total Vol.",
1321
+ gameStarts: "Game starts",
1322
+ moreMarketsTitle: "More markets",
1323
+ gameLinesTab: "Game Lines",
1324
+ halvesTab: "Halves",
1325
+ exactScoreTab: "Exact Score",
1326
+ cornersTab: "Corners",
1327
+ goalsTab: "Goals",
1328
+ assistsTab: "Assists",
1329
+ shotsTab: "Shots",
1330
+ otherTab: "Other",
1331
+ moneylineTitle: "Moneyline",
1332
+ spreadTitle: "Spreads",
1333
+ totalTitle: "Totals",
1334
+ fullPeriod: "Regular time",
1335
+ firstHalfPeriod: "1st half",
1336
+ secondHalfPeriod: "2nd half",
1337
+ quarterOnePeriod: "1st quarter",
1338
+ quarterTwoPeriod: "2nd quarter",
1339
+ quarterThreePeriod: "3rd quarter",
1340
+ quarterFourPeriod: "4th quarter",
1341
+ overtimePeriod: "Overtime",
1342
+ otherPeriod: "Other",
1343
+ loadingTitle: "Loading section",
1344
+ loadingDescription: "Fetching the latest markets for this game.",
1345
+ emptyTitle: "No markets available",
1346
+ emptyDescription: (sectionLabel) => `There are no ${sectionLabel} markets yet.`,
1347
+ loadMore: "Load more",
1348
+ loadingMore: "Loading more",
1349
+ bestPriceBadge: "Best price",
1350
+ selectOutcomeAria: (marketTitle, outcomeLabel, priceLabel) => `Select ${outcomeLabel} in ${marketTitle} at ${priceLabel}`
1351
+ }
1307
1352
  },
1308
1353
  header: {
1309
1354
  bannerAria: "Site header",
@@ -1465,7 +1510,8 @@ var defaultAggUiConfig = {
1465
1510
  showFeesBreakdown: false,
1466
1511
  enableGradients: false,
1467
1512
  enableVenueEventDiscoveryFilters: false,
1468
- enableNotifications: true
1513
+ enableNotifications: true,
1514
+ showSportsMarkets: false
1469
1515
  },
1470
1516
  market: {
1471
1517
  arbitrageThreshold: 0,
@@ -1496,7 +1542,7 @@ var mergeAggUiSearchConfig = (config) => {
1496
1542
  };
1497
1543
  };
1498
1544
  var mergeAggUiConfig = (persisted, config) => {
1499
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L, _M, _N, _O, _P, _Q, _R, _S, _T, _U, _V, _W, _X;
1545
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L, _M, _N, _O, _P, _Q, _R, _S, _T, _U, _V, _W, _X, _Y, _Z;
1500
1546
  const locale = (_d = (_c = (_a = config == null ? void 0 : config.general) == null ? void 0 : _a.locale) != null ? _c : (_b = persisted.general) == null ? void 0 : _b.locale) != null ? _d : DEFAULT_LOCALE;
1501
1547
  const theme = (_h = (_g = (_e = config == null ? void 0 : config.general) == null ? void 0 : _e.theme) != null ? _g : (_f = persisted.general) == null ? void 0 : _f.theme) != null ? _h : defaultAggUiConfig.general.theme;
1502
1548
  const formatters = createFormatters(locale);
@@ -1518,27 +1564,28 @@ var mergeAggUiConfig = (persisted, config) => {
1518
1564
  showFeesBreakdown: (_v = (_u = config == null ? void 0 : config.features) == null ? void 0 : _u.showFeesBreakdown) != null ? _v : defaultAggUiConfig.features.showFeesBreakdown,
1519
1565
  enableGradients: (_x = (_w = config == null ? void 0 : config.features) == null ? void 0 : _w.enableGradients) != null ? _x : defaultAggUiConfig.features.enableGradients,
1520
1566
  enableVenueEventDiscoveryFilters: (_z = (_y = config == null ? void 0 : config.features) == null ? void 0 : _y.enableVenueEventDiscoveryFilters) != null ? _z : defaultAggUiConfig.features.enableVenueEventDiscoveryFilters,
1521
- enableNotifications: (_B = (_A = config == null ? void 0 : config.features) == null ? void 0 : _A.enableNotifications) != null ? _B : defaultAggUiConfig.features.enableNotifications
1567
+ enableNotifications: (_B = (_A = config == null ? void 0 : config.features) == null ? void 0 : _A.enableNotifications) != null ? _B : defaultAggUiConfig.features.enableNotifications,
1568
+ showSportsMarkets: (_D = (_C = config == null ? void 0 : config.features) == null ? void 0 : _C.showSportsMarkets) != null ? _D : defaultAggUiConfig.features.showSportsMarkets
1522
1569
  },
1523
1570
  market: {
1524
- arbitrageThreshold: (_D = (_C = config == null ? void 0 : config.market) == null ? void 0 : _C.arbitrageThreshold) != null ? _D : defaultAggUiConfig.market.arbitrageThreshold,
1525
- maxMidpointIdsPerRequest: (_F = (_E = config == null ? void 0 : config.market) == null ? void 0 : _E.maxMidpointIdsPerRequest) != null ? _F : defaultAggUiConfig.market.maxMidpointIdsPerRequest
1571
+ arbitrageThreshold: (_F = (_E = config == null ? void 0 : config.market) == null ? void 0 : _E.arbitrageThreshold) != null ? _F : defaultAggUiConfig.market.arbitrageThreshold,
1572
+ maxMidpointIdsPerRequest: (_H = (_G = config == null ? void 0 : config.market) == null ? void 0 : _G.maxMidpointIdsPerRequest) != null ? _H : defaultAggUiConfig.market.maxMidpointIdsPerRequest
1526
1573
  },
1527
1574
  chart: {
1528
- defaultChartTimeRange: (_H = (_G = config == null ? void 0 : config.chart) == null ? void 0 : _G.defaultChartTimeRange) != null ? _H : defaultAggUiConfig.chart.defaultChartTimeRange,
1529
- selectedChartTimeRange: (_L = (_K = (_I = persisted.chart) == null ? void 0 : _I.selectedChartTimeRange) != null ? _K : (_J = config == null ? void 0 : config.chart) == null ? void 0 : _J.defaultChartTimeRange) != null ? _L : defaultAggUiConfig.chart.defaultChartTimeRange,
1575
+ defaultChartTimeRange: (_J = (_I = config == null ? void 0 : config.chart) == null ? void 0 : _I.defaultChartTimeRange) != null ? _J : defaultAggUiConfig.chart.defaultChartTimeRange,
1576
+ selectedChartTimeRange: (_N = (_M = (_K = persisted.chart) == null ? void 0 : _K.selectedChartTimeRange) != null ? _M : (_L = config == null ? void 0 : config.chart) == null ? void 0 : _L.defaultChartTimeRange) != null ? _N : defaultAggUiConfig.chart.defaultChartTimeRange,
1530
1577
  setSelectedChartTimeRange: defaultAggUiConfig.chart.setSelectedChartTimeRange
1531
1578
  },
1532
1579
  formatting: {
1533
- formatNumber: (_N = (_M = config == null ? void 0 : config.formatting) == null ? void 0 : _M.formatNumber) != null ? _N : formatters.formatNumber,
1534
- formatPercent: (_P = (_O = config == null ? void 0 : config.formatting) == null ? void 0 : _O.formatPercent) != null ? _P : formatters.formatPercent,
1535
- formatCurrency: (_R = (_Q = config == null ? void 0 : config.formatting) == null ? void 0 : _Q.formatCurrency) != null ? _R : formatters.formatCurrency,
1536
- formatCompactCurrency: (_T = (_S = config == null ? void 0 : config.formatting) == null ? void 0 : _S.formatCompactCurrency) != null ? _T : formatters.formatCompactCurrency,
1537
- formatDate: (_V = (_U = config == null ? void 0 : config.formatting) == null ? void 0 : _U.formatDate) != null ? _V : formatters.formatDate
1580
+ formatNumber: (_P = (_O = config == null ? void 0 : config.formatting) == null ? void 0 : _O.formatNumber) != null ? _P : formatters.formatNumber,
1581
+ formatPercent: (_R = (_Q = config == null ? void 0 : config.formatting) == null ? void 0 : _Q.formatPercent) != null ? _R : formatters.formatPercent,
1582
+ formatCurrency: (_T = (_S = config == null ? void 0 : config.formatting) == null ? void 0 : _S.formatCurrency) != null ? _T : formatters.formatCurrency,
1583
+ formatCompactCurrency: (_V = (_U = config == null ? void 0 : config.formatting) == null ? void 0 : _U.formatCompactCurrency) != null ? _V : formatters.formatCompactCurrency,
1584
+ formatDate: (_X = (_W = config == null ? void 0 : config.formatting) == null ? void 0 : _W.formatDate) != null ? _X : formatters.formatDate
1538
1585
  },
1539
1586
  search: mergeAggUiSearchConfig(config == null ? void 0 : config.search),
1540
1587
  trading: {
1541
- executionMode: (_X = (_W = config == null ? void 0 : config.trading) == null ? void 0 : _W.executionMode) != null ? _X : defaultAggUiConfig.trading.executionMode
1588
+ executionMode: (_Z = (_Y = config == null ? void 0 : config.trading) == null ? void 0 : _Y.executionMode) != null ? _Z : defaultAggUiConfig.trading.executionMode
1542
1589
  },
1543
1590
  walletActions: config == null ? void 0 : config.walletActions,
1544
1591
  solanaRpcUrl: config == null ? void 0 : config.solanaRpcUrl
@@ -4055,6 +4102,7 @@ function mapOrderStatusToTerminalEvent(status) {
4055
4102
  }
4056
4103
  function useExecutionProgress({
4057
4104
  orderIds,
4105
+ quoteId,
4058
4106
  enabled,
4059
4107
  mode
4060
4108
  }) {
@@ -4230,17 +4278,202 @@ function useExecutionProgress({
4230
4278
  return;
4231
4279
  }
4232
4280
  }, []);
4233
- const isListening = enabled && !!orderIds && orderIds.length > 0;
4281
+ const isStatusPolling = enabled && !!quoteId;
4282
+ const isListening = !isStatusPolling && enabled && !!orderIds && orderIds.length > 0;
4234
4283
  useOnOrderSubmitted(isListening ? handleOrderSubmitted : null);
4235
4284
  useOnBalanceUpdate(isListening ? handleBalanceUpdate : null);
4236
4285
  useOnOrderEvent(isListening ? handleOrderEvent : null);
4237
4286
  const client = useAggClient();
4238
4287
  const terminalOrderIdsRef = (0, import_react10.useRef)(/* @__PURE__ */ new Set());
4239
4288
  const pollInFlightRef = (0, import_react10.useRef)(false);
4289
+ const buildSubmittedOrdersFromStatus = (0, import_react10.useCallback)(
4290
+ (orders) => {
4291
+ return orders.map((order) => {
4292
+ var _a, _b;
4293
+ return {
4294
+ type: "order_submitted",
4295
+ venue: order.venue,
4296
+ orderId: order.orderId,
4297
+ side: "",
4298
+ price: Number((_b = (_a = order.executionPriceRaw) != null ? _a : order.quotedPriceRaw) != null ? _b : 0),
4299
+ size: 0,
4300
+ timestamp: new Date(order.updatedAt).getTime() / 1e3
4301
+ };
4302
+ });
4303
+ },
4304
+ []
4305
+ );
4306
+ const buildTerminalEventsFromStatus = (0, import_react10.useCallback)(
4307
+ (status, fallbackOrderIds, fallbackTimestamp) => {
4308
+ const terminalEvents = status.orders.map((order) => {
4309
+ var _a, _b;
4310
+ const mappedEvent = (_a = order.event) != null ? _a : mapOrderStatusToTerminalEvent(order.status);
4311
+ if (!mappedEvent) return null;
4312
+ return {
4313
+ orderId: order.orderId,
4314
+ venue: order.venue,
4315
+ event: mappedEvent,
4316
+ filledAmountRaw: order.filledAmountRaw,
4317
+ remainingAmountRaw: order.remainingAmountRaw,
4318
+ actualSharesRaw: order.actualSharesRaw,
4319
+ actualToWinRaw: order.actualToWinRaw,
4320
+ quotedSharesRaw: order.quotedSharesRaw,
4321
+ quotedToWinRaw: order.quotedToWinRaw,
4322
+ executionPriceRaw: order.executionPriceRaw,
4323
+ quotedPriceRaw: order.quotedPriceRaw,
4324
+ errorReason: (_b = order.errorReason) != null ? _b : order.partialFillReason,
4325
+ timestamp: new Date(order.updatedAt).getTime() || fallbackTimestamp
4326
+ };
4327
+ }).filter((order) => order != null);
4328
+ if (!status.terminal || terminalEvents.length > 0 || !["failed", "cancelled", "expired"].includes(status.overallState)) {
4329
+ return terminalEvents;
4330
+ }
4331
+ return fallbackOrderIds.map((orderId) => {
4332
+ var _a;
4333
+ return {
4334
+ orderId,
4335
+ venue: "",
4336
+ event: "failed",
4337
+ errorReason: (_a = status.errorReason) != null ? _a : "Execution failed.",
4338
+ timestamp: fallbackTimestamp
4339
+ };
4340
+ });
4341
+ },
4342
+ []
4343
+ );
4344
+ const setFatalPollingFailure = (0, import_react10.useCallback)((message, failedOrderIds) => {
4345
+ setDagProgress((prev) => {
4346
+ var _a, _b, _c, _d, _e, _f;
4347
+ return {
4348
+ dagRunId: (_a = prev == null ? void 0 : prev.dagRunId) != null ? _a : "",
4349
+ totalSteps: (_b = prev == null ? void 0 : prev.totalSteps) != null ? _b : 0,
4350
+ currentSequence: (_c = prev == null ? void 0 : prev.currentSequence) != null ? _c : 0,
4351
+ currentStepType: (_d = prev == null ? void 0 : prev.currentStepType) != null ? _d : null,
4352
+ completedSequences: (_e = prev == null ? void 0 : prev.completedSequences) != null ? _e : [],
4353
+ stepTypes: (_f = prev == null ? void 0 : prev.stepTypes) != null ? _f : {},
4354
+ status: "failed",
4355
+ errorReason: message
4356
+ };
4357
+ });
4358
+ setTerminalOrderEvents((prev) => {
4359
+ const existingByOrderId = new Map(prev.map((event) => [event.orderId, event]));
4360
+ const timestamp = Date.now();
4361
+ for (const orderId of failedOrderIds) {
4362
+ if (existingByOrderId.has(orderId)) continue;
4363
+ existingByOrderId.set(orderId, {
4364
+ orderId,
4365
+ venue: "",
4366
+ event: "failed",
4367
+ errorReason: message,
4368
+ timestamp
4369
+ });
4370
+ }
4371
+ return Array.from(existingByOrderId.values()).sort(
4372
+ (left, right) => left.timestamp - right.timestamp
4373
+ );
4374
+ });
4375
+ }, []);
4240
4376
  (0, import_react10.useEffect)(() => {
4241
4377
  terminalOrderIdsRef.current = new Set(terminalOrderEvents.map((e) => e.orderId));
4242
4378
  }, [terminalOrderEvents]);
4243
4379
  (0, import_react10.useEffect)(() => {
4380
+ if (!isStatusPolling || !quoteId) return;
4381
+ let cancelled = false;
4382
+ let timeout = null;
4383
+ const stopPolling = () => {
4384
+ if (timeout !== null) {
4385
+ clearTimeout(timeout);
4386
+ timeout = null;
4387
+ }
4388
+ };
4389
+ const scheduleNextPoll = (delayMs) => {
4390
+ if (cancelled) return;
4391
+ timeout = setTimeout(() => {
4392
+ void pollExecutionStatus();
4393
+ }, delayMs != null ? delayMs : ORDER_POLL_INTERVAL_MS);
4394
+ };
4395
+ const pollExecutionStatus = () => __async(null, null, function* () {
4396
+ if (cancelled || pollInFlightRef.current) return;
4397
+ pollInFlightRef.current = true;
4398
+ try {
4399
+ const status = yield client.getExecutionStatus(__spreadValues({
4400
+ quoteId
4401
+ }, mode ? { mode } : {}));
4402
+ if (cancelled) return;
4403
+ const resolvedOrderIds = status.orderIds.length > 0 ? status.orderIds : orderIds != null ? orderIds : [];
4404
+ if (resolvedOrderIds.length > 0) {
4405
+ setPhase("order_submitted");
4406
+ }
4407
+ setSubmittedOrders(buildSubmittedOrdersFromStatus(status.orders));
4408
+ if (status.dagProgress) {
4409
+ setDagProgress(__spreadProps(__spreadValues({}, status.dagProgress), {
4410
+ stepTypes: Object.fromEntries(
4411
+ Object.entries(status.dagProgress.stepTypes).map(([sequence, stepType]) => [
4412
+ Number(sequence),
4413
+ stepType
4414
+ ])
4415
+ )
4416
+ }));
4417
+ } else if (status.terminal && ["failed", "cancelled", "expired"].includes(status.overallState)) {
4418
+ setDagProgress((prev) => {
4419
+ var _a, _b, _c, _d, _e, _f, _g;
4420
+ return {
4421
+ dagRunId: (_b = (_a = prev == null ? void 0 : prev.dagRunId) != null ? _a : status.executionId) != null ? _b : "",
4422
+ totalSteps: (_c = prev == null ? void 0 : prev.totalSteps) != null ? _c : status.steps.length,
4423
+ currentSequence: (_d = prev == null ? void 0 : prev.currentSequence) != null ? _d : 0,
4424
+ currentStepType: (_e = prev == null ? void 0 : prev.currentStepType) != null ? _e : null,
4425
+ completedSequences: (_f = prev == null ? void 0 : prev.completedSequences) != null ? _f : [],
4426
+ stepTypes: (_g = prev == null ? void 0 : prev.stepTypes) != null ? _g : {},
4427
+ status: "failed",
4428
+ errorReason: status.errorReason
4429
+ };
4430
+ });
4431
+ }
4432
+ const fallbackTimestamp = Date.now();
4433
+ const nextTerminalEvents = buildTerminalEventsFromStatus(
4434
+ status,
4435
+ resolvedOrderIds,
4436
+ fallbackTimestamp
4437
+ );
4438
+ setTerminalOrderEvents(nextTerminalEvents);
4439
+ if (status.terminal) {
4440
+ stopPolling();
4441
+ return;
4442
+ }
4443
+ scheduleNextPoll(status.pollAfterMs);
4444
+ } catch (error) {
4445
+ if (cancelled) return;
4446
+ const statusCode = typeof error === "object" && error != null && "status" in error && typeof error.status === "number" ? error.status : null;
4447
+ if (statusCode === 400 || statusCode === 401 || statusCode === 403) {
4448
+ setFatalPollingFailure(
4449
+ error instanceof Error ? error.message : "Execution status polling failed.",
4450
+ orderIds != null ? orderIds : []
4451
+ );
4452
+ stopPolling();
4453
+ return;
4454
+ }
4455
+ scheduleNextPoll(ORDER_POLL_INTERVAL_MS);
4456
+ } finally {
4457
+ pollInFlightRef.current = false;
4458
+ }
4459
+ });
4460
+ void pollExecutionStatus();
4461
+ return () => {
4462
+ cancelled = true;
4463
+ stopPolling();
4464
+ };
4465
+ }, [
4466
+ buildSubmittedOrdersFromStatus,
4467
+ buildTerminalEventsFromStatus,
4468
+ client,
4469
+ isStatusPolling,
4470
+ mode,
4471
+ orderIds,
4472
+ quoteId,
4473
+ setFatalPollingFailure
4474
+ ]);
4475
+ (0, import_react10.useEffect)(() => {
4476
+ if (isStatusPolling) return;
4244
4477
  if (!isListening || !(orderIds == null ? void 0 : orderIds.length)) return;
4245
4478
  let cancelled = false;
4246
4479
  let interval = null;
@@ -4328,7 +4561,7 @@ function useExecutionProgress({
4328
4561
  cancelled = true;
4329
4562
  stopPolling();
4330
4563
  };
4331
- }, [client, isListening, mode, orderIds]);
4564
+ }, [client, isListening, isStatusPolling, mode, orderIds]);
4332
4565
  return { phase, submittedOrders, latestBalance, dagProgress, terminalOrderEvents };
4333
4566
  }
4334
4567
 
@@ -5945,7 +6178,6 @@ function useLiveOutcomePrices(venueMarkets) {
5945
6178
  for (const vm of venueMarkets) {
5946
6179
  for (const outcome of (_d = vm.venueMarketOutcomes) != null ? _d : []) {
5947
6180
  if (!enableLiveUpdates) {
5948
- prices.set(outcome.id, outcome.price);
5949
6181
  continue;
5950
6182
  }
5951
6183
  const liveMidpoint = liveByOutcomeId.get(outcome.id);
@@ -6498,31 +6730,8 @@ function useMidpoints(venueMarkets, options) {
6498
6730
  };
6499
6731
  }
6500
6732
 
6501
- // src/use-tradable-venues.ts
6502
- var import_react29 = require("react");
6503
- function useTradableVenues(venueMarkets) {
6504
- const { prices, isLoading } = useMidpoints(venueMarkets);
6505
- const tradableVenues = (0, import_react29.useMemo)(() => {
6506
- var _a;
6507
- if (isLoading) return null;
6508
- if (!venueMarkets || venueMarkets.length === 0) return /* @__PURE__ */ new Set();
6509
- const set = /* @__PURE__ */ new Set();
6510
- for (const market of venueMarkets) {
6511
- const outcomes = (_a = market.venueMarketOutcomes) != null ? _a : [];
6512
- for (const outcome of outcomes) {
6513
- if (prices.has(outcome.id)) {
6514
- set.add(market.venue);
6515
- break;
6516
- }
6517
- }
6518
- }
6519
- return set;
6520
- }, [venueMarkets, prices, isLoading]);
6521
- return { tradableVenues, isLoading };
6522
- }
6523
-
6524
6733
  // src/use-rolling-chart-window.ts
6525
- var import_react30 = require("react");
6734
+ var import_react29 = require("react");
6526
6735
  var RANGE_SECONDS_BY_RANGE = {
6527
6736
  "1H": 60 * 60,
6528
6737
  "6H": 6 * 60 * 60,
@@ -6553,16 +6762,16 @@ var useRollingChartWindow = (options) => {
6553
6762
  var _a;
6554
6763
  const tickMs = (_a = options.tickMs) != null ? _a : 1e3;
6555
6764
  const optionsNowMs = options.nowMs;
6556
- const nowMs = (0, import_react30.useMemo)(() => optionsNowMs != null ? optionsNowMs : (() => Date.now()), [optionsNowMs]);
6557
- const [nowSec, setNowSec] = (0, import_react30.useState)(() => Math.floor(nowMs() / 1e3));
6558
- (0, import_react30.useEffect)(() => {
6765
+ const nowMs = (0, import_react29.useMemo)(() => optionsNowMs != null ? optionsNowMs : (() => Date.now()), [optionsNowMs]);
6766
+ const [nowSec, setNowSec] = (0, import_react29.useState)(() => Math.floor(nowMs() / 1e3));
6767
+ (0, import_react29.useEffect)(() => {
6559
6768
  setNowSec(Math.floor(nowMs() / 1e3));
6560
6769
  const handle = setInterval(() => {
6561
6770
  setNowSec(Math.floor(nowMs() / 1e3));
6562
6771
  }, tickMs);
6563
6772
  return () => clearInterval(handle);
6564
6773
  }, [tickMs, nowMs]);
6565
- return (0, import_react30.useMemo)(
6774
+ return (0, import_react29.useMemo)(
6566
6775
  () => resolveRollingWindow({ range: options.range, nowSec, interval: options.interval }),
6567
6776
  [options.range, options.interval, nowSec]
6568
6777
  );
@@ -6655,11 +6864,11 @@ function useMarketOrderbook(options) {
6655
6864
  }
6656
6865
 
6657
6866
  // src/use-arb.ts
6658
- var import_react31 = require("react");
6867
+ var import_react30 = require("react");
6659
6868
  function useMarketArb(marketId) {
6660
6869
  const ws = useAggWebSocket();
6661
- const [state, setState] = (0, import_react31.useState)({ arbReturn: null, isLive: false });
6662
- (0, import_react31.useEffect)(() => {
6870
+ const [state, setState] = (0, import_react30.useState)({ arbReturn: null, isLive: false });
6871
+ (0, import_react30.useEffect)(() => {
6663
6872
  if (!ws || !marketId) return;
6664
6873
  const cached = ws.getArb(marketId);
6665
6874
  if (cached != null) {
@@ -6678,10 +6887,10 @@ var EMPTY_ARB_FEED = {
6678
6887
  };
6679
6888
  function useArbFeed() {
6680
6889
  const ws = useAggWebSocket();
6681
- const [state, setState] = (0, import_react31.useState)(EMPTY_ARB_FEED);
6682
- const stateRef = (0, import_react31.useRef)(state);
6890
+ const [state, setState] = (0, import_react30.useState)(EMPTY_ARB_FEED);
6891
+ const stateRef = (0, import_react30.useRef)(state);
6683
6892
  stateRef.current = state;
6684
- (0, import_react31.useEffect)(() => {
6893
+ (0, import_react30.useEffect)(() => {
6685
6894
  if (!ws) return;
6686
6895
  const off = ws.subscribeArbFeed((batch) => {
6687
6896
  setState((prev) => {
@@ -6921,15 +7130,15 @@ function useOrders(options = {}) {
6921
7130
 
6922
7131
  // src/use-search.ts
6923
7132
  var import_react_query31 = require("@tanstack/react-query");
6924
- var import_react32 = require("react");
7133
+ var import_react31 = require("react");
6925
7134
  function useSearch(options) {
6926
7135
  var _a, _b, _c;
6927
- const client = (0, import_react32.useContext)(AggClientContext);
6928
- const queryClient = (0, import_react32.useContext)(import_react_query31.QueryClientContext);
6929
- const [fallbackQueryClient] = (0, import_react32.useState)(() => new import_react_query31.QueryClient());
7136
+ const client = (0, import_react31.useContext)(AggClientContext);
7137
+ const queryClient = (0, import_react31.useContext)(import_react_query31.QueryClientContext);
7138
+ const [fallbackQueryClient] = (0, import_react31.useState)(() => new import_react_query31.QueryClient());
6930
7139
  const { q, type, categoryIds, limit = 20, enabled = true, deep = false } = options;
6931
7140
  const isEnabled = enabled && q.length > 0;
6932
- (0, import_react32.useEffect)(() => {
7141
+ (0, import_react31.useEffect)(() => {
6933
7142
  if (queryClient) return void 0;
6934
7143
  fallbackQueryClient.mount();
6935
7144
  return () => {
@@ -6983,7 +7192,7 @@ function useSearch(options) {
6983
7192
  }
6984
7193
 
6985
7194
  // src/use-market-search.ts
6986
- var import_react33 = require("react");
7195
+ var import_react32 = require("react");
6987
7196
  function useMarketSearch(options) {
6988
7197
  var _a;
6989
7198
  const {
@@ -6994,8 +7203,8 @@ function useMarketSearch(options) {
6994
7203
  enableSuggestions = true,
6995
7204
  minLength = 1
6996
7205
  } = options;
6997
- const [query, setQueryState] = (0, import_react33.useState)("");
6998
- const [submittedQuery, setSubmittedQuery] = (0, import_react33.useState)(null);
7206
+ const [query, setQueryState] = (0, import_react32.useState)("");
7207
+ const [submittedQuery, setSubmittedQuery] = (0, import_react32.useState)(null);
6999
7208
  const debouncedQuery = useDebouncedValue(query, debounceMs);
7000
7209
  const trimmedDebounced = debouncedQuery.trim();
7001
7210
  const suggestionsEnabled = enableSuggestions && trimmedDebounced.length >= minLength;
@@ -7016,10 +7225,10 @@ function useMarketSearch(options) {
7016
7225
  enabled: submittedQ.length > 0,
7017
7226
  deep: true
7018
7227
  });
7019
- const setQuery = (0, import_react33.useCallback)((value) => {
7228
+ const setQuery = (0, import_react32.useCallback)((value) => {
7020
7229
  setQueryState(value);
7021
7230
  }, []);
7022
- const submit = (0, import_react33.useCallback)(
7231
+ const submit = (0, import_react32.useCallback)(
7023
7232
  (q) => {
7024
7233
  const target = (q != null ? q : query).trim();
7025
7234
  if (target.length === 0) return;
@@ -7027,7 +7236,7 @@ function useMarketSearch(options) {
7027
7236
  },
7028
7237
  [query]
7029
7238
  );
7030
- const clear = (0, import_react33.useCallback)(() => {
7239
+ const clear = (0, import_react32.useCallback)(() => {
7031
7240
  setQueryState("");
7032
7241
  setSubmittedQuery(null);
7033
7242
  }, []);
@@ -7070,7 +7279,130 @@ function useMarketSearch(options) {
7070
7279
 
7071
7280
  // src/use-smart-route.ts
7072
7281
  var import_react_query32 = require("@tanstack/react-query");
7282
+
7283
+ // src/smart-route-refresh-policy.ts
7284
+ var THIN_SMART_ROUTE_REFETCH_INTERVAL_MS = 5e3;
7285
+ var SMART_ROUTE_REFRESH_DEADLINE_BUFFER_MS = 4e3;
7286
+ var SMART_ROUTE_MIN_REFETCH_INTERVAL_MS = 5e3;
7287
+ var SMART_ROUTE_MAX_REFETCH_INTERVAL_MS = 2e4;
7288
+ var SMART_ROUTE_HIGH_SLIPPAGE_BPS = 75;
7289
+ var SMART_ROUTE_SHALLOW_TOP_LEVEL_RATIO = 0.7;
7290
+ var SMART_ROUTE_DEEP_FILL_LEVEL_COUNT = 3;
7291
+ var LIQUIDITY_CONSTRAINED_STATUSES = /* @__PURE__ */ new Set([
7292
+ "infeasible",
7293
+ "no_orderbooks",
7294
+ "insufficient_depth",
7295
+ "no_bids_above_min_price"
7296
+ ]);
7297
+ var THIN_LIQUIDITY_WARNING_PATTERN = /partial(?:[_\s-]?fill)?|insufficient(?:[_\s-]?liquidity|[_\s-]?depth)|shallow|price moved|no active quote path|couldn'?t fill|unable to fill|quote stale|stale/i;
7298
+ var resolveMsUntilIsoTimestamp = (value, nowMs) => {
7299
+ if (!value) return null;
7300
+ const parsedValue = Date.parse(value);
7301
+ if (!Number.isFinite(parsedValue)) return null;
7302
+ return parsedValue - nowMs;
7303
+ };
7304
+ var clampIntervalToRefreshDeadline = ({
7305
+ intervalMs,
7306
+ refreshAt,
7307
+ nowMs
7308
+ }) => {
7309
+ const msUntilRefresh = resolveMsUntilIsoTimestamp(refreshAt, nowMs);
7310
+ if (msUntilRefresh == null || msUntilRefresh <= 0) {
7311
+ return Math.min(
7312
+ SMART_ROUTE_MAX_REFETCH_INTERVAL_MS,
7313
+ Math.max(SMART_ROUTE_MIN_REFETCH_INTERVAL_MS, intervalMs)
7314
+ );
7315
+ }
7316
+ return Math.max(
7317
+ SMART_ROUTE_MIN_REFETCH_INTERVAL_MS,
7318
+ Math.min(SMART_ROUTE_MAX_REFETCH_INTERVAL_MS, intervalMs, Math.floor(msUntilRefresh))
7319
+ );
7320
+ };
7321
+ var assessThinSmartRouteLiquidity = (quote, nowMs = Date.now()) => {
7322
+ var _a, _b;
7323
+ if (!quote) {
7324
+ return {
7325
+ isThin: false,
7326
+ reasons: []
7327
+ };
7328
+ }
7329
+ const reasons = /* @__PURE__ */ new Set();
7330
+ if (LIQUIDITY_CONSTRAINED_STATUSES.has(quote.status)) {
7331
+ reasons.add("liquidity_status");
7332
+ }
7333
+ if (typeof ((_a = quote.slippage) == null ? void 0 : _a.slippageBps) === "number" && Number.isFinite(quote.slippage.slippageBps) && quote.slippage.slippageBps >= SMART_ROUTE_HIGH_SLIPPAGE_BPS) {
7334
+ reasons.add("high_slippage");
7335
+ }
7336
+ const msUntilRefresh = resolveMsUntilIsoTimestamp(quote.refreshAt, nowMs);
7337
+ if (msUntilRefresh != null && msUntilRefresh <= SMART_ROUTE_REFRESH_DEADLINE_BUFFER_MS) {
7338
+ reasons.add("refresh_due_soon");
7339
+ }
7340
+ const hasShallowTopLevel = quote.fills.some((fill) => {
7341
+ var _a2, _b2;
7342
+ if (fill.fills.length <= 1 || fill.venueQty <= 0) return false;
7343
+ const topLevelSize = (_b2 = (_a2 = fill.fills[0]) == null ? void 0 : _a2.size) != null ? _b2 : 0;
7344
+ if (!Number.isFinite(topLevelSize) || topLevelSize <= 0) return false;
7345
+ return topLevelSize / fill.venueQty < SMART_ROUTE_SHALLOW_TOP_LEVEL_RATIO;
7346
+ });
7347
+ if (hasShallowTopLevel) {
7348
+ reasons.add("shallow_top_level");
7349
+ }
7350
+ const hasDeepFillLevels = quote.fills.some(
7351
+ (fill) => fill.fills.length >= SMART_ROUTE_DEEP_FILL_LEVEL_COUNT
7352
+ );
7353
+ if (hasDeepFillLevels) {
7354
+ reasons.add("deep_fill_levels");
7355
+ }
7356
+ const hasThinWarning = ((_b = quote.warnings) != null ? _b : []).some(
7357
+ (warning) => THIN_LIQUIDITY_WARNING_PATTERN.test(warning.reason)
7358
+ );
7359
+ if (hasThinWarning) {
7360
+ reasons.add("warning_signal");
7361
+ }
7362
+ return {
7363
+ isThin: reasons.size > 0,
7364
+ reasons: [...reasons]
7365
+ };
7366
+ };
7367
+ var resolveSmartRouteRefetchInterval = (args, nowMs = Date.now()) => {
7368
+ const {
7369
+ aggressiveIntervalMs = THIN_SMART_ROUTE_REFETCH_INTERVAL_MS,
7370
+ data,
7371
+ defaultIntervalMs,
7372
+ isDocumentVisible,
7373
+ isEditing = false,
7374
+ isInputValid,
7375
+ isMarketOpen,
7376
+ isPanelActive,
7377
+ isSubmitting,
7378
+ queryEnabled
7379
+ } = args;
7380
+ if (defaultIntervalMs <= 0) return false;
7381
+ const isActivelyViewingQuote = isPanelActive || isEditing;
7382
+ if (!queryEnabled || !isInputValid || !isActivelyViewingQuote || !isMarketOpen || isSubmitting || !isDocumentVisible) {
7383
+ return false;
7384
+ }
7385
+ const defaultInterval = clampIntervalToRefreshDeadline({
7386
+ intervalMs: defaultIntervalMs,
7387
+ refreshAt: data == null ? void 0 : data.refreshAt,
7388
+ nowMs
7389
+ });
7390
+ if (!data) return defaultInterval;
7391
+ const thinLiquidity = assessThinSmartRouteLiquidity(data, nowMs);
7392
+ if (!thinLiquidity.isThin) return defaultInterval;
7393
+ return clampIntervalToRefreshDeadline({
7394
+ intervalMs: aggressiveIntervalMs,
7395
+ refreshAt: data.refreshAt,
7396
+ nowMs
7397
+ });
7398
+ };
7399
+
7400
+ // src/use-smart-route.ts
7073
7401
  var SMART_ROUTE_STALE_TIME_MS = 2e4;
7402
+ var getIsDocumentVisible = () => {
7403
+ if (typeof document === "undefined") return true;
7404
+ return document.visibilityState !== "hidden";
7405
+ };
7074
7406
  function useSmartRoute(options) {
7075
7407
  var _a, _b;
7076
7408
  const client = useAggClient();
@@ -7088,9 +7420,12 @@ function useSmartRoute(options) {
7088
7420
  compareVenues,
7089
7421
  deepEstimate,
7090
7422
  enabled = true,
7091
- staleTimeMs = SMART_ROUTE_STALE_TIME_MS
7423
+ staleTimeMs = SMART_ROUTE_STALE_TIME_MS,
7424
+ refreshContext
7092
7425
  } = options;
7093
7426
  const resolvedVenueMarketOutcomeId = (_a = venueMarketOutcomeId != null ? venueMarketOutcomeId : venueMarketId) != null ? _a : outcomeId;
7427
+ const hasValidInput = (maxSpend != null ? maxSpend : 0) > 0 || (sellShares != null ? sellShares : 0) > 0;
7428
+ const queryEnabled = enabled && !!resolvedVenueMarketOutcomeId && hasValidInput;
7094
7429
  const query = (0, import_react_query32.useQuery)({
7095
7430
  queryKey: [
7096
7431
  "smart-route",
@@ -7122,11 +7457,25 @@ function useSmartRoute(options) {
7122
7457
  { signal }
7123
7458
  );
7124
7459
  }),
7125
- enabled: enabled && !!resolvedVenueMarketOutcomeId && ((maxSpend != null ? maxSpend : 0) > 0 || (sellShares != null ? sellShares : 0) > 0),
7460
+ enabled: queryEnabled,
7126
7461
  staleTime: staleTimeMs,
7127
- refetchInterval: staleTimeMs > 0 ? staleTimeMs : false,
7462
+ refetchInterval: (queryState) => {
7463
+ var _a2, _b2, _c, _d;
7464
+ return resolveSmartRouteRefetchInterval({
7465
+ data: queryState.state.data,
7466
+ defaultIntervalMs: staleTimeMs,
7467
+ isDocumentVisible: getIsDocumentVisible(),
7468
+ isEditing: (_a2 = refreshContext == null ? void 0 : refreshContext.isEditing) != null ? _a2 : false,
7469
+ isInputValid: hasValidInput,
7470
+ isMarketOpen: (_b2 = refreshContext == null ? void 0 : refreshContext.isMarketOpen) != null ? _b2 : true,
7471
+ isPanelActive: (_c = refreshContext == null ? void 0 : refreshContext.isPanelActive) != null ? _c : true,
7472
+ isSubmitting: (_d = refreshContext == null ? void 0 : refreshContext.isSubmitting) != null ? _d : false,
7473
+ queryEnabled
7474
+ });
7475
+ },
7128
7476
  gcTime: 6e4,
7129
7477
  refetchOnWindowFocus: false,
7478
+ refetchIntervalInBackground: false,
7130
7479
  retry: 1,
7131
7480
  placeholderData: import_react_query32.keepPreviousData
7132
7481
  });
@@ -7181,7 +7530,7 @@ function useUserHoldings(options) {
7181
7530
  }
7182
7531
 
7183
7532
  // src/use-enriched-venue-event.ts
7184
- var import_react35 = require("react");
7533
+ var import_react34 = require("react");
7185
7534
 
7186
7535
  // src/use-venue-event.ts
7187
7536
  var import_react_query34 = require("@tanstack/react-query");
@@ -7209,23 +7558,29 @@ function useVenueEvent(options) {
7209
7558
 
7210
7559
  // src/use-venue-markets.ts
7211
7560
  var import_react_query35 = require("@tanstack/react-query");
7212
- var import_react34 = require("react");
7561
+ var import_react33 = require("react");
7213
7562
  function useVenueMarkets(options) {
7214
- var _a, _b, _c, _d, _e;
7215
- const client = (0, import_react34.useContext)(AggClientContext);
7216
- const queryClient = (0, import_react34.useContext)(import_react_query35.QueryClientContext);
7217
- const [fallbackQueryClient] = (0, import_react34.useState)(() => new import_react_query35.QueryClient());
7563
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
7564
+ const client = (0, import_react33.useContext)(AggClientContext);
7565
+ const queryClient = (0, import_react33.useContext)(import_react_query35.QueryClientContext);
7566
+ const [fallbackQueryClient] = (0, import_react33.useState)(() => new import_react_query35.QueryClient());
7218
7567
  const venue = options == null ? void 0 : options.venue;
7219
7568
  const venueEventId = options == null ? void 0 : options.venueEventId;
7220
7569
  const search = options == null ? void 0 : options.search;
7221
7570
  const matchStatus = options == null ? void 0 : options.matchStatus;
7222
7571
  const status = options == null ? void 0 : options.status;
7223
7572
  const categoryIds = options == null ? void 0 : options.categoryIds;
7573
+ const aggKey = options == null ? void 0 : options.aggKey;
7574
+ const sportsMarketType = options == null ? void 0 : options.sportsMarketType;
7575
+ const period = options == null ? void 0 : options.period;
7576
+ const marketCategory = options == null ? void 0 : options.marketCategory;
7577
+ const marketGroup = options == null ? void 0 : options.marketGroup;
7224
7578
  const enabled = (_a = options == null ? void 0 : options.enabled) != null ? _a : true;
7225
7579
  const limit = (_b = options == null ? void 0 : options.limit) != null ? _b : 20;
7226
7580
  const sortBy = options == null ? void 0 : options.sortBy;
7227
7581
  const sortDir = options == null ? void 0 : options.sortDir;
7228
- (0, import_react34.useEffect)(() => {
7582
+ const context = options == null ? void 0 : options.context;
7583
+ (0, import_react33.useEffect)(() => {
7229
7584
  if (queryClient) return void 0;
7230
7585
  fallbackQueryClient.mount();
7231
7586
  return () => {
@@ -7245,9 +7600,15 @@ function useVenueMarkets(options) {
7245
7600
  matchStatus != null ? matchStatus : "",
7246
7601
  status != null ? status : "",
7247
7602
  (_c = categoryIds == null ? void 0 : categoryIds.join(",")) != null ? _c : "",
7603
+ (_d = aggKey == null ? void 0 : aggKey.join(",")) != null ? _d : "",
7604
+ (_e = sportsMarketType == null ? void 0 : sportsMarketType.join(",")) != null ? _e : "",
7605
+ (_f = period == null ? void 0 : period.join(",")) != null ? _f : "",
7606
+ (_g = marketCategory == null ? void 0 : marketCategory.join(",")) != null ? _g : "",
7607
+ (_h = marketGroup == null ? void 0 : marketGroup.join(",")) != null ? _h : "",
7248
7608
  limit,
7249
7609
  sortBy != null ? sortBy : "",
7250
- sortDir != null ? sortDir : ""
7610
+ sortDir != null ? sortDir : "",
7611
+ context != null ? context : ""
7251
7612
  ],
7252
7613
  queryFn: (_0) => __async(null, [_0], function* ({ pageParam }) {
7253
7614
  if (!client) {
@@ -7260,10 +7621,16 @@ function useVenueMarkets(options) {
7260
7621
  matchStatus,
7261
7622
  status,
7262
7623
  categoryIds,
7624
+ aggKey,
7625
+ sportsMarketType,
7626
+ period,
7627
+ marketCategory,
7628
+ marketGroup,
7263
7629
  limit,
7264
7630
  cursor: pageParam,
7265
7631
  sortBy,
7266
- sortDir
7632
+ sortDir,
7633
+ context
7267
7634
  });
7268
7635
  return res;
7269
7636
  }),
@@ -7277,7 +7644,7 @@ function useVenueMarkets(options) {
7277
7644
  },
7278
7645
  queryClient != null ? queryClient : fallbackQueryClient
7279
7646
  );
7280
- const markets = (_e = (_d = query.data) == null ? void 0 : _d.pages.flatMap((page) => page.data)) != null ? _e : [];
7647
+ const markets = (_j = (_i = query.data) == null ? void 0 : _i.pages.flatMap((page) => page.data)) != null ? _j : [];
7281
7648
  const hasNextPage = !!query.hasNextPage;
7282
7649
  return __spreadProps(__spreadValues({}, query), {
7283
7650
  markets,
@@ -7289,23 +7656,38 @@ function useVenueMarkets(options) {
7289
7656
  function mergeEventWithFullMarkets(event, fullMarkets) {
7290
7657
  if (fullMarkets.length === 0) return event;
7291
7658
  const fullById = new Map(fullMarkets.map((m) => [m.id, m]));
7292
- const mergedMarkets = event.venueMarkets.map((minimal) => {
7659
+ const ordering = event.venueMarkets.length > 0 ? event.venueMarkets : fullMarkets;
7660
+ const mergedMarkets = ordering.map((minimal) => {
7293
7661
  var _a;
7294
7662
  return (_a = fullById.get(minimal.id)) != null ? _a : minimal;
7295
7663
  });
7296
7664
  return __spreadProps(__spreadValues({}, event), { venueMarkets: mergedMarkets });
7297
7665
  }
7298
7666
  function useEnrichedVenueEvent(options) {
7299
- var _b;
7667
+ var _b, _c;
7300
7668
  const _a = useVenueEvent(options), { event, isLoading, error } = _a, rest = __objRest(_a, ["event", "isLoading", "error"]);
7301
- const { markets, isLoading: isEnriching } = useVenueMarkets({
7669
+ const eventEndedAt = (event == null ? void 0 : event.endDate) && Number.isFinite(Date.parse(event.endDate)) ? Date.parse(event.endDate) : null;
7670
+ const shouldFetchOnlyOpenMarkets = eventEndedAt == null || eventEndedAt >= Date.now();
7671
+ const { markets: openMarkets, isLoading: isEnrichingOpenMarkets } = useVenueMarkets({
7302
7672
  venueEventId: options.eventId,
7303
7673
  enabled: ((_b = options.enabled) != null ? _b : true) && !!event,
7304
- status: "open" /* open */,
7305
- sortBy: "yesPrice",
7306
- sortDir: "desc"
7674
+ status: shouldFetchOnlyOpenMarkets ? "open" /* open */ : void 0
7675
+ // No explicit sortBy: event-scoped /venue-markets sorts by the event's
7676
+ // type-aware order (structureOrderBy). Keeping this in lockstep with
7677
+ // MarketDetailsList preserves the shared React Query cache key and the
7678
+ // event-type ordering.
7307
7679
  });
7308
- const enrichedEvent = (0, import_react35.useMemo)(() => {
7680
+ const shouldFetchAllMarketsFallback = ((_c = options.enabled) != null ? _c : true) && !!event && shouldFetchOnlyOpenMarkets && !isEnrichingOpenMarkets && openMarkets.length === 0;
7681
+ const { markets: fallbackMarkets, isLoading: isEnrichingFallbackMarkets } = useVenueMarkets({
7682
+ venueEventId: options.eventId,
7683
+ enabled: shouldFetchAllMarketsFallback
7684
+ // No status filter on fallback: if an active event temporarily has only
7685
+ // closed/resolved markets, still render the event page instead of the
7686
+ // unavailable state.
7687
+ });
7688
+ const markets = fallbackMarkets.length > 0 ? fallbackMarkets : openMarkets;
7689
+ const isEnriching = isEnrichingOpenMarkets || isEnrichingFallbackMarkets;
7690
+ const enrichedEvent = (0, import_react34.useMemo)(() => {
7309
7691
  if (!event) return void 0;
7310
7692
  if (markets.length === 0) return event;
7311
7693
  return mergeEventWithFullMarkets(event, markets);
@@ -7320,12 +7702,12 @@ function useEnrichedVenueEvent(options) {
7320
7702
 
7321
7703
  // src/use-venue-events.ts
7322
7704
  var import_react_query36 = require("@tanstack/react-query");
7323
- var import_react36 = require("react");
7705
+ var import_react35 = require("react");
7324
7706
  function useVenueEvents(options) {
7325
7707
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
7326
- const client = (0, import_react36.useContext)(AggClientContext);
7327
- const queryClient = (0, import_react36.useContext)(import_react_query36.QueryClientContext);
7328
- const [fallbackQueryClient] = (0, import_react36.useState)(() => new import_react_query36.QueryClient());
7708
+ const client = (0, import_react35.useContext)(AggClientContext);
7709
+ const queryClient = (0, import_react35.useContext)(import_react_query36.QueryClientContext);
7710
+ const [fallbackQueryClient] = (0, import_react35.useState)(() => new import_react_query36.QueryClient());
7329
7711
  const venues = options == null ? void 0 : options.venues;
7330
7712
  const search = options == null ? void 0 : options.search;
7331
7713
  const categoryIds = options == null ? void 0 : options.categoryIds;
@@ -7340,8 +7722,9 @@ function useVenueEvents(options) {
7340
7722
  const minYesPrice = options == null ? void 0 : options.minYesPrice;
7341
7723
  const maxYesPrice = options == null ? void 0 : options.maxYesPrice;
7342
7724
  const endDateFrom = options == null ? void 0 : options.endDateFrom;
7725
+ const grouped = options == null ? void 0 : options.grouped;
7343
7726
  const initialPages = options == null ? void 0 : options.initialPages;
7344
- (0, import_react36.useEffect)(() => {
7727
+ (0, import_react35.useEffect)(() => {
7345
7728
  if (queryClient) return void 0;
7346
7729
  fallbackQueryClient.mount();
7347
7730
  return () => {
@@ -7366,6 +7749,7 @@ function useVenueEvents(options) {
7366
7749
  minYesPrice != null ? minYesPrice : "",
7367
7750
  maxYesPrice != null ? maxYesPrice : "",
7368
7751
  endDateFrom != null ? endDateFrom : "",
7752
+ grouped != null ? grouped : false,
7369
7753
  limit
7370
7754
  ],
7371
7755
  queryFn: (_0) => __async(null, [_0], function* ({ pageParam }) {
@@ -7385,6 +7769,7 @@ function useVenueEvents(options) {
7385
7769
  minYesPrice,
7386
7770
  maxYesPrice,
7387
7771
  endDateFrom,
7772
+ grouped,
7388
7773
  cursor: pageParam
7389
7774
  });
7390
7775
  return res;
@@ -7401,8 +7786,8 @@ function useVenueEvents(options) {
7401
7786
  },
7402
7787
  queryClient != null ? queryClient : fallbackQueryClient
7403
7788
  );
7404
- const prefetchedRef = (0, import_react36.useRef)(false);
7405
- (0, import_react36.useEffect)(() => {
7789
+ const prefetchedRef = (0, import_react35.useRef)(false);
7790
+ (0, import_react35.useEffect)(() => {
7406
7791
  var _a2, _b2;
7407
7792
  if (prefetchedRef.current) return;
7408
7793
  if (!initialPages || initialPages <= 1) return;
@@ -7420,7 +7805,7 @@ function useVenueEvents(options) {
7420
7805
  query.hasNextPage,
7421
7806
  query.fetchNextPage
7422
7807
  ]);
7423
- const events = (0, import_react36.useMemo)(
7808
+ const events = (0, import_react35.useMemo)(
7424
7809
  () => {
7425
7810
  var _a2, _b2;
7426
7811
  return (_b2 = (_a2 = query.data) == null ? void 0 : _a2.pages.flatMap((page) => page.data)) != null ? _b2 : [];
@@ -7538,7 +7923,7 @@ var computePriceGaps = ({
7538
7923
  };
7539
7924
 
7540
7925
  // src/use-viewport-midpoints.ts
7541
- var import_react37 = require("react");
7926
+ var import_react36 = require("react");
7542
7927
  var buildOutcomeMidpointMap = (outcomes) => {
7543
7928
  const m = /* @__PURE__ */ new Map();
7544
7929
  if (!outcomes) return m;
@@ -7591,15 +7976,15 @@ function useViewportMidpoints(visibleMarkets, options) {
7591
7976
  market: { maxMidpointIdsPerRequest: configuredMaxMidpointIdsPerRequest }
7592
7977
  } = useAggUiConfig();
7593
7978
  const maxMidpointIdsPerRequest = (_a = options == null ? void 0 : options.maxMidpointIdsPerRequest) != null ? _a : configuredMaxMidpointIdsPerRequest;
7594
- const [cache, setCache] = (0, import_react37.useState)(() => /* @__PURE__ */ new Map());
7595
- const inFlightRef = (0, import_react37.useRef)(/* @__PURE__ */ new Set());
7596
- const visibleRef = (0, import_react37.useRef)(visibleMarkets);
7979
+ const [cache, setCache] = (0, import_react36.useState)(() => /* @__PURE__ */ new Map());
7980
+ const inFlightRef = (0, import_react36.useRef)(/* @__PURE__ */ new Set());
7981
+ const visibleRef = (0, import_react36.useRef)(visibleMarkets);
7597
7982
  visibleRef.current = visibleMarkets;
7598
- const visibleFp = (0, import_react37.useMemo)(
7983
+ const visibleFp = (0, import_react36.useMemo)(
7599
7984
  () => [...new Set(visibleMarkets.map((m) => m.id))].sort().join("|"),
7600
7985
  [visibleMarkets]
7601
7986
  );
7602
- (0, import_react37.useEffect)(() => {
7987
+ (0, import_react36.useEffect)(() => {
7603
7988
  const toFetch = resolveUncachedVisibleMarketIds(visibleRef.current, cache, inFlightRef.current);
7604
7989
  if (!toFetch.length) return;
7605
7990
  let cancelled = false;
@@ -7623,7 +8008,7 @@ function useViewportMidpoints(visibleMarkets, options) {
7623
8008
  cancelled = true;
7624
8009
  };
7625
8010
  }, [visibleFp, cache, maxMidpointIdsPerRequest]);
7626
- const { prices, venueByOutcomeId } = (0, import_react37.useMemo)(() => {
8011
+ const { prices, venueByOutcomeId } = (0, import_react36.useMemo)(() => {
7627
8012
  var _a2, _b, _c, _d;
7628
8013
  const map = /* @__PURE__ */ new Map();
7629
8014
  const venueMap = /* @__PURE__ */ new Map();
@@ -7656,15 +8041,15 @@ function useViewportMidpoints(visibleMarkets, options) {
7656
8041
  }
7657
8042
 
7658
8043
  // src/use-visible-ids.ts
7659
- var import_react38 = require("react");
8044
+ var import_react37 = require("react");
7660
8045
  function useVisibleIds(options = {}) {
7661
8046
  const { rootMargin = "0px", threshold = 0 } = options;
7662
- const [visibleIds, setVisibleIds] = (0, import_react38.useState)(() => /* @__PURE__ */ new Set());
7663
- const observerRef = (0, import_react38.useRef)(null);
7664
- const elementsRef = (0, import_react38.useRef)(/* @__PURE__ */ new Map());
7665
- const elementIdRef = (0, import_react38.useRef)(/* @__PURE__ */ new WeakMap());
7666
- const callbackRefsRef = (0, import_react38.useRef)(/* @__PURE__ */ new Map());
7667
- (0, import_react38.useEffect)(() => {
8047
+ const [visibleIds, setVisibleIds] = (0, import_react37.useState)(() => /* @__PURE__ */ new Set());
8048
+ const observerRef = (0, import_react37.useRef)(null);
8049
+ const elementsRef = (0, import_react37.useRef)(/* @__PURE__ */ new Map());
8050
+ const elementIdRef = (0, import_react37.useRef)(/* @__PURE__ */ new WeakMap());
8051
+ const callbackRefsRef = (0, import_react37.useRef)(/* @__PURE__ */ new Map());
8052
+ (0, import_react37.useEffect)(() => {
7668
8053
  if (typeof IntersectionObserver === "undefined") return;
7669
8054
  const observer = new IntersectionObserver(
7670
8055
  (entries) => {
@@ -7696,7 +8081,7 @@ function useVisibleIds(options = {}) {
7696
8081
  observerRef.current = null;
7697
8082
  };
7698
8083
  }, [rootMargin, threshold]);
7699
- const register = (0, import_react38.useCallback)((id) => {
8084
+ const register = (0, import_react37.useCallback)((id) => {
7700
8085
  const existing = callbackRefsRef.current.get(id);
7701
8086
  if (existing) return existing;
7702
8087
  const callback = (el) => {
@@ -7898,7 +8283,6 @@ var toAppConfigResult = (query) => {
7898
8283
  useSearch,
7899
8284
  useSmartRoute,
7900
8285
  useSyncBalances,
7901
- useTradableVenues,
7902
8286
  useUserActivity,
7903
8287
  useUserHoldings,
7904
8288
  useVenueEvent,