@agg-build/hooks 1.2.0 → 1.2.12

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.d.ts CHANGED
@@ -2,12 +2,12 @@ import * as _tanstack_react_query from '@tanstack/react-query';
2
2
  import { QueryClient } from '@tanstack/react-query';
3
3
  export { QueryClient, QueryClientProvider, useQueryClient } from '@tanstack/react-query';
4
4
  import * as _agg_build_sdk from '@agg-build/sdk';
5
- import { CandleBuilder, AggAuthStartBody, AggAuthStartResult, AggClientSessionInput, AggClient, RampQuote, RampQuoteRequest, RampWidgetSession, RampSessionRequest, QuoteManagedResponse, QuoteManagedParams, ExecuteManagedResponse, ExecuteManagedParams, GetPositionsParams, WsOrderSubmitted, WsBalanceUpdate, RedeemResponse, RedeemRequest, WsRedeemEvent, AggWebSocket, WsWithdrawalLifecycleEvent, WsCandleInterval, WsTrade, AggregatedOrderbookResponse, AggLinkAccountBody, AggLinkAccountResult, AggLinkAccountConfirmResult, UserActivityQuery, UserActivityItem, CandleInterval, OrderbookState, OrderbookQuoteResponse, OrderListQuery, TradeExecutorOrder, SmartRouteSide, SmartRouteResponse, MidpointRow, BatchMidpointsResponse, AppClientConfigResponse } from '@agg-build/sdk';
5
+ import { CandleBuilder, AggAuthStartBody, AggAuthStartResult, AggClientSessionInput, AggClient, RampQuote, RampQuoteRequest, RampWidgetSession, RampSessionRequest, QuoteManagedResponse, QuoteManagedParams, ExecuteManagedResponse, ExecuteManagedParams, GetPositionsParams, WsOrderSubmitted, WsBalanceUpdate, RedeemResponse, RedeemRequest, WsRedeemEvent, AggWebSocket, WsOrderEvent, WsWithdrawalLifecycleEvent, WsCandleInterval, WsTrade, AggregatedOrderbookResponse, AggLinkAccountBody, AggLinkAccountResult, AggLinkAccountConfirmResult, UserActivityQuery, UserActivityItem, PaginatedResponse, CandleInterval, OrderbookState, OrderbookQuoteResponse, OrderListQuery, TradeExecutorOrder, SmartRouteSide, SmartRouteResponse, MidpointRow, BatchMidpointsResponse, AppClientConfigResponse } from '@agg-build/sdk';
6
6
  export { TurnstileChallengeError } from '@agg-build/sdk';
7
7
  import React, { ReactNode } from 'react';
8
- export { UseManagedBalancesOptions, UseWithdrawFlowOptions, UseWithdrawFlowResult, UseWithdrawManagedOptions, UseWithdrawalLifecycleResult, WithdrawalLifecycleState, useManagedBalances, useWithdrawFlow, useWithdrawManaged, useWithdrawalLifecycle } from './withdraw.js';
8
+ export { UseManagedBalancesOptions, UseWithdrawEstimateParams, UseWithdrawFlowOptions, UseWithdrawFlowResult, UseWithdrawManagedOptions, UseWithdrawalLifecycleResult, WithdrawFeeEstimate, WithdrawalLifecycleState, useManagedBalances, useWithdrawEstimate, useWithdrawFlow, useWithdrawManaged, useWithdrawalLifecycle } from './withdraw.js';
9
9
  export { U as UseDepositAddressesOptions, g as getDepositAddress, u as useDepositAddresses } from './use-deposit-addresses-B9ICS-3U.js';
10
- export { U as UseSyncBalancesOptions, u as useSyncBalances } from './use-sync-balances-B1_8tBKw.js';
10
+ export { U as UseSyncBalancesOptions, u as useSyncBalances } from './use-sync-balances-CeD8qZWP.js';
11
11
 
12
12
  /** Use these constants instead of hardcoding "kalshi" or "polymarket". */
13
13
  declare enum Venue {
@@ -126,6 +126,8 @@ type UnifiedBalanceResponse = {
126
126
  type GetOrdersQuery = {
127
127
  status?: OrderStatus | undefined;
128
128
  orderId?: string | undefined;
129
+ /** Filter to all legs of one quote (multi-venue split routes). */
130
+ quoteId?: string | undefined;
129
131
  cursor?: string | undefined;
130
132
  limit?: number | undefined;
131
133
  };
@@ -137,6 +139,12 @@ type GetPositionsQuery = {
137
139
  type OrderListItem = {
138
140
  status: string;
139
141
  id: string;
142
+ /**
143
+ * Parent quote — lets the frontend correlate legs of a multi-venue
144
+ * split route without a second request. Nullable for sell-side /
145
+ * standalone orders without a Quote row.
146
+ */
147
+ quoteId: string | null;
140
148
  createdAt: Date;
141
149
  updatedAt: Date;
142
150
  venue: Venue;
@@ -145,8 +153,28 @@ type OrderListItem = {
145
153
  slippageBps: number | null;
146
154
  quotedPriceRaw: string | null;
147
155
  quotedCostRaw: string | null;
156
+ /**
157
+ * Quote-time shares + payout, 6-decimal atomic. Lets the UI render
158
+ * "Quoted X shares / $Y to win" without re-deriving from cost ÷
159
+ * price (precision drift on fractional fills; divide-by-zero before
160
+ * `executionPrice` exists).
161
+ */
162
+ quotedSharesRaw: string | null;
163
+ quotedToWinRaw: string | null;
148
164
  filledAmountRaw: string | null;
149
165
  executionPrice: string | null;
166
+ /**
167
+ * Actual shares + payout, populated by the venue's finalize handler.
168
+ * Pair with the quoted-side fields above to render the diff inline.
169
+ */
170
+ actualSharesRaw: string | null;
171
+ actualToWinRaw: string | null;
172
+ /**
173
+ * Set only on `partial_fill`. One of `"venue_capacity"`,
174
+ * `"price_slipped"`, `"user_cancelled"`, `"timeout"`, `"bridge_short"`,
175
+ * or a venue-specific tag.
176
+ */
177
+ partialFillReason: string | null;
150
178
  txHash: string | null;
151
179
  errorMessage: string | null;
152
180
  dagRunId: string | null;
@@ -176,7 +204,7 @@ type PositionGroup = {
176
204
  venue: Venue;
177
205
  size: number;
178
206
  venueMarketId: string;
179
- venueMarketOutcomeId?: string | null;
207
+ venueMarketOutcomeId: string;
180
208
  }[];
181
209
  totalSize: number;
182
210
  avgEntryPrice: number;
@@ -204,6 +232,14 @@ type VenueMarket = {
204
232
  title?: string | null | undefined;
205
233
  externalIdentifier?: string | null | undefined;
206
234
  winner?: boolean | null | undefined;
235
+ /** Counterpart outcomes on matched sibling markets — only populated
236
+ * on the parent (queried) market's outcomes. Each entry is a
237
+ * `{ venueMarketId, venueMarketOutcomeId }` ref into the same
238
+ * response's `matchedVenueMarkets[].venueMarketOutcomes[]`. */
239
+ matchedVenueMarketOutcomes?: {
240
+ venueMarketId: string;
241
+ venueMarketOutcomeId: string;
242
+ }[];
207
243
  }[];
208
244
  externalIdentifier: string;
209
245
  status?: MarketStatus | undefined;
@@ -276,6 +312,13 @@ type VenueEvent = {
276
312
  venues?: Venue[];
277
313
  venueCount?: number | undefined;
278
314
  marketCount?: number | undefined;
315
+ /**
316
+ * ISO-8601 duration denormalized from Series.recurrence. `null` means
317
+ * the event has no recurring schedule (one-off). Use this value with
318
+ * the `?recurrence=` filter on /venue-events; discover all available
319
+ * values via GET /recurrences.
320
+ */
321
+ recurrence?: string | null | undefined;
279
322
  };
280
323
  type Orderbook = {
281
324
  bids: {
@@ -288,6 +331,14 @@ type Orderbook = {
288
331
  }[];
289
332
  negRisk?: boolean | undefined;
290
333
  };
334
+ /** Reference to a counterpart outcome on a matched sibling market.
335
+ * Resolves into the same response's `matchedVenueMarkets[].venueMarketOutcomes[]`
336
+ * by id. Sourced from `MatchedVenueMarketOutcome` so the alignment is
337
+ * robust to inversely-framed binary markets and multi-outcome markets. */
338
+ type MatchedVenueMarketOutcomeRef = {
339
+ venueMarketId: string;
340
+ venueMarketOutcomeId: string;
341
+ };
291
342
  type VenueMarketOutcome = {
292
343
  id: string;
293
344
  price: number;
@@ -296,6 +347,9 @@ type VenueMarketOutcome = {
296
347
  title?: string | null | undefined;
297
348
  externalIdentifier?: string | null | undefined;
298
349
  winner?: boolean | null | undefined;
350
+ /** Counterpart outcomes on matched sibling markets — only populated on
351
+ * the parent (queried) market's outcomes. */
352
+ matchedVenueMarketOutcomes?: MatchedVenueMarketOutcomeRef[];
299
353
  };
300
354
  type VenueEventWithMarkets = VenueEvent & {
301
355
  venueMarkets: VenueMarket[];
@@ -508,6 +562,12 @@ interface AggUiLabels {
508
562
  max: string;
509
563
  tokenLabel: string;
510
564
  networkLabel: string;
565
+ estimatedFees: string;
566
+ networkReserve: string;
567
+ networkReserveTooltipAria: string;
568
+ networkReserveTooltipLineOne: string;
569
+ networkReserveTooltipLineTwo: string;
570
+ youReceive: string;
511
571
  confirm: string;
512
572
  successTitle: string;
513
573
  successDescription: (tokenSymbol: string) => string;
@@ -517,7 +577,11 @@ interface AggUiLabels {
517
577
  successDescriptionPartial: (tokenSymbol: string) => string;
518
578
  successTitleFailed: string;
519
579
  successDescriptionFailed: (tokenSymbol: string) => string;
580
+ retry: string;
581
+ close: string;
582
+ loadingDescription: string;
520
583
  summary: {
584
+ requestedWithdrawal: string;
521
585
  amountReceived: string;
522
586
  network: string;
523
587
  toWallet: string;
@@ -535,6 +599,12 @@ interface AggUiLabels {
535
599
  completed: string;
536
600
  partial: string;
537
601
  failed: string;
602
+ loadingSteps: {
603
+ preparing: string;
604
+ bridging: string;
605
+ sending: string;
606
+ confirming: string;
607
+ };
538
608
  /**
539
609
  * Per-leg step labels rendered in the success step's execution
540
610
  * timeline. `bridge` covers cross-chain hops, `transfer` covers
@@ -592,6 +662,40 @@ interface AggUiLabels {
592
662
  externalWallet: string;
593
663
  card: string;
594
664
  };
665
+ /**
666
+ * Status-aware titles per activity status. The activity row reads
667
+ * the appropriate variant based on the normalized status
668
+ * ("completed" | "pending" | "failed" | "canceled") so the cell
669
+ * matches the icon and tone — e.g. a pending withdrawal reads
670
+ * "Processing withdrawal", a failed card deposit reads
671
+ * "Failed deposit with card".
672
+ */
673
+ depositStatusTitles: {
674
+ connectedWallet: {
675
+ pending: string;
676
+ completed: string;
677
+ failed: string;
678
+ canceled: string;
679
+ };
680
+ externalWallet: {
681
+ pending: string;
682
+ completed: string;
683
+ failed: string;
684
+ canceled: string;
685
+ };
686
+ card: {
687
+ pending: string;
688
+ completed: string;
689
+ failed: string;
690
+ canceled: string;
691
+ };
692
+ };
693
+ withdrawalStatusTitles: {
694
+ pending: string;
695
+ completed: string;
696
+ failed: string;
697
+ canceled: string;
698
+ };
595
699
  withdrawalTitle: (tokenSymbol: string) => string;
596
700
  };
597
701
  positions: {
@@ -626,6 +730,15 @@ interface AggUiLabels {
626
730
  eventList: {
627
731
  matchedTab: string;
628
732
  allTab: string;
733
+ sortByLabel: string;
734
+ sortBy24hVolume: string;
735
+ sortByTopArbitrage: string;
736
+ sortByTotalVolume: string;
737
+ sortByEndingSoon: string;
738
+ subcategoriesLabel: string;
739
+ subcategoriesAll: string;
740
+ subcategoriesOpenAria: string;
741
+ subcategoriesCloseAria: string;
629
742
  loading: (title: string) => string;
630
743
  tabsAria: (title: string) => string;
631
744
  emptyAria: string;
@@ -806,6 +919,61 @@ interface AggUiLabels {
806
919
  noMarketSelected: string;
807
920
  noOrderbooks: string;
808
921
  quoteUnavailable: string;
922
+ quoteBalanceMismatch: string;
923
+ serviceTemporarilyUnavailable: string;
924
+ orderDeadlineExpiredBeforeSubmission: string;
925
+ /**
926
+ * Venue rejected a SELL because the user's on-chain position is
927
+ * zero (VMP overstated, prior sell/redeem, transfer out, etc.).
928
+ * Default: "You don't currently hold any on-chain shares of this
929
+ * outcome. If you just sold or redeemed elsewhere, your position
930
+ * display will refresh shortly — try again after that."
931
+ */
932
+ sellNoOnchainPosition: string;
933
+ /**
934
+ * Venue couldn't fill at the quoted price (Limitless simulation
935
+ * failed, Myriad walk produced no in-tolerance levels, Hyperliquid
936
+ * `could not immediately match`, etc.).
937
+ */
938
+ venueQuoteUnfillable: string;
939
+ /**
940
+ * Bare-minimum venue order-size violation (Limitless 0.01-share
941
+ * floor, Polymarket post-fee dust, Hyperliquid min-notional).
942
+ */
943
+ venueMinOrderSize: string;
944
+ /**
945
+ * Source-chain balance changed between quote and submit. Covers
946
+ * Limitless Base USDC, Polymarket pUSD, Solana SPL InsufficientFunds,
947
+ * BNB BEP20 transfer-exceeds-balance.
948
+ */
949
+ sourceBalanceChanged: string;
950
+ /**
951
+ * Venue market resolved / closed between quote and submit.
952
+ */
953
+ venueMarketResolved: string;
954
+ /**
955
+ * dFlow wallet KYC required (verify at dflow.net/proof).
956
+ */
957
+ dflowWalletUnverified: string;
958
+ /**
959
+ * No active quote path on the matcher right now (dFlow
960
+ * route_not_found, etc.).
961
+ */
962
+ venueNoQuotePath: string;
963
+ /**
964
+ * Solana blockhash expired before the tx landed — re-quote needed.
965
+ */
966
+ solanaBlockhashExpired: string;
967
+ /**
968
+ * Venue / aggregator API is rate-limited; retry shortly.
969
+ */
970
+ venueRateLimited: string;
971
+ /**
972
+ * Service-side bug surfaced at admission time (DagValidationError,
973
+ * Duplicate step ID, etc.). Retrying the same quote will hit the
974
+ * same bug; user should contact support.
975
+ */
976
+ serviceBlockedOrder: string;
809
977
  selectedVenueUnavailable: string;
810
978
  engineUnavailable: string;
811
979
  insufficientInputAmount: string;
@@ -819,6 +987,7 @@ interface AggUiLabels {
819
987
  deposit: string;
820
988
  kycRequired: string;
821
989
  kycNotVerifiedTooltip: string;
990
+ kycVerify: string;
822
991
  kycVerifyModalTitle: string;
823
992
  kycVerifyModalDescription: string;
824
993
  kycStartVerification: string;
@@ -832,6 +1001,7 @@ interface AggUiLabels {
832
1001
  splitOrderDescription: string;
833
1002
  viewAllRoutes: (count: number) => string;
834
1003
  venueUnavailableInRegion: string;
1004
+ verified: string;
835
1005
  platformFee: string;
836
1006
  estimatedFees: string;
837
1007
  estimatedFeesTooltipAria: string;
@@ -843,6 +1013,7 @@ interface AggUiLabels {
843
1013
  buyingOutcome: (label: string) => string;
844
1014
  sellingOutcome: (label: string) => string;
845
1015
  findingBestRoute: string;
1016
+ checkingBalance: string;
846
1017
  submittingOrderProgress: string;
847
1018
  orderSubmittedProgress: (orderId: string) => string;
848
1019
  executingOnVenue: (venueLabel: string) => string;
@@ -1009,6 +1180,58 @@ interface AggUiLabels {
1009
1180
  bannerAria: string;
1010
1181
  logoAria: string;
1011
1182
  };
1183
+ /**
1184
+ * Copy for the global notification bridge (`AggNotificationEventsProvider`).
1185
+ * Each leaf is read from a websocket / activity-feed lifecycle event and
1186
+ * rendered into the existing toast primitive. Keep these terse — the toast
1187
+ * footprint is small and detail lines wrap awkwardly past two lines.
1188
+ */
1189
+ notifications: {
1190
+ order: {
1191
+ filledTitle: string;
1192
+ filledMessage: (params: {
1193
+ venueLabel?: string;
1194
+ sideLabel?: string;
1195
+ amountLabel?: string;
1196
+ priceLabel?: string;
1197
+ }) => string;
1198
+ partialFilledTitle: string;
1199
+ partialFilledMessage: (params: {
1200
+ venueLabel?: string;
1201
+ sideLabel?: string;
1202
+ amountLabel?: string;
1203
+ priceLabel?: string;
1204
+ }) => string;
1205
+ failedTitle: string;
1206
+ failedMessage: (errorReason?: string) => string;
1207
+ };
1208
+ deposit: {
1209
+ completedTitle: string;
1210
+ completedMessage: (params: {
1211
+ amountLabel?: string;
1212
+ tokenLabel?: string;
1213
+ }) => string;
1214
+ failedTitle: string;
1215
+ failedMessage: (params: {
1216
+ amountLabel?: string;
1217
+ tokenLabel?: string;
1218
+ }) => string;
1219
+ };
1220
+ withdrawal: {
1221
+ completedTitle: string;
1222
+ completedMessage: (params: {
1223
+ amountLabel?: string;
1224
+ tokenLabel?: string;
1225
+ }) => string;
1226
+ partialTitle: string;
1227
+ partialMessage: (params: {
1228
+ amountLabel?: string;
1229
+ tokenLabel?: string;
1230
+ }) => string;
1231
+ failedTitle: string;
1232
+ failedMessage: (errorReason?: string) => string;
1233
+ };
1234
+ };
1012
1235
  }
1013
1236
  type DeepPartial<TValue> = {
1014
1237
  [TKey in keyof TValue]?: TValue[TKey] extends (...args: infer TArgs) => infer TReturn ? (...args: TArgs) => TReturn : TValue[TKey] extends object ? DeepPartial<TValue[TKey]> : TValue[TKey];
@@ -1041,6 +1264,15 @@ interface AggUiFeatureFlagsConfig {
1041
1264
  showFeesBreakdown: boolean;
1042
1265
  /** Enable gradients */
1043
1266
  enableGradients: boolean;
1267
+ /** Enable venue-events discovery filters UI and query wiring. */
1268
+ enableVenueEventDiscoveryFilters: boolean;
1269
+ /**
1270
+ * Enable the global notification bridge that emits toasts for order /
1271
+ * deposit / withdrawal lifecycle events. Defaults to `true`. Set to
1272
+ * `false` to suppress those toasts (the toast surface itself stays mounted
1273
+ * for ad-hoc partner-fired toasts).
1274
+ */
1275
+ enableNotifications: boolean;
1044
1276
  }
1045
1277
  type AggUiFeatureFlagsConfigInput = Partial<AggUiFeatureFlagsConfig>;
1046
1278
  interface AggUiMarketConfig {
@@ -1093,6 +1325,12 @@ interface AggUiConfig {
1093
1325
  enableLogs: boolean;
1094
1326
  /** Enable AGG websocket pipeline logs */
1095
1327
  enableWebsocketsLogs: boolean;
1328
+ /**
1329
+ * Enable developer-only debug instrumentation
1330
+ * (e.g. the Place Order execution-debug collector)
1331
+ * Off by default
1332
+ */
1333
+ enableDebug: boolean;
1096
1334
  /** General UI settings */
1097
1335
  general: AggUiGeneralConfig;
1098
1336
  /** UI feature flags */
@@ -1124,6 +1362,8 @@ interface AggUiConfigInput {
1124
1362
  enableLogs?: boolean;
1125
1363
  /** Enable AGG websocket pipeline logs */
1126
1364
  enableWebsocketsLogs?: boolean;
1365
+ /** Enable developer-only debug instrumentation (Place Order debug, etc.). */
1366
+ enableDebug?: boolean;
1127
1367
  /** General UI overrides */
1128
1368
  general?: AggUiGeneralConfigInput;
1129
1369
  /** Feature flag overrides */
@@ -1273,6 +1513,8 @@ declare const DEFAULT_AGG_ROOT_CLASS_NAME = "agg-root";
1273
1513
  declare const CHART_TIME_RANGES: ChartTimeRange[];
1274
1514
 
1275
1515
  declare const useAggClient: () => AggClient;
1516
+ /** Like {@link useAggClient}, but returns `null` when no `<AggProvider>` is mounted. */
1517
+ declare const useOptionalAggClient: () => AggClient | null;
1276
1518
  declare const useAggUiConfig: () => AggUiConfig;
1277
1519
  declare const useAggLabels: () => AggUiLabels;
1278
1520
  declare const useAggAuthContext: () => AggAuthContextValue;
@@ -1326,10 +1568,27 @@ declare const resolveOrderEligibility: (params: {
1326
1568
  }) => OrderEligibility;
1327
1569
  declare function resolveDefaultMarket(event: VenueEventWithMarkets | null): VenueMarket | null;
1328
1570
 
1571
+ /**
1572
+ * Active trade side. Modeled as a frozen const-object so callers can use
1573
+ * enum-style access (`TradeSide.Buy`, `TradeSide.Sell`) while the resulting
1574
+ * type is still the plain `"buy" | "sell"` string union — interoperable
1575
+ * everywhere a literal is expected (URL params, JSON payloads, helper
1576
+ * function signatures).
1577
+ */
1578
+ declare const TradeSide: {
1579
+ readonly Buy: "buy";
1580
+ readonly Sell: "sell";
1581
+ };
1582
+ type TradeSide = (typeof TradeSide)[keyof typeof TradeSide];
1329
1583
  interface TradingState {
1330
1584
  event: VenueEventWithMarkets | null;
1331
1585
  market: VenueMarket | null;
1332
1586
  outcome: VenueMarketOutcome | null;
1587
+ /**
1588
+ * Currently selected buy/sell side. Optional in shape (older fixtures and
1589
+ * snapshots may omit it) — readers should treat `undefined` as `Buy`.
1590
+ */
1591
+ tradeSide?: TradeSide;
1333
1592
  }
1334
1593
  type TradingAction = {
1335
1594
  type: "INITIALIZE_EVENT";
@@ -1348,6 +1607,9 @@ type TradingAction = {
1348
1607
  type: "SELECT_MARKET_AND_OUTCOME";
1349
1608
  marketId: string;
1350
1609
  outcomeId: string;
1610
+ } | {
1611
+ type: "SET_TRADE_SIDE";
1612
+ tradeSide: TradeSide;
1351
1613
  };
1352
1614
  declare function tradingReducer(state: TradingState, action: TradingAction): TradingState;
1353
1615
  interface EventTradingContextValue {
@@ -1358,6 +1620,14 @@ interface EventTradingContextValue {
1358
1620
  selectedMarketId: string | null;
1359
1621
  selectedOutcomeId: string | null;
1360
1622
  selectedVenue: string | null;
1623
+ /**
1624
+ * Currently selected trade side. Drives `bestAsk` vs `bestBid` selection
1625
+ * across all price-display surfaces (home tile, event details, market
1626
+ * details, place-order outcome buttons) so flipping Buy/Sell in PlaceOrder
1627
+ * is reflected everywhere. Defaults to `"buy"`.
1628
+ */
1629
+ tradeSide: TradeSide;
1630
+ setTradeSide: (tradeSide: TradeSide) => void;
1361
1631
  initializeFromEvent: (event: VenueEventWithMarkets | null) => void;
1362
1632
  syncEvent: (event: VenueEventWithMarkets) => void;
1363
1633
  selectMarket: (marketId: string, market?: VenueMarket) => void;
@@ -1381,6 +1651,49 @@ declare const invalidateBalanceQueries: (queryClient: QueryClient, options?: Inv
1381
1651
  * holdings, so positions need to be refetched alongside balances.
1382
1652
  */
1383
1653
  declare const invalidatePositionQueries: (queryClient: QueryClient, options?: InvalidateBalanceQueriesOptions) => void;
1654
+ declare const userActivityQueryKeys: {
1655
+ all: () => readonly ["user-activity"];
1656
+ };
1657
+ type UserActivityInvalidationStrategy = "remove" | "invalidate";
1658
+ interface InvalidateUserActivityOptions {
1659
+ /**
1660
+ * - "remove" (default): drop the entire `["user-activity"]` family from the
1661
+ * cache so the observed `useInfiniteQuery` refetches from page 1 only.
1662
+ * Avoids duplicate/shifted rows when a new entry appears at the top after
1663
+ * a deposit/withdraw — page 2's cursor was computed against the old head.
1664
+ * - "invalidate": invalidate in place; refetches all currently cached pages.
1665
+ * Cheaper paint-wise (keeps prior data visible) but can momentarily show
1666
+ * duplicate rows during the refetch.
1667
+ */
1668
+ strategy?: UserActivityInvalidationStrategy;
1669
+ }
1670
+ /**
1671
+ * Refresh the `useUserActivity` infinite query family after money movement.
1672
+ * Defaults to `removeQueries` so the next render refetches page 1 cleanly
1673
+ * (cursor-based pagination can't guarantee ordering after a new head row).
1674
+ */
1675
+ declare const invalidateUserActivityQueries: (queryClient: QueryClient, options?: InvalidateUserActivityOptions) => void;
1676
+ interface InvalidateUserMoneyStateOptions {
1677
+ /** Forwarded to balance + position invalidations. Defaults to "active". */
1678
+ refetchType?: BalanceRefetchType;
1679
+ /** Forwarded to activity invalidation. Defaults to "remove". */
1680
+ activityStrategy?: UserActivityInvalidationStrategy;
1681
+ }
1682
+ /**
1683
+ * Invalidate every cache surface affected by a successful deposit or
1684
+ * withdrawal. Call AFTER the backend has confirmed the operation — not on
1685
+ * modal close, not on optimistic submit.
1686
+ *
1687
+ * Scope (kept narrow on purpose):
1688
+ * - balances (canonical + venue) — the balance number changed
1689
+ * - positions — derived "available to trade" / share-count UIs read this
1690
+ * alongside balances; refetch keeps them consistent
1691
+ * - user activity — the deposit/withdraw row needs to appear in the feed
1692
+ *
1693
+ * Out of scope: orders / execution-orders (trade-side, not money movement),
1694
+ * current-user (no money fields change on deposit/withdraw today).
1695
+ */
1696
+ declare const invalidateUserMoneyState: (queryClient: QueryClient, options?: InvalidateUserMoneyStateOptions) => void;
1384
1697
 
1385
1698
  declare function useRampQuotes(): _tanstack_react_query.UseMutationResult<RampQuote[], Error, RampQuoteRequest, unknown>;
1386
1699
 
@@ -1623,6 +1936,19 @@ interface ExecutionTerminalOrderEvent {
1623
1936
  event: "filled" | "partial_fill" | "failed";
1624
1937
  filledAmountRaw?: string;
1625
1938
  remainingAmountRaw?: string;
1939
+ /** Actual shares + payout received, 6-decimal atomic. Set by the venue's
1940
+ * finalize handler on filled/partial_fill — the source of truth for the
1941
+ * execution summary so it never reuses the stale quote estimate. */
1942
+ actualSharesRaw?: string;
1943
+ actualToWinRaw?: string;
1944
+ /** Quote-time shares + payout, 6-decimal atomic. Snapshot of what the user
1945
+ * accepted; surfaced for "Quoted X / Got Y" diffs. */
1946
+ quotedSharesRaw?: string;
1947
+ quotedToWinRaw?: string;
1948
+ /** Avg execution price (decimal string). Pair with `quotedPriceRaw`
1949
+ * for inline slippage diffs and to derive shares when actual*Raw is absent. */
1950
+ executionPriceRaw?: string;
1951
+ quotedPriceRaw?: string;
1626
1952
  errorReason?: string;
1627
1953
  timestamp: number;
1628
1954
  }
@@ -1648,6 +1974,10 @@ interface ClosedPositionTotals {
1648
1974
  }
1649
1975
  declare const computeClosedPositionTotals: (group: PositionGroup) => ClosedPositionTotals;
1650
1976
 
1977
+ declare class RedeemRejectedError extends Error {
1978
+ readonly response: RedeemResponse;
1979
+ constructor(message: string, response: RedeemResponse);
1980
+ }
1651
1981
  declare const useRedeem: () => _tanstack_react_query.UseMutationResult<RedeemResponse, Error, RedeemRequest, unknown>;
1652
1982
 
1653
1983
  type RedeemEvent = WsRedeemEvent;
@@ -1655,9 +1985,100 @@ declare const useOnRedeemEvent: (listener: ((event: RedeemEvent) => void) | null
1655
1985
 
1656
1986
  declare const useRedeemEligibleCount: () => number;
1657
1987
 
1988
+ interface RedeemLegLifecycle {
1989
+ status: "submitted" | "confirmed" | "failed";
1990
+ txHash: string | null;
1991
+ errorMessage: string | null;
1992
+ }
1993
+ interface RedeemLifecycleState {
1994
+ /** True until terminal — drives the claim button spinner. */
1995
+ pending: boolean;
1996
+ /** True once every expected leg has flipped to confirmed or failed. */
1997
+ terminal: boolean;
1998
+ /** True iff terminal AND every leg.status === "confirmed". */
1999
+ allConfirmed: boolean;
2000
+ /** True iff any leg.status === "failed" (including pre-failed legs). */
2001
+ anyFailed: boolean;
2002
+ /** First non-null leg.errorMessage when anyFailed; null otherwise. */
2003
+ errorMessage: string | null;
2004
+ /** Per-leg lifecycle keyed by venueMarketOutcomeId. */
2005
+ legs: Record<string, RedeemLegLifecycle>;
2006
+ }
2007
+ interface UseRedeemLifecycleInput {
2008
+ redeemId: string;
2009
+ /**
2010
+ * Legs the API returned with status === "submitted" (EVM async path).
2011
+ * Each receives a redeem_event with status confirmed or failed.
2012
+ */
2013
+ expectedOutcomeIds: string[];
2014
+ /**
2015
+ * Legs the API returned with status === "ineligible" or "rejected".
2016
+ * Pre-seeded into legs as terminal-failed; no WS event will ever arrive.
2017
+ */
2018
+ preFailedOutcomeIds?: string[];
2019
+ /** Optional pre-seeded errorMessage per pre-failed leg, indexed by venueMarketOutcomeId. */
2020
+ preFailedReasons?: Record<string, string | null>;
2021
+ /**
2022
+ * Legs the API returned with status === "confirmed" (SVM sync path:
2023
+ * tx landed inline inside the HTTP call, VMP.redeemedAt already set
2024
+ * server-side). Pre-seeded into legs as terminal-confirmed; no WS
2025
+ * event will ever arrive.
2026
+ */
2027
+ preConfirmedOutcomeIds?: string[];
2028
+ /** Optional pre-seeded txHash per pre-confirmed leg, indexed by venueMarketOutcomeId. */
2029
+ preConfirmedTxHashes?: Record<string, string | null>;
2030
+ }
2031
+ /**
2032
+ * Subscribes once to `redeem_event` WS events and materializes a per-`redeemId`
2033
+ * lifecycle record for every in-flight redeem the caller is tracking.
2034
+ *
2035
+ * **Input shape** — the caller passes one {@link UseRedeemLifecycleInput} entry
2036
+ * per in-flight redeem. Legs are split into three buckets:
2037
+ * - `expectedOutcomeIds` — the EVM async path. The API returned these legs with
2038
+ * `status === "submitted"`; each will eventually receive a `redeem_event` WS
2039
+ * message with `status === "confirmed"` or `"failed"`.
2040
+ * - `preFailedOutcomeIds` — legs the API returned as `"ineligible"` or
2041
+ * `"rejected"` at submit time. Pre-seeded into the returned state as
2042
+ * terminal-failed; no WS event will ever arrive for them.
2043
+ * - `preConfirmedOutcomeIds` — the SVM sync path. The transaction landed inline
2044
+ * inside the HTTP call so `VenueMarketPosition.redeemedAt` is already set
2045
+ * server-side before the response returns. Pre-seeded as terminal-confirmed;
2046
+ * no WS event will ever arrive.
2047
+ *
2048
+ * **Entry lifecycle** — when the caller drops a `redeemId` from `inputs`, its
2049
+ * entry disappears from the returned record on the next render. There is no
2050
+ * tombstone or TTL — the lifecycle is purely driven by what is in `inputs`.
2051
+ *
2052
+ * **Performance** — the `inputs` array's reference identity matters. The hook
2053
+ * re-derives the internal `redeemId → input` map on every render where
2054
+ * `inputs` is a new reference. Callers should memoize the array via `useMemo`
2055
+ * to avoid the re-derivation overhead. A common pattern:
2056
+ * ```ts
2057
+ * const inputs = useMemo(
2058
+ * () => Object.values(activeRedeems).map(toLifecycleInput),
2059
+ * [activeRedeems],
2060
+ * );
2061
+ * ```
2062
+ *
2063
+ * **New-entry gap** — when the caller adds a new `redeemId` to `inputs`, the
2064
+ * returned record does not include it for the render where it was added. The
2065
+ * seed entry is written inside a `useEffect` (which runs after paint). Treat a
2066
+ * missing entry as "pending / not terminal yet" — the same as
2067
+ * `state.pending === true`.
2068
+ *
2069
+ * **No REST backfill** — if the WS subscription drops mid-flight (page refresh,
2070
+ * disconnect), the in-memory lifecycle state is lost. Redeems typically settle
2071
+ * in seconds and each position's `redeemStatus` is polled separately, so no
2072
+ * REST backfill is provided here.
2073
+ */
2074
+ declare function useRedeemLifecycles(inputs: UseRedeemLifecycleInput[]): Record<string, RedeemLifecycleState>;
2075
+
2076
+ declare function useRedeemLifecycle(input: UseRedeemLifecycleInput | null): RedeemLifecycleState;
2077
+
1658
2078
  declare function useAggWebSocket(): AggWebSocket | null;
1659
2079
  declare function useOnOrderSubmitted(callback: ((msg: WsOrderSubmitted) => void) | null): void;
1660
2080
  declare function useOnBalanceUpdate(callback: ((msg: WsBalanceUpdate) => void) | null): void;
2081
+ declare function useOnOrderEvent(callback: ((msg: WsOrderEvent) => void) | null): void;
1661
2082
  declare function useOnWithdrawalLifecycle(callback: ((msg: WsWithdrawalLifecycleEvent) => void) | null): void;
1662
2083
 
1663
2084
  interface MarketChartCandle {
@@ -1667,7 +2088,7 @@ interface MarketChartCandle {
1667
2088
  low: number;
1668
2089
  close: number;
1669
2090
  volume: number | null;
1670
- source: "rest" | "ws" | "trade";
2091
+ source: "rest" | "ws" | "trade" | "midpoint";
1671
2092
  }
1672
2093
  interface MarketChartVenueData {
1673
2094
  venue: string;
@@ -1677,6 +2098,13 @@ interface MarketChartVenueData {
1677
2098
  liveCandle: MarketChartCandle | null;
1678
2099
  lineValue: number | undefined;
1679
2100
  lastTrade: WsTrade | null;
2101
+ /**
2102
+ * Epoch seconds of the most recent real REST or WS update that touched this
2103
+ * venue (REST candle, trade, or midpoint). Used by the renderer's stale-data
2104
+ * indicator — independent of any synthetic point that `extendSeriesToNow`
2105
+ * projects onto the line. `null` when nothing has been seen yet.
2106
+ */
2107
+ lastUpdateTs: number | null;
1680
2108
  }
1681
2109
  interface MarketChartData {
1682
2110
  marketId: string;
@@ -1689,6 +2117,11 @@ interface MarketChartData {
1689
2117
  endTs: number | null;
1690
2118
  /** Per-venue chart state. The primary venue contains the canonical REST history. */
1691
2119
  venues: Record<string, MarketChartVenueData>;
2120
+ /**
2121
+ * Max of `lastUpdateTs` across all venues. Surfaced separately so the
2122
+ * renderer can show a stale indicator without crawling the venues map.
2123
+ */
2124
+ lastUpdateTs: number | null;
1692
2125
  }
1693
2126
 
1694
2127
  type MarketOrderbookIntegrity = "ok" | "resyncing";
@@ -1757,6 +2190,10 @@ declare const AUTH_CHOOSER_OPEN_EVENT = "agg-auth:open-chooser";
1757
2190
  declare const requestAggAuthChooserOpen: () => void;
1758
2191
 
1759
2192
  interface UseCategoriesOptions {
2193
+ /** Optional query-key scope to isolate caches across different surfaces. */
2194
+ queryKeyScope?: string;
2195
+ /** Fetch child categories for a parent category id. Omit for top-level categories. */
2196
+ parentId?: string | null;
1760
2197
  enabled?: boolean;
1761
2198
  /** Page size when using cursor pagination. Default 20. */
1762
2199
  limit?: number;
@@ -2209,11 +2646,20 @@ declare function useExecutionOrders(options?: UseExecutionOrdersOptions): {
2209
2646
 
2210
2647
  interface UseUserActivityOptions extends Omit<UserActivityQuery, "cursor"> {
2211
2648
  enabled?: boolean;
2649
+ /**
2650
+ * Poll interval (ms) used while any cached activity row is mid-lifecycle
2651
+ * (deposit pending, withdrawal bridging, trade submitted, etc.). Idle
2652
+ * feeds — every row in a terminal state — don't poll. Set to `false` to
2653
+ * disable the lifecycle-aware poll entirely.
2654
+ *
2655
+ * Defaults to 15s.
2656
+ */
2657
+ pendingRefetchIntervalMs?: number | false;
2212
2658
  }
2213
2659
  declare function useUserActivity(options?: UseUserActivityOptions): {
2214
2660
  activities: UserActivityItem[];
2215
2661
  hasNextPage: boolean;
2216
- data: _tanstack_react_query.InfiniteData<_agg_build_sdk.PaginatedResponse<UserActivityItem>, unknown>;
2662
+ data: _tanstack_react_query.InfiniteData<PaginatedResponse<UserActivityItem>, unknown>;
2217
2663
  error: Error;
2218
2664
  isError: true;
2219
2665
  isPending: false;
@@ -2223,8 +2669,8 @@ declare function useUserActivity(options?: UseUserActivityOptions): {
2223
2669
  isSuccess: false;
2224
2670
  isPlaceholderData: false;
2225
2671
  status: "error";
2226
- fetchNextPage: (options?: _tanstack_react_query.FetchNextPageOptions) => Promise<_tanstack_react_query.InfiniteQueryObserverResult<_tanstack_react_query.InfiniteData<_agg_build_sdk.PaginatedResponse<UserActivityItem>, unknown>, Error>>;
2227
- fetchPreviousPage: (options?: _tanstack_react_query.FetchPreviousPageOptions) => Promise<_tanstack_react_query.InfiniteQueryObserverResult<_tanstack_react_query.InfiniteData<_agg_build_sdk.PaginatedResponse<UserActivityItem>, unknown>, Error>>;
2672
+ fetchNextPage: (options?: _tanstack_react_query.FetchNextPageOptions) => Promise<_tanstack_react_query.InfiniteQueryObserverResult<_tanstack_react_query.InfiniteData<PaginatedResponse<UserActivityItem>, unknown>, Error>>;
2673
+ fetchPreviousPage: (options?: _tanstack_react_query.FetchPreviousPageOptions) => Promise<_tanstack_react_query.InfiniteQueryObserverResult<_tanstack_react_query.InfiniteData<PaginatedResponse<UserActivityItem>, unknown>, Error>>;
2228
2674
  hasPreviousPage: boolean;
2229
2675
  isFetchNextPageError: boolean;
2230
2676
  isFetchingNextPage: boolean;
@@ -2243,13 +2689,13 @@ declare function useUserActivity(options?: UseUserActivityOptions): {
2243
2689
  isRefetching: boolean;
2244
2690
  isStale: boolean;
2245
2691
  isEnabled: boolean;
2246
- refetch: (options?: _tanstack_react_query.RefetchOptions) => Promise<_tanstack_react_query.QueryObserverResult<_tanstack_react_query.InfiniteData<_agg_build_sdk.PaginatedResponse<UserActivityItem>, unknown>, Error>>;
2692
+ refetch: (options?: _tanstack_react_query.RefetchOptions) => Promise<_tanstack_react_query.QueryObserverResult<_tanstack_react_query.InfiniteData<PaginatedResponse<UserActivityItem>, unknown>, Error>>;
2247
2693
  fetchStatus: _tanstack_react_query.FetchStatus;
2248
- promise: Promise<_tanstack_react_query.InfiniteData<_agg_build_sdk.PaginatedResponse<UserActivityItem>, unknown>>;
2694
+ promise: Promise<_tanstack_react_query.InfiniteData<PaginatedResponse<UserActivityItem>, unknown>>;
2249
2695
  } | {
2250
2696
  activities: UserActivityItem[];
2251
2697
  hasNextPage: boolean;
2252
- data: _tanstack_react_query.InfiniteData<_agg_build_sdk.PaginatedResponse<UserActivityItem>, unknown>;
2698
+ data: _tanstack_react_query.InfiniteData<PaginatedResponse<UserActivityItem>, unknown>;
2253
2699
  error: null;
2254
2700
  isError: false;
2255
2701
  isPending: false;
@@ -2261,8 +2707,8 @@ declare function useUserActivity(options?: UseUserActivityOptions): {
2261
2707
  isSuccess: true;
2262
2708
  isPlaceholderData: false;
2263
2709
  status: "success";
2264
- fetchNextPage: (options?: _tanstack_react_query.FetchNextPageOptions) => Promise<_tanstack_react_query.InfiniteQueryObserverResult<_tanstack_react_query.InfiniteData<_agg_build_sdk.PaginatedResponse<UserActivityItem>, unknown>, Error>>;
2265
- fetchPreviousPage: (options?: _tanstack_react_query.FetchPreviousPageOptions) => Promise<_tanstack_react_query.InfiniteQueryObserverResult<_tanstack_react_query.InfiniteData<_agg_build_sdk.PaginatedResponse<UserActivityItem>, unknown>, Error>>;
2710
+ fetchNextPage: (options?: _tanstack_react_query.FetchNextPageOptions) => Promise<_tanstack_react_query.InfiniteQueryObserverResult<_tanstack_react_query.InfiniteData<PaginatedResponse<UserActivityItem>, unknown>, Error>>;
2711
+ fetchPreviousPage: (options?: _tanstack_react_query.FetchPreviousPageOptions) => Promise<_tanstack_react_query.InfiniteQueryObserverResult<_tanstack_react_query.InfiniteData<PaginatedResponse<UserActivityItem>, unknown>, Error>>;
2266
2712
  hasPreviousPage: boolean;
2267
2713
  isFetchingNextPage: boolean;
2268
2714
  isFetchingPreviousPage: boolean;
@@ -2279,9 +2725,9 @@ declare function useUserActivity(options?: UseUserActivityOptions): {
2279
2725
  isRefetching: boolean;
2280
2726
  isStale: boolean;
2281
2727
  isEnabled: boolean;
2282
- refetch: (options?: _tanstack_react_query.RefetchOptions) => Promise<_tanstack_react_query.QueryObserverResult<_tanstack_react_query.InfiniteData<_agg_build_sdk.PaginatedResponse<UserActivityItem>, unknown>, Error>>;
2728
+ refetch: (options?: _tanstack_react_query.RefetchOptions) => Promise<_tanstack_react_query.QueryObserverResult<_tanstack_react_query.InfiniteData<PaginatedResponse<UserActivityItem>, unknown>, Error>>;
2283
2729
  fetchStatus: _tanstack_react_query.FetchStatus;
2284
- promise: Promise<_tanstack_react_query.InfiniteData<_agg_build_sdk.PaginatedResponse<UserActivityItem>, unknown>>;
2730
+ promise: Promise<_tanstack_react_query.InfiniteData<PaginatedResponse<UserActivityItem>, unknown>>;
2285
2731
  } | {
2286
2732
  activities: UserActivityItem[];
2287
2733
  hasNextPage: boolean;
@@ -2297,8 +2743,8 @@ declare function useUserActivity(options?: UseUserActivityOptions): {
2297
2743
  isSuccess: false;
2298
2744
  isPlaceholderData: false;
2299
2745
  status: "error";
2300
- fetchNextPage: (options?: _tanstack_react_query.FetchNextPageOptions) => Promise<_tanstack_react_query.InfiniteQueryObserverResult<_tanstack_react_query.InfiniteData<_agg_build_sdk.PaginatedResponse<UserActivityItem>, unknown>, Error>>;
2301
- fetchPreviousPage: (options?: _tanstack_react_query.FetchPreviousPageOptions) => Promise<_tanstack_react_query.InfiniteQueryObserverResult<_tanstack_react_query.InfiniteData<_agg_build_sdk.PaginatedResponse<UserActivityItem>, unknown>, Error>>;
2746
+ fetchNextPage: (options?: _tanstack_react_query.FetchNextPageOptions) => Promise<_tanstack_react_query.InfiniteQueryObserverResult<_tanstack_react_query.InfiniteData<PaginatedResponse<UserActivityItem>, unknown>, Error>>;
2747
+ fetchPreviousPage: (options?: _tanstack_react_query.FetchPreviousPageOptions) => Promise<_tanstack_react_query.InfiniteQueryObserverResult<_tanstack_react_query.InfiniteData<PaginatedResponse<UserActivityItem>, unknown>, Error>>;
2302
2748
  hasPreviousPage: boolean;
2303
2749
  isFetchingNextPage: boolean;
2304
2750
  isFetchingPreviousPage: boolean;
@@ -2315,9 +2761,9 @@ declare function useUserActivity(options?: UseUserActivityOptions): {
2315
2761
  isRefetching: boolean;
2316
2762
  isStale: boolean;
2317
2763
  isEnabled: boolean;
2318
- refetch: (options?: _tanstack_react_query.RefetchOptions) => Promise<_tanstack_react_query.QueryObserverResult<_tanstack_react_query.InfiniteData<_agg_build_sdk.PaginatedResponse<UserActivityItem>, unknown>, Error>>;
2764
+ refetch: (options?: _tanstack_react_query.RefetchOptions) => Promise<_tanstack_react_query.QueryObserverResult<_tanstack_react_query.InfiniteData<PaginatedResponse<UserActivityItem>, unknown>, Error>>;
2319
2765
  fetchStatus: _tanstack_react_query.FetchStatus;
2320
- promise: Promise<_tanstack_react_query.InfiniteData<_agg_build_sdk.PaginatedResponse<UserActivityItem>, unknown>>;
2766
+ promise: Promise<_tanstack_react_query.InfiniteData<PaginatedResponse<UserActivityItem>, unknown>>;
2321
2767
  } | {
2322
2768
  activities: UserActivityItem[];
2323
2769
  hasNextPage: boolean;
@@ -2333,8 +2779,8 @@ declare function useUserActivity(options?: UseUserActivityOptions): {
2333
2779
  isSuccess: false;
2334
2780
  isPlaceholderData: false;
2335
2781
  status: "pending";
2336
- fetchNextPage: (options?: _tanstack_react_query.FetchNextPageOptions) => Promise<_tanstack_react_query.InfiniteQueryObserverResult<_tanstack_react_query.InfiniteData<_agg_build_sdk.PaginatedResponse<UserActivityItem>, unknown>, Error>>;
2337
- fetchPreviousPage: (options?: _tanstack_react_query.FetchPreviousPageOptions) => Promise<_tanstack_react_query.InfiniteQueryObserverResult<_tanstack_react_query.InfiniteData<_agg_build_sdk.PaginatedResponse<UserActivityItem>, unknown>, Error>>;
2782
+ fetchNextPage: (options?: _tanstack_react_query.FetchNextPageOptions) => Promise<_tanstack_react_query.InfiniteQueryObserverResult<_tanstack_react_query.InfiniteData<PaginatedResponse<UserActivityItem>, unknown>, Error>>;
2783
+ fetchPreviousPage: (options?: _tanstack_react_query.FetchPreviousPageOptions) => Promise<_tanstack_react_query.InfiniteQueryObserverResult<_tanstack_react_query.InfiniteData<PaginatedResponse<UserActivityItem>, unknown>, Error>>;
2338
2784
  hasPreviousPage: boolean;
2339
2785
  isFetchingNextPage: boolean;
2340
2786
  isFetchingPreviousPage: boolean;
@@ -2351,9 +2797,9 @@ declare function useUserActivity(options?: UseUserActivityOptions): {
2351
2797
  isRefetching: boolean;
2352
2798
  isStale: boolean;
2353
2799
  isEnabled: boolean;
2354
- refetch: (options?: _tanstack_react_query.RefetchOptions) => Promise<_tanstack_react_query.QueryObserverResult<_tanstack_react_query.InfiniteData<_agg_build_sdk.PaginatedResponse<UserActivityItem>, unknown>, Error>>;
2800
+ refetch: (options?: _tanstack_react_query.RefetchOptions) => Promise<_tanstack_react_query.QueryObserverResult<_tanstack_react_query.InfiniteData<PaginatedResponse<UserActivityItem>, unknown>, Error>>;
2355
2801
  fetchStatus: _tanstack_react_query.FetchStatus;
2356
- promise: Promise<_tanstack_react_query.InfiniteData<_agg_build_sdk.PaginatedResponse<UserActivityItem>, unknown>>;
2802
+ promise: Promise<_tanstack_react_query.InfiniteData<PaginatedResponse<UserActivityItem>, unknown>>;
2357
2803
  } | {
2358
2804
  activities: UserActivityItem[];
2359
2805
  hasNextPage: boolean;
@@ -2368,8 +2814,8 @@ declare function useUserActivity(options?: UseUserActivityOptions): {
2368
2814
  isSuccess: false;
2369
2815
  isPlaceholderData: false;
2370
2816
  status: "pending";
2371
- fetchNextPage: (options?: _tanstack_react_query.FetchNextPageOptions) => Promise<_tanstack_react_query.InfiniteQueryObserverResult<_tanstack_react_query.InfiniteData<_agg_build_sdk.PaginatedResponse<UserActivityItem>, unknown>, Error>>;
2372
- fetchPreviousPage: (options?: _tanstack_react_query.FetchPreviousPageOptions) => Promise<_tanstack_react_query.InfiniteQueryObserverResult<_tanstack_react_query.InfiniteData<_agg_build_sdk.PaginatedResponse<UserActivityItem>, unknown>, Error>>;
2817
+ fetchNextPage: (options?: _tanstack_react_query.FetchNextPageOptions) => Promise<_tanstack_react_query.InfiniteQueryObserverResult<_tanstack_react_query.InfiniteData<PaginatedResponse<UserActivityItem>, unknown>, Error>>;
2818
+ fetchPreviousPage: (options?: _tanstack_react_query.FetchPreviousPageOptions) => Promise<_tanstack_react_query.InfiniteQueryObserverResult<_tanstack_react_query.InfiniteData<PaginatedResponse<UserActivityItem>, unknown>, Error>>;
2373
2819
  hasPreviousPage: boolean;
2374
2820
  isFetchingNextPage: boolean;
2375
2821
  isFetchingPreviousPage: boolean;
@@ -2387,13 +2833,13 @@ declare function useUserActivity(options?: UseUserActivityOptions): {
2387
2833
  isRefetching: boolean;
2388
2834
  isStale: boolean;
2389
2835
  isEnabled: boolean;
2390
- refetch: (options?: _tanstack_react_query.RefetchOptions) => Promise<_tanstack_react_query.QueryObserverResult<_tanstack_react_query.InfiniteData<_agg_build_sdk.PaginatedResponse<UserActivityItem>, unknown>, Error>>;
2836
+ refetch: (options?: _tanstack_react_query.RefetchOptions) => Promise<_tanstack_react_query.QueryObserverResult<_tanstack_react_query.InfiniteData<PaginatedResponse<UserActivityItem>, unknown>, Error>>;
2391
2837
  fetchStatus: _tanstack_react_query.FetchStatus;
2392
- promise: Promise<_tanstack_react_query.InfiniteData<_agg_build_sdk.PaginatedResponse<UserActivityItem>, unknown>>;
2838
+ promise: Promise<_tanstack_react_query.InfiniteData<PaginatedResponse<UserActivityItem>, unknown>>;
2393
2839
  } | {
2394
2840
  activities: UserActivityItem[];
2395
2841
  hasNextPage: boolean;
2396
- data: _tanstack_react_query.InfiniteData<_agg_build_sdk.PaginatedResponse<UserActivityItem>, unknown>;
2842
+ data: _tanstack_react_query.InfiniteData<PaginatedResponse<UserActivityItem>, unknown>;
2397
2843
  isError: false;
2398
2844
  error: null;
2399
2845
  isPending: false;
@@ -2405,8 +2851,8 @@ declare function useUserActivity(options?: UseUserActivityOptions): {
2405
2851
  isFetchNextPageError: false;
2406
2852
  isFetchPreviousPageError: false;
2407
2853
  status: "success";
2408
- fetchNextPage: (options?: _tanstack_react_query.FetchNextPageOptions) => Promise<_tanstack_react_query.InfiniteQueryObserverResult<_tanstack_react_query.InfiniteData<_agg_build_sdk.PaginatedResponse<UserActivityItem>, unknown>, Error>>;
2409
- fetchPreviousPage: (options?: _tanstack_react_query.FetchPreviousPageOptions) => Promise<_tanstack_react_query.InfiniteQueryObserverResult<_tanstack_react_query.InfiniteData<_agg_build_sdk.PaginatedResponse<UserActivityItem>, unknown>, Error>>;
2854
+ fetchNextPage: (options?: _tanstack_react_query.FetchNextPageOptions) => Promise<_tanstack_react_query.InfiniteQueryObserverResult<_tanstack_react_query.InfiniteData<PaginatedResponse<UserActivityItem>, unknown>, Error>>;
2855
+ fetchPreviousPage: (options?: _tanstack_react_query.FetchPreviousPageOptions) => Promise<_tanstack_react_query.InfiniteQueryObserverResult<_tanstack_react_query.InfiniteData<PaginatedResponse<UserActivityItem>, unknown>, Error>>;
2410
2856
  hasPreviousPage: boolean;
2411
2857
  isFetchingNextPage: boolean;
2412
2858
  isFetchingPreviousPage: boolean;
@@ -2423,9 +2869,9 @@ declare function useUserActivity(options?: UseUserActivityOptions): {
2423
2869
  isRefetching: boolean;
2424
2870
  isStale: boolean;
2425
2871
  isEnabled: boolean;
2426
- refetch: (options?: _tanstack_react_query.RefetchOptions) => Promise<_tanstack_react_query.QueryObserverResult<_tanstack_react_query.InfiniteData<_agg_build_sdk.PaginatedResponse<UserActivityItem>, unknown>, Error>>;
2872
+ refetch: (options?: _tanstack_react_query.RefetchOptions) => Promise<_tanstack_react_query.QueryObserverResult<_tanstack_react_query.InfiniteData<PaginatedResponse<UserActivityItem>, unknown>, Error>>;
2427
2873
  fetchStatus: _tanstack_react_query.FetchStatus;
2428
- promise: Promise<_tanstack_react_query.InfiniteData<_agg_build_sdk.PaginatedResponse<UserActivityItem>, unknown>>;
2874
+ promise: Promise<_tanstack_react_query.InfiniteData<PaginatedResponse<UserActivityItem>, unknown>>;
2429
2875
  };
2430
2876
 
2431
2877
  interface UseExternalIdOptions {
@@ -2780,6 +3226,38 @@ declare function useLiveOutcomePrices(venueMarkets: VenueMarket[] | null | undef
2780
3226
  */
2781
3227
  declare function findLivePriceById(livePrices: Map<string, number>, id: string): number | undefined;
2782
3228
 
3229
+ type LiveBestPrices = ReadonlyMap<string, {
3230
+ bestBid?: number;
3231
+ bestAsk?: number;
3232
+ }>;
3233
+ /**
3234
+ * WS-derived cross-venue + cross-outcome best bid/ask per outcome.
3235
+ *
3236
+ * For each outcome in `venueMarkets` (plus matched twins via MVMO refs):
3237
+ * - bestBid/bestAsk taken from the per-outcome aggregated top of book.
3238
+ * - Then folded across MVMO groups: lowest bestAsk wins (cheapest to buy),
3239
+ * highest bestBid wins (best to sell). The chosen best is broadcast to
3240
+ * every member of the group so display surfaces pick it up regardless
3241
+ * of which outcome they look up.
3242
+ *
3243
+ * Empty until WS snapshots/deltas land for the subscribed outcomes. Designed
3244
+ * to merge as overrides on top of REST `bestPrices` from `useMidpoints`, with
3245
+ * WS winning where present.
3246
+ */
3247
+ declare function useLiveBestPrices(venueMarkets: VenueMarket[] | null | undefined): LiveBestPrices;
3248
+ /**
3249
+ * Merge WS bestBid/bestAsk over a REST `bestPrices` map, WS values winning
3250
+ * where present. Returns the REST map unchanged when WS is empty. Designed
3251
+ * for callers that need to pass a single `bestPrices` map to display logic.
3252
+ */
3253
+ declare function mergeBestPricesPreferringLive(rest: ReadonlyMap<string, {
3254
+ bestBid?: number;
3255
+ bestAsk?: number;
3256
+ }> | null | undefined, live: LiveBestPrices): ReadonlyMap<string, {
3257
+ bestBid?: number;
3258
+ bestAsk?: number;
3259
+ }>;
3260
+
2783
3261
  /**
2784
3262
  * Subscribe to real-time trade feed for a canonical market.
2785
3263
  * Manages a separate trade subscription on the WS (trades use a different channel).
@@ -2790,27 +3268,100 @@ declare function useLiveTrades(canonicalMarketId: string | null): WsTrade[];
2790
3268
  interface UseMidpointsResult {
2791
3269
  /** Map of outcomeId → price. Empty while loading. */
2792
3270
  prices: Map<string, number>;
3271
+ /**
3272
+ * Map of outcomeId → lowest midpoint available for that exact semantic outcome
3273
+ * across the selected market cluster. Alias of `prices`, exposed under a
3274
+ * clearer name for display surfaces that want a single source of truth.
3275
+ */
3276
+ bestMidpointsByOutcomeId: Map<string, number>;
2793
3277
  /**
2794
3278
  * Map of outcomeId → venue name that provided the price in `prices`.
2795
- * When a matched venue offers a lower YES price, this records that venue so
2796
- * callers can show the correct venue logo alongside the best price.
3279
+ * When a matched sibling offers a lower midpoint for the same semantic
3280
+ * side, this records that sibling's venue so callers can show the
3281
+ * correct venue logo alongside the best price.
2797
3282
  * Empty while loading or when the API response omits `venue` fields.
2798
3283
  */
2799
3284
  venueByOutcomeId: Map<string, string>;
3285
+ /**
3286
+ * Map of outcomeId → { bestBid?, bestAsk? }. Top-of-book prices extracted
3287
+ * from the midpoints response when bestPrice=true. Empty while loading
3288
+ * or when bestPrice data is unavailable.
3289
+ */
3290
+ bestPrices: Map<string, {
3291
+ bestBid?: number;
3292
+ bestAsk?: number;
3293
+ }>;
3294
+ /**
3295
+ * Map of outcomeId → { bestBidVenue?, bestAskVenue? }. Tracks which venue
3296
+ * supplied the winning side of the book across the MVMO group so display
3297
+ * surfaces can pair the logo with the price. Distinct per side because
3298
+ * "best buy" and "best sell" can come from different venues.
3299
+ */
3300
+ bestPriceVenuesByOutcomeId: Map<string, {
3301
+ bestBidVenue?: string;
3302
+ bestAskVenue?: string;
3303
+ }>;
2800
3304
  /** True while the midpoints fetch is in flight. */
2801
3305
  isLoading: boolean;
3306
+ /** Best midpoint value across all venues. Undefined while loading. */
3307
+ bestMidpoint: number | undefined;
3308
+ /**
3309
+ * Venue that produced `bestMidpoint`. Paired with `bestMidpoint` from the
3310
+ * same winning outcome so display surfaces can render a matching logo +
3311
+ * price. Undefined when no candidate produced a price or when the
3312
+ * response lacked a `venue` field.
3313
+ */
3314
+ bestMidpointVenue: string | undefined;
2802
3315
  }
2803
3316
  /**
2804
3317
  * Fetches live midpoints for the given venue markets.
2805
3318
  *
2806
3319
  * Returns { prices, isLoading } so callers can show a skeleton while loading.
2807
3320
  *
2808
- * Uses per-outcome midpoints from the API (each outcome has its own orderbook
2809
- * midpoint) to avoid the primary-outcome inversion bug. Falls back to the
2810
- * market-level midpoint with label-based derivation when outcomes are absent.
3321
+ * Cross-venue best-price selection walks each parent outcome's
3322
+ * `matchedVenueMarketOutcomes` (MVMO references) and looks up the matched
3323
+ * counterpart's per-outcome midpoint in `matched[].outcomes`. The lowest
3324
+ * midpoint wins per outcome — semantically correct for both Yes and No
3325
+ * sides because MVMO links same-side counterparts regardless of label
3326
+ * inversion. No label heuristics; no `1 - midpoint` flips.
2811
3327
  */
2812
3328
  declare function useMidpoints(venueMarkets: VenueMarket[] | null | undefined): UseMidpointsResult;
2813
3329
 
3330
+ interface UseTradableVenuesResult {
3331
+ /**
3332
+ * Set of venue strings that have at least one outcome with a non-null
3333
+ * midpoint from the engine. When non-null, this is the authoritative
3334
+ * set of venues that have a live orderbook for the given cluster.
3335
+ *
3336
+ * `null` while midpoints are still loading — callers should treat this
3337
+ * as "unknown, don't filter yet" and show all venues optimistically.
3338
+ */
3339
+ tradableVenues: ReadonlySet<string> | null;
3340
+ /** True while the underlying midpoints fetch is in flight. */
3341
+ isLoading: boolean;
3342
+ }
3343
+ /**
3344
+ * Dynamic venue-orderbook availability check.
3345
+ *
3346
+ * Walks the cluster's midpoints (already fetched via /midpoints by the
3347
+ * surrounding component, or fetched fresh here if not) and returns the
3348
+ * set of venues that have at least one outcome with a non-null midpoint.
3349
+ * A venue with NO non-null midpoints across all its outcomes is treated
3350
+ * as "no live orderbook" — it appeared in matching/discovery but the
3351
+ * engine isn't quoting it (e.g. opinion).
3352
+ *
3353
+ * The signal is purely runtime: no hardcoded venue allowlist. New
3354
+ * venues that join without orderbook support get filtered automatically;
3355
+ * venues whose orderbook stream temporarily drops also get filtered
3356
+ * until midpoints come back. This keeps the FE in lockstep with what the
3357
+ * engine is actually able to quote, without coordinating constants
3358
+ * across BE/FE on every venue addition.
3359
+ *
3360
+ * Use this in surfaces that need to show "X tradeable venues" or filter
3361
+ * a venue logo strip — see `getVenueSummary`'s `tradableVenues` option.
3362
+ */
3363
+ declare function useTradableVenues(venueMarkets: VenueMarket[] | null | undefined): UseTradableVenuesResult;
3364
+
2814
3365
  interface UseMarketChartOptions {
2815
3366
  /** VenueMarketOutcome.id */
2816
3367
  marketId: string | null;
@@ -2823,6 +3374,25 @@ interface UseMarketChartOptions {
2823
3374
  enabled?: boolean;
2824
3375
  /** Enable live WS updates. Defaults to the global `enableLiveUpdates` config. */
2825
3376
  live?: boolean;
3377
+ /**
3378
+ * Auto-refetch the REST history at this cadence (ms). Pair with a rolling
3379
+ * window whose `endTs` advances at the same bucket interval — each tick
3380
+ * refetches the latest window under a stable cache key, so closed bars
3381
+ * the WebSocket missed are backfilled. `null`/omitted disables auto-refetch.
3382
+ */
3383
+ refetchIntervalMs?: number | null;
3384
+ /**
3385
+ * Stable identifier for the user-selected range (e.g. `"1H"`, `"6H"`).
3386
+ * Used as the React Query cache key so the entry survives bucket rollovers
3387
+ * and tab/page revisits. The concrete `startTs`/`endTs` advance under the
3388
+ * same key and are passed to the fetch via closure.
3389
+ *
3390
+ * If omitted, falls back to `interval` — preserves cache reuse for callers
3391
+ * that don't drive a rolling window. Note that 6H and 1D both use a 5m
3392
+ * interval, so callers using rolling windows should pass an explicit
3393
+ * `rangeKey` to keep their cache entries separate.
3394
+ */
3395
+ rangeKey?: string;
2826
3396
  }
2827
3397
  interface UseMarketChartResult {
2828
3398
  data: MarketChartData | null;
@@ -2833,6 +3403,93 @@ interface UseMarketChartResult {
2833
3403
  }
2834
3404
  declare function useMarketChart(options: UseMarketChartOptions): UseMarketChartResult;
2835
3405
 
3406
+ interface UseRollingChartWindowOptions {
3407
+ range: ChartTimeRange;
3408
+ /**
3409
+ * Override the WS candle interval. Defaults to the canonical mapping from
3410
+ * `timeRangeToInterval`. Tests use this to inject a deterministic value.
3411
+ */
3412
+ interval?: WsCandleInterval;
3413
+ /**
3414
+ * Tick cadence for `nowSec`, in milliseconds. Defaults to 1s. The query
3415
+ * boundary (`endTs`) is bucketized so React Query only refetches when the
3416
+ * candle bucket advances, not on every tick.
3417
+ */
3418
+ tickMs?: number;
3419
+ /**
3420
+ * Read of `Date.now()` (ms). Overridable for tests.
3421
+ */
3422
+ nowMs?: () => number;
3423
+ }
3424
+ interface RollingChartWindow {
3425
+ range: ChartTimeRange;
3426
+ interval: WsCandleInterval;
3427
+ /** Width of the visible/rolling domain in seconds. */
3428
+ rangeSeconds: number;
3429
+ /** Width of one closed bar in seconds. */
3430
+ intervalSeconds: number;
3431
+ /**
3432
+ * Current wall-clock seconds, updated on every tick. The visible domain is
3433
+ * always `[nowSec - rangeSeconds, nowSec]` — use this for filtering points
3434
+ * to the rolling window.
3435
+ */
3436
+ nowSec: number;
3437
+ /**
3438
+ * Bucketized end of the rolling window. Snaps to the next interval
3439
+ * boundary so the React Query key (and therefore REST refetch) only
3440
+ * advances when a new candle bucket starts. Use this as `endTs` for the
3441
+ * REST query.
3442
+ */
3443
+ endTs: number;
3444
+ /**
3445
+ * Bucketized start: `endTs - rangeSeconds`. Use as `startTs` for the
3446
+ * REST query.
3447
+ */
3448
+ startTs: number;
3449
+ /**
3450
+ * Refetch interval to pass to React Query, in milliseconds. Matches one
3451
+ * candle bucket so historical bars roll in cleanly even without WS.
3452
+ */
3453
+ refetchIntervalMs: number;
3454
+ }
3455
+ declare const rangeToSeconds: (range: ChartTimeRange) => number;
3456
+ /**
3457
+ * Pure resolver for the rolling window, factored out of `useRollingChartWindow`
3458
+ * so the time-math can be unit-tested without rendering React.
3459
+ *
3460
+ * Invariants:
3461
+ * - `nowSec - rangeSeconds === domainStartTs` (the visible domain is
3462
+ * always exactly `rangeSeconds` wide regardless of how long mounted).
3463
+ * - `endTs - startTs === rangeSeconds` (the bucketized query window is
3464
+ * also exactly `rangeSeconds` wide; only the alignment to bucket
3465
+ * boundaries differs from the visible domain).
3466
+ * - `endTs % intervalSeconds === 0` (snaps to next bucket boundary so
3467
+ * the React Query key stays stable between bucket rollovers).
3468
+ */
3469
+ declare const resolveRollingWindow: (params: {
3470
+ range: ChartTimeRange;
3471
+ nowSec: number;
3472
+ interval?: WsCandleInterval;
3473
+ }) => RollingChartWindow;
3474
+ /**
3475
+ * Drives a rolling time domain `[nowSec - rangeSeconds, nowSec]` that ticks
3476
+ * while the chart is mounted.
3477
+ *
3478
+ * Why two timestamps (`nowSec` vs `endTs`):
3479
+ * - `nowSec` updates every `tickMs` (default 1s) so the visible domain
3480
+ * stays exactly `rangeSeconds` wide. Series points outside that domain
3481
+ * should be filtered out by the caller.
3482
+ * - `endTs` is bucketized to the next interval boundary so React Query's
3483
+ * key only changes when a new candle bucket actually starts. Without
3484
+ * this, the chart would refetch every tick.
3485
+ *
3486
+ * The bucket advance is also what drives REST refetches that backfill any
3487
+ * closed bars the WebSocket missed. WS updates feed the in-flight candle
3488
+ * and promote it on rollover (see `chart-cache.applyMidpointToMarketChart`);
3489
+ * the REST refetch only matters when WS is disconnected or quiet.
3490
+ */
3491
+ declare const useRollingChartWindow: (options: UseRollingChartWindowOptions) => RollingChartWindow;
3492
+
2836
3493
  interface UseMarketOrderbookVenueOutcome {
2837
3494
  venue: VenueMarket["venue"];
2838
3495
  venueMarketOutcomeId: string;
@@ -3092,6 +3749,15 @@ interface UseSearchOptions {
3092
3749
  limit?: number;
3093
3750
  /** If provided, enable/disable the query. Defaults to true. */
3094
3751
  enabled?: boolean;
3752
+ /**
3753
+ * Opt in to the server-side reranker for higher-quality top results.
3754
+ *
3755
+ * Recommended for the full search-results page (submit / Enter) and NOT
3756
+ * for debounced typeahead — the latter shouldn't pay reranker latency on
3757
+ * every keystroke. The flag is baked into the query cache key, so deep
3758
+ * and light variants of the same query never share results. Default false.
3759
+ */
3760
+ deep?: boolean;
3095
3761
  }
3096
3762
  /**
3097
3763
  * Search events or markets via the /search endpoint with cursor-based pagination.
@@ -3101,6 +3767,9 @@ interface UseSearchOptions {
3101
3767
  * ```ts
3102
3768
  * const { data } = useSearch<VenueEventWithMarkets>({ q: "...", type: "events" });
3103
3769
  * ```
3770
+ *
3771
+ * For typeahead + full-results in one hook, prefer `useMarketSearch` — it
3772
+ * wires up the debounce, submit, and cancellation semantics out of the box.
3104
3773
  */
3105
3774
  declare function useSearch<T = VenueEvent>(options: UseSearchOptions): {
3106
3775
  data: T[];
@@ -3118,6 +3787,100 @@ declare function useSearch<T = VenueEvent>(options: UseSearchOptions): {
3118
3787
  isPlaceholderData: boolean;
3119
3788
  };
3120
3789
 
3790
+ interface UseMarketSearchOptions {
3791
+ /** Search type: "events" or "markets". */
3792
+ type: "events" | "markets";
3793
+ /** Optional category ID filter. */
3794
+ categoryIds?: string[];
3795
+ /** Page size for both modes. Default 20. */
3796
+ limit?: number;
3797
+ /**
3798
+ * Debounce delay applied to the typeahead/light query, in ms. The submit
3799
+ * path bypasses debounce entirely. Default 200.
3800
+ */
3801
+ debounceMs?: number;
3802
+ /**
3803
+ * Set to `false` to disable the typeahead/light query (no /search call
3804
+ * while the user types). The submit path still fires deep searches.
3805
+ * Default true.
3806
+ */
3807
+ enableSuggestions?: boolean;
3808
+ /**
3809
+ * Minimum query length before the typeahead fires. Default 1 — set higher
3810
+ * (e.g. 3) if `/search` cost per keystroke is a concern. The submit path
3811
+ * ignores this threshold.
3812
+ */
3813
+ minLength?: number;
3814
+ }
3815
+ /**
3816
+ * Combined typeahead + submit hook for the canonical search UX.
3817
+ *
3818
+ * ┌─────────────────────────────┐
3819
+ * │ user types "tru" │ → debounced light /search → suggestions[]
3820
+ * │ user types "trum" │ → debounced light /search → suggestions[]
3821
+ * │ user presses Enter │ → deep /search → results[]
3822
+ * └─────────────────────────────┘
3823
+ *
3824
+ * Typeahead (`suggestions`) and submit-results (`results`) are cached under
3825
+ * separate TanStack Query keys, so navigating away and back doesn't lose
3826
+ * either. Server-side the same separation holds: the `deep` flag is part of
3827
+ * the cache key, so the two modes never collide.
3828
+ *
3829
+ * ```tsx
3830
+ * const { query, setQuery, submit, suggestions, results } = useMarketSearch({
3831
+ * type: "markets",
3832
+ * });
3833
+ *
3834
+ * <input
3835
+ * value={query}
3836
+ * onChange={(e) => setQuery(e.target.value)}
3837
+ * onKeyDown={(e) => { if (e.key === "Enter") submit(); }}
3838
+ * />
3839
+ * {suggestions.data.map(...)} // dropdown
3840
+ * {results.data.map(...)} // full page after Enter
3841
+ * ```
3842
+ */
3843
+ declare function useMarketSearch<T = VenueEvent>(options: UseMarketSearchOptions): {
3844
+ /** Current input value (controlled). */
3845
+ query: string;
3846
+ /** Update the input value. Triggers the debounced typeahead. */
3847
+ setQuery: (value: string) => void;
3848
+ /** The query value that produced the current `results`, or null if none. */
3849
+ submittedQuery: string | null;
3850
+ /** Fire a deep search. Use this on Enter / Search button. */
3851
+ submit: (q?: string) => void;
3852
+ /** Reset both input and results state. */
3853
+ clear: () => void;
3854
+ /**
3855
+ * Typeahead state. Backed by a light /search call (no reranker).
3856
+ * `data` is paginated like `useSearch.data` (flattened across pages).
3857
+ */
3858
+ suggestions: {
3859
+ data: T[];
3860
+ isLoading: boolean;
3861
+ isError: boolean;
3862
+ error: Error | null;
3863
+ };
3864
+ /**
3865
+ * Full-page results state. Backed by a deep /search call (reranker on).
3866
+ * Cursor pagination is exposed via `fetchNextPage` / `hasNextPage`.
3867
+ */
3868
+ results: {
3869
+ data: T[];
3870
+ isLoading: boolean;
3871
+ isError: boolean;
3872
+ error: Error | null;
3873
+ hasNextPage: boolean;
3874
+ fetchNextPage: (options?: _tanstack_react_query.FetchNextPageOptions) => Promise<_tanstack_react_query.InfiniteQueryObserverResult<_tanstack_react_query.InfiniteData<{
3875
+ type: "markets" | "events";
3876
+ data: T[];
3877
+ nextCursor: string | null;
3878
+ hasMore: boolean;
3879
+ }, unknown>, Error>>;
3880
+ isFetchingNextPage: boolean;
3881
+ };
3882
+ };
3883
+
3121
3884
  interface UseSmartRouteOptions {
3122
3885
  /** Venue market outcome ID used by the smart-route endpoint. */
3123
3886
  venueMarketOutcomeId?: string | null;
@@ -3139,8 +3902,18 @@ interface UseSmartRouteOptions {
3139
3902
  slipCapBps?: number;
3140
3903
  /** Include venue-by-venue comparison quotes. */
3141
3904
  compareVenues?: boolean;
3905
+ /**
3906
+ * Opt in to the deep cost-estimate surface — response `feeBreakdown`
3907
+ * gains `setupCosts` (chain approvals + Kalshi ATAs) with `alreadyPaid`
3908
+ * flags from prior trade history, and `setupCostsTotal` is folded into
3909
+ * `totalCostIncFees` (with `estimatedProfit` / `returnPct` recomputed).
3910
+ * Buy-only.
3911
+ */
3912
+ deepEstimate?: boolean;
3142
3913
  /** Enable/disable the query. Default true. */
3143
3914
  enabled?: boolean;
3915
+ /** Cache freshness and polling interval in milliseconds. Defaults to SMART_ROUTE_STALE_TIME_MS. */
3916
+ staleTimeMs?: number;
3144
3917
  }
3145
3918
  interface UseSmartRouteResult {
3146
3919
  data: SmartRouteResponse | null;
@@ -3768,6 +4541,8 @@ interface UseVenueEventsOptions {
3768
4541
  sortBy?: string;
3769
4542
  /** Sort direction: "asc" or "desc". */
3770
4543
  sortDir?: string;
4544
+ /** Recurrence filter (for venue events that support recurrence dimensions). */
4545
+ recurrence?: string;
3771
4546
  /** If provided, enable the query. */
3772
4547
  enabled?: boolean;
3773
4548
  /** Page size when using cursor pagination. Default 20. */
@@ -4495,15 +5270,18 @@ declare function computePriceGaps(input: ComputePriceGapsInput): Map<string, num
4495
5270
  * • Markets that become visible for the first time are batched into a
4496
5271
  * single request on the next render.
4497
5272
  *
4498
- * The returned `prices` map is keyed by outcome id — "Yes" outcomes get the
4499
- * aggregated best midpoint across matched venues; "No" outcomes get its
4500
- * complement (1 - midpoint).
5273
+ * Cross-venue best-price selection walks each parent outcome's
5274
+ * `matchedVenueMarketOutcomes` (MVMO references) and looks up the matched
5275
+ * counterpart's per-outcome midpoint. The lowest midpoint wins per
5276
+ * outcome — semantically correct for both Yes and No sides because MVMO
5277
+ * links same-side counterparts regardless of label inversion.
4501
5278
  */
4502
5279
  declare function useViewportMidpoints(visibleMarkets: VenueMarket[]): {
4503
5280
  prices: Map<string, number>;
4504
5281
  /**
4505
5282
  * Map of outcomeId → venue name that provided the price in `prices`.
4506
- * Populated when a matched venue offers a lower YES price than the primary.
5283
+ * Populated when a matched sibling offers a lower midpoint for the same
5284
+ * semantic side.
4507
5285
  */
4508
5286
  venueByOutcomeId: Map<string, string>;
4509
5287
  };
@@ -4536,6 +5314,7 @@ interface UseAppConfigResult {
4536
5314
  disabledVenues: AppClientConfigResponse["disabledVenues"];
4537
5315
  disabledCategoryPresets: AppClientConfigResponse["disabledCategoryPresets"];
4538
5316
  earlyAccessEnabled: AppClientConfigResponse["earlyAccessEnabled"];
5317
+ authOptions: AppClientConfigResponse["authOptions"];
4539
5318
  isLoading: boolean;
4540
5319
  error: unknown;
4541
5320
  }
@@ -4545,4 +5324,4 @@ interface UseAppConfigResult {
4545
5324
  */
4546
5325
  declare function useAppConfig(): UseAppConfigResult;
4547
5326
 
4548
- export { AUTH_CHOOSER_OPEN_EVENT, type AggAuthContextValue, type AggAuthSignInOptions, type AggBalanceContextValue, AggBalanceProvider, AggProvider, type AggProviderProps, AggProvider as AggSdkProvider, type AggProviderProps as AggSdkProviderProps, type AggUiConfig, type AggUiConfigInput, type AggUiLabels, type AggUiLabelsInput, AggUiProvider, CHART_TIME_RANGES, CONFIRMED_MATCH_STATUSES, type ChartTimeRange, type ClosedPositionTotals, type ComputePriceGapsInput, DEFAULT_AGG_ROOT_CLASS_NAME, type DagStepProgress, type EventListStateContextValue, EventListStateProvider, type EventListStateSnapshot, type EventTradingContextValue, type EventTradingState, type ExecutionProgressPhase, type ExecutionTerminalOrderEvent, type GeoBlockState, type GetOrdersQuery, type GetPositionsQuery, type LiveCandle, type MarketChartCandle, type MarketChartData, type MarketChartVenueData, type MarketOrderbookData, type MarketOrderbookIntegrity, MarketStatus, type MarketTradingState, MatchStatus, MatchType, type OrderEligibility, type OrderEligibilityReason, type OrderListItem, type OrderbookResult, type PositionGroup, type PriceGapMarket, type RedeemEvent, type ScaledCandlePoint, type SdkUiConfig, type SdkUiConfigInput, type SdkUiProviderProps, type ThemeMode, type TradingAction, type TradingState, type TradingStateBase, type TradingStateKind, type UseAggAuthOptions, type UseAggAuthReturn, type UseAppConfigResult, type UseCategoriesOptions, type UseEnrichedVenueEventOptions, type UseExecuteManagedOptions, type UseExecutionOrdersOptions, type UseExecutionPositionsOptions, type UseExecutionProgressOptions, type UseExecutionProgressResult, type UseExternalIdOptions, type UseExternalIdReturn, type UseLinkAccountReturn, type UseLiveCandleOverlayOptions, type UseLiveCandleOverlayResult, type UseLiveCandlesOptions, type UseLiveCandlesResult, type UseLiveMarketResult, type UseMarketChartOptions, type UseMarketChartResult, type UseMarketOrderbookOptions, type UseMarketOrderbookResult, type UseMarketOrderbookVenueOutcome, type UseOrderBookOptions, type UseOrderbookQuoteOptions, type UseOrderbookQuoteResult, type UseOrdersOptions, type UsePositionsOptions, type UseQuoteManagedOptions, type UseSearchOptions, type UseSmartRouteOptions, type UseSmartRouteResult, type UseUserActivityOptions, type UseUserHoldingsOptions, type UseVenueEventOptions, type UseVenueEventsOptions, type UseVenueMarketMidpointsOptions, type UseVenueMarketsOptions, type UseVisibleIdsOptions, type UseVisibleIdsResult, Venue, type VenueEvent, type VenueEventWithMarkets, type VenueMarket, type VenueMarketOutcome, type WalletActionSendTokenParams, type WalletActions, computeClosedPositionTotals, computePriceGaps, defaultAggUiConfig, defaultAggUiConfig as defaultSdkUiConfig, executionKeys, findLivePriceById, getBuilder, getOrCreateBuilder, getWalletAddressFromUserProfile, invalidateBalanceQueries, invalidatePositionQueries, optimizedImageUrl, parseEmail, parseEmailStrict, requestAggAuthChooserOpen, resolveAggUiLabels, resolveDefaultMarket as resolveDefaultTradingMarket, resolveEventTradingState, resolveMarketTradingState, resolveMarketWinningOutcome, resolveOrderEligibility, resolveTradingStateKind, sortVenues, timeRangeToInterval, tradingReducer, useAggAuth, useAggAuthContext, useAggAuthState, useAggBalance, useAggBalanceContext, useAggBalanceState, useAggClient, useAggLabels, useAggUiConfig, useAggWebSocket, useAppConfig, useCategories, useDebouncedValue, useEnrichedVenueEvent, useEventListState, useEventOrderbookData, useEventTradingContext, useExecuteManaged, useExecutionOrders, useExecutionPositions, useExecutionProgress, useExternalId, useGeoBlock, useLabels, useLinkAccount, useLiveCandleOverlay, useLiveCandles, useLiveMarket, useLiveMarketStores, useLiveOutcomePrices, useLiveTrades, useMarketChart, useMarketOrderbook, useMidpoints, useOnBalanceUpdate, useOnOrderSubmitted, useOnRedeemEvent, useOnWithdrawalLifecycle, useOrderBook, useOrderbookQuote, useOrders, usePositions, useQuoteManaged, useRampQuotes, useRampSession, useRedeem, useRedeemEligibleCount, useSdkLabels, useSdkUiConfig, useSearch, useSmartRoute, useUserActivity, useUserHoldings, useVenueEvent, useVenueEvents, useVenueMarketMidpoints, useVenueMarkets, useViewportMidpoints, useVisibleIds };
5327
+ export { AUTH_CHOOSER_OPEN_EVENT, type AggAuthContextValue, type AggAuthSignInOptions, type AggBalanceContextValue, AggBalanceProvider, AggProvider, type AggProviderProps, AggProvider as AggSdkProvider, type AggProviderProps as AggSdkProviderProps, type AggUiConfig, type AggUiConfigInput, type AggUiLabels, type AggUiLabelsInput, AggUiProvider, CHART_TIME_RANGES, CONFIRMED_MATCH_STATUSES, type ChartTimeRange, type ClosedPositionTotals, type ComputePriceGapsInput, DEFAULT_AGG_ROOT_CLASS_NAME, type DagStepProgress, type EventListStateContextValue, EventListStateProvider, type EventListStateSnapshot, type EventTradingContextValue, type EventTradingState, type ExecutionProgressPhase, type ExecutionTerminalOrderEvent, type GeoBlockState, type GetOrdersQuery, type GetPositionsQuery, type InvalidateUserActivityOptions, type InvalidateUserMoneyStateOptions, type LiveBestPrices, type LiveCandle, type MarketChartCandle, type MarketChartData, type MarketChartVenueData, type MarketOrderbookData, type MarketOrderbookIntegrity, MarketStatus, type MarketTradingState, MatchStatus, MatchType, type OrderEligibility, type OrderEligibilityReason, type OrderListItem, type OrderbookResult, type PositionGroup, type PriceGapMarket, type RedeemEvent, type RedeemLegLifecycle, type RedeemLifecycleState, RedeemRejectedError, type RollingChartWindow, type ScaledCandlePoint, type SdkUiConfig, type SdkUiConfigInput, type SdkUiProviderProps, type ThemeMode, TradeSide, type TradingAction, type TradingState, type TradingStateBase, type TradingStateKind, type UseAggAuthOptions, type UseAggAuthReturn, type UseAppConfigResult, type UseCategoriesOptions, type UseEnrichedVenueEventOptions, type UseExecuteManagedOptions, type UseExecutionOrdersOptions, type UseExecutionPositionsOptions, type UseExecutionProgressOptions, type UseExecutionProgressResult, type UseExternalIdOptions, type UseExternalIdReturn, type UseLinkAccountReturn, type UseLiveCandleOverlayOptions, type UseLiveCandleOverlayResult, type UseLiveCandlesOptions, type UseLiveCandlesResult, type UseLiveMarketResult, type UseMarketChartOptions, type UseMarketChartResult, type UseMarketOrderbookOptions, type UseMarketOrderbookResult, type UseMarketOrderbookVenueOutcome, type UseMarketSearchOptions, type UseMidpointsResult, type UseOrderBookOptions, type UseOrderbookQuoteOptions, type UseOrderbookQuoteResult, type UseOrdersOptions, type UsePositionsOptions, type UseQuoteManagedOptions, type UseRedeemLifecycleInput, type UseRollingChartWindowOptions, type UseSearchOptions, type UseSmartRouteOptions, type UseSmartRouteResult, type UseTradableVenuesResult, type UseUserActivityOptions, type UseUserHoldingsOptions, type UseVenueEventOptions, type UseVenueEventsOptions, type UseVenueMarketMidpointsOptions, type UseVenueMarketsOptions, type UseVisibleIdsOptions, type UseVisibleIdsResult, type UserActivityInvalidationStrategy, Venue, type VenueEvent, type VenueEventWithMarkets, type VenueMarket, type VenueMarketOutcome, type WalletActionSendTokenParams, type WalletActions, computeClosedPositionTotals, computePriceGaps, defaultAggUiConfig, defaultAggUiConfig as defaultSdkUiConfig, executionKeys, findLivePriceById, getBuilder, getOrCreateBuilder, getWalletAddressFromUserProfile, invalidateBalanceQueries, invalidatePositionQueries, invalidateUserActivityQueries, invalidateUserMoneyState, mergeBestPricesPreferringLive, optimizedImageUrl, parseEmail, parseEmailStrict, rangeToSeconds, requestAggAuthChooserOpen, resolveAggUiLabels, resolveDefaultMarket as resolveDefaultTradingMarket, resolveEventTradingState, resolveMarketTradingState, resolveMarketWinningOutcome, resolveOrderEligibility, resolveRollingWindow, resolveTradingStateKind, sortVenues, timeRangeToInterval, tradingReducer, useAggAuth, useAggAuthContext, useAggAuthState, useAggBalance, useAggBalanceContext, useAggBalanceState, useAggClient, useAggLabels, useAggUiConfig, useAggWebSocket, useAppConfig, useCategories, useDebouncedValue, useEnrichedVenueEvent, useEventListState, useEventOrderbookData, useEventTradingContext, useExecuteManaged, useExecutionOrders, useExecutionPositions, useExecutionProgress, useExternalId, useGeoBlock, useLabels, useLinkAccount, useLiveBestPrices, useLiveCandleOverlay, useLiveCandles, useLiveMarket, useLiveMarketStores, useLiveOutcomePrices, useLiveTrades, useMarketChart, useMarketOrderbook, useMarketSearch, useMidpoints, useOnBalanceUpdate, useOnOrderEvent, useOnOrderSubmitted, useOnRedeemEvent, useOnWithdrawalLifecycle, useOptionalAggClient, useOrderBook, useOrderbookQuote, useOrders, usePositions, useQuoteManaged, useRampQuotes, useRampSession, useRedeem, useRedeemEligibleCount, useRedeemLifecycle, useRedeemLifecycles, useRollingChartWindow, useSdkLabels, useSdkUiConfig, useSearch, useSmartRoute, useTradableVenues, useUserActivity, useUserHoldings, useVenueEvent, useVenueEvents, useVenueMarketMidpoints, useVenueMarkets, useViewportMidpoints, useVisibleIds, userActivityQueryKeys };