@agg-build/hooks 1.2.12 → 1.3.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.mjs CHANGED
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  useRampQuotes,
3
3
  useRampSession
4
- } from "./chunk-R6VANZRA.mjs";
4
+ } from "./chunk-KXO3JOXF.mjs";
5
5
  import {
6
6
  useWithdrawEstimate,
7
7
  useWithdrawFlow,
8
8
  useWithdrawalLifecycle
9
- } from "./chunk-V34QGQBO.mjs";
9
+ } from "./chunk-OBHXWQ6L.mjs";
10
10
  import {
11
11
  AggAuthContext,
12
12
  AggBalanceProvider,
@@ -43,6 +43,7 @@ import {
43
43
  invalidateBalanceQueries,
44
44
  invalidatePositionQueries,
45
45
  invalidateUserActivityQueries,
46
+ invalidateUserClaimState,
46
47
  invalidateUserMoneyState,
47
48
  marketDataKeys,
48
49
  marketOrderbookDataToResponse,
@@ -93,10 +94,10 @@ import {
93
94
  useSyncBalances,
94
95
  useWithdrawManaged,
95
96
  userActivityQueryKeys
96
- } from "./chunk-2C7JR5OH.mjs";
97
+ } from "./chunk-VLYLQSDD.mjs";
97
98
 
98
99
  // src/index.ts
99
- import { QueryClient as QueryClient4, QueryClientProvider, useQueryClient as useQueryClient2 } from "@tanstack/react-query";
100
+ import { QueryClient as QueryClient4, QueryClientProvider, useQueryClient as useQueryClient3 } from "@tanstack/react-query";
100
101
  import { TurnstileChallengeError } from "@agg-build/sdk";
101
102
 
102
103
  // src/use-geo-block.ts
@@ -119,6 +120,32 @@ function useGeoBlock() {
119
120
  };
120
121
  }
121
122
 
123
+ // src/venue-availability.ts
124
+ var normalizeVenueId = (venueId) => venueId.trim().toLowerCase();
125
+ var getDisabledVenueSet = (disabledVenues) => {
126
+ return new Set((disabledVenues != null ? disabledVenues : []).map(normalizeVenueId));
127
+ };
128
+ var isVenueDisabledByConfig = (venueId, disabledVenues) => {
129
+ return getDisabledVenueSet(disabledVenues).has(normalizeVenueId(venueId));
130
+ };
131
+ var getVisibleVenuesByConfig = (venues, disabledVenues) => {
132
+ const disabledVenueSet = getDisabledVenueSet(disabledVenues);
133
+ return venues.filter((venue) => !disabledVenueSet.has(normalizeVenueId(venue.id)));
134
+ };
135
+ var getVisibleVenueIdsByConfig = (venueIds, disabledVenues) => {
136
+ const disabledVenueSet = getDisabledVenueSet(disabledVenues);
137
+ return venueIds.filter((venueId) => !disabledVenueSet.has(normalizeVenueId(venueId)));
138
+ };
139
+ var getVenueAvailabilityState = ({
140
+ venueId,
141
+ disabledVenues,
142
+ isLocationBlocked
143
+ }) => {
144
+ if (isVenueDisabledByConfig(venueId, disabledVenues)) return "hidden";
145
+ if (isLocationBlocked) return "geoblocked";
146
+ return "available";
147
+ };
148
+
122
149
  // src/use-agg-auth.ts
123
150
  import { useCallback } from "react";
124
151
  function useAggAuth(options = {}) {
@@ -187,7 +214,7 @@ var requestAggAuthChooserOpen = () => {
187
214
  };
188
215
 
189
216
  // src/use-categories.ts
190
- import { useInfiniteQuery } from "@tanstack/react-query";
217
+ import { useInfiniteQuery, useQueries } from "@tanstack/react-query";
191
218
  function useCategories(options) {
192
219
  var _a, _b, _c, _d, _e, _f;
193
220
  const client = useAggClient();
@@ -218,6 +245,41 @@ function useCategories(options) {
218
245
  hasNextPage
219
246
  });
220
247
  }
248
+ function useCategoryChildren(options) {
249
+ var _a, _b, _c, _d;
250
+ const client = useAggClient();
251
+ const queryKeyScope = (_a = options == null ? void 0 : options.queryKeyScope) != null ? _a : "category-children";
252
+ const enabled = (_b = options == null ? void 0 : options.enabled) != null ? _b : true;
253
+ const limit = (_c = options == null ? void 0 : options.limit) != null ? _c : 20;
254
+ const parentIds = Array.from(
255
+ new Set(((_d = options == null ? void 0 : options.parentIds) != null ? _d : []).filter((parentId) => Boolean(parentId)))
256
+ );
257
+ const queries = useQueries({
258
+ queries: parentIds.map((parentId) => ({
259
+ queryKey: [queryKeyScope, "parent", parentId, limit],
260
+ queryFn: () => __async(null, null, function* () {
261
+ return client.getCategories({
262
+ limit,
263
+ cursor: void 0,
264
+ parentId
265
+ });
266
+ }),
267
+ enabled
268
+ }))
269
+ });
270
+ const childrenByParentId = /* @__PURE__ */ new Map();
271
+ queries.forEach((query, index) => {
272
+ var _a2, _b2;
273
+ const parentId = parentIds[index];
274
+ if (!parentId) return;
275
+ childrenByParentId.set(parentId, (_b2 = (_a2 = query.data) == null ? void 0 : _a2.data) != null ? _b2 : []);
276
+ });
277
+ return {
278
+ queries,
279
+ childrenByParentId,
280
+ isLoading: queries.some((query) => query.isLoading)
281
+ };
282
+ }
221
283
 
222
284
  // src/use-debounced-value.ts
223
285
  import { useEffect, useState as useState2 } from "react";
@@ -243,6 +305,7 @@ function useExecutionOrders(options = {}) {
243
305
  status,
244
306
  orderId,
245
307
  quoteId,
308
+ mode,
246
309
  limit = 50,
247
310
  enabled = true,
248
311
  refetchIntervalMs = false
@@ -250,14 +313,22 @@ function useExecutionOrders(options = {}) {
250
313
  const query = useInfiniteQuery2({
251
314
  // quoteId + orderId are part of the cache key — different filters
252
315
  // produce different result sets, so they have to vary the key.
253
- queryKey: ["execution-orders", status != null ? status : "all", quoteId != null ? quoteId : null, orderId != null ? orderId : null, limit],
254
- queryFn: ({ pageParam }) => client.getExecutionOrders({
316
+ queryKey: [
317
+ "execution-orders",
318
+ status != null ? status : "all",
319
+ quoteId != null ? quoteId : null,
320
+ orderId != null ? orderId : null,
321
+ ...mode ? [mode] : [],
322
+ limit
323
+ ],
324
+ queryFn: ({ pageParam }) => client.getExecutionOrders(__spreadProps(__spreadValues({
255
325
  status,
256
326
  orderId,
257
- quoteId,
327
+ quoteId
328
+ }, mode ? { mode } : {}), {
258
329
  limit,
259
330
  cursor: pageParam
260
- }),
331
+ })),
261
332
  initialPageParam: void 0,
262
333
  getNextPageParam: (lastPage) => {
263
334
  var _a2;
@@ -292,6 +363,9 @@ var hasPendingActivity = (pages) => {
292
363
  if (!pages) return false;
293
364
  for (const page of pages) {
294
365
  for (const item of page.data) {
366
+ if (item.type === "redeem" && item.legs.length > 0 && item.legs.every((leg) => leg.status.toLowerCase() === "confirmed")) {
367
+ continue;
368
+ }
295
369
  if (PENDING_ACTIVITY_STATUSES.has(item.status.toLowerCase())) return true;
296
370
  }
297
371
  }
@@ -307,7 +381,7 @@ function useUserActivity(options = {}) {
307
381
  pendingRefetchIntervalMs = DEFAULT_PENDING_REFETCH_INTERVAL_MS
308
382
  } = options;
309
383
  const query = useInfiniteQuery3({
310
- queryKey: ["user-activity", type != null ? type : "all", limit],
384
+ queryKey: userActivityQueryKeys.feed(type, limit),
311
385
  queryFn: ({ pageParam }) => client.getUserActivity({
312
386
  type,
313
387
  limit,
@@ -372,14 +446,15 @@ import { useInfiniteQuery as useInfiniteQuery4 } from "@tanstack/react-query";
372
446
  function useExecutionPositions(options = {}) {
373
447
  var _a, _b;
374
448
  const client = useAggClient();
375
- const { limit = 50, status, enabled = true } = options;
449
+ const { limit = 50, status, mode, enabled = true } = options;
376
450
  const query = useInfiniteQuery4({
377
- queryKey: executionKeys.positions(null, limit, status != null ? status : null),
378
- queryFn: ({ pageParam }) => client.getExecutionPositions({
451
+ queryKey: executionKeys.positions(null, limit, status != null ? status : null, mode != null ? mode : null),
452
+ queryFn: ({ pageParam }) => client.getExecutionPositions(__spreadProps(__spreadValues({
379
453
  limit,
380
- status,
454
+ status
455
+ }, mode ? { mode } : {}), {
381
456
  cursor: pageParam
382
- }),
457
+ })),
383
458
  initialPageParam: void 0,
384
459
  getNextPageParam: (lastPage) => {
385
460
  var _a2;
@@ -403,7 +478,7 @@ import { useMemo as useMemo3 } from "react";
403
478
  import { mergeCandles, mergeClosedCandles } from "@agg-build/sdk";
404
479
 
405
480
  // src/use-market-chart.ts
406
- import { keepPreviousData as keepPreviousData2, useQueries } from "@tanstack/react-query";
481
+ import { keepPreviousData as keepPreviousData2, useQueries as useQueries2 } from "@tanstack/react-query";
407
482
 
408
483
  // src/market-data/subscription.ts
409
484
  import { useEffect as useEffect2, useMemo } from "react";
@@ -488,7 +563,7 @@ function useMarketChart(options) {
488
563
  orderbook: true,
489
564
  trades: true
490
565
  });
491
- const queries = useQueries({
566
+ const queries = useQueries2({
492
567
  queries: outcomeIds.map((outcomeId) => ({
493
568
  // Cache key is intentionally time-free. The rolling window's
494
569
  // startTs/endTs advance on every bucket but the user expects the same
@@ -849,7 +924,7 @@ function useLiveMarket(canonicalMarketId) {
849
924
 
850
925
  // src/use-live-outcome-prices.ts
851
926
  import { useMemo as useMemo6, useRef as useRef2 } from "react";
852
- import { useQueries as useQueries2 } from "@tanstack/react-query";
927
+ import { useQueries as useQueries3 } from "@tanstack/react-query";
853
928
  var EMPTY_PRICES = /* @__PURE__ */ new Map();
854
929
  var buildMidpointFingerprint = (outcomeIds, queries) => {
855
930
  var _a, _b, _c;
@@ -875,7 +950,7 @@ function useLiveOutcomePrices(venueMarkets) {
875
950
  }
876
951
  return [...ids].sort();
877
952
  }, [venueMarkets]);
878
- const queries = useQueries2({
953
+ const queries = useQueries3({
879
954
  queries: outcomeIds.map((id) => ({
880
955
  queryKey: marketDataKeys.live(id),
881
956
  queryFn: () => createMarketLiveState(id),
@@ -925,7 +1000,7 @@ function findLivePriceById(livePrices, id) {
925
1000
 
926
1001
  // src/use-live-best-prices.ts
927
1002
  import { useMemo as useMemo7, useRef as useRef3 } from "react";
928
- import { useQueries as useQueries3 } from "@tanstack/react-query";
1003
+ import { useQueries as useQueries4 } from "@tanstack/react-query";
929
1004
  var EMPTY = /* @__PURE__ */ new Map();
930
1005
  var extractOutcomeBestPrices = (state) => {
931
1006
  var _a, _b;
@@ -967,7 +1042,7 @@ function useLiveBestPrices(venueMarkets) {
967
1042
  }
968
1043
  return [...ids].sort();
969
1044
  }, [venueMarkets]);
970
- const queries = useQueries3({
1045
+ const queries = useQueries4({
971
1046
  queries: outcomeIds.map((id) => ({
972
1047
  queryKey: marketDataKeys.live(id),
973
1048
  queryFn: () => createMarketLiveState(id),
@@ -1354,7 +1429,7 @@ var useRollingChartWindow = (options) => {
1354
1429
  };
1355
1430
 
1356
1431
  // src/use-market-orderbook.ts
1357
- import { useQueries as useQueries4, useQueryClient } from "@tanstack/react-query";
1432
+ import { useQueries as useQueries5, useQueryClient } from "@tanstack/react-query";
1358
1433
  function useMarketOrderbook(options) {
1359
1434
  var _a, _b, _c, _d, _e, _f, _g;
1360
1435
  const queryClient = useQueryClient();
@@ -1374,7 +1449,7 @@ function useMarketOrderbook(options) {
1374
1449
  enabled: enabled && !!selectedOutcomeId,
1375
1450
  orderbook: true
1376
1451
  });
1377
- const liveQueries = useQueries4({
1452
+ const liveQueries = useQueries5({
1378
1453
  queries: subscriptionIds.map((subscriptionId) => ({
1379
1454
  queryKey: marketDataKeys.live(subscriptionId),
1380
1455
  queryFn: () => createMarketLiveState(subscriptionId),
@@ -1439,6 +1514,64 @@ function useMarketOrderbook(options) {
1439
1514
  };
1440
1515
  }
1441
1516
 
1517
+ // src/use-arb.ts
1518
+ import { useEffect as useEffect6, useRef as useRef4, useState as useState5 } from "react";
1519
+ function useMarketArb(marketId) {
1520
+ const ws = useAggWebSocket();
1521
+ const [state, setState] = useState5({ arbReturn: null, isLive: false });
1522
+ useEffect6(() => {
1523
+ if (!ws || !marketId) return;
1524
+ const cached = ws.getArb(marketId);
1525
+ if (cached != null) {
1526
+ setState({ arbReturn: cached.arbReturn, isLive: true });
1527
+ }
1528
+ const off = ws.subscribeArb(marketId, (msg) => {
1529
+ setState({ arbReturn: msg.arbReturn, isLive: true });
1530
+ });
1531
+ return off;
1532
+ }, [ws, marketId]);
1533
+ return state;
1534
+ }
1535
+ var EMPTY_ARB_FEED = {
1536
+ byMarket: /* @__PURE__ */ new Map(),
1537
+ byEvent: /* @__PURE__ */ new Map()
1538
+ };
1539
+ function useArbFeed() {
1540
+ const ws = useAggWebSocket();
1541
+ const [state, setState] = useState5(EMPTY_ARB_FEED);
1542
+ const stateRef = useRef4(state);
1543
+ stateRef.current = state;
1544
+ useEffect6(() => {
1545
+ if (!ws) return;
1546
+ const off = ws.subscribeArbFeed((batch) => {
1547
+ setState((prev) => {
1548
+ const nextByMarket = new Map(prev.byMarket);
1549
+ for (const entry of batch.entries) {
1550
+ nextByMarket.set(entry.marketId, {
1551
+ arb: entry.arbReturn,
1552
+ eventId: entry.venueEventId
1553
+ });
1554
+ }
1555
+ const nextByEvent = /* @__PURE__ */ new Map();
1556
+ for (const { arb, eventId } of nextByMarket.values()) {
1557
+ if (eventId == null) continue;
1558
+ const current = nextByEvent.get(eventId);
1559
+ if (current == null || arb > current) {
1560
+ nextByEvent.set(eventId, arb);
1561
+ }
1562
+ }
1563
+ return { byMarket: nextByMarket, byEvent: nextByEvent };
1564
+ });
1565
+ });
1566
+ return off;
1567
+ }, [ws]);
1568
+ const publicByMarket = /* @__PURE__ */ new Map();
1569
+ for (const [marketId, { arb }] of state.byMarket) {
1570
+ publicByMarket.set(marketId, arb);
1571
+ }
1572
+ return { byMarket: publicByMarket, byEvent: state.byEvent };
1573
+ }
1574
+
1442
1575
  // src/use-order-book.ts
1443
1576
  import { keepPreviousData as keepPreviousData3, useQuery as useQuery3 } from "@tanstack/react-query";
1444
1577
  function useOrderBook(options) {
@@ -1653,15 +1786,15 @@ import {
1653
1786
  keepPreviousData as keepPreviousData5,
1654
1787
  useInfiniteQuery as useInfiniteQuery5
1655
1788
  } from "@tanstack/react-query";
1656
- import { useContext as useContext2, useEffect as useEffect6, useState as useState5 } from "react";
1789
+ import { useContext as useContext2, useEffect as useEffect7, useState as useState6 } from "react";
1657
1790
  function useSearch(options) {
1658
1791
  var _a, _b, _c;
1659
1792
  const client = useContext2(AggClientContext);
1660
1793
  const queryClient = useContext2(QueryClientContext);
1661
- const [fallbackQueryClient] = useState5(() => new QueryClient());
1794
+ const [fallbackQueryClient] = useState6(() => new QueryClient());
1662
1795
  const { q, type, categoryIds, limit = 20, enabled = true, deep = false } = options;
1663
1796
  const isEnabled = enabled && q.length > 0;
1664
- useEffect6(() => {
1797
+ useEffect7(() => {
1665
1798
  if (queryClient) return void 0;
1666
1799
  fallbackQueryClient.mount();
1667
1800
  return () => {
@@ -1715,7 +1848,7 @@ function useSearch(options) {
1715
1848
  }
1716
1849
 
1717
1850
  // src/use-market-search.ts
1718
- import { useCallback as useCallback5, useState as useState6 } from "react";
1851
+ import { useCallback as useCallback5, useState as useState7 } from "react";
1719
1852
  function useMarketSearch(options) {
1720
1853
  var _a;
1721
1854
  const {
@@ -1726,8 +1859,8 @@ function useMarketSearch(options) {
1726
1859
  enableSuggestions = true,
1727
1860
  minLength = 1
1728
1861
  } = options;
1729
- const [query, setQueryState] = useState6("");
1730
- const [submittedQuery, setSubmittedQuery] = useState6(null);
1862
+ const [query, setQueryState] = useState7("");
1863
+ const [submittedQuery, setSubmittedQuery] = useState7(null);
1731
1864
  const debouncedQuery = useDebouncedValue(query, debounceMs);
1732
1865
  const trimmedDebounced = debouncedQuery.trim();
1733
1866
  const suggestionsEnabled = enableSuggestions && trimmedDebounced.length >= minLength;
@@ -1812,6 +1945,7 @@ function useSmartRoute(options) {
1812
1945
  outcomeId,
1813
1946
  side,
1814
1947
  tradeSide,
1948
+ mode,
1815
1949
  maxSpend,
1816
1950
  sellShares,
1817
1951
  chainBalances,
@@ -1828,6 +1962,7 @@ function useSmartRoute(options) {
1828
1962
  resolvedVenueMarketOutcomeId,
1829
1963
  side != null ? side : null,
1830
1964
  tradeSide != null ? tradeSide : null,
1965
+ ...mode ? [mode] : [],
1831
1966
  maxSpend != null ? maxSpend : null,
1832
1967
  sellShares != null ? sellShares : null,
1833
1968
  chainBalances ? JSON.stringify(chainBalances) : null,
@@ -1837,17 +1972,18 @@ function useSmartRoute(options) {
1837
1972
  ],
1838
1973
  queryFn: (_0) => __async(null, [_0], function* ({ signal }) {
1839
1974
  return client.getSmartRoute(
1840
- {
1975
+ __spreadProps(__spreadValues({
1841
1976
  venueMarketOutcomeId: resolvedVenueMarketOutcomeId,
1842
1977
  side: side != null ? side : void 0,
1843
- tradeSide: tradeSide != null ? tradeSide : void 0,
1978
+ tradeSide: tradeSide != null ? tradeSide : void 0
1979
+ }, mode ? { mode } : {}), {
1844
1980
  maxSpend,
1845
1981
  sellShares,
1846
1982
  chainBalances,
1847
1983
  slipCapBps,
1848
1984
  compareVenues,
1849
1985
  deepEstimate
1850
- },
1986
+ }),
1851
1987
  { signal }
1852
1988
  );
1853
1989
  }),
@@ -1929,12 +2065,12 @@ function useVenueEvent(options) {
1929
2065
 
1930
2066
  // src/use-venue-markets.ts
1931
2067
  import { QueryClient as QueryClient2, QueryClientContext as QueryClientContext2, useInfiniteQuery as useInfiniteQuery7 } from "@tanstack/react-query";
1932
- import { useContext as useContext3, useEffect as useEffect7, useState as useState7 } from "react";
2068
+ import { useContext as useContext3, useEffect as useEffect8, useState as useState8 } from "react";
1933
2069
  function useVenueMarkets(options) {
1934
2070
  var _a, _b, _c, _d, _e;
1935
2071
  const client = useContext3(AggClientContext);
1936
2072
  const queryClient = useContext3(QueryClientContext2);
1937
- const [fallbackQueryClient] = useState7(() => new QueryClient2());
2073
+ const [fallbackQueryClient] = useState8(() => new QueryClient2());
1938
2074
  const venue = options == null ? void 0 : options.venue;
1939
2075
  const venueEventId = options == null ? void 0 : options.venueEventId;
1940
2076
  const search = options == null ? void 0 : options.search;
@@ -1945,7 +2081,7 @@ function useVenueMarkets(options) {
1945
2081
  const limit = (_b = options == null ? void 0 : options.limit) != null ? _b : 20;
1946
2082
  const sortBy = options == null ? void 0 : options.sortBy;
1947
2083
  const sortDir = options == null ? void 0 : options.sortDir;
1948
- useEffect7(() => {
2084
+ useEffect8(() => {
1949
2085
  if (queryClient) return void 0;
1950
2086
  fallbackQueryClient.mount();
1951
2087
  return () => {
@@ -2045,12 +2181,12 @@ import {
2045
2181
  keepPreviousData as keepPreviousData7,
2046
2182
  useInfiniteQuery as useInfiniteQuery8
2047
2183
  } from "@tanstack/react-query";
2048
- import { useContext as useContext4, useEffect as useEffect8, useMemo as useMemo12, useRef as useRef4, useState as useState8 } from "react";
2184
+ import { useContext as useContext4, useEffect as useEffect9, useMemo as useMemo12, useRef as useRef5, useState as useState9 } from "react";
2049
2185
  function useVenueEvents(options) {
2050
2186
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
2051
2187
  const client = useContext4(AggClientContext);
2052
2188
  const queryClient = useContext4(QueryClientContext3);
2053
- const [fallbackQueryClient] = useState8(() => new QueryClient3());
2189
+ const [fallbackQueryClient] = useState9(() => new QueryClient3());
2054
2190
  const venues = options == null ? void 0 : options.venues;
2055
2191
  const search = options == null ? void 0 : options.search;
2056
2192
  const categoryIds = options == null ? void 0 : options.categoryIds;
@@ -2066,7 +2202,7 @@ function useVenueEvents(options) {
2066
2202
  const maxYesPrice = options == null ? void 0 : options.maxYesPrice;
2067
2203
  const endDateFrom = options == null ? void 0 : options.endDateFrom;
2068
2204
  const initialPages = options == null ? void 0 : options.initialPages;
2069
- useEffect8(() => {
2205
+ useEffect9(() => {
2070
2206
  if (queryClient) return void 0;
2071
2207
  fallbackQueryClient.mount();
2072
2208
  return () => {
@@ -2126,8 +2262,8 @@ function useVenueEvents(options) {
2126
2262
  },
2127
2263
  queryClient != null ? queryClient : fallbackQueryClient
2128
2264
  );
2129
- const prefetchedRef = useRef4(false);
2130
- useEffect8(() => {
2265
+ const prefetchedRef = useRef5(false);
2266
+ useEffect9(() => {
2131
2267
  var _a2, _b2;
2132
2268
  if (prefetchedRef.current) return;
2133
2269
  if (!initialPages || initialPages <= 1) return;
@@ -2231,29 +2367,52 @@ function useVenueMarketMidpoints(options) {
2231
2367
 
2232
2368
  // src/utils/compute-price-gaps.ts
2233
2369
  var MIN_PRICE_GAP_PCT = 3;
2234
- function computePriceGaps(input) {
2370
+ var MAX_PRICE_GAP_PCT = 50;
2371
+ var normalizeMidpoint = (value) => {
2372
+ if (typeof value !== "number" || !Number.isFinite(value)) return void 0;
2373
+ if (value <= 0) return void 0;
2374
+ if (value > 1) return void 0;
2375
+ return value;
2376
+ };
2377
+ var collectMarketMidpoints = (market, midpointsByVenueMarketId) => {
2235
2378
  var _a;
2236
- const { markets, midpointsByVenueMarketId } = input;
2237
- const result = /* @__PURE__ */ new Map();
2379
+ const midpoints = [];
2380
+ const marketMidpoint = normalizeMidpoint(midpointsByVenueMarketId.get(market.id));
2381
+ if (marketMidpoint != null) {
2382
+ midpoints.push(marketMidpoint);
2383
+ }
2384
+ for (const matchedMarket of (_a = market.matchedVenueMarkets) != null ? _a : []) {
2385
+ const matchedMidpoint = normalizeMidpoint(midpointsByVenueMarketId.get(matchedMarket.id));
2386
+ if (matchedMidpoint == null) continue;
2387
+ midpoints.push(matchedMidpoint);
2388
+ }
2389
+ return midpoints;
2390
+ };
2391
+ var computePriceGapPct = (midpoints) => {
2392
+ if (midpoints.length < 2) return void 0;
2393
+ const minMidpoint = Math.min(...midpoints);
2394
+ const maxMidpoint = Math.max(...midpoints);
2395
+ if (minMidpoint <= 0 || maxMidpoint <= minMidpoint) return void 0;
2396
+ const gapPct = (maxMidpoint - minMidpoint) * 100;
2397
+ if (gapPct < MIN_PRICE_GAP_PCT) return void 0;
2398
+ if (gapPct > MAX_PRICE_GAP_PCT) return void 0;
2399
+ return gapPct;
2400
+ };
2401
+ var computePriceGaps = ({
2402
+ markets,
2403
+ midpointsByVenueMarketId
2404
+ }) => {
2405
+ const gapsByVenueMarketId = /* @__PURE__ */ new Map();
2238
2406
  for (const market of markets) {
2239
- const ownMidpoint = midpointsByVenueMarketId.get(market.id);
2240
- if (ownMidpoint == null || ownMidpoint <= 0) continue;
2241
- const siblings = (_a = market.matchedVenueMarkets) != null ? _a : [];
2242
- if (siblings.length === 0) continue;
2243
- let maxGap = 0;
2244
- for (const sibling of siblings) {
2245
- const siblingMidpoint = midpointsByVenueMarketId.get(sibling.id);
2246
- if (siblingMidpoint == null || siblingMidpoint <= 0) continue;
2247
- const gap = Math.abs(ownMidpoint - siblingMidpoint) / ownMidpoint * 100;
2248
- if (gap > maxGap) maxGap = gap;
2249
- }
2250
- if (maxGap >= MIN_PRICE_GAP_PCT) result.set(market.id, maxGap);
2407
+ const gapPct = computePriceGapPct(collectMarketMidpoints(market, midpointsByVenueMarketId));
2408
+ if (gapPct == null) continue;
2409
+ gapsByVenueMarketId.set(market.id, gapPct);
2251
2410
  }
2252
- return result;
2253
- }
2411
+ return gapsByVenueMarketId;
2412
+ };
2254
2413
 
2255
2414
  // src/use-viewport-midpoints.ts
2256
- import { useEffect as useEffect9, useMemo as useMemo13, useRef as useRef5, useState as useState9 } from "react";
2415
+ import { useEffect as useEffect10, useMemo as useMemo13, useRef as useRef6, useState as useState10 } from "react";
2257
2416
  var buildOutcomeMidpointMap = (outcomes) => {
2258
2417
  const m = /* @__PURE__ */ new Map();
2259
2418
  if (!outcomes) return m;
@@ -2301,15 +2460,15 @@ var buildCachedMidpointEntries = (requestedVenueMarketIds, rows) => {
2301
2460
  };
2302
2461
  function useViewportMidpoints(visibleMarkets) {
2303
2462
  const client = useAggClient();
2304
- const [cache, setCache] = useState9(() => /* @__PURE__ */ new Map());
2305
- const inFlightRef = useRef5(/* @__PURE__ */ new Set());
2306
- const visibleRef = useRef5(visibleMarkets);
2463
+ const [cache, setCache] = useState10(() => /* @__PURE__ */ new Map());
2464
+ const inFlightRef = useRef6(/* @__PURE__ */ new Set());
2465
+ const visibleRef = useRef6(visibleMarkets);
2307
2466
  visibleRef.current = visibleMarkets;
2308
2467
  const visibleFp = useMemo13(
2309
2468
  () => [...new Set(visibleMarkets.map((m) => m.id))].sort().join("|"),
2310
2469
  [visibleMarkets]
2311
2470
  );
2312
- useEffect9(() => {
2471
+ useEffect10(() => {
2313
2472
  const toFetch = resolveUncachedVisibleMarketIds(visibleRef.current, cache, inFlightRef.current);
2314
2473
  if (!toFetch.length) return;
2315
2474
  let cancelled = false;
@@ -2366,15 +2525,15 @@ function useViewportMidpoints(visibleMarkets) {
2366
2525
  }
2367
2526
 
2368
2527
  // src/use-visible-ids.ts
2369
- import { useCallback as useCallback6, useEffect as useEffect10, useRef as useRef6, useState as useState10 } from "react";
2528
+ import { useCallback as useCallback6, useEffect as useEffect11, useRef as useRef7, useState as useState11 } from "react";
2370
2529
  function useVisibleIds(options = {}) {
2371
2530
  const { rootMargin = "0px", threshold = 0 } = options;
2372
- const [visibleIds, setVisibleIds] = useState10(() => /* @__PURE__ */ new Set());
2373
- const observerRef = useRef6(null);
2374
- const elementsRef = useRef6(/* @__PURE__ */ new Map());
2375
- const elementIdRef = useRef6(/* @__PURE__ */ new WeakMap());
2376
- const callbackRefsRef = useRef6(/* @__PURE__ */ new Map());
2377
- useEffect10(() => {
2531
+ const [visibleIds, setVisibleIds] = useState11(() => /* @__PURE__ */ new Set());
2532
+ const observerRef = useRef7(null);
2533
+ const elementsRef = useRef7(/* @__PURE__ */ new Map());
2534
+ const elementIdRef = useRef7(/* @__PURE__ */ new WeakMap());
2535
+ const callbackRefsRef = useRef7(/* @__PURE__ */ new Map());
2536
+ useEffect11(() => {
2378
2537
  if (typeof IntersectionObserver === "undefined") return;
2379
2538
  const observer = new IntersectionObserver(
2380
2539
  (entries) => {
@@ -2439,16 +2598,38 @@ function useVisibleIds(options = {}) {
2439
2598
  }
2440
2599
 
2441
2600
  // src/use-app-config.ts
2442
- import { useQuery as useQuery9 } from "@tanstack/react-query";
2601
+ import { useQuery as useQuery9, useQueryClient as useQueryClient2 } from "@tanstack/react-query";
2443
2602
  var FIVE_MINUTES = 5 * 60 * 1e3;
2603
+ var APP_CONFIG_QUERY_KEY = ["agg", "app-config"];
2444
2604
  function useAppConfig() {
2445
- var _a, _b, _c, _d, _e, _f, _g, _h;
2446
2605
  const client = useAggClient();
2447
2606
  const query = useQuery9({
2448
- queryKey: ["agg", "app-config"],
2607
+ queryKey: APP_CONFIG_QUERY_KEY,
2449
2608
  queryFn: () => client.getAppConfig(),
2450
2609
  staleTime: FIVE_MINUTES
2451
2610
  });
2611
+ return toAppConfigResult({
2612
+ data: query.data,
2613
+ isLoading: query.isLoading,
2614
+ error: query.error
2615
+ });
2616
+ }
2617
+ function useCachedAppConfig() {
2618
+ const queryClient = useQueryClient2();
2619
+ const query = useQuery9({
2620
+ queryKey: APP_CONFIG_QUERY_KEY,
2621
+ enabled: false,
2622
+ initialData: () => queryClient.getQueryData(APP_CONFIG_QUERY_KEY),
2623
+ staleTime: FIVE_MINUTES
2624
+ });
2625
+ return toAppConfigResult({
2626
+ data: query.data,
2627
+ isLoading: query.isLoading,
2628
+ error: query.error
2629
+ });
2630
+ }
2631
+ var toAppConfigResult = (query) => {
2632
+ var _a, _b, _c, _d, _e, _f, _g, _h;
2452
2633
  return {
2453
2634
  disabledVenues: (_b = (_a = query.data) == null ? void 0 : _a.disabledVenues) != null ? _b : [],
2454
2635
  disabledCategoryPresets: (_d = (_c = query.data) == null ? void 0 : _c.disabledCategoryPresets) != null ? _d : [],
@@ -2457,7 +2638,7 @@ function useAppConfig() {
2457
2638
  isLoading: query.isLoading,
2458
2639
  error: query.error
2459
2640
  };
2460
- }
2641
+ };
2461
2642
  export {
2462
2643
  AUTH_CHOOSER_OPEN_EVENT,
2463
2644
  AggBalanceProvider,
@@ -2468,6 +2649,8 @@ export {
2468
2649
  CONFIRMED_MATCH_STATUSES,
2469
2650
  DEFAULT_AGG_ROOT_CLASS_NAME,
2470
2651
  EventListStateProvider,
2652
+ MAX_PRICE_GAP_PCT,
2653
+ MIN_PRICE_GAP_PCT,
2471
2654
  MarketStatus,
2472
2655
  MatchStatus,
2473
2656
  MatchType,
@@ -2486,12 +2669,18 @@ export {
2486
2669
  getBuilder,
2487
2670
  getDepositAddress,
2488
2671
  getOrCreateBuilder,
2672
+ getVenueAvailabilityState,
2673
+ getVisibleVenueIdsByConfig,
2674
+ getVisibleVenuesByConfig,
2489
2675
  getWalletAddressFromUserProfile,
2490
2676
  invalidateBalanceQueries,
2491
2677
  invalidatePositionQueries,
2492
2678
  invalidateUserActivityQueries,
2679
+ invalidateUserClaimState,
2493
2680
  invalidateUserMoneyState,
2681
+ isVenueDisabledByConfig,
2494
2682
  mergeBestPricesPreferringLive,
2683
+ normalizeVenueId,
2495
2684
  optimizedImageUrl,
2496
2685
  parseEmail,
2497
2686
  parseEmailStrict,
@@ -2519,7 +2708,10 @@ export {
2519
2708
  useAggUiConfig,
2520
2709
  useAggWebSocket,
2521
2710
  useAppConfig,
2711
+ useArbFeed,
2712
+ useCachedAppConfig,
2522
2713
  useCategories,
2714
+ useCategoryChildren,
2523
2715
  useDebouncedValue,
2524
2716
  useDepositAddresses,
2525
2717
  useEnrichedVenueEvent,
@@ -2542,6 +2734,7 @@ export {
2542
2734
  useLiveOutcomePrices,
2543
2735
  useLiveTrades,
2544
2736
  useManagedBalances,
2737
+ useMarketArb,
2545
2738
  useMarketChart,
2546
2739
  useMarketOrderbook,
2547
2740
  useMarketSearch,
@@ -2556,7 +2749,7 @@ export {
2556
2749
  useOrderbookQuote,
2557
2750
  useOrders,
2558
2751
  usePositions,
2559
- useQueryClient2 as useQueryClient,
2752
+ useQueryClient3 as useQueryClient,
2560
2753
  useQuoteManaged,
2561
2754
  useRampQuotes,
2562
2755
  useRampSession,