@agg-build/hooks 2.1.1 → 2.1.3

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
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  useRampQuotes,
3
3
  useRampSession
4
- } from "./chunk-AFZD3GIQ.mjs";
4
+ } from "./chunk-SN4AO5D7.mjs";
5
5
  import {
6
6
  useWithdrawEstimate,
7
7
  useWithdrawFlow,
8
8
  useWithdrawPreview,
9
9
  useWithdrawalLifecycle
10
- } from "./chunk-5P53A3NQ.mjs";
10
+ } from "./chunk-NZEXGOFC.mjs";
11
11
  import {
12
12
  AggAuthContext,
13
13
  AggBalanceProvider,
@@ -95,7 +95,7 @@ import {
95
95
  useSyncBalances,
96
96
  useWithdrawManaged,
97
97
  userActivityQueryKeys
98
- } from "./chunk-FYEPQHKO.mjs";
98
+ } from "./chunk-56RISN73.mjs";
99
99
 
100
100
  // src/index.ts
101
101
  import { QueryClient as QueryClient4, QueryClientProvider, useQueryClient as useQueryClient3 } from "@tanstack/react-query";
@@ -1003,6 +1003,7 @@ function findLivePriceById(livePrices, id) {
1003
1003
  import { useMemo as useMemo7, useRef as useRef3 } from "react";
1004
1004
  import { useQueries as useQueries4 } from "@tanstack/react-query";
1005
1005
  var EMPTY = /* @__PURE__ */ new Map();
1006
+ var EMPTY_CANDIDATES = /* @__PURE__ */ new Map();
1006
1007
  var extractOutcomeBestPrices = (state) => {
1007
1008
  var _a, _b;
1008
1009
  const ob = state == null ? void 0 : state.orderbook;
@@ -1120,6 +1121,175 @@ function mergeBestPricesPreferringLive(rest, live) {
1120
1121
  }
1121
1122
  return merged;
1122
1123
  }
1124
+ var pickSideVenue = (venues, level, side) => {
1125
+ if (venues) {
1126
+ let bestVenue;
1127
+ let bestValue;
1128
+ for (const [venue, info] of Object.entries(venues)) {
1129
+ const value = side === "bid" ? info.bestBid : info.bestAsk;
1130
+ if (value == null) continue;
1131
+ const wins = bestValue == null || (side === "bid" ? value > bestValue : value < bestValue);
1132
+ if (wins) {
1133
+ bestValue = value;
1134
+ bestVenue = venue;
1135
+ }
1136
+ }
1137
+ if (bestVenue != null) return bestVenue;
1138
+ }
1139
+ if (level == null ? void 0 : level.venues) {
1140
+ let bestVenue;
1141
+ let bestSize = -Infinity;
1142
+ for (const [venue, size] of Object.entries(level.venues)) {
1143
+ if (size > bestSize) {
1144
+ bestSize = size;
1145
+ bestVenue = venue;
1146
+ }
1147
+ }
1148
+ if (bestVenue != null) return bestVenue;
1149
+ }
1150
+ return void 0;
1151
+ };
1152
+ var extractOutcomeBestCandidate = (state) => {
1153
+ var _a;
1154
+ const ob = state == null ? void 0 : state.orderbook;
1155
+ if (!ob) return {};
1156
+ const candidate = {};
1157
+ const bidLevel = ob.bids[0];
1158
+ const askLevel = ob.asks[0];
1159
+ if ((bidLevel == null ? void 0 : bidLevel.price) != null) {
1160
+ candidate.bestBid = bidLevel.price;
1161
+ const venue = pickSideVenue(ob.venues, bidLevel, "bid");
1162
+ if (venue) candidate.bestBidVenue = venue;
1163
+ }
1164
+ if ((askLevel == null ? void 0 : askLevel.price) != null) {
1165
+ candidate.bestAsk = askLevel.price;
1166
+ const venue = pickSideVenue(ob.venues, askLevel, "ask");
1167
+ if (venue) candidate.bestAskVenue = venue;
1168
+ }
1169
+ if (ob.midpoint != null) {
1170
+ candidate.midpoint = ob.midpoint;
1171
+ const midVenue = (_a = candidate.bestAskVenue) != null ? _a : candidate.bestBidVenue;
1172
+ if (midVenue) candidate.midpointVenue = midVenue;
1173
+ }
1174
+ if (ob.timestamp != null) candidate.updatedAt = ob.timestamp;
1175
+ return candidate;
1176
+ };
1177
+ function buildLiveBestPriceCandidates(outcomeIds, states, venueMarkets) {
1178
+ var _a, _b, _c;
1179
+ const perOutcome = /* @__PURE__ */ new Map();
1180
+ for (let i = 0; i < outcomeIds.length; i++) {
1181
+ const candidate = extractOutcomeBestCandidate(states[i]);
1182
+ if (candidate.bestBid != null || candidate.bestAsk != null || candidate.midpoint != null) {
1183
+ perOutcome.set(outcomeIds[i], candidate);
1184
+ }
1185
+ }
1186
+ if (perOutcome.size === 0 || !(venueMarkets == null ? void 0 : venueMarkets.length)) {
1187
+ return perOutcome;
1188
+ }
1189
+ const result = new Map(perOutcome);
1190
+ for (const vm of venueMarkets) {
1191
+ for (const outcome of (_a = vm.venueMarketOutcomes) != null ? _a : []) {
1192
+ const refs = (_b = outcome.matchedVenueMarketOutcomes) != null ? _b : [];
1193
+ if (!refs.length) continue;
1194
+ const group = [outcome.id, ...refs.map((ref) => ref.venueMarketOutcomeId)];
1195
+ let groupBestAsk;
1196
+ let groupBestAskVenue;
1197
+ let groupBestBid;
1198
+ let groupBestBidVenue;
1199
+ let groupUpdatedAt;
1200
+ for (const id of group) {
1201
+ const entry = perOutcome.get(id);
1202
+ if (!entry) continue;
1203
+ if (entry.bestAsk != null && (groupBestAsk == null || entry.bestAsk < groupBestAsk)) {
1204
+ groupBestAsk = entry.bestAsk;
1205
+ groupBestAskVenue = entry.bestAskVenue;
1206
+ }
1207
+ if (entry.bestBid != null && (groupBestBid == null || entry.bestBid > groupBestBid)) {
1208
+ groupBestBid = entry.bestBid;
1209
+ groupBestBidVenue = entry.bestBidVenue;
1210
+ }
1211
+ if (entry.updatedAt != null && (groupUpdatedAt == null || entry.updatedAt > groupUpdatedAt)) {
1212
+ groupUpdatedAt = entry.updatedAt;
1213
+ }
1214
+ }
1215
+ if (groupBestAsk == null && groupBestBid == null) continue;
1216
+ for (const id of group) {
1217
+ const prev = (_c = result.get(id)) != null ? _c : {};
1218
+ const next = __spreadValues({}, prev);
1219
+ if (groupBestBid != null) {
1220
+ next.bestBid = groupBestBid;
1221
+ if (groupBestBidVenue) next.bestBidVenue = groupBestBidVenue;
1222
+ }
1223
+ if (groupBestAsk != null) {
1224
+ next.bestAsk = groupBestAsk;
1225
+ if (groupBestAskVenue) next.bestAskVenue = groupBestAskVenue;
1226
+ }
1227
+ if (groupUpdatedAt != null) next.updatedAt = groupUpdatedAt;
1228
+ result.set(id, next);
1229
+ }
1230
+ }
1231
+ }
1232
+ return result;
1233
+ }
1234
+ var buildCandidateFingerprint = (outcomeIds, queries) => {
1235
+ var _a, _b, _c, _d;
1236
+ const parts = [];
1237
+ for (let i = 0; i < outcomeIds.length; i++) {
1238
+ const ob = (_b = (_a = queries[i]) == null ? void 0 : _a.data) == null ? void 0 : _b.orderbook;
1239
+ const bid = (_c = ob == null ? void 0 : ob.bids[0]) == null ? void 0 : _c.price;
1240
+ const ask = (_d = ob == null ? void 0 : ob.asks[0]) == null ? void 0 : _d.price;
1241
+ const mid = ob == null ? void 0 : ob.midpoint;
1242
+ const ts = ob == null ? void 0 : ob.timestamp;
1243
+ const venues = (ob == null ? void 0 : ob.venues) ? Object.keys(ob.venues).sort().join(",") : "";
1244
+ parts.push(`${outcomeIds[i]}:${bid != null ? bid : "_"}:${ask != null ? ask : "_"}:${mid != null ? mid : "_"}:${ts != null ? ts : "_"}:${venues}`);
1245
+ }
1246
+ return parts.join("|");
1247
+ };
1248
+ function useLiveBestPriceCandidates(venueMarkets) {
1249
+ const {
1250
+ features: { enableLiveUpdates }
1251
+ } = useAggUiConfig();
1252
+ const outcomeIds = useMemo7(() => {
1253
+ var _a, _b;
1254
+ if (!(venueMarkets == null ? void 0 : venueMarkets.length)) return [];
1255
+ const ids = /* @__PURE__ */ new Set();
1256
+ for (const vm of venueMarkets) {
1257
+ for (const outcome of (_a = vm.venueMarketOutcomes) != null ? _a : []) {
1258
+ if (outcome.id) ids.add(outcome.id);
1259
+ for (const ref of (_b = outcome.matchedVenueMarketOutcomes) != null ? _b : []) {
1260
+ if (ref.venueMarketOutcomeId) ids.add(ref.venueMarketOutcomeId);
1261
+ }
1262
+ }
1263
+ }
1264
+ return [...ids].sort();
1265
+ }, [venueMarkets]);
1266
+ const queries = useQueries4({
1267
+ queries: outcomeIds.map((id) => ({
1268
+ queryKey: marketDataKeys.live(id),
1269
+ queryFn: () => createMarketLiveState(id),
1270
+ enabled: false,
1271
+ staleTime: Infinity,
1272
+ gcTime: 5 * 6e4,
1273
+ initialData: () => createMarketLiveState(id)
1274
+ }))
1275
+ });
1276
+ const fingerprint = buildCandidateFingerprint(outcomeIds, queries);
1277
+ const prevRef = useRef3({
1278
+ fingerprint: "",
1279
+ result: EMPTY_CANDIDATES
1280
+ });
1281
+ return useMemo7(() => {
1282
+ if (!(venueMarkets == null ? void 0 : venueMarkets.length) || !enableLiveUpdates) return EMPTY_CANDIDATES;
1283
+ if (fingerprint === prevRef.current.fingerprint) return prevRef.current.result;
1284
+ const states = outcomeIds.map((_, i) => {
1285
+ var _a;
1286
+ return (_a = queries[i]) == null ? void 0 : _a.data;
1287
+ });
1288
+ const result = buildLiveBestPriceCandidates(outcomeIds, states, venueMarkets);
1289
+ prevRef.current = { fingerprint, result };
1290
+ return result;
1291
+ }, [venueMarkets, enableLiveUpdates, fingerprint, outcomeIds, queries]);
1292
+ }
1123
1293
 
1124
1294
  // src/use-live-trades.ts
1125
1295
  function useLiveTrades(canonicalMarketId) {
@@ -1364,31 +1534,8 @@ function useMidpoints(venueMarkets, options) {
1364
1534
  };
1365
1535
  }
1366
1536
 
1367
- // src/use-tradable-venues.ts
1368
- import { useMemo as useMemo9 } from "react";
1369
- function useTradableVenues(venueMarkets) {
1370
- const { prices, isLoading } = useMidpoints(venueMarkets);
1371
- const tradableVenues = useMemo9(() => {
1372
- var _a;
1373
- if (isLoading) return null;
1374
- if (!venueMarkets || venueMarkets.length === 0) return /* @__PURE__ */ new Set();
1375
- const set = /* @__PURE__ */ new Set();
1376
- for (const market of venueMarkets) {
1377
- const outcomes = (_a = market.venueMarketOutcomes) != null ? _a : [];
1378
- for (const outcome of outcomes) {
1379
- if (prices.has(outcome.id)) {
1380
- set.add(market.venue);
1381
- break;
1382
- }
1383
- }
1384
- }
1385
- return set;
1386
- }, [venueMarkets, prices, isLoading]);
1387
- return { tradableVenues, isLoading };
1388
- }
1389
-
1390
1537
  // src/use-rolling-chart-window.ts
1391
- import { useEffect as useEffect5, useMemo as useMemo10, useState as useState4 } from "react";
1538
+ import { useEffect as useEffect5, useMemo as useMemo9, useState as useState4 } from "react";
1392
1539
  var RANGE_SECONDS_BY_RANGE = {
1393
1540
  "1H": 60 * 60,
1394
1541
  "6H": 6 * 60 * 60,
@@ -1419,7 +1566,7 @@ var useRollingChartWindow = (options) => {
1419
1566
  var _a;
1420
1567
  const tickMs = (_a = options.tickMs) != null ? _a : 1e3;
1421
1568
  const optionsNowMs = options.nowMs;
1422
- const nowMs = useMemo10(() => optionsNowMs != null ? optionsNowMs : (() => Date.now()), [optionsNowMs]);
1569
+ const nowMs = useMemo9(() => optionsNowMs != null ? optionsNowMs : (() => Date.now()), [optionsNowMs]);
1423
1570
  const [nowSec, setNowSec] = useState4(() => Math.floor(nowMs() / 1e3));
1424
1571
  useEffect5(() => {
1425
1572
  setNowSec(Math.floor(nowMs() / 1e3));
@@ -1428,7 +1575,7 @@ var useRollingChartWindow = (options) => {
1428
1575
  }, tickMs);
1429
1576
  return () => clearInterval(handle);
1430
1577
  }, [tickMs, nowMs]);
1431
- return useMemo10(
1578
+ return useMemo9(
1432
1579
  () => resolveRollingWindow({ range: options.range, nowSec, interval: options.interval }),
1433
1580
  [options.range, options.interval, nowSec]
1434
1581
  );
@@ -1941,7 +2088,130 @@ function useMarketSearch(options) {
1941
2088
 
1942
2089
  // src/use-smart-route.ts
1943
2090
  import { keepPreviousData as keepPreviousData6, useQuery as useQuery6 } from "@tanstack/react-query";
2091
+
2092
+ // src/smart-route-refresh-policy.ts
2093
+ var THIN_SMART_ROUTE_REFETCH_INTERVAL_MS = 5e3;
2094
+ var SMART_ROUTE_REFRESH_DEADLINE_BUFFER_MS = 4e3;
2095
+ var SMART_ROUTE_MIN_REFETCH_INTERVAL_MS = 5e3;
2096
+ var SMART_ROUTE_MAX_REFETCH_INTERVAL_MS = 2e4;
2097
+ var SMART_ROUTE_HIGH_SLIPPAGE_BPS = 75;
2098
+ var SMART_ROUTE_SHALLOW_TOP_LEVEL_RATIO = 0.7;
2099
+ var SMART_ROUTE_DEEP_FILL_LEVEL_COUNT = 3;
2100
+ var LIQUIDITY_CONSTRAINED_STATUSES = /* @__PURE__ */ new Set([
2101
+ "infeasible",
2102
+ "no_orderbooks",
2103
+ "insufficient_depth",
2104
+ "no_bids_above_min_price"
2105
+ ]);
2106
+ 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;
2107
+ var resolveMsUntilIsoTimestamp = (value, nowMs) => {
2108
+ if (!value) return null;
2109
+ const parsedValue = Date.parse(value);
2110
+ if (!Number.isFinite(parsedValue)) return null;
2111
+ return parsedValue - nowMs;
2112
+ };
2113
+ var clampIntervalToRefreshDeadline = ({
2114
+ intervalMs,
2115
+ refreshAt,
2116
+ nowMs
2117
+ }) => {
2118
+ const msUntilRefresh = resolveMsUntilIsoTimestamp(refreshAt, nowMs);
2119
+ if (msUntilRefresh == null || msUntilRefresh <= 0) {
2120
+ return Math.min(
2121
+ SMART_ROUTE_MAX_REFETCH_INTERVAL_MS,
2122
+ Math.max(SMART_ROUTE_MIN_REFETCH_INTERVAL_MS, intervalMs)
2123
+ );
2124
+ }
2125
+ return Math.max(
2126
+ SMART_ROUTE_MIN_REFETCH_INTERVAL_MS,
2127
+ Math.min(SMART_ROUTE_MAX_REFETCH_INTERVAL_MS, intervalMs, Math.floor(msUntilRefresh))
2128
+ );
2129
+ };
2130
+ var assessThinSmartRouteLiquidity = (quote, nowMs = Date.now()) => {
2131
+ var _a, _b;
2132
+ if (!quote) {
2133
+ return {
2134
+ isThin: false,
2135
+ reasons: []
2136
+ };
2137
+ }
2138
+ const reasons = /* @__PURE__ */ new Set();
2139
+ if (LIQUIDITY_CONSTRAINED_STATUSES.has(quote.status)) {
2140
+ reasons.add("liquidity_status");
2141
+ }
2142
+ if (typeof ((_a = quote.slippage) == null ? void 0 : _a.slippageBps) === "number" && Number.isFinite(quote.slippage.slippageBps) && quote.slippage.slippageBps >= SMART_ROUTE_HIGH_SLIPPAGE_BPS) {
2143
+ reasons.add("high_slippage");
2144
+ }
2145
+ const msUntilRefresh = resolveMsUntilIsoTimestamp(quote.refreshAt, nowMs);
2146
+ if (msUntilRefresh != null && msUntilRefresh <= SMART_ROUTE_REFRESH_DEADLINE_BUFFER_MS) {
2147
+ reasons.add("refresh_due_soon");
2148
+ }
2149
+ const hasShallowTopLevel = quote.fills.some((fill) => {
2150
+ var _a2, _b2;
2151
+ if (fill.fills.length <= 1 || fill.venueQty <= 0) return false;
2152
+ const topLevelSize = (_b2 = (_a2 = fill.fills[0]) == null ? void 0 : _a2.size) != null ? _b2 : 0;
2153
+ if (!Number.isFinite(topLevelSize) || topLevelSize <= 0) return false;
2154
+ return topLevelSize / fill.venueQty < SMART_ROUTE_SHALLOW_TOP_LEVEL_RATIO;
2155
+ });
2156
+ if (hasShallowTopLevel) {
2157
+ reasons.add("shallow_top_level");
2158
+ }
2159
+ const hasDeepFillLevels = quote.fills.some(
2160
+ (fill) => fill.fills.length >= SMART_ROUTE_DEEP_FILL_LEVEL_COUNT
2161
+ );
2162
+ if (hasDeepFillLevels) {
2163
+ reasons.add("deep_fill_levels");
2164
+ }
2165
+ const hasThinWarning = ((_b = quote.warnings) != null ? _b : []).some(
2166
+ (warning) => THIN_LIQUIDITY_WARNING_PATTERN.test(warning.reason)
2167
+ );
2168
+ if (hasThinWarning) {
2169
+ reasons.add("warning_signal");
2170
+ }
2171
+ return {
2172
+ isThin: reasons.size > 0,
2173
+ reasons: [...reasons]
2174
+ };
2175
+ };
2176
+ var resolveSmartRouteRefetchInterval = (args, nowMs = Date.now()) => {
2177
+ const {
2178
+ aggressiveIntervalMs = THIN_SMART_ROUTE_REFETCH_INTERVAL_MS,
2179
+ data,
2180
+ defaultIntervalMs,
2181
+ isDocumentVisible,
2182
+ isEditing = false,
2183
+ isInputValid,
2184
+ isMarketOpen,
2185
+ isPanelActive,
2186
+ isSubmitting,
2187
+ queryEnabled
2188
+ } = args;
2189
+ if (defaultIntervalMs <= 0) return false;
2190
+ const isActivelyViewingQuote = isPanelActive || isEditing;
2191
+ if (!queryEnabled || !isInputValid || !isActivelyViewingQuote || !isMarketOpen || isSubmitting || !isDocumentVisible) {
2192
+ return false;
2193
+ }
2194
+ const defaultInterval = clampIntervalToRefreshDeadline({
2195
+ intervalMs: defaultIntervalMs,
2196
+ refreshAt: data == null ? void 0 : data.refreshAt,
2197
+ nowMs
2198
+ });
2199
+ if (!data) return defaultInterval;
2200
+ const thinLiquidity = assessThinSmartRouteLiquidity(data, nowMs);
2201
+ if (!thinLiquidity.isThin) return defaultInterval;
2202
+ return clampIntervalToRefreshDeadline({
2203
+ intervalMs: aggressiveIntervalMs,
2204
+ refreshAt: data.refreshAt,
2205
+ nowMs
2206
+ });
2207
+ };
2208
+
2209
+ // src/use-smart-route.ts
1944
2210
  var SMART_ROUTE_STALE_TIME_MS = 2e4;
2211
+ var getIsDocumentVisible = () => {
2212
+ if (typeof document === "undefined") return true;
2213
+ return document.visibilityState !== "hidden";
2214
+ };
1945
2215
  function useSmartRoute(options) {
1946
2216
  var _a, _b;
1947
2217
  const client = useAggClient();
@@ -1959,9 +2229,12 @@ function useSmartRoute(options) {
1959
2229
  compareVenues,
1960
2230
  deepEstimate,
1961
2231
  enabled = true,
1962
- staleTimeMs = SMART_ROUTE_STALE_TIME_MS
2232
+ staleTimeMs = SMART_ROUTE_STALE_TIME_MS,
2233
+ refreshContext
1963
2234
  } = options;
1964
2235
  const resolvedVenueMarketOutcomeId = (_a = venueMarketOutcomeId != null ? venueMarketOutcomeId : venueMarketId) != null ? _a : outcomeId;
2236
+ const hasValidInput = (maxSpend != null ? maxSpend : 0) > 0 || (sellShares != null ? sellShares : 0) > 0;
2237
+ const queryEnabled = enabled && !!resolvedVenueMarketOutcomeId && hasValidInput;
1965
2238
  const query = useQuery6({
1966
2239
  queryKey: [
1967
2240
  "smart-route",
@@ -1993,11 +2266,25 @@ function useSmartRoute(options) {
1993
2266
  { signal }
1994
2267
  );
1995
2268
  }),
1996
- enabled: enabled && !!resolvedVenueMarketOutcomeId && ((maxSpend != null ? maxSpend : 0) > 0 || (sellShares != null ? sellShares : 0) > 0),
2269
+ enabled: queryEnabled,
1997
2270
  staleTime: staleTimeMs,
1998
- refetchInterval: staleTimeMs > 0 ? staleTimeMs : false,
2271
+ refetchInterval: (queryState) => {
2272
+ var _a2, _b2, _c, _d;
2273
+ return resolveSmartRouteRefetchInterval({
2274
+ data: queryState.state.data,
2275
+ defaultIntervalMs: staleTimeMs,
2276
+ isDocumentVisible: getIsDocumentVisible(),
2277
+ isEditing: (_a2 = refreshContext == null ? void 0 : refreshContext.isEditing) != null ? _a2 : false,
2278
+ isInputValid: hasValidInput,
2279
+ isMarketOpen: (_b2 = refreshContext == null ? void 0 : refreshContext.isMarketOpen) != null ? _b2 : true,
2280
+ isPanelActive: (_c = refreshContext == null ? void 0 : refreshContext.isPanelActive) != null ? _c : true,
2281
+ isSubmitting: (_d = refreshContext == null ? void 0 : refreshContext.isSubmitting) != null ? _d : false,
2282
+ queryEnabled
2283
+ });
2284
+ },
1999
2285
  gcTime: 6e4,
2000
2286
  refetchOnWindowFocus: false,
2287
+ refetchIntervalInBackground: false,
2001
2288
  retry: 1,
2002
2289
  placeholderData: keepPreviousData6
2003
2290
  });
@@ -2052,7 +2339,7 @@ function useUserHoldings(options) {
2052
2339
  }
2053
2340
 
2054
2341
  // src/use-enriched-venue-event.ts
2055
- import { useMemo as useMemo11 } from "react";
2342
+ import { useMemo as useMemo10 } from "react";
2056
2343
 
2057
2344
  // src/use-venue-event.ts
2058
2345
  import { useQuery as useQuery7 } from "@tanstack/react-query";
@@ -2082,7 +2369,7 @@ function useVenueEvent(options) {
2082
2369
  import { QueryClient as QueryClient2, QueryClientContext as QueryClientContext2, useInfiniteQuery as useInfiniteQuery7 } from "@tanstack/react-query";
2083
2370
  import { useContext as useContext3, useEffect as useEffect8, useState as useState8 } from "react";
2084
2371
  function useVenueMarkets(options) {
2085
- var _a, _b, _c, _d, _e;
2372
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
2086
2373
  const client = useContext3(AggClientContext);
2087
2374
  const queryClient = useContext3(QueryClientContext2);
2088
2375
  const [fallbackQueryClient] = useState8(() => new QueryClient2());
@@ -2092,10 +2379,16 @@ function useVenueMarkets(options) {
2092
2379
  const matchStatus = options == null ? void 0 : options.matchStatus;
2093
2380
  const status = options == null ? void 0 : options.status;
2094
2381
  const categoryIds = options == null ? void 0 : options.categoryIds;
2382
+ const aggKey = options == null ? void 0 : options.aggKey;
2383
+ const sportsMarketType = options == null ? void 0 : options.sportsMarketType;
2384
+ const period = options == null ? void 0 : options.period;
2385
+ const marketCategory = options == null ? void 0 : options.marketCategory;
2386
+ const marketGroup = options == null ? void 0 : options.marketGroup;
2095
2387
  const enabled = (_a = options == null ? void 0 : options.enabled) != null ? _a : true;
2096
2388
  const limit = (_b = options == null ? void 0 : options.limit) != null ? _b : 20;
2097
2389
  const sortBy = options == null ? void 0 : options.sortBy;
2098
2390
  const sortDir = options == null ? void 0 : options.sortDir;
2391
+ const context = options == null ? void 0 : options.context;
2099
2392
  useEffect8(() => {
2100
2393
  if (queryClient) return void 0;
2101
2394
  fallbackQueryClient.mount();
@@ -2116,9 +2409,15 @@ function useVenueMarkets(options) {
2116
2409
  matchStatus != null ? matchStatus : "",
2117
2410
  status != null ? status : "",
2118
2411
  (_c = categoryIds == null ? void 0 : categoryIds.join(",")) != null ? _c : "",
2412
+ (_d = aggKey == null ? void 0 : aggKey.join(",")) != null ? _d : "",
2413
+ (_e = sportsMarketType == null ? void 0 : sportsMarketType.join(",")) != null ? _e : "",
2414
+ (_f = period == null ? void 0 : period.join(",")) != null ? _f : "",
2415
+ (_g = marketCategory == null ? void 0 : marketCategory.join(",")) != null ? _g : "",
2416
+ (_h = marketGroup == null ? void 0 : marketGroup.join(",")) != null ? _h : "",
2119
2417
  limit,
2120
2418
  sortBy != null ? sortBy : "",
2121
- sortDir != null ? sortDir : ""
2419
+ sortDir != null ? sortDir : "",
2420
+ context != null ? context : ""
2122
2421
  ],
2123
2422
  queryFn: (_0) => __async(null, [_0], function* ({ pageParam }) {
2124
2423
  if (!client) {
@@ -2131,10 +2430,16 @@ function useVenueMarkets(options) {
2131
2430
  matchStatus,
2132
2431
  status,
2133
2432
  categoryIds,
2433
+ aggKey,
2434
+ sportsMarketType,
2435
+ period,
2436
+ marketCategory,
2437
+ marketGroup,
2134
2438
  limit,
2135
2439
  cursor: pageParam,
2136
2440
  sortBy,
2137
- sortDir
2441
+ sortDir,
2442
+ context
2138
2443
  });
2139
2444
  return res;
2140
2445
  }),
@@ -2148,7 +2453,7 @@ function useVenueMarkets(options) {
2148
2453
  },
2149
2454
  queryClient != null ? queryClient : fallbackQueryClient
2150
2455
  );
2151
- const markets = (_e = (_d = query.data) == null ? void 0 : _d.pages.flatMap((page) => page.data)) != null ? _e : [];
2456
+ const markets = (_j = (_i = query.data) == null ? void 0 : _i.pages.flatMap((page) => page.data)) != null ? _j : [];
2152
2457
  const hasNextPage = !!query.hasNextPage;
2153
2458
  return __spreadProps(__spreadValues({}, query), {
2154
2459
  markets,
@@ -2160,7 +2465,8 @@ function useVenueMarkets(options) {
2160
2465
  function mergeEventWithFullMarkets(event, fullMarkets) {
2161
2466
  if (fullMarkets.length === 0) return event;
2162
2467
  const fullById = new Map(fullMarkets.map((m) => [m.id, m]));
2163
- const mergedMarkets = event.venueMarkets.map((minimal) => {
2468
+ const ordering = event.venueMarkets.length > 0 ? event.venueMarkets : fullMarkets;
2469
+ const mergedMarkets = ordering.map((minimal) => {
2164
2470
  var _a;
2165
2471
  return (_a = fullById.get(minimal.id)) != null ? _a : minimal;
2166
2472
  });
@@ -2169,14 +2475,18 @@ function mergeEventWithFullMarkets(event, fullMarkets) {
2169
2475
  function useEnrichedVenueEvent(options) {
2170
2476
  var _b;
2171
2477
  const _a = useVenueEvent(options), { event, isLoading, error } = _a, rest = __objRest(_a, ["event", "isLoading", "error"]);
2478
+ const eventEndedAt = (event == null ? void 0 : event.endDate) && Number.isFinite(Date.parse(event.endDate)) ? Date.parse(event.endDate) : null;
2479
+ const shouldFetchOnlyOpenMarkets = eventEndedAt == null || eventEndedAt >= Date.now();
2172
2480
  const { markets, isLoading: isEnriching } = useVenueMarkets({
2173
2481
  venueEventId: options.eventId,
2174
2482
  enabled: ((_b = options.enabled) != null ? _b : true) && !!event,
2175
- status: "open" /* open */,
2176
- sortBy: "yesPrice",
2177
- sortDir: "desc"
2483
+ status: shouldFetchOnlyOpenMarkets ? "open" /* open */ : void 0
2484
+ // No explicit sortBy: event-scoped /venue-markets sorts by the event's
2485
+ // type-aware order (structureOrderBy). Keeping this in lockstep with
2486
+ // MarketDetailsList preserves the shared React Query cache key and the
2487
+ // event-type ordering.
2178
2488
  });
2179
- const enrichedEvent = useMemo11(() => {
2489
+ const enrichedEvent = useMemo10(() => {
2180
2490
  if (!event) return void 0;
2181
2491
  if (markets.length === 0) return event;
2182
2492
  return mergeEventWithFullMarkets(event, markets);
@@ -2196,7 +2506,7 @@ import {
2196
2506
  keepPreviousData as keepPreviousData7,
2197
2507
  useInfiniteQuery as useInfiniteQuery8
2198
2508
  } from "@tanstack/react-query";
2199
- import { useContext as useContext4, useEffect as useEffect9, useMemo as useMemo12, useRef as useRef5, useState as useState9 } from "react";
2509
+ import { useContext as useContext4, useEffect as useEffect9, useMemo as useMemo11, useRef as useRef5, useState as useState9 } from "react";
2200
2510
  function useVenueEvents(options) {
2201
2511
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
2202
2512
  const client = useContext4(AggClientContext);
@@ -2216,6 +2526,7 @@ function useVenueEvents(options) {
2216
2526
  const minYesPrice = options == null ? void 0 : options.minYesPrice;
2217
2527
  const maxYesPrice = options == null ? void 0 : options.maxYesPrice;
2218
2528
  const endDateFrom = options == null ? void 0 : options.endDateFrom;
2529
+ const grouped = options == null ? void 0 : options.grouped;
2219
2530
  const initialPages = options == null ? void 0 : options.initialPages;
2220
2531
  useEffect9(() => {
2221
2532
  if (queryClient) return void 0;
@@ -2242,6 +2553,7 @@ function useVenueEvents(options) {
2242
2553
  minYesPrice != null ? minYesPrice : "",
2243
2554
  maxYesPrice != null ? maxYesPrice : "",
2244
2555
  endDateFrom != null ? endDateFrom : "",
2556
+ grouped != null ? grouped : false,
2245
2557
  limit
2246
2558
  ],
2247
2559
  queryFn: (_0) => __async(null, [_0], function* ({ pageParam }) {
@@ -2261,6 +2573,7 @@ function useVenueEvents(options) {
2261
2573
  minYesPrice,
2262
2574
  maxYesPrice,
2263
2575
  endDateFrom,
2576
+ grouped,
2264
2577
  cursor: pageParam
2265
2578
  });
2266
2579
  return res;
@@ -2296,7 +2609,7 @@ function useVenueEvents(options) {
2296
2609
  query.hasNextPage,
2297
2610
  query.fetchNextPage
2298
2611
  ]);
2299
- const events = useMemo12(
2612
+ const events = useMemo11(
2300
2613
  () => {
2301
2614
  var _a2, _b2;
2302
2615
  return (_b2 = (_a2 = query.data) == null ? void 0 : _a2.pages.flatMap((page) => page.data)) != null ? _b2 : [];
@@ -2414,7 +2727,7 @@ var computePriceGaps = ({
2414
2727
  };
2415
2728
 
2416
2729
  // src/use-viewport-midpoints.ts
2417
- import { useEffect as useEffect10, useMemo as useMemo13, useRef as useRef6, useState as useState10 } from "react";
2730
+ import { useEffect as useEffect10, useMemo as useMemo12, useRef as useRef6, useState as useState10 } from "react";
2418
2731
  var buildOutcomeMidpointMap = (outcomes) => {
2419
2732
  const m = /* @__PURE__ */ new Map();
2420
2733
  if (!outcomes) return m;
@@ -2471,7 +2784,7 @@ function useViewportMidpoints(visibleMarkets, options) {
2471
2784
  const inFlightRef = useRef6(/* @__PURE__ */ new Set());
2472
2785
  const visibleRef = useRef6(visibleMarkets);
2473
2786
  visibleRef.current = visibleMarkets;
2474
- const visibleFp = useMemo13(
2787
+ const visibleFp = useMemo12(
2475
2788
  () => [...new Set(visibleMarkets.map((m) => m.id))].sort().join("|"),
2476
2789
  [visibleMarkets]
2477
2790
  );
@@ -2499,7 +2812,7 @@ function useViewportMidpoints(visibleMarkets, options) {
2499
2812
  cancelled = true;
2500
2813
  };
2501
2814
  }, [visibleFp, cache, maxMidpointIdsPerRequest]);
2502
- const { prices, venueByOutcomeId } = useMemo13(() => {
2815
+ const { prices, venueByOutcomeId } = useMemo12(() => {
2503
2816
  var _a2, _b, _c, _d;
2504
2817
  const map = /* @__PURE__ */ new Map();
2505
2818
  const venueMap = /* @__PURE__ */ new Map();
@@ -2667,11 +2980,13 @@ export {
2667
2980
  TradeSide,
2668
2981
  TurnstileChallengeError,
2669
2982
  Venue,
2983
+ buildLiveBestPriceCandidates,
2670
2984
  computeClosedPositionTotals,
2671
2985
  computePriceGaps,
2672
2986
  defaultAggUiConfig,
2673
2987
  defaultAggUiConfig as defaultSdkUiConfig,
2674
2988
  executionKeys,
2989
+ extractOutcomeBestCandidate,
2675
2990
  findLivePriceById,
2676
2991
  getBuilder,
2677
2992
  getDepositAddress,
@@ -2733,6 +3048,7 @@ export {
2733
3048
  useGeoBlock,
2734
3049
  useLabels,
2735
3050
  useLinkAccount,
3051
+ useLiveBestPriceCandidates,
2736
3052
  useLiveBestPrices,
2737
3053
  useLiveCandleOverlay,
2738
3054
  useLiveCandles,
@@ -2770,7 +3086,6 @@ export {
2770
3086
  useSearch,
2771
3087
  useSmartRoute,
2772
3088
  useSyncBalances,
2773
- useTradableVenues,
2774
3089
  useUserActivity,
2775
3090
  useUserHoldings,
2776
3091
  useVenueEvent,