@agg-build/hooks 2.1.0 → 2.1.2

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
@@ -90,11 +90,13 @@ __export(src_exports, {
90
90
  TradeSide: () => TradeSide,
91
91
  TurnstileChallengeError: () => import_sdk4.TurnstileChallengeError,
92
92
  Venue: () => Venue,
93
+ buildLiveBestPriceCandidates: () => buildLiveBestPriceCandidates,
93
94
  computeClosedPositionTotals: () => computeClosedPositionTotals,
94
95
  computePriceGaps: () => computePriceGaps,
95
96
  defaultAggUiConfig: () => defaultAggUiConfig,
96
97
  defaultSdkUiConfig: () => defaultAggUiConfig,
97
98
  executionKeys: () => executionKeys,
99
+ extractOutcomeBestCandidate: () => extractOutcomeBestCandidate,
98
100
  findLivePriceById: () => findLivePriceById,
99
101
  getBuilder: () => getBuilder,
100
102
  getDepositAddress: () => getDepositAddress,
@@ -156,6 +158,7 @@ __export(src_exports, {
156
158
  useGeoBlock: () => useGeoBlock,
157
159
  useLabels: () => useLabels,
158
160
  useLinkAccount: () => useLinkAccount,
161
+ useLiveBestPriceCandidates: () => useLiveBestPriceCandidates,
159
162
  useLiveBestPrices: () => useLiveBestPrices,
160
163
  useLiveCandleOverlay: () => useLiveCandleOverlay,
161
164
  useLiveCandles: () => useLiveCandles,
@@ -783,6 +786,13 @@ var enUsLabels = {
783
786
  categoryTabsAria: "Home page category tabs"
784
787
  },
785
788
  userProfile: {
789
+ balance: {
790
+ availableBalance: "Available Balance",
791
+ balanceByNetwork: "Balance by network",
792
+ paperModeNetwork: "Paper",
793
+ paperModeWarning: "Paper mode is enabled. These are simulated funds for paper trading.",
794
+ networkTooltipDescription: "Funds are stored across networks. We handle routing automatically, but keeping funds on the right network enables faster trades and lower fees. When depositing, you can choose your preferred network."
795
+ },
786
796
  activity: {
787
797
  depositType: "Deposit",
788
798
  redeemType: "Claim",
@@ -1148,6 +1158,7 @@ var enUsLabels = {
1148
1158
  orderSkip: "Skip",
1149
1159
  orderRetryRemaining: "Retry remaining",
1150
1160
  resolvedEarningsTitle: "Your Earnings",
1161
+ resolvedResolutionDateLabel: "Resolution date",
1151
1162
  resolvedSharesLabel: "Shares",
1152
1163
  resolvedTotalPayoutLabel: "Total payout",
1153
1164
  claimWinnings: "Claim Winnings",
@@ -1467,7 +1478,10 @@ var defaultAggUiConfig = {
1467
1478
  }
1468
1479
  },
1469
1480
  formatting: defaultFormatters,
1470
- search: defaultAggUiSearchConfig
1481
+ search: defaultAggUiSearchConfig,
1482
+ trading: {
1483
+ executionMode: "live"
1484
+ }
1471
1485
  };
1472
1486
  var mergeAggUiSearchConfig = (config) => {
1473
1487
  var _a, _b, _c;
@@ -1482,7 +1496,7 @@ var mergeAggUiSearchConfig = (config) => {
1482
1496
  };
1483
1497
  };
1484
1498
  var mergeAggUiConfig = (persisted, config) => {
1485
- 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;
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;
1486
1500
  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;
1487
1501
  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;
1488
1502
  const formatters = createFormatters(locale);
@@ -1523,6 +1537,9 @@ var mergeAggUiConfig = (persisted, config) => {
1523
1537
  formatDate: (_V = (_U = config == null ? void 0 : config.formatting) == null ? void 0 : _U.formatDate) != null ? _V : formatters.formatDate
1524
1538
  },
1525
1539
  search: mergeAggUiSearchConfig(config == null ? void 0 : config.search),
1540
+ trading: {
1541
+ executionMode: (_X = (_W = config == null ? void 0 : config.trading) == null ? void 0 : _W.executionMode) != null ? _X : defaultAggUiConfig.trading.executionMode
1542
+ },
1526
1543
  walletActions: config == null ? void 0 : config.walletActions,
1527
1544
  solanaRpcUrl: config == null ? void 0 : config.solanaRpcUrl
1528
1545
  };
@@ -1797,7 +1814,7 @@ var balanceQueryKeys = {
1797
1814
  execution: () => executionKeys.balances(),
1798
1815
  // Kept as an alias for backward compatibility with existing callers.
1799
1816
  // The balance provider now uses the same canonical execution balances key.
1800
- provider: () => executionKeys.balances(),
1817
+ provider: (mode) => executionKeys.balances(mode),
1801
1818
  venue: (venuesKey) => ["venue-balances", venuesKey],
1802
1819
  venuePrefix: () => ["venue-balances"]
1803
1820
  };
@@ -1871,6 +1888,7 @@ var invalidateUserClaimState = (queryClient, options) => {
1871
1888
  // src/core/providers/balance-provider.tsx
1872
1889
  var import_jsx_runtime2 = require("react/jsx-runtime");
1873
1890
  var CHAIN_LABELS = {
1891
+ 0: "Paper",
1874
1892
  1: "Ethereum",
1875
1893
  10: "Optimism",
1876
1894
  56: "BNB",
@@ -1902,17 +1920,23 @@ var EMPTY_MANAGED_BALANCES = {
1902
1920
  function AggBalanceProvider({ children }) {
1903
1921
  const client = (0, import_react3.useContext)(AggClientContext);
1904
1922
  const authContext = (0, import_react3.useContext)(AggAuthContext);
1923
+ const {
1924
+ trading: { executionMode }
1925
+ } = (0, import_react3.useContext)(AggUiContext);
1905
1926
  if (!authContext) {
1906
1927
  throw new Error("AggBalanceProvider must be used within an <AggAuthProvider>");
1907
1928
  }
1908
1929
  const { isAuthenticated } = authContext;
1930
+ const queryExecutionMode = executionMode === "paper" ? "paper" : void 0;
1909
1931
  const balancesQuery = (0, import_react_query2.useQuery)({
1910
- queryKey: balanceQueryKeys.provider(),
1932
+ queryKey: balanceQueryKeys.provider(queryExecutionMode),
1911
1933
  queryFn: () => __async(null, null, function* () {
1912
1934
  if (!client || !isAuthenticated) {
1913
1935
  return EMPTY_MANAGED_BALANCES;
1914
1936
  }
1915
- return client.getManagedBalances();
1937
+ return client.getManagedBalances(
1938
+ queryExecutionMode ? { mode: queryExecutionMode } : void 0
1939
+ );
1916
1940
  }),
1917
1941
  enabled: Boolean(client && isAuthenticated),
1918
1942
  staleTime: 60 * 1e3,
@@ -2499,6 +2523,98 @@ var applyOrderbookDepth = (data, depth) => {
2499
2523
  });
2500
2524
  };
2501
2525
 
2526
+ // src/market-data/market-resolution-cache.ts
2527
+ var isRecord = (value) => {
2528
+ return typeof value === "object" && value !== null;
2529
+ };
2530
+ var NESTED_COLLECTION_FIELDS = ["pages", "data", "markets", "events", "venueMarkets"];
2531
+ var marketContainsOutcomeId = (market, outcomeId) => {
2532
+ if (!isRecord(market)) return false;
2533
+ const outcomes = market.venueMarketOutcomes;
2534
+ if (!Array.isArray(outcomes)) return false;
2535
+ return outcomes.some((outcome) => isRecord(outcome) && outcome.id === outcomeId);
2536
+ };
2537
+ var cachedDataContainsOutcomeId = (data, outcomeId) => {
2538
+ if (Array.isArray(data)) {
2539
+ return data.some((entry) => cachedDataContainsOutcomeId(entry, outcomeId));
2540
+ }
2541
+ if (!isRecord(data)) return false;
2542
+ if (marketContainsOutcomeId(data, outcomeId)) return true;
2543
+ return NESTED_COLLECTION_FIELDS.some((field) => {
2544
+ const value = data[field];
2545
+ return Array.isArray(value) && value.some((entry) => cachedDataContainsOutcomeId(entry, outcomeId));
2546
+ });
2547
+ };
2548
+ var normalizeLabel = (label) => {
2549
+ return typeof label === "string" ? label.trim().toLowerCase() : "";
2550
+ };
2551
+ var findResolvedOutcome = (resolvedOutcomes, outcome) => {
2552
+ var _a;
2553
+ const externalIdentifier = outcome.externalIdentifier;
2554
+ if (typeof externalIdentifier === "string" && externalIdentifier.length > 0) {
2555
+ const matchedByExternalId = resolvedOutcomes.find(
2556
+ (resolved) => resolved.externalIdentifier === externalIdentifier
2557
+ );
2558
+ if (matchedByExternalId) return matchedByExternalId;
2559
+ }
2560
+ const label = normalizeLabel(outcome.label);
2561
+ if (label) {
2562
+ return (_a = resolvedOutcomes.find((resolved) => normalizeLabel(resolved.label) === label)) != null ? _a : null;
2563
+ }
2564
+ return null;
2565
+ };
2566
+ var applyWinnersToOutcomes = (outcomes, resolution) => {
2567
+ let changed = false;
2568
+ const next = outcomes.map((outcome) => {
2569
+ if (!isRecord(outcome)) return outcome;
2570
+ const resolved = findResolvedOutcome(resolution.outcomes, outcome);
2571
+ if (!resolved) return outcome;
2572
+ const nextWinner = resolved.winner === true;
2573
+ if (outcome.winner === nextWinner) return outcome;
2574
+ changed = true;
2575
+ return __spreadProps(__spreadValues({}, outcome), { winner: nextWinner });
2576
+ });
2577
+ return changed ? next : outcomes;
2578
+ };
2579
+ var applyResolutionToMarket = (market, resolution) => {
2580
+ const outcomes = market.venueMarketOutcomes;
2581
+ if (!Array.isArray(outcomes)) return market;
2582
+ if (!outcomes.some((outcome) => isRecord(outcome) && outcome.id === resolution.outcomeId)) {
2583
+ return market;
2584
+ }
2585
+ const nextOutcomes = applyWinnersToOutcomes(outcomes, resolution);
2586
+ const statusChanged = market.status !== resolution.status;
2587
+ if (!statusChanged && nextOutcomes === outcomes) return market;
2588
+ return __spreadProps(__spreadValues({}, market), { status: resolution.status, venueMarketOutcomes: nextOutcomes });
2589
+ };
2590
+ var applyResolutionToCachedData = (data, resolution) => {
2591
+ if (Array.isArray(data)) {
2592
+ let changed2 = false;
2593
+ const next2 = data.map((entry) => {
2594
+ const updated = applyResolutionToCachedData(entry, resolution);
2595
+ if (updated !== entry) changed2 = true;
2596
+ return updated;
2597
+ });
2598
+ return changed2 ? next2 : data;
2599
+ }
2600
+ if (!isRecord(data)) return data;
2601
+ if (Array.isArray(data.venueMarketOutcomes)) {
2602
+ return applyResolutionToMarket(data, resolution);
2603
+ }
2604
+ let changed = false;
2605
+ const next = __spreadValues({}, data);
2606
+ for (const field of NESTED_COLLECTION_FIELDS) {
2607
+ const value = data[field];
2608
+ if (!Array.isArray(value)) continue;
2609
+ const updated = applyResolutionToCachedData(value, resolution);
2610
+ if (updated !== value) {
2611
+ next[field] = updated;
2612
+ changed = true;
2613
+ }
2614
+ }
2615
+ return changed ? next : data;
2616
+ };
2617
+
2502
2618
  // src/market-data/query-keys.ts
2503
2619
  var marketDataKeys = {
2504
2620
  all: () => ["market-data"],
@@ -2766,6 +2882,62 @@ function AggWebSocketProvider({ children }) {
2766
2882
  const invalidateActivityCaches = (0, import_react6.useCallback)(() => {
2767
2883
  invalidateUserActivityQueries(queryClient);
2768
2884
  }, [queryClient]);
2885
+ const invalidateResolutionCaches = (0, import_react6.useCallback)(
2886
+ (resolution) => {
2887
+ const { outcomeId } = resolution;
2888
+ syncLiveQuery(outcomeId, (previous) => {
2889
+ if (!previous) return previous;
2890
+ if (previous.orderbook == null && previous.orderbookError == null) return previous;
2891
+ return __spreadProps(__spreadValues({}, previous), {
2892
+ orderbook: null,
2893
+ orderbookError: null,
2894
+ integrity: "ok"
2895
+ });
2896
+ });
2897
+ const affectedQueries = queryClient.getQueryCache().findAll({
2898
+ predicate: (query) => cachedDataContainsOutcomeId(query.state.data, outcomeId)
2899
+ });
2900
+ for (const query of affectedQueries) {
2901
+ queryClient.setQueryData(
2902
+ query.queryKey,
2903
+ (previous) => applyResolutionToCachedData(previous, resolution)
2904
+ );
2905
+ }
2906
+ queryClient.invalidateQueries({
2907
+ queryKey: ["midpoints"],
2908
+ refetchType: "all"
2909
+ });
2910
+ queryClient.invalidateQueries({
2911
+ queryKey: ["venue-market-midpoints"],
2912
+ refetchType: "all"
2913
+ });
2914
+ queryClient.invalidateQueries({
2915
+ queryKey: ["venue-event"],
2916
+ refetchType: "all"
2917
+ });
2918
+ queryClient.invalidateQueries({
2919
+ queryKey: ["venue-markets"],
2920
+ refetchType: "all"
2921
+ });
2922
+ queryClient.invalidateQueries({
2923
+ queryKey: ["events"],
2924
+ refetchType: "all"
2925
+ });
2926
+ queryClient.invalidateQueries({
2927
+ queryKey: ["event-list"],
2928
+ refetchType: "all"
2929
+ });
2930
+ queryClient.invalidateQueries({
2931
+ queryKey: ["search"],
2932
+ refetchType: "all"
2933
+ });
2934
+ queryClient.invalidateQueries({
2935
+ predicate: (query) => cachedDataContainsOutcomeId(query.state.data, outcomeId),
2936
+ refetchType: "all"
2937
+ });
2938
+ },
2939
+ [queryClient, syncLiveQuery]
2940
+ );
2769
2941
  const callbacks = (0, import_react6.useMemo)(
2770
2942
  () => ({
2771
2943
  onSnapshot: (marketId, book) => {
@@ -2914,6 +3086,14 @@ function AggWebSocketProvider({ children }) {
2914
3086
  listener(msg);
2915
3087
  }
2916
3088
  },
3089
+ onMarketResolved: (msg) => {
3090
+ invalidateResolutionCaches(msg);
3091
+ if (isClientAuthenticated) {
3092
+ invalidateBalanceCaches();
3093
+ invalidatePositionCaches();
3094
+ invalidateActivityCaches();
3095
+ }
3096
+ },
2917
3097
  onError: (msg) => {
2918
3098
  const outcomeId = resolveSnapshotUnavailableOutcomeId(msg.message);
2919
3099
  if (!outcomeId) return;
@@ -2951,6 +3131,7 @@ function AggWebSocketProvider({ children }) {
2951
3131
  invalidateActivityCaches,
2952
3132
  invalidateBalanceCaches,
2953
3133
  invalidatePositionCaches,
3134
+ invalidateResolutionCaches,
2954
3135
  isClientAuthenticated,
2955
3136
  queryClient,
2956
3137
  syncChartQueries,
@@ -5786,6 +5967,7 @@ function findLivePriceById(livePrices, id) {
5786
5967
  var import_react27 = require("react");
5787
5968
  var import_react_query25 = require("@tanstack/react-query");
5788
5969
  var EMPTY = /* @__PURE__ */ new Map();
5970
+ var EMPTY_CANDIDATES = /* @__PURE__ */ new Map();
5789
5971
  var extractOutcomeBestPrices = (state) => {
5790
5972
  var _a, _b;
5791
5973
  const ob = state == null ? void 0 : state.orderbook;
@@ -5903,6 +6085,175 @@ function mergeBestPricesPreferringLive(rest, live) {
5903
6085
  }
5904
6086
  return merged;
5905
6087
  }
6088
+ var pickSideVenue = (venues, level, side) => {
6089
+ if (venues) {
6090
+ let bestVenue;
6091
+ let bestValue;
6092
+ for (const [venue, info] of Object.entries(venues)) {
6093
+ const value = side === "bid" ? info.bestBid : info.bestAsk;
6094
+ if (value == null) continue;
6095
+ const wins = bestValue == null || (side === "bid" ? value > bestValue : value < bestValue);
6096
+ if (wins) {
6097
+ bestValue = value;
6098
+ bestVenue = venue;
6099
+ }
6100
+ }
6101
+ if (bestVenue != null) return bestVenue;
6102
+ }
6103
+ if (level == null ? void 0 : level.venues) {
6104
+ let bestVenue;
6105
+ let bestSize = -Infinity;
6106
+ for (const [venue, size] of Object.entries(level.venues)) {
6107
+ if (size > bestSize) {
6108
+ bestSize = size;
6109
+ bestVenue = venue;
6110
+ }
6111
+ }
6112
+ if (bestVenue != null) return bestVenue;
6113
+ }
6114
+ return void 0;
6115
+ };
6116
+ var extractOutcomeBestCandidate = (state) => {
6117
+ var _a;
6118
+ const ob = state == null ? void 0 : state.orderbook;
6119
+ if (!ob) return {};
6120
+ const candidate = {};
6121
+ const bidLevel = ob.bids[0];
6122
+ const askLevel = ob.asks[0];
6123
+ if ((bidLevel == null ? void 0 : bidLevel.price) != null) {
6124
+ candidate.bestBid = bidLevel.price;
6125
+ const venue = pickSideVenue(ob.venues, bidLevel, "bid");
6126
+ if (venue) candidate.bestBidVenue = venue;
6127
+ }
6128
+ if ((askLevel == null ? void 0 : askLevel.price) != null) {
6129
+ candidate.bestAsk = askLevel.price;
6130
+ const venue = pickSideVenue(ob.venues, askLevel, "ask");
6131
+ if (venue) candidate.bestAskVenue = venue;
6132
+ }
6133
+ if (ob.midpoint != null) {
6134
+ candidate.midpoint = ob.midpoint;
6135
+ const midVenue = (_a = candidate.bestAskVenue) != null ? _a : candidate.bestBidVenue;
6136
+ if (midVenue) candidate.midpointVenue = midVenue;
6137
+ }
6138
+ if (ob.timestamp != null) candidate.updatedAt = ob.timestamp;
6139
+ return candidate;
6140
+ };
6141
+ function buildLiveBestPriceCandidates(outcomeIds, states, venueMarkets) {
6142
+ var _a, _b, _c;
6143
+ const perOutcome = /* @__PURE__ */ new Map();
6144
+ for (let i = 0; i < outcomeIds.length; i++) {
6145
+ const candidate = extractOutcomeBestCandidate(states[i]);
6146
+ if (candidate.bestBid != null || candidate.bestAsk != null || candidate.midpoint != null) {
6147
+ perOutcome.set(outcomeIds[i], candidate);
6148
+ }
6149
+ }
6150
+ if (perOutcome.size === 0 || !(venueMarkets == null ? void 0 : venueMarkets.length)) {
6151
+ return perOutcome;
6152
+ }
6153
+ const result = new Map(perOutcome);
6154
+ for (const vm of venueMarkets) {
6155
+ for (const outcome of (_a = vm.venueMarketOutcomes) != null ? _a : []) {
6156
+ const refs = (_b = outcome.matchedVenueMarketOutcomes) != null ? _b : [];
6157
+ if (!refs.length) continue;
6158
+ const group = [outcome.id, ...refs.map((ref) => ref.venueMarketOutcomeId)];
6159
+ let groupBestAsk;
6160
+ let groupBestAskVenue;
6161
+ let groupBestBid;
6162
+ let groupBestBidVenue;
6163
+ let groupUpdatedAt;
6164
+ for (const id of group) {
6165
+ const entry = perOutcome.get(id);
6166
+ if (!entry) continue;
6167
+ if (entry.bestAsk != null && (groupBestAsk == null || entry.bestAsk < groupBestAsk)) {
6168
+ groupBestAsk = entry.bestAsk;
6169
+ groupBestAskVenue = entry.bestAskVenue;
6170
+ }
6171
+ if (entry.bestBid != null && (groupBestBid == null || entry.bestBid > groupBestBid)) {
6172
+ groupBestBid = entry.bestBid;
6173
+ groupBestBidVenue = entry.bestBidVenue;
6174
+ }
6175
+ if (entry.updatedAt != null && (groupUpdatedAt == null || entry.updatedAt > groupUpdatedAt)) {
6176
+ groupUpdatedAt = entry.updatedAt;
6177
+ }
6178
+ }
6179
+ if (groupBestAsk == null && groupBestBid == null) continue;
6180
+ for (const id of group) {
6181
+ const prev = (_c = result.get(id)) != null ? _c : {};
6182
+ const next = __spreadValues({}, prev);
6183
+ if (groupBestBid != null) {
6184
+ next.bestBid = groupBestBid;
6185
+ if (groupBestBidVenue) next.bestBidVenue = groupBestBidVenue;
6186
+ }
6187
+ if (groupBestAsk != null) {
6188
+ next.bestAsk = groupBestAsk;
6189
+ if (groupBestAskVenue) next.bestAskVenue = groupBestAskVenue;
6190
+ }
6191
+ if (groupUpdatedAt != null) next.updatedAt = groupUpdatedAt;
6192
+ result.set(id, next);
6193
+ }
6194
+ }
6195
+ }
6196
+ return result;
6197
+ }
6198
+ var buildCandidateFingerprint = (outcomeIds, queries) => {
6199
+ var _a, _b, _c, _d;
6200
+ const parts = [];
6201
+ for (let i = 0; i < outcomeIds.length; i++) {
6202
+ const ob = (_b = (_a = queries[i]) == null ? void 0 : _a.data) == null ? void 0 : _b.orderbook;
6203
+ const bid = (_c = ob == null ? void 0 : ob.bids[0]) == null ? void 0 : _c.price;
6204
+ const ask = (_d = ob == null ? void 0 : ob.asks[0]) == null ? void 0 : _d.price;
6205
+ const mid = ob == null ? void 0 : ob.midpoint;
6206
+ const ts = ob == null ? void 0 : ob.timestamp;
6207
+ const venues = (ob == null ? void 0 : ob.venues) ? Object.keys(ob.venues).sort().join(",") : "";
6208
+ parts.push(`${outcomeIds[i]}:${bid != null ? bid : "_"}:${ask != null ? ask : "_"}:${mid != null ? mid : "_"}:${ts != null ? ts : "_"}:${venues}`);
6209
+ }
6210
+ return parts.join("|");
6211
+ };
6212
+ function useLiveBestPriceCandidates(venueMarkets) {
6213
+ const {
6214
+ features: { enableLiveUpdates }
6215
+ } = useAggUiConfig();
6216
+ const outcomeIds = (0, import_react27.useMemo)(() => {
6217
+ var _a, _b;
6218
+ if (!(venueMarkets == null ? void 0 : venueMarkets.length)) return [];
6219
+ const ids = /* @__PURE__ */ new Set();
6220
+ for (const vm of venueMarkets) {
6221
+ for (const outcome of (_a = vm.venueMarketOutcomes) != null ? _a : []) {
6222
+ if (outcome.id) ids.add(outcome.id);
6223
+ for (const ref of (_b = outcome.matchedVenueMarketOutcomes) != null ? _b : []) {
6224
+ if (ref.venueMarketOutcomeId) ids.add(ref.venueMarketOutcomeId);
6225
+ }
6226
+ }
6227
+ }
6228
+ return [...ids].sort();
6229
+ }, [venueMarkets]);
6230
+ const queries = (0, import_react_query25.useQueries)({
6231
+ queries: outcomeIds.map((id) => ({
6232
+ queryKey: marketDataKeys.live(id),
6233
+ queryFn: () => createMarketLiveState(id),
6234
+ enabled: false,
6235
+ staleTime: Infinity,
6236
+ gcTime: 5 * 6e4,
6237
+ initialData: () => createMarketLiveState(id)
6238
+ }))
6239
+ });
6240
+ const fingerprint = buildCandidateFingerprint(outcomeIds, queries);
6241
+ const prevRef = (0, import_react27.useRef)({
6242
+ fingerprint: "",
6243
+ result: EMPTY_CANDIDATES
6244
+ });
6245
+ return (0, import_react27.useMemo)(() => {
6246
+ if (!(venueMarkets == null ? void 0 : venueMarkets.length) || !enableLiveUpdates) return EMPTY_CANDIDATES;
6247
+ if (fingerprint === prevRef.current.fingerprint) return prevRef.current.result;
6248
+ const states = outcomeIds.map((_, i) => {
6249
+ var _a;
6250
+ return (_a = queries[i]) == null ? void 0 : _a.data;
6251
+ });
6252
+ const result = buildLiveBestPriceCandidates(outcomeIds, states, venueMarkets);
6253
+ prevRef.current = { fingerprint, result };
6254
+ return result;
6255
+ }, [venueMarkets, enableLiveUpdates, fingerprint, outcomeIds, queries]);
6256
+ }
5906
6257
 
5907
6258
  // src/use-live-trades.ts
5908
6259
  function useLiveTrades(canonicalMarketId) {
@@ -7441,11 +7792,13 @@ var toAppConfigResult = (query) => {
7441
7792
  TradeSide,
7442
7793
  TurnstileChallengeError,
7443
7794
  Venue,
7795
+ buildLiveBestPriceCandidates,
7444
7796
  computeClosedPositionTotals,
7445
7797
  computePriceGaps,
7446
7798
  defaultAggUiConfig,
7447
7799
  defaultSdkUiConfig,
7448
7800
  executionKeys,
7801
+ extractOutcomeBestCandidate,
7449
7802
  findLivePriceById,
7450
7803
  getBuilder,
7451
7804
  getDepositAddress,
@@ -7507,6 +7860,7 @@ var toAppConfigResult = (query) => {
7507
7860
  useGeoBlock,
7508
7861
  useLabels,
7509
7862
  useLinkAccount,
7863
+ useLiveBestPriceCandidates,
7510
7864
  useLiveBestPrices,
7511
7865
  useLiveCandleOverlay,
7512
7866
  useLiveCandles,