@agg-build/hooks 4.17.0 → 4.18.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.
@@ -59,11 +59,13 @@ var Venue = /* @__PURE__ */ ((Venue2) => {
59
59
  Venue2["opinion"] = "opinion";
60
60
  Venue2["predict"] = "predict";
61
61
  Venue2["pred"] = "pred";
62
+ Venue2["tiprun"] = "tiprun";
62
63
  Venue2["probable"] = "probable";
63
64
  Venue2["myriad"] = "myriad";
64
65
  Venue2["hyperliquid"] = "hyperliquid";
65
66
  Venue2["novig"] = "novig";
66
67
  Venue2["prophetx"] = "prophetx";
68
+ Venue2["betdex"] = "betdex";
67
69
  return Venue2;
68
70
  })(Venue || {});
69
71
  var ACTIVE_VENUES = [
@@ -73,11 +75,13 @@ var ACTIVE_VENUES = [
73
75
  "opinion" /* opinion */,
74
76
  "predict" /* predict */,
75
77
  "pred" /* pred */,
78
+ "tiprun" /* tiprun */,
76
79
  "probable" /* probable */,
77
80
  "myriad" /* myriad */,
78
81
  "hyperliquid" /* hyperliquid */,
79
82
  "novig" /* novig */,
80
- "prophetx" /* prophetx */
83
+ "prophetx" /* prophetx */,
84
+ "betdex" /* betdex */
81
85
  ];
82
86
  var INACTIVE_VENUES = [];
83
87
  var ACTIVE_VENUE_SET = new Set(ACTIVE_VENUES);
@@ -158,6 +162,9 @@ function parseEmailStrict(raw) {
158
162
  return result.data;
159
163
  }
160
164
 
165
+ // ../common/src/enums/image-size.ts
166
+ var RETINA_IMAGE_SIZES = [80 /* xl */, 96 /* xxl */, 120 /* xxxl */];
167
+
161
168
  // ../common/src/utils/image-url.ts
162
169
  function pickVariant(px) {
163
170
  if (px <= 44 /* sm */) return 44 /* sm */;
@@ -173,6 +180,13 @@ function optimizedImageUrl(url, maxPx) {
173
180
  const filename = variant === 0 /* original */ ? "original.webp" : `${variant}.webp`;
174
181
  return url.replace(VARIANT_RE, `/${filename}`);
175
182
  }
183
+ function retinaImageUrl(url, maxPx) {
184
+ if (!url) return void 0;
185
+ if (!VARIANT_RE.test(url)) return void 0;
186
+ const variant = RETINA_IMAGE_SIZES.find((size) => size >= maxPx * 2);
187
+ if (variant == null) return void 0;
188
+ return url.replace(VARIANT_RE, `/${variant}.webp`);
189
+ }
176
190
 
177
191
  // ../common/src/utils/sort-venues.ts
178
192
  var VENUE_SORT_ORDER = [
@@ -180,10 +194,12 @@ var VENUE_SORT_ORDER = [
180
194
  "hyperliquid" /* hyperliquid */,
181
195
  "predict" /* predict */,
182
196
  "prophetx" /* prophetx */,
197
+ "betdex" /* betdex */,
183
198
  "kalshi" /* kalshi */,
184
199
  "limitless" /* limitless */,
185
200
  "myriad" /* myriad */,
186
201
  "pred" /* pred */,
202
+ "tiprun" /* tiprun */,
187
203
  "probable" /* probable */,
188
204
  "novig" /* novig */,
189
205
  "opinion" /* opinion */
@@ -228,6 +244,19 @@ function evict() {
228
244
  builders.delete(oldest);
229
245
  }
230
246
  }
247
+ function getCandleStoreDiagnostics() {
248
+ return {
249
+ builders: builders.size,
250
+ retainedCandles: [...builders.values()].reduce(
251
+ (total, builder) => total + ["1m", "5m", "1h", "1d"].reduce(
252
+ (count, interval) => count + builder.getClosed(interval).length + (builder.getForming(interval) ? 1 : 0),
253
+ 0
254
+ ),
255
+ 0
256
+ ),
257
+ maxBuilders: MAX_BUILDERS
258
+ };
259
+ }
231
260
 
232
261
  // src/core/ui-config/labels.ts
233
262
  var enUsLabels = {
@@ -244,6 +273,10 @@ var enUsLabels = {
244
273
  lineChartAria: "Line chart",
245
274
  candlestickChartAria: "Candlestick chart",
246
275
  lineChartSeriesSwitchAria: "Chart series switch",
276
+ chartSources: (historyVenue, liquidityVenue) => `History: ${historyVenue} \xB7 Resting liquidity: ${liquidityVenue != null ? liquidityVenue : "all venues"}`,
277
+ chartBidLiquidity: (amount) => `Bid ${amount}`,
278
+ chartAskLiquidity: (amount) => `Ask ${amount}`,
279
+ chartEmpty: "No price history in this range",
247
280
  lineChartSeriesOptionAria: (seriesLabel) => `Show ${seriesLabel} series`,
248
281
  chartTypeSwitchAria: "Chart type switch",
249
282
  lineChartType: "Line",
@@ -255,12 +288,14 @@ var enUsLabels = {
255
288
  opinion: "Opinion",
256
289
  predict: "Predict",
257
290
  pred: "PRED",
291
+ tiprun: "Tip Run",
258
292
  limitless: "Limitless",
259
293
  probable: "Probable",
260
294
  myriad: "Myriad",
261
295
  hyperliquid: "Hyperliquid",
262
296
  novig: "Novig",
263
- prophetx: "ProphetX"
297
+ prophetx: "ProphetX",
298
+ betdex: "BETDEX"
264
299
  },
265
300
  auth: {
266
301
  connect: (connectorName) => connectorName ? `Sign in with ${connectorName}` : "Sign in",
@@ -545,16 +580,80 @@ var enUsLabels = {
545
580
  activity: "Activity"
546
581
  },
547
582
  balance: {
548
- availableBalance: "Withdrawable Balance",
583
+ availableBalance: "Balance",
549
584
  manage: "Manage",
550
585
  reservedForOpenOrders: (amount) => `${amount} reserved for open orders`,
551
586
  positionsValue: "Positions Value",
552
587
  kalshiBalance: "Kalshi Balance",
553
588
  balanceByNetwork: "Balance by network",
589
+ venueAccount: "Venue account",
590
+ balanceUnavailable: "Balance unavailable",
554
591
  paperModeNetwork: "Paper",
555
592
  paperModeWarning: "Paper mode is enabled. These are simulated funds for paper trading.",
556
593
  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."
557
594
  },
595
+ hostedBetdex: {
596
+ deposit: "Deposit USDC",
597
+ depositInstructions: {
598
+ production: "Send USDC on Solana to this BETDEX account address.",
599
+ sandbox: "This is a sandbox account. Use sandbox test funds only."
600
+ },
601
+ depositAddress: "BETDEX Solana deposit address",
602
+ transferUnavailable: "This transfer is temporarily unavailable. Check its status before trying again.",
603
+ withdraw: "Withdraw USDC",
604
+ withdrawalAmount: "Amount (USDC)",
605
+ withdrawalDestination: "Your Solana wallet address",
606
+ withdrawalSubmit: "Withdraw from BETDEX",
607
+ withdrawalCheck: "Check withdrawal",
608
+ withdrawalRetry: "Retry the same withdrawal",
609
+ withdrawalNew: "New withdrawal",
610
+ withdrawalUnknown: "The response was not confirmed. Your request is saved; retrying checks the same withdrawal.",
611
+ withdrawalStatuses: {
612
+ processing: "Withdrawal is processing.",
613
+ confirmed: "Withdrawal confirmed.",
614
+ failed: "Withdrawal failed. Funds are available again.",
615
+ flagged: "Withdrawal needs review. Funds remain reserved.",
616
+ review_required: "Withdrawal needs review. Funds remain reserved."
617
+ },
618
+ title: "BETDEX account",
619
+ description: "USDC held with BETDEX, separate from your connected wallets.",
620
+ sandbox: "Sandbox \xB7 simulated funds",
621
+ createAccount: "Set up BETDEX account",
622
+ checkSetup: "Check account setup",
623
+ provisioning: "Account setup is processing. Check again for confirmation.",
624
+ suspended: "This BETDEX account is suspended.",
625
+ unavailable: "BETDEX balance is temporarily unavailable.",
626
+ provisioningUnavailable: "BETDEX account setup is currently unavailable.",
627
+ total: "Total balance",
628
+ available: "Available to trade",
629
+ reserved: "Reserved for open orders",
630
+ refresh: "Refresh account",
631
+ creationFailed: "We could not confirm account setup. Refresh to check its status before trying again.",
632
+ showActivity: "Show account activity",
633
+ hideActivity: "Hide account activity",
634
+ activityTitle: "BETDEX account activity",
635
+ activityDescription: "Observed ledger entries, not spendable balances or per-order fees. A ledger entry alone does not confirm a withdrawal's completion.",
636
+ activityEmpty: "No account activity on this page.",
637
+ activityUnavailable: "BETDEX account activity is temporarily unavailable.",
638
+ activityPrevious: "Previous activity page",
639
+ activityNext: "Next activity page",
640
+ activityRefresh: "Refresh activity",
641
+ activityCodes: {
642
+ Deposit: "Deposit",
643
+ Withdrawal: "Withdrawal",
644
+ TradeCreation: "Trade created",
645
+ TradeVoid: "Trade voided",
646
+ TradeWin: "Trade payout",
647
+ WalletToWallet: "Wallet transfer",
648
+ Commission: "Commission",
649
+ MarketPositionVoid: "Position voided",
650
+ MarketPositionPayout: "Position payout",
651
+ MarketPositionRefund: "Position refund",
652
+ ManualDebit: "Manual debit",
653
+ ManualCredit: "Manual credit",
654
+ SettlementResidual: "Settlement adjustment"
655
+ }
656
+ },
558
657
  activity: {
559
658
  depositType: "Deposit",
560
659
  redeemType: "Claim",
@@ -641,6 +740,9 @@ var enUsLabels = {
641
740
  filledShort: "Filled",
642
741
  totalShort: "Total",
643
742
  expirationHeader: "Expiration",
743
+ buy: "Buy",
744
+ sell: "Sell",
745
+ nowPrefix: "now",
644
746
  goodTilCanceled: "Good 'til canceled",
645
747
  expired: "Expired",
646
748
  cancel: "Cancel",
@@ -705,6 +807,17 @@ var enUsLabels = {
705
807
  priceGap: "Price Gap"
706
808
  },
707
809
  eventItemDetails: {
810
+ chartLegend: "Markets on chart",
811
+ selectChartMarkets: "Select a line above to show its history",
812
+ marketHistoryUnavailable: "History unavailable",
813
+ comparisonSource: (venue) => `${venue} \xB7 Outcome probabilities \xB7 Click a line to show or hide it`,
814
+ comparisonSeriesCount: (shown, total) => `Showing ${shown} of ${total} series`,
815
+ comparisonSeriesPage: (page, total) => `Page ${page} of ${total}`,
816
+ comparisonSeriesBudget: (limit) => `Up to ${limit} series are live at once. Change pages to compare others; your selected outcome stays visible.`,
817
+ comparisonPreviousSeries: "Previous series",
818
+ comparisonNextSeries: "Next series",
819
+ comparisonSelectedSeries: "Selected",
820
+ comparisonHiddenSeries: "Hidden",
708
821
  loading: "Loading market details",
709
822
  unavailableAria: "Market details unavailable",
710
823
  unavailableTitle: "Market details unavailable",
@@ -810,6 +923,7 @@ var enUsLabels = {
810
923
  settlementCriticalDifferenceLabel: "Critical",
811
924
  settlementValueUnavailable: "Not provided",
812
925
  settlementLoading: "Loading settlement",
926
+ settlementDetailsLoadError: "Settlement details could not be loaded.",
813
927
  settlementDetailsAria: (venueLabel) => `${venueLabel} settlement details`,
814
928
  settlementShowMoreAria: (ctaLabel, venueLabel) => `${ctaLabel} for ${venueLabel}`,
815
929
  settlementDescriptionLabel: "Description",
@@ -831,6 +945,9 @@ var enUsLabels = {
831
945
  maximumFractionDigits: 2
832
946
  })}\xA2 avg. price`,
833
947
  balance: (value) => `Balance ${value}`,
948
+ betdexBalance: (value) => `BETDEX balance ${value}`,
949
+ betdexBalanceUnavailable: "BETDEX balance unavailable",
950
+ manageBetdexAccount: "Manage BETDEX account",
834
951
  shares: (value) => `${value.toLocaleString("en-US", {
835
952
  minimumFractionDigits: Number.isInteger(value) ? 0 : 1,
836
953
  maximumFractionDigits: 2
@@ -947,7 +1064,12 @@ var enUsLabels = {
947
1064
  error: "We couldn't confirm your verification."
948
1065
  }
949
1066
  },
950
- connectKalshi: "Connect to trade Kalshi",
1067
+ connectKalshi: "Connect Kalshi to trade",
1068
+ connectProphetx: "Connect ProphetX to trade",
1069
+ manageProphetx: "Manage ProphetX connection",
1070
+ prophetxFundingNotice: "Manage funds on ProphetX",
1071
+ prophetxSettlementNotice: "This position settles on ProphetX",
1072
+ requiresKalshiAccount: "Requires Kalshi account",
951
1073
  tradingAccessVenues: "Venues",
952
1074
  tradingAccessAvailable: "Available",
953
1075
  tradingAccessAddKalshiAccount: "Add Kalshi Account",
@@ -995,6 +1117,7 @@ var enUsLabels = {
995
1117
  verified: "Verified",
996
1118
  platformFee: "0% platform fees",
997
1119
  estimatedFees: "Estimated fees",
1120
+ betdexSettlementFeeNotice: "BETDEX charges 1% of net profit per market at settlement, not per fill. The final fee depends on all positions in that market.",
998
1121
  executionReserve: "Execution reserve",
999
1122
  executionReserveTooltipAria: "Why funds are reserved",
1000
1123
  executionReserveDescription: "Held for price movement or possible venue charges, not a confirmed fee. Unused funds are returned after execution.",
@@ -1058,6 +1181,11 @@ var enUsLabels = {
1058
1181
  orderFullyFilled: "Order fully filled",
1059
1182
  orderPartiallyFilled: "Order partially filled",
1060
1183
  orderAveragePrice: (priceLabel) => `avg. ${priceLabel}`,
1184
+ orderAmount: "Order amount",
1185
+ orderLimitPrice: (priceLabel) => `limit ${priceLabel}`,
1186
+ limitVenueOrder: (venueLabel) => `${venueLabel} limit order`,
1187
+ limitOrderSubmitting: "Submitting limit order...",
1188
+ limitOrderSubmitted: "Limit order submitted",
1061
1189
  orderComplete: "Order complete",
1062
1190
  orderFilledAtPrice: (venueLabel, priceLabel) => `${venueLabel} order filled at ${priceLabel}`,
1063
1191
  orderFilledAtPriceWithAmount: (venueLabel, priceLabel, amountLabel) => `${venueLabel} order filled at ${priceLabel} (${amountLabel})`,
@@ -1140,6 +1268,22 @@ var enUsLabels = {
1140
1268
  cancel: "Cancel",
1141
1269
  fallbackError: "Signature declined. Please try again."
1142
1270
  },
1271
+ connectProphetxModal: {
1272
+ disconnect: "Disconnect ProphetX",
1273
+ disconnecting: "Disconnecting\u2026",
1274
+ disconnectError: "Could not disconnect ProphetX. Finish any open orders and try again.",
1275
+ title: "Connect ProphetX Account",
1276
+ description: "Add your ProphetX access key and secret key to trade with your existing account.",
1277
+ fundingNotice: "Trades use your ProphetX balance. Deposits, withdrawals, and transfers are managed on ProphetX, outside AGG.",
1278
+ instructions: "Create an API key in your ProphetX account settings",
1279
+ accessKey: "Access key",
1280
+ secretKey: "Secret key",
1281
+ verify: "Verify connection",
1282
+ verifying: "Verifying\u2026",
1283
+ error: "Could not connect to ProphetX. Check your credentials and try again.",
1284
+ connected: "Your ProphetX account is connected.",
1285
+ done: "Done"
1286
+ },
1143
1287
  connectKalshiModal: {
1144
1288
  ariaLabel: "Connect Kalshi Account",
1145
1289
  title: "Connect Kalshi Account",
@@ -1173,11 +1317,6 @@ var enUsLabels = {
1173
1317
  privateKeyLabel: "Private Key",
1174
1318
  privateKeyPlaceholder: "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASC..."
1175
1319
  },
1176
- help: {
1177
- label: "Having trouble?",
1178
- docsLinkLabel: "View Kalshi docs",
1179
- tutorialLinkLabel: "Watch tutorial video"
1180
- },
1181
1320
  actions: {
1182
1321
  cancel: "Cancel",
1183
1322
  verifyConnection: "Verify Connection"
@@ -1191,6 +1330,20 @@ var enUsLabels = {
1191
1330
  }
1192
1331
  },
1193
1332
  eventMarketPage: {
1333
+ loadMoreMarkets: "Load more markets",
1334
+ loadingMoreMarkets: "Loading markets\u2026",
1335
+ openOrders: {
1336
+ title: "Open orders",
1337
+ limitPriceHeader: "Limit price",
1338
+ filledHeader: "Filled",
1339
+ totalHeader: "Total",
1340
+ expirationHeader: "Expiration",
1341
+ // Abbreviated forms for the stacked mobile card.
1342
+ limitShort: "Limit",
1343
+ filledShort: "Filled",
1344
+ totalShort: "Tot.",
1345
+ expirationShort: "Exp."
1346
+ },
1194
1347
  unavailableAria: "Event market page unavailable",
1195
1348
  unavailableTitle: "Something went wrong",
1196
1349
  unavailableDescription: "We're having trouble loading this event right now.\nTry refreshing or check back later.",
@@ -1557,7 +1710,7 @@ var mergeAggUiConfig = (persisted, config) => {
1557
1710
  // src/execution/query-keys.ts
1558
1711
  var executionKeys = {
1559
1712
  all: () => ["execution"],
1560
- balances: (mode) => mode ? ["execution", "balances", mode] : ["execution", "balances"],
1713
+ balances: (mode, custody) => custody && custody !== "managed" ? ["execution", "balances", mode != null ? mode : "live", custody] : mode ? ["execution", "balances", mode] : ["execution", "balances"],
1561
1714
  positions: (cursor, limit, status, mode) => mode ? ["execution", "positions", cursor != null ? cursor : null, limit != null ? limit : null, status != null ? status : null, mode] : ["execution", "positions", cursor != null ? cursor : null, limit != null ? limit : null, status != null ? status : null],
1562
1715
  positionsPrefix: () => ["execution", "positions"],
1563
1716
  claimablePositionsCount: () => ["execution", "positions", "claimable-count"],
@@ -1583,7 +1736,11 @@ var balanceQueryKeys = {
1583
1736
  venue: (venuesKey) => ["venue-balances", venuesKey],
1584
1737
  venuePrefix: () => ["venue-balances"]
1585
1738
  };
1586
- var BALANCE_REFRESHING_ORDER_EVENTS = /* @__PURE__ */ new Set(["filled", "partial_fill"]);
1739
+ var BALANCE_REFRESHING_ORDER_EVENTS = /* @__PURE__ */ new Set([
1740
+ "filled",
1741
+ "partial_fill",
1742
+ "cancelled"
1743
+ ]);
1587
1744
  var invalidateBalanceQueries = (queryClient, options) => {
1588
1745
  var _a;
1589
1746
  const refetchType = (_a = options == null ? void 0 : options.refetchType) != null ? _a : "active";
@@ -1604,6 +1761,7 @@ var invalidateBalanceQueries = (queryClient, options) => {
1604
1761
  queryKey: balanceQueryKeys.venuePrefix(),
1605
1762
  refetchType
1606
1763
  });
1764
+ queryClient.invalidateQueries({ queryKey: ["agg", "hosted-venue-account"], refetchType });
1607
1765
  };
1608
1766
  var invalidatePositionQueries = (queryClient, options) => {
1609
1767
  var _a;
@@ -1654,7 +1812,7 @@ var invalidateUserClaimState = (queryClient, options) => {
1654
1812
  import { useContext as useContext7 } from "react";
1655
1813
 
1656
1814
  // src/core/providers/agg-provider.tsx
1657
- import { useQueryClient as useQueryClient3 } from "@tanstack/react-query";
1815
+ import { useQueryClient as useQueryClient4 } from "@tanstack/react-query";
1658
1816
 
1659
1817
  // src/core/providers/auth-provider.tsx
1660
1818
  import { QueryClient, QueryClientContext } from "@tanstack/react-query";
@@ -2106,7 +2264,7 @@ var EMPTY_MANAGED_BALANCES = {
2106
2264
  positions: []
2107
2265
  };
2108
2266
  function AggBalanceProvider({ children }) {
2109
- var _a;
2267
+ var _a, _b;
2110
2268
  const client = useContext2(AggClientContext);
2111
2269
  const authContext = useContext2(AggAuthContext);
2112
2270
  const { executionMode } = useResolvedExecutionMode();
@@ -2169,8 +2327,8 @@ function AggBalanceProvider({ children }) {
2169
2327
  }
2170
2328
  return sum + token.chains.reduce(
2171
2329
  (chainSum, chain) => {
2172
- var _a2, _b;
2173
- return chainSum + toTokenUnits((_a2 = chain.availableRaw) != null ? _a2 : chain.balanceRaw, (_b = chain.decimals) != null ? _b : token.decimals);
2330
+ var _a2, _b2;
2331
+ return chainSum + toTokenUnits((_a2 = chain.availableRaw) != null ? _a2 : chain.balanceRaw, (_b2 = chain.decimals) != null ? _b2 : token.decimals);
2174
2332
  },
2175
2333
  0
2176
2334
  );
@@ -2184,8 +2342,8 @@ function AggBalanceProvider({ children }) {
2184
2342
  }
2185
2343
  return sum + token.chains.reduce(
2186
2344
  (chainSum, chain) => {
2187
- var _a2, _b;
2188
- return chainSum + toTokenUnits((_a2 = chain.heldRaw) != null ? _a2 : "0", (_b = chain.decimals) != null ? _b : token.decimals);
2345
+ var _a2, _b2;
2346
+ return chainSum + toTokenUnits((_a2 = chain.heldRaw) != null ? _a2 : "0", (_b2 = chain.decimals) != null ? _b2 : token.decimals);
2189
2347
  },
2190
2348
  0
2191
2349
  );
@@ -2193,29 +2351,40 @@ function AggBalanceProvider({ children }) {
2193
2351
  }, [managedBalances]);
2194
2352
  const buildBalanceBreakdown = useCallback2(
2195
2353
  (rawForChain) => {
2196
- var _a2, _b;
2197
- const byChain = /* @__PURE__ */ new Map();
2354
+ var _a2, _b2;
2355
+ const bySource = /* @__PURE__ */ new Map();
2198
2356
  const cash = managedBalances.cash;
2357
+ const chainVenues = connectedVenues.filter((venue) => venue !== "betdex");
2199
2358
  for (const token of cash) {
2200
2359
  if (!isUsdBasedToken(token.tokenSymbol)) continue;
2201
2360
  for (const chain of token.chains) {
2202
- const current = (_a2 = byChain.get(chain.chainId)) != null ? _a2 : {
2203
- label: chainLabelFromId(chain.chainId),
2361
+ const native = chain.custodyKind === "VENUE_ACCOUNT";
2362
+ const key = native ? JSON.stringify([
2363
+ "venue-account",
2364
+ chain.venue,
2365
+ chain.venueAccountId,
2366
+ chain.externalAccountId,
2367
+ chain.chainId
2368
+ ]) : String(chain.chainId);
2369
+ const current = (_a2 = bySource.get(key)) != null ? _a2 : __spreadValues({
2370
+ key,
2371
+ label: native ? chain.venue ? resolveAggUiLabels("en").venues[chain.venue] : resolveAggUiLabels("en").userProfile.balance.venueAccount : chainLabelFromId(chain.chainId),
2204
2372
  balance: 0,
2205
- accountCount: 0
2206
- };
2207
- current.balance += toTokenUnits(rawForChain(chain), (_b = chain.decimals) != null ? _b : token.decimals);
2373
+ accountCount: 0,
2374
+ venues: native && chain.venue ? [chain.venue] : chainVenues.length > 0 ? chainVenues : void 0
2375
+ }, native ? {
2376
+ venue: chain.venue,
2377
+ venueAccountId: chain.venueAccountId,
2378
+ externalAccountId: chain.externalAccountId,
2379
+ isFresh: chain.isFresh === true
2380
+ } : {});
2381
+ current.balance += toTokenUnits(rawForChain(chain), (_b2 = chain.decimals) != null ? _b2 : token.decimals);
2208
2382
  current.accountCount += 1;
2209
- byChain.set(chain.chainId, current);
2383
+ if (native) current.isFresh = current.isFresh === true && chain.isFresh === true;
2384
+ bySource.set(key, current);
2210
2385
  }
2211
2386
  }
2212
- return Array.from(byChain.entries()).sort((a, b) => a[1].label.localeCompare(b[1].label)).map(([chainId, value2]) => ({
2213
- key: String(chainId),
2214
- label: value2.label,
2215
- balance: value2.balance,
2216
- accountCount: value2.accountCount,
2217
- venues: connectedVenues.length > 0 ? connectedVenues : void 0
2218
- }));
2387
+ return Array.from(bySource.values()).sort((a, b) => a.label.localeCompare(b.label));
2219
2388
  },
2220
2389
  [connectedVenues, managedBalances.cash]
2221
2390
  );
@@ -2237,8 +2406,27 @@ function AggBalanceProvider({ children }) {
2237
2406
  return actualPositionsBalance + reservedBalance;
2238
2407
  }, [managedBalances.positions, reservedBalance]);
2239
2408
  const kalshiVenueCash = (_a = managedBalances.venueCash) == null ? void 0 : _a.find((item) => item.venue === "kalshi");
2409
+ const venueCashBalances = useMemo2(
2410
+ () => {
2411
+ var _a2;
2412
+ return Object.fromEntries(
2413
+ ((_a2 = managedBalances.venueCash) != null ? _a2 : []).map((item) => [item.venue, item.balanceCents / 100])
2414
+ );
2415
+ },
2416
+ [managedBalances.venueCash]
2417
+ );
2240
2418
  const kalshiBalance = kalshiVenueCash ? kalshiVenueCash.balanceCents / 100 : null;
2241
2419
  const kalshiPortfolioValue = (kalshiVenueCash == null ? void 0 : kalshiVenueCash.portfolioValueCents) == null ? null : kalshiVenueCash.portfolioValueCents / 100;
2420
+ const betdexCash = (_b = managedBalances.venueCash) == null ? void 0 : _b.find(
2421
+ (item) => item.venue === "betdex" && item.accountModel === "platform-hosted"
2422
+ );
2423
+ const hostedUsd = (raw) => {
2424
+ if (raw === void 0 || !/^-?\d+$/.test(raw)) return null;
2425
+ const value2 = Number(raw) / 1e6;
2426
+ return Number.isFinite(value2) ? value2 : null;
2427
+ };
2428
+ const betdexBalance = (betdexCash == null ? void 0 : betdexCash.decimals) === 6 ? hostedUsd(betdexCash.balanceRaw) : null;
2429
+ const betdexAvailableBalance = (betdexCash == null ? void 0 : betdexCash.decimals) === 6 ? hostedUsd(betdexCash.availableRaw) : null;
2242
2430
  const refetch = useCallback2(() => {
2243
2431
  if (!isAuthenticated) return;
2244
2432
  void refetchBalances();
@@ -2258,6 +2446,8 @@ function AggBalanceProvider({ children }) {
2258
2446
  positionsBalanceTotal: 0,
2259
2447
  kalshiBalance: null,
2260
2448
  kalshiPortfolioValue: null,
2449
+ betdexBalance: null,
2450
+ betdexAvailableBalance: null,
2261
2451
  balanceBreakdown: [],
2262
2452
  availableBalanceBreakdown: [],
2263
2453
  connectedVenues: [],
@@ -2276,7 +2466,10 @@ function AggBalanceProvider({ children }) {
2276
2466
  reservedBalance,
2277
2467
  positionsBalanceTotal,
2278
2468
  kalshiBalance,
2469
+ venueCashBalances,
2279
2470
  kalshiPortfolioValue,
2471
+ betdexBalance,
2472
+ betdexAvailableBalance,
2280
2473
  balanceBreakdown,
2281
2474
  availableBalanceBreakdown,
2282
2475
  connectedVenues,
@@ -2294,7 +2487,10 @@ function AggBalanceProvider({ children }) {
2294
2487
  isBalancesLoading,
2295
2488
  isAuthenticated,
2296
2489
  kalshiBalance,
2490
+ venueCashBalances,
2297
2491
  kalshiPortfolioValue,
2492
+ betdexBalance,
2493
+ betdexAvailableBalance,
2298
2494
  managedBalances,
2299
2495
  balancesQuery.dataUpdatedAt,
2300
2496
  positionsBalanceTotal,
@@ -2354,14 +2550,15 @@ function useCachedAppConfig() {
2354
2550
  });
2355
2551
  }
2356
2552
  var toAppConfigResult = (query) => {
2357
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
2553
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
2358
2554
  return {
2359
- disabledVenues: (_b = (_a = query.data) == null ? void 0 : _a.disabledVenues) != null ? _b : [],
2360
- disabledCategoryPresets: (_d = (_c = query.data) == null ? void 0 : _c.disabledCategoryPresets) != null ? _d : [],
2361
- earlyAccessEnabled: (_f = (_e = query.data) == null ? void 0 : _e.earlyAccessEnabled) != null ? _f : false,
2362
- authOptions: (_h = (_g = query.data) == null ? void 0 : _g.authOptions) != null ? _h : [],
2363
- tradingMode: (_i = query.data) == null ? void 0 : _i.tradingMode,
2364
- paperStartingBalance: (_j = query.data) == null ? void 0 : _j.paperStartingBalance,
2555
+ prophetxExecutionMode: query.data ? (_a = query.data.prophetxExecutionMode) != null ? _a : "clearinghouse" : void 0,
2556
+ disabledVenues: (_c = (_b = query.data) == null ? void 0 : _b.disabledVenues) != null ? _c : [],
2557
+ disabledCategoryPresets: (_e = (_d = query.data) == null ? void 0 : _d.disabledCategoryPresets) != null ? _e : [],
2558
+ earlyAccessEnabled: (_g = (_f = query.data) == null ? void 0 : _f.earlyAccessEnabled) != null ? _g : false,
2559
+ authOptions: (_i = (_h = query.data) == null ? void 0 : _h.authOptions) != null ? _i : [],
2560
+ tradingMode: (_j = query.data) == null ? void 0 : _j.tradingMode,
2561
+ paperStartingBalance: (_k = query.data) == null ? void 0 : _k.paperStartingBalance,
2365
2562
  isLoading: query.isLoading,
2366
2563
  error: query.error
2367
2564
  };
@@ -2423,254 +2620,11 @@ import {
2423
2620
  useCallback as useCallback4,
2424
2621
  useContext as useContext5,
2425
2622
  useEffect as useEffect2,
2426
- useMemo as useMemo4,
2623
+ useMemo as useMemo5,
2427
2624
  useRef as useRef2,
2428
2625
  useState as useState2
2429
2626
  } from "react";
2430
- import { useQueryClient as useQueryClient2 } from "@tanstack/react-query";
2431
-
2432
- // src/market-data/chart-cache.ts
2433
- var MAX_CACHE_RETENTION_SECONDS = 7 * 30 * 24 * 60 * 60 + 14 * 24 * 60 * 60;
2434
- var getIntervalSeconds = (interval) => {
2435
- switch (interval) {
2436
- case "1m":
2437
- return 60;
2438
- case "5m":
2439
- return 5 * 60;
2440
- case "1h":
2441
- return 60 * 60;
2442
- case "1d":
2443
- return 24 * 60 * 60;
2444
- }
2445
- };
2446
- var createVenueData = (venue, outcomeIds = []) => ({
2447
- venue,
2448
- outcomeIds,
2449
- candles: [],
2450
- liveCandle: null,
2451
- lineValue: void 0,
2452
- lastTrade: null,
2453
- lastUpdateTs: null
2454
- });
2455
- var pruneCandlesBefore = (candles, cutoffTs) => {
2456
- if (cutoffTs <= 0) return candles;
2457
- let firstKeptIndex = 0;
2458
- while (firstKeptIndex < candles.length && candles[firstKeptIndex].time < cutoffTs) {
2459
- firstKeptIndex += 1;
2460
- }
2461
- if (firstKeptIndex === 0) return candles;
2462
- return candles.slice(firstKeptIndex);
2463
- };
2464
- var promoteClosedLiveCandle = (candles, liveCandle, expectedCandleTime) => {
2465
- if (!liveCandle || liveCandle.time >= expectedCandleTime) {
2466
- return { candles, promoted: false };
2467
- }
2468
- if (candles.some((candle) => candle.time === liveCandle.time)) {
2469
- return { candles, promoted: false };
2470
- }
2471
- return { candles: sortCandles([...candles, liveCandle]), promoted: true };
2472
- };
2473
- var resolveMaxLastUpdateTs = (venues) => {
2474
- let max = null;
2475
- for (const venueData of Object.values(venues)) {
2476
- if (venueData.lastUpdateTs != null && (max == null || venueData.lastUpdateTs > max)) {
2477
- max = venueData.lastUpdateTs;
2478
- }
2479
- }
2480
- return max;
2481
- };
2482
- var sortCandles = (candles) => {
2483
- return [...candles].sort((left, right) => left.time - right.time);
2484
- };
2485
- var createMarketChartData = (params) => {
2486
- var _a;
2487
- const candles = sortCandles(
2488
- params.response.data.map((candle) => ({
2489
- time: Math.floor(candle.t / 1e3),
2490
- open: candle.o,
2491
- high: candle.h,
2492
- low: candle.l,
2493
- close: candle.c,
2494
- volume: candle.v,
2495
- source: "rest"
2496
- }))
2497
- );
2498
- const lastCandle = candles[candles.length - 1];
2499
- const lastUpdateTs = (_a = lastCandle == null ? void 0 : lastCandle.time) != null ? _a : null;
2500
- const venues = {
2501
- [params.response.venue]: {
2502
- venue: params.response.venue,
2503
- outcomeIds: [params.response.venueMarketOutcomeId],
2504
- candles,
2505
- liveCandle: null,
2506
- lineValue: lastCandle == null ? void 0 : lastCandle.close,
2507
- lastTrade: null,
2508
- lastUpdateTs
2509
- }
2510
- };
2511
- return {
2512
- marketId: params.marketId,
2513
- outcomeIds: [params.response.venueMarketOutcomeId],
2514
- primaryVenue: params.response.venue,
2515
- interval: params.interval,
2516
- startTs: params.startTs,
2517
- endTs: params.endTs,
2518
- venues,
2519
- lastUpdateTs
2520
- };
2521
- };
2522
- var mergeMarketChartData = (params) => {
2523
- var _a, _b;
2524
- if (params.datasets.length === 0) {
2525
- return null;
2526
- }
2527
- const primaryVenue = (_b = (_a = params.datasets[0]) == null ? void 0 : _a.primaryVenue) != null ? _b : "aggregate";
2528
- const outcomeIds = Array.from(
2529
- new Set(
2530
- params.datasets.flatMap((dataset) => {
2531
- return dataset.outcomeIds.length > 0 ? dataset.outcomeIds : [dataset.marketId];
2532
- })
2533
- )
2534
- );
2535
- const venues = params.datasets.reduce((acc, dataset) => {
2536
- for (const [venue, venueData] of Object.entries(dataset.venues)) {
2537
- const existingVenueData = acc[venue];
2538
- acc[venue] = existingVenueData ? __spreadProps(__spreadValues({}, venueData), {
2539
- outcomeIds: Array.from(
2540
- /* @__PURE__ */ new Set([...existingVenueData.outcomeIds, ...venueData.outcomeIds])
2541
- )
2542
- }) : venueData;
2543
- }
2544
- return acc;
2545
- }, {});
2546
- return {
2547
- marketId: params.marketId,
2548
- outcomeIds,
2549
- primaryVenue,
2550
- interval: params.interval,
2551
- startTs: params.startTs,
2552
- endTs: params.endTs,
2553
- venues,
2554
- lastUpdateTs: resolveMaxLastUpdateTs(venues)
2555
- };
2556
- };
2557
- var applyMidpointToMarketChart = (data, update) => {
2558
- var _a;
2559
- if (!data || !Number.isFinite(update.midpoint)) {
2560
- return data;
2561
- }
2562
- const targetVenueEntry = Object.entries(data.venues).find(
2563
- ([, venueData]) => venueData.outcomeIds.includes(update.outcomeId)
2564
- );
2565
- if (!targetVenueEntry && data.marketId !== update.outcomeId) {
2566
- return data;
2567
- }
2568
- const [targetVenueName, currentVenue] = targetVenueEntry != null ? targetVenueEntry : [
2569
- data.primaryVenue,
2570
- (_a = data.venues[data.primaryVenue]) != null ? _a : createVenueData(data.primaryVenue, [update.outcomeId])
2571
- ];
2572
- const intervalSeconds = getIntervalSeconds(data.interval);
2573
- const expectedCandleTime = update.timestamp - update.timestamp % intervalSeconds;
2574
- let liveCandle = currentVenue.liveCandle;
2575
- const { candles: promotedCandles } = promoteClosedLiveCandle(
2576
- currentVenue.candles,
2577
- liveCandle,
2578
- expectedCandleTime
2579
- );
2580
- const nextCandles = pruneCandlesBefore(
2581
- promotedCandles,
2582
- update.timestamp - MAX_CACHE_RETENTION_SECONDS
2583
- );
2584
- if (liveCandle && liveCandle.time === expectedCandleTime) {
2585
- if (liveCandle.source === "trade") {
2586
- liveCandle = __spreadProps(__spreadValues({}, liveCandle), {
2587
- close: update.midpoint
2588
- });
2589
- } else {
2590
- liveCandle = __spreadProps(__spreadValues({}, liveCandle), {
2591
- close: update.midpoint,
2592
- high: Math.max(liveCandle.high, update.midpoint),
2593
- low: Math.min(liveCandle.low, update.midpoint),
2594
- source: "midpoint"
2595
- });
2596
- }
2597
- } else {
2598
- liveCandle = {
2599
- time: expectedCandleTime,
2600
- open: update.midpoint,
2601
- high: update.midpoint,
2602
- low: update.midpoint,
2603
- close: update.midpoint,
2604
- volume: 0,
2605
- source: "midpoint"
2606
- };
2607
- }
2608
- const nextVenues = __spreadProps(__spreadValues({}, data.venues), {
2609
- [targetVenueName]: __spreadProps(__spreadValues({}, currentVenue), {
2610
- outcomeIds: currentVenue.outcomeIds.includes(update.outcomeId) ? currentVenue.outcomeIds : [...currentVenue.outcomeIds, update.outcomeId],
2611
- candles: nextCandles,
2612
- liveCandle,
2613
- lineValue: update.midpoint,
2614
- lastUpdateTs: update.timestamp
2615
- })
2616
- });
2617
- return __spreadProps(__spreadValues({}, data), {
2618
- venues: nextVenues,
2619
- lastUpdateTs: resolveMaxLastUpdateTs(nextVenues)
2620
- });
2621
- };
2622
- var applyTradeToMarketChart = (data, trade) => {
2623
- var _a, _b, _c;
2624
- if (!data || data.marketId !== trade.outcomeId) {
2625
- return data;
2626
- }
2627
- const currentVenue = (_a = data.venues[trade.venue]) != null ? _a : createVenueData(trade.venue);
2628
- const intervalSeconds = getIntervalSeconds(data.interval);
2629
- const expectedCandleTime = trade.timestamp - trade.timestamp % intervalSeconds;
2630
- let liveCandle = currentVenue.liveCandle;
2631
- const { candles: promotedCandles } = promoteClosedLiveCandle(
2632
- currentVenue.candles,
2633
- liveCandle,
2634
- expectedCandleTime
2635
- );
2636
- const nextCandles = pruneCandlesBefore(
2637
- promotedCandles,
2638
- trade.timestamp - MAX_CACHE_RETENTION_SECONDS
2639
- );
2640
- if (liveCandle && liveCandle.time === expectedCandleTime) {
2641
- liveCandle = __spreadProps(__spreadValues({}, liveCandle), {
2642
- close: trade.price,
2643
- high: Math.max(liveCandle.high, trade.price),
2644
- low: Math.min(liveCandle.low, trade.price),
2645
- volume: ((_b = liveCandle.volume) != null ? _b : 0) + trade.size,
2646
- source: "trade"
2647
- });
2648
- } else if (!liveCandle || liveCandle.time !== expectedCandleTime) {
2649
- liveCandle = {
2650
- time: expectedCandleTime,
2651
- open: trade.price,
2652
- high: trade.price,
2653
- low: trade.price,
2654
- close: trade.price,
2655
- volume: trade.size,
2656
- source: "trade"
2657
- };
2658
- }
2659
- const nextVenues = __spreadProps(__spreadValues({}, data.venues), {
2660
- [trade.venue]: __spreadProps(__spreadValues({}, currentVenue), {
2661
- outcomeIds: currentVenue.outcomeIds.includes(trade.outcomeId) ? currentVenue.outcomeIds : [...currentVenue.outcomeIds, trade.outcomeId],
2662
- candles: nextCandles,
2663
- liveCandle,
2664
- lineValue: (_c = liveCandle == null ? void 0 : liveCandle.close) != null ? _c : trade.price,
2665
- lastTrade: trade,
2666
- lastUpdateTs: trade.timestamp
2667
- })
2668
- });
2669
- return __spreadProps(__spreadValues({}, data), {
2670
- venues: nextVenues,
2671
- lastUpdateTs: resolveMaxLastUpdateTs(nextVenues)
2672
- });
2673
- };
2627
+ import { useQueryClient as useQueryClient3 } from "@tanstack/react-query";
2674
2628
 
2675
2629
  // src/market-data/live-cache.ts
2676
2630
  var MAX_TRADES = 50;
@@ -2683,13 +2637,6 @@ var createMarketLiveState = (marketId, overrides) => __spreadValues({
2683
2637
  isConnected: false,
2684
2638
  integrity: "ok"
2685
2639
  }, overrides);
2686
- var withLiveConnectionState = (data, isConnected) => {
2687
- if (!data) return data;
2688
- if (data.isConnected === isConnected) return data;
2689
- return __spreadProps(__spreadValues({}, data), {
2690
- isConnected
2691
- });
2692
- };
2693
2640
  var withLiveOrderbook = (data, orderbook, source) => {
2694
2641
  const current = data != null ? data : createMarketLiveState(orderbook.marketId);
2695
2642
  return __spreadProps(__spreadValues({}, current), {
@@ -2724,133 +2671,254 @@ var withLiveTrade = (data, trade) => {
2724
2671
  });
2725
2672
  };
2726
2673
 
2727
- // src/market-data/orderbook-cache.ts
2728
- var truncateLevels = (levels, depth) => {
2729
- if (depth == null) return levels;
2730
- return levels.slice(0, Math.max(0, depth));
2674
+ // src/market-data/live-store.ts
2675
+ import { useMemo as useMemo4, useSyncExternalStore } from "react";
2676
+ import { useQueryClient as useQueryClient2 } from "@tanstack/react-query";
2677
+
2678
+ // src/market-data/query-keys.ts
2679
+ var marketDataKeys = {
2680
+ all: () => ["market-data"],
2681
+ live: (marketId) => ["market-data", "live", marketId],
2682
+ livePrefix: () => ["market-data", "live"],
2683
+ orderbook: (marketId, selectionKey, depth) => ["market-data", "orderbook", marketId, selectionKey != null ? selectionKey : null, depth != null ? depth : null],
2684
+ orderbookPrefix: (marketId) => marketId == null ? ["market-data", "orderbook"] : ["market-data", "orderbook", marketId],
2685
+ orderbookQuote: (marketId, side, size) => ["market-data", "orderbook-quote", marketId, side, size],
2686
+ /**
2687
+ * Stable per `{marketId, interval, rangeKey}`. Deliberately excludes the
2688
+ * concrete `startTs`/`endTs` of the rolling window — those advance every
2689
+ * candle bucket, and including them would mint a fresh key on every
2690
+ * rollover, defeating React Query's cache on tab/page revisits. The
2691
+ * current window is passed to `queryFn` via closure instead, and
2692
+ * `refetchInterval` advances the data under the stable key.
2693
+ */
2694
+ chart: (marketId, interval, rangeKey, countBack) => ["market-data", "chart", marketId, interval, rangeKey, countBack != null ? countBack : null],
2695
+ chartPrefix: (marketId, interval) => {
2696
+ if (!marketId) return ["market-data", "chart"];
2697
+ if (!interval) return ["market-data", "chart", marketId];
2698
+ return ["market-data", "chart", marketId, interval];
2699
+ }
2731
2700
  };
2732
- var truncateVenueOrderbooks = (venueOrderbooks, depth) => {
2733
- if (depth == null) return venueOrderbooks;
2734
- return Object.fromEntries(
2735
- Object.entries(venueOrderbooks).map(([venue, book]) => [
2736
- venue,
2737
- {
2738
- bids: truncateLevels(book.bids, depth),
2739
- asks: truncateLevels(book.asks, depth)
2740
- }
2741
- ])
2742
- );
2701
+
2702
+ // src/market-data/live-store.ts
2703
+ var LIVE_RETENTION = {
2704
+ maxInactiveSnapshots: 32,
2705
+ maxInactiveLevels: 16384,
2706
+ inactiveTtlMs: 5e3,
2707
+ maxEntries: 300
2743
2708
  };
2744
- var aggregateVenueLevels = (venueOrderbooks, side) => {
2745
- var _a;
2746
- const levelsByPrice = /* @__PURE__ */ new Map();
2747
- for (const [venue, orderbook] of Object.entries(venueOrderbooks)) {
2748
- for (const level of orderbook[side]) {
2749
- const currentLevel = levelsByPrice.get(level.price);
2750
- if (currentLevel) {
2751
- currentLevel.size += level.size;
2752
- currentLevel.venues[venue] = ((_a = currentLevel.venues[venue]) != null ? _a : 0) + level.size;
2753
- continue;
2754
- }
2755
- levelsByPrice.set(level.price, {
2756
- price: level.price,
2757
- size: level.size,
2758
- venues: {
2759
- [venue]: level.size
2760
- }
2709
+ var levelEntries = (state) => {
2710
+ var _a, _b, _c, _d, _e;
2711
+ const book = state.orderbook;
2712
+ return book ? ((_b = (_a = book.bids) == null ? void 0 : _a.length) != null ? _b : 0) + ((_d = (_c = book.asks) == null ? void 0 : _c.length) != null ? _d : 0) + Object.values((_e = book.venueOrderbooks) != null ? _e : {}).reduce(
2713
+ (n, venue) => n + venue.bids.length + venue.asks.length,
2714
+ 0
2715
+ ) : 0;
2716
+ };
2717
+ var hasSnapshot = (state) => !!state.orderbook || !!state.candles || state.trades.length > 0;
2718
+ var MarketLiveStore = class {
2719
+ constructor(seed) {
2720
+ this.seed = seed;
2721
+ this.connectionState = false;
2722
+ this.connectionGeneration = 0;
2723
+ this.states = /* @__PURE__ */ new Map();
2724
+ this.listeners = /* @__PURE__ */ new Map();
2725
+ this.touched = /* @__PURE__ */ new Map();
2726
+ this.needsPrune = false;
2727
+ }
2728
+ ensure(id) {
2729
+ var _a, _b;
2730
+ let state = this.states.get(id);
2731
+ if (state && !this.listeners.has(id) && Date.now() - ((_a = this.touched.get(id)) != null ? _a : 0) >= LIVE_RETENTION.inactiveTtlMs) {
2732
+ this.drop(id);
2733
+ state = void 0;
2734
+ }
2735
+ if (!state) {
2736
+ const seed = (_b = this.seed) == null ? void 0 : _b.call(this, id);
2737
+ state = __spreadProps(__spreadValues({}, createMarketLiveState(id, __spreadValues({ isConnected: this.connectionState }, seed))), {
2738
+ connectionGeneration: this.connectionGeneration,
2739
+ orderbookGeneration: (seed == null ? void 0 : seed.orderbook) ? -1 : this.connectionGeneration
2761
2740
  });
2741
+ this.states.set(id, state);
2742
+ this.touched.set(id, Date.now());
2743
+ this.needsPrune = true;
2762
2744
  }
2745
+ return state;
2746
+ }
2747
+ get(id) {
2748
+ const state = this.ensure(id);
2749
+ this.touched.set(id, Date.now());
2750
+ if (this.needsPrune) this.prune(/* @__PURE__ */ new Set([id]));
2751
+ return state;
2752
+ }
2753
+ /** Read retained data without creating a state, keeping it alive, or observing updates. */
2754
+ peek(id) {
2755
+ var _a;
2756
+ if (!this.listeners.has(id) && Date.now() - ((_a = this.touched.get(id)) != null ? _a : 0) >= LIVE_RETENTION.inactiveTtlMs)
2757
+ return void 0;
2758
+ return this.states.get(id);
2759
+ }
2760
+ /** Protect a render's whole selection before useSyncExternalStore subscribes. */
2761
+ getMany(ids) {
2762
+ const result = ids.map((id) => {
2763
+ const state = this.ensure(id);
2764
+ this.touched.set(id, Date.now());
2765
+ return state;
2766
+ });
2767
+ if (this.needsPrune) this.prune(new Set(ids));
2768
+ return result;
2769
+ }
2770
+ update(id, updater) {
2771
+ var _a;
2772
+ const previous = this.ensure(id);
2773
+ const next = updater(previous);
2774
+ if (!next || next === previous) return;
2775
+ const bookChanged = next.orderbook && (!previous.orderbook || next.orderbook.seq !== previous.orderbook.seq || next.orderbook.checksum !== previous.orderbook.checksum || next.orderbook.timestamp !== previous.orderbook.timestamp || next.orderbookSnapshotVersion !== previous.orderbookSnapshotVersion);
2776
+ this.states.set(
2777
+ id,
2778
+ bookChanged ? __spreadProps(__spreadValues({}, next), { orderbookGeneration: this.connectionGeneration }) : next
2779
+ );
2780
+ if (bookChanged || next.candles !== previous.candles || next.trades !== previous.trades)
2781
+ this.touched.set(id, Date.now());
2782
+ for (const listener of (_a = this.listeners.get(id)) != null ? _a : []) listener();
2783
+ if (!this.listeners.has(id) || this.needsPrune) this.prune(/* @__PURE__ */ new Set([id]));
2784
+ }
2785
+ connected(connected) {
2786
+ if (connected && !this.connectionState) this.connectionGeneration++;
2787
+ this.connectionState = connected;
2788
+ for (const id of [...this.states.keys()])
2789
+ this.update(
2790
+ id,
2791
+ (state) => state.isConnected === connected && state.connectionGeneration === this.connectionGeneration ? state : __spreadValues(__spreadProps(__spreadValues({}, state), {
2792
+ isConnected: connected,
2793
+ connectionGeneration: this.connectionGeneration
2794
+ }), connected ? {} : { candles: void 0 })
2795
+ );
2796
+ }
2797
+ subscribe(ids, listener) {
2798
+ var _a;
2799
+ for (const id of ids) {
2800
+ const set = (_a = this.listeners.get(id)) != null ? _a : /* @__PURE__ */ new Set();
2801
+ set.add(listener);
2802
+ this.listeners.set(id, set);
2803
+ this.touched.set(id, Date.now());
2804
+ }
2805
+ return () => {
2806
+ for (const id of ids) {
2807
+ const set = this.listeners.get(id);
2808
+ set == null ? void 0 : set.delete(listener);
2809
+ if (!(set == null ? void 0 : set.size)) {
2810
+ this.listeners.delete(id);
2811
+ this.touched.set(id, Date.now());
2812
+ }
2813
+ }
2814
+ this.prune();
2815
+ };
2816
+ }
2817
+ getDiagnostics() {
2818
+ const inactive = [...this.states].filter(([id]) => !this.listeners.has(id));
2819
+ return {
2820
+ entries: this.states.size,
2821
+ activeEntries: this.listeners.size,
2822
+ cachedBooks: [...this.states.values()].filter((state) => state.orderbook).length,
2823
+ cachedLevelEntries: [...this.states.values()].reduce(
2824
+ (n, state) => n + levelEntries(state),
2825
+ 0
2826
+ ),
2827
+ inactiveSnapshots: inactive.filter(([, state]) => hasSnapshot(state)).length,
2828
+ inactiveLevelEntries: inactive.reduce((n, [, state]) => n + levelEntries(state), 0),
2829
+ limits: LIVE_RETENTION
2830
+ };
2831
+ }
2832
+ drop(id) {
2833
+ this.states.delete(id);
2834
+ this.touched.delete(id);
2835
+ }
2836
+ prune(protectedIds = /* @__PURE__ */ new Set()) {
2837
+ var _a, _b;
2838
+ this.needsPrune = false;
2839
+ if (this.timer) clearTimeout(this.timer);
2840
+ this.timer = void 0;
2841
+ const now = Date.now();
2842
+ const inactive = [...this.states].filter(([id]) => !this.listeners.has(id) && !protectedIds.has(id)).sort(([a], [b]) => {
2843
+ var _a2, _b2;
2844
+ return ((_a2 = this.touched.get(a)) != null ? _a2 : 0) - ((_b2 = this.touched.get(b)) != null ? _b2 : 0);
2845
+ });
2846
+ let count = inactive.filter(([, state]) => hasSnapshot(state)).length;
2847
+ let levels = inactive.reduce((n, [, state]) => n + levelEntries(state), 0);
2848
+ for (const [id, state] of inactive) {
2849
+ if (now - ((_a = this.touched.get(id)) != null ? _a : 0) >= LIVE_RETENTION.inactiveTtlMs || this.states.size > LIVE_RETENTION.maxEntries || count > LIVE_RETENTION.maxInactiveSnapshots || levels > LIVE_RETENTION.maxInactiveLevels) {
2850
+ if (hasSnapshot(state)) count--;
2851
+ levels -= levelEntries(state);
2852
+ this.drop(id);
2853
+ }
2854
+ }
2855
+ let nextExpiry = Infinity;
2856
+ for (const id of this.states.keys())
2857
+ if (!this.listeners.has(id))
2858
+ nextExpiry = Math.min(
2859
+ nextExpiry,
2860
+ ((_b = this.touched.get(id)) != null ? _b : now) + LIVE_RETENTION.inactiveTtlMs
2861
+ );
2862
+ if (Number.isFinite(nextExpiry))
2863
+ this.timer = setTimeout(
2864
+ () => {
2865
+ this.timer = void 0;
2866
+ this.prune();
2867
+ },
2868
+ Math.max(1, nextExpiry - now)
2869
+ );
2763
2870
  }
2764
- return [...levelsByPrice.values()].sort(
2765
- (left, right) => side === "bids" ? right.price - left.price : left.price - right.price
2766
- );
2767
- };
2768
- var createMarketOrderbookDataFromVenueOrderbooks = ({
2769
- marketId,
2770
- venueOrderbooks,
2771
- timestamp = Math.floor(Date.now() / 1e3)
2772
- }) => {
2773
- var _a, _b, _c, _d;
2774
- const bids = aggregateVenueLevels(venueOrderbooks, "bids");
2775
- const asks = aggregateVenueLevels(venueOrderbooks, "asks");
2776
- const bestBid = (_b = (_a = bids[0]) == null ? void 0 : _a.price) != null ? _b : null;
2777
- const bestAsk = (_d = (_c = asks[0]) == null ? void 0 : _c.price) != null ? _d : null;
2778
- return {
2779
- marketId,
2780
- orderbook: {
2781
- bids,
2782
- asks
2783
- },
2784
- venueOrderbooks,
2785
- venues: Object.fromEntries(
2786
- Object.entries(venueOrderbooks).map(([venue, orderbook]) => {
2787
- var _a2, _b2, _c2, _d2;
2788
- return [
2789
- venue,
2790
- {
2791
- bestBid: (_b2 = (_a2 = orderbook.bids[0]) == null ? void 0 : _a2.price) != null ? _b2 : null,
2792
- bestAsk: (_d2 = (_c2 = orderbook.asks[0]) == null ? void 0 : _c2.price) != null ? _d2 : null
2793
- }
2794
- ];
2795
- })
2796
- ),
2797
- midpoint: bestBid != null && bestAsk != null ? (bestBid + bestAsk) / 2 : null,
2798
- spread: bestBid != null && bestAsk != null ? bestAsk - bestBid : null,
2799
- timestamp,
2800
- snapshotVersion: 0,
2801
- integrity: "ok"
2802
- };
2803
- };
2804
- var createMarketOrderbookDataFromState = (state, options) => {
2805
- var _a;
2806
- return {
2807
- marketId: state.marketId,
2808
- orderbook: {
2809
- bids: state.bids,
2810
- asks: state.asks
2811
- },
2812
- venueOrderbooks: state.venueOrderbooks,
2813
- venues: state.venues,
2814
- midpoint: state.midpoint,
2815
- spread: state.spread,
2816
- timestamp: state.timestamp,
2817
- snapshotVersion: (_a = options == null ? void 0 : options.snapshotVersion) != null ? _a : 0,
2818
- seq: state.seq,
2819
- checksum: state.checksum,
2820
- integrity: "ok"
2821
- };
2822
- };
2823
- var marketOrderbookDataToResponse = (data) => {
2824
- return {
2825
- venueMarketId: data.marketId,
2826
- orderbook: data.orderbook,
2827
- venueOrderbooks: data.venueOrderbooks,
2828
- venues: data.venues,
2829
- midpoint: data.midpoint,
2830
- spread: data.spread,
2831
- timestamp: data.timestamp,
2832
- seq: data.seq,
2833
- checksum: data.checksum,
2834
- matchedMarkets: data.matchedMarkets
2835
- };
2836
- };
2837
- var withOrderbookIntegrity = (data, integrity) => {
2838
- if (!data) return data;
2839
- if (data.integrity === integrity) return data;
2840
- return __spreadProps(__spreadValues({}, data), {
2841
- integrity
2842
- });
2843
- };
2844
- var applyOrderbookDepth = (data, depth) => {
2845
- if (depth == null) return data;
2846
- return __spreadProps(__spreadValues({}, data), {
2847
- orderbook: {
2848
- bids: truncateLevels(data.orderbook.bids, depth),
2849
- asks: truncateLevels(data.orderbook.asks, depth)
2850
- },
2851
- venueOrderbooks: truncateVenueOrderbooks(data.venueOrderbooks, depth)
2852
- });
2853
2871
  };
2872
+ var stores = /* @__PURE__ */ new WeakMap();
2873
+ function getMarketLiveStore(client) {
2874
+ let store = stores.get(client);
2875
+ if (!store) {
2876
+ store = new MarketLiveStore((id) => {
2877
+ var _a;
2878
+ return (_a = client.getQueryData) == null ? void 0 : _a.call(client, marketDataKeys.live(id));
2879
+ });
2880
+ stores.set(client, store);
2881
+ }
2882
+ return store;
2883
+ }
2884
+ function useLiveStates(ids) {
2885
+ const client = useQueryClient2();
2886
+ const store = getMarketLiveStore(client);
2887
+ const key = JSON.stringify(ids);
2888
+ const selector = useMemo4(() => {
2889
+ const selectedIds = JSON.parse(key);
2890
+ let previous = [];
2891
+ return {
2892
+ subscribe: (listener) => store.subscribe(selectedIds, listener),
2893
+ get: () => {
2894
+ const next = store.getMany(selectedIds).map((data) => ({ data }));
2895
+ if (next.length === previous.length && next.every((entry, index) => {
2896
+ var _a;
2897
+ return entry.data === ((_a = previous[index]) == null ? void 0 : _a.data);
2898
+ }))
2899
+ return previous;
2900
+ previous = next;
2901
+ return next;
2902
+ }
2903
+ };
2904
+ }, [key, store]);
2905
+ return useSyncExternalStore(selector.subscribe, selector.get, selector.get);
2906
+ }
2907
+ function mergeCandleTails(previous, next) {
2908
+ return Object.fromEntries(
2909
+ ["1m", "5m", "1h", "1d"].map((interval) => {
2910
+ var _a;
2911
+ const oldClosed = (_a = previous == null ? void 0 : previous[interval].closed) != null ? _a : [];
2912
+ const incoming = next[interval].closed;
2913
+ const closed = incoming.length ? [
2914
+ ...new Map(
2915
+ [...oldClosed, ...incoming].map((candle) => [candle.openTime, candle])
2916
+ ).values()
2917
+ ].sort((a, b) => a.openTime - b.openTime).slice(-500) : oldClosed;
2918
+ return [interval, { forming: next[interval].forming, closed }];
2919
+ })
2920
+ );
2921
+ }
2854
2922
 
2855
2923
  // src/market-data/market-resolution-cache.ts
2856
2924
  var isRecord = (value) => {
@@ -2944,29 +3012,116 @@ var applyResolutionToCachedData = (data, resolution) => {
2944
3012
  return changed ? next : data;
2945
3013
  };
2946
3014
 
2947
- // src/market-data/query-keys.ts
2948
- var marketDataKeys = {
2949
- all: () => ["market-data"],
2950
- live: (marketId) => ["market-data", "live", marketId],
2951
- livePrefix: () => ["market-data", "live"],
2952
- orderbook: (marketId, selectionKey, depth) => ["market-data", "orderbook", marketId, selectionKey != null ? selectionKey : null, depth != null ? depth : null],
2953
- orderbookPrefix: (marketId) => marketId == null ? ["market-data", "orderbook"] : ["market-data", "orderbook", marketId],
2954
- orderbookQuote: (marketId, side, size) => ["market-data", "orderbook-quote", marketId, side, size],
2955
- /**
2956
- * Stable per `{marketId, interval, rangeKey}`. Deliberately excludes the
2957
- * concrete `startTs`/`endTs` of the rolling window — those advance every
2958
- * candle bucket, and including them would mint a fresh key on every
2959
- * rollover, defeating React Query's cache on tab/page revisits. The
2960
- * current window is passed to `queryFn` via closure instead, and
2961
- * `refetchInterval` advances the data under the stable key.
2962
- */
2963
- chart: (marketId, interval, rangeKey, countBack) => ["market-data", "chart", marketId, interval, rangeKey, countBack != null ? countBack : null],
2964
- chartPrefix: (marketId, interval) => {
2965
- if (!marketId) return ["market-data", "chart"];
2966
- if (!interval) return ["market-data", "chart", marketId];
2967
- return ["market-data", "chart", marketId, interval];
2968
- }
3015
+ // src/market-data/history-retention.ts
3016
+ var DEFAULT_HISTORY_RETENTION = {
3017
+ maxInactiveQueries: 16,
3018
+ maxInactivePoints: 2e4
3019
+ };
3020
+ var owners = /* @__PURE__ */ new WeakMap();
3021
+ var isHistory = (key) => key[0] === "market-data" && key[1] === "chart";
3022
+ var points = (data) => {
3023
+ const chart = data;
3024
+ return (chart == null ? void 0 : chart.venues) ? Object.values(chart.venues).reduce(
3025
+ (total, venue) => total + venue.candles.length + (venue.liveCandle ? 1 : 0),
3026
+ 0
3027
+ ) : 0;
2969
3028
  };
3029
+ function getChartHistoryRetentionStats(client) {
3030
+ var _a, _b, _c;
3031
+ const queries = client.getQueryCache().findAll({ queryKey: marketDataKeys.chartPrefix() });
3032
+ const active = queries.filter((query) => query.getObserversCount() > 0);
3033
+ const inactive = queries.filter((query) => query.getObserversCount() === 0);
3034
+ const owner = owners.get(client);
3035
+ return {
3036
+ activeQueries: active.length,
3037
+ inactiveQueries: inactive.length,
3038
+ activePoints: active.reduce((sum, query) => sum + points(query.state.data), 0),
3039
+ inactivePoints: inactive.reduce((sum, query) => sum + points(query.state.data), 0),
3040
+ inFlightQueries: queries.filter((query) => query.state.fetchStatus === "fetching").length,
3041
+ trackedQueries: (_a = owner == null ? void 0 : owner.touched.size) != null ? _a : 0,
3042
+ evictedQueries: (_b = owner == null ? void 0 : owner.evicted) != null ? _b : 0,
3043
+ limits: (_c = owner == null ? void 0 : owner.limits) != null ? _c : DEFAULT_HISTORY_RETENTION
3044
+ };
3045
+ }
3046
+ function installChartHistoryRetention(client, limits = DEFAULT_HISTORY_RETENTION) {
3047
+ let owner = owners.get(client);
3048
+ if (!owner) {
3049
+ owner = {
3050
+ refs: 0,
3051
+ clock: Date.now(),
3052
+ touched: /* @__PURE__ */ new Map(),
3053
+ evicted: 0,
3054
+ queued: false,
3055
+ pruning: false,
3056
+ limits,
3057
+ unsubscribe: () => {
3058
+ },
3059
+ prune: () => {
3060
+ }
3061
+ };
3062
+ owners.set(client, owner);
3063
+ const current2 = owner;
3064
+ const prune = () => {
3065
+ if (current2.pruning) return;
3066
+ current2.pruning = true;
3067
+ try {
3068
+ const inactive = client.getQueryCache().findAll({ queryKey: marketDataKeys.chartPrefix() }).filter((query) => query.getObserversCount() === 0).sort(
3069
+ (a, b) => {
3070
+ var _a, _b;
3071
+ return ((_a = current2.touched.get(a.queryHash)) != null ? _a : a.state.dataUpdatedAt) - ((_b = current2.touched.get(b.queryHash)) != null ? _b : b.state.dataUpdatedAt);
3072
+ }
3073
+ );
3074
+ let count = inactive.length;
3075
+ let totalPoints = inactive.reduce((sum, query) => sum + points(query.state.data), 0);
3076
+ for (const query of inactive) {
3077
+ if (count <= current2.limits.maxInactiveQueries && totalPoints <= current2.limits.maxInactivePoints)
3078
+ break;
3079
+ if (query.getObserversCount() > 0) continue;
3080
+ count--;
3081
+ totalPoints -= points(query.state.data);
3082
+ current2.evicted++;
3083
+ current2.touched.delete(query.queryHash);
3084
+ client.removeQueries({ queryKey: query.queryKey, exact: true });
3085
+ }
3086
+ } finally {
3087
+ current2.pruning = false;
3088
+ }
3089
+ };
3090
+ current2.prune = prune;
3091
+ const schedule = () => {
3092
+ if (current2.queued) return;
3093
+ current2.queued = true;
3094
+ queueMicrotask(() => {
3095
+ current2.queued = false;
3096
+ prune();
3097
+ });
3098
+ };
3099
+ current2.unsubscribe = client.getQueryCache().subscribe((event) => {
3100
+ if (!isHistory(event.query.queryKey)) return;
3101
+ if (event.type === "removed") current2.touched.delete(event.query.queryHash);
3102
+ else if (event.type === "observerAdded" || event.type === "updated" || event.type === "added") {
3103
+ current2.clock = Math.max(current2.clock + 1, Date.now());
3104
+ current2.touched.set(event.query.queryHash, current2.clock);
3105
+ }
3106
+ if (!current2.pruning) schedule();
3107
+ });
3108
+ schedule();
3109
+ }
3110
+ owner.refs++;
3111
+ const current = owner;
3112
+ let released = false;
3113
+ return () => {
3114
+ if (released) return;
3115
+ released = true;
3116
+ if (--current.refs > 0) return;
3117
+ queueMicrotask(() => {
3118
+ if (current.refs > 0) return;
3119
+ current.prune();
3120
+ current.unsubscribe();
3121
+ owners.delete(client);
3122
+ });
3123
+ };
3124
+ }
2970
3125
 
2971
3126
  // src/core/providers/hooks.ts
2972
3127
  import { useContext as useContext4 } from "react";
@@ -3013,20 +3168,12 @@ var AggWebSocketContext = createContext3(null);
3013
3168
  var AggWebSocketConnectionContext = createContext3(false);
3014
3169
  var AggWsUserEventContext = createContext3(null);
3015
3170
  var snapshotUnavailableOutcomeIdPattern = /snapshot unavailable for\s+([^\s]+)/i;
3016
- var ORDERBOOK_DEBUG_TOP_LEVELS = 5;
3017
3171
  var resolveSnapshotUnavailableOutcomeId = (errorMessage) => {
3018
3172
  var _a;
3019
3173
  const matchedOutcomeId = (_a = snapshotUnavailableOutcomeIdPattern.exec(errorMessage)) == null ? void 0 : _a[1];
3020
3174
  if (!matchedOutcomeId) return null;
3021
3175
  return matchedOutcomeId.replace(/[.,;:!?]+$/, "");
3022
3176
  };
3023
- var summarizeTopLevels = (levels) => {
3024
- return levels.slice(0, ORDERBOOK_DEBUG_TOP_LEVELS).map((level) => ({ price: level.price, size: level.size }));
3025
- };
3026
- var debugOrderbook = (enabled, event, payload) => {
3027
- if (!enabled) return;
3028
- console.debug(`[AggHooks][ws-provider] ${event}`, payload);
3029
- };
3030
3177
  function useAggWebSocket() {
3031
3178
  return useContext5(AggWebSocketContext);
3032
3179
  }
@@ -3106,7 +3253,9 @@ function useOnWithdrawalLifecycle(callback) {
3106
3253
  function AggWebSocketProvider({ children }) {
3107
3254
  const client = useAggClient();
3108
3255
  const { enableWebsocketsLogs } = useAggUiConfig();
3109
- const queryClient = useQueryClient2();
3256
+ const queryClient = useQueryClient3();
3257
+ const liveStore = getMarketLiveStore(queryClient);
3258
+ useEffect2(() => installChartHistoryRetention(queryClient), [queryClient]);
3110
3259
  const [ws, setWs] = useState2(null);
3111
3260
  const [isConnected, setIsConnected] = useState2(false);
3112
3261
  const [isClientAuthenticated, setIsClientAuthenticated] = useState2(client.isAuthenticated);
@@ -3126,7 +3275,7 @@ function AggWebSocketProvider({ children }) {
3126
3275
  const withdrawalLifecycleListenersRef = useRef2(
3127
3276
  /* @__PURE__ */ new Set()
3128
3277
  );
3129
- const userEventListeners = useMemo4(
3278
+ const userEventListeners = useMemo5(
3130
3279
  () => ({
3131
3280
  addOrderSubmittedListener: (cb) => {
3132
3281
  orderSubmittedListenersRef.current.add(cb);
@@ -3161,43 +3310,11 @@ function AggWebSocketProvider({ children }) {
3161
3310
  }),
3162
3311
  []
3163
3312
  );
3164
- const syncOrderbookQueries = useCallback4(
3165
- (marketId, updater) => {
3166
- var _a;
3167
- const queries = queryClient.getQueryCache().findAll({
3168
- queryKey: marketDataKeys.orderbookPrefix(marketId)
3169
- });
3170
- for (const query of queries) {
3171
- const depth = (_a = query.queryKey[4]) != null ? _a : null;
3172
- queryClient.setQueryData(
3173
- query.queryKey,
3174
- (previous) => updater(query.queryKey, depth, previous)
3175
- );
3176
- }
3177
- },
3178
- [queryClient]
3179
- );
3180
- const syncChartQueries = useCallback4(
3181
- (marketId, updater) => {
3182
- const queries = queryClient.getQueryCache().findAll({
3183
- queryKey: marketDataKeys.chartPrefix(marketId)
3184
- });
3185
- for (const query of queries) {
3186
- queryClient.setQueryData(
3187
- query.queryKey,
3188
- (previous) => updater(query.queryKey, previous)
3189
- );
3190
- }
3191
- },
3192
- [queryClient]
3193
- );
3194
3313
  const syncLiveQuery = useCallback4(
3195
3314
  (marketId, updater) => {
3196
- queryClient.setQueryData(marketDataKeys.live(marketId), (previous) => {
3197
- return updater(previous);
3198
- });
3315
+ liveStore.update(marketId, (previous) => updater(previous));
3199
3316
  },
3200
- [queryClient]
3317
+ [liveStore]
3201
3318
  );
3202
3319
  const invalidateBalanceCaches = useCallback4(() => {
3203
3320
  const now = Date.now();
@@ -3216,9 +3333,9 @@ function AggWebSocketProvider({ children }) {
3216
3333
  const { outcomeId } = resolution;
3217
3334
  syncLiveQuery(outcomeId, (previous) => {
3218
3335
  if (!previous) return previous;
3219
- if (previous.orderbook == null && previous.orderbookError == null) return previous;
3220
3336
  return __spreadProps(__spreadValues({}, previous), {
3221
3337
  orderbook: null,
3338
+ orderbookSnapshotVersion: previous.orderbookSnapshotVersion + 1,
3222
3339
  orderbookError: null,
3223
3340
  integrity: "ok"
3224
3341
  });
@@ -3267,93 +3384,63 @@ function AggWebSocketProvider({ children }) {
3267
3384
  },
3268
3385
  [queryClient, syncLiveQuery]
3269
3386
  );
3270
- const callbacks = useMemo4(
3387
+ const publishLocalCandles = useCallback4(
3388
+ (id) => {
3389
+ const builder = getOrCreateBuilder(id);
3390
+ const candles = Object.fromEntries(
3391
+ ["1m", "5m", "1h", "1d"].map((interval) => [
3392
+ interval,
3393
+ {
3394
+ forming: builder.getForming(interval) ? __spreadValues({}, builder.getForming(interval)) : null,
3395
+ closed: builder.getClosed(interval).slice(-2)
3396
+ }
3397
+ ])
3398
+ );
3399
+ liveStore.update(id, (previous) => __spreadProps(__spreadValues({}, previous), { candles }));
3400
+ },
3401
+ [liveStore]
3402
+ );
3403
+ const callbacks = useMemo5(
3271
3404
  () => ({
3405
+ onMarketView: (view) => {
3406
+ if (view.book && view.integrity === "ok")
3407
+ resyncDeadlineByMarketRef.current.delete(view.outcomeId);
3408
+ liveStore.update(view.outcomeId, (previous) => __spreadProps(__spreadValues({}, view.book ? withLiveOrderbook(previous, view.book, view.snapshot ? "snapshot" : "delta") : previous), {
3409
+ integrity: view.integrity,
3410
+ candles: mergeCandleTails(previous.candles, view.candles),
3411
+ receivedAtMs: view.receivedAtMs,
3412
+ trades: [...view.trades, ...previous.trades].slice(0, 50)
3413
+ }));
3414
+ getOrCreateBuilder(view.outcomeId).replaceTail(view.candles);
3415
+ },
3272
3416
  onSnapshot: (marketId, book) => {
3273
- const orderbook = createMarketOrderbookDataFromState(book);
3417
+ var _a, _b;
3418
+ if ((_a = wsRef.current) == null ? void 0 : _a.processesCandles) return;
3274
3419
  resyncDeadlineByMarketRef.current.delete(marketId);
3275
- syncOrderbookQueries(marketId, (_queryKey, depth, previous) => {
3276
- var _a;
3277
- const previousSnapshotVersion = (_a = previous == null ? void 0 : previous.snapshotVersion) != null ? _a : 0;
3278
- return applyOrderbookDepth(
3279
- __spreadProps(__spreadValues({}, orderbook), {
3280
- snapshotVersion: previousSnapshotVersion + 1
3281
- }),
3282
- depth
3283
- );
3284
- });
3285
3420
  syncLiveQuery(marketId, (previous) => withLiveOrderbook(previous, book, "snapshot"));
3286
- if (book.midpoint != null) {
3421
+ if (!((_b = wsRef.current) == null ? void 0 : _b.processesCandles) && book.midpoint != null) {
3287
3422
  getOrCreateBuilder(marketId).addMidpoint(book.midpoint, book.timestamp);
3288
- syncChartQueries(
3289
- marketId,
3290
- (_queryKey, previous) => applyMidpointToMarketChart(previous, {
3291
- outcomeId: marketId,
3292
- midpoint: book.midpoint,
3293
- timestamp: book.timestamp
3294
- })
3295
- );
3423
+ publishLocalCandles(marketId);
3296
3424
  }
3297
3425
  },
3298
3426
  onDelta: (marketId, book) => {
3299
3427
  var _a, _b;
3300
- const previousLiveState = queryClient.getQueryData(marketDataKeys.live(marketId));
3301
- debugOrderbook(enableWebsocketsLogs, "delta_received", {
3302
- outcomeId: marketId,
3303
- seq: book.seq,
3304
- checksum: book.checksum,
3305
- hasTargetOrderbook: Boolean(previousLiveState == null ? void 0 : previousLiveState.orderbook),
3306
- beforeTop: (previousLiveState == null ? void 0 : previousLiveState.orderbook) ? {
3307
- bids: summarizeTopLevels(previousLiveState.orderbook.bids),
3308
- asks: summarizeTopLevels(previousLiveState.orderbook.asks)
3309
- } : null,
3310
- afterTop: {
3311
- bids: summarizeTopLevels(book.bids),
3312
- asks: summarizeTopLevels(book.asks)
3313
- }
3314
- });
3315
- const orderbook = createMarketOrderbookDataFromState(book);
3428
+ if ((_a = wsRef.current) == null ? void 0 : _a.processesCandles) return;
3316
3429
  resyncDeadlineByMarketRef.current.delete(marketId);
3317
- syncOrderbookQueries(marketId, (_queryKey, depth, previous) => {
3318
- var _a2;
3319
- const previousSnapshotVersion = (_a2 = previous == null ? void 0 : previous.snapshotVersion) != null ? _a2 : 0;
3320
- return applyOrderbookDepth(
3321
- __spreadProps(__spreadValues({}, orderbook), {
3322
- snapshotVersion: previousSnapshotVersion
3323
- }),
3324
- depth
3325
- );
3326
- });
3327
3430
  syncLiveQuery(marketId, (previous) => withLiveOrderbook(previous, book, "delta"));
3328
- const nextLiveState = queryClient.getQueryData(
3329
- marketDataKeys.live(marketId)
3330
- );
3331
- debugOrderbook(enableWebsocketsLogs, "delta_cached", {
3332
- outcomeId: marketId,
3333
- seq: (_b = (_a = nextLiveState == null ? void 0 : nextLiveState.orderbook) == null ? void 0 : _a.seq) != null ? _b : null,
3334
- selectorTop: (nextLiveState == null ? void 0 : nextLiveState.orderbook) ? {
3335
- bids: summarizeTopLevels(nextLiveState.orderbook.bids),
3336
- asks: summarizeTopLevels(nextLiveState.orderbook.asks)
3337
- } : null
3338
- });
3339
- if (book.midpoint != null) {
3431
+ if (!((_b = wsRef.current) == null ? void 0 : _b.processesCandles) && book.midpoint != null) {
3340
3432
  getOrCreateBuilder(marketId).addMidpoint(book.midpoint, book.timestamp);
3341
- syncChartQueries(
3342
- marketId,
3343
- (_queryKey, previous) => applyMidpointToMarketChart(previous, {
3344
- outcomeId: marketId,
3345
- midpoint: book.midpoint,
3346
- timestamp: book.timestamp
3347
- })
3348
- );
3433
+ publishLocalCandles(marketId);
3349
3434
  }
3350
3435
  },
3351
3436
  onTrade: (trade) => {
3352
- syncChartQueries(trade.outcomeId, (_queryKey, previous) => {
3353
- return applyTradeToMarketChart(previous, trade);
3354
- });
3437
+ var _a, _b;
3438
+ if ((_a = wsRef.current) == null ? void 0 : _a.processesCandles) return;
3355
3439
  syncLiveQuery(trade.outcomeId, (previous) => withLiveTrade(previous, trade));
3356
- getOrCreateBuilder(trade.outcomeId).addTrade(trade.price, trade.size, trade.timestamp);
3440
+ if (!((_b = wsRef.current) == null ? void 0 : _b.processesCandles)) {
3441
+ getOrCreateBuilder(trade.outcomeId).addTrade(trade.price, trade.size, trade.timestamp);
3442
+ publishLocalCandles(trade.outcomeId);
3443
+ }
3357
3444
  },
3358
3445
  onHeartbeat: () => {
3359
3446
  const now = Date.now();
@@ -3369,10 +3456,6 @@ function AggWebSocketProvider({ children }) {
3369
3456
  if (event.type !== "seq_gap" && event.type !== "checksum_mismatch") return;
3370
3457
  const id = (_a = event.outcomeId) != null ? _a : event.marketId;
3371
3458
  resyncDeadlineByMarketRef.current.set(id, Date.now() + 35e3);
3372
- syncOrderbookQueries(
3373
- id,
3374
- (_queryKey, _depth, previous) => withOrderbookIntegrity(previous, "resyncing")
3375
- );
3376
3459
  syncLiveQuery(id, (previous) => withLiveIntegrity(previous, "resyncing"));
3377
3460
  },
3378
3461
  onOrderSubmitted: (msg) => {
@@ -3441,38 +3524,34 @@ function AggWebSocketProvider({ children }) {
3441
3524
  } else {
3442
3525
  resetAllBuilders();
3443
3526
  }
3444
- const liveQueries = queryClient.getQueryCache().findAll({
3445
- queryKey: marketDataKeys.livePrefix()
3446
- });
3447
- for (const query of liveQueries) {
3448
- queryClient.setQueryData(query.queryKey, (previous) => {
3449
- return withLiveConnectionState(
3450
- previous,
3451
- connected
3452
- );
3453
- });
3454
- }
3527
+ liveStore.connected(connected);
3455
3528
  }
3456
3529
  }),
3457
3530
  [
3458
3531
  client,
3459
- enableWebsocketsLogs,
3460
3532
  invalidateActivityCaches,
3461
3533
  invalidateBalanceCaches,
3462
3534
  invalidatePositionCaches,
3463
3535
  invalidateResolutionCaches,
3464
3536
  isClientAuthenticated,
3465
3537
  queryClient,
3466
- syncChartQueries,
3467
3538
  syncLiveQuery,
3468
- syncOrderbookQueries
3539
+ liveStore,
3540
+ publishLocalCandles
3469
3541
  ]
3470
3542
  );
3543
+ const callbacksRef = useRef2(callbacks);
3544
+ callbacksRef.current = callbacks;
3545
+ useEffect2(() => {
3546
+ var _a;
3547
+ (_a = wsRef.current) == null ? void 0 : _a.setCallbacks(callbacks);
3548
+ }, [callbacks]);
3471
3549
  useEffect2(() => {
3550
+ var _a;
3472
3551
  let instance = null;
3473
3552
  const resyncDeadlineByMarket = resyncDeadlineByMarketRef.current;
3474
3553
  try {
3475
- instance = client.createWebSocket(callbacks, { enableLogs: enableWebsocketsLogs });
3554
+ instance = client.createWebSocket(callbacksRef.current, { enableLogs: enableWebsocketsLogs });
3476
3555
  } catch (e) {
3477
3556
  console.warn(
3478
3557
  "[AggUI] WebSocket connection could not be established. Ensure wsUrl is configured in createAggClient(). Real-time features (live prices, order updates) are disabled."
@@ -3482,6 +3561,11 @@ function AggWebSocketProvider({ children }) {
3482
3561
  setIsConnected(false);
3483
3562
  return;
3484
3563
  }
3564
+ (_a = instance.setHostDiagnostics) == null ? void 0 : _a.call(instance, () => ({
3565
+ live: liveStore.getDiagnostics(),
3566
+ history: getChartHistoryRetentionStats(queryClient),
3567
+ candles: getCandleStoreDiagnostics()
3568
+ }));
3485
3569
  setWs(instance);
3486
3570
  wsRef.current = instance;
3487
3571
  return () => {
@@ -3493,12 +3577,12 @@ function AggWebSocketProvider({ children }) {
3493
3577
  setWs(null);
3494
3578
  setIsConnected(false);
3495
3579
  };
3496
- }, [callbacks, client, enableWebsocketsLogs, isClientAuthenticated]);
3580
+ }, [client, enableWebsocketsLogs, isClientAuthenticated, liveStore, queryClient]);
3497
3581
  return /* @__PURE__ */ jsx6(AggWebSocketConnectionContext.Provider, { value: isConnected, children: /* @__PURE__ */ jsx6(AggWsUserEventContext.Provider, { value: userEventListeners, children: /* @__PURE__ */ jsx6(AggWebSocketContext.Provider, { value: ws, children }) }) });
3498
3582
  }
3499
3583
 
3500
3584
  // src/core/providers/ui-provider.tsx
3501
- import { useCallback as useCallback6, useEffect as useEffect3, useMemo as useMemo6, useState as useState3 } from "react";
3585
+ import { useCallback as useCallback6, useEffect as useEffect3, useMemo as useMemo7, useState as useState3 } from "react";
3502
3586
 
3503
3587
  // src/core/ui-config/constants.ts
3504
3588
  var DEFAULT_AGG_ROOT_CLASS_NAME = "agg-root";
@@ -3575,7 +3659,7 @@ var applyThemeToDocument = (theme) => {
3575
3659
  };
3576
3660
 
3577
3661
  // src/core/providers/event-trading-context.tsx
3578
- import { createContext as createContext4, useCallback as useCallback5, useContext as useContext6, useMemo as useMemo5, useReducer, useRef as useRef3 } from "react";
3662
+ import { createContext as createContext4, useCallback as useCallback5, useContext as useContext6, useMemo as useMemo6, useReducer, useRef as useRef3 } from "react";
3579
3663
  import { jsx as jsx7 } from "react/jsx-runtime";
3580
3664
  var OPEN_TRADING_STATE = {
3581
3665
  kind: "open",
@@ -3976,7 +4060,7 @@ var EventTradingProvider = ({
3976
4060
  (tradeSide) => dispatch({ type: "SET_TRADE_SIDE", tradeSide }),
3977
4061
  [dispatch]
3978
4062
  );
3979
- const value = useMemo5(
4063
+ const value = useMemo6(
3980
4064
  () => {
3981
4065
  var _a2, _b2, _c, _d, _e, _f, _g, _h, _i;
3982
4066
  return {
@@ -4043,8 +4127,8 @@ var getSearchStateAfterSelect = (selectedEvent) => {
4043
4127
  };
4044
4128
  };
4045
4129
  var AggUiProvider = ({ config, children }) => {
4046
- const persisted = useMemo6(() => loadPersistedConfig(), []);
4047
- const mergedConfig = useMemo6(() => mergeAggUiConfig(persisted, config), [persisted, config]);
4130
+ const persisted = useMemo7(() => loadPersistedConfig(), []);
4131
+ const mergedConfig = useMemo7(() => mergeAggUiConfig(persisted, config), [persisted, config]);
4048
4132
  const [selectedChartTimeRange, setSelectedChartTimeRange] = useState3(
4049
4133
  mergedConfig.chart.selectedChartTimeRange
4050
4134
  );
@@ -4096,7 +4180,7 @@ var AggUiProvider = ({ config, children }) => {
4096
4180
  setIsShowingAllResults(false);
4097
4181
  (_b = (_a = mergedConfig.search).closeResults) == null ? void 0 : _b.call(_a);
4098
4182
  }, [mergedConfig.search]);
4099
- const resolvedConfig = useMemo6(() => {
4183
+ const resolvedConfig = useMemo7(() => {
4100
4184
  return __spreadProps(__spreadValues({}, mergedConfig), {
4101
4185
  chart: __spreadProps(__spreadValues({}, mergedConfig.chart), {
4102
4186
  selectedChartTimeRange,
@@ -4164,7 +4248,7 @@ import { jsx as jsx9 } from "react/jsx-runtime";
4164
4248
  var hasWarnedMissingQueryClient = false;
4165
4249
  function useQueryClientCheck() {
4166
4250
  try {
4167
- useQueryClient3();
4251
+ useQueryClient4();
4168
4252
  } catch (e) {
4169
4253
  if (!hasWarnedMissingQueryClient) {
4170
4254
  hasWarnedMissingQueryClient = true;
@@ -4203,10 +4287,10 @@ function useResolvedExecutionMode(override) {
4203
4287
  }
4204
4288
 
4205
4289
  // src/execution/use-execute-managed.ts
4206
- import { useMutation, useQueryClient as useQueryClient4 } from "@tanstack/react-query";
4290
+ import { useMutation, useQueryClient as useQueryClient5 } from "@tanstack/react-query";
4207
4291
  function useExecuteManaged(options) {
4208
4292
  const client = useAggClient();
4209
- const queryClient = useQueryClient4();
4293
+ const queryClient = useQueryClient5();
4210
4294
  return useMutation({
4211
4295
  mutationFn: (params) => client.executeManaged(params),
4212
4296
  onSuccess: (data) => {
@@ -4235,10 +4319,10 @@ function useExecuteManaged(options) {
4235
4319
  }
4236
4320
 
4237
4321
  // src/execution/use-place-limit-order.ts
4238
- import { useMutation as useMutation2, useQueryClient as useQueryClient5 } from "@tanstack/react-query";
4322
+ import { useMutation as useMutation2, useQueryClient as useQueryClient6 } from "@tanstack/react-query";
4239
4323
  function usePlaceLimitOrder(options) {
4240
4324
  const client = useAggClient();
4241
- const queryClient = useQueryClient5();
4325
+ const queryClient = useQueryClient6();
4242
4326
  return useMutation2({
4243
4327
  mutationFn: (params) => client.placeLimitOrder(params),
4244
4328
  onSuccess: (data) => {
@@ -4254,10 +4338,10 @@ function usePlaceLimitOrder(options) {
4254
4338
  }
4255
4339
 
4256
4340
  // src/execution/use-cancel-managed-order.ts
4257
- import { useMutation as useMutation3, useQueryClient as useQueryClient6 } from "@tanstack/react-query";
4341
+ import { useMutation as useMutation3, useQueryClient as useQueryClient7 } from "@tanstack/react-query";
4258
4342
  function useCancelManagedOrder(options) {
4259
4343
  const client = useAggClient();
4260
- const queryClient = useQueryClient6();
4344
+ const queryClient = useQueryClient7();
4261
4345
  return useMutation3({
4262
4346
  mutationFn: (orderId) => client.cancelManagedOrder(orderId),
4263
4347
  onSuccess: (data, orderId) => {
@@ -4277,10 +4361,10 @@ function useCancelManagedOrder(options) {
4277
4361
  }
4278
4362
 
4279
4363
  // src/execution/use-withdraw-managed.ts
4280
- import { useMutation as useMutation4, useQueryClient as useQueryClient7 } from "@tanstack/react-query";
4364
+ import { useMutation as useMutation4, useQueryClient as useQueryClient8 } from "@tanstack/react-query";
4281
4365
  function useWithdrawManaged(options) {
4282
4366
  const client = useAggClient();
4283
- const queryClient = useQueryClient7();
4367
+ const queryClient = useQueryClient8();
4284
4368
  return useMutation4({
4285
4369
  mutationFn: (params) => client.withdrawManaged(params),
4286
4370
  onSuccess: (data) => {
@@ -4296,10 +4380,11 @@ function useWithdrawManaged(options) {
4296
4380
  import { useQuery as useQuery3 } from "@tanstack/react-query";
4297
4381
  function useManagedBalances(options) {
4298
4382
  const client = useAggClient();
4299
- const { enabled = true, mode } = options != null ? options : {};
4383
+ const { enabled = true, mode, custody } = options != null ? options : {};
4384
+ const params = __spreadValues(__spreadValues({}, mode ? { mode } : {}), custody ? { custody } : {});
4300
4385
  const query = useQuery3({
4301
- queryKey: executionKeys.balances(mode),
4302
- queryFn: () => client.getManagedBalances(mode ? { mode } : void 0),
4386
+ queryKey: executionKeys.balances(mode, custody),
4387
+ queryFn: () => client.getManagedBalances(Object.keys(params).length ? params : void 0),
4303
4388
  enabled,
4304
4389
  staleTime: 1e4,
4305
4390
  // A matched fill can precede settlement and the API's next balance snapshot.
@@ -4336,7 +4421,7 @@ function usePositions(options) {
4336
4421
  }
4337
4422
 
4338
4423
  // src/execution/use-deposit-addresses.ts
4339
- import { useEffect as useEffect4, useMemo as useMemo7, useRef as useRef4, useState as useState4 } from "react";
4424
+ import { useEffect as useEffect4, useMemo as useMemo8, useRef as useRef4, useState as useState4 } from "react";
4340
4425
  import { useQuery as useQuery5 } from "@tanstack/react-query";
4341
4426
  var SVM_CHAIN_IDS = /* @__PURE__ */ new Set([792703809]);
4342
4427
  function getDepositAddress(chainId, data) {
@@ -4377,9 +4462,9 @@ function useDepositAddresses(options) {
4377
4462
  });
4378
4463
  const isReady = ((_a = query.data) == null ? void 0 : _a.ready) === true;
4379
4464
  const readyData = isReady ? query.data : void 0;
4380
- const evmAddress = useMemo7(() => readyData == null ? void 0 : readyData.evmAddress, [readyData]);
4381
- const svmAddress = useMemo7(() => readyData == null ? void 0 : readyData.svmAddress, [readyData]);
4382
- const supportedChains = useMemo7(() => readyData == null ? void 0 : readyData.supportedChains, [readyData]);
4465
+ const evmAddress = useMemo8(() => readyData == null ? void 0 : readyData.evmAddress, [readyData]);
4466
+ const svmAddress = useMemo8(() => readyData == null ? void 0 : readyData.svmAddress, [readyData]);
4467
+ const supportedChains = useMemo8(() => readyData == null ? void 0 : readyData.supportedChains, [readyData]);
4383
4468
  return __spreadProps(__spreadValues({}, query), {
4384
4469
  isReady,
4385
4470
  isTimedOut,
@@ -4393,10 +4478,10 @@ function useDepositAddresses(options) {
4393
4478
  }
4394
4479
 
4395
4480
  // src/execution/use-sync-balances.ts
4396
- import { useMutation as useMutation5, useQueryClient as useQueryClient8 } from "@tanstack/react-query";
4481
+ import { useMutation as useMutation5, useQueryClient as useQueryClient9 } from "@tanstack/react-query";
4397
4482
  function useSyncBalances(options) {
4398
4483
  const client = useAggClient();
4399
- const queryClient = useQueryClient8();
4484
+ const queryClient = useQueryClient9();
4400
4485
  return useMutation5({
4401
4486
  mutationFn: () => client.syncManagedBalances(),
4402
4487
  onSuccess: () => {
@@ -4606,7 +4691,7 @@ function useExecutionProgress({
4606
4691
  submittedOrderVenueByIdRef.current.set(msg.orderId, trimmedVenue);
4607
4692
  }
4608
4693
  const { event } = msg;
4609
- if (event === "filled" || event === "partial_fill" || event === "failed" || event === "bridge_ws_subscribe_failed" || event === "expired" || event === "dag_cancelled") {
4694
+ if (event === "filled" || event === "partial_fill" || event === "failed" || event === "bridge_ws_subscribe_failed" || event === "expired" || event === "dag_cancelled" || event === "cancelled") {
4610
4695
  const mappedEvent = event === "filled" || event === "partial_fill" ? event : "failed";
4611
4696
  const resolvedVenue = trimmedVenue || submittedOrderVenueByIdRef.current.get(msg.orderId) || "";
4612
4697
  if (resolvedVenue) {
@@ -5125,11 +5210,11 @@ function useExecutionProgress({
5125
5210
  }
5126
5211
 
5127
5212
  // src/execution/use-balance-refill-policies.ts
5128
- import { useMutation as useMutation6, useQuery as useQuery6, useQueryClient as useQueryClient9 } from "@tanstack/react-query";
5213
+ import { useMutation as useMutation6, useQuery as useQuery6, useQueryClient as useQueryClient10 } from "@tanstack/react-query";
5129
5214
  function useBalanceRefillPolicies(options) {
5130
5215
  var _a, _b;
5131
5216
  const client = useAggClient();
5132
- const queryClient = useQueryClient9();
5217
+ const queryClient = useQueryClient10();
5133
5218
  const queryKey = executionKeys.balanceRefillPolicies();
5134
5219
  const query = useQuery6({
5135
5220
  queryKey,
@@ -5210,7 +5295,7 @@ var computeClosedPositionTotals = (group) => {
5210
5295
  };
5211
5296
 
5212
5297
  // src/execution/use-redeem.ts
5213
- import { useMutation as useMutation7, useQueryClient as useQueryClient10 } from "@tanstack/react-query";
5298
+ import { useMutation as useMutation7, useQueryClient as useQueryClient11 } from "@tanstack/react-query";
5214
5299
  var RedeemRejectedError = class extends Error {
5215
5300
  constructor(message, response) {
5216
5301
  super(message);
@@ -5221,7 +5306,7 @@ var RedeemRejectedError = class extends Error {
5221
5306
  var isLegRejected = (status) => status === "ineligible" || status === "rejected";
5222
5307
  var useRedeem = () => {
5223
5308
  const client = useAggClient();
5224
- const queryClient = useQueryClient10();
5309
+ const queryClient = useQueryClient11();
5225
5310
  const { executionMode } = useResolvedExecutionMode();
5226
5311
  return useMutation7({
5227
5312
  mutationFn: (body) => __async(null, null, function* () {
@@ -5282,7 +5367,7 @@ var useRedeemEligibleCount = () => {
5282
5367
  };
5283
5368
 
5284
5369
  // src/execution/use-redeem-lifecycles.ts
5285
- import { useEffect as useEffect6, useMemo as useMemo8, useState as useState6 } from "react";
5370
+ import { useEffect as useEffect6, useMemo as useMemo9, useState as useState6 } from "react";
5286
5371
  var computeDerivedState = (legs, expectedCount) => {
5287
5372
  const legCount = Object.keys(legs).length;
5288
5373
  let allTerminal = legCount === expectedCount;
@@ -5333,7 +5418,7 @@ var seedState = (input) => {
5333
5418
  };
5334
5419
  };
5335
5420
  function useRedeemLifecycles(inputs) {
5336
- const inputsByRedeemId = useMemo8(() => {
5421
+ const inputsByRedeemId = useMemo9(() => {
5337
5422
  const map = {};
5338
5423
  for (const input of inputs) {
5339
5424
  map[input.redeemId] = input;
@@ -5365,7 +5450,7 @@ function useRedeemLifecycles(inputs) {
5365
5450
  });
5366
5451
  }, [inputsByRedeemId]);
5367
5452
  useOnRedeemEvent(
5368
- useMemo8(() => {
5453
+ useMemo9(() => {
5369
5454
  if (Object.keys(inputsByRedeemId).length === 0) return null;
5370
5455
  return (event) => {
5371
5456
  const input = inputsByRedeemId[event.redeemId];
@@ -5400,7 +5485,7 @@ function useRedeemLifecycles(inputs) {
5400
5485
  }
5401
5486
 
5402
5487
  // src/execution/use-redeem-lifecycle.ts
5403
- import { useMemo as useMemo9 } from "react";
5488
+ import { useMemo as useMemo10 } from "react";
5404
5489
  var INITIAL_STATE = {
5405
5490
  pending: true,
5406
5491
  terminal: false,
@@ -5411,13 +5496,14 @@ var INITIAL_STATE = {
5411
5496
  };
5412
5497
  function useRedeemLifecycle(input) {
5413
5498
  var _a;
5414
- const inputs = useMemo9(() => input ? [input] : [], [input]);
5499
+ const inputs = useMemo10(() => input ? [input] : [], [input]);
5415
5500
  const map = useRedeemLifecycles(inputs);
5416
5501
  if (!input) return INITIAL_STATE;
5417
5502
  return (_a = map[input.redeemId]) != null ? _a : INITIAL_STATE;
5418
5503
  }
5419
5504
 
5420
5505
  export {
5506
+ __pow,
5421
5507
  __spreadValues,
5422
5508
  __spreadProps,
5423
5509
  __objRest,
@@ -5431,6 +5517,7 @@ export {
5431
5517
  parseEmail,
5432
5518
  parseEmailStrict,
5433
5519
  optimizedImageUrl,
5520
+ retinaImageUrl,
5434
5521
  sortVenues,
5435
5522
  getOrCreateBuilder,
5436
5523
  getBuilder,
@@ -5452,15 +5539,10 @@ export {
5452
5539
  useCachedAppConfig,
5453
5540
  EventListStateProvider,
5454
5541
  useEventListState,
5455
- getIntervalSeconds,
5456
- createMarketChartData,
5457
- mergeMarketChartData,
5458
5542
  createMarketLiveState,
5459
- createMarketOrderbookDataFromVenueOrderbooks,
5460
- createMarketOrderbookDataFromState,
5461
- marketOrderbookDataToResponse,
5462
- applyOrderbookDepth,
5463
5543
  marketDataKeys,
5544
+ getMarketLiveStore,
5545
+ useLiveStates,
5464
5546
  useAggClient,
5465
5547
  useOptionalAggClient,
5466
5548
  useAggUiConfig,