@agg-build/hooks 4.28.0 → 4.28.1

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["UserProfile","AggClient","QueryClient","CURRENT_USER_QUERY_KEY","const","CURRENT_USER_STALE_TIME_MS","getCurrentUserQueryKey","queryKeyScope","fetchCurrentUserProfile","queryClient","client","queryKey","Promise","fetchQuery","queryFn","getCurrentUser","staleTime","UserProfile","AggAuthStartBody","AggAuthStartResult","AggClientSessionInput","AccountType","AccountProvider","TurnstileChallengeError","AggAuthSignInOptions","BrowserAuthLocation","domain","uri","AuthCallbackTokens","accessToken","refreshToken","tokenType","userId","AuthCodeExchangeResult","user","WalletAuthResult","WalletAuthClient","authStart","body","Promise","buildSiweMessage","params","address","chainId","issuedAt","nonce","statement","buildSiwsMessage","verify","args","message","signature","AuthCallbackClient","exchangeAuthCode","code","LinkConfirmCallbackClient","linkAccountConfirm","token","createPlaceholderUserProfile","input","id","username","avatarUrl","externalId","isLocationBlocked","venueAccounts","accounts","wallets","createWalletSessionUser","type","siwe","provider","wallet","providerAccountId","getBrowserAuthLocation","window","location","host","origin","resolveAuthCallbackUrl","callbackUrl","URL","href","parseAuthCallbackCode","resolvedUrl","searchParams","get","parseLinkConfirmToken","AUTH_METHOD_IDS","const","AggAuthMethodId","EXISTING_METHOD_NAMES","email","google","apple","AggIdentityExistsError","Error","constructor","existingMethod","attemptedMethod","name","IDENTITY_EXISTS_PARAMS","parseAuthCallbackIdentityExists","find","getAuthCallbackCleanupPath","URLSearchParams","search","delete","toString","pathname","exchangeAuthCallbackCode","client","cleanupPath","result","confirmLinkAccountCallback","parseAuthCallbackTokens","hash","startsWith","slice","undefined","createAuthCallbackSession","tokens","executeWalletAuthFlow","options","trim","chain","startResult","turnstileToken","siteKey","signMessage","TurnstileChallengeError","UserProfile","AggClient","QueryClient","QueryClientContext","useCallback","useContext","useEffect","useMemo","useState","ReactNode","fetchCurrentUserProfile","confirmLinkAccountCallback","createAuthCallbackSession","exchangeAuthCallbackCode","executeWalletAuthFlow","getAuthCallbackCleanupPath","parseAuthCallbackIdentityExists","parseAuthCallbackTokens","AggAuthContext","AggClientContext","AggAuthContextValue","AggAuthSignInOptions","AuthSnapshot","isAuthenticated","user","getClientAuthSnapshot","client","AggAuthProviderProps","children","toError","value","Error","String","replaceAuthCallbackUrl","cleanupPath","window","history","replaceState","AggAuthProvider","React","JSX","Element","queryClientFromContext","fallbackQueryClient","queryClient","snapshot","setIsAuthenticated","setUser","isLoading","setIsLoading","error","setError","isWeb3User","accounts","Array","isArray","some","account","provider","toLowerCase","refreshCurrentUser","targetClient","Promise","fullUser","state","catch","clearAccessToken","authStatus","refreshAccessToken","then","onAuthStateChange","authenticated","signIn","options","missingClientError","address","trim","missingAddressError","result","setSession","signInError","resolvedError","startAuth","authStart","startAuthError","session","resolvedUser","sessionError","undefined","handleAuthCallback","callbackUrl","identityError","exchangedSession","confirmedLink","tokens","callbackError","signOut","clearError","QueryClient","useContext","AppTradingMode","useAggUiConfig","AggExecutionModeContext","UseResolvedExecutionModeResult","executionMode","isPaperMode","isResolving","useResolvedExecutionMode","override","serverConfig","tradingMode","isLoading","trading","configuredExecutionMode","localMode","undefined","UnifiedBalanceResponse","Venue","useQuery","useCallback","useContext","useMemo","ReactNode","balanceQueryKeys","useResolvedExecutionMode","resolveAggUiLabels","AggAuthContext","AggBalanceContext","AggClientContext","AggBalanceBreakdownItem","AggBalanceContextValue","CHAIN_LABELS","Record","chainLabelFromId","chainId","toTokenUnits","raw","decimals","numeric","Number","isFinite","isUsdBasedToken","tokenSymbol","toUpperCase","includes","EMPTY_MANAGED_BALANCES","cash","positions","AggBalanceProviderProps","children","AggBalanceProvider","React","JSX","Element","client","authContext","executionMode","Error","isAuthenticated","queryExecutionMode","undefined","balancesQuery","queryKey","provider","queryFn","Promise","getManagedBalances","mode","enabled","Boolean","staleTime","refetchInterval","refetchIntervalInBackground","refetchOnWindowFocus","refetchOnReconnect","managedBalancesData","data","managedBalances","connectedVenues","Array","from","Set","map","position","venue","sort","a","b","localeCompare","balancesError","error","isBalancesLoading","isLoading","refetchBalances","refetch","totalBalance","reduce","sum","token","tokenAcrossChains","chains","chainSum","chain","balanceRaw","availableBalance","availableRaw","reservedBalance","reservedRaw","heldRaw","buildBalanceBreakdown","rawForChain","bySource","Map","chainVenues","filter","native","custodyKind","key","JSON","stringify","venueAccountId","externalAccountId","String","current","get","label","venues","userProfile","balance","venueAccount","accountCount","length","isFresh","set","values","balanceBreakdown","availableBalanceBreakdown","positionsBalanceTotal","actualPositionsBalance","kalshiVenueCash","venueCash","find","item","venueCashBalances","Object","fromEntries","balanceCents","kalshiBalance","kalshiPortfolioValue","portfolioValueCents","betdexCash","accountModel","hostedUsd","test","value","betdexBalance","betdexAvailableBalance","refetchConnectionStatus","getCurrentUser","dataUpdatedAt","AggClient","ReactNode","AggClientContext","AggClientProviderProps","client","children","AggClientProvider","t0","$","_c","t1","t2","_c","AppClientConfigResponse","useQuery","useQueryClient","useAggClient","useOptionalAggClient","FIVE_MINUTES","NO_APP_SCOPE","appConfigQueryKey","appId","const","UseAppConfigResult","prophetxExecutionMode","novigExecutionMode","disabledVenues","disabledCategoryPresets","earlyAccessEnabled","authOptions","tradingMode","paperStartingBalance","isLoading","error","useAppConfig","client","query","queryKey","queryFn","getAppConfig","staleTime","refetchInterval","toAppConfigResult","data","useCachedAppConfig","queryClient","enabled","initialData","getQueryData","undefined","useQueryClient","useMemo","ReactNode","useAppConfig","AggExecutionModeContext","AggExecutionModeProvider","children","React","JSX","Element","tradingMode","paperStartingBalance","isLoading","value","createContext","useCallback","useContext","useRef","ReactNode","STALENESS_THRESHOLD_MS","MAX_INITIAL_PAGES","EventListStateSnapshot","categoryTab","venueTab","scrollY","loadedPageCount","capturedAt","EventListStateContextValue","capture","state","Omit","consume","EventListStateContext","EventListStateProvider","children","React","JSX","Element","snapshotRef","current","Math","min","Date","now","snapshot","age","value","stableValue","args","useEventListState","context","Error","ChartTimeRange","DEFAULT_AGG_ROOT_CLASS_NAME","CHART_TIME_RANGES","AggUiGeneralConfig","AggUiPersistedConfig","ChartTimeRange","ThemeMode","CHART_TIME_RANGES","STORAGE_KEY","isBrowser","window","normalizeTheme","value","undefined","normalizeChartTimeRange","includes","loadPersistedConfig","raw","localStorage","getItem","parsed","JSON","parse","locale","general","theme","selectedChartTimeRange","chart","result","PersistConfigPayload","persistConfig","config","payload","setItem","stringify","STORAGE_KEY","isBrowser","ThemeMode","applyThemeToDocument","theme","document","isDark","documentElement","dataset","aggTheme","classList","toggle","aggRoots","querySelectorAll","HTMLElement","forEach","rootElement","MarketStatus","VenueEventWithMarkets","VenueMarket","VenueMarketOutcome","createContext","useCallback","useContext","useMemo","useReducer","useRef","TradingStateKind","TradingStateBase","kind","status","isOpen","isTradingDisabled","startsAt","endsAt","resolvesAt","winningOutcome","MarketTradingState","market","EventTradingState","displayMarkets","tradableMarkets","marketStates","Array","state","primaryMarket","OrderEligibilityReason","OrderEligibility","canPlaceOrder","reason","OPEN_TRADING_STATE","open","resolveTradingStateKind","Exclude","resolved","paused","unopened","resolveMarketWinningOutcome","localWinningOutcome","venueMarketOutcomes","find","outcome","winner","matchedVenueMarkets","length","matchedRefs","matchedVenueMarketOutcomes","ref","matchedMarket","item","id","venueMarketId","matchedOutcome","venueMarketOutcomeId","AFFIRMATIVE_WINNER_LABELS","Set","isAffirmativeWinnerLabel","label","has","trim","toLowerCase","resolvePreferredWinningMarket","marketWithAffirmativeWinner","resolveMarketTradingState","startDate","endDate","resolutionDate","deriveEventTradingStateKind","some","marketState","every","resolveEventStateStatus","event","closed","resolveEventWinningOutcome","preferredMarket","resolveEventTradingState","venueMarkets","map","derivedKind","explicitKind","preferredWinningMarket","filter","toEventReason","mapped","Record","unavailable","toMarketReason","resolveOrderEligibility","params","eventTradingState","eventState","resolveDefaultMarket","tradableMarket","resolveDefaultTradingMarket","resolveDefaultOutcome","yesOutcome","o","findMarketById","marketId","m","findOutcomeById","outcomeId","findOutcomeAcrossMarkets","TradeSide","Buy","Sell","const","TradingState","tradeSide","TradingAction","type","tradingReducer","action","previousMarketId","previousOutcomeId","syncedMarket","syncedOutcome","outcomeInCurrentMarket","found","targetMarketState","_exhaustive","logAction","actionType","payload","prev","next","enableLogs","console","group","log","eventId","marketIds","outcomeIds","flatMap","selectedMarketId","selectedOutcomeId","groupEnd","EventTradingContextValue","selectedEvent","selectedMarket","selectedOutcome","selectedEventId","selectedVenue","setTradeSide","initializeFromEvent","syncEvent","selectMarket","selectOutcome","selectMarketAndOutcome","initialState","EventTradingContext","undefined","useEventTradingContext","EventTradingProviderProps","children","React","ReactNode","EventTradingProvider","JSX","Element","rawDispatch","stateRef","pendingAtomicSelectionRef","current","pendingAtomicSelection","dispatch","value","venue","MarketStatus","_exhaustive","useCallback","useEffect","useMemo","useState","DEFAULT_AGG_ROOT_CLASS_NAME","loadPersistedConfig","persistConfig","applyThemeToDocument","AggUiConfig","ChartTimeRange","SdkUiProviderProps","VenueEventWithMarkets","mergeAggUiConfig","AggLabelsContext","AggUiContext","EventTradingProvider","hasWarnedMissingAggStyles","warnIfAggStylesAreMissing","window","document","rootElement","querySelector","HTMLElement","computedStyle","getComputedStyle","hasSemanticColorToken","getPropertyValue","trim","length","hasTailwindColorToken","hasTailwindRadiusToken","console","warn","logConfig","config","enableLogs","group","log","groupEnd","SearchSelectState","Pick","value","getSearchStateAfterSelect","selectedEvent","result","isShowingAllResults","AggUiProvider","children","React","JSX","Element","persisted","mergedConfig","selectedChartTimeRange","setSelectedChartTimeRange","chart","handleSetSelectedChartTimeRange","range","searchValue","setSearchValue","search","searchResult","setSearchResult","setIsShowingAllResults","handleSearchChange","onChange","handleSearchSelect","nextSearchState","onSelect","handleOpenResults","openResults","handleCloseResults","closeResults","resolvedConfig","locale","general","theme","resolvedRootClassName","rootClassName","filter","Boolean","join","labels","features","enableAnimations","enableGradients","useQueryClient","AggAuthProvider","AggBalanceProvider","AggClientProvider","AggExecutionModeProvider","EventListStateProvider","AggWebSocketProvider","AggProviderProps","AggUiProvider","hasWarnedMissingQueryClient","useQueryClientCheck","console","error","AggProvider","client","config","children","React","JSX","Element","Error","useMutation","useQueryClient","ExecuteManagedParams","ExecuteManagedResponse","SmartRouteResponse","useAggClient","executionKeys","invalidateBalanceQueries","UseExecuteManagedOptions","onSuccess","data","onError","error","Error","useExecuteManaged","options","client","queryClient","mutationFn","params","executeManaged","setQueriesData","queryKey","route","consumedPrimary","quoteId","consumedComparison","venueSoloQuotes","some","quote","map","invalidateQueries","ordersPrefix","positionsPrefix","useQueryClient","useMutation","useQueryClient","PlaceLimitOrderParams","PlaceLimitOrderResponse","useAggClient","invalidateBalanceQueries","executionKeys","UsePlaceLimitOrderOptions","onSuccess","data","onError","error","Error","usePlaceLimitOrder","options","client","queryClient","mutationFn","params","placeLimitOrder","invalidateQueries","queryKey","ordersPrefix","positionsPrefix","useQueryClient","useMutation","useQueryClient","CancelManagedExecutionResponse","useAggClient","invalidateBalanceQueries","invalidatePositionQueries","invalidateUserActivityQueries","executionKeys","UseCancelManagedOrderOptions","onSuccess","data","orderId","onError","error","Error","useCancelManagedOrder","options","client","queryClient","mutationFn","cancelManagedOrder","invalidateQueries","queryKey","ordersPrefix","useQueryClient","useQuery","GetPositionsParams","useAggClient","executionKeys","UsePositionsOptions","enabled","usePositions","options","client","cursor","limit","status","mode","query","queryKey","positions","queryFn","getPositions","staleTime","gcTime","retry","data","nextCursor","hasMore","useCallback","useEffect","useRef","useState","ExecutionStatusOrder","ExecutionStatusResponse","ExecutionStatusStep","WsBalanceUpdate","WsOrderEvent","WsOrderSubmitted","useAggClient","useOnBalanceUpdate","useOnOrderEvent","useOnOrderSubmitted","TERMINAL_ORDER_STATUSES","Set","ORDER_POLL_INTERVAL_MS","mapOrderStatusToTerminalEvent","status","ExecutionTerminalOrderEvent","mergeTerminalOrderEvents","currentEvents","incomingEvents","mergedByOrderId","Map","map","event","orderId","incomingEvent","currentEvent","get","set","timestamp","values","sort","left","right","ExecutionProgressPhase","DagStepProgress","dagRunId","totalSteps","currentSequence","currentStepType","completedSequences","stepTypes","Record","errorReason","venue","filledAmountRaw","remainingAmountRaw","actualSharesRaw","actualToWinRaw","quotedSharesRaw","quotedToWinRaw","executionPriceRaw","quotedPriceRaw","ExecutionStepProgress","ExecutionRawStepProgress","Pick","EXECUTION_STEP_STATUS_RANK","pending","in_progress","failed","completed","skipped","getExecutionStepIdentity","step","groupId","sequence","stepType","orderIds","join","getExecutionGroupAttempt","steps","reduce","highestAttempt","Math","max","attempt","groupExecutionStepsByGroupId","groupedSteps","existingSteps","push","pickExecutionGroupPresentation","groupStatus","label","bridge","mergeExecutionStepProgress","previous","incoming","previousByGroupId","incomingByGroupId","mergedByIdentity","identity","current","groupPresentation","groupIds","keys","previousGroup","incomingGroup","previousStep","incomingStep","isNewerAttempt","shouldUseIncoming","Array","from","localeCompare","mergeRawExecutionStepProgress","mergedBySequence","mergeExecutionStatusOrders","order","Date","updatedAt","getTime","UseExecutionProgressOptions","quoteId","enabled","mode","UseExecutionProgressResult","phase","submittedOrders","latestBalance","dagProgress","terminalOrderEvents","executionSteps","rawExecutionSteps","executionOrders","useExecutionProgress","setPhase","setSubmittedOrders","setLatestBalance","setDagProgress","setTerminalOrderEvents","setExecutionSteps","setRawExecutionSteps","setExecutionOrders","orderIdSetRef","submittedOrderVenueByIdRef","length","handleOrderSubmitted","msg","has","trimmedVenue","trim","prev","handleBalanceUpdate","handleOrderEvent","mappedEvent","resolvedVenue","fallbackErrorReason","undefined","nextTerminalEvent","initialStepTypes","seq","type","Object","entries","Number","startedAt","completedAt","find","toISOString","buildFailedProgress","baseStepTypes","isStatusPolling","isListening","client","terminalOrderIdsRef","pollInFlightRef","buildSubmittedOrdersFromStatus","orders","side","price","size","buildTerminalEventsFromStatus","fallbackOrderIds","fallbackTimestamp","terminalEvents","partialFillReason","filter","terminal","coveredOrderIds","fallbackEvent","overallState","includes","setFatalPollingFailure","message","failedOrderIds","existingByOrderId","now","e","cancelled","timeout","ReturnType","setTimeout","stopPolling","clearTimeout","scheduleNextPoll","delayMs","pollExecutionStatus","Promise","getExecutionStatus","resolvedOrderIds","fromEntries","executionId","nextTerminalEvents","pollAfterMs","error","statusCode","Error","interval","setInterval","clearInterval","reconcile","id","all","res","getExecutionOrders","limit","data","mapped","executionPrice","errorMessage","covered","every","useMutation","useQuery","useQueryClient","CreateBalanceRefillPolicyParams","UpdateBalanceRefillPolicyParams","useAggClient","executionKeys","UseBalanceRefillPoliciesOptions","enabled","useBalanceRefillPolicies","options","client","queryClient","queryKey","balanceRefillPolicies","query","queryFn","getBalanceRefillPolicies","staleTime","refetchInterval","state","data","some","policy","includes","latestAttempt","status","createPolicy","mutationFn","params","createBalanceRefillPolicy","onSuccess","setQueryData","updatePolicy","policyId","updateBalanceRefillPolicy","updated","current","map","id","policies","useQueryClient","PositionGroup","ClosedPositionTotals","totalTraded","amountWon","returnPct","winningOutcomeIds","isPartialWin","computeClosedPositionTotals","group","outcomes","venueMarket","venueMarketOutcomes","isResolved","status","Set","winningCount","settledCount","outcome","avgEntryPrice","totalSize","winner","totalValue","breakdown","venueBreakdown","venueMarketOutcomeId","add","Array","from","useMutation","useQueryClient","RedeemRequest","RedeemResponse","useAggClient","useResolvedExecutionMode","invalidateUserClaimState","RedeemRejectedError","Error","response","constructor","message","name","isLegRejected","status","useRedeem","client","queryClient","executionMode","mutationFn","body","redeem","mode","results","length","every","r","reasons","map","reason","filter","Boolean","join","onSettled","useQueryClient","WsRedeemEvent","useOnRedeemEvent","useOnRedeemEventBase","RedeemEvent","listener","event","useQuery","AggClient","useAggAuthState","useAggClient","executionKeys","CLAIMABLE_COUNT_PAGE_LIMIT","getClaimablePositionsCount","client","Promise","total","cursor","page","getExecutionPositions","status","limit","group","data","redeemStatus","hasMore","nextCursor","undefined","useRedeemEligibleCount","isAuthenticated","query","queryKey","claimablePositionsCount","queryFn","enabled","staleTime","refetchInterval","useEffect","useMemo","useState","WsRedeemEvent","useOnRedeemEvent","RedeemLegLifecycle","status","txHash","errorMessage","RedeemLifecycleState","pending","terminal","allConfirmed","anyFailed","legs","Record","UseRedeemLifecycleInput","redeemId","expectedOutcomeIds","preFailedOutcomeIds","preFailedReasons","preConfirmedOutcomeIds","preConfirmedTxHashes","computeDerivedState","expectedCount","legCount","Object","keys","length","allTerminal","leg","values","seedState","input","id","derived","useRedeemLifecycles","inputs","inputsByRedeemId","map","stateMap","setStateMap","next","entries","prev","changed","existing","event","nextLegs","venueMarketOutcomeId","nextState","useMemo","useRedeemLifecycles","RedeemLifecycleState","UseRedeemLifecycleInput","INITIAL_STATE","pending","terminal","allConfirmed","anyFailed","errorMessage","legs","useRedeemLifecycle","input","inputs","map","redeemId","useContext","AggAuthContext","GeoBlockState","isLocationBlocked","isTradingBlocked","isDepositBlocked","DEFAULT_STATE","useGeoBlock","authContext","process","env","NEXT_PUBLIC_GEO_BLOCK_DISABLE","isBlocked","user","VenueAvailabilityState","normalizeVenueId","venueId","trim","toLowerCase","getDisabledVenueSet","disabledVenues","Set","map","isVenueDisabledByConfig","has","getVisibleVenuesByConfig","id","venues","TVenue","disabledVenueSet","filter","venue","getVisibleVenueIdsByConfig","venueIds","TVenueId","getVenueAvailabilityState","isConfigLoading","isLocationBlocked","Venue","VenueKeyStatus","useQuery","useAggClient","venueKeyQueryKeys","all","const","status","venue","useVenueKeyStatus","enabled","client","queryKey","queryFn","getVenueKeyStatus","useEffect","useRef","useMutation","useQuery","useQueryClient","useAggAuthContext","useAggClient","useResolvedExecutionMode","invalidateBalanceQueries","hostedVenueAccountQueryKeys","all","const","account","venue","userId","mode","useHostedVenueAccount","enabled","client","user","isAuthenticated","executionMode","isResolving","queryClient","id","permitted","queryKey","session","current","assertSession","Error","queryFn","getHostedVenueAccount","staleTime","refetchInterval","refetchIntervalInBackground","retry","provision","mutationFn","request","run","ReturnType","provisionHostedVenueAccount","onSuccess","result","setQueryData","reset","mutate","mutateAsync","isAvailable","useQueryClient","useEffect","useRef","useQuery","useAggAuthContext","useAggClient","useResolvedExecutionMode","hostedVenueAccountQueryKeys","useHostedVenueActivity","venue","page","enabled","client","user","isAuthenticated","executionMode","isResolving","userId","id","permitted","Number","isInteger","session","current","mounted","assertSession","Error","activity","queryKey","all","queryFn","result","getHostedVenueActivity","mode","staleTime","retry","isAvailable","useCallback","useQuery","useAggAuthContext","useAggClient","sharedKycQueryKeys","status","userId","const","useSharedKyc","client","isAuthenticated","user","id","query","queryKey","queryFn","getSharedKycStatus","enabled","staleTime","retry","refetch","refreshStatus","Promise","result","cancelRefetch","error","data","verified","initiateVerification","venue","redirectUri","initiateKyc","isPending","useCallback","UserProfile","useAggAuthContext","UseAggAuthOptions","signMessage","message","Promise","address","chainId","chain","UseAggAuthReturn","isAuthenticated","user","signIn","statement","signOut","isLoading","error","Error","useAggAuth","options","signInWithProvider","useCallback","useState","AggLinkAccountBody","AggLinkAccountConfirmResult","AggLinkAccountResult","AggLinkAccountWalletConfirmBody","useAggClient","UseLinkAccountReturn","startLink","body","Promise","confirmLink","input","isLoading","error","Error","useLinkAccount","client","setIsLoading","setError","run","fn","T","catch","e","err","String","finally","linkAccount","linkAccountConfirm","AUTH_CHOOSER_OPEN_EVENT","AggAuthChooserOpenDetail","highlightMethod","requestAggAuthChooserOpen","detail","window","dispatchEvent","CustomEvent","useInfiniteQuery","useQueries","Category","useAggClient","UseCategoriesOptions","queryKeyScope","parentId","enabled","limit","UseCategoryChildrenOptions","parentIds","useCategories","options","client","query","queryKey","queryFn","pageParam","res","getCategories","cursor","initialPageParam","undefined","getNextPageParam","lastPage","nextCursor","categories","data","pages","flatMap","p","hasNextPage","useCategoryChildren","Array","from","Set","filter","Boolean","queries","map","childrenByParentId","Map","forEach","index","set","isLoading","some","useEffect","useState","useDebouncedValue","value","T","delay","debouncedValue","setDebouncedValue","timeoutId","window","setTimeout","clearTimeout","useInfiniteQuery","GetOrdersQuery","OrderListItem","useAggClient","ExecutionOrderStatusInput","NonNullable","UseExecutionOrdersOptions","Omit","status","enabled","mode","refetchIntervalMs","useExecutionOrders","options","client","orderType","orderId","quoteId","venueMarketIds","limit","venueMarketIdsKey","length","Set","sort","query","queryKey","queryFn","pageParam","getExecutionOrders","cursor","initialPageParam","undefined","getNextPageParam","lastPage","hasMore","nextCursor","refetchInterval","orders","data","pages","flatMap","page","hasNextPage","useQueries","UseQueryResult","GetOrdersQuery","OrderListItem","useMemo","useAggClient","MAX_ORDER_VENUE_MARKET_IDS_PER_REQUEST","DEFAULT_PAGE_LIMIT","DEFAULT_MAX_PAGES_PER_BATCH","UseExecutionOrdersForMarketsOptions","venueMarketIds","ReadonlyArray","status","NonNullable","orderType","mode","limit","maxPagesPerBatch","enabled","UseExecutionOrdersForMarketsResult","orders","isLoading","error","Error","isTruncated","BatchResult","hasMore","combineBatches","results","flatMap","result","data","some","find","chunk","items","T","size","chunks","index","length","push","slice","useExecutionOrdersForMarkets","client","batchKey","Set","sort","join","batches","split","combine","queries","map","batchVenueMarketIds","queryKey","queryFn","Promise","cursor","page","response","getExecutionOrders","nextCursor","undefined","keepPreviousData","useInfiniteQuery","PaginatedResponse","UserActivityItem","UserActivityQuery","UserActivityType","useAggClient","userActivityQueryKeys","UseUserActivityOptions","Omit","enabled","pendingRefetchIntervalMs","DEFAULT_PENDING_REFETCH_INTERVAL_MS","PENDING_ACTIVITY_STATUSES","Set","hasPendingActivity","pages","ReadonlyArray","page","item","data","type","legs","length","every","leg","status","toLowerCase","has","useUserActivity","options","client","limit","query","queryKey","feed","queryFn","pageParam","getUserActivity","cursor","initialPageParam","undefined","getNextPageParam","lastPage","hasMore","nextCursor","placeholderData","refetchInterval","q","state","activities","flatMap","hasNextPage","keepPreviousData","useInfiniteQuery","LeaderboardMetric","LeaderboardRow","PaginatedResponse","useAggClient","LeaderboardPeriod","LEADERBOARD_PERIODS","UseLeaderboardOptions","period","metric","limit","enabled","utcDayKey","d","Date","toISOString","slice","leaderboardRange","now","from","to","spanDays","UTC","getUTCFullYear","getUTCMonth","getUTCDate","leaderboardQueryKeys","all","const","list","LEADERBOARD_STALE_TIME_MS","useLeaderboard","options","client","query","queryKey","queryFn","pageParam","getLeaderboard","cursor","initialPageParam","undefined","getNextPageParam","lastPage","hasMore","nextCursor","placeholderData","staleTime","seen","Set","rows","data","pages","flatMap","page","filter","row","has","userId","add","hasNextPage","UserProfile","useCallback","useState","useAggClient","UseExternalIdOptions","onSuccess","profile","onError","error","Error","UseExternalIdReturn","linkExternalId","assertion","externalId","timestamp","hmac","Promise","isLoading","useExternalId","options","client","onErrorCb","setIsLoading","setError","err","resolvedError","String","useInfiniteQuery","GetPositionsQuery","PositionGroup","useAggClient","executionKeys","UseExecutionPositionsOptions","Omit","enabled","mode","useExecutionPositions","options","client","limit","status","query","queryKey","positions","queryFn","pageParam","getExecutionPositions","cursor","initialPageParam","undefined","getNextPageParam","lastPage","hasMore","nextCursor","data","pages","flatMap","page","hasNextPage","isAggApiError","isServer","QueryObserverOptions","ReadRetryOptions","Pick","MAX_TIMER_DELAY_MS","hint","error","Error","undefined","value","retryAfterMs","Number","isSafeInteger","withReadRetry","options","retry","failureCount","retryDelay","attempt","Math","min","MAX_TIMER_DELAY_MS","ChartBarsMeta","ChartBarsResponse","WsCandleInterval","WsTrade","MarketChartCandle","time","open","high","low","close","mean","volume","source","MarketChartVenueData","venue","outcomeIds","candles","liveCandle","lineValue","lastTrade","lastUpdateTs","MarketChartData","delivery","marketId","primaryVenue","interval","startTs","endTs","venues","Record","MAX_CACHE_RETENTION_SECONDS","getIntervalSeconds","createVenueData","undefined","pruneCandlesBefore","cutoffTs","firstKeptIndex","length","slice","promoteClosedLiveCandle","expectedCandleTime","promoted","some","candle","sortCandles","resolveMaxLastUpdateTs","max","venueData","Object","values","sort","left","right","_upsertFinalCandle","nextCandle","index","findIndex","nextCandles","createMarketChartData","params","response","data","map","Math","floor","t","o","h","l","c","Number","isFinite","v","const","lastCandle","venueMarketOutcomeId","meta","mergeMarketChartData","datasets","Array","from","Set","flatMap","dataset","reduce","acc","entries","existingVenueData","find","MarketChartMidpointUpdate","outcomeId","midpoint","timestamp","applyMidpointToMarketChart","update","targetVenueEntry","includes","targetVenueName","currentVenue","intervalSeconds","promotedCandles","min","nextVenues","applyTradeToMarketChart","trade","price","size","loadImmutableHistory","isAggApiError","AggClient","AggWebSocket","ChartBarsResponse","ChartHistoryManifest","ChartCandle","ChartDeliveryError","Error","constructor","state","NonNullable","retryAfterMs","name","usable","response","data","length","meta","withActualFreshness","serverTime","Number","isFinite","Date","now","lastBarOpenTime","at","t","staleSeconds","Math","max","fetchChartHistory","client","socket","request","Parameters","signal","AbortSignal","onInitial","Promise","readBars","params","getChartBars","decode","text","decodeHistory","throwIfAborted","venueMarketOutcomeId","preferImmutableHistory","verified","manifest","history","getChartHistoryManifest","complete","loadHistory","filter","bar","from","to","error","aborted","status","fullyCovered","finalizedThrough","initial","venue","resolution","tail","countBack","undefined","incomplete","includes","isAggApiError","MarketChartData","ChartDeliveryError","MAX_TIMER_DELAY_MS","notBefore","WeakMap","validDelay","value","Number","isSafeInteger","record","query","delay","set","Math","min","MAX_SAFE_INTEGER","Date","now","delete","chartRetryRemaining","max","get","chartRefetchInterval","interval","remaining","waitForDeadline","signal","AbortSignal","Promise","throwIfAborted","resolve","reject","aborted","clearTimeout","timer","removeEventListener","reason","setTimeout","addEventListener","once","runChartQuery","load","T","data","delivery","complete","includes","state","retryAfterMs","undefined","error","Candle","LiveSnapshot","MarketChartCandle","MarketChartData","closedCaches","WeakMap","key","candles","toChart","candle","time","openTime","open","o","high","h","low","l","close","c","volume","v","source","overlayCandleTail","history","live","rolling","tail","interval","venue","venues","primaryVenue","endTs","Date","now","last","at","Infinity","closed","filter","map","join","cached","get","length","set","forming","lastSourceTime","Math","max","orderbook","timestamp","trades","lastUpdateTs","Number","isFinite","liveCandle","lineValue","lastTrade","useEffect","useMemo","useAggWebSocket","UseMarketDataSubscriptionOptions","marketId","additionalMarketIds","enabled","orderbook","trades","useMarketDataSubscription","ws","allIds","ids","Set","add","id","stableKey","join","length","unsubscribers","Array","unsub","subscribe","push","ChartBarsMeta","WsCandleInterval","keepPreviousData","useQueries","useQueryClient","withReadRetry","useAggClient","useAggUiConfig","useAggWebSocket","useAggWebSocketConnectionState","createMarketChartData","mergeMarketChartData","MarketChartData","marketDataKeys","runChartQuery","chartRefetchInterval","ChartDeliveryError","fetchChartHistory","useLiveStates","overlayCandleTail","useMarketDataSubscription","UseMarketChartOptions","marketId","venueMarketIds","visibleVenue","liveOutcomeIds","interval","startTs","endTs","countBack","enabled","live","refetchIntervalMs","staleTimeMs","rangeKey","MarketChartAvailability","Partial","state","NonNullable","complete","UseMarketChartResult","availability","Record","data","isLoading","error","Error","isLive","refetch","Promise","useMarketChartQueries","options","client","queryClient","socket","isConnected","features","enableLiveUpdates","resolvedRangeKey","liveEnabled","outcomeIds","ids","Set","add","venueMarketId","sort","primaryOutcomeId","find","Boolean","isQueryEnabled","length","subscribedIds","filter","id","includes","subscribedPrimaryId","additionalMarketIds","orderbook","trades","queries","map","outcomeId","queryKey","chart","queryFn","signal","AbortSignal","owner","getQueryCache","exact","response","venueMarketOutcomeId","resolution","from","undefined","to","initial","aborted","setQueryData","meta","chartWindow","chartEndTs","staleTime","query","gcTime","refetchOnWindowFocus","retry","failureCount","retryDelay","_attempt","retryAfterMs","Math","min","max","placeholderData","refetchInterval","refetchIntervalInBackground","liveStates","overlaid","index","forEach","sameOutcome","metadata","delivery","pending","isPlaceholderData","isFetching","Object","values","venues","some","venue","candles","liveCandle","UseMarketChartsResult","charts","errors","useMarketCharts","String","all","useMarketChart","successfulDatasets","flatMap","datasets","hasPendingQuery","firstError","isInRange","candle","time","hasVisibleHistory","entries","venueName","useQueryClient","useEffect","useMemo","useReducer","useRef","CandleBuilder","useAggWebSocket","getOrCreateBuilder","useLiveMarketStores","venueMarketIds","ws","forceRender","c","subsRef","Map","unsub","unlisten","stableKey","slice","sort","join","length","current","desired","Set","id","sub","has","delete","builder","subscribe","onChange","set","clear","map","useMemo","Candle","CandleInterval","mergeCandles","mergeClosedCandles","VenueMarket","useMarketChart","useLiveMarketStores","LiveCandle","time","o","h","l","c","v","venue","source","UseLiveCandlesOptions","market","interval","mode","startTs","endTs","UseLiveCandlesResult","candles","liveCandle","isLoading","candleToLive","openTime","useLiveCandles","options","venueMarketIds","id","ids","matchedVenueMarkets","m","push","builders","restMarketId","marketId","data","chartData","enabled","liveData","length","closed","forming","getClosed","getForming","map","b","byTime","Map","venueEntries","Object","values","venues","venueData","set","open","high","low","close","volume","merged","Array","from","sort","a","useCallback","useMemo","CandleInterval","VenueMarket","useLiveCandles","LiveCandle","ScaledCandlePoint","time","open","high","low","close","v","UseLiveCandleOverlayOptions","market","interval","mode","startTs","endTs","enabled","scale","UseLiveCandleOverlayResult","liveCandle","scaledCandles","lineValue","live","isLoading","timeRangeToInterval","range","useLiveCandleOverlay","options","candles","rawCandles","rawLive","scaleCandle","candle","o","h","l","c","map","length","useEffect","useMemo","VenueMarket","useAggUiConfig","useAggWebSocket","extractSelectedOutcomeIds","selectedMarket","ids","Set","outcome","venueMarketOutcomes","id","add","matched","matchedVenueMarkets","sort","useEventOrderbookData","venueMarkets","selectedMarketId","ws","features","enableLiveUpdates","length","find","m","selectedOutcomeIds","selectedKey","join","unsubscribers","map","subscribe","unsub","OrderbookLevel","OrderbookState","OutcomeOrderbookResponse","VenueOrderbookLevel","orderbookTimestampSeconds","timestamp","outcomeOrderbookToState","response","marketId","venue","orderbook","midpoint","spread","seq","checksum","venueMarketOutcomeId","attribute","l","price","size","venues","venueLevels","outcomeId","bids","map","asks","venueOrderbooks","bestBid","bestAsk","Orderbook","AggregatedOrderbookResponse","OrderbookState","MarketOrderbookIntegrity","MarketOrderbookData","marketId","orderbook","venueOrderbooks","venues","midpoint","spread","timestamp","snapshotVersion","seq","checksum","matchedMarkets","integrity","truncateLevels","price","size","levels","T","depth","slice","Math","max","truncateVenueOrderbooks","Object","fromEntries","entries","map","venue","book","bids","asks","createMarketOrderbookDataFromResponse","response","venueMarketId","undefined","aggregateVenueLevels","side","levelsByPrice","Map","Record","level","currentLevel","get","set","values","sort","left","right","createMarketOrderbookDataFromVenueOrderbooks","floor","Date","now","bestBid","bestAsk","createMarketOrderbookDataFromState","state","options","marketOrderbookDataToResponse","data","marketOrderbookDataToState","withOrderbookIntegrity","applyOrderbookDepth","computeChecksum","AggClient","OutcomeOrderbookResponse","MarketLiveStore","outcomeOrderbookToState","SOCKET_GRACE_MS","REST_BUDGET_MS","MAX_SEED_AGE_MS","hasFreshSnapshot","store","id","now","Date","state","get","orderbook","integrity","timestamp","createOrderbookSnapshotQuery","client","Pick","ids","socketHealthy","context","signal","AbortSignal","Promise","Record","fetchSnapshotQuery","bind","selectOrderbookSnapshots","length","Error","missing","filter","aborted","resolve","unsubscribe","finish","clearTimeout","timer","removeEventListener","setTimeout","subscribe","addEventListener","once","requested","initialStates","Map","map","controller","AbortController","abort","response","getOutcomeOrderbooks","venueMarketOutcomeIds","Object","fromEntries","data","flatMap","book","index","venueMarketOutcomeId","Number","isFinite","isSafeInteger","seq","isInteger","checksum","snapshot","bids","asks","every","level","price","size","projectedChecksum","snapshotChecksum","current","live","initial","initialBook","orderbookSnapshotVersion","sameGeneration","isConnected","orderbookGeneration","connectionGeneration","update","previous","orderbookError","error","useQuery","useQueryClient","VenueMarket","useAggWebSocket","useAggWebSocketConnectionState","useAggClient","useAggUiConfig","outcomeOrderbookToState","applyOrderbookDepth","createMarketOrderbookDataFromState","MarketOrderbookData","getMarketLiveStore","useLiveStates","createOrderbookSnapshotQuery","useMarketDataSubscription","createMarketLiveState","UseMarketOrderbookVenueOutcome","venue","venueMarketOutcomeId","UseMarketOrderbookOptions","marketId","depth","enabled","venueOutcomes","live","UseMarketOrderbookResult","data","dataById","Record","isLoading","error","Error","isLive","refetch","Promise","useMarketOrderbook","options","queryClient","client","ws","isConnected","features","enableLiveUpdates","selectedId","liveEnabled","outcomeIds","map","v","filter","Boolean","subscriptionIds","length","Set","selectedOutcomeId","additionalMarketIds","slice","orderbook","store","liveQueries","sortedIds","sort","preferSocket","every","id","get","connectionGeneration","seedQuery","queryKey","queryFn","staleTime","gcTime","refetchOnWindowFocus","retry","liveStates","subscriptionId","index","peek","seededOrderbooks","liveBook","seed","bids","asks","primaryOrderbook","primarySnapshotVersion","orderbookSnapshotVersion","snapshotVersion","Object","fromEntries","flatMap","hasAnyOrderbook","some","seedLoading","liveOrderbookErrorMessage","find","liveState","orderbookError","forEach","update","previous","resnapshot","useQueryClient","OrderbookState","WsTrade","useAggUiConfig","useAggWebSocketConnectionState","useLiveStates","useMarketOrderbook","UseLiveMarketResult","orderbook","trades","isConnected","integrity","outcomeOrderbookToState","useLiveMarket","canonicalMarketId","features","enableLiveUpdates","connected","snapshot","venueMarketOutcomeId","enabled","live","data","useMemo","useRef","VenueMarket","useLiveStates","useAggUiConfig","MarketLiveState","EMPTY_PRICES","Map","buildMidpointFingerprint","outcomeIds","queries","Array","data","parts","i","length","midpoint","orderbook","push","join","useLiveOutcomePrices","venueMarkets","features","enableLiveUpdates","ids","Set","vm","outcome","venueMarketOutcomes","id","add","ref","matchedVenueMarketOutcomes","venueMarketOutcomeId","sort","fingerprint","prevRef","prices","current","liveByOutcomeId","state","set","outcomeId","liveMidpoint","get","findLivePriceById","livePrices","findLivePriceForLabel","label","normalizedLabel","trim","toLowerCase","sum","count","price","undefined","useMemo","useRef","VenueMarket","useLiveStates","useAggUiConfig","MarketLiveState","LiveBestPrices","ReadonlyMap","bestBid","bestAsk","LiveBestPriceCandidate","bestBidVenue","bestAskVenue","midpoint","midpointVenue","updatedAt","LiveBestPriceCandidates","EMPTY","Map","EMPTY_CANDIDATES","extractOutcomeBestPrices","state","ob","orderbook","bids","price","asks","undefined","buildFingerprint","outcomeIds","queries","Array","data","parts","i","length","bid","ask","push","join","useLiveBestPrices","venueMarkets","features","enableLiveUpdates","ids","Set","vm","outcome","venueMarketOutcomes","id","add","ref","matchedVenueMarketOutcomes","venueMarketOutcomeId","sort","fingerprint","prevRef","result","current","perOutcome","best","set","size","refs","group","map","groupBestAsk","groupBestBid","entry","get","prev","nextBid","nextAsk","mergeBestPricesPreferringLive","rest","live","merged","liveEntry","pickSideVenue","venues","Record","level","side","bestVenue","bestValue","venue","info","Object","entries","value","wins","bestSize","Infinity","extractOutcomeBestCandidate","candidate","bidLevel","askLevel","midVenue","timestamp","buildLiveBestPriceCandidates","states","groupBestAskVenue","groupBestBidVenue","groupUpdatedAt","next","buildCandidateFingerprint","mid","ts","keys","useLiveBestPriceCandidates","_","WsTrade","useAggUiConfig","useLiveMarket","useMarketDataSubscription","useLiveTrades","canonicalMarketId","features","enableLiveUpdates","trades","marketId","enabled","Boolean","orderbook","MidpointItem","VenueMarket","useQuery","useMemo","useAggClient","useAggUiConfig","UseMidpointsOptions","maxMidpointIdsPerRequest","UseMidpointsResult","prices","Map","bestMidpointsByOutcomeId","currentMidpointsByOutcomeId","venueByOutcomeId","bestPrices","bestBid","bestAsk","bestPriceVenuesByOutcomeId","bestBidVenue","bestAskVenue","isLoading","bestMidpoint","bestMidpointVenue","normalizeVenueMarketIds","venueMarkets","ids","Set","market","id","add","sibling","matchedVenueMarkets","sort","left","right","localeCompare","EMPTY_MIDPOINTS_POLL_MS","EMPTY_MIDPOINTS_MAX_FETCHES","hasUsableMidpoint","item","midpoint","outcomes","some","outcome","isMidpointResponseComplete","data","primaryVenueMarketIds","itemByMarketId","map","venueMarketId","every","get","normalizeOutcomeLabel","label","trim","toLowerCase","normalizeSemanticOutcomeLabel","normalizedLabel","outcomeMatchesSemanticSide","title","leftCandidates","value","filter","Boolean","rightCandidates","candidate","includes","resolveBestMidpointCandidateOutcomeIds","length","candidateIds","venueMarketOutcomes","yesOutcome","find","push","firstOutcomeId","resolveSiblingOutcomeMidpoint","matched","ref","venueMarketOutcomeId","venue","m","sibOutcome","o","resolveSemanticFallbackMidpoint","marketById","best","siblingMarket","siblingOutcome","extractBestPrices","venuesByOutcome","setEntry","outcomeId","next","prev","merged","set","prevVenues","mergedVenues","has","refs","matchedVenueMarketOutcomes","group","entry","venues","useMidpoints","options","client","configuredMaxMidpointIdsPerRequest","bestMidpointCandidateOutcomeIds","queryKey","queryFn","getMidpoints","bestPrice","enabled","staleTime","query","state","Infinity","refetchInterval","dataUpdateCount","gcTime","refetchOnMount","refetchOnWindowFocus","refetchOnReconnect","result","currentMap","venueMap","bestVenue","sib","fallback","normalizeVenueMarketIds","WsCandleInterval","useEffect","useMemo","useState","ChartTimeRange","getIntervalSeconds","timeRangeToInterval","UseRollingChartWindowOptions","range","interval","tickMs","nowMs","RollingChartWindow","rangeSeconds","intervalSeconds","nowSec","endTs","startTs","refetchIntervalMs","RANGE_SECONDS_BY_RANGE","Record","ALL","rangeToSeconds","resolveRollingWindow","params","Math","ceil","useRollingChartWindow","options","optionsNowMs","Date","now","setNowSec","floor","handle","setInterval","clearInterval","useEffect","useRef","useState","WsArbFeedBatch","WsArbMarketUpdate","useAggWebSocket","UseMarketArbResult","arbReturn","isLive","UseArbFeedResult","byMarket","Map","byEvent","MarketArbState","ArbFeedState","arb","eventId","useMarketArb","marketId","ws","state","setState","cached","getArb","off","subscribeArb","msg","EMPTY_ARB_FEED","useArbFeed","stateRef","current","subscribeArbFeed","batch","prev","nextByMarket","entry","entries","set","venueEventId","nextByEvent","values","get","publicByMarket","Orderbook","VenueMarketOutcome","VenueMarket","AggClient","AggregatedOrderbookResponse","keepPreviousData","useQuery","useAggClient","marketOrderbookDataToResponse","useMarketOrderbook","OrderbookResult","market","outcome","orderbook","UseOrderBookOptions","orderbooks","enabled","canonicalMarketId","fetchBatchBookQuery","client","venueMarketIds","signal","AbortSignal","getOrderbooks","createBatchBookQuery","bind","useOrderBook","options","requestedVenueMarketIds","Set","map","id","canonicalResult","marketId","length","venueOutcomes","venue","venueMarketOutcomeId","undefined","batchedResult","queryKey","const","queryFn","staleTime","gcTime","refetchOnWindowFocus","retry","placeholderData","data","canonicalData","merged","flatMap","venueBook","venueOrderbooks","bids","asks","liveBooksByMarketId","Map","filter","item","status","venueMarketId","index","get","aggregated","error","isLoading","Error","String","results","isLive","OrderbookQuoteResponse","keepPreviousData","useQuery","useAggClient","createMarketOrderbookDataFromVenueOrderbooks","marketDataKeys","useDebouncedValue","UseOrderbookQuoteOptions","marketId","side","size","enabled","UseOrderbookQuoteResult","data","isLoading","isFetching","error","Error","QUOTE_DEBOUNCE_MS","createUnavailableOrderbookError","message","code","retryable","status","undefined","quoteVenueOrderbooks","requestedSize","venueOrderbooks","Record","bids","Array","price","asks","marketData","levels","orderbook","remaining","fillsByVenue","Map","cost","level","venue","venueSize","Object","entries","venues","fillSize","Math","min","fillCost","existing","get","set","filledSize","max","totalCost","values","reduce","sum","fill","avgPrice","slippage","midpoint","fills","map","useOrderbookQuote","options","client","debouncedSize","shouldFetch","query","queryKey","orderbookQuote","const","queryFn","response","getOrderbooks","venueMarketIds","item","find","entry","venueMarketId","fromEntries","staleTime","gcTime","retry","placeholderData","String","useQuery","OrderListQuery","TradeExecutorOrder","useAggClient","UseOrdersOptions","enabled","useOrders","options","client","userId","status","limit","offset","query","queryKey","queryFn","getOrders","orders","data","total","MarketStatus","VenueEvent","QueryClient","QueryClientContext","keepPreviousData","useInfiniteQuery","useContext","useEffect","useState","withReadRetry","AggClientContext","UseSearchOptions","q","type","categoryIds","status","limit","enabled","deep","mode","useSearch","options","client","queryClient","fallbackQueryClient","isEnabled","length","undefined","mount","unmount","Error","queryKey","join","effectiveQueryClient","retryOptions","defaultQueryOptions","query","queryFn","pageParam","signal","res","search","T","cursor","initialPageParam","getNextPageParam","lastPage","hasMore","nextCursor","placeholderData","data","pages","flatMap","page","isLoading","isError","error","hasNextPage","fetchNextPage","isFetchingNextPage","isPlaceholderData","QueryClient","MarketStatus","VenueEvent","useCallback","useState","useDebouncedValue","useSearch","UseMarketSearchOptions","type","categoryIds","status","limit","debounceMs","enableSuggestions","minLength","useMarketSearch","options","query","setQueryState","submittedQuery","setSubmittedQuery","debouncedQuery","trimmedDebounced","trim","suggestionsEnabled","length","suggestionsQuery","T","q","enabled","mode","submittedQ","resultsQuery","setQuery","value","submit","target","clear","suggestions","data","isLoading","isError","error","results","hasNextPage","fetchNextPage","isFetchingNextPage","SmartRouteResponse","THIN_SMART_ROUTE_REFETCH_INTERVAL_MS","SMART_ROUTE_REFRESH_DEADLINE_BUFFER_MS","SMART_ROUTE_MIN_REFETCH_INTERVAL_MS","SMART_ROUTE_MAX_REFETCH_INTERVAL_MS","SMART_ROUTE_HIGH_SLIPPAGE_BPS","SMART_ROUTE_SHALLOW_TOP_LEVEL_RATIO","SMART_ROUTE_DEEP_FILL_LEVEL_COUNT","LIQUIDITY_CONSTRAINED_STATUSES","Set","THIN_LIQUIDITY_WARNING_PATTERN","ThinSmartRouteLiquidityReason","SmartRouteThinLiquidityAssessment","isThin","reasons","ResolveSmartRouteRefetchIntervalArgs","data","defaultIntervalMs","aggressiveIntervalMs","adaptive","isDocumentVisible","isEditing","isInputValid","isMarketOpen","isPanelActive","isSubmitting","queryEnabled","resolveMsUntilIsoTimestamp","value","nowMs","parsedValue","Date","parse","Number","isFinite","clampIntervalToRefreshDeadline","intervalMs","refreshAt","msUntilRefresh","Math","min","max","floor","assessThinSmartRouteLiquidity","quote","now","has","status","add","slippage","slippageBps","hasShallowTopLevel","fills","some","fill","length","venueQty","topLevelSize","size","hasDeepFillLevels","hasThinWarning","warnings","warning","test","reason","resolveSmartRouteRefetchInterval","args","isActivelyViewingQuote","primaryUsesProphetx","venue","deadlines","quoteRefreshNotBefore","quoteFailure","retryAt","filter","map","undefined","defaultInterval","thinLiquidity","ExecutionMode","SmartRouteResponse","SmartRouteSide","keepPreviousData","useQuery","useAggClient","resolveSmartRouteRefetchInterval","SMART_ROUTE_STALE_TIME_MS","UseSmartRouteOptions","venueMarketOutcomeId","venueMarketId","outcomeId","side","tradeSide","mode","maxSpend","sellShares","chainBalances","Record","slipCapBps","compareVenues","sellCacheScope","accountId","positionVersion","balanceCacheScope","balanceVersion","balanceKey","deepEstimate","enabled","staleTimeMs","refreshContext","isPanelActive","isEditing","isMarketOpen","isSubmitting","SmartRouteLoadingReason","UseSmartRouteResult","data","isLoading","isFetching","error","Error","refetch","Promise","loadingReason","getIsDocumentVisible","document","visibilityState","useSmartRoute","options","client","resolvedVenueMarketOutcomeId","hasValidInput","queryEnabled","query","queryKey","JSON","stringify","const","queryFn","signal","getSmartRoute","undefined","staleTime","refetchInterval","queryState","state","adaptive","defaultIntervalMs","isDocumentVisible","isInputValid","gcTime","refetchOnWindowFocus","refetchIntervalInBackground","retry","placeholderData","isPlaceholderData","String","getIsDocumentVisible","BatchOrderbooksResponse","ExecutionMode","SmartRouteResponse","Venue","keepPreviousData","useQueries","useQuery","useAggClient","resolveSmartRouteRefetchInterval","SMART_ROUTE_STALE_TIME_MS","UseSmartRouteOptions","LimitOrderVenueQuoteRequest","venue","venueMarketOutcomeId","venueMarketId","UseLimitOrderVenueQuotesOptions","requests","tradeSide","amount","marketId","accountId","chainBalances","Record","mode","slipCapBps","enabled","staleTimeMs","refreshContext","LimitOrderVenueQuoteResult","request","data","tickSize","sizeStepRaw","minSizeRaw","isLoading","isFetching","error","Error","refetch","Promise","UseLimitOrderVenueQuotesResult","quotes","isMetadataPending","getIsDocumentVisible","document","visibilityState","MAX_ORDERBOOK_METADATA_MARKET_IDS","getUniqueVenueRequests","requestsByVenue","Map","has","set","values","sort","left","right","localeCompare","resolveLimitOrderTickSizesByVenue","response","tickSizes","setTickSize","Number","isFinite","item","entry","Object","entries","venueOrderbooks","tick","market","matchedMarkets","requestedMarket","LimitOrderSizeRules","resolveLimitOrderSizeRulesByVenue","rulesByVenue","setRules","useLimitOrderVenueQuotes","options","client","uniqueRequests","hasValidInput","hasRequiredAccount","Boolean","queryEnabled","serializedChainBalances","JSON","stringify","metadataMarketIds","Set","flatMap","slice","tickMetadataQuery","queryKey","const","queryFn","signal","AbortSignal","getOrderbooks","venueMarketIds","staleTime","gcTime","refetchOnWindowFocus","retry","queries","map","getSmartRoute","maxSpend","sellShares","allowedVenues","placeholderData","refetchInterval","queryState","state","defaultIntervalMs","isDocumentVisible","isEditing","isInputValid","isMarketOpen","isPanelActive","isSubmitting","refetchIntervalInBackground","tickSizesByVenue","sizeRulesByVenue","query","index","queryError","get","String","isPending","some","quote","find","all","getIsDocumentVisible","getUniqueVenueRequests","ExecutionMode","SmartRouteResponse","Venue","useQueries","useAggClient","resolveSmartRouteRefetchInterval","SMART_ROUTE_STALE_TIME_MS","UseSmartRouteOptions","VenueSellQuoteRequest","venue","requestedSellShares","sellShares","availableShares","UseVenueSellQuotesOptions","venueMarketOutcomeId","accountId","positionVersion","requests","mode","slipCapBps","enabled","staleTimeMs","refreshContext","VenueSellQuoteResult","request","data","isLoading","isFetching","error","Error","refetch","Promise","UseVenueSellQuotesResult","quotes","getIsDocumentVisible","document","visibilityState","getUniqueVenueRequests","requestsByVenue","Map","has","set","values","sort","left","right","localeCompare","useVenueSellQuotes","options","client","uniqueRequests","queries","map","hasValidInput","queryEnabled","queryKey","allowedVenues","compareVenues","tradeSide","const","queryFn","signal","AbortSignal","getSmartRoute","staleTime","refetchInterval","queryState","state","adaptive","defaultIntervalMs","isDocumentVisible","isEditing","isInputValid","isMarketOpen","isPanelActive","isSubmitting","gcTime","refetchOnWindowFocus","refetchIntervalInBackground","retry","query","index","queryError","String","some","quote","find","all","useInfiniteQuery","Venue","useAggClient","UseUserHoldingsOptions","venue","venueMarketId","venueEventId","enabled","limit","useUserHoldings","options","client","query","queryKey","queryFn","pageParam","getUserHoldings","cursor","initialPageParam","undefined","getNextPageParam","lastPage","nextCursor","holdings","data","pages","flatMap","p","hasNextPage","MarketStatus","AggClient","RecurringCryptoDuration","RecurringCryptoVenueMarket","RecurringCryptoWindowMarket","useQuery","useAggClient","VenueEventWithMarkets","RESOLVING_POLL_INTERVAL_MS","FALLBACK_VENUE_EVENT_PAGE_LIMIT","FALLBACK_VENUE_EVENT_MAX_PAGES","FALLBACK_TARGET_WINDOW_COUNT","RECURRING_MARKET_STATUSES","open","closed","resolved","unopened","paused","RECURRING_DURATION_MS","Record","PT5M","PT15M","PT30M","PT1H","PT4H","P1D","RECURRING_SLUG_DURATION","RECURRING_DURATION_AGG_KEY_SEGMENT","Partial","RECURRING_CRYPTO_SLUG_PATTERN","RECURRING_CRYPTO_AGG_KEY_PATTERN","RECURRING_CRYPTO_DAILY_AGG_KEY_PATTERN","RecurringCryptoIdentity","asset","duration","windowStart","RecurringCryptoMarketInstance","id","windowEnd","status","venueEventId","venueMarketId","venue","RecurringCryptoTimeline","all","visible","ended","live","upcoming","viewed","UseRecurringCryptoMarketsOptions","event","enabled","isRecurringCryptoDuration","value","Object","prototype","hasOwnProperty","call","parseTimestamp","timestamp","Date","parse","Number","isFinite","hasCryptoCategory","categories","some","category","name","displayName","trim","toLowerCase","resolveWindowStartFromEnd","end","endDate","venueMarkets","map","market","find","startDate","parseAggKeyWindowStart","match","RegExpMatchArray","year","monthIndex","day","hour","minute","UTC","parsed","getUTCFullYear","getUTCMonth","getUTCDate","getUTCHours","getUTCMinutes","resolveRecurringCryptoIdentity","slugMatch","slug","durationSegment","epochSeconds","parsedEpochSeconds","isSafeInteger","toUpperCase","aggKeyMatch","aggKey","dailyAggKeyMatch","recurrence","mergeWindowMarkets","current","incoming","marketsById","Map","forEach","set","values","mergeRecurringCryptoWindows","windows","windowsById","windowMarket","existing","get","markets","sort","left","right","selectNavigableMarket","navigableMarkets","filter","priceSource","resolveRecurringCryptoTimeline","now","flatMap","startsAt","endsAt","endedMarkets","Infinity","length","slice","defaultVisible","index","findIndex","candidate","viewedStart","viewedEnd","marketToReplace","fetchRecurringCryptoPage","client","options","NonNullable","Parameters","signal","AbortSignal","listRecurringCryptoMarkets","includeOrderbookPrices","includeReferencePrices","includeDirectVenueMarkets","limit","createEmptyPriceComparison","count","min","max","spread","spreadBps","byVenue","normalizeFallbackVenueEvent","identity","candidateIdentity","venueMarket","toISOString","quoteAsset","externalEventId","externalIdentifier","externalMarketId","question","routeable","splitOrdersAllowed","outcomes","venueMarketOutcomes","outcome","venueMarketOutcomeId","externalOutcomeId","label","title","midpoint","bestBid","bestAsk","markSource","lastKnownPrice","orderbookDepth","metrics","volume","volume24h","openInterest","liquidity","resolution","sourceName","sourceUrl","sourceDomain","rawCriteria","confidence","referencePrice","raw","decimals","normalized","provider","providerMarketId","comparisons","outcomePrices","up","down","formatCanonicalRecurringAggKey","date","isNaN","getTime","twoDigits","String","padStart","join","fetchCanonicalAggKeyWindows","Promise","durationMs","currentWindowStart","Math","floor","windowStarts","Set","aggKeys","response","getVenueEvents","venues","data","fetchFallbackVenueEventWindows","categoryIds","responses","seenCursors","cursor","page","sortBy","sortDir","endDateFrom","push","nextCursor","hasMore","undefined","has","add","flat","fetchRecurringCryptoMarkets","anchorStart","queryAssets","canonicalAggKeyWindowsPromise","catch","anchorOptions","assets","durations","window","windowStartFrom","windowStartTo","anchorResponse","anchor","timelineVenues","canonicalAggKeyWindows","unscopedAnchorResponse","matchingWindow","viewedWindow","timelineStart","recurringCryptoTransitionPollInterval","timeline","useRecurringCryptoMarkets","isEnabled","query","queryKey","queryFn","staleTime","gcTime","refetchOnWindowFocus","refetchOnReconnect","refetchOnMount","refetchInterval","queryState","state","retry","isRecurringCryptoMarket","MarketStatus","MarketStatus","useQuery","useAggClient","VenueEventWithMarkets","resolveRecurringCryptoIdentity","UseVenueEventOptions","eventId","enabled","cluster","minVolume","RESOLUTION_POLL_MS","RESOLUTION_POLL_MAX_PAST_END_MS","resolutionPollInterval","event","now","Date","isRecurringCryptoMarket","status","resolved","closed","eventEndsAt","endDate","parse","Number","NaN","paused","isFinite","shouldPoll","venueMarkets","some","market","endsAt","getTime","open","useVenueEvent","options","client","query","queryKey","queryFn","signal","getVenueEventById","staleTime","gcTime","refetchOnWindowFocus","refetchOnReconnect","refetchOnMount","refetchInterval","state","data","retry","undefined","MarketStatus","MarketStatus","MatchStatus","Venue","QueryClient","QueryClientContext","useInfiniteQuery","useContext","useEffect","useState","AggClientContext","UseVenueMarketsOptions","venue","venueEventId","cluster","search","status","matchStatus","aggKey","sportsMarketType","period","marketCategory","marketGroup","limit","fetchAll","enabled","sortBy","sortDir","context","projection","minVolume","useVenueMarkets","options","client","queryClient","fallbackQueryClient","undefined","mount","unmount","Error","query","queryKey","join","queryFn","pageParam","signal","res","getVenueMarkets","cursor","initialPageParam","getNextPageParam","lastPage","hasMore","nextCursor","markets","data","pages","flatMap","page","hasNextPage","fetchNextPage","isFetchingNextPage","QueryClient","MarketStatus","VenueMarket","useMemo","VenueEventWithMarkets","useVenueEvent","UseVenueEventOptions","useVenueMarkets","mergeEventWithFullMarkets","event","fullMarkets","length","fullById","Map","map","m","id","ordering","venueMarkets","mergedMarkets","minimal","get","UseEnrichedVenueEventOptions","progressive","projection","minVolume","useEnrichedVenueEvent","options","isLoading","error","rest","eventEndedAt","endDate","Number","isFinite","Date","parse","shouldFetchOnlyOpenMarkets","now","openQuery","venueEventId","eventId","cluster","enabled","status","open","undefined","limit","fetchAll","markets","openMarkets","isEnrichingOpenMarkets","shouldFetchAllMarketsFallback","fallbackQuery","fallbackMarkets","isEnrichingFallbackMarkets","activeQuery","isEnriching","enrichedEvent","hasMoreMarkets","hasNextPage","loadMoreMarkets","fetchNextPage","isLoadingMoreMarkets","isFetchingNextPage","MarketStatus","MarketStatus","MatchStatus","Venue","RecurrenceFilter","QueryClient","QueryClientContext","keepPreviousData","useInfiniteQuery","useContext","useEffect","useMemo","useRef","useState","AggClientContext","VenueEventWithMarkets","UseVenueEventsOptions","queryKeyScope","venues","search","categoryIds","matchStatus","status","sortBy","sortDir","recurrence","enabled","limit","minVolume","minYesPrice","maxYesPrice","endDateFrom","grouped","initialPages","useVenueEvents","options","client","queryClient","fallbackQueryClient","undefined","mount","unmount","Error","query","queryKey","join","queryFn","pageParam","signal","res","getVenueEvents","cursor","initialPageParam","getNextPageParam","lastPage","hasMore","nextCursor","placeholderData","prefetchedRef","current","isLoading","isFetching","isError","isPlaceholderData","pagesLoaded","data","pages","length","hasNextPage","fetchNextPage","events","flatMap","page","loadedPageCount","QueryClient","SportsLiveResponse","SportsLiveState","useQuery","useAggClient","SportsGameStatus","SportsLiveParticipant","SPORTS_LIVE_POLL_INTERVAL_MS","SPORTS_SCHEDULED_POLL_INTERVAL_MS","sportsLiveQueryKey","sortedEventIds","const","sportsLiveRefetchInterval","response","data","some","state","status","useSportsLive","eventIds","enabled","client","Set","map","eventId","trim","filter","Boolean","sort","query","queryKey","queryFn","signal","Promise","getSportsLive","length","refetchInterval","queryState","refetchIntervalInBackground","refetchOnWindowFocus","states","stateByEventId","Map","missingEventIds","BatchMidpointsResponse","MidpointRow","keepPreviousData","useQuery","useAggClient","useAggUiConfig","normalizeVenueMarketIds","venueMarketIds","Set","map","venueMarketId","trim","filter","Boolean","sort","left","right","localeCompare","mapMidpointsByVenueMarketId","rows","Array","matched","Map","mappedMidpoints","forEach","row","set","midpoint","matchedRow","has","mapArbReturnByVenueMarketId","mappedArbReturns","arbReturn","UseVenueMarketMidpointsOptions","enabled","maxMidpointIdsPerRequest","useVenueMarketMidpoints","options","client","market","configuredMaxMidpointIdsPerRequest","requestedVenueMarketIds","query","queryKey","length","const","queryFn","signal","data","getMidpoints","bestPrice","staleTime","gcTime","refetchOnWindowFocus","retry","placeholderData","midpointRows","midpointsByVenueMarketId","arbReturnByVenueMarketId","VenueMarket","MIN_PRICE_GAP_PCT","MAX_PRICE_GAP_PCT","PriceGapValue","ComputePriceGapsOptions","markets","midpointsByVenueMarketId","ReadonlyMap","normalizeMidpoint","value","Number","isFinite","undefined","collectMarketMidpoints","market","midpoints","marketMidpoint","get","id","push","matchedMarket","matchedVenueMarkets","matchedMidpoint","computePriceGapPct","length","minMidpoint","Math","min","maxMidpoint","max","gapPct","computePriceGaps","Map","gapsByVenueMarketId","set","useEffect","useMemo","useRef","useState","VenueMarket","useAggClient","useAggUiConfig","CachedMidpoint","venue","ownOutcomes","Map","matched","Array","venueMarketId","outcomes","MidpointRowWithMatches","venueMarketOutcomeId","midpoint","buildOutcomeMidpointMap","m","o","set","resolveUncachedVisibleMarketIds","visibleMarkets","cache","inFlightIds","Set","seen","idsToFetch","consider","id","has","add","push","market","sibling","matchedVenueMarkets","buildCachedMidpointEntries","requestedVenueMarketIds","rows","rowsByVenueMarketId","map","item","nextCacheEntries","get","sib","UseViewportMidpointsOptions","maxMidpointIdsPerRequest","useViewportMidpoints","options","prices","venueByOutcomeId","client","configuredMaxMidpointIdsPerRequest","setCache","inFlightRef","visibleRef","current","visibleFp","sort","join","toFetch","length","cancelled","getMidpoints","bestPrice","then","resp","data","prev","next","entry","catch","finally","delete","venueMap","ownVenue","outcome","venueMarketOutcomes","best","bestVenue","ref","matchedVenueMarketOutcomes","find","sibMidpoint","useCallback","useEffect","useRef","useState","UseVisibleIdsOptions","rootMargin","threshold","UseVisibleIdsResult","visibleIds","Set","register","id","el","Element","useVisibleIds","options","setVisibleIds","observerRef","IntersectionObserver","elementsRef","Map","elementIdRef","WeakMap","callbackRefsRef","observer","entries","prev","changed","next","entry","current","get","target","isIntersecting","has","add","delete","values","observe","disconnect","existing","callback","unobserve","curr","set","useCallback","useEffect","useState","useAggAuthContext","useResolvedExecutionMode","STORAGE_KEY","isBrowser","window","seenKey","userId","hasSeen","localStorage","getItem","markSeen","setItem","UsePaperOnboardingResult","isOpen","dismiss","usePaperOnboarding","isPaperMode","isResolving","isAuthenticated","user","id","dismissed","setDismissed","seen","setSeen","Boolean","useQuery","VenueMarket","useAggClient","UseSettlementDetailsDataOptions","eventId","market","Pick","enabled","needsEvent","needsMarket","useSettlementDetailsData","options","client","eventQuery","queryKey","appId","queryFn","signal","getVenueEventById","staleTime","gcTime","retry","marketQuery","id","Error","response","getVenueMarkets","venue","venueEventId","undefined","externalIdentifier","limit","projection","selected","data","find","candidate","markets","useEffect","useRef","useState","useMutation","useQuery","useQueryClient","HostedVenueWithdrawal","HostedVenueWithdrawalRequest","useAggAuthContext","useAggClient","useResolvedExecutionMode","hostedVenueAccountQueryKeys","invalidateBalanceQueries","Journal","request","withdrawalId","Environment","validRequest","value","row","mode","test","requestId","amountRaw","destinationAddress","undefined","useHostedVenueTransfers","accountId","environment","client","user","isAuthenticated","executionMode","isResolving","queryClient","userId","id","permitted","scope","JSON","stringify","storageKey","entry","setEntry","ready","journal","invalid","session","current","mounted","dispatching","intent","assertSession","Error","save","next","localStorage","setItem","assertResult","result","invalidate","invalidateQueries","queryKey","account","deposit","mutationFn","getHostedVenueDepositAddress","retry","withdrawal","getHostedVenueWithdrawal","withdrawHostedVenue","status","queryFn","enabled","refetchInterval","query","state","data","refetchIntervalInBackground","resetDeposit","reset","resetWithdrawal","text","getItem","parse","terminal","isAvailable","storageError","isError","submit","const","crypto","randomUUID","mutateAsync","check","clear","removeItem","useQueryClient"],"sources":["../src/current-user-query.ts","../src/core/providers/auth-utils.ts","../src/core/providers/auth-provider.tsx","../src/use-resolved-execution-mode.ts","../src/core/providers/balance-provider.tsx","../src/core/providers/client-provider.tsx","../src/use-app-config.ts","../src/core/providers/execution-mode-provider.tsx","../src/core/providers/event-list-state-context.tsx","../src/core/ui-config/constants.ts","../src/core/ui-config/storage.ts","../src/core/ui-config/theme-utils.ts","../src/core/providers/event-trading-context.tsx","../src/core/providers/ui-provider.tsx","../src/core/providers/agg-provider.tsx","../src/execution/use-execute-managed.ts","../src/execution/use-place-limit-order.ts","../src/execution/use-cancel-managed-order.ts","../src/execution/use-positions.ts","../src/execution/use-execution-progress.ts","../src/execution/use-balance-refill-policies.ts","../src/execution/compute-closed-position-totals.ts","../src/execution/use-redeem.ts","../src/execution/use-on-redeem-event.ts","../src/execution/use-redeem-eligible-count.ts","../src/execution/use-redeem-lifecycles.ts","../src/execution/use-redeem-lifecycle.ts","../src/use-geo-block.ts","../src/venue-availability.ts","../src/use-venue-key-status.ts","../src/use-hosted-venue-account.ts","../src/use-hosted-venue-activity.ts","../src/use-shared-kyc.ts","../src/use-agg-auth.ts","../src/use-link-account.ts","../src/auth-chooser-events.ts","../src/use-categories.ts","../src/use-debounced-value.ts","../src/use-execution-orders.ts","../src/use-execution-orders-for-markets.ts","../src/use-user-activity.ts","../src/use-leaderboard.ts","../src/use-external-id.ts","../src/use-execution-positions.ts","../src/read-retry.ts","../src/market-data/chart-cache.ts","../src/market-data/chart-history.ts","../src/market-data/chart-retry-gate.ts","../src/market-data/chart-tail.ts","../src/market-data/subscription.ts","../src/use-market-chart.ts","../src/use-live-market-stores.ts","../src/use-live-candles.ts","../src/use-live-candle-overlay.ts","../src/use-event-orderbook-data.ts","../src/market-data/orderbook-snapshot.ts","../src/market-data/orderbook-cache.ts","../src/market-data/snapshot-selection.ts","../src/use-market-orderbook.ts","../src/use-live-market.ts","../src/use-live-outcome-prices.ts","../src/use-live-best-prices.ts","../src/use-live-trades.ts","../src/use-midpoints.ts","../src/use-rolling-chart-window.ts","../src/use-arb.ts","../src/use-order-book.ts","../src/use-orderbook-quote.ts","../src/use-orders.ts","../src/use-search.ts","../src/use-market-search.ts","../src/smart-route-refresh-policy.ts","../src/use-smart-route.ts","../src/use-limit-order-venue-quotes.ts","../src/use-venue-sell-quotes.ts","../src/use-user-holdings.ts","../src/use-recurring-crypto-markets.ts","../src/use-venue-event.ts","../src/use-venue-markets.ts","../src/use-enriched-venue-event.ts","../src/use-venue-events.ts","../src/use-sports-live.ts","../src/use-venue-market-midpoints.ts","../src/utils/compute-price-gaps.ts","../src/use-viewport-midpoints.ts","../src/use-visible-ids.ts","../src/use-paper-onboarding.ts","../src/use-settlement-details-data.ts","../src/use-hosted-venue-transfers.ts"],"sourcesContent":["import type { UserProfile, AggClient } from \"@agg-build/sdk\";\nimport type { QueryClient } from \"@tanstack/react-query\";\n\nexport const CURRENT_USER_QUERY_KEY = [\"current-user\"] as const;\nexport const CURRENT_USER_STALE_TIME_MS = 60_000;\n\nexport const getCurrentUserQueryKey = (\n queryKeyScope: string = CURRENT_USER_QUERY_KEY[0],\n): [string] => {\n return [queryKeyScope];\n};\n\nexport const fetchCurrentUserProfile = (\n queryClient: QueryClient,\n client: AggClient,\n queryKey = CURRENT_USER_QUERY_KEY,\n): Promise<UserProfile> => {\n return queryClient.fetchQuery({\n queryKey,\n queryFn: () => client.getCurrentUser(),\n staleTime: CURRENT_USER_STALE_TIME_MS,\n });\n};\n","import type {\n UserProfile,\n AggAuthStartBody,\n AggAuthStartResult,\n AggClientSessionInput,\n} from \"@agg-build/sdk\";\nimport { AccountType, AccountProvider, TurnstileChallengeError } from \"@agg-build/sdk\";\nimport type { AggAuthSignInOptions } from \"./types\";\n\nexport interface BrowserAuthLocation {\n domain: string;\n uri: string;\n}\n\nexport interface AuthCallbackTokens {\n accessToken: string;\n refreshToken: string;\n tokenType?: string;\n userId?: string;\n}\n\ntype AuthCodeExchangeResult = {\n accessToken: string;\n refreshToken?: string;\n user: UserProfile;\n};\n\ntype WalletAuthResult = {\n accessToken: string;\n refreshToken?: string;\n user: UserProfile;\n};\n\ntype WalletAuthClient = {\n authStart: (body: AggAuthStartBody) => Promise<AggAuthStartResult>;\n buildSiweMessage: (params: {\n address: string;\n chainId?: number;\n domain: string;\n issuedAt?: string;\n nonce: string;\n statement?: string;\n uri: string;\n }) => string;\n buildSiwsMessage: (params: {\n address: string;\n chainId?: string;\n domain: string;\n issuedAt?: string;\n nonce: string;\n statement?: string;\n uri: string;\n }) => string;\n verify: (args: { message: string; signature: string }) => Promise<WalletAuthResult>;\n};\n\ntype AuthCallbackClient = {\n exchangeAuthCode: (code: string) => Promise<AuthCodeExchangeResult>;\n};\n\ntype LinkConfirmCallbackClient = {\n linkAccountConfirm: (token: string) => Promise<unknown>;\n};\n\nexport const createPlaceholderUserProfile = (input: { id: string }): UserProfile => {\n return {\n id: input.id,\n username: null,\n avatarUrl: null,\n externalId: null,\n isLocationBlocked: false,\n venueAccounts: null,\n accounts: [],\n wallets: [],\n };\n};\n\nexport const createWalletSessionUser = (input: { address: string; id: string }): UserProfile => {\n return {\n ...createPlaceholderUserProfile({ id: input.id }),\n accounts: [\n {\n type: AccountType.siwe,\n provider: AccountProvider.wallet,\n providerAccountId: input.address,\n },\n ],\n };\n};\n\nexport const getBrowserAuthLocation = (): BrowserAuthLocation => {\n if (typeof window === \"undefined\") {\n return {\n domain: \"localhost\",\n uri: \"http://localhost\",\n };\n }\n\n return {\n domain: window.location.host,\n uri: window.location.origin,\n };\n};\n\nconst resolveAuthCallbackUrl = (callbackUrl?: string | URL): URL | null => {\n return callbackUrl instanceof URL\n ? callbackUrl\n : typeof callbackUrl === \"string\"\n ? new URL(\n callbackUrl,\n typeof window === \"undefined\" ? \"http://localhost\" : window.location.origin,\n )\n : typeof window === \"undefined\"\n ? null\n : new URL(window.location.href);\n};\n\nexport const parseAuthCallbackCode = (callbackUrl?: string | URL): string | null => {\n const resolvedUrl = resolveAuthCallbackUrl(callbackUrl);\n return resolvedUrl?.searchParams.get(\"code\") ?? null;\n};\n\nexport const parseLinkConfirmToken = (callbackUrl?: string | URL): string | null => {\n const resolvedUrl = resolveAuthCallbackUrl(callbackUrl);\n return resolvedUrl?.searchParams.get(\"link_confirm_token\") ?? null;\n};\n\nconst AUTH_METHOD_IDS = [\"siwe\", \"siws\", \"google\", \"twitter\", \"apple\", \"email\"] as const;\ntype AggAuthMethodId = (typeof AUTH_METHOD_IDS)[number];\n\nconst EXISTING_METHOD_NAMES = { email: \"an email link\", google: \"Google\", apple: \"Apple\" } as const;\n\nexport class AggIdentityExistsError extends Error {\n readonly code = \"identity_exists\";\n constructor(\n message: string,\n readonly existingMethod: \"email\" | \"google\" | \"apple\",\n readonly attemptedMethod: AggAuthMethodId,\n ) {\n super(message);\n this.name = \"AggIdentityExistsError\";\n }\n}\n\nconst IDENTITY_EXISTS_PARAMS = [\"error\", \"message\", \"existing_method\", \"attempted_method\"];\n\nexport const parseAuthCallbackIdentityExists = (\n callbackUrl?: string | URL,\n): AggIdentityExistsError | null => {\n const params = resolveAuthCallbackUrl(callbackUrl)?.searchParams;\n if (params?.get(\"error\") !== \"identity_exists\") return null;\n\n const existingMethod = params.get(\"existing_method\");\n if (existingMethod !== \"email\" && existingMethod !== \"google\" && existingMethod !== \"apple\") {\n return null;\n }\n const attemptedMethod = AUTH_METHOD_IDS.find((id) => id === params.get(\"attempted_method\"));\n if (!attemptedMethod) return null;\n\n // The `message` query param is attacker-controllable; never display it.\n const name = EXISTING_METHOD_NAMES[existingMethod];\n return new AggIdentityExistsError(\n `You've signed in with ${name} before. Please continue with ${name}.`,\n existingMethod,\n attemptedMethod,\n );\n};\n\nexport const getAuthCallbackCleanupPath = (callbackUrl?: string | URL): string | null => {\n const resolvedUrl = resolveAuthCallbackUrl(callbackUrl);\n if (!resolvedUrl) return null;\n\n const params = new URLSearchParams(resolvedUrl.search);\n params.delete(\"code\");\n params.delete(\"link_confirm_token\");\n if (params.get(\"error\") === \"identity_exists\") {\n for (const name of IDENTITY_EXISTS_PARAMS) params.delete(name);\n }\n const search = params.toString();\n\n return `${resolvedUrl.pathname}${search ? `?${search}` : \"\"}`;\n};\n\nexport const exchangeAuthCallbackCode = async (\n client: AuthCallbackClient,\n callbackUrl?: string | URL,\n): Promise<{ cleanupPath: string | null; user: UserProfile } | null> => {\n const code = parseAuthCallbackCode(callbackUrl);\n if (!code) return null;\n\n const result = await client.exchangeAuthCode(code);\n\n return {\n cleanupPath: getAuthCallbackCleanupPath(callbackUrl),\n user: result.user,\n };\n};\n\n/**\n * Confirm an account-link round-trip. After `linkAccount()` → provider OAuth, the\n * browser lands back on `redirectUrl` with a `?link_confirm_token=` param; this\n * exchanges it for the persisted Account row. Returns null when no link token is\n * present (not a link callback). Throws (HTTP 409) when the identity is already\n * linked to a DIFFERENT principal — the caller surfaces it as the callback error;\n * `already_linked_same` (same principal) resolves idempotently.\n */\nexport const confirmLinkAccountCallback = async (\n client: LinkConfirmCallbackClient,\n callbackUrl?: string | URL,\n): Promise<{ cleanupPath: string | null } | null> => {\n const token = parseLinkConfirmToken(callbackUrl);\n if (!token) return null;\n\n await client.linkAccountConfirm(token);\n\n return { cleanupPath: getAuthCallbackCleanupPath(callbackUrl) };\n};\n\nexport const parseAuthCallbackTokens = (callbackUrl?: string | URL): AuthCallbackTokens | null => {\n const resolvedUrl = resolveAuthCallbackUrl(callbackUrl);\n if (!resolvedUrl) return null;\n\n const hash = resolvedUrl.hash.startsWith(\"#\") ? resolvedUrl.hash.slice(1) : resolvedUrl.hash;\n if (!hash) return null;\n\n const params = new URLSearchParams(hash);\n const accessToken = params.get(\"access_token\");\n const refreshToken = params.get(\"refresh_token\");\n\n if (!accessToken || !refreshToken) return null;\n\n const userId = params.get(\"user_id\") ?? undefined;\n const tokenType = params.get(\"token_type\") ?? undefined;\n\n return {\n accessToken,\n refreshToken,\n tokenType,\n userId,\n };\n};\n\nexport const createAuthCallbackSession = (tokens: AuthCallbackTokens): AggClientSessionInput => {\n return {\n accessToken: tokens.accessToken,\n refreshToken: tokens.refreshToken,\n user: tokens.userId ? createPlaceholderUserProfile({ id: tokens.userId }) : undefined,\n };\n};\n\nexport const executeWalletAuthFlow = async (input: {\n client: WalletAuthClient;\n location?: BrowserAuthLocation;\n options: AggAuthSignInOptions;\n}): Promise<WalletAuthResult> => {\n const address = input.options.address.trim();\n const chain = input.options.chain ?? \"ethereum\";\n const provider = chain === \"solana\" ? \"siws\" : \"siwe\";\n const location = input.location ?? getBrowserAuthLocation();\n const startResult = await input.client.authStart({\n provider,\n ...(input.options.turnstileToken ? { turnstileToken: input.options.turnstileToken } : {}),\n });\n\n if (startResult.type === \"challenge_required\") {\n if (!startResult.siteKey) {\n throw new Error(\"Server returned challenge_required but no siteKey was provided.\");\n }\n // Throw a typed error so the auth package can catch it, render the Turnstile\n // widget, and retry with the resulting token.\n throw new TurnstileChallengeError(startResult.siteKey);\n }\n\n if (startResult.type !== \"nonce\") {\n throw new Error(`AGG auth start returned an unexpected \"${startResult.type}\" response`);\n }\n\n const message =\n chain === \"solana\"\n ? input.client.buildSiwsMessage({\n domain: location.domain,\n address,\n uri: location.uri,\n nonce: startResult.nonce,\n chainId: typeof input.options.chainId === \"string\" ? input.options.chainId : \"mainnet\",\n statement: startResult.statement ?? input.options.statement,\n })\n : input.client.buildSiweMessage({\n domain: location.domain,\n // Any casing: `buildSiweMessage` applies the EIP-55 checksum itself.\n address,\n uri: location.uri,\n nonce: startResult.nonce,\n chainId: typeof input.options.chainId === \"number\" ? input.options.chainId : undefined,\n statement: startResult.statement ?? input.options.statement,\n });\n\n const signature = await input.options.signMessage(message);\n const result = await input.client.verify({ message, signature });\n\n return {\n accessToken: result.accessToken,\n refreshToken: result.refreshToken,\n user: createWalletSessionUser({\n id: result.user.id,\n address,\n }),\n };\n};\n","import type { UserProfile, AggClient } from \"@agg-build/sdk\";\nimport { QueryClient, QueryClientContext } from \"@tanstack/react-query\";\nimport { useCallback, useContext, useEffect, useMemo, useState, type ReactNode } from \"react\";\nimport { fetchCurrentUserProfile } from \"../../current-user-query\";\nimport {\n confirmLinkAccountCallback,\n createAuthCallbackSession,\n exchangeAuthCallbackCode,\n executeWalletAuthFlow,\n getAuthCallbackCleanupPath,\n parseAuthCallbackIdentityExists,\n parseAuthCallbackTokens,\n} from \"./auth-utils\";\nimport { AggAuthContext, AggClientContext } from \"./contexts\";\nimport type { AggAuthContextValue, AggAuthSignInOptions } from \"./types\";\n\ninterface AuthSnapshot {\n isAuthenticated: boolean;\n user: UserProfile | undefined;\n}\n\nconst getClientAuthSnapshot = (client: AggClient | null): AuthSnapshot => {\n return {\n isAuthenticated: client?.isAuthenticated ?? false,\n user: client?.user,\n };\n};\n\ninterface AggAuthProviderProps {\n children: ReactNode;\n}\n\nconst toError = (value: unknown): Error => {\n return value instanceof Error ? value : new Error(String(value));\n};\n\nconst replaceAuthCallbackUrl = (cleanupPath: string | null): void => {\n if (!cleanupPath || typeof window === \"undefined\") return;\n window.history.replaceState(null, \"\", cleanupPath);\n};\n\nexport function AggAuthProvider({ children }: AggAuthProviderProps): React.JSX.Element {\n const client = useContext(AggClientContext);\n const queryClientFromContext = useContext(QueryClientContext);\n const fallbackQueryClient = useMemo(() => new QueryClient(), []);\n const queryClient =\n queryClientFromContext && \"fetchQuery\" in queryClientFromContext\n ? queryClientFromContext\n : fallbackQueryClient;\n const snapshot = getClientAuthSnapshot(client);\n const [isAuthenticated, setIsAuthenticated] = useState(snapshot.isAuthenticated);\n const [user, setUser] = useState<UserProfile | undefined>(snapshot.user);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const isWeb3User = useMemo<boolean>(() => {\n const accounts = user?.accounts;\n if (!Array.isArray(accounts)) return true;\n return accounts.some((account) => {\n const provider = String(account.provider ?? \"\").toLowerCase();\n return provider === \"wallet\" || provider === \"solana_wallet\";\n });\n }, [user]);\n\n const refreshCurrentUser = useCallback(\n async (targetClient: AggClient): Promise<UserProfile> => {\n const fullUser = await fetchCurrentUserProfile(queryClient, targetClient);\n setIsAuthenticated(true);\n setUser(fullUser);\n return fullUser;\n },\n [queryClient],\n );\n\n useEffect(() => {\n const state = getClientAuthSnapshot(client);\n setIsAuthenticated(state.isAuthenticated);\n setUser(state.user);\n setIsLoading(false);\n setError(null);\n\n if (!client) return;\n\n if (state.isAuthenticated) {\n // Token already in memory — validate it and hydrate the full profile.\n refreshCurrentUser(client).catch(() => {\n client.clearAccessToken();\n });\n } else if (client.authStatus === \"unknown\") {\n // Bootstrap hint found but no token in memory — attempt silent refresh.\n // This succeeds with cookie-refresh delivery (HttpOnly cookie carries the refresh token).\n // With body delivery the refresh token is lost on reload and this safely falls through to unauthenticated.\n client\n .refreshAccessToken()\n .then(() => refreshCurrentUser(client))\n .catch(() => {\n client.clearAccessToken();\n });\n }\n }, [client, refreshCurrentUser]);\n\n useEffect(() => {\n if (!client) return;\n\n return client.onAuthStateChange((authenticated) => {\n setIsAuthenticated(authenticated);\n setUser(client.user);\n if (!authenticated) {\n setIsLoading(false);\n setError(null);\n }\n });\n }, [client]);\n\n const signIn = useCallback(\n async (options: AggAuthSignInOptions): Promise<void> => {\n if (!client) {\n const missingClientError = new Error(\"Agg client is not configured in <AggProvider>\");\n setError(missingClientError);\n throw missingClientError;\n }\n\n const address = options.address.trim();\n if (!address) {\n const missingAddressError = new Error(\"Wallet address is required\");\n setError(missingAddressError);\n throw missingAddressError;\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n const result = await executeWalletAuthFlow({\n client,\n options: {\n ...options,\n address,\n },\n });\n\n client.setSession(result);\n setIsAuthenticated(true);\n setUser(result.user);\n await refreshCurrentUser(client);\n } catch (signInError) {\n const resolvedError = toError(signInError);\n setError(resolvedError);\n throw resolvedError;\n } finally {\n setIsLoading(false);\n }\n },\n [client, refreshCurrentUser],\n );\n\n const startAuth = useCallback<AggAuthContextValue[\"startAuth\"]>(\n async (options) => {\n if (!client) {\n const missingClientError = new Error(\"Agg client is not configured in <AggProvider>\");\n setError(missingClientError);\n throw missingClientError;\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n return await client.authStart(options);\n } catch (startAuthError) {\n const resolvedError = toError(startAuthError);\n setError(resolvedError);\n throw resolvedError;\n } finally {\n setIsLoading(false);\n }\n },\n [client],\n );\n\n const setSession = useCallback<AggAuthContextValue[\"setSession\"]>(\n async (session) => {\n if (!client) {\n const missingClientError = new Error(\"Agg client is not configured in <AggProvider>\");\n setError(missingClientError);\n throw missingClientError;\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n client.setSession(session);\n const resolvedUser = await refreshCurrentUser(client);\n setIsAuthenticated(true);\n setUser(resolvedUser);\n return resolvedUser;\n } catch (sessionError) {\n client.clearAccessToken();\n setIsAuthenticated(false);\n setUser(undefined);\n const resolvedError = toError(sessionError);\n setError(resolvedError);\n throw resolvedError;\n } finally {\n setIsLoading(false);\n }\n },\n [client, refreshCurrentUser],\n );\n\n const handleAuthCallback = useCallback<AggAuthContextValue[\"handleAuthCallback\"]>(\n async (callbackUrl) => {\n if (!client) {\n const missingClientError = new Error(\"Agg client is not configured in <AggProvider>\");\n setError(missingClientError);\n throw missingClientError;\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n const identityError = parseAuthCallbackIdentityExists(callbackUrl);\n if (identityError) {\n if (callbackUrl === undefined) {\n replaceAuthCallbackUrl(getAuthCallbackCleanupPath(callbackUrl));\n }\n throw identityError;\n }\n\n const exchangedSession = await exchangeAuthCallbackCode(client, callbackUrl);\n if (exchangedSession) {\n const resolvedUser = await refreshCurrentUser(client);\n\n if (callbackUrl === undefined) {\n replaceAuthCallbackUrl(exchangedSession.cleanupPath);\n }\n\n return resolvedUser;\n }\n\n // Account-link callback: the caller was already authenticated and just\n // authorized a provider — confirm the link and refresh, don't re-session.\n const confirmedLink = await confirmLinkAccountCallback(client, callbackUrl);\n if (confirmedLink) {\n const resolvedUser = await refreshCurrentUser(client);\n\n if (callbackUrl === undefined) {\n replaceAuthCallbackUrl(confirmedLink.cleanupPath);\n }\n\n return resolvedUser;\n }\n\n const tokens = parseAuthCallbackTokens(callbackUrl);\n if (!tokens) return null;\n\n client.setSession(createAuthCallbackSession(tokens));\n setIsAuthenticated(client.isAuthenticated);\n setUser(client.user);\n const resolvedUser = await refreshCurrentUser(client);\n\n if (callbackUrl === undefined) {\n replaceAuthCallbackUrl(getAuthCallbackCleanupPath(callbackUrl));\n }\n\n return resolvedUser;\n } catch (callbackError) {\n const resolvedError = toError(callbackError);\n setError(resolvedError);\n throw resolvedError;\n } finally {\n setIsLoading(false);\n }\n },\n [client, refreshCurrentUser],\n );\n\n const signOut = useCallback(async (): Promise<void> => {\n await client?.signOut();\n setIsAuthenticated(false);\n setUser(undefined);\n setError(null);\n }, [client]);\n\n const clearError = useCallback((): void => {\n setError(null);\n }, []);\n\n const value = useMemo<AggAuthContextValue>(() => {\n return {\n isAuthenticated,\n isWeb3User,\n user,\n isLoading,\n error,\n signIn,\n startAuth,\n setSession,\n handleAuthCallback,\n signOut,\n clearError,\n };\n }, [\n clearError,\n error,\n handleAuthCallback,\n isAuthenticated,\n isWeb3User,\n isLoading,\n setSession,\n signIn,\n signOut,\n startAuth,\n user,\n ]);\n\n return <AggAuthContext.Provider value={value}>{children}</AggAuthContext.Provider>;\n}\n","import { useContext } from \"react\";\nimport type { AppTradingMode } from \"@agg-build/sdk\";\nimport { useAggUiConfig } from \"./core/provider\";\nimport { AggExecutionModeContext } from \"./core/providers/contexts\";\n\nexport interface UseResolvedExecutionModeResult {\n /**\n * The mode every execution surface must trade against. Once `/app/config`\n * resolves this is the server's value, unconditionally.\n */\n executionMode: AppTradingMode;\n /** Convenience for the common branch. */\n isPaperMode: boolean;\n /**\n * True while `/app/config` is still in flight, so the value above is a\n * locally-configured guess rather than the server's answer. Surfaces that\n * render mode-specific chrome (a paper badge, a hidden Limit tab, hidden\n * deposit controls) should hold or skeleton until this is false — otherwise\n * a paper app briefly paints live chrome, and vice versa.\n */\n isResolving: boolean;\n}\n\n/**\n * Resolve the app's execution mode with the server as the source of truth.\n *\n * Paper/live is an app-level setting owned by the partner admin (SNA-2964);\n * end users cannot change it, and a partner's own `trading.executionMode`\n * provider config cannot override it. That local value survives only as the\n * pre-resolution guess and as the answer for callers running without a\n * reachable `/app/config`.\n *\n * The API enforces the same decision independently — a client that ignores\n * this hook still cannot place a live order against a paper app.\n */\nexport function useResolvedExecutionMode(\n /**\n * Per-surface `executionMode` prop, where one exists (`EventMarketPage`,\n * `UserProfilePage`, `PlaceOrder`, …). Kept for source compatibility and\n * honoured only BEFORE the server answers — an app-level mode cannot be\n * overridden per surface, so the documented \"live panel inside a paper app\"\n * pattern no longer applies.\n */\n override?: AppTradingMode,\n): UseResolvedExecutionModeResult {\n // Read from context, never fetch here: a surface rendered under a bare\n // <AggUiProvider> (Storybook, tests, hand-composed partner layouts) has no\n // client to fetch with, and must degrade to local config instead of throwing.\n const serverConfig = useContext(AggExecutionModeContext);\n const tradingMode = serverConfig?.tradingMode;\n const isLoading = serverConfig?.isLoading ?? false;\n const {\n trading: { executionMode: configuredExecutionMode },\n } = useAggUiConfig();\n\n // Precedence, highest first: server → per-surface prop → provider config →\n // live. The server wins the moment it has spoken; everything below it only\n // exists to keep first paint from flashing the wrong chrome.\n const localMode = override ?? configuredExecutionMode;\n const executionMode: AppTradingMode = tradingMode ?? (localMode === \"paper\" ? \"paper\" : \"live\");\n\n return {\n executionMode,\n isPaperMode: executionMode === \"paper\",\n isResolving: tradingMode === undefined && isLoading,\n };\n}\n","import type { UnifiedBalanceResponse, Venue } from \"@agg-build/sdk\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport { useCallback, useContext, useMemo, type ReactNode } from \"react\";\nimport { balanceQueryKeys } from \"../../execution/balance-invalidation\";\nimport { useResolvedExecutionMode } from \"../../use-resolved-execution-mode\";\nimport { resolveAggUiLabels } from \"../ui-config/labels\";\nimport { AggAuthContext, AggBalanceContext, AggClientContext } from \"./contexts\";\nimport type { AggBalanceBreakdownItem, AggBalanceContextValue } from \"./types\";\n\nconst CHAIN_LABELS: Record<number, string> = {\n 0: \"Paper\",\n 1: \"Ethereum\",\n 10: \"Optimism\",\n 56: \"BNB\",\n 137: \"Polygon\",\n 1337: \"Hyperliquid\",\n 8453: \"Base\",\n 42161: \"Arbitrum\",\n 43114: \"Avalanche\",\n 11155111: \"Sepolia\",\n 792703809: \"Solana\",\n};\n\nconst chainLabelFromId = (chainId: number): string => {\n return CHAIN_LABELS[chainId] ?? `Chain ${chainId}`;\n};\n\nconst toTokenUnits = (raw: string, decimals: number): number => {\n const numeric = Number(raw);\n if (!Number.isFinite(numeric)) return 0;\n return numeric / 10 ** decimals;\n};\n\nconst isUsdBasedToken = (tokenSymbol: string): boolean => {\n return tokenSymbol?.toUpperCase()?.includes(\"USD\");\n};\n\nconst EMPTY_MANAGED_BALANCES: UnifiedBalanceResponse = {\n cash: [],\n positions: [],\n};\n\ninterface AggBalanceProviderProps {\n children: ReactNode;\n}\n\nexport function AggBalanceProvider({ children }: AggBalanceProviderProps): React.JSX.Element {\n const client = useContext(AggClientContext);\n const authContext = useContext(AggAuthContext);\n // App-level paper/live, server-owned. Reading local ui-config here would\n // leave a paper app fetching live balances for its header chips and\n // profile totals.\n const { executionMode } = useResolvedExecutionMode();\n\n if (!authContext) {\n throw new Error(\"AggBalanceProvider must be used within an <AggAuthProvider>\");\n }\n\n const { isAuthenticated } = authContext;\n const queryExecutionMode = executionMode === \"paper\" ? \"paper\" : undefined;\n\n const balancesQuery = useQuery({\n queryKey: balanceQueryKeys.provider(queryExecutionMode),\n queryFn: async (): Promise<UnifiedBalanceResponse> => {\n if (!client || !isAuthenticated) {\n return EMPTY_MANAGED_BALANCES;\n }\n\n return client.getManagedBalances(\n queryExecutionMode ? { mode: queryExecutionMode } : undefined,\n );\n },\n enabled: Boolean(client && isAuthenticated),\n staleTime: 60 * 1000,\n // A matched fill can precede settlement and the API's next balance snapshot.\n // Keep visible clients converging even if that first invalidation reads old cash.\n refetchInterval: queryExecutionMode === \"paper\" ? false : 5_000,\n refetchIntervalInBackground: false,\n refetchOnWindowFocus: \"always\",\n refetchOnReconnect: \"always\",\n });\n\n const managedBalancesData = balancesQuery.data;\n const managedBalances = useMemo(\n () => managedBalancesData ?? EMPTY_MANAGED_BALANCES,\n [managedBalancesData],\n );\n const connectedVenues = useMemo(() => {\n return Array.from(new Set(managedBalances.positions.map((position) => position.venue))).sort(\n (a, b) => a.localeCompare(b),\n ) as Venue[];\n }, [managedBalances.positions]);\n // A failed background refetch must not replace a previously loaded balance\n // snapshot with a fatal error state. React Query keeps the cached data usable\n // while it retries (including after an automatic access-token refresh).\n const balancesError = managedBalancesData === undefined ? balancesQuery.error : null;\n const isBalancesLoading = balancesQuery.isLoading;\n const refetchBalances = balancesQuery.refetch;\n\n const totalBalance = useMemo((): number => {\n const cash = managedBalances.cash;\n return cash.reduce((sum, token) => {\n if (!isUsdBasedToken(token.tokenSymbol)) return sum;\n const tokenAcrossChains = token.chains.reduce(\n (chainSum, chain) =>\n chainSum + toTokenUnits(chain.balanceRaw, chain.decimals ?? token.decimals),\n 0,\n );\n return sum + tokenAcrossChains;\n }, 0);\n }, [managedBalances]);\n\n const availableBalance = useMemo((): number => {\n return managedBalances.cash.reduce((sum, token) => {\n if (!isUsdBasedToken(token.tokenSymbol)) return sum;\n if (token.availableRaw != null) {\n return sum + toTokenUnits(token.availableRaw, token.decimals);\n }\n return (\n sum +\n token.chains.reduce(\n (chainSum, chain) =>\n chainSum +\n toTokenUnits(chain.availableRaw ?? chain.balanceRaw, chain.decimals ?? token.decimals),\n 0,\n )\n );\n }, 0);\n }, [managedBalances]);\n\n const reservedBalance = useMemo((): number => {\n return managedBalances.cash.reduce((sum, token) => {\n if (!isUsdBasedToken(token.tokenSymbol)) return sum;\n if (token.reservedRaw != null) {\n return sum + toTokenUnits(token.reservedRaw, token.decimals);\n }\n return (\n sum +\n token.chains.reduce(\n (chainSum, chain) =>\n chainSum + toTokenUnits(chain.heldRaw ?? \"0\", chain.decimals ?? token.decimals),\n 0,\n )\n );\n }, 0);\n }, [managedBalances]);\n\n const buildBalanceBreakdown = useCallback(\n (rawForChain: (chain: UnifiedBalanceResponse[\"cash\"][number][\"chains\"][number]) => string) => {\n const bySource = new Map<string, AggBalanceBreakdownItem>();\n const cash = managedBalances.cash;\n // Hosted BETDEX collateral is not spendable from any user's chain wallet.\n const chainVenues = connectedVenues.filter((venue) => venue !== \"betdex\");\n\n for (const token of cash) {\n if (!isUsdBasedToken(token.tokenSymbol)) continue;\n for (const chain of token.chains) {\n const native = chain.custodyKind === \"VENUE_ACCOUNT\";\n const key = native\n ? JSON.stringify([\n \"venue-account\",\n chain.venue,\n chain.venueAccountId,\n chain.externalAccountId,\n chain.chainId,\n ])\n : String(chain.chainId);\n const current = bySource.get(key) ?? {\n key,\n label: native\n ? chain.venue\n ? resolveAggUiLabels(\"en\").venues[chain.venue]\n : resolveAggUiLabels(\"en\").userProfile.balance.venueAccount\n : chainLabelFromId(chain.chainId),\n balance: 0,\n accountCount: 0,\n venues:\n native && chain.venue\n ? [chain.venue]\n : chainVenues.length > 0\n ? chainVenues\n : undefined,\n ...(native\n ? {\n venue: chain.venue,\n venueAccountId: chain.venueAccountId,\n externalAccountId: chain.externalAccountId,\n isFresh: chain.isFresh === true,\n }\n : {}),\n };\n current.balance += toTokenUnits(rawForChain(chain), chain.decimals ?? token.decimals);\n current.accountCount += 1;\n if (native) current.isFresh = current.isFresh === true && chain.isFresh === true;\n bySource.set(key, current);\n }\n }\n\n return Array.from(bySource.values()).sort((a, b) => a.label.localeCompare(b.label));\n },\n [connectedVenues, managedBalances.cash],\n );\n\n const balanceBreakdown = useMemo((): AggBalanceBreakdownItem[] => {\n return buildBalanceBreakdown((chain) => chain.balanceRaw);\n }, [buildBalanceBreakdown]);\n\n const availableBalanceBreakdown = useMemo((): AggBalanceBreakdownItem[] => {\n return buildBalanceBreakdown((chain) => chain.availableRaw ?? chain.balanceRaw);\n }, [buildBalanceBreakdown]);\n\n const positionsBalanceTotal = useMemo((): number => {\n const positions = managedBalances.positions;\n const actualPositionsBalance = positions.reduce(\n (sum, position) => sum + (Number.isFinite(position.balance) ? position.balance : 0),\n 0,\n );\n return actualPositionsBalance + reservedBalance;\n }, [managedBalances.positions, reservedBalance]);\n\n const kalshiVenueCash = managedBalances.venueCash?.find((item) => item.venue === \"kalshi\");\n const venueCashBalances = useMemo(\n () =>\n Object.fromEntries(\n (managedBalances.venueCash ?? []).map((item) => [item.venue, item.balanceCents / 100]),\n ),\n [managedBalances.venueCash],\n );\n const kalshiBalance = kalshiVenueCash ? kalshiVenueCash.balanceCents / 100 : null;\n const kalshiPortfolioValue =\n kalshiVenueCash?.portfolioValueCents == null ? null : kalshiVenueCash.portfolioValueCents / 100;\n\n const betdexCash = managedBalances.venueCash?.find(\n (item) => item.venue === \"betdex\" && item.accountModel === \"platform-hosted\",\n );\n const hostedUsd = (raw: string | undefined): number | null => {\n if (raw === undefined || !/^-?\\d+$/.test(raw)) return null;\n const value = Number(raw) / 1_000_000;\n return Number.isFinite(value) ? value : null;\n };\n const betdexBalance = betdexCash?.decimals === 6 ? hostedUsd(betdexCash.balanceRaw) : null;\n const betdexAvailableBalance =\n betdexCash?.decimals === 6 ? hostedUsd(betdexCash.availableRaw) : null;\n\n const refetch = useCallback((): void => {\n if (!isAuthenticated) return;\n void refetchBalances();\n }, [isAuthenticated, refetchBalances]);\n\n const refetchConnectionStatus = useCallback((): void => {\n if (!client || !isAuthenticated) return;\n void client.getCurrentUser();\n }, [client, isAuthenticated]);\n\n const value = useMemo<AggBalanceContextValue>(() => {\n if (!isAuthenticated) {\n return {\n managedBalances,\n dataUpdatedAt: 0,\n totalBalance: 0,\n availableBalance: 0,\n reservedBalance: 0,\n positionsBalanceTotal: 0,\n kalshiBalance: null,\n kalshiPortfolioValue: null,\n betdexBalance: null,\n betdexAvailableBalance: null,\n balanceBreakdown: [],\n availableBalanceBreakdown: [],\n connectedVenues: [],\n isLoading: false,\n error: null,\n refetch,\n refetchConnectionStatus,\n };\n }\n\n const error =\n balancesError instanceof Error\n ? balancesError\n : balancesError\n ? new Error(String(balancesError))\n : null;\n\n return {\n managedBalances,\n dataUpdatedAt: balancesQuery.dataUpdatedAt,\n totalBalance,\n availableBalance,\n reservedBalance,\n positionsBalanceTotal,\n kalshiBalance,\n venueCashBalances,\n kalshiPortfolioValue,\n betdexBalance,\n betdexAvailableBalance,\n balanceBreakdown,\n availableBalanceBreakdown,\n connectedVenues,\n isLoading: isBalancesLoading,\n error,\n refetch,\n refetchConnectionStatus,\n };\n }, [\n balanceBreakdown,\n availableBalance,\n availableBalanceBreakdown,\n balancesError,\n connectedVenues,\n isBalancesLoading,\n isAuthenticated,\n kalshiBalance,\n venueCashBalances,\n kalshiPortfolioValue,\n betdexBalance,\n betdexAvailableBalance,\n managedBalances,\n balancesQuery.dataUpdatedAt,\n positionsBalanceTotal,\n refetch,\n refetchConnectionStatus,\n reservedBalance,\n totalBalance,\n ]);\n\n return <AggBalanceContext.Provider value={value}>{children}</AggBalanceContext.Provider>;\n}\n","import type { AggClient } from \"@agg-build/sdk\";\nimport type { ReactNode } from \"react\";\nimport { AggClientContext } from \"./contexts\";\n\ninterface AggClientProviderProps {\n client?: AggClient;\n children: ReactNode;\n}\n\nexport function AggClientProvider({ client, children }: AggClientProviderProps): React.JSX.Element {\n \"use memo\";\n return <AggClientContext.Provider value={client ?? null}>{children}</AggClientContext.Provider>;\n}\n","import type { AppClientConfigResponse } from \"@agg-build/sdk\";\nimport { useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { useAggClient, useOptionalAggClient } from \"./core/provider\";\n\nconst FIVE_MINUTES = 5 * 60 * 1000;\n\n/**\n * Stands in for the appId on an admin-key-only client, so those entries get\n * their own cache slot instead of colliding with a real App's config.\n */\nconst NO_APP_SCOPE = \"__no-app__\";\n\n/**\n * App config is per-App data, and `tradingMode` on it is the client-side\n * trading authority (SNA-2964). Two `AggClient`s for different Apps under one\n * `QueryClient` — a partner switching Apps, an admin previewing one — must not\n * read each other's entry, or a live app paints paper chrome and vice versa.\n */\nexport const appConfigQueryKey = (appId: string | undefined) =>\n [\"agg\", \"app-config\", appId ?? NO_APP_SCOPE] as const;\n\nexport interface UseAppConfigResult {\n prophetxExecutionMode?: \"clearinghouse\" | \"direct\";\n novigExecutionMode?: \"clearinghouse\" | \"direct\";\n disabledVenues: AppClientConfigResponse[\"disabledVenues\"];\n disabledCategoryPresets: AppClientConfigResponse[\"disabledCategoryPresets\"];\n earlyAccessEnabled: AppClientConfigResponse[\"earlyAccessEnabled\"];\n authOptions: AppClientConfigResponse[\"authOptions\"];\n /**\n * Server-owned paper/live mode. `undefined` until `/app/config` resolves —\n * deliberately NOT defaulted here, so callers can tell \"not loaded yet\"\n * apart from \"the server said live\". Resolve it via\n * `useResolvedExecutionMode`, not by reading this directly.\n */\n tradingMode: AppClientConfigResponse[\"tradingMode\"] | undefined;\n /** One-time paper grant in dollars; `undefined` until config resolves. */\n paperStartingBalance: number | undefined;\n isLoading: boolean;\n error: unknown;\n}\n\n/**\n * Fetch the current App's UI config (disabled venues, category presets, and\n * the server-owned paper/live mode).\n *\n * Cadence is deliberately the 5 minutes this hook has always used. Execution\n * settings can change at runtime; stale cached settings affect presentation,\n * while the server remains authoritative: the API resolves mode from the App on every request\n * (`resolveTradingMode`), so a client that still believes the old value\n * renders the wrong chrome but cannot execute in the wrong mode or spend real\n * funds. That does not justify polling a partner's app every minute.\n *\n * A bounded `refetchInterval` is still worth having — without one, a tab left\n * open on a single screen never learns about a flip at all — but it matches\n * `staleTime` rather than undercutting it.\n *\n * `refetchOnWindowFocus`/`refetchOnReconnect` are deliberately left at the\n * host's defaults. Forcing `\"always\"` here would override a partner's own\n * `QueryClient` settings (the demo sets `refetchOnWindowFocus: false`), which\n * is not this hook's call to make.\n */\nexport function useAppConfig(): UseAppConfigResult {\n const client = useAggClient();\n\n const query = useQuery<AppClientConfigResponse>({\n queryKey: appConfigQueryKey(client.appId),\n queryFn: () => client.getAppConfig(),\n staleTime: FIVE_MINUTES,\n // Skipped entirely while the tab is unfocused — query-core only fires the\n // interval when `refetchIntervalInBackground` is set or the window is\n // focused — so a background tab costs nothing.\n refetchInterval: FIVE_MINUTES,\n });\n\n return toAppConfigResult({\n data: query.data,\n isLoading: query.isLoading,\n error: query.error,\n });\n}\n\n/**\n * Read the current App's UI config from the React Query cache without starting a fetch.\n * Use this in surfaces that open after config has already been loaded by a parent screen.\n */\nexport function useCachedAppConfig(): UseAppConfigResult {\n const queryClient = useQueryClient();\n // Optional, not `useAggClient()`: this hook must keep working under a bare\n // <AggUiProvider> with no client, where it simply finds nothing cached.\n const client = useOptionalAggClient();\n const queryKey = appConfigQueryKey(client?.appId);\n const query = useQuery<AppClientConfigResponse>({\n queryKey,\n enabled: false,\n initialData: () => queryClient.getQueryData<AppClientConfigResponse>(queryKey),\n staleTime: FIVE_MINUTES,\n });\n\n return toAppConfigResult({\n data: query.data,\n isLoading: query.isLoading,\n error: query.error,\n });\n}\n\nconst toAppConfigResult = (query: {\n data?: AppClientConfigResponse;\n isLoading: boolean;\n error: unknown;\n}): UseAppConfigResult => {\n return {\n prophetxExecutionMode: query.data\n ? (query.data.prophetxExecutionMode ?? \"clearinghouse\")\n : undefined,\n novigExecutionMode: query.data ? (query.data.novigExecutionMode ?? \"clearinghouse\") : undefined,\n disabledVenues: query.data?.disabledVenues ?? [],\n disabledCategoryPresets: query.data?.disabledCategoryPresets ?? [],\n earlyAccessEnabled: query.data?.earlyAccessEnabled ?? false,\n authOptions: query.data?.authOptions ?? [],\n tradingMode: query.data?.tradingMode,\n paperStartingBalance: query.data?.paperStartingBalance,\n isLoading: query.isLoading,\n error: query.error,\n };\n};\n","import { useMemo, type ReactNode } from \"react\";\nimport { useAppConfig } from \"../../use-app-config\";\nimport { AggExecutionModeContext } from \"./contexts\";\n\n/**\n * Resolves app-level paper/live mode once, from `/app/config`, and publishes\n * it to every surface below.\n *\n * Mounted inside `AggProvider`, where a client and a QueryClient are\n * guaranteed. Deliberately a provider rather than a hook each surface calls:\n * a surface calling `useAppConfig` directly would hard-require an\n * `<AggProvider>` ancestor, breaking components that legitimately render\n * under a bare `<AggUiProvider>` — Storybook stories, unit tests, and\n * partners composing pieces by hand.\n */\nexport function AggExecutionModeProvider({ children }: { children: ReactNode }): React.JSX.Element {\n const { tradingMode, paperStartingBalance, isLoading } = useAppConfig();\n\n const value = useMemo(\n () => ({ tradingMode, paperStartingBalance, isLoading }),\n [tradingMode, paperStartingBalance, isLoading],\n );\n\n return (\n <AggExecutionModeContext.Provider value={value}>{children}</AggExecutionModeContext.Provider>\n );\n}\n","import { createContext, useCallback, useContext, useRef, type ReactNode } from \"react\";\n\nconst STALENESS_THRESHOLD_MS = 5 * 60 * 1000; // 5 minutes\nconst MAX_INITIAL_PAGES = 10;\n\nexport type EventListStateSnapshot = {\n /** Category tab selected in HomePage */\n categoryTab: string | null;\n /** Venue/provider tab selected in EventList */\n venueTab: string | null;\n /** Scroll offset (pixels from top of document) */\n scrollY: number;\n /** Number of infinite query pages that were loaded */\n loadedPageCount: number;\n /** Timestamp when state was captured */\n capturedAt: number;\n};\n\nexport type EventListStateContextValue = {\n /** Store a snapshot of the current list state (called before navigating away) */\n capture: (state: Omit<EventListStateSnapshot, \"capturedAt\">) => void;\n /** Return the stored snapshot and clear it (one-time read). Returns null if no snapshot or stale. */\n consume: () => EventListStateSnapshot | null;\n};\n\nconst EventListStateContext = createContext<EventListStateContextValue | null>(null);\n\nexport function EventListStateProvider({ children }: { children: ReactNode }): React.JSX.Element {\n const snapshotRef = useRef<EventListStateSnapshot | null>(null);\n\n const capture = useCallback((state: Omit<EventListStateSnapshot, \"capturedAt\">) => {\n snapshotRef.current = {\n ...state,\n loadedPageCount: Math.min(state.loadedPageCount, MAX_INITIAL_PAGES),\n capturedAt: Date.now(),\n };\n }, []);\n\n const consume = useCallback((): EventListStateSnapshot | null => {\n const snapshot = snapshotRef.current;\n snapshotRef.current = null;\n\n if (!snapshot) return null;\n\n const age = Date.now() - snapshot.capturedAt;\n if (age > STALENESS_THRESHOLD_MS) return null;\n\n return snapshot;\n }, []);\n\n const value = useRef<EventListStateContextValue>({ capture, consume });\n value.current.capture = capture;\n value.current.consume = consume;\n\n // Stable reference to avoid re-renders\n const stableValue = useRef<EventListStateContextValue>({\n capture: (...args) => value.current.capture(...args),\n consume: () => value.current.consume(),\n }).current;\n\n return (\n <EventListStateContext.Provider value={stableValue}>{children}</EventListStateContext.Provider>\n );\n}\n\nexport function useEventListState(): EventListStateContextValue {\n const context = useContext(EventListStateContext);\n\n if (!context) {\n throw new Error(\"useEventListState must be used within an <AggProvider>\");\n }\n\n return context;\n}\n","import type { ChartTimeRange } from \"./types\";\n\nexport const DEFAULT_AGG_ROOT_CLASS_NAME = \"agg-root\";\n\nexport const CHART_TIME_RANGES: ChartTimeRange[] = [\"1H\", \"6H\", \"1D\", \"1W\", \"1M\", \"ALL\"];\n","import type { AggUiGeneralConfig, AggUiPersistedConfig, ChartTimeRange, ThemeMode } from \"./types\";\nimport { CHART_TIME_RANGES } from \"./constants\";\n\nconst STORAGE_KEY = \"agg_sdk_ui\";\n\nconst isBrowser = (): boolean => typeof window !== \"undefined\" && \"localStorage\" in window;\n\nconst normalizeTheme = (value: unknown): ThemeMode | undefined => {\n if (value === \"light\" || value === \"dark\") {\n return value;\n }\n return undefined;\n};\n\nconst normalizeChartTimeRange = (value: unknown): ChartTimeRange | undefined => {\n if (typeof value === \"string\" && CHART_TIME_RANGES.includes(value as ChartTimeRange)) {\n return value as ChartTimeRange;\n }\n return undefined;\n};\n\nexport const loadPersistedConfig = (): AggUiPersistedConfig => {\n if (!isBrowser()) return {};\n try {\n const raw = window.localStorage.getItem(STORAGE_KEY);\n if (!raw) return {};\n const parsed = JSON.parse(raw) as AggUiPersistedConfig;\n const locale = typeof parsed.general?.locale === \"string\" ? parsed.general.locale : undefined;\n const theme = normalizeTheme(parsed.general?.theme);\n const selectedChartTimeRange = normalizeChartTimeRange(parsed.chart?.selectedChartTimeRange);\n\n const result: AggUiPersistedConfig = {};\n\n if (locale || theme) {\n result.general = { locale, theme };\n }\n\n if (selectedChartTimeRange) {\n result.chart = { selectedChartTimeRange };\n }\n\n return result;\n } catch {\n return {};\n }\n};\n\nexport interface PersistConfigPayload {\n locale: AggUiGeneralConfig[\"locale\"];\n theme: AggUiGeneralConfig[\"theme\"];\n selectedChartTimeRange?: ChartTimeRange;\n}\n\nexport const persistConfig = (config: PersistConfigPayload): void => {\n if (!isBrowser()) return;\n const theme = normalizeTheme(config.theme);\n const selectedChartTimeRange = normalizeChartTimeRange(config.selectedChartTimeRange);\n const payload: AggUiPersistedConfig = {\n general: {\n locale: config.locale,\n theme,\n },\n ...(selectedChartTimeRange ? { chart: { selectedChartTimeRange } } : {}),\n };\n try {\n window.localStorage.setItem(STORAGE_KEY, JSON.stringify(payload));\n } catch {\n // ignore storage errors\n }\n};\n","import type { ThemeMode } from \"./types\";\n\nexport const applyThemeToDocument = (theme: ThemeMode): void => {\n if (typeof document === \"undefined\") return;\n const isDark = theme === \"dark\";\n\n // Ancestor-based selectors (.dark .agg-root)\n document.documentElement.dataset.aggTheme = theme;\n document.documentElement.classList.toggle(\"dark\", isDark);\n document.documentElement.classList.toggle(\"agg-dark\", isDark);\n document.documentElement.classList.toggle(\"light\", !isDark);\n\n // Self-based selectors (.agg-root.dark, .agg-root[data-agg-theme=\"dark\"])\n const aggRoots = document.querySelectorAll<HTMLElement>(\".agg-root\");\n aggRoots.forEach((rootElement) => {\n rootElement.dataset.aggTheme = theme;\n rootElement.classList.toggle(\"dark\", isDark);\n rootElement.classList.toggle(\"agg-dark\", isDark);\n rootElement.classList.toggle(\"light\", !isDark);\n });\n};\n","import {\n MarketStatus,\n type VenueEventWithMarkets,\n type VenueMarket,\n type VenueMarketOutcome,\n} from \"@agg-build/sdk\";\nimport { createContext, useCallback, useContext, useMemo, useReducer, useRef } from \"react\";\n\n// ── Trading state types ──\n\nexport type TradingStateKind =\n | \"open\"\n | \"closed\"\n | \"resolved\"\n | \"paused\"\n | \"unopened\"\n | \"unavailable\";\n\nexport type TradingStateBase = {\n kind: TradingStateKind;\n status: MarketStatus | null;\n isOpen: boolean;\n isTradingDisabled: boolean;\n startsAt: string | null;\n endsAt: string | null;\n resolvesAt: string | null;\n winningOutcome: VenueMarketOutcome | null;\n};\n\nexport type MarketTradingState = TradingStateBase & {\n market: VenueMarket | null;\n};\n\nexport type EventTradingState = TradingStateBase & {\n displayMarkets: VenueMarket[];\n tradableMarkets: VenueMarket[];\n marketStates: Array<{ market: VenueMarket; state: MarketTradingState }>;\n primaryMarket: VenueMarket | null;\n};\n\n// ── Order eligibility ──\n\nexport type OrderEligibilityReason =\n | \"eligible\"\n | \"no_event_selected\"\n | \"no_market_selected\"\n | \"no_outcome_selected\"\n | \"event_resolved\"\n | \"event_closed\"\n | \"event_paused\"\n | \"event_unopened\"\n | \"event_unavailable\"\n | \"market_resolved\"\n | \"market_closed\"\n | \"market_paused\"\n | \"market_unopened\"\n | \"market_unavailable\";\n\nexport type OrderEligibility = {\n canPlaceOrder: boolean;\n reason: OrderEligibilityReason;\n};\n\n// ── Trading state helpers ──\n\nconst OPEN_TRADING_STATE: TradingStateBase = {\n kind: \"open\",\n status: MarketStatus.open,\n isOpen: true,\n isTradingDisabled: false,\n startsAt: null,\n endsAt: null,\n resolvesAt: null,\n winningOutcome: null,\n};\n\nexport const resolveTradingStateKind = (\n status?: MarketStatus | null,\n): Exclude<TradingStateKind, \"unavailable\"> => {\n if (!status || status === MarketStatus.open) return \"open\";\n if (status === MarketStatus.resolved) return \"resolved\";\n if (status === MarketStatus.paused) return \"paused\";\n if (status === MarketStatus.unopened) return \"unopened\";\n return \"closed\";\n};\n\nexport const resolveMarketWinningOutcome = (\n market?: VenueMarket | null,\n): VenueMarketOutcome | null => {\n if (!market) return null;\n\n const localWinningOutcome =\n market.venueMarketOutcomes.find((outcome) => outcome.winner === true) ?? null;\n if (localWinningOutcome) return localWinningOutcome;\n\n const matchedVenueMarkets = market.matchedVenueMarkets ?? [];\n if (!matchedVenueMarkets.length) return null;\n\n for (const outcome of market.venueMarketOutcomes) {\n const matchedRefs = outcome.matchedVenueMarketOutcomes ?? [];\n for (const ref of matchedRefs) {\n const matchedMarket = matchedVenueMarkets.find((item) => item.id === ref.venueMarketId);\n if (!matchedMarket) continue;\n\n const matchedOutcome = matchedMarket.venueMarketOutcomes?.find(\n (item) => item.id === ref.venueMarketOutcomeId,\n );\n if (matchedOutcome?.winner === true) {\n return outcome;\n }\n }\n }\n\n return null;\n};\n\nconst AFFIRMATIVE_WINNER_LABELS = new Set([\"yes\", \"up\", \"buy\", \"long\", \"true\"]);\n\nconst isAffirmativeWinnerLabel = (label: string | null | undefined): boolean => {\n if (!label) return false;\n return AFFIRMATIVE_WINNER_LABELS.has(label.trim().toLowerCase());\n};\n\nconst resolvePreferredWinningMarket = (\n marketStates: Array<{ market: VenueMarket; state: MarketTradingState }>,\n): VenueMarket | null => {\n const marketWithAffirmativeWinner = marketStates.find((item) =>\n isAffirmativeWinnerLabel(item.state.winningOutcome?.label),\n );\n\n if (marketWithAffirmativeWinner) {\n return marketWithAffirmativeWinner.market;\n }\n\n return marketStates.find((item) => item.state.winningOutcome)?.market ?? null;\n};\n\nexport const resolveMarketTradingState = (market?: VenueMarket | null): MarketTradingState => {\n if (!market) {\n return {\n ...OPEN_TRADING_STATE,\n kind: \"unavailable\",\n status: null,\n isOpen: false,\n isTradingDisabled: true,\n market: null,\n };\n }\n\n const kind = resolveTradingStateKind(market.status);\n\n return {\n kind,\n status: market.status ?? (kind === \"open\" ? MarketStatus.open : null),\n isOpen: kind === \"open\",\n isTradingDisabled: kind !== \"open\",\n startsAt: market.startDate ?? null,\n endsAt: market.endDate ?? null,\n resolvesAt: market.resolutionDate ?? null,\n market,\n winningOutcome: resolveMarketWinningOutcome(market),\n };\n};\n\nconst deriveEventTradingStateKind = (marketStates: MarketTradingState[]): TradingStateKind => {\n if (marketStates.length === 0) return \"unavailable\";\n if (marketStates.some((marketState) => marketState.kind === \"open\")) return \"open\";\n if (marketStates.every((marketState) => marketState.kind === \"resolved\")) return \"resolved\";\n if (marketStates.every((marketState) => marketState.kind === \"paused\")) return \"paused\";\n if (marketStates.every((marketState) => marketState.kind === \"unopened\")) return \"unopened\";\n return \"closed\";\n};\n\nconst resolveEventStateStatus = (\n event: VenueEventWithMarkets,\n kind: TradingStateKind,\n): MarketStatus | null => {\n if (event.status) return event.status;\n if (kind === \"unavailable\") return null;\n if (kind === \"open\") return MarketStatus.open;\n if (kind === \"resolved\") return MarketStatus.resolved;\n if (kind === \"paused\") return MarketStatus.paused;\n if (kind === \"unopened\") return MarketStatus.unopened;\n return MarketStatus.closed;\n};\n\nconst resolveEventWinningOutcome = (\n marketStates: Array<{ market: VenueMarket; state: MarketTradingState }>,\n preferredMarket: VenueMarket | null,\n): VenueMarketOutcome | null => {\n if (preferredMarket) {\n return (\n marketStates.find((item) => item.market.id === preferredMarket.id)?.state.winningOutcome ??\n null\n );\n }\n\n return marketStates.find((item) => item.state.winningOutcome)?.state.winningOutcome ?? null;\n};\n\nexport const resolveEventTradingState = (\n event?: VenueEventWithMarkets | null,\n): EventTradingState => {\n if (!event?.venueMarkets.length) {\n return {\n ...OPEN_TRADING_STATE,\n kind: \"unavailable\",\n status: event?.status ?? null,\n isOpen: false,\n isTradingDisabled: true,\n startsAt: event?.startDate ?? null,\n endsAt: event?.endDate ?? null,\n displayMarkets: [],\n tradableMarkets: [],\n marketStates: [],\n primaryMarket: null,\n };\n }\n\n const marketStates = event.venueMarkets.map((market) => ({\n market,\n state: resolveMarketTradingState(market),\n }));\n const derivedKind = deriveEventTradingStateKind(marketStates.map((item) => item.state));\n const explicitKind = event.status ? resolveTradingStateKind(event.status) : null;\n const kind =\n explicitKind && (explicitKind !== \"open\" || derivedKind === \"open\")\n ? explicitKind\n : derivedKind;\n const preferredWinningMarket = resolvePreferredWinningMarket(marketStates);\n const tradableMarkets = marketStates\n .filter((item) => item.state.isOpen)\n .map((item) => item.market);\n const displayMarkets = kind === \"open\" ? tradableMarkets : event.venueMarkets;\n const primaryMarket =\n (kind !== \"open\" ? preferredWinningMarket : null) ??\n displayMarkets[0] ??\n tradableMarkets[0] ??\n event.venueMarkets[0] ??\n null;\n\n return {\n kind,\n status: resolveEventStateStatus(event, kind),\n isOpen: kind === \"open\",\n isTradingDisabled: kind !== \"open\",\n startsAt: event.startDate ?? primaryMarket?.startDate ?? null,\n endsAt: event.endDate ?? primaryMarket?.endDate ?? null,\n resolvesAt:\n marketStates.find((item) => item.state.resolvesAt)?.state.resolvesAt ??\n primaryMarket?.resolutionDate ??\n null,\n winningOutcome: resolveEventWinningOutcome(marketStates, preferredWinningMarket),\n displayMarkets,\n tradableMarkets,\n marketStates,\n primaryMarket,\n };\n};\n\n// ── Order eligibility helpers ──\n\nconst toEventReason = (kind: TradingStateKind): OrderEligibilityReason => {\n const mapped: Record<Exclude<TradingStateKind, \"open\">, OrderEligibilityReason> = {\n resolved: \"event_resolved\",\n closed: \"event_closed\",\n paused: \"event_paused\",\n unopened: \"event_unopened\",\n unavailable: \"event_unavailable\",\n };\n return mapped[kind as Exclude<TradingStateKind, \"open\">] ?? \"event_unavailable\";\n};\n\nconst toMarketReason = (kind: TradingStateKind): OrderEligibilityReason => {\n const mapped: Record<Exclude<TradingStateKind, \"open\">, OrderEligibilityReason> = {\n resolved: \"market_resolved\",\n closed: \"market_closed\",\n paused: \"market_paused\",\n unopened: \"market_unopened\",\n unavailable: \"market_unavailable\",\n };\n return mapped[kind as Exclude<TradingStateKind, \"open\">] ?? \"market_unavailable\";\n};\n\nexport const resolveOrderEligibility = (params: {\n event: VenueEventWithMarkets | null;\n market: VenueMarket | null;\n outcome: VenueMarketOutcome | null;\n eventTradingState?: EventTradingState;\n}): OrderEligibility => {\n if (!params.event) return { canPlaceOrder: false, reason: \"no_event_selected\" };\n if (!params.market) return { canPlaceOrder: false, reason: \"no_market_selected\" };\n if (!params.outcome) return { canPlaceOrder: false, reason: \"no_outcome_selected\" };\n\n const eventState = params.eventTradingState ?? resolveEventTradingState(params.event);\n if (eventState.isTradingDisabled) {\n return { canPlaceOrder: false, reason: toEventReason(eventState.kind) };\n }\n\n const marketState = resolveMarketTradingState(params.market);\n if (marketState.isTradingDisabled) {\n return { canPlaceOrder: false, reason: toMarketReason(marketState.kind) };\n }\n\n return { canPlaceOrder: true, reason: \"eligible\" };\n};\n\n// ── Selection helpers ──\n\nexport function resolveDefaultMarket(event: VenueEventWithMarkets | null): VenueMarket | null {\n if (!event?.venueMarkets.length) return null;\n const tradableMarket = event.venueMarkets.find(\n (market) => resolveMarketTradingState(market).isOpen,\n );\n if (tradableMarket) return tradableMarket;\n\n const marketStates = event.venueMarkets.map((market) => ({\n market,\n state: resolveMarketTradingState(market),\n }));\n const preferredWinningMarket = resolvePreferredWinningMarket(marketStates);\n\n return preferredWinningMarket ?? event.venueMarkets[0] ?? null;\n}\n\nexport { resolveDefaultMarket as resolveDefaultTradingMarket };\n\nexport function resolveDefaultOutcome(market: VenueMarket | null): VenueMarketOutcome | null {\n const yesOutcome = market?.venueMarketOutcomes.find((o) => o?.label?.toLowerCase() === \"yes\");\n if (yesOutcome) return yesOutcome;\n return market?.venueMarketOutcomes?.[0] ?? null;\n}\n\nexport function findMarketById(\n event: VenueEventWithMarkets | null,\n marketId: string,\n): VenueMarket | null {\n if (!event) return null;\n return event.venueMarkets.find((m) => m.id === marketId) ?? null;\n}\n\nexport function findOutcomeById(\n market: VenueMarket | null,\n outcomeId: string,\n): VenueMarketOutcome | null {\n if (!market) return null;\n return market.venueMarketOutcomes.find((o) => o.id === outcomeId) ?? null;\n}\n\nexport function findOutcomeAcrossMarkets(\n event: VenueEventWithMarkets | null,\n outcomeId: string,\n): { market: VenueMarket; outcome: VenueMarketOutcome } | null {\n if (!event) return null;\n for (const market of event.venueMarkets) {\n const outcome = market.venueMarketOutcomes.find((o) => o.id === outcomeId);\n if (outcome) return { market, outcome };\n }\n return null;\n}\n\n// ── State ──\n\n/**\n * Active trade side. Modeled as a frozen const-object so callers can use\n * enum-style access (`TradeSide.Buy`, `TradeSide.Sell`) while the resulting\n * type is still the plain `\"buy\" | \"sell\"` string union — interoperable\n * everywhere a literal is expected (URL params, JSON payloads, helper\n * function signatures).\n */\nexport const TradeSide = {\n Buy: \"buy\",\n Sell: \"sell\",\n} as const;\nexport type TradeSide = (typeof TradeSide)[keyof typeof TradeSide];\n\nexport interface TradingState {\n event: VenueEventWithMarkets | null;\n market: VenueMarket | null;\n outcome: VenueMarketOutcome | null;\n /**\n * Currently selected buy/sell side. Optional in shape (older fixtures and\n * snapshots may omit it) — readers should treat `undefined` as `Buy`.\n */\n tradeSide?: TradeSide;\n}\n\n// ── Actions ──\n\nexport type TradingAction =\n | { type: \"INITIALIZE_EVENT\"; event: VenueEventWithMarkets | null }\n | { type: \"SYNC_EVENT\"; event: VenueEventWithMarkets }\n | { type: \"SELECT_MARKET\"; marketId: string; market?: VenueMarket }\n | { type: \"SELECT_OUTCOME\"; outcomeId: string }\n | { type: \"SELECT_MARKET_AND_OUTCOME\"; marketId: string; outcomeId: string }\n | { type: \"SET_TRADE_SIDE\"; tradeSide: TradeSide };\n\n// ── Reducer ──\n\nexport function tradingReducer(state: TradingState, action: TradingAction): TradingState {\n switch (action.type) {\n case \"INITIALIZE_EVENT\": {\n // Always snap the trade side back to Buy when an event is (re)initialised\n // — including the `null` case (user navigating to the home view). This\n // ensures the home grid and any newly opened event start in Buy mode\n // regardless of where the side was left previously.\n if (!action.event) {\n return { event: null, market: null, outcome: null, tradeSide: TradeSide.Buy };\n }\n return {\n event: action.event,\n market: null,\n outcome: null,\n tradeSide: TradeSide.Buy,\n };\n }\n\n case \"SYNC_EVENT\": {\n const previousMarketId = state.market?.id ?? null;\n const previousOutcomeId = state.outcome?.id ?? null;\n const syncedMarket = previousMarketId ? findMarketById(action.event, previousMarketId) : null;\n\n if (!syncedMarket || resolveMarketTradingState(syncedMarket).isTradingDisabled) {\n return {\n event: action.event,\n market: null,\n outcome: null,\n tradeSide: state.tradeSide ?? TradeSide.Buy,\n };\n }\n\n const syncedOutcome = previousOutcomeId\n ? findOutcomeById(syncedMarket, previousOutcomeId)\n : null;\n\n return {\n event: action.event,\n market: syncedMarket,\n outcome: syncedOutcome,\n tradeSide: state.tradeSide ?? TradeSide.Buy,\n };\n }\n\n case \"SET_TRADE_SIDE\": {\n if ((state.tradeSide ?? TradeSide.Buy) === action.tradeSide) return state;\n return { ...state, tradeSide: action.tradeSide };\n }\n\n case \"SELECT_MARKET\": {\n const market = findMarketById(state.event, action.marketId) ?? action.market ?? null;\n if (!market) return state;\n if (resolveMarketTradingState(market).kind === \"resolved\") return state;\n return {\n ...state,\n market,\n outcome: resolveDefaultOutcome(market),\n };\n }\n\n case \"SELECT_OUTCOME\": {\n if (state.outcome?.id === action.outcomeId) {\n return state;\n }\n\n // Fast path: check current market first\n if (state.market) {\n const outcomeInCurrentMarket = findOutcomeById(state.market, action.outcomeId);\n if (outcomeInCurrentMarket) {\n if (resolveMarketTradingState(state.market).kind === \"resolved\") {\n return state;\n }\n return { ...state, outcome: outcomeInCurrentMarket };\n }\n }\n\n // Cross-market search — block jump to non-tradable markets\n const found = findOutcomeAcrossMarkets(state.event, action.outcomeId);\n if (!found) return state;\n\n const targetMarketState = resolveMarketTradingState(found.market);\n if (targetMarketState.isTradingDisabled) return state;\n\n return {\n ...state,\n market: found.market,\n outcome: found.outcome,\n };\n }\n\n case \"SELECT_MARKET_AND_OUTCOME\": {\n const market = findMarketById(state.event, action.marketId);\n if (!market) return state;\n if (resolveMarketTradingState(market).kind === \"resolved\") return state;\n\n const outcome = findOutcomeById(market, action.outcomeId);\n if (!outcome) return state;\n\n return { ...state, market, outcome };\n }\n\n default: {\n const _exhaustive: never = action;\n return _exhaustive;\n }\n }\n}\n\nfunction logAction(\n actionType: string,\n payload: unknown,\n prev: TradingState,\n next: TradingState,\n enableLogs: boolean,\n): void {\n if (!enableLogs) return;\n\n console.group(`[EventTrading] ${actionType}`);\n console.log(\"payload\", payload);\n console.log(\"prev\", prev);\n console.log(\"next\", next);\n console.log(\"IDS\", {\n eventId: next.event?.id,\n marketIds: next.event?.venueMarkets.map((m) => m.id),\n outcomeIds: next.event?.venueMarkets.flatMap((m) => m.venueMarketOutcomes.map((o) => o.id)),\n selectedMarketId: next.market?.id,\n selectedOutcomeId: next.outcome?.id,\n });\n console.groupEnd();\n}\n\n// ── Context ──\n\nexport interface EventTradingContextValue {\n selectedEvent: VenueEventWithMarkets | null;\n selectedMarket: VenueMarket | null;\n selectedOutcome: VenueMarketOutcome | null;\n\n selectedEventId: string | null;\n selectedMarketId: string | null;\n selectedOutcomeId: string | null;\n selectedVenue: string | null;\n\n /**\n * Currently selected trade side. Drives `bestAsk` vs `bestBid` selection\n * across all price-display surfaces (home tile, event details, market\n * details, place-order outcome buttons) so flipping Buy/Sell in PlaceOrder\n * is reflected everywhere. Defaults to `\"buy\"`.\n */\n tradeSide: TradeSide;\n setTradeSide: (tradeSide: TradeSide) => void;\n\n initializeFromEvent: (event: VenueEventWithMarkets | null) => void;\n syncEvent: (event: VenueEventWithMarkets) => void;\n selectMarket: (marketId: string, market?: VenueMarket) => void;\n selectOutcome: (outcomeId: string) => void;\n selectMarketAndOutcome: (marketId: string, outcomeId: string) => void;\n}\n\nconst initialState: TradingState = {\n event: null,\n market: null,\n outcome: null,\n tradeSide: TradeSide.Buy,\n};\n\nexport const EventTradingContext = createContext<EventTradingContextValue | undefined>(undefined);\n\nexport const useEventTradingContext = (): EventTradingContextValue | undefined => {\n return useContext(EventTradingContext);\n};\n\ninterface EventTradingProviderProps {\n children: React.ReactNode;\n enableLogs?: boolean;\n}\n\nexport const EventTradingProvider = ({\n children,\n enableLogs = false,\n}: EventTradingProviderProps): React.JSX.Element => {\n const [state, rawDispatch] = useReducer(tradingReducer, initialState);\n const stateRef = useRef(state);\n const pendingAtomicSelectionRef = useRef<{ marketId: string; outcomeId: string } | null>(null);\n stateRef.current = state;\n\n const pendingAtomicSelection = pendingAtomicSelectionRef.current;\n if (\n pendingAtomicSelection &&\n state.market?.id === pendingAtomicSelection.marketId &&\n state.outcome?.id === pendingAtomicSelection.outcomeId\n ) {\n pendingAtomicSelectionRef.current = null;\n }\n\n const dispatch = useCallback(\n (action: TradingAction) => {\n const prev = stateRef.current;\n rawDispatch(action);\n\n // Log after dispatch — next state is computed synchronously by React\n // We re-compute it here for logging only; the real state update is in rawDispatch\n const next = tradingReducer(prev, action);\n logAction(action.type, action, prev, next, enableLogs);\n },\n [enableLogs],\n );\n\n const initializeFromEvent = useCallback(\n (event: VenueEventWithMarkets | null) => dispatch({ type: \"INITIALIZE_EVENT\", event }),\n [dispatch],\n );\n\n const syncEvent = useCallback(\n (event: VenueEventWithMarkets) => dispatch({ type: \"SYNC_EVENT\", event }),\n [dispatch],\n );\n\n const selectMarket = useCallback(\n (marketId: string, market?: VenueMarket) =>\n dispatch({ type: \"SELECT_MARKET\", marketId, market }),\n [dispatch],\n );\n\n const selectOutcome = useCallback(\n (outcomeId: string) => {\n if (stateRef.current.outcome?.id === outcomeId) return;\n if (pendingAtomicSelectionRef.current?.outcomeId === outcomeId) return;\n dispatch({ type: \"SELECT_OUTCOME\", outcomeId });\n },\n [dispatch],\n );\n\n const selectMarketAndOutcome = useCallback(\n (marketId: string, outcomeId: string) => {\n if (stateRef.current.market?.id === marketId && stateRef.current.outcome?.id === outcomeId) {\n return;\n }\n if (\n pendingAtomicSelectionRef.current?.marketId === marketId &&\n pendingAtomicSelectionRef.current?.outcomeId === outcomeId\n ) {\n return;\n }\n pendingAtomicSelectionRef.current = { marketId, outcomeId };\n dispatch({ type: \"SELECT_MARKET_AND_OUTCOME\", marketId, outcomeId });\n },\n [dispatch],\n );\n\n const setTradeSide = useCallback(\n (tradeSide: TradeSide) => dispatch({ type: \"SET_TRADE_SIDE\", tradeSide }),\n [dispatch],\n );\n\n const value = useMemo<EventTradingContextValue>(\n () => ({\n selectedEvent: state.event,\n selectedMarket: state.market,\n selectedOutcome: state.outcome,\n\n selectedEventId: state.event?.id ?? null,\n selectedMarketId: state.market?.id ?? null,\n selectedOutcomeId: state.outcome?.id ?? null,\n selectedVenue: state.market?.venue ?? null,\n\n tradeSide: state.tradeSide ?? TradeSide.Buy,\n setTradeSide,\n\n initializeFromEvent,\n syncEvent,\n selectMarket,\n selectOutcome,\n selectMarketAndOutcome,\n }),\n [\n state,\n initializeFromEvent,\n syncEvent,\n selectMarket,\n selectOutcome,\n selectMarketAndOutcome,\n setTradeSide,\n ],\n );\n\n return <EventTradingContext.Provider value={value}>{children}</EventTradingContext.Provider>;\n};\n","import { useCallback, useEffect, useMemo, useState } from \"react\";\nimport { DEFAULT_AGG_ROOT_CLASS_NAME } from \"../ui-config/constants\";\nimport { loadPersistedConfig, persistConfig } from \"../ui-config/storage\";\nimport { applyThemeToDocument } from \"../ui-config/theme-utils\";\nimport type {\n AggUiConfig,\n ChartTimeRange,\n SdkUiProviderProps,\n VenueEventWithMarkets,\n} from \"../ui-config/types\";\nimport { mergeAggUiConfig } from \"../ui-config/utils\";\nimport { AggLabelsContext, AggUiContext } from \"./contexts\";\nimport { EventTradingProvider } from \"./event-trading-context\";\n\nlet hasWarnedMissingAggStyles = false;\n\nconst warnIfAggStylesAreMissing = (): void => {\n if (hasWarnedMissingAggStyles) return;\n if (typeof window === \"undefined\" || typeof document === \"undefined\") return;\n const rootElement = document.querySelector<HTMLElement>(`.${DEFAULT_AGG_ROOT_CLASS_NAME}`);\n if (!rootElement) return;\n\n const computedStyle = window.getComputedStyle(rootElement);\n const hasSemanticColorToken =\n computedStyle.getPropertyValue(\"--agg-color-primary\").trim().length > 0;\n const hasTailwindColorToken =\n computedStyle.getPropertyValue(\"--color-agg-primary\").trim().length > 0;\n const hasTailwindRadiusToken =\n computedStyle.getPropertyValue(\"--radius-agg-md\").trim().length > 0;\n\n if (hasSemanticColorToken && hasTailwindColorToken && hasTailwindRadiusToken) {\n return;\n }\n\n hasWarnedMissingAggStyles = true;\n\n console.warn(\n '[agg] Missing AGG UI styles. Import \"@agg-build/ui/styles.css\" once at your app entrypoint so agg token utilities resolve correctly.',\n );\n};\n\nfunction logConfig(config: AggUiConfig, enableLogs: boolean): void {\n if (!enableLogs) return;\n\n console.group(`[AggUiProvider]`);\n console.log(\"config\", config);\n console.groupEnd();\n}\n\ntype SearchSelectState = Pick<AggUiConfig[\"search\"], \"result\" | \"isShowingAllResults\"> & {\n value: string;\n};\n\nexport const getSearchStateAfterSelect = (\n selectedEvent: VenueEventWithMarkets,\n): SearchSelectState => {\n return {\n value: \"\",\n result: selectedEvent,\n isShowingAllResults: false,\n };\n};\n\nexport const AggUiProvider = ({ config, children }: SdkUiProviderProps): React.JSX.Element => {\n const persisted = useMemo(() => loadPersistedConfig(), []);\n const mergedConfig = useMemo(() => mergeAggUiConfig(persisted, config), [persisted, config]);\n const [selectedChartTimeRange, setSelectedChartTimeRange] = useState<ChartTimeRange>(\n mergedConfig.chart.selectedChartTimeRange,\n );\n\n const handleSetSelectedChartTimeRange = useCallback((range: ChartTimeRange): void => {\n setSelectedChartTimeRange(range);\n }, []);\n\n const [searchValue, setSearchValue] = useState(mergedConfig.search.value);\n const [searchResult, setSearchResult] = useState(mergedConfig.search.result);\n const [isShowingAllResults, setIsShowingAllResults] = useState(\n mergedConfig.search.isShowingAllResults,\n );\n\n useEffect(() => {\n setSearchValue(mergedConfig.search.value);\n }, [mergedConfig.search.value]);\n\n useEffect(() => {\n setSearchResult(mergedConfig.search.result);\n }, [mergedConfig.search.result]);\n\n useEffect(() => {\n setIsShowingAllResults(mergedConfig.search.isShowingAllResults);\n }, [mergedConfig.search.isShowingAllResults]);\n\n const handleSearchChange = useCallback(\n (value: string): void => {\n setSearchValue(value);\n setSearchResult(null);\n setIsShowingAllResults(false);\n mergedConfig.search.onChange?.(value);\n },\n [mergedConfig.search],\n );\n\n const handleSearchSelect = useCallback(\n (value: VenueEventWithMarkets): void => {\n const nextSearchState = getSearchStateAfterSelect(value);\n setSearchValue(nextSearchState.value);\n setSearchResult(nextSearchState.result);\n setIsShowingAllResults(nextSearchState.isShowingAllResults);\n mergedConfig.search.onSelect?.(value);\n },\n [mergedConfig.search],\n );\n\n const handleOpenResults = useCallback((): void => {\n setIsShowingAllResults(true);\n mergedConfig.search.openResults?.();\n }, [mergedConfig.search]);\n\n const handleCloseResults = useCallback((): void => {\n setIsShowingAllResults(false);\n mergedConfig.search.closeResults?.();\n }, [mergedConfig.search]);\n\n const resolvedConfig = useMemo(() => {\n return {\n ...mergedConfig,\n chart: {\n ...mergedConfig.chart,\n selectedChartTimeRange,\n setSelectedChartTimeRange: handleSetSelectedChartTimeRange,\n },\n search: {\n ...mergedConfig.search,\n value: searchValue,\n onChange: handleSearchChange,\n onSelect: handleSearchSelect,\n openResults: handleOpenResults,\n closeResults: handleCloseResults,\n result: searchResult,\n isShowingAllResults,\n },\n };\n }, [\n handleCloseResults,\n handleOpenResults,\n handleSearchChange,\n handleSearchSelect,\n handleSetSelectedChartTimeRange,\n isShowingAllResults,\n mergedConfig,\n searchResult,\n searchValue,\n selectedChartTimeRange,\n ]);\n\n useEffect(() => {\n persistConfig({\n locale: resolvedConfig.general.locale,\n theme: resolvedConfig.general.theme,\n selectedChartTimeRange: resolvedConfig.chart.selectedChartTimeRange,\n });\n }, [\n resolvedConfig.general.locale,\n resolvedConfig.general.theme,\n resolvedConfig.chart.selectedChartTimeRange,\n ]);\n\n useEffect(() => {\n applyThemeToDocument(resolvedConfig.general.theme);\n }, [resolvedConfig.general.theme]);\n\n useEffect(() => {\n warnIfAggStylesAreMissing();\n }, []);\n\n const resolvedRootClassName = [\n DEFAULT_AGG_ROOT_CLASS_NAME,\n resolvedConfig.general.theme === \"dark\" ? \"dark\" : null,\n resolvedConfig.general.rootClassName,\n ]\n .filter(Boolean)\n .join(\" \");\n\n logConfig(resolvedConfig, resolvedConfig.enableLogs);\n\n return (\n <AggLabelsContext.Provider value={resolvedConfig.general.labels}>\n <AggUiContext.Provider value={resolvedConfig}>\n <EventTradingProvider enableLogs={resolvedConfig.enableLogs}>\n <div\n className={resolvedRootClassName}\n data-agg-animations={resolvedConfig.features.enableAnimations ? \"true\" : \"false\"}\n data-agg-gradients={resolvedConfig.features.enableGradients ? \"true\" : \"false\"}\n data-agg-theme={resolvedConfig.general.theme}\n >\n {children}\n </div>\n </EventTradingProvider>\n </AggUiContext.Provider>\n </AggLabelsContext.Provider>\n );\n};\n","import { useQueryClient } from \"@tanstack/react-query\";\nimport { AggAuthProvider } from \"./auth-provider\";\nimport { AggBalanceProvider } from \"./balance-provider\";\nimport { AggClientProvider } from \"./client-provider\";\nimport { AggExecutionModeProvider } from \"./execution-mode-provider\";\nimport { EventListStateProvider } from \"./event-list-state-context\";\nimport { AggWebSocketProvider } from \"./ws-provider\";\nimport type { AggProviderProps } from \"./types\";\nimport { AggUiProvider } from \"./ui-provider\";\n\nlet hasWarnedMissingQueryClient = false;\n\nfunction useQueryClientCheck(): void {\n try {\n useQueryClient();\n } catch {\n if (!hasWarnedMissingQueryClient) {\n hasWarnedMissingQueryClient = true;\n console.error(\n \"[agg] AggProvider requires a QueryClientProvider ancestor. \" +\n \"Wrap AggProvider in a <QueryClientProvider client={queryClient}>.\",\n );\n }\n }\n}\n\nexport const AggProvider = ({ client, config, children }: AggProviderProps): React.JSX.Element => {\n useQueryClientCheck();\n\n if (!client) {\n throw new Error(\n \"AggProvider requires a valid AggClient instance. \" +\n \"Create one with createAggClient() and pass it via the 'client' prop.\",\n );\n }\n\n return (\n <AggClientProvider client={client}>\n <AggUiProvider config={config}>\n {/* Above the balance provider: paper/live decides which balances to\n fetch, so the mode must be resolved before that query is keyed. */}\n <AggExecutionModeProvider>\n <EventListStateProvider>\n <AggWebSocketProvider>\n <AggAuthProvider>\n <AggBalanceProvider>{children}</AggBalanceProvider>\n </AggAuthProvider>\n </AggWebSocketProvider>\n </EventListStateProvider>\n </AggExecutionModeProvider>\n </AggUiProvider>\n </AggClientProvider>\n );\n};\n","import { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport type {\n ExecuteManagedParams,\n ExecuteManagedResponse,\n SmartRouteResponse,\n} from \"@agg-build/sdk\";\nimport { useAggClient } from \"../core/provider\";\nimport { executionKeys } from \"./query-keys\";\nimport { invalidateBalanceQueries } from \"./balance-invalidation\";\n\nexport interface UseExecuteManagedOptions {\n onSuccess?: (data: ExecuteManagedResponse) => void;\n onError?: (error: Error) => void;\n}\n\n/**\n * Mutation hook for executing a previously quoted managed trade.\n * On success, invalidates orders, positions, and balances queries.\n */\nexport function useExecuteManaged(options?: UseExecuteManagedOptions) {\n const client = useAggClient();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: (params: ExecuteManagedParams) => client.executeManaged(params),\n onSuccess: (data) => {\n // The progress surface retains the accepted execution. Remove its consumed\n // ticket from every matching route cache before the order form reappears.\n queryClient.setQueriesData<SmartRouteResponse>({ queryKey: [\"smart-route\"] }, (route) => {\n if (!route) return route;\n const consumedPrimary = route.quoteId === data.quoteId;\n const consumedComparison = route.venueSoloQuotes?.some(\n (quote) => quote.quoteId === data.quoteId,\n );\n if (!consumedPrimary && !consumedComparison) return route;\n return {\n ...route,\n ...(consumedPrimary ? { quoteId: \"\" } : {}),\n ...(consumedComparison\n ? {\n venueSoloQuotes: route.venueSoloQuotes!.map((quote) =>\n quote.quoteId === data.quoteId ? { ...quote, quoteId: \"\" } : quote,\n ),\n }\n : {}),\n };\n });\n queryClient.invalidateQueries({ queryKey: executionKeys.ordersPrefix() });\n queryClient.invalidateQueries({ queryKey: executionKeys.positionsPrefix() });\n invalidateBalanceQueries(queryClient);\n options?.onSuccess?.(data);\n },\n onError: options?.onError,\n });\n}\n","import { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport type { PlaceLimitOrderParams, PlaceLimitOrderResponse } from \"@agg-build/sdk\";\nimport { useAggClient } from \"../core/provider\";\nimport { invalidateBalanceQueries } from \"./balance-invalidation\";\nimport { executionKeys } from \"./query-keys\";\n\nexport interface UsePlaceLimitOrderOptions {\n onSuccess?: (data: PlaceLimitOrderResponse) => void;\n onError?: (error: Error) => void;\n}\n\nexport function usePlaceLimitOrder(options?: UsePlaceLimitOrderOptions) {\n const client = useAggClient();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: (params: PlaceLimitOrderParams) => client.placeLimitOrder(params),\n onSuccess: (data) => {\n queryClient.invalidateQueries({ queryKey: executionKeys.ordersPrefix() });\n queryClient.invalidateQueries({ queryKey: [\"execution-orders\"] });\n queryClient.invalidateQueries({ queryKey: executionKeys.positionsPrefix() });\n invalidateBalanceQueries(queryClient);\n options?.onSuccess?.(data);\n },\n onError: options?.onError,\n });\n}\n","import { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport type { CancelManagedExecutionResponse } from \"@agg-build/sdk\";\nimport { useAggClient } from \"../core/provider\";\nimport {\n invalidateBalanceQueries,\n invalidatePositionQueries,\n invalidateUserActivityQueries,\n} from \"./balance-invalidation\";\nimport { executionKeys } from \"./query-keys\";\n\nexport interface UseCancelManagedOrderOptions {\n onSuccess?: (data: CancelManagedExecutionResponse, orderId: string) => void;\n onError?: (error: Error, orderId: string) => void;\n}\n\nexport function useCancelManagedOrder(options?: UseCancelManagedOrderOptions) {\n const client = useAggClient();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: (orderId: string) => client.cancelManagedOrder(orderId),\n onSuccess: (data, orderId) => {\n queryClient.invalidateQueries({ queryKey: executionKeys.ordersPrefix() });\n queryClient.invalidateQueries({ queryKey: [\"execution-orders\"] });\n invalidatePositionQueries(queryClient);\n invalidateBalanceQueries(queryClient);\n invalidateUserActivityQueries(queryClient);\n options?.onSuccess?.(data, orderId);\n },\n onError: (error, orderId) => {\n options?.onError?.(error, orderId);\n },\n });\n}\n","import { useQuery } from \"@tanstack/react-query\";\nimport type { GetPositionsParams } from \"@agg-build/sdk\";\nimport { useAggClient } from \"../core/provider\";\nimport { executionKeys } from \"./query-keys\";\n\nexport interface UsePositionsOptions extends GetPositionsParams {\n enabled?: boolean;\n}\n\n/**\n * Query hook for fetching user positions grouped by matched market.\n */\nexport function usePositions(options?: UsePositionsOptions) {\n const client = useAggClient();\n const { enabled = true, cursor, limit, status, mode } = options ?? {};\n\n const query = useQuery({\n queryKey: executionKeys.positions(cursor, limit, status, mode),\n queryFn: () => client.getPositions({ cursor, limit, status, ...(mode ? { mode } : {}) }),\n enabled,\n staleTime: 10_000,\n gcTime: 5 * 60_000,\n retry: 1,\n });\n\n return {\n ...query,\n positions: query.data?.data,\n nextCursor: query.data?.nextCursor,\n hasMore: query.data?.hasMore ?? false,\n };\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\";\nimport type {\n ExecutionStatusOrder,\n ExecutionStatusResponse,\n ExecutionStatusStep,\n WsBalanceUpdate,\n WsOrderEvent,\n WsOrderSubmitted,\n} from \"@agg-build/sdk\";\nimport { useAggClient } from \"../core/providers/hooks\";\nimport {\n useOnBalanceUpdate,\n useOnOrderEvent,\n useOnOrderSubmitted,\n} from \"../core/providers/ws-provider\";\n\n// `expired` is included alongside the venue-fill statuses so the HTTP poll\n// fallback recognises orders that the server timed out before the venue\n// ever submitted them. Without this the modal would keep polling indefinitely\n// when the server-side row settled on `expired` but no terminal WS event\n// landed (reconnect, dropped event, or the row was flipped before the WS\n// subscribe completed). Mirrors the WS-side `expired` handling below.\nconst TERMINAL_ORDER_STATUSES = new Set([\n \"filled\",\n \"partial_fill\",\n \"failed\",\n \"cancelled\",\n \"expired\",\n]);\nconst ORDER_POLL_INTERVAL_MS = 5000;\n\nfunction mapOrderStatusToTerminalEvent(\n status: string,\n): ExecutionTerminalOrderEvent[\"event\"] | null {\n if (status === \"filled\") return \"filled\";\n if (status === \"partial_fill\") return \"partial_fill\";\n if (status === \"failed\" || status === \"cancelled\" || status === \"expired\") return \"failed\";\n return null;\n}\n\nexport const mergeTerminalOrderEvents = (\n currentEvents: ExecutionTerminalOrderEvent[],\n incomingEvents: ExecutionTerminalOrderEvent[],\n): ExecutionTerminalOrderEvent[] => {\n const mergedByOrderId = new Map(currentEvents.map((event) => [event.orderId, event]));\n\n for (const incomingEvent of incomingEvents) {\n const currentEvent = mergedByOrderId.get(incomingEvent.orderId);\n if (!currentEvent) {\n mergedByOrderId.set(incomingEvent.orderId, incomingEvent);\n continue;\n }\n\n // A confirmed full fill is terminal and monotonic. In particular, do not\n // let a delayed HTTP replica/poll response downgrade a WS success.\n if (currentEvent.event === \"filled\") continue;\n if (incomingEvent.event === \"filled\" || incomingEvent.timestamp >= currentEvent.timestamp) {\n mergedByOrderId.set(incomingEvent.orderId, incomingEvent);\n }\n }\n\n return [...mergedByOrderId.values()].sort((left, right) => left.timestamp - right.timestamp);\n};\n\nexport type ExecutionProgressPhase = \"idle\" | \"pending\" | \"order_submitted\" | \"balance_updated\";\n\nexport interface DagStepProgress {\n dagRunId: string;\n totalSteps: number;\n currentSequence: number;\n currentStepType: string | null;\n completedSequences: number[];\n /** Maps sequence number → stepType string for all steps seen so far. */\n stepTypes: Record<number, string>;\n status: \"running\" | \"completed\" | \"failed\";\n errorReason: string | null;\n}\n\nexport interface ExecutionTerminalOrderEvent {\n orderId: string;\n venue: string;\n event: \"filled\" | \"partial_fill\" | \"failed\";\n filledAmountRaw?: string;\n remainingAmountRaw?: string;\n /** Actual shares + payout received, 6-decimal atomic. Set by the venue's\n * finalize handler on filled/partial_fill — the source of truth for the\n * execution summary so it never reuses the stale quote estimate. */\n actualSharesRaw?: string;\n actualToWinRaw?: string;\n /** Quote-time shares + payout, 6-decimal atomic. Snapshot of what the user\n * accepted; surfaced for \"Quoted X / Got Y\" diffs. */\n quotedSharesRaw?: string;\n quotedToWinRaw?: string;\n /** Avg execution price (decimal string). Pair with `quotedPriceRaw`\n * for inline slippage diffs and to derive shares when actual*Raw is absent. */\n executionPriceRaw?: string;\n quotedPriceRaw?: string;\n errorReason?: string;\n timestamp: number;\n}\n\nexport type ExecutionStepProgress = ExecutionStatusStep;\n\nexport type ExecutionRawStepProgress = Pick<\n ExecutionStatusStep,\n \"sequence\" | \"stepType\" | \"status\" | \"attempt\" | \"startedAt\" | \"completedAt\" | \"errorReason\"\n>;\n\nconst EXECUTION_STEP_STATUS_RANK: Record<ExecutionRawStepProgress[\"status\"], number> = {\n pending: 0,\n in_progress: 1,\n failed: 2,\n completed: 3,\n skipped: 3,\n};\n\nconst getExecutionStepIdentity = (step: ExecutionStepProgress): string =>\n [step.groupId, step.sequence, step.stepType, ...step.orderIds].join(\":\");\n\nconst getExecutionGroupAttempt = (steps: ExecutionStepProgress[]): number =>\n steps.reduce((highestAttempt, step) => Math.max(highestAttempt, step.attempt), 0);\n\nconst groupExecutionStepsByGroupId = (\n steps: ExecutionStepProgress[],\n): Map<string, ExecutionStepProgress[]> => {\n const groupedSteps = new Map<string, ExecutionStepProgress[]>();\n for (const step of steps) {\n const existingSteps = groupedSteps.get(step.groupId) ?? [];\n existingSteps.push(step);\n groupedSteps.set(step.groupId, existingSteps);\n }\n return groupedSteps;\n};\n\nconst pickExecutionGroupPresentation = (\n step: ExecutionStepProgress,\n): Pick<ExecutionStepProgress, \"groupStatus\" | \"label\" | \"bridge\"> => ({\n groupStatus: step.groupStatus,\n label: step.label,\n ...(step.bridge ? { bridge: step.bridge } : {}),\n});\n\n/**\n * Merge polling/WS snapshots without letting a delayed response visually move\n * a completed group backwards. Enriched status responses can repeat a raw\n * sequence when shared setup/fill work is copied per venue leg, so sequence\n * alone is not a valid identity here.\n */\nexport const mergeExecutionStepProgress = (\n previous: ExecutionStepProgress[],\n incoming: ExecutionStepProgress[],\n): ExecutionStepProgress[] => {\n const previousByGroupId = groupExecutionStepsByGroupId(previous);\n const incomingByGroupId = groupExecutionStepsByGroupId(incoming);\n const mergedByIdentity = new Map(previous.map((step) => [getExecutionStepIdentity(step), step]));\n\n for (const step of incoming) {\n const identity = getExecutionStepIdentity(step);\n const current = mergedByIdentity.get(identity);\n if (!current || step.attempt > current.attempt) {\n mergedByIdentity.set(identity, step);\n continue;\n }\n\n if (step.attempt < current.attempt) continue;\n if (EXECUTION_STEP_STATUS_RANK[step.status] < EXECUTION_STEP_STATUS_RANK[current.status]) {\n continue;\n }\n\n mergedByIdentity.set(identity, step);\n }\n\n const groupPresentation = new Map<\n string,\n Pick<ExecutionStepProgress, \"groupStatus\" | \"label\" | \"bridge\">\n >();\n const groupIds = new Set([...previousByGroupId.keys(), ...incomingByGroupId.keys()]);\n\n for (const groupId of groupIds) {\n const previousGroup = previousByGroupId.get(groupId) ?? [];\n const incomingGroup = incomingByGroupId.get(groupId) ?? [];\n const previousStep = previousGroup[0];\n const incomingStep = incomingGroup[0];\n if (!previousStep && incomingStep) {\n groupPresentation.set(groupId, pickExecutionGroupPresentation(incomingStep));\n continue;\n }\n if (!incomingStep && previousStep) {\n groupPresentation.set(groupId, pickExecutionGroupPresentation(previousStep));\n continue;\n }\n if (!previousStep || !incomingStep) continue;\n\n const isNewerAttempt =\n getExecutionGroupAttempt(incomingGroup) > getExecutionGroupAttempt(previousGroup);\n const shouldUseIncoming =\n isNewerAttempt ||\n EXECUTION_STEP_STATUS_RANK[incomingStep.groupStatus] >=\n EXECUTION_STEP_STATUS_RANK[previousStep.groupStatus];\n groupPresentation.set(\n groupId,\n pickExecutionGroupPresentation(shouldUseIncoming ? incomingStep : previousStep),\n );\n }\n\n return Array.from(mergedByIdentity.values())\n .map((step) => ({ ...step, ...groupPresentation.get(step.groupId) }))\n .sort((left, right) => {\n if (left.sequence !== right.sequence) return left.sequence - right.sequence;\n return getExecutionStepIdentity(left).localeCompare(getExecutionStepIdentity(right));\n });\n};\n\nexport const mergeRawExecutionStepProgress = (\n previous: ExecutionRawStepProgress[],\n incoming: ExecutionRawStepProgress[],\n): ExecutionRawStepProgress[] => {\n const mergedBySequence = new Map(previous.map((step) => [step.sequence, step]));\n\n for (const step of incoming) {\n const current = mergedBySequence.get(step.sequence);\n if (!current || step.attempt > current.attempt) {\n mergedBySequence.set(step.sequence, step);\n continue;\n }\n if (step.attempt < current.attempt) continue;\n if (EXECUTION_STEP_STATUS_RANK[step.status] < EXECUTION_STEP_STATUS_RANK[current.status]) {\n continue;\n }\n mergedBySequence.set(step.sequence, step);\n }\n\n return Array.from(mergedBySequence.values()).sort(\n (left, right) => left.sequence - right.sequence,\n );\n};\n\nexport const mergeExecutionStatusOrders = (\n previous: ExecutionStatusOrder[],\n incoming: ExecutionStatusOrder[],\n): ExecutionStatusOrder[] => {\n const mergedByOrderId = new Map(previous.map((order) => [order.orderId, order]));\n\n for (const order of incoming) {\n const current = mergedByOrderId.get(order.orderId);\n if (!current || new Date(order.updatedAt).getTime() >= new Date(current.updatedAt).getTime()) {\n mergedByOrderId.set(order.orderId, order);\n }\n }\n\n return Array.from(mergedByOrderId.values());\n};\n\nexport interface UseExecutionProgressOptions {\n orderIds: string[] | null;\n quoteId?: string | null;\n enabled: boolean;\n mode?: \"live\" | \"paper\";\n}\n\nexport interface UseExecutionProgressResult {\n phase: ExecutionProgressPhase;\n submittedOrders: WsOrderSubmitted[];\n latestBalance: WsBalanceUpdate | null;\n dagProgress: DagStepProgress | null;\n terminalOrderEvents: ExecutionTerminalOrderEvent[];\n executionSteps: ExecutionStepProgress[];\n rawExecutionSteps: ExecutionRawStepProgress[];\n executionOrders: ExecutionStatusOrder[];\n}\n\nexport function useExecutionProgress({\n orderIds,\n quoteId,\n enabled,\n mode,\n}: UseExecutionProgressOptions): UseExecutionProgressResult {\n const [phase, setPhase] = useState<ExecutionProgressPhase>(\"idle\");\n const [submittedOrders, setSubmittedOrders] = useState<WsOrderSubmitted[]>([]);\n const [latestBalance, setLatestBalance] = useState<WsBalanceUpdate | null>(null);\n const [dagProgress, setDagProgress] = useState<DagStepProgress | null>(null);\n const [terminalOrderEvents, setTerminalOrderEvents] = useState<ExecutionTerminalOrderEvent[]>([]);\n const [executionSteps, setExecutionSteps] = useState<ExecutionStepProgress[]>([]);\n const [rawExecutionSteps, setRawExecutionSteps] = useState<ExecutionRawStepProgress[]>([]);\n const [executionOrders, setExecutionOrders] = useState<ExecutionStatusOrder[]>([]);\n const orderIdSetRef = useRef(new Set<string>());\n const submittedOrderVenueByIdRef = useRef(new Map<string, string>());\n\n useEffect(() => {\n orderIdSetRef.current = new Set(orderIds ?? []);\n }, [orderIds]);\n\n useEffect(() => {\n if (enabled && orderIds && orderIds.length > 0) {\n setPhase(\"pending\");\n setSubmittedOrders([]);\n setLatestBalance(null);\n setDagProgress(null);\n setTerminalOrderEvents([]);\n setExecutionSteps([]);\n setRawExecutionSteps([]);\n setExecutionOrders([]);\n submittedOrderVenueByIdRef.current = new Map();\n } else if (!enabled) {\n setPhase(\"idle\");\n if (!orderIds || orderIds.length === 0) {\n setSubmittedOrders([]);\n setLatestBalance(null);\n setDagProgress(null);\n setTerminalOrderEvents([]);\n setExecutionSteps([]);\n setRawExecutionSteps([]);\n setExecutionOrders([]);\n }\n submittedOrderVenueByIdRef.current = new Map();\n }\n }, [enabled, orderIds]);\n\n const handleOrderSubmitted = useCallback((msg: WsOrderSubmitted): void => {\n if (!orderIdSetRef.current.has(msg.orderId)) return;\n\n const trimmedVenue = msg.venue.trim();\n if (trimmedVenue) {\n submittedOrderVenueByIdRef.current.set(msg.orderId, trimmedVenue);\n }\n\n setSubmittedOrders((prev) => [...prev, msg]);\n setPhase(\"order_submitted\");\n }, []);\n\n const handleBalanceUpdate = useCallback((msg: WsBalanceUpdate): void => {\n setLatestBalance(msg);\n setPhase((current) => {\n if (current === \"order_submitted\" || current === \"pending\") {\n return \"balance_updated\";\n }\n return current;\n });\n }, []);\n\n const handleOrderEvent = useCallback((msg: WsOrderEvent): void => {\n if (!orderIdSetRef.current.has(msg.orderId)) return;\n\n const trimmedVenue = msg.venue.trim();\n if (trimmedVenue) {\n submittedOrderVenueByIdRef.current.set(msg.orderId, trimmedVenue);\n }\n\n const { event } = msg;\n\n // Terminal-order events: any WS message that means \"this orderId is\n // done, stop waiting on it\". Mapped down to the three SDK-exposed\n // terminal events (`filled` / `partial_fill` / `failed`) so the\n // place-order UI's `deriveAggregateOrderStatus` can read one shape.\n //\n // `expired` and `dag_cancelled` are non-failure terminal shapes that\n // still need to unwedge the UI:\n // - `expired` — server-side admission timeout / staleness sweep.\n // - `dag_cancelled` — operator/manual cancel. The order never made\n // it to the venue, so there is no fill data; surface as `failed`\n // so the modal exits \"pending\" instead of hanging on the hard\n // 60 s client-side timeout (which historically was the only thing\n // that broke users out of this state).\n // `bridge_ws_subscribe_failed` is a venue-agnostic infra failure that\n // also maps to `failed` (kept here to preserve the existing copy).\n if (\n event === \"filled\" ||\n event === \"partial_fill\" ||\n event === \"failed\" ||\n event === \"bridge_ws_subscribe_failed\" ||\n event === \"expired\" ||\n event === \"dag_cancelled\" ||\n event === \"cancelled\"\n ) {\n const mappedEvent: ExecutionTerminalOrderEvent[\"event\"] =\n event === \"filled\" || event === \"partial_fill\" ? event : \"failed\";\n const resolvedVenue =\n trimmedVenue || submittedOrderVenueByIdRef.current.get(msg.orderId) || \"\";\n if (resolvedVenue) {\n submittedOrderVenueByIdRef.current.set(msg.orderId, resolvedVenue);\n }\n\n const fallbackErrorReason =\n event === \"bridge_ws_subscribe_failed\"\n ? \"Bridge event subscription failed.\"\n : event === \"expired\"\n ? \"Order expired before it could be submitted.\"\n : event === \"dag_cancelled\"\n ? \"Order was cancelled before submission.\"\n : undefined;\n\n const nextTerminalEvent: ExecutionTerminalOrderEvent = {\n orderId: msg.orderId,\n venue: resolvedVenue,\n event: mappedEvent,\n filledAmountRaw: msg.filledAmountRaw,\n remainingAmountRaw: msg.remainingAmountRaw,\n actualSharesRaw: msg.actualSharesRaw,\n actualToWinRaw: msg.actualToWinRaw,\n quotedSharesRaw: msg.quotedSharesRaw,\n quotedToWinRaw: msg.quotedToWinRaw,\n executionPriceRaw: msg.executionPriceRaw,\n quotedPriceRaw: msg.quotedPriceRaw,\n errorReason: msg.errorReason ?? fallbackErrorReason,\n timestamp: msg.timestamp,\n };\n\n setTerminalOrderEvents((previous) => mergeTerminalOrderEvents(previous, [nextTerminalEvent]));\n return;\n }\n\n if (event === \"dag_started\") {\n // Pre-populate stepTypes from dag_started so labels are available\n // before each step_started event arrives (avoids \"Step N of M\" flash).\n const initialStepTypes: Record<number, string> = {};\n if (msg.stepTypes) {\n for (const [seq, type] of Object.entries(msg.stepTypes)) {\n initialStepTypes[Number(seq)] = type;\n }\n }\n setDagProgress({\n dagRunId: msg.dagRunId ?? \"\",\n totalSteps: msg.totalSteps ?? 0,\n currentSequence: 0,\n currentStepType: null,\n completedSequences: [],\n stepTypes: initialStepTypes,\n status: \"running\",\n errorReason: null,\n });\n setRawExecutionSteps((previous) =>\n mergeRawExecutionStepProgress(\n previous,\n Object.entries(initialStepTypes).map(([sequence, stepType]) => ({\n sequence: Number(sequence),\n stepType,\n status: \"pending\",\n attempt: 0,\n startedAt: null,\n completedAt: null,\n errorReason: null,\n })),\n ),\n );\n return;\n }\n\n if (event === \"step_started\" || event === \"step_retrying\") {\n setDagProgress((prev) => {\n if (!prev) return prev;\n const seq = msg.sequence ?? prev.currentSequence;\n const stepType = msg.stepType ?? prev.currentStepType;\n return {\n ...prev,\n currentSequence: seq,\n currentStepType: stepType,\n stepTypes: stepType != null ? { ...prev.stepTypes, [seq]: stepType } : prev.stepTypes,\n };\n });\n const { sequence, stepType } = msg;\n if (sequence != null && stepType) {\n setRawExecutionSteps((previous) =>\n mergeRawExecutionStepProgress(previous, [\n {\n sequence,\n stepType,\n status: \"in_progress\",\n attempt:\n msg.attempt ?? previous.find((step) => step.sequence === sequence)?.attempt ?? 0,\n startedAt: new Date(msg.timestamp).toISOString(),\n completedAt: null,\n errorReason: null,\n },\n ]),\n );\n }\n return;\n }\n\n if (event === \"step_waiting\") {\n setDagProgress((prev) => {\n if (!prev) return prev;\n const seq = msg.sequence ?? prev.currentSequence;\n const stepType = msg.stepType ?? prev.currentStepType;\n return {\n ...prev,\n currentSequence: seq,\n currentStepType: stepType,\n stepTypes: stepType != null ? { ...prev.stepTypes, [seq]: stepType } : prev.stepTypes,\n };\n });\n const { sequence, stepType } = msg;\n if (sequence != null && stepType) {\n setRawExecutionSteps((previous) =>\n mergeRawExecutionStepProgress(previous, [\n {\n sequence,\n stepType,\n status: \"in_progress\",\n attempt:\n msg.attempt ?? previous.find((step) => step.sequence === sequence)?.attempt ?? 0,\n startedAt: new Date(msg.timestamp).toISOString(),\n completedAt: null,\n errorReason: null,\n },\n ]),\n );\n }\n return;\n }\n\n if (event === \"step_completed\") {\n setDagProgress((prev) => {\n if (!prev) return prev;\n const seq = msg.sequence;\n const stepType = msg.stepType;\n return {\n ...prev,\n completedSequences:\n seq != null ? [...prev.completedSequences, seq] : prev.completedSequences,\n stepTypes:\n seq != null && stepType != null\n ? { ...prev.stepTypes, [seq]: stepType }\n : prev.stepTypes,\n };\n });\n const { sequence, stepType } = msg;\n if (sequence != null && stepType) {\n const completedAt = new Date(msg.timestamp).toISOString();\n setRawExecutionSteps((previous) =>\n mergeRawExecutionStepProgress(previous, [\n {\n sequence,\n stepType,\n status: \"completed\",\n attempt:\n msg.attempt ?? previous.find((step) => step.sequence === sequence)?.attempt ?? 0,\n startedAt: null,\n completedAt,\n errorReason: null,\n },\n ]),\n );\n }\n return;\n }\n\n if (event === \"dag_completed\") {\n setDagProgress((prev) => {\n if (!prev) return prev;\n return { ...prev, status: \"completed\" };\n });\n return;\n }\n\n // For DAG failure events we can't early-return when `prev` is null:\n // a WS reconnect mid-execution may deliver `step_failed` / `dag_failed`\n // on the new socket without a preceding `dag_started`, which would\n // otherwise leave the modal stuck in \"submitting\" forever. When that\n // happens, we synthesize a minimal failed progress object from whatever\n // metadata the failure event carries so the UI can transition.\n const buildFailedProgress = (prev: DagStepProgress | null): DagStepProgress => {\n const seq = msg.sequence ?? prev?.currentSequence ?? 0;\n const stepType = msg.stepType ?? prev?.currentStepType ?? null;\n const baseStepTypes = prev?.stepTypes ?? {};\n const stepTypes = seq && stepType ? { ...baseStepTypes, [seq]: stepType } : baseStepTypes;\n return {\n dagRunId: msg.dagRunId ?? prev?.dagRunId ?? \"\",\n totalSteps: msg.totalSteps ?? prev?.totalSteps ?? 0,\n currentSequence: seq,\n currentStepType: stepType,\n completedSequences: prev?.completedSequences ?? [],\n stepTypes,\n status: \"failed\",\n errorReason: msg.errorReason ?? prev?.errorReason ?? null,\n };\n };\n\n if (event === \"step_failed\") {\n setDagProgress((prev) => buildFailedProgress(prev));\n const { sequence, stepType } = msg;\n if (sequence != null && stepType) {\n setRawExecutionSteps((previous) =>\n mergeRawExecutionStepProgress(previous, [\n {\n sequence,\n stepType,\n status: \"failed\",\n attempt:\n msg.attempt ?? previous.find((step) => step.sequence === sequence)?.attempt ?? 0,\n startedAt: null,\n completedAt: new Date(msg.timestamp).toISOString(),\n errorReason: msg.errorReason ?? null,\n },\n ]),\n );\n }\n return;\n }\n\n if (event === \"dag_failed\") {\n setDagProgress((prev) => buildFailedProgress(prev));\n return;\n }\n }, []);\n\n const isStatusPolling = enabled && !!quoteId;\n const isListening = enabled && !!orderIds && orderIds.length > 0;\n\n useOnOrderSubmitted(isListening ? handleOrderSubmitted : null);\n useOnBalanceUpdate(isListening ? handleBalanceUpdate : null);\n useOnOrderEvent(isListening ? handleOrderEvent : null);\n\n // Race mitigation + ongoing reconcile: WS listener subscribes only after\n // `orderIds` are known (post place-order response), but DAG events can fire\n // within ~500ms inside the place-order handler, and `ws-gateway` fan-out is\n // unbuffered. We fire an immediate HTTP reconcile on subscribe, then poll\n // every ORDER_POLL_INTERVAL_MS for any orderId that hasn't reached a\n // terminal event yet, so transient WS drops don't leave the modal hung.\n const client = useAggClient();\n const terminalOrderIdsRef = useRef<Set<string>>(new Set());\n const pollInFlightRef = useRef(false);\n\n const buildSubmittedOrdersFromStatus = useCallback(\n (orders: ExecutionStatusOrder[]): WsOrderSubmitted[] => {\n return orders.map((order) => ({\n type: \"order_submitted\",\n venue: order.venue,\n orderId: order.orderId,\n side: \"\",\n price: Number(order.executionPriceRaw ?? order.quotedPriceRaw ?? 0),\n size: 0,\n timestamp: new Date(order.updatedAt).getTime() / 1000,\n }));\n },\n [],\n );\n\n const buildTerminalEventsFromStatus = useCallback(\n (\n status: ExecutionStatusResponse,\n fallbackOrderIds: string[],\n fallbackTimestamp: number,\n ): ExecutionTerminalOrderEvent[] => {\n const terminalEvents = status.orders\n .map((order) => {\n const mappedEvent = order.event ?? mapOrderStatusToTerminalEvent(order.status);\n if (!mappedEvent) return null;\n\n return {\n orderId: order.orderId,\n venue: order.venue,\n event: mappedEvent,\n filledAmountRaw: order.filledAmountRaw,\n remainingAmountRaw: order.remainingAmountRaw,\n actualSharesRaw: order.actualSharesRaw,\n actualToWinRaw: order.actualToWinRaw,\n quotedSharesRaw: order.quotedSharesRaw,\n quotedToWinRaw: order.quotedToWinRaw,\n executionPriceRaw: order.executionPriceRaw,\n quotedPriceRaw: order.quotedPriceRaw,\n errorReason: order.errorReason ?? order.partialFillReason,\n timestamp: new Date(order.updatedAt).getTime() || fallbackTimestamp,\n };\n })\n .filter((order) => order != null) as ExecutionTerminalOrderEvent[];\n\n if (!status.terminal) {\n return terminalEvents;\n }\n\n const coveredOrderIds = new Set(terminalEvents.map((event) => event.orderId));\n const fallbackEvent: ExecutionTerminalOrderEvent[\"event\"] | null =\n status.overallState === \"filled\"\n ? \"filled\"\n : status.overallState === \"partially_filled\"\n ? \"partial_fill\"\n : [\"failed\", \"cancelled\", \"expired\"].includes(status.overallState)\n ? \"failed\"\n : null;\n if (!fallbackEvent) return terminalEvents;\n\n return [\n ...terminalEvents,\n ...fallbackOrderIds\n .filter((orderId) => !coveredOrderIds.has(orderId))\n .map((orderId) => ({\n orderId,\n venue: \"\",\n event: fallbackEvent,\n errorReason:\n fallbackEvent === \"failed\" ? (status.errorReason ?? \"Execution failed.\") : undefined,\n timestamp: fallbackTimestamp,\n })),\n ];\n },\n [],\n );\n\n const setFatalPollingFailure = useCallback((message: string, failedOrderIds: string[]): void => {\n setDagProgress((prev) => ({\n dagRunId: prev?.dagRunId ?? \"\",\n totalSteps: prev?.totalSteps ?? 0,\n currentSequence: prev?.currentSequence ?? 0,\n currentStepType: prev?.currentStepType ?? null,\n completedSequences: prev?.completedSequences ?? [],\n stepTypes: prev?.stepTypes ?? {},\n status: \"failed\",\n errorReason: message,\n }));\n\n setTerminalOrderEvents((prev) => {\n const existingByOrderId = new Map(prev.map((event) => [event.orderId, event]));\n const timestamp = Date.now();\n\n for (const orderId of failedOrderIds) {\n if (existingByOrderId.has(orderId)) continue;\n existingByOrderId.set(orderId, {\n orderId,\n venue: \"\",\n event: \"failed\",\n errorReason: message,\n timestamp,\n });\n }\n\n return Array.from(existingByOrderId.values()).sort(\n (left, right) => left.timestamp - right.timestamp,\n );\n });\n }, []);\n\n useEffect(() => {\n terminalOrderIdsRef.current = new Set(terminalOrderEvents.map((e) => e.orderId));\n }, [terminalOrderEvents]);\n\n useEffect(() => {\n if (!isStatusPolling || !quoteId) return;\n\n let cancelled = false;\n let timeout: ReturnType<typeof setTimeout> | null = null;\n\n const stopPolling = (): void => {\n if (timeout !== null) {\n clearTimeout(timeout);\n timeout = null;\n }\n };\n\n const scheduleNextPoll = (delayMs: number | null | undefined): void => {\n if (cancelled) return;\n timeout = setTimeout(() => {\n void pollExecutionStatus();\n }, delayMs ?? ORDER_POLL_INTERVAL_MS);\n };\n\n const pollExecutionStatus = async (): Promise<void> => {\n if (cancelled || pollInFlightRef.current) return;\n\n pollInFlightRef.current = true;\n try {\n const status = await client.getExecutionStatus({\n quoteId,\n ...(mode ? { mode } : {}),\n });\n if (cancelled) return;\n\n const resolvedOrderIds = status.orderIds.length > 0 ? status.orderIds : (orderIds ?? []);\n\n if (resolvedOrderIds.length > 0) {\n setPhase(\"order_submitted\");\n }\n\n setSubmittedOrders(buildSubmittedOrdersFromStatus(status.orders));\n setExecutionOrders((previous) => mergeExecutionStatusOrders(previous, status.orders));\n\n if (status.dagProgress) {\n setDagProgress({\n ...status.dagProgress,\n stepTypes: Object.fromEntries(\n Object.entries(status.dagProgress.stepTypes).map(([sequence, stepType]) => [\n Number(sequence),\n stepType,\n ]),\n ),\n });\n } else if (\n status.terminal &&\n [\"failed\", \"cancelled\", \"expired\"].includes(status.overallState)\n ) {\n setDagProgress((prev) => ({\n dagRunId: prev?.dagRunId ?? status.executionId ?? \"\",\n totalSteps: prev?.totalSteps ?? status.steps.length,\n currentSequence: prev?.currentSequence ?? 0,\n currentStepType: prev?.currentStepType ?? null,\n completedSequences: prev?.completedSequences ?? [],\n stepTypes: prev?.stepTypes ?? {},\n status: \"failed\",\n errorReason: status.errorReason,\n }));\n }\n\n setExecutionSteps((previous) => mergeExecutionStepProgress(previous, status.steps));\n setRawExecutionSteps((previous) =>\n mergeRawExecutionStepProgress(\n previous,\n status.steps.map((step) => ({\n sequence: step.sequence,\n stepType: step.stepType,\n status: step.status,\n attempt: step.attempt,\n startedAt: step.startedAt,\n completedAt: step.completedAt,\n errorReason: step.errorReason,\n })),\n ),\n );\n\n const fallbackTimestamp = Date.now();\n const nextTerminalEvents = buildTerminalEventsFromStatus(\n status,\n resolvedOrderIds,\n fallbackTimestamp,\n );\n setTerminalOrderEvents((previous) =>\n mergeTerminalOrderEvents(previous, nextTerminalEvents),\n );\n\n if (status.terminal) {\n stopPolling();\n return;\n }\n\n scheduleNextPoll(status.pollAfterMs);\n } catch (error) {\n if (cancelled) return;\n\n const statusCode =\n typeof error === \"object\" &&\n error != null &&\n \"status\" in error &&\n typeof (error as { status?: unknown }).status === \"number\"\n ? (error as { status: number }).status\n : null;\n\n if (statusCode === 400 || statusCode === 401 || statusCode === 403) {\n setFatalPollingFailure(\n error instanceof Error ? error.message : \"Execution status polling failed.\",\n orderIds ?? [],\n );\n stopPolling();\n return;\n }\n\n scheduleNextPoll(ORDER_POLL_INTERVAL_MS);\n } finally {\n pollInFlightRef.current = false;\n }\n };\n\n void pollExecutionStatus();\n\n return () => {\n cancelled = true;\n stopPolling();\n };\n }, [\n buildSubmittedOrdersFromStatus,\n buildTerminalEventsFromStatus,\n client,\n isStatusPolling,\n mode,\n orderIds,\n quoteId,\n setFatalPollingFailure,\n ]);\n\n useEffect(() => {\n if (isStatusPolling) return;\n if (!isListening || !orderIds?.length) return;\n\n let cancelled = false;\n let interval: ReturnType<typeof setInterval> | null = null;\n\n const stopPolling = (): void => {\n if (interval !== null) {\n clearInterval(interval);\n interval = null;\n }\n };\n\n const reconcile = async (): Promise<void> => {\n if (cancelled || pollInFlightRef.current) return;\n const pending = orderIds.filter((id) => !terminalOrderIdsRef.current.has(id));\n if (pending.length === 0) {\n stopPolling();\n return;\n }\n\n pollInFlightRef.current = true;\n try {\n const orders = await Promise.all(\n pending.map(async (orderId) => {\n try {\n const res = await client.getExecutionOrders({\n orderId,\n limit: 1,\n ...(mode ? { mode } : {}),\n });\n return res.data?.[0] ?? null;\n } catch {\n return null;\n }\n }),\n );\n if (cancelled) return;\n\n const terminalEvents: ExecutionTerminalOrderEvent[] = [];\n for (const order of orders) {\n if (!order) continue;\n if (!TERMINAL_ORDER_STATUSES.has(order.status)) continue;\n const mapped = mapOrderStatusToTerminalEvent(order.status);\n if (!mapped) continue;\n terminalEvents.push({\n orderId: order.id,\n venue: order.venue ?? \"\",\n event: mapped,\n filledAmountRaw: order.filledAmountRaw ?? undefined,\n actualSharesRaw: order.actualSharesRaw ?? undefined,\n actualToWinRaw: order.actualToWinRaw ?? undefined,\n quotedSharesRaw: order.quotedSharesRaw ?? undefined,\n quotedToWinRaw: order.quotedToWinRaw ?? undefined,\n executionPriceRaw: order.executionPrice ?? undefined,\n quotedPriceRaw: order.quotedPriceRaw ?? undefined,\n errorReason: order.errorMessage ?? undefined,\n timestamp: new Date(order.updatedAt).getTime() || Date.now(),\n });\n }\n if (terminalEvents.length > 0) {\n setTerminalOrderEvents((previous) => mergeTerminalOrderEvents(previous, terminalEvents));\n }\n\n // Stop polling immediately when this fetch covers all remaining\n // orders, rather than waiting for the ref sync + next tick.\n const covered = new Set([\n ...terminalOrderIdsRef.current,\n ...terminalEvents.map((e) => e.orderId),\n ]);\n if (orderIds.every((id) => covered.has(id))) {\n stopPolling();\n }\n } finally {\n pollInFlightRef.current = false;\n }\n };\n\n void reconcile();\n interval = setInterval(() => {\n void reconcile();\n }, ORDER_POLL_INTERVAL_MS);\n\n return () => {\n cancelled = true;\n stopPolling();\n };\n }, [client, isListening, isStatusPolling, mode, orderIds]);\n\n return {\n phase,\n submittedOrders,\n latestBalance,\n dagProgress,\n terminalOrderEvents,\n executionSteps,\n rawExecutionSteps,\n executionOrders,\n };\n}\n","import { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport type {\n CreateBalanceRefillPolicyParams,\n UpdateBalanceRefillPolicyParams,\n} from \"@agg-build/sdk\";\nimport { useAggClient } from \"../core/provider\";\nimport { executionKeys } from \"./query-keys\";\n\nexport interface UseBalanceRefillPoliciesOptions {\n enabled?: boolean;\n}\n\nexport function useBalanceRefillPolicies(options?: UseBalanceRefillPoliciesOptions) {\n const client = useAggClient();\n const queryClient = useQueryClient();\n const queryKey = executionKeys.balanceRefillPolicies();\n const query = useQuery({\n queryKey,\n queryFn: () => client.getBalanceRefillPolicies(),\n enabled: options?.enabled ?? true,\n staleTime: 15_000,\n refetchInterval: (state) =>\n state.state.data?.some((policy) =>\n [\"reserved\", \"executing\"].includes(policy.latestAttempt?.status ?? \"\"),\n )\n ? 5_000\n : false,\n });\n\n const createPolicy = useMutation({\n mutationFn: (params: CreateBalanceRefillPolicyParams) =>\n client.createBalanceRefillPolicy(params),\n onSuccess: (policy) => {\n queryClient.setQueryData(queryKey, [policy]);\n },\n });\n const updatePolicy = useMutation({\n mutationFn: ({\n policyId,\n params,\n }: {\n policyId: string;\n params: UpdateBalanceRefillPolicyParams;\n }) => client.updateBalanceRefillPolicy(policyId, params),\n onSuccess: (updated) => {\n queryClient.setQueryData(queryKey, (current: typeof query.data) =>\n (current ?? []).map((policy) => (policy.id === updated.id ? updated : policy)),\n );\n },\n });\n\n return {\n ...query,\n policies: query.data ?? [],\n createPolicy,\n updatePolicy,\n };\n}\n","import type { PositionGroup } from \"@agg-build/sdk\";\n\nexport interface ClosedPositionTotals {\n totalTraded: number;\n amountWon: number;\n returnPct: number;\n winningOutcomeIds: string[];\n isPartialWin: boolean;\n}\n\nexport const computeClosedPositionTotals = (group: PositionGroup): ClosedPositionTotals => {\n const outcomes = group.venueMarket.venueMarketOutcomes;\n // When the market hasn't resolved yet (e.g. user-closed exit on an open market),\n // the \"Amount won\" column reflects the realized/current value, not winner-only payouts.\n const isResolved = group.venueMarket.status === \"resolved\";\n let totalTraded = 0;\n let amountWon = 0;\n const winningOutcomeIds = new Set<string>();\n let winningCount = 0;\n let settledCount = 0;\n\n for (const outcome of outcomes) {\n totalTraded += outcome.avgEntryPrice * outcome.totalSize;\n\n if (isResolved) {\n if (outcome.winner === true) {\n amountWon += outcome.totalValue;\n winningCount += 1;\n\n for (const breakdown of outcome.venueBreakdown) {\n if (breakdown.venueMarketOutcomeId) {\n winningOutcomeIds.add(breakdown.venueMarketOutcomeId);\n }\n }\n }\n } else {\n amountWon += outcome.totalValue;\n }\n\n if (outcome.winner !== null) {\n settledCount += 1;\n }\n }\n\n const returnPct = totalTraded === 0 ? 0 : (amountWon - totalTraded) / totalTraded;\n\n return {\n totalTraded,\n amountWon,\n returnPct,\n winningOutcomeIds: Array.from(winningOutcomeIds),\n isPartialWin: winningCount > 0 && winningCount < settledCount,\n };\n};\n","import { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport type { RedeemRequest, RedeemResponse } from \"@agg-build/sdk\";\nimport { useAggClient } from \"../core/provider\";\nimport { useResolvedExecutionMode } from \"../use-resolved-execution-mode\";\nimport { invalidateUserClaimState } from \"./balance-invalidation\";\n\nexport class RedeemRejectedError extends Error {\n readonly response: RedeemResponse;\n\n constructor(message: string, response: RedeemResponse) {\n super(message);\n this.name = \"RedeemRejectedError\";\n this.response = response;\n }\n}\n\nconst isLegRejected = (status: RedeemResponse[\"results\"][number][\"status\"]): boolean =>\n status === \"ineligible\" || status === \"rejected\";\n\nexport const useRedeem = () => {\n const client = useAggClient();\n const queryClient = useQueryClient();\n const { executionMode } = useResolvedExecutionMode();\n\n return useMutation<RedeemResponse, Error, RedeemRequest>({\n mutationFn: async (body) => {\n // State the mode explicitly, like the other execution calls. A paper\n // app ignores it and settles on paper regardless, so the pre-resolution\n // window — where this is still the locally-configured guess — cannot\n // redeem against the wrong ledger.\n const response = await client.redeem({ mode: executionMode, ...body });\n if (response.results.length > 0 && response.results.every((r) => isLegRejected(r.status))) {\n const reasons = response.results\n .map((r) => r.reason)\n .filter((r): r is string => Boolean(r));\n const message = reasons.length > 0 ? reasons.join(\"; \") : \"Redeem rejected\";\n throw new RedeemRejectedError(message, response);\n }\n return response;\n },\n onSettled: () => {\n invalidateUserClaimState(queryClient);\n },\n });\n};\n","import type { WsRedeemEvent } from \"@agg-build/sdk\";\nimport { useOnRedeemEvent as useOnRedeemEventBase } from \"../core/providers/ws-provider\";\n\nexport type RedeemEvent = WsRedeemEvent;\n\nexport const useOnRedeemEvent = (listener: ((event: RedeemEvent) => void) | null): void => {\n useOnRedeemEventBase(listener);\n};\n","import { useQuery } from \"@tanstack/react-query\";\nimport type { AggClient } from \"@agg-build/sdk\";\nimport { useAggAuthState, useAggClient } from \"../core/provider\";\nimport { executionKeys } from \"./query-keys\";\n\nconst CLAIMABLE_COUNT_PAGE_LIMIT = 100;\n\nconst getClaimablePositionsCount = async (client: AggClient): Promise<number> => {\n let total = 0;\n let cursor: string | undefined;\n\n // Claimable (redeemStatus \"eligible\") groups live in the ACTIVE bucket:\n // a won-but-unclaimed position stays Active until the redeem stamps\n // `redeemedAt` (server bucket rule since 2026-05-14 — see\n // VenueMarketPositionService.getPositions). Closed-bucket groups are\n // redeemed, lost, or dust — \"eligible\" there would need ≥10 unredeemed\n // dust legs summing past the redeem threshold, which doesn't occur in\n // practice. This previously walked status:\"closed\" and therefore always\n // counted ~0. Walk the active cursor until exhausted so the badge is exact.\n do {\n const page = await client.getExecutionPositions({\n status: \"active\",\n limit: CLAIMABLE_COUNT_PAGE_LIMIT,\n cursor,\n });\n\n for (const group of page.data) {\n if (group.redeemStatus === \"eligible\") {\n total += 1;\n }\n }\n\n cursor = page.hasMore ? (page.nextCursor ?? undefined) : undefined;\n } while (cursor);\n\n return total;\n};\n\nexport const useRedeemEligibleCount = (): number => {\n const client = useAggClient();\n const { isAuthenticated } = useAggAuthState();\n\n const query = useQuery({\n queryKey: executionKeys.claimablePositionsCount(),\n queryFn: () => getClaimablePositionsCount(client),\n enabled: isAuthenticated,\n staleTime: 30_000,\n refetchInterval: isAuthenticated ? 45_000 : false,\n });\n\n if (!isAuthenticated) return 0;\n return query.data ?? 0;\n};\n","import { useEffect, useMemo, useState } from \"react\";\nimport type { WsRedeemEvent } from \"@agg-build/sdk\";\nimport { useOnRedeemEvent } from \"../core/providers/ws-provider\";\n\nexport interface RedeemLegLifecycle {\n status: \"submitted\" | \"confirmed\" | \"failed\";\n txHash: string | null;\n errorMessage: string | null;\n}\n\nexport interface RedeemLifecycleState {\n /** True until terminal — drives the claim button spinner. */\n pending: boolean;\n /** True once every expected leg has flipped to confirmed or failed. */\n terminal: boolean;\n /** True iff terminal AND every leg.status === \"confirmed\". */\n allConfirmed: boolean;\n /** True iff any leg.status === \"failed\" (including pre-failed legs). */\n anyFailed: boolean;\n /** First non-null leg.errorMessage when anyFailed; null otherwise. */\n errorMessage: string | null;\n /** Per-leg lifecycle keyed by venueMarketOutcomeId. */\n legs: Record<string, RedeemLegLifecycle>;\n}\n\nexport interface UseRedeemLifecycleInput {\n redeemId: string;\n /**\n * Legs the API returned with status === \"submitted\" (EVM async path).\n * Each receives a redeem_event with status confirmed or failed.\n */\n expectedOutcomeIds: string[];\n /**\n * Legs the API returned with status === \"ineligible\" or \"rejected\".\n * Pre-seeded into legs as terminal-failed; no WS event will ever arrive.\n */\n preFailedOutcomeIds?: string[];\n /** Optional pre-seeded errorMessage per pre-failed leg, indexed by venueMarketOutcomeId. */\n preFailedReasons?: Record<string, string | null>;\n /**\n * Legs the API returned with status === \"confirmed\" (SVM sync path:\n * tx landed inline inside the HTTP call, VMP.redeemedAt already set\n * server-side). Pre-seeded into legs as terminal-confirmed; no WS\n * event will ever arrive.\n */\n preConfirmedOutcomeIds?: string[];\n /** Optional pre-seeded txHash per pre-confirmed leg, indexed by venueMarketOutcomeId. */\n preConfirmedTxHashes?: Record<string, string | null>;\n}\n\nconst computeDerivedState = (\n legs: Record<string, RedeemLegLifecycle>,\n expectedCount: number,\n): {\n terminal: boolean;\n allConfirmed: boolean;\n anyFailed: boolean;\n errorMessage: string | null;\n} => {\n const legCount = Object.keys(legs).length;\n let allTerminal = legCount === expectedCount;\n let allConfirmed = allTerminal;\n let anyFailed = false;\n let errorMessage: string | null = null;\n for (const leg of Object.values(legs)) {\n if (leg.status === \"submitted\") allTerminal = false;\n if (leg.status !== \"confirmed\") allConfirmed = false;\n if (leg.status === \"failed\") {\n anyFailed = true;\n if (errorMessage === null && leg.errorMessage) errorMessage = leg.errorMessage;\n }\n }\n return {\n terminal: allTerminal,\n allConfirmed: allTerminal && allConfirmed,\n anyFailed,\n errorMessage,\n };\n};\n\nconst seedState = (input: UseRedeemLifecycleInput): RedeemLifecycleState => {\n const legs: Record<string, RedeemLegLifecycle> = {};\n for (const id of input.preFailedOutcomeIds ?? []) {\n legs[id] = {\n status: \"failed\",\n txHash: null,\n errorMessage: input.preFailedReasons?.[id] ?? null,\n };\n }\n for (const id of input.preConfirmedOutcomeIds ?? []) {\n legs[id] = {\n status: \"confirmed\",\n txHash: input.preConfirmedTxHashes?.[id] ?? null,\n errorMessage: null,\n };\n }\n const expectedCount =\n input.expectedOutcomeIds.length +\n (input.preFailedOutcomeIds?.length ?? 0) +\n (input.preConfirmedOutcomeIds?.length ?? 0);\n const derived = computeDerivedState(legs, expectedCount);\n return {\n pending: !derived.terminal,\n terminal: derived.terminal,\n allConfirmed: derived.allConfirmed,\n anyFailed: derived.anyFailed,\n errorMessage: derived.errorMessage,\n legs,\n };\n};\n\n/**\n * Subscribes once to `redeem_event` WS events and materializes a per-`redeemId`\n * lifecycle record for every in-flight redeem the caller is tracking.\n *\n * **Input shape** — the caller passes one {@link UseRedeemLifecycleInput} entry\n * per in-flight redeem. Legs are split into three buckets:\n * - `expectedOutcomeIds` — the EVM async path. The API returned these legs with\n * `status === \"submitted\"`; each will eventually receive a `redeem_event` WS\n * message with `status === \"confirmed\"` or `\"failed\"`.\n * - `preFailedOutcomeIds` — legs the API returned as `\"ineligible\"` or\n * `\"rejected\"` at submit time. Pre-seeded into the returned state as\n * terminal-failed; no WS event will ever arrive for them.\n * - `preConfirmedOutcomeIds` — the SVM sync path. The transaction landed inline\n * inside the HTTP call so `VenueMarketPosition.redeemedAt` is already set\n * server-side before the response returns. Pre-seeded as terminal-confirmed;\n * no WS event will ever arrive.\n *\n * **Entry lifecycle** — when the caller drops a `redeemId` from `inputs`, its\n * entry disappears from the returned record on the next render. There is no\n * tombstone or TTL — the lifecycle is purely driven by what is in `inputs`.\n *\n * **Performance** — the `inputs` array's reference identity matters. The hook\n * re-derives the internal `redeemId → input` map on every render where\n * `inputs` is a new reference. Callers should memoize the array via `useMemo`\n * to avoid the re-derivation overhead. A common pattern:\n * ```ts\n * const inputs = useMemo(\n * () => Object.values(activeRedeems).map(toLifecycleInput),\n * [activeRedeems],\n * );\n * ```\n *\n * **New-entry gap** — when the caller adds a new `redeemId` to `inputs`, the\n * returned record does not include it for the render where it was added. The\n * seed entry is written inside a `useEffect` (which runs after paint). Treat a\n * missing entry as \"pending / not terminal yet\" — the same as\n * `state.pending === true`.\n *\n * **No REST backfill** — if the WS subscription drops mid-flight (page refresh,\n * disconnect), the in-memory lifecycle state is lost. Redeems typically settle\n * in seconds and each position's `redeemStatus` is polled separately, so no\n * REST backfill is provided here.\n */\nexport function useRedeemLifecycles(\n inputs: UseRedeemLifecycleInput[],\n): Record<string, RedeemLifecycleState> {\n const inputsByRedeemId = useMemo<Record<string, UseRedeemLifecycleInput>>(() => {\n const map: Record<string, UseRedeemLifecycleInput> = {};\n for (const input of inputs) {\n map[input.redeemId] = input;\n }\n return map;\n }, [inputs]);\n\n const [stateMap, setStateMap] = useState<Record<string, RedeemLifecycleState>>(() => {\n const next: Record<string, RedeemLifecycleState> = {};\n for (const [id, input] of Object.entries(inputsByRedeemId)) {\n next[id] = seedState(input);\n }\n return next;\n });\n\n // Backfill seed state for redeemIds added after the first render. The\n // `useState` lazy initializer only runs once (on mount), so any redeemId\n // that arrives later is absent from the returned record until this effect\n // fires (after the next paint). During that render-to-effect window,\n // consumers should treat a missing entry as pending — the same as\n // `state.pending === true`.\n useEffect(() => {\n setStateMap((prev) => {\n let changed = false;\n const next: Record<string, RedeemLifecycleState> = {};\n for (const [id, input] of Object.entries(inputsByRedeemId)) {\n const existing = prev[id];\n if (existing) {\n next[id] = existing;\n } else {\n next[id] = seedState(input);\n changed = true;\n }\n }\n if (Object.keys(next).length !== Object.keys(prev).length) changed = true;\n return changed ? next : prev;\n });\n }, [inputsByRedeemId]);\n\n useOnRedeemEvent(\n useMemo(() => {\n if (Object.keys(inputsByRedeemId).length === 0) return null;\n return (event: WsRedeemEvent) => {\n const input = inputsByRedeemId[event.redeemId];\n if (!input) return;\n setStateMap((prev) => {\n const existing = prev[event.redeemId];\n if (!existing) return prev;\n const nextLegs: Record<string, RedeemLegLifecycle> = {\n ...existing.legs,\n [event.venueMarketOutcomeId]: {\n status: event.status,\n txHash: event.txHash,\n errorMessage: event.errorMessage,\n },\n };\n const expectedCount =\n input.expectedOutcomeIds.length +\n (input.preFailedOutcomeIds?.length ?? 0) +\n (input.preConfirmedOutcomeIds?.length ?? 0);\n const derived = computeDerivedState(nextLegs, expectedCount);\n const nextState: RedeemLifecycleState = {\n pending: !derived.terminal,\n terminal: derived.terminal,\n allConfirmed: derived.allConfirmed,\n anyFailed: derived.anyFailed,\n errorMessage: derived.errorMessage,\n legs: nextLegs,\n };\n return { ...prev, [event.redeemId]: nextState };\n });\n };\n }, [inputsByRedeemId]),\n );\n\n return stateMap;\n}\n","import { useMemo } from \"react\";\nimport {\n useRedeemLifecycles,\n type RedeemLifecycleState,\n type UseRedeemLifecycleInput,\n} from \"./use-redeem-lifecycles\";\n\nconst INITIAL_STATE: RedeemLifecycleState = {\n pending: true,\n terminal: false,\n allConfirmed: false,\n anyFailed: false,\n errorMessage: null,\n legs: {},\n};\n\nexport function useRedeemLifecycle(input: UseRedeemLifecycleInput | null): RedeemLifecycleState {\n const inputs = useMemo(() => (input ? [input] : []), [input]);\n const map = useRedeemLifecycles(inputs);\n if (!input) return INITIAL_STATE;\n return map[input.redeemId] ?? INITIAL_STATE;\n}\n","import { useContext } from \"react\";\nimport { AggAuthContext } from \"./core/providers/contexts\";\n\nexport interface GeoBlockState {\n /** Whether the user's location is blocked at the platform level. */\n isLocationBlocked: boolean;\n /** Whether trading is blocked for the user's location. */\n isTradingBlocked: boolean;\n /** Whether deposits are blocked for the user's location. */\n isDepositBlocked: boolean;\n}\n\nconst DEFAULT_STATE: GeoBlockState = {\n isLocationBlocked: false,\n isTradingBlocked: false,\n isDepositBlocked: false,\n};\n\n/**\n * Reads geo-block state from the authenticated user's profile.\n * Returns all-false when the user is not authenticated (no profile available).\n */\nexport function useGeoBlock(): GeoBlockState {\n const authContext = useContext(AggAuthContext);\n\n if (process.env.NEXT_PUBLIC_GEO_BLOCK_DISABLE === \"true\") return DEFAULT_STATE;\n\n const isBlocked = authContext?.user?.isLocationBlocked ?? false;\n\n if (!isBlocked) return DEFAULT_STATE;\n\n return {\n isLocationBlocked: true,\n isTradingBlocked: true,\n isDepositBlocked: true,\n };\n}\n","export type VenueAvailabilityState = \"available\" | \"geoblocked\" | \"hidden\";\n\nexport const normalizeVenueId = (venueId: string): string => venueId.trim().toLowerCase();\n\nconst getDisabledVenueSet = (disabledVenues?: readonly string[]): Set<string> => {\n return new Set((disabledVenues ?? []).map(normalizeVenueId));\n};\n\nexport const isVenueDisabledByConfig = (\n venueId: string,\n disabledVenues?: readonly string[],\n): boolean => {\n return getDisabledVenueSet(disabledVenues).has(normalizeVenueId(venueId));\n};\n\nexport const getVisibleVenuesByConfig = <TVenue extends { id: string }>(\n venues: readonly TVenue[],\n disabledVenues?: readonly string[],\n): TVenue[] => {\n const disabledVenueSet = getDisabledVenueSet(disabledVenues);\n\n return venues.filter((venue) => !disabledVenueSet.has(normalizeVenueId(venue.id)));\n};\n\nexport const getVisibleVenueIdsByConfig = <TVenueId extends string>(\n venueIds: readonly TVenueId[],\n disabledVenues?: readonly string[],\n): TVenueId[] => {\n const disabledVenueSet = getDisabledVenueSet(disabledVenues);\n\n return venueIds.filter((venueId) => !disabledVenueSet.has(normalizeVenueId(venueId)));\n};\n\nexport const getVenueAvailabilityState = ({\n venueId,\n disabledVenues,\n isConfigLoading,\n isLocationBlocked,\n}: {\n venueId: string;\n disabledVenues?: readonly string[];\n /**\n * Treat unresolved app configuration as hidden so venue-specific UI does not\n * flash before `/app/config` resolves.\n */\n isConfigLoading?: boolean;\n isLocationBlocked?: boolean;\n}): VenueAvailabilityState => {\n if (isConfigLoading) return \"hidden\";\n if (isVenueDisabledByConfig(venueId, disabledVenues)) return \"hidden\";\n if (isLocationBlocked) return \"geoblocked\";\n return \"available\";\n};\n","import type { Venue, VenueKeyStatus } from \"@agg-build/sdk\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport { useAggClient } from \"./core/provider\";\n\nexport const venueKeyQueryKeys = {\n all: [\"agg\", \"venue-keys\"] as const,\n status: (venue: Venue) => [...venueKeyQueryKeys.all, venue, \"status\"] as const,\n};\n\nexport const useVenueKeyStatus = (venue: Venue, enabled = true) => {\n const client = useAggClient();\n\n return useQuery<VenueKeyStatus>({\n queryKey: venueKeyQueryKeys.status(venue),\n queryFn: () => client.getVenueKeyStatus(venue),\n enabled,\n });\n};\n","import { useEffect, useRef } from \"react\";\nimport { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { useAggAuthContext, useAggClient } from \"./core/provider\";\nimport { useResolvedExecutionMode } from \"./use-resolved-execution-mode\";\nimport { invalidateBalanceQueries } from \"./execution/balance-invalidation\";\n\nexport const hostedVenueAccountQueryKeys = {\n all: [\"agg\", \"hosted-venue-account\"] as const,\n account: (venue: \"betdex\", userId: string | null, mode: string) =>\n [\"agg\", \"hosted-venue-account\", venue, userId, mode] as const,\n};\n\nexport function useHostedVenueAccount(venue: \"betdex\", enabled = true) {\n const client = useAggClient();\n const { user, isAuthenticated } = useAggAuthContext();\n const { executionMode, isResolving } = useResolvedExecutionMode();\n const queryClient = useQueryClient();\n const userId = user?.id ?? null;\n const permitted =\n enabled && isAuthenticated && userId !== null && !isResolving && executionMode === \"live\";\n const queryKey = hostedVenueAccountQueryKeys.account(venue, userId, executionMode);\n const session = useRef({ client, userId, executionMode, permitted });\n session.current = { client, userId, executionMode, permitted };\n const assertSession = () => {\n const current = session.current;\n if (\n !permitted ||\n !current.permitted ||\n current.client !== client ||\n current.userId !== userId ||\n current.executionMode !== executionMode\n )\n throw new Error(\"Hosted custody is unavailable for this session\");\n };\n const account = useQuery({\n queryKey,\n queryFn: () => {\n assertSession();\n return client.getHostedVenueAccount(venue, { mode: executionMode });\n },\n enabled: permitted,\n staleTime: 3_000,\n refetchInterval: permitted ? 5_000 : false,\n refetchIntervalInBackground: false,\n retry: false,\n });\n const provision = useMutation({\n mutationFn: (request: {\n run: () => ReturnType<typeof client.provisionHostedVenueAccount>;\n queryKey: typeof queryKey;\n }) => request.run(),\n // Retain the dispatch-time user key even if the observer changes users.\n onSuccess: (result, request) => {\n queryClient.setQueryData(request.queryKey, result);\n invalidateBalanceQueries(queryClient);\n },\n retry: false,\n });\n const { reset } = provision;\n useEffect(() => {\n reset();\n }, [userId, executionMode, reset]);\n const request = () => ({\n queryKey,\n run: () => {\n assertSession();\n return client.provisionHostedVenueAccount(venue, { mode: \"live\" });\n },\n });\n return {\n account,\n provision: {\n ...provision,\n mutate: () => provision.mutate(request()),\n mutateAsync: () => provision.mutateAsync(request()),\n },\n isAvailable: permitted,\n };\n}\n","import { useEffect, useRef } from \"react\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport { useAggAuthContext, useAggClient } from \"./core/provider\";\nimport { useResolvedExecutionMode } from \"./use-resolved-execution-mode\";\nimport { hostedVenueAccountQueryKeys } from \"./use-hosted-venue-account\";\n\n/** Display-only, explicitly requested pages. No automatic background polling. */\nexport function useHostedVenueActivity(venue: \"betdex\", page = 0, enabled = true) {\n const client = useAggClient();\n const { user, isAuthenticated } = useAggAuthContext();\n const { executionMode, isResolving } = useResolvedExecutionMode();\n const userId = user?.id ?? null;\n const permitted =\n enabled &&\n isAuthenticated &&\n userId !== null &&\n !isResolving &&\n executionMode === \"live\" &&\n Number.isInteger(page) &&\n page >= 0 &&\n page <= 9999;\n const session = useRef({ client, userId, executionMode, permitted });\n session.current = { client, userId, executionMode, permitted };\n const mounted = useRef(true);\n useEffect(() => {\n mounted.current = true;\n return () => {\n mounted.current = false;\n };\n }, []);\n const assertSession = () => {\n const current = session.current;\n if (\n !mounted.current ||\n !permitted ||\n !current.permitted ||\n current.client !== client ||\n current.userId !== userId ||\n current.executionMode !== executionMode\n )\n throw new Error(\"Hosted activity is unavailable for this session\");\n };\n const activity = useQuery({\n queryKey: [...hostedVenueAccountQueryKeys.all, \"activity\", venue, userId, executionMode, page],\n queryFn: async () => {\n assertSession();\n const result = await client.getHostedVenueActivity(venue, { mode: executionMode, page });\n assertSession();\n return result;\n },\n enabled: permitted,\n staleTime: 3000,\n retry: false,\n });\n return { activity, isAvailable: permitted };\n}\n","import { useCallback } from \"react\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport { useAggAuthContext, useAggClient } from \"./core/provider\";\n\nexport const sharedKycQueryKeys = {\n status: (userId: string | null) => [\"agg\", \"shared-kyc\", userId] as const,\n};\n\n/** Shared CH-backed identity state; legacy venue flags and callback query strings are not approval. */\nexport const useSharedKyc = () => {\n const client = useAggClient();\n const { isAuthenticated, user } = useAggAuthContext();\n const userId = user?.id ?? null;\n const query = useQuery({\n queryKey: sharedKycQueryKeys.status(userId),\n queryFn: () => client.getSharedKycStatus(),\n enabled: isAuthenticated && userId !== null,\n staleTime: 15_000,\n retry: false,\n });\n const { refetch } = query;\n\n const refreshStatus = useCallback(async (): Promise<\"verified\" | \"unverified\"> => {\n if (!isAuthenticated || !userId) return \"unverified\";\n const result = await refetch({ cancelRefetch: false });\n if (result.error) throw result.error;\n return result.data?.verified === true ? \"verified\" : \"unverified\";\n }, [isAuthenticated, userId, refetch]);\n\n const initiateVerification = useCallback(\n ({ venue, redirectUri }: { venue: string; redirectUri: string }) =>\n client.initiateKyc(venue, redirectUri),\n [client],\n );\n\n const status: \"loading\" | \"unverified\" | \"verified\" = !isAuthenticated\n ? \"unverified\"\n : !userId || query.isPending\n ? \"loading\"\n : query.data?.verified === true\n ? \"verified\"\n : \"unverified\";\n\n return { status, refreshStatus, initiateVerification };\n};\n","import { useCallback } from \"react\";\nimport type { UserProfile } from \"@agg-build/sdk\";\nimport { useAggAuthContext } from \"./core/provider\";\n\nexport interface UseAggAuthOptions {\n signMessage?: (message: string) => Promise<string>;\n address?: string;\n chainId?: number | string;\n /** Wallet chain — \"ethereum\" (default) or \"solana\". */\n chain?: \"ethereum\" | \"solana\";\n}\n\nexport interface UseAggAuthReturn {\n isAuthenticated: boolean;\n user: UserProfile | undefined;\n signIn: (statement?: string) => Promise<void>;\n signOut: () => Promise<void>;\n isLoading: boolean;\n error: Error | null;\n}\n\nexport function useAggAuth(options: UseAggAuthOptions = {}): UseAggAuthReturn {\n const {\n isAuthenticated,\n user,\n isLoading,\n error,\n signIn: signInWithProvider,\n signOut,\n } = useAggAuthContext();\n\n const signIn = useCallback(\n async (statement?: string) => {\n if (!options.signMessage) {\n throw new Error(\n \"signMessage is required to call signIn. Pass wallet options to useAggAuth().\",\n );\n }\n if (!options.address) {\n throw new Error(\"address is required to call signIn. Pass wallet options to useAggAuth().\");\n }\n\n await signInWithProvider({\n signMessage: options.signMessage,\n address: options.address,\n chainId: options.chainId,\n chain: options.chain,\n statement,\n });\n },\n [options.address, options.chain, options.chainId, options.signMessage, signInWithProvider],\n );\n\n return { isAuthenticated, user, signIn, signOut, isLoading, error };\n}\n","import { useCallback, useState } from \"react\";\nimport type {\n AggLinkAccountBody,\n AggLinkAccountConfirmResult,\n AggLinkAccountResult,\n AggLinkAccountWalletConfirmBody,\n} from \"@agg-build/sdk\";\nimport { useAggClient } from \"./core/provider\";\n\nexport interface UseLinkAccountReturn {\n startLink: (body: AggLinkAccountBody) => Promise<AggLinkAccountResult>;\n confirmLink: (\n input: string | AggLinkAccountWalletConfirmBody,\n ) => Promise<AggLinkAccountConfirmResult>;\n isLoading: boolean;\n error: Error | null;\n}\n\n/**\n * Hook for initiating and completing an account-link flow (OAuth / email / wallet).\n *\n * After an OAuth/email `startLink` call, the provider callback redirects the browser\n * back to the app's `redirectUrl` with a `link_confirm_token` query param. Read that\n * param on the redirect target route and pass it to `confirmLink`.\n *\n * Wallet providers (`siwe`/`siws`) instead return `{ type: \"wallet_challenge\", message }`\n * from `startLink`; sign that `message` verbatim and pass\n * `{ kind: \"wallet_signature\", message, signature }` to `confirmLink`.\n */\nexport function useLinkAccount(): UseLinkAccountReturn {\n const client = useAggClient();\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const run = <T>(fn: () => Promise<T>): Promise<T> => {\n setIsLoading(true);\n setError(null);\n return fn()\n .catch((e: unknown) => {\n const err = e instanceof Error ? e : new Error(String(e));\n setError(err);\n throw err;\n })\n .finally(() => setIsLoading(false));\n };\n\n const startLink = useCallback(\n (body: AggLinkAccountBody) => run(() => client.linkAccount(body)),\n [client],\n );\n\n const confirmLink = useCallback(\n (input: string | AggLinkAccountWalletConfirmBody) =>\n run(() => client.linkAccountConfirm(input)),\n [client],\n );\n\n return { startLink, confirmLink, isLoading, error };\n}\n","export const AUTH_CHOOSER_OPEN_EVENT = \"agg-auth:open-chooser\";\n\nexport interface AggAuthChooserOpenDetail {\n highlightMethod?: \"siwe\" | \"siws\" | \"google\" | \"twitter\" | \"apple\" | \"email\";\n}\n\nexport const requestAggAuthChooserOpen = (detail: AggAuthChooserOpenDetail = {}): void => {\n if (typeof window === \"undefined\") return;\n\n window.dispatchEvent(\n new CustomEvent<AggAuthChooserOpenDetail>(AUTH_CHOOSER_OPEN_EVENT, { detail }),\n );\n};\n","import { useInfiniteQuery, useQueries } from \"@tanstack/react-query\";\nimport type { Category } from \"@agg-build/sdk\";\nimport { useAggClient } from \"./core/provider\";\n\nexport interface UseCategoriesOptions {\n /** Optional query-key scope to isolate caches across different surfaces. */\n queryKeyScope?: string;\n /** Fetch child categories for a parent category id. Omit for top-level categories. */\n parentId?: string | null;\n enabled?: boolean;\n /** Page size when using cursor pagination. Default 20. */\n limit?: number;\n}\n\nexport interface UseCategoryChildrenOptions {\n /** Optional query-key scope to isolate caches across different surfaces. */\n queryKeyScope?: string;\n /** Parent category ids whose first child page should be fetched. */\n parentIds?: readonly (string | null | undefined)[];\n enabled?: boolean;\n /** Page size for each child query. Default 20. */\n limit?: number;\n}\n\n/**\n * Fetch categories via the API with cursor-based pagination.\n * Use fetchNextPage for \"Load more\". Same pattern as useVenueEvents.\n */\nexport function useCategories(options?: UseCategoriesOptions) {\n const client = useAggClient();\n const queryKeyScope = options?.queryKeyScope ?? \"categories\";\n const parentId = options?.parentId ?? null;\n const enabled = options?.enabled ?? true;\n const limit = options?.limit ?? 20;\n\n const query = useInfiniteQuery({\n queryKey: [queryKeyScope, \"parent\", parentId ?? \"__root__\", limit],\n queryFn: async ({ pageParam }) => {\n const res = await client.getCategories({\n limit,\n cursor: pageParam as string | undefined,\n ...(parentId != null ? { parentId } : {}),\n });\n return res;\n },\n initialPageParam: undefined as string | undefined,\n getNextPageParam: (lastPage) => lastPage.nextCursor ?? undefined,\n enabled,\n });\n\n const categories = query.data?.pages.flatMap((p) => p.data) ?? [];\n const hasNextPage = !!query.hasNextPage;\n\n return {\n ...query,\n categories,\n hasNextPage,\n };\n}\n\n/**\n * Fetch the first page of children for multiple parent categories.\n * This is intentionally first-page only: it is used to render folder affordances\n * and keep already-open branches visible without issuing one-off queries inside\n * the component tree for every rendered row.\n */\nexport function useCategoryChildren(options?: UseCategoryChildrenOptions) {\n const client = useAggClient();\n const queryKeyScope = options?.queryKeyScope ?? \"category-children\";\n const enabled = options?.enabled ?? true;\n const limit = options?.limit ?? 20;\n const parentIds = Array.from(\n new Set((options?.parentIds ?? []).filter((parentId): parentId is string => Boolean(parentId))),\n );\n\n const queries = useQueries({\n queries: parentIds.map((parentId) => ({\n queryKey: [queryKeyScope, \"parent\", parentId, limit],\n queryFn: async () => {\n return client.getCategories({\n limit,\n cursor: undefined,\n parentId,\n });\n },\n enabled,\n })),\n });\n\n const childrenByParentId = new Map<string, Category[]>();\n\n queries.forEach((query, index) => {\n const parentId = parentIds[index];\n if (!parentId) return;\n childrenByParentId.set(parentId, query.data?.data ?? []);\n });\n\n return {\n queries,\n childrenByParentId,\n isLoading: queries.some((query) => query.isLoading),\n };\n}\n","import { useEffect, useState } from \"react\";\n\nexport function useDebouncedValue<T>(value: T, delay: number): T {\n const [debouncedValue, setDebouncedValue] = useState(value);\n\n useEffect(() => {\n const timeoutId = window.setTimeout(() => {\n setDebouncedValue(value);\n }, delay);\n\n return () => {\n window.clearTimeout(timeoutId);\n };\n }, [value, delay]);\n\n return debouncedValue;\n}\n","import { useInfiniteQuery } from \"@tanstack/react-query\";\nimport type { GetOrdersQuery, OrderListItem } from \"@agg-build/sdk\";\nimport { useAggClient } from \"./core/provider\";\n\ntype ExecutionOrderStatusInput =\n | NonNullable<GetOrdersQuery[\"status\"]>\n | `${NonNullable<GetOrdersQuery[\"status\"]>}`;\n\nexport interface UseExecutionOrdersOptions extends Omit<GetOrdersQuery, \"cursor\" | \"status\"> {\n status?: ExecutionOrderStatusInput;\n enabled?: boolean;\n mode?: \"live\" | \"paper\";\n refetchIntervalMs?: number | false;\n}\n\nexport function useExecutionOrders(options: UseExecutionOrdersOptions = {}) {\n const client = useAggClient();\n const {\n status,\n orderType,\n orderId,\n quoteId,\n venueMarketIds,\n mode,\n limit = 50,\n enabled = true,\n refetchIntervalMs = false,\n } = options;\n\n // Sorted + deduped so the same set of markets in any order shares one cache\n // entry; empty means \"no filter\", matching the API.\n const venueMarketIdsKey = venueMarketIds?.length ? [...new Set(venueMarketIds)].sort() : null;\n\n const query = useInfiniteQuery({\n // quoteId + orderId are part of the cache key — different filters\n // produce different result sets, so they have to vary the key.\n queryKey: [\n \"execution-orders\",\n status ?? \"all\",\n quoteId ?? null,\n orderId ?? null,\n ...(venueMarketIdsKey ? [{ venueMarketIds: venueMarketIdsKey }] : []),\n ...(orderType ? [orderType] : []),\n ...(mode ? [mode] : []),\n limit,\n ],\n queryFn: ({ pageParam }) =>\n client.getExecutionOrders({\n status: status as GetOrdersQuery[\"status\"],\n orderType,\n orderId,\n quoteId,\n ...(venueMarketIdsKey ? { venueMarketIds: venueMarketIdsKey } : {}),\n ...(mode ? { mode } : {}),\n limit,\n cursor: pageParam as string | undefined,\n }),\n initialPageParam: undefined as string | undefined,\n getNextPageParam: (lastPage) =>\n lastPage.hasMore ? (lastPage.nextCursor ?? undefined) : undefined,\n enabled,\n refetchInterval: refetchIntervalMs,\n });\n\n const orders = query.data?.pages.flatMap((page) => page.data) ?? [];\n const hasNextPage = !!query.hasNextPage;\n\n return {\n ...query,\n orders: orders as OrderListItem[],\n hasNextPage,\n };\n}\n","import { useQueries, type UseQueryResult } from \"@tanstack/react-query\";\nimport type { GetOrdersQuery, OrderListItem } from \"@agg-build/sdk\";\nimport { useMemo } from \"react\";\nimport { useAggClient } from \"./core/provider\";\n\n/**\n * Market ids sent per `GET /execution/orders` request. The API has no cap; this\n * keeps the repeated-param URL under common CDN limits — the same batch size\n * `getMidpoints` uses.\n */\nexport const MAX_ORDER_VENUE_MARKET_IDS_PER_REQUEST = 75;\n\nconst DEFAULT_PAGE_LIMIT = 100;\nconst DEFAULT_MAX_PAGES_PER_BATCH = 5;\n\nexport interface UseExecutionOrdersForMarketsOptions {\n /** Any number of venue markets — split into batches of 75, one request each. */\n venueMarketIds: ReadonlyArray<string>;\n status?: GetOrdersQuery[\"status\"] | `${NonNullable<GetOrdersQuery[\"status\"]>}`;\n orderType?: \"market\" | \"limit\";\n mode?: \"live\" | \"paper\";\n /** Page size per request, max 100. */\n limit?: number;\n /**\n * Pages read per batch before giving up. Orders come newest first across\n * every status, so a long history on these markets can outrun one page.\n */\n maxPagesPerBatch?: number;\n enabled?: boolean;\n}\n\nexport interface UseExecutionOrdersForMarketsResult {\n orders: OrderListItem[];\n isLoading: boolean;\n error: Error | null;\n /** A batch still had pages left at `maxPagesPerBatch` — the list may be incomplete. */\n isTruncated: boolean;\n}\n\ntype BatchResult = { orders: OrderListItem[]; hasMore: boolean };\n\n/** Module-level so React Query can keep its result stable between renders. */\nconst combineBatches = (\n results: UseQueryResult<BatchResult, Error>[],\n): UseExecutionOrdersForMarketsResult => ({\n orders: results.flatMap((result) => result.data?.orders ?? []),\n isLoading: results.some((result) => result.isLoading),\n error: results.find((result) => result.error)?.error ?? null,\n isTruncated: results.some((result) => result.data?.hasMore === true),\n});\n\nconst chunk = <T>(items: T[], size: number): T[][] => {\n const chunks: T[][] = [];\n for (let index = 0; index < items.length; index += size) {\n chunks.push(items.slice(index, index + size));\n }\n return chunks;\n};\n\n/**\n * The user's orders on a set of venue markets, however many there are. Long\n * lists are split into batches of 75 to keep each URL short; the batches run\n * in parallel, each reading its own pages, and the results are merged.\n *\n * Query keys start with `\"execution-orders\"`, so placing or cancelling an\n * order invalidates these along with `useExecutionOrders`.\n */\nexport function useExecutionOrdersForMarkets({\n venueMarketIds,\n status,\n orderType,\n mode,\n limit = DEFAULT_PAGE_LIMIT,\n maxPagesPerBatch = DEFAULT_MAX_PAGES_PER_BATCH,\n enabled = true,\n}: UseExecutionOrdersForMarketsOptions): UseExecutionOrdersForMarketsResult {\n const client = useAggClient();\n\n // Sorted + deduped first so the same markets in any order produce the same\n // batches, and so the same cache entries.\n const batchKey = [...new Set(venueMarketIds)].sort().join(\",\");\n const batches = useMemo(\n () => (batchKey ? chunk(batchKey.split(\",\"), MAX_ORDER_VENUE_MARKET_IDS_PER_REQUEST) : []),\n [batchKey],\n );\n\n return useQueries({\n combine: combineBatches,\n queries: batches.map((batchVenueMarketIds) => ({\n queryKey: [\n \"execution-orders\",\n \"by-markets\",\n batchVenueMarketIds,\n status ?? \"all\",\n orderType ?? null,\n mode ?? null,\n limit,\n maxPagesPerBatch,\n ],\n queryFn: async (): Promise<BatchResult> => {\n const orders: OrderListItem[] = [];\n let cursor: string | undefined;\n\n for (let page = 0; page < maxPagesPerBatch; page += 1) {\n const response = await client.getExecutionOrders({\n venueMarketIds: batchVenueMarketIds,\n status: status as GetOrdersQuery[\"status\"],\n orderType,\n ...(mode ? { mode } : {}),\n limit,\n ...(cursor ? { cursor } : {}),\n });\n orders.push(...(response.data as OrderListItem[]));\n cursor = response.hasMore ? (response.nextCursor ?? undefined) : undefined;\n if (!cursor) return { orders, hasMore: false };\n }\n\n return { orders, hasMore: true };\n },\n enabled,\n })),\n });\n}\n","import { keepPreviousData, useInfiniteQuery } from \"@tanstack/react-query\";\nimport type {\n PaginatedResponse,\n UserActivityItem,\n UserActivityQuery,\n UserActivityType,\n} from \"@agg-build/sdk\";\nimport { useAggClient } from \"./core/provider\";\nimport { userActivityQueryKeys } from \"./execution/balance-invalidation\";\n\nexport interface UseUserActivityOptions extends Omit<UserActivityQuery, \"cursor\"> {\n enabled?: boolean;\n /**\n * Poll interval (ms) used while any cached activity row is mid-lifecycle\n * (deposit pending, withdrawal bridging, trade submitted, etc.). Idle\n * feeds — every row in a terminal state — don't poll. Set to `false` to\n * disable the lifecycle-aware poll entirely.\n *\n * Defaults to 15s.\n */\n pendingRefetchIntervalMs?: number | false;\n}\n\nconst DEFAULT_PENDING_REFETCH_INTERVAL_MS = 15_000;\n\n/**\n * Non-terminal status strings seen across the three activity-item shapes the\n * profile feed renders (`trade`, `deposit`, `withdrawal`). Anything in this\n * set means the backend will eventually flip the row to a terminal state, so\n * the feed should poll until it does.\n *\n * Kept lowercase for case-insensitive matching against `item.status`.\n */\nconst PENDING_ACTIVITY_STATUSES = new Set<string>([\n \"pending\",\n // trade pre-fill lifecycle\n \"signing\",\n \"pending_bridge\",\n \"submitting\",\n \"submitted\",\n // withdrawal lifecycle\n \"bridging\",\n \"transferring\",\n]);\n\nconst hasPendingActivity = (\n pages: ReadonlyArray<PaginatedResponse<UserActivityItem>> | undefined,\n): boolean => {\n if (!pages) return false;\n for (const page of pages) {\n for (const item of page.data) {\n if (\n item.type === \"redeem\" &&\n item.legs.length > 0 &&\n item.legs.every((leg) => leg.status.toLowerCase() === \"confirmed\")\n ) {\n continue;\n }\n if (PENDING_ACTIVITY_STATUSES.has(item.status.toLowerCase())) return true;\n }\n }\n return false;\n};\n\nexport function useUserActivity(options: UseUserActivityOptions = {}) {\n const client = useAggClient();\n const {\n type,\n limit = 50,\n enabled = true,\n pendingRefetchIntervalMs = DEFAULT_PENDING_REFETCH_INTERVAL_MS,\n } = options;\n\n const query = useInfiniteQuery({\n queryKey: userActivityQueryKeys.feed(type, limit),\n queryFn: ({ pageParam }) =>\n client.getUserActivity({\n type: type as UserActivityType | undefined,\n limit,\n cursor: pageParam as string | undefined,\n }),\n initialPageParam: undefined as string | undefined,\n getNextPageParam: (lastPage) =>\n lastPage.hasMore ? (lastPage.nextCursor ?? undefined) : undefined,\n enabled,\n // Keep the previously-loaded pages visible while a refetch is in\n // flight (typically after a deposit / withdraw cache invalidation).\n // Without this the feed flashes to the skeleton mid-session, which\n // is worse UX than briefly showing slightly-stale rows.\n placeholderData: keepPreviousData,\n refetchInterval: (q) => {\n if (pendingRefetchIntervalMs === false) return false;\n const data = q.state.data as { pages: PaginatedResponse<UserActivityItem>[] } | undefined;\n return hasPendingActivity(data?.pages) ? pendingRefetchIntervalMs : false;\n },\n });\n\n const activities = query.data?.pages.flatMap((page) => page.data) ?? [];\n const hasNextPage = !!query.hasNextPage;\n\n return {\n ...query,\n activities: activities as UserActivityItem[],\n hasNextPage,\n };\n}\n","import { keepPreviousData, useInfiniteQuery } from \"@tanstack/react-query\";\nimport type { LeaderboardMetric, LeaderboardRow, PaginatedResponse } from \"@agg-build/sdk\";\nimport { useAggClient } from \"./core/provider\";\n\n/** Preset ranges the leaderboard UI offers. The API itself takes any from/to. */\nexport type LeaderboardPeriod = \"1d\" | \"7d\" | \"30d\" | \"all\";\nexport const LEADERBOARD_PERIODS: readonly LeaderboardPeriod[] = [\"1d\", \"7d\", \"30d\", \"all\"];\n\nexport interface UseLeaderboardOptions {\n /** Default `30d`. */\n period?: LeaderboardPeriod;\n /** Default `realizedPnl`. */\n metric?: LeaderboardMetric;\n /** Page size, 1..100. Default 50. */\n limit?: number;\n enabled?: boolean;\n}\n\nconst utcDayKey = (d: Date): string => d.toISOString().slice(0, 10);\n\n/**\n * Inclusive UTC day range for a preset. `1d` is today, `7d` is the last 7\n * UTC days including today, `30d` the last 30. `all` returns no bounds.\n */\nexport function leaderboardRange(\n period: LeaderboardPeriod,\n now: Date = new Date(),\n): { from?: string; to?: string } {\n if (period === \"all\") return {};\n const spanDays = period === \"1d\" ? 0 : period === \"7d\" ? 6 : 29;\n const from = new Date(\n Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate() - spanDays),\n );\n return { from: utcDayKey(from), to: utcDayKey(now) };\n}\n\nexport const leaderboardQueryKeys = {\n all: () => [\"leaderboard\"] as const,\n list: (period: LeaderboardPeriod, metric: LeaderboardMetric, limit: number) =>\n [\"leaderboard\", period, metric, limit] as const,\n};\n\n/** 60 s: the API caches leaderboard responses for the same window. */\nconst LEADERBOARD_STALE_TIME_MS = 60_000;\n\nexport function useLeaderboard(options: UseLeaderboardOptions = {}) {\n const client = useAggClient();\n const { period = \"30d\", metric = \"realizedPnl\", limit = 50, enabled = true } = options;\n\n const query = useInfiniteQuery({\n queryKey: leaderboardQueryKeys.list(period, metric, limit),\n queryFn: ({ pageParam }) =>\n client.getLeaderboard({\n ...leaderboardRange(period),\n metric,\n limit,\n cursor: pageParam as string | undefined,\n }),\n initialPageParam: undefined as string | undefined,\n getNextPageParam: (lastPage: PaginatedResponse<LeaderboardRow>) =>\n lastPage.hasMore ? (lastPage.nextCursor ?? undefined) : undefined,\n enabled,\n // Keep the previous list on screen while a period/metric switch loads.\n placeholderData: keepPreviousData,\n staleTime: LEADERBOARD_STALE_TIME_MS,\n });\n\n // A trader can move across a page boundary between fetches; keep the first\n // occurrence so row keys stay unique.\n const seen = new Set<string>();\n const rows = (query.data?.pages.flatMap((page) => page.data) ?? []).filter((row) => {\n if (seen.has(row.userId)) return false;\n seen.add(row.userId);\n return true;\n });\n\n return {\n ...query,\n rows: rows as LeaderboardRow[],\n hasNextPage: !!query.hasNextPage,\n };\n}\n","import type { UserProfile } from \"@agg-build/sdk\";\nimport { useCallback, useState } from \"react\";\nimport { useAggClient } from \"./core/provider\";\n\nexport interface UseExternalIdOptions {\n onSuccess?: (profile: UserProfile) => void;\n onError?: (error: Error) => void;\n}\n\nexport interface UseExternalIdReturn {\n linkExternalId: (assertion: {\n externalId: string;\n timestamp: number;\n hmac: string;\n }) => Promise<UserProfile>;\n isLoading: boolean;\n error: Error | null;\n}\n\nexport function useExternalId(options: UseExternalIdOptions = {}): UseExternalIdReturn {\n const client = useAggClient();\n const { onSuccess, onError: onErrorCb } = options;\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const linkExternalId = useCallback(\n async (assertion: {\n externalId: string;\n timestamp: number;\n hmac: string;\n }): Promise<UserProfile> => {\n setIsLoading(true);\n setError(null);\n\n try {\n const profile = await client.linkExternalId(assertion);\n onSuccess?.(profile);\n return profile;\n } catch (err) {\n const resolvedError = err instanceof Error ? err : new Error(String(err));\n setError(resolvedError);\n onErrorCb?.(resolvedError);\n throw resolvedError;\n } finally {\n setIsLoading(false);\n }\n },\n [client, onErrorCb, onSuccess],\n );\n\n return { linkExternalId, isLoading, error };\n}\n","import { useInfiniteQuery } from \"@tanstack/react-query\";\nimport type { GetPositionsQuery, PositionGroup } from \"@agg-build/sdk\";\nimport { useAggClient } from \"./core/provider\";\nimport { executionKeys } from \"./execution/query-keys\";\n\nexport interface UseExecutionPositionsOptions extends Omit<GetPositionsQuery, \"cursor\"> {\n enabled?: boolean;\n mode?: \"live\" | \"paper\";\n}\n\nexport function useExecutionPositions(options: UseExecutionPositionsOptions = {}) {\n const client = useAggClient();\n const { limit = 50, status, mode, enabled = true } = options;\n\n const query = useInfiniteQuery({\n queryKey: executionKeys.positions(null, limit, status ?? null, mode ?? null),\n queryFn: ({ pageParam }) =>\n client.getExecutionPositions({\n limit,\n status,\n ...(mode ? { mode } : {}),\n cursor: pageParam as string | undefined,\n }),\n initialPageParam: undefined as string | undefined,\n getNextPageParam: (lastPage) =>\n lastPage.hasMore ? (lastPage.nextCursor ?? undefined) : undefined,\n enabled,\n });\n\n const positions = query.data?.pages.flatMap((page) => page.data) ?? [];\n const hasNextPage = !!query.hasNextPage;\n\n return {\n ...query,\n positions: positions as PositionGroup[],\n hasNextPage,\n };\n}\n","import { isAggApiError } from \"@agg-build/sdk\";\nimport { isServer, type QueryObserverOptions } from \"@tanstack/react-query\";\n\ntype ReadRetryOptions = Pick<QueryObserverOptions, \"retry\" | \"retryDelay\">;\nconst MAX_TIMER_DELAY_MS = 2_147_483_647;\nconst hint = (error: Error): number | undefined => {\n if (!isAggApiError(error)) return undefined;\n const value = error.retryAfterMs;\n return typeof value === \"number\" && Number.isSafeInteger(value) && value >= 0 ? value : undefined;\n};\n\n/** Read-query policy only: retain configured retry counts, honoring API delays without retrying early. */\nexport function withReadRetry(options: ReadRetryOptions): {\n retry: (failureCount: number, error: Error) => boolean;\n retryDelay: (attempt: number, error: Error) => number;\n} {\n return {\n retry: (failureCount, error) => {\n // Oversized setTimeout delays overflow to ~1ms in supported runtimes. Stop instead.\n if ((hint(error) ?? 0) > MAX_TIMER_DELAY_MS) return false;\n const retry = options.retry ?? (isServer ? 0 : 3);\n return typeof retry === \"function\"\n ? retry(failureCount, error)\n : retry === true || (typeof retry === \"number\" && failureCount < retry);\n },\n retryDelay: (attempt, error) =>\n hint(error) ??\n (typeof options.retryDelay === \"function\"\n ? options.retryDelay(attempt, error)\n : (options.retryDelay ?? Math.min(1000 * 2 ** attempt, 30_000))),\n };\n}\n","import type { ChartBarsMeta, ChartBarsResponse, WsCandleInterval, WsTrade } from \"@agg-build/sdk\";\n\nexport interface MarketChartCandle {\n time: number;\n open: number;\n high: number;\n low: number;\n close: number;\n mean?: number;\n volume: number | null;\n source: \"rest\" | \"ws\" | \"trade\" | \"midpoint\";\n}\n\nexport interface MarketChartVenueData {\n venue: string;\n /** Venue-scoped outcome IDs that contributed to this venue series. */\n outcomeIds: string[];\n candles: MarketChartCandle[];\n liveCandle: MarketChartCandle | null;\n lineValue: number | undefined;\n lastTrade: WsTrade | null;\n /**\n * Epoch seconds of the most recent real REST or WS update that touched this\n * venue (REST candle, trade, or midpoint). Used by the renderer's stale-data\n * indicator — independent of any synthetic point that `extendSeriesToNow`\n * projects onto the line. `null` when nothing has been seen yet.\n */\n lastUpdateTs: number | null;\n}\n\nexport interface MarketChartData {\n /** Delivery availability/freshness from the history source, unaffected by stream ticks. */\n delivery?: ChartBarsMeta;\n marketId: string;\n /** All venue-scoped outcome IDs that were requested for this chart selection. */\n outcomeIds: string[];\n /** Venue key for the canonical historical bar series returned by GET /charts/bars. */\n primaryVenue: string;\n interval: WsCandleInterval;\n startTs: number | null;\n endTs: number | null;\n /** Per-venue chart state. The primary venue contains the canonical REST history. */\n venues: Record<string, MarketChartVenueData>;\n /**\n * Max of `lastUpdateTs` across all venues. Surfaced separately so the\n * renderer can show a stale indicator without crawling the venues map.\n */\n lastUpdateTs: number | null;\n}\n\n/**\n * Largest range we support (`ALL` ≈ 6 months) plus a generous buffer. The\n * cache prunes closed candles older than this so a long-lived session\n * doesn't grow the array unboundedly as WS pushes new bars over hours/days.\n */\nexport const MAX_CACHE_RETENTION_SECONDS = 7 * 30 * 24 * 60 * 60 + 14 * 24 * 60 * 60;\n\nexport const getIntervalSeconds = (interval: WsCandleInterval): number => {\n switch (interval) {\n case \"1m\":\n return 60;\n case \"5m\":\n return 5 * 60;\n case \"1h\":\n return 60 * 60;\n case \"1d\":\n return 24 * 60 * 60;\n }\n};\n\nconst createVenueData = (venue: string, outcomeIds: string[] = []): MarketChartVenueData => ({\n venue,\n outcomeIds,\n candles: [],\n liveCandle: null,\n lineValue: undefined,\n lastTrade: null,\n lastUpdateTs: null,\n});\n\nconst pruneCandlesBefore = (\n candles: MarketChartCandle[],\n cutoffTs: number,\n): MarketChartCandle[] => {\n if (cutoffTs <= 0) return candles;\n let firstKeptIndex = 0;\n while (firstKeptIndex < candles.length && candles[firstKeptIndex].time < cutoffTs) {\n firstKeptIndex += 1;\n }\n if (firstKeptIndex === 0) return candles;\n return candles.slice(firstKeptIndex);\n};\n\n/**\n * If `liveCandle` belongs to a strictly earlier bucket than `expectedCandleTime`,\n * the bar has closed. Promote it onto the end of `candles[]` (deduped by time)\n * so the now-closed bar persists in history instead of being thrown away when\n * the next bucket starts forming.\n */\nconst promoteClosedLiveCandle = (\n candles: MarketChartCandle[],\n liveCandle: MarketChartCandle | null,\n expectedCandleTime: number,\n): { candles: MarketChartCandle[]; promoted: boolean } => {\n if (!liveCandle || liveCandle.time >= expectedCandleTime) {\n return { candles, promoted: false };\n }\n if (candles.some((candle) => candle.time === liveCandle.time)) {\n return { candles, promoted: false };\n }\n return { candles: sortCandles([...candles, liveCandle]), promoted: true };\n};\n\nconst resolveMaxLastUpdateTs = (venues: Record<string, MarketChartVenueData>): number | null => {\n let max: number | null = null;\n for (const venueData of Object.values(venues)) {\n if (venueData.lastUpdateTs != null && (max == null || venueData.lastUpdateTs > max)) {\n max = venueData.lastUpdateTs;\n }\n }\n return max;\n};\n\nconst sortCandles = (candles: MarketChartCandle[]): MarketChartCandle[] => {\n return [...candles].sort((left, right) => left.time - right.time);\n};\n\nconst _upsertFinalCandle = (\n candles: MarketChartCandle[],\n nextCandle: MarketChartCandle,\n): MarketChartCandle[] => {\n const index = candles.findIndex((candle) => candle.time === nextCandle.time);\n if (index < 0) return sortCandles([...candles, nextCandle]);\n\n const nextCandles = [...candles];\n nextCandles[index] = nextCandle;\n return nextCandles;\n};\n\nexport const createMarketChartData = (params: {\n marketId: string;\n interval: WsCandleInterval;\n startTs: number | null;\n endTs: number | null;\n response: ChartBarsResponse;\n}): MarketChartData => {\n const candles = sortCandles(\n params.response.data.map((candle) => ({\n time: Math.floor(candle.t / 1000),\n open: candle.o,\n high: candle.h,\n low: candle.l,\n close: candle.c,\n ...(Number.isFinite(candle.mean) ? { mean: candle.mean } : {}),\n volume: candle.v,\n source: \"rest\" as const,\n })),\n );\n const lastCandle = candles[candles.length - 1];\n const lastUpdateTs = lastCandle?.time ?? null;\n const venues = {\n [params.response.venue]: {\n venue: params.response.venue,\n outcomeIds: [params.response.venueMarketOutcomeId],\n candles,\n liveCandle: null,\n lineValue: lastCandle?.close,\n lastTrade: null,\n lastUpdateTs,\n } satisfies MarketChartVenueData,\n };\n\n return {\n marketId: params.marketId,\n delivery: params.response.meta,\n outcomeIds: [params.response.venueMarketOutcomeId],\n primaryVenue: params.response.venue,\n interval: params.interval,\n startTs: params.startTs,\n endTs: params.endTs,\n venues,\n lastUpdateTs,\n };\n};\n\nexport const mergeMarketChartData = (params: {\n marketId: string;\n interval: WsCandleInterval;\n startTs: number | null;\n endTs: number | null;\n datasets: MarketChartData[];\n}): MarketChartData | null => {\n if (params.datasets.length === 0) {\n return null;\n }\n\n const primaryVenue = params.datasets[0]?.primaryVenue ?? \"aggregate\";\n const outcomeIds = Array.from(\n new Set(\n params.datasets.flatMap((dataset) => {\n return dataset.outcomeIds.length > 0 ? dataset.outcomeIds : [dataset.marketId];\n }),\n ),\n );\n\n const venues = params.datasets.reduce<Record<string, MarketChartVenueData>>((acc, dataset) => {\n for (const [venue, venueData] of Object.entries(dataset.venues)) {\n const existingVenueData = acc[venue];\n\n // We expect one logical outcome series per venue for this chart flow.\n // If that assumption changes, the aggregation layer should be extended\n // to merge duplicate venue keys instead of overwriting them here.\n acc[venue] = existingVenueData\n ? {\n ...venueData,\n outcomeIds: Array.from(\n new Set([...existingVenueData.outcomeIds, ...venueData.outcomeIds]),\n ),\n }\n : venueData;\n }\n\n return acc;\n }, {});\n\n return {\n marketId: params.marketId,\n delivery:\n params.datasets.find((dataset) => dataset.marketId === params.marketId)?.delivery ??\n params.datasets[0]?.delivery,\n outcomeIds,\n primaryVenue,\n interval: params.interval,\n startTs: params.startTs,\n endTs: params.endTs,\n venues,\n lastUpdateTs: resolveMaxLastUpdateTs(venues),\n };\n};\n\nexport interface MarketChartMidpointUpdate {\n outcomeId: string;\n midpoint: number;\n /** Seconds since epoch. */\n timestamp: number;\n}\n\n/**\n * Apply an orderbook midpoint to the chart cache.\n *\n * Why: trades are the canonical source of price movement, but many markets\n * trade rarely. The orderbook ticks every few seconds via deltas; reflecting\n * the midpoint into a forming candle keeps the chart line moving in sync\n * with the orderbook UI rather than freezing at the last REST close.\n *\n * The midpoint never overrides a candle that has already received a real\n * trade in the same bucket — trades win on close/high/low/volume. Midpoint\n * updates only seed an empty bucket or extend a midpoint-sourced candle.\n *\n * Each chart cache entry is keyed by a single venue-scoped outcomeId, so the\n * target venue is the one whose `outcomeIds` contains `update.outcomeId`.\n * REST bootstrap always seeds exactly that one venue, so this lookup is\n * deterministic.\n */\nexport const applyMidpointToMarketChart = (\n data: MarketChartData | null | undefined,\n update: MarketChartMidpointUpdate,\n): MarketChartData | null | undefined => {\n if (!data || !Number.isFinite(update.midpoint)) {\n return data;\n }\n\n const targetVenueEntry = Object.entries(data.venues).find(([, venueData]) =>\n venueData.outcomeIds.includes(update.outcomeId),\n );\n\n if (!targetVenueEntry && data.marketId !== update.outcomeId) {\n return data;\n }\n\n const [targetVenueName, currentVenue] = targetVenueEntry ?? [\n data.primaryVenue,\n data.venues[data.primaryVenue] ?? createVenueData(data.primaryVenue, [update.outcomeId]),\n ];\n const intervalSeconds = getIntervalSeconds(data.interval);\n const expectedCandleTime = update.timestamp - (update.timestamp % intervalSeconds);\n\n let liveCandle = currentVenue.liveCandle;\n // Promote any closed (earlier-bucket) liveCandle into history before\n // starting/updating the current bucket. Without this, an older liveCandle\n // would be discarded when the next bucket's first update arrives.\n const { candles: promotedCandles } = promoteClosedLiveCandle(\n currentVenue.candles,\n liveCandle,\n expectedCandleTime,\n );\n // Drop closed bars older than our retention horizon so a long-lived\n // session can't grow the array unboundedly.\n const nextCandles = pruneCandlesBefore(\n promotedCandles,\n update.timestamp - MAX_CACHE_RETENTION_SECONDS,\n );\n\n if (liveCandle && liveCandle.time === expectedCandleTime) {\n if (liveCandle.source === \"trade\") {\n // Trades dominate: only roll the close so the line tracks the latest\n // mid, but do not stomp the trade-derived high/low/volume.\n liveCandle = {\n ...liveCandle,\n close: update.midpoint,\n };\n } else {\n liveCandle = {\n ...liveCandle,\n close: update.midpoint,\n high: Math.max(liveCandle.high, update.midpoint),\n low: Math.min(liveCandle.low, update.midpoint),\n source: \"midpoint\",\n };\n }\n } else {\n liveCandle = {\n time: expectedCandleTime,\n open: update.midpoint,\n high: update.midpoint,\n low: update.midpoint,\n close: update.midpoint,\n volume: 0,\n source: \"midpoint\",\n };\n }\n\n const nextVenues = {\n ...data.venues,\n [targetVenueName]: {\n ...currentVenue,\n outcomeIds: currentVenue.outcomeIds.includes(update.outcomeId)\n ? currentVenue.outcomeIds\n : [...currentVenue.outcomeIds, update.outcomeId],\n candles: nextCandles,\n liveCandle,\n lineValue: update.midpoint,\n lastUpdateTs: update.timestamp,\n },\n };\n\n return {\n ...data,\n venues: nextVenues,\n lastUpdateTs: resolveMaxLastUpdateTs(nextVenues),\n };\n};\n\nexport const applyTradeToMarketChart = (\n data: MarketChartData | null | undefined,\n trade: WsTrade,\n): MarketChartData | null | undefined => {\n if (!data || data.marketId !== trade.outcomeId) {\n return data;\n }\n\n const currentVenue = data.venues[trade.venue] ?? createVenueData(trade.venue);\n const intervalSeconds = getIntervalSeconds(data.interval);\n const expectedCandleTime = trade.timestamp - (trade.timestamp % intervalSeconds);\n\n let liveCandle = currentVenue.liveCandle;\n const { candles: promotedCandles } = promoteClosedLiveCandle(\n currentVenue.candles,\n liveCandle,\n expectedCandleTime,\n );\n const nextCandles = pruneCandlesBefore(\n promotedCandles,\n trade.timestamp - MAX_CACHE_RETENTION_SECONDS,\n );\n\n if (liveCandle && liveCandle.time === expectedCandleTime) {\n liveCandle = {\n ...liveCandle,\n close: trade.price,\n high: Math.max(liveCandle.high, trade.price),\n low: Math.min(liveCandle.low, trade.price),\n volume: (liveCandle.volume ?? 0) + trade.size,\n source: \"trade\",\n };\n } else if (!liveCandle || liveCandle.time !== expectedCandleTime) {\n liveCandle = {\n time: expectedCandleTime,\n open: trade.price,\n high: trade.price,\n low: trade.price,\n close: trade.price,\n volume: trade.size,\n source: \"trade\",\n };\n }\n\n const nextVenues = {\n ...data.venues,\n [trade.venue]: {\n ...currentVenue,\n outcomeIds: currentVenue.outcomeIds.includes(trade.outcomeId)\n ? currentVenue.outcomeIds\n : [...currentVenue.outcomeIds, trade.outcomeId],\n candles: nextCandles,\n liveCandle,\n lineValue: liveCandle?.close ?? trade.price,\n lastTrade: trade,\n lastUpdateTs: trade.timestamp,\n },\n };\n\n return {\n ...data,\n venues: nextVenues,\n lastUpdateTs: resolveMaxLastUpdateTs(nextVenues),\n };\n};\n","import {\n loadImmutableHistory,\n isAggApiError,\n type AggClient,\n type AggWebSocket,\n type ChartBarsResponse,\n type ChartHistoryManifest,\n type ChartCandle,\n} from \"@agg-build/sdk\";\n\nexport class ChartDeliveryError extends Error {\n constructor(\n readonly state: NonNullable<ChartBarsResponse[\"meta\"][\"state\"]>,\n readonly retryAfterMs?: number,\n ) {\n super(`Chart delivery ${state}`);\n this.name = \"ChartDeliveryError\";\n }\n}\nconst usable = (response: ChartBarsResponse): ChartBarsResponse => {\n if (response.data.length === 0 && response.meta?.state && response.meta.state !== \"empty\")\n throw new ChartDeliveryError(response.meta.state, response.meta.retryAfterMs);\n return response;\n};\nconst withActualFreshness = (response: ChartBarsResponse): ChartBarsResponse => {\n const serverTime = Number.isFinite(response.meta.serverTime)\n ? response.meta.serverTime\n : Date.now();\n const lastBarOpenTime = response.data.at(-1)?.t ?? null;\n return {\n ...response,\n meta: {\n ...response.meta,\n serverTime,\n lastBarOpenTime,\n staleSeconds:\n lastBarOpenTime == null ? null : Math.max(0, (serverTime - lastBarOpenTime) / 1000),\n },\n };\n};\n\n/** API checks app visibility; finalized objects and dynamic JSON decode are processed in the Worker. */\nexport async function fetchChartHistory(\n client: AggClient,\n socket: AggWebSocket | null,\n request: Parameters<AggClient[\"getChartBars\"]>[0],\n signal?: AbortSignal,\n onInitial?: (response: ChartBarsResponse) => void,\n): Promise<ChartBarsResponse> {\n const readBars = async (params: typeof request): Promise<ChartBarsResponse> => {\n const response = await client.getChartBars(params, {\n signal,\n ...(socket ? { decode: (text: string) => socket.decodeHistory(text) } : {}),\n });\n signal?.throwIfAborted();\n if (response.venueMarketOutcomeId !== request.venueMarketOutcomeId)\n throw new Error(\"Chart history identity mismatch\");\n return response;\n };\n if (!client.preferImmutableHistory) return usable(await readBars(request));\n\n let verified: { manifest: ChartHistoryManifest; history: ChartCandle[] } | undefined;\n try {\n const manifest = await client.getChartHistoryManifest(request, { signal });\n if (manifest.venueMarketOutcomeId !== request.venueMarketOutcomeId)\n throw new Error(\"Chart manifest identity mismatch\");\n if (manifest.meta.complete) {\n const history = await (socket\n ? socket.loadHistory(manifest, { signal })\n : loadImmutableHistory({ manifest, signal }));\n verified = {\n manifest,\n history: history.filter(\n (bar) => (request.from == null || bar.t >= request.from) && bar.t < request.to,\n ),\n };\n }\n } catch (error) {\n if (signal?.aborted || (isAggApiError(error) && (error.status === 429 || error.status === 503)))\n throw error;\n }\n // Only absent/unverified immutable history needs a full origin fallback.\n signal?.throwIfAborted();\n if (!verified) return usable(await readBars(request));\n\n const { manifest, history } = verified;\n const fullyCovered = manifest.finalizedThrough >= request.to;\n const initial = withActualFreshness({\n venueMarketOutcomeId: manifest.venueMarketOutcomeId,\n venue: manifest.venue,\n resolution: manifest.resolution,\n data: history,\n meta: {\n ...manifest.meta,\n state: fullyCovered ? (history.length ? \"ready\" : \"empty\") : \"warming\",\n complete: fullyCovered,\n },\n });\n if (fullyCovered) return usable(initial);\n\n // Publish verified nonempty history before requesting the forming tail. The caller's\n // original query promise remains active, preserving cancellation on range changes.\n if (history.length > 0) onInitial?.(initial);\n signal?.throwIfAborted();\n try {\n const tail = await readBars({\n ...request,\n resolution: manifest.resolution,\n from: Math.max(request.from ?? 0, manifest.finalizedThrough),\n countBack: undefined,\n });\n if (tail.venue !== manifest.venue || tail.resolution !== manifest.resolution)\n throw new Error(\"Chart tail series mismatch\");\n const data = [\n ...history,\n ...tail.data.filter((bar) => bar.t >= manifest.finalizedThrough && bar.t < request.to),\n ];\n const incomplete =\n tail.meta.complete === false ||\n [\"warming\", \"failed\", \"unsupported\"].includes(tail.meta.state ?? \"\");\n return usable(\n withActualFreshness({\n ...tail,\n resolution: manifest.resolution,\n data,\n meta: {\n ...initial.meta,\n ...tail.meta,\n complete: !incomplete,\n state: incomplete ? (tail.meta.state ?? \"warming\") : data.length ? \"ready\" : \"empty\",\n },\n }),\n );\n } catch (error) {\n if (signal?.aborted) throw error;\n // A failed mutable tail cannot discard or re-fetch a verified immutable prefix.\n return usable(\n withActualFreshness({\n ...initial,\n meta: {\n ...initial.meta,\n state: error instanceof ChartDeliveryError ? error.state : \"failed\",\n complete: false,\n ...((error instanceof ChartDeliveryError || isAggApiError(error)) &&\n error.retryAfterMs != null\n ? { retryAfterMs: error.retryAfterMs }\n : {}),\n },\n }),\n );\n }\n}\n","import { isAggApiError } from \"@agg-build/sdk\";\nimport type { MarketChartData } from \"./chart-cache\";\nimport { ChartDeliveryError } from \"./chart-history\";\n\nconst MAX_TIMER_DELAY_MS = 2_147_483_647;\n// Query ownership preserves a deadline through observers/remounts without retaining evicted queries.\nconst notBefore = new WeakMap<object, number>();\nconst validDelay = (value: unknown): value is number =>\n typeof value === \"number\" && Number.isSafeInteger(value) && value >= 0;\n\nfunction record(query: object, delay: unknown): void {\n if (validDelay(delay) && delay > 0)\n notBefore.set(query, Math.min(Number.MAX_SAFE_INTEGER, Date.now() + delay));\n else notBefore.delete(query);\n}\n\nexport function chartRetryRemaining(query: object): number {\n return Math.max(0, (notBefore.get(query) ?? 0) - Date.now());\n}\n\n/** TanStack owns this interval; long server hints must not overflow a browser timer into an early poll. */\nexport function chartRefetchInterval(query: object, interval: number | false): number | false {\n if (interval === false) return false;\n const remaining = chartRetryRemaining(query);\n return remaining > MAX_TIMER_DELAY_MS ? false : Math.max(interval, remaining);\n}\n\nasync function waitForDeadline(query: object, signal: AbortSignal): Promise<void> {\n while (chartRetryRemaining(query) > 0) {\n signal.throwIfAborted();\n await new Promise<void>((resolve, reject) => {\n const aborted = () => {\n clearTimeout(timer);\n signal.removeEventListener(\"abort\", aborted);\n reject(signal.reason);\n };\n const timer = setTimeout(\n () => {\n signal.removeEventListener(\"abort\", aborted);\n resolve();\n },\n Math.min(chartRetryRemaining(query), MAX_TIMER_DELAY_MS),\n );\n signal.addEventListener(\"abort\", aborted, { once: true });\n if (signal.aborted) aborted();\n });\n }\n signal.throwIfAborted();\n}\n\n/** Guard every query execution, including manual refetch and invalidation; never schedule background work. */\nexport async function runChartQuery<T extends MarketChartData>(\n query: object,\n signal: AbortSignal,\n load: () => Promise<T>,\n): Promise<T> {\n await waitForDeadline(query, signal);\n try {\n const data = await load();\n signal.throwIfAborted();\n const delivery = data.delivery;\n // Only a fresh source result can establish a deadline. Reading retained data/ticks cannot extend it.\n record(\n query,\n delivery && delivery.complete !== true && ![\"ready\", \"empty\"].includes(delivery.state ?? \"\")\n ? delivery.retryAfterMs\n : undefined,\n );\n return data;\n } catch (error) {\n if (!signal.aborted) {\n const delay = isAggApiError(error)\n ? error.retryAfterMs\n : error instanceof ChartDeliveryError && validDelay(error.retryAfterMs)\n ? error.retryAfterMs\n : undefined;\n record(query, delay);\n }\n throw error;\n }\n}\n","import type { Candle } from \"@agg-build/sdk\";\nimport type { LiveSnapshot } from \"./live-store\";\nimport type { MarketChartCandle, MarketChartData } from \"./chart-cache\";\n\nconst closedCaches = new WeakMap<MarketChartData, { key: string; candles: MarketChartCandle[] }>();\nconst toChart = (candle: Candle): MarketChartCandle => ({\n time: candle.openTime,\n open: candle.o,\n high: candle.h,\n low: candle.l,\n close: candle.c,\n volume: candle.v,\n source: \"ws\",\n});\n\n/** Overlay only active views. Retained TanStack histories keep their own freshness and array identity. */\nexport function overlayCandleTail(\n history: MarketChartData,\n live: LiveSnapshot | undefined,\n rolling: boolean,\n): MarketChartData {\n const tail = live?.candles?.[history.interval];\n const venue = history.venues[history.primaryVenue];\n if (!tail || !venue || (!rolling && history.endTs != null && history.endTs < Date.now()))\n return history;\n const last = venue.candles.at(-1)?.time ?? -Infinity;\n const closed = tail.closed.filter((candle) => candle.openTime > last);\n const key = closed.map((candle) => `${candle.openTime}:${candle.c}:${candle.v}`).join(\"|\");\n let cached = closedCaches.get(history);\n if (!cached || cached.key !== key) {\n cached = {\n key,\n candles: closed.length ? [...venue.candles, ...closed.map(toChart)] : venue.candles,\n };\n closedCaches.set(history, cached);\n }\n const forming = tail.forming && tail.forming.openTime >= last ? toChart(tail.forming) : null;\n const lastSourceTime = Math.max(\n live.orderbook?.timestamp ?? -Infinity,\n live.trades[0]?.timestamp ?? -Infinity,\n venue.lastUpdateTs ?? -Infinity,\n );\n const lastUpdateTs = Number.isFinite(lastSourceTime) ? lastSourceTime : null;\n return {\n ...history,\n lastUpdateTs,\n venues: {\n ...history.venues,\n [history.primaryVenue]: {\n ...venue,\n candles: cached.candles,\n liveCandle: forming,\n lineValue: forming?.close ?? venue.lineValue,\n lastTrade: live.trades[0] ?? venue.lastTrade,\n lastUpdateTs,\n },\n },\n };\n}\n","import { useEffect, useMemo } from \"react\";\nimport { useAggWebSocket } from \"../core/providers/ws-provider\";\n\nexport interface UseMarketDataSubscriptionOptions {\n marketId: string | null;\n /** Additional market IDs to subscribe alongside `marketId` (e.g. other venues in the same group). */\n additionalMarketIds?: string[];\n enabled?: boolean;\n orderbook?: boolean;\n trades?: boolean;\n}\n\nexport function useMarketDataSubscription({\n marketId,\n additionalMarketIds,\n enabled = true,\n orderbook = true,\n trades = false,\n}: UseMarketDataSubscriptionOptions): void {\n const ws = useAggWebSocket();\n\n const allIds = useMemo(() => {\n const ids = new Set<string>();\n if (marketId) ids.add(marketId);\n if (additionalMarketIds) {\n for (const id of additionalMarketIds) {\n if (id) ids.add(id);\n }\n }\n return [...ids];\n }, [marketId, additionalMarketIds]);\n\n const stableKey = allIds.join(\"|\");\n\n useEffect(() => {\n if (!ws || !allIds.length || !enabled || (!orderbook && !trades)) return;\n\n const unsubscribers: Array<() => void> = [];\n\n for (const id of allIds) {\n if (orderbook) {\n const unsub = ws.subscribe(id, \"orderbook\");\n unsubscribers.push(unsub);\n }\n if (trades) {\n const unsub = ws.subscribe(id, \"trades\");\n unsubscribers.push(unsub);\n }\n }\n\n return () => {\n for (const unsub of unsubscribers) {\n unsub();\n }\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [enabled, stableKey, orderbook, trades, ws]);\n}\n","import type { ChartBarsMeta, WsCandleInterval } from \"@agg-build/sdk\";\nimport { keepPreviousData, useQueries, useQueryClient } from \"@tanstack/react-query\";\nimport { withReadRetry } from \"./read-retry\";\nimport { useAggClient, useAggUiConfig } from \"./core/provider\";\nimport { useAggWebSocket, useAggWebSocketConnectionState } from \"./core/providers/ws-provider\";\nimport {\n createMarketChartData,\n mergeMarketChartData,\n type MarketChartData,\n} from \"./market-data/chart-cache\";\nimport { marketDataKeys } from \"./market-data/query-keys\";\nimport { runChartQuery, chartRefetchInterval } from \"./market-data/chart-retry-gate\";\nimport { ChartDeliveryError, fetchChartHistory } from \"./market-data/chart-history\";\nimport { useLiveStates } from \"./market-data/live-store\";\nimport { overlayCandleTail } from \"./market-data/chart-tail\";\nimport { useMarketDataSubscription } from \"./market-data/subscription\";\n\nexport interface UseMarketChartOptions {\n /** VenueMarketOutcome.id */\n marketId: string | null;\n /** Additional venue market outcome IDs to subscribe for WS updates. */\n venueMarketIds?: string[];\n /** Scope readiness to the visible venue while retaining other requested histories. */\n visibleVenue?: string | null;\n /** Optional live subset; settled outcomes can keep cached history without stream subscriptions. */\n liveOutcomeIds?: string[];\n interval?: WsCandleInterval;\n startTs?: number | null;\n endTs?: number | null;\n countBack?: number | null;\n enabled?: boolean;\n /** Enable live WS updates. Defaults to the global `enableLiveUpdates` config. */\n live?: boolean;\n /**\n * Auto-refetch the REST history at this cadence (ms). Pair with a rolling\n * window whose `endTs` advances at the same bucket interval — each tick\n * refetches the latest window under a stable cache key, so closed bars\n * the WebSocket missed are backfilled. `null`/omitted disables auto-refetch.\n */\n refetchIntervalMs?: number | null;\n /** Optional history freshness duration; live stream writes do not extend it. */\n staleTimeMs?: number;\n /**\n * Stable identifier for the user-selected range (e.g. `\"1H\"`, `\"6H\"`).\n * Used as the React Query cache key so the entry survives bucket rollovers\n * and tab/page revisits. The concrete `startTs`/`endTs` advance under the\n * same key and are passed to the fetch via closure.\n *\n * If omitted, includes the requested start/end timestamps so different fixed\n * historical windows never share data. Note that 6H and 1D both use a 5m\n * interval, so callers using rolling windows should pass an explicit\n * `rangeKey` to keep their cache entries separate.\n */\n rangeKey?: string;\n}\n\nexport type MarketChartAvailability = Partial<ChartBarsMeta> & {\n state: NonNullable<ChartBarsMeta[\"state\"]>;\n complete: boolean;\n};\n\nexport interface UseMarketChartResult {\n /** Per-outcome delivery state remains available when another venue can already render. */\n availability?: Record<string, MarketChartAvailability>;\n data: MarketChartData | null;\n isLoading: boolean;\n error: Error | null;\n isLive: boolean;\n refetch: () => Promise<unknown>;\n}\n\nfunction useMarketChartQueries(options: UseMarketChartOptions) {\n const client = useAggClient();\n const queryClient = useQueryClient();\n const socket = useAggWebSocket();\n const isConnected = useAggWebSocketConnectionState();\n const {\n features: { enableLiveUpdates },\n } = useAggUiConfig();\n const {\n marketId,\n venueMarketIds,\n liveOutcomeIds,\n interval = \"5m\",\n startTs = null,\n endTs = null,\n countBack = null,\n enabled = true,\n live,\n refetchIntervalMs = null,\n staleTimeMs,\n rangeKey,\n } = options;\n\n const resolvedRangeKey = rangeKey ?? `${interval}:${startTs ?? \"count\"}:${endTs ?? \"unset\"}`;\n\n const liveEnabled = live ?? enableLiveUpdates;\n\n // Stabilize outcomeIds order across renders. Callers (e.g. event-details)\n // derive `venueMarketIds` from a live-price-sorted array; every WS midpoint\n // can reorder it. If we mirrored that order into useQueries, the slot at\n // index 0 would point to a different outcome on each WS tick, churning\n // observer wiring and (in the worst case) firing extra fetches before\n // React Query's per-slot dedup catches up. Sorting lexicographically gives\n // every render the same slot assignment regardless of input order.\n //\n // `primaryOutcomeId` keeps the caller's intent: `marketId` first if\n // provided, otherwise the first non-empty entry of `venueMarketIds`.\n const outcomeIds = (() => {\n const ids = new Set<string>();\n if (marketId) ids.add(marketId);\n if (venueMarketIds) {\n for (const venueMarketId of venueMarketIds) {\n if (venueMarketId) ids.add(venueMarketId);\n }\n }\n return [...ids].sort();\n })();\n const primaryOutcomeId = marketId ?? venueMarketIds?.find(Boolean) ?? null;\n const isQueryEnabled =\n enabled && outcomeIds.length > 0 && endTs != null && (startTs != null || countBack != null);\n\n const subscribedIds = liveOutcomeIds\n ? outcomeIds.filter((id) => liveOutcomeIds.includes(id))\n : outcomeIds;\n const subscribedPrimaryId =\n primaryOutcomeId && subscribedIds.includes(primaryOutcomeId)\n ? primaryOutcomeId\n : (subscribedIds[0] ?? null);\n useMarketDataSubscription({\n marketId: subscribedPrimaryId,\n additionalMarketIds: subscribedIds.filter((id) => id !== subscribedPrimaryId),\n enabled: Boolean(isQueryEnabled && liveEnabled && subscribedIds.length > 0),\n orderbook: true,\n trades: true,\n });\n\n const queries = useQueries({\n queries: outcomeIds.map((outcomeId) => ({\n // Cache key is intentionally time-free. The rolling window's\n // startTs/endTs advance on every bucket but the user expects the same\n // chart on revisit — see comment on `marketDataKeys.chart`. queryFn\n // closes over the current window so refetches still fetch fresh data.\n queryKey: marketDataKeys.chart(outcomeId, interval, resolvedRangeKey, countBack),\n queryFn: async ({ signal }: { signal: AbortSignal }): Promise<MarketChartData> => {\n const owner = queryClient.getQueryCache().find({\n queryKey: marketDataKeys.chart(outcomeId, interval, resolvedRangeKey, countBack),\n exact: true,\n });\n if (!owner) throw new Error(\"Chart query was removed before fetching\");\n return runChartQuery(owner, signal, async () => {\n const response = await fetchChartHistory(\n client,\n socket,\n {\n venueMarketOutcomeId: outcomeId,\n resolution: interval,\n from: startTs ?? undefined,\n to: endTs!,\n countBack: countBack ?? undefined,\n },\n signal,\n (initial) => {\n if (signal.aborted) return;\n queryClient.setQueryData(\n marketDataKeys.chart(outcomeId, interval, resolvedRangeKey, countBack),\n createMarketChartData({\n marketId: outcomeId,\n interval: initial.resolution ?? interval,\n startTs,\n endTs,\n response: initial,\n }),\n );\n },\n );\n\n return createMarketChartData({\n marketId: outcomeId,\n interval: response.resolution ?? interval,\n startTs,\n endTs,\n response,\n });\n });\n },\n enabled: isQueryEnabled,\n meta: { chartWindow: rangeKey ? \"rolling\" : \"fixed\", chartEndTs: endTs },\n // Treat data as fresh for one bucket — within that window the\n // existing entry serves remounts without a refetch, and the\n // `refetchInterval` below schedules the next bucket's refresh.\n staleTime: (query: { state: { data?: MarketChartData } }) => {\n // A remount after the rolling bucket advances needs its missing history.\n if (\n rangeKey &&\n endTs != null &&\n query.state.data?.endTs != null &&\n query.state.data.endTs < endTs\n )\n return 0;\n return (\n staleTimeMs ??\n (refetchIntervalMs != null && refetchIntervalMs > 0 ? refetchIntervalMs : 30_000)\n );\n },\n // 60 min — survives typical tab/page revisits without re-fetching.\n gcTime: 60 * 60_000,\n refetchOnWindowFocus: false,\n ...withReadRetry({\n retry: (failureCount: number, error: Error) => {\n if (error instanceof ChartDeliveryError) {\n if (error.state === \"unsupported\") return false;\n if (error.state === \"warming\") return failureCount < 8;\n }\n return failureCount < 1;\n },\n retryDelay: (_attempt: number, error: Error) =>\n error instanceof ChartDeliveryError && error.retryAfterMs != null\n ? Math.min(error.state === \"warming\" ? 1000 : 5000, Math.max(0, error.retryAfterMs))\n : 1000,\n }),\n placeholderData: keepPreviousData,\n refetchInterval: (query: object) =>\n chartRefetchInterval(\n query,\n refetchIntervalMs != null && refetchIntervalMs > 0 ? refetchIntervalMs : false,\n ),\n refetchIntervalInBackground: false,\n })),\n });\n\n // Disabled chart consumers keep their REST cache but must not retain live\n // listeners. `live:false` still permits an enabled view to observe a stream\n // owned by its parent; it controls subscription ownership above.\n const liveStates = useLiveStates(isQueryEnabled ? outcomeIds : []);\n const overlaid = queries.map((query, index) => ({\n ...query,\n data:\n query.data?.marketId === outcomeIds[index]\n ? overlayCandleTail(query.data, liveStates[index]?.data, !!rangeKey)\n : undefined,\n }));\n const availability: Record<string, MarketChartAvailability> = {};\n if (isQueryEnabled)\n queries.forEach((query, index) => {\n const sameOutcome = query.data?.marketId === outcomeIds[index];\n const metadata = sameOutcome ? query.data?.delivery : undefined;\n const error = query.error;\n const pending = query.isLoading || query.isPlaceholderData || query.isFetching;\n const state: MarketChartAvailability[\"state\"] =\n error instanceof ChartDeliveryError\n ? error.state\n : error\n ? \"failed\"\n : pending || !sameOutcome\n ? \"warming\"\n : (metadata?.state ??\n (Object.values(query.data!.venues).some(\n (venue) => venue.candles.length > 0 || venue.liveCandle,\n )\n ? \"ready\"\n : \"empty\"));\n availability[outcomeIds[index]!] = {\n ...metadata,\n state,\n complete: (state === \"ready\" || state === \"empty\") && (metadata?.complete ?? true),\n ...(error instanceof ChartDeliveryError && error.retryAfterMs != null\n ? { retryAfterMs: error.retryAfterMs }\n : {}),\n };\n });\n return {\n queries: overlaid,\n availability,\n outcomeIds,\n primaryOutcomeId,\n interval,\n startTs,\n endTs,\n isQueryEnabled,\n liveEnabled: liveEnabled && subscribedIds.length > 0,\n isConnected,\n };\n}\n\n/** Independent outcome histories, including multiple markets on the same venue. */\nexport interface UseMarketChartsResult {\n availability?: Record<string, MarketChartAvailability>;\n charts: Record<string, MarketChartData>;\n errors: Record<string, Error>;\n isLoading: boolean;\n isLive: boolean;\n refetch: () => Promise<unknown>;\n}\n\nexport function useMarketCharts(options: UseMarketChartOptions): UseMarketChartsResult {\n const { queries, availability, outcomeIds, isQueryEnabled, liveEnabled, isConnected } =\n useMarketChartQueries(options);\n const charts: Record<string, MarketChartData> = {};\n const errors: Record<string, Error> = {};\n queries.forEach((query, index) => {\n const outcomeId = outcomeIds[index]!;\n // A previous query slot may belong to a different outcome after a venue switch.\n if (query.data?.marketId === outcomeId && !query.isPlaceholderData)\n charts[outcomeId] = query.data;\n if (query.error)\n errors[outcomeId] =\n query.error instanceof Error ? query.error : new Error(String(query.error));\n });\n return {\n availability,\n charts,\n errors,\n isLoading: Boolean(\n isQueryEnabled && queries.some((query) => query.isLoading || query.isPlaceholderData),\n ),\n isLive: Boolean(isQueryEnabled && liveEnabled && isConnected),\n refetch: async () => Promise.all(queries.map((query) => query.refetch())),\n };\n}\n\nexport function useMarketChart(options: UseMarketChartOptions): UseMarketChartResult {\n const {\n queries,\n availability,\n primaryOutcomeId,\n interval,\n startTs,\n endTs,\n isQueryEnabled,\n liveEnabled,\n isConnected,\n } = useMarketChartQueries(options);\n const successfulDatasets = queries.flatMap((query) => {\n return query.data ? [query.data] : [];\n });\n const data =\n primaryOutcomeId && successfulDatasets.length > 0\n ? mergeMarketChartData({\n marketId: primaryOutcomeId,\n interval: successfulDatasets[0]?.interval ?? interval,\n startTs,\n endTs,\n datasets: successfulDatasets,\n })\n : null;\n\n const hasPendingQuery = queries.some((query) => query.isLoading || query.isPlaceholderData);\n const firstError = queries.find((query) => query.error != null)?.error ?? null;\n const error =\n data == null && !hasPendingQuery\n ? firstError instanceof Error\n ? firstError\n : firstError\n ? new Error(String(firstError))\n : null\n : null;\n // Show any usable in-range history immediately, but do not let an early empty\n // or out-of-range response trigger ALL fallback while another venue is warming.\n const isInRange = (candle: { time: number }): boolean =>\n (startTs == null || candle.time >= startTs / 1000) &&\n (endTs == null || candle.time <= endTs / 1000);\n const hasVisibleHistory = queries.some(\n (query) =>\n !query.isPlaceholderData &&\n query.data &&\n Object.entries(query.data.venues).some(\n ([venueName, venue]) =>\n (!options.visibleVenue || venueName === options.visibleVenue) &&\n (venue.candles.some(isInRange) ||\n (venue.liveCandle != null && isInRange(venue.liveCandle))),\n ),\n );\n const isLoading = Boolean(isQueryEnabled && hasPendingQuery && !hasVisibleHistory);\n\n return {\n data,\n availability,\n isLoading,\n error,\n isLive: Boolean(isQueryEnabled && liveEnabled && primaryOutcomeId && isConnected),\n refetch: async () => Promise.all(queries.map((query) => query.refetch())),\n };\n}\n","import { useEffect, useMemo, useReducer, useRef } from \"react\";\nimport type { CandleBuilder } from \"@agg-build/sdk\";\nimport { useAggWebSocket } from \"./core/providers/ws-provider\";\nimport { getOrCreateBuilder } from \"./candle-store\";\n\n/**\n * Subscribe to multiple venue markets and return their CandleBuilder instances.\n * Each market gets its own WS subscription (refcounted) and CandleBuilder.\n * Re-renders when ANY builder's onChange fires (batched at ~16ms by CandleBuilder).\n */\nexport function useLiveMarketStores(venueMarketIds: string[]): CandleBuilder[] {\n const ws = useAggWebSocket();\n const [, forceRender] = useReducer((c: number) => c + 1, 0);\n const subsRef = useRef(new Map<string, { unsub: () => void; unlisten: () => void }>());\n\n const stableKey = useMemo(() => venueMarketIds.slice().sort().join(\"|\"), [venueMarketIds]);\n\n useEffect(() => {\n if (!ws || venueMarketIds.length === 0) return;\n\n const current = subsRef.current;\n const desired = new Set(venueMarketIds);\n\n // Unsubscribe removed markets\n for (const [id, sub] of current) {\n if (!desired.has(id)) {\n sub.unsub();\n sub.unlisten();\n current.delete(id);\n }\n }\n\n // Subscribe new markets\n for (const id of desired) {\n if (!current.has(id)) {\n const builder = getOrCreateBuilder(id);\n const unsub = ws.subscribe(id, \"orderbook\");\n const unlisten = builder.onChange(forceRender);\n current.set(id, { unsub, unlisten });\n }\n }\n\n return () => {\n for (const [, sub] of current) {\n sub.unsub();\n sub.unlisten();\n }\n current.clear();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [ws, stableKey]);\n\n return venueMarketIds.map((id) => getOrCreateBuilder(id));\n}\n","import { useMemo } from \"react\";\nimport {\n type Candle,\n type CandleInterval,\n mergeCandles,\n mergeClosedCandles,\n VenueMarket,\n} from \"@agg-build/sdk\";\nimport { useMarketChart } from \"./use-market-chart\";\nimport { useLiveMarketStores } from \"./use-live-market-stores\";\n\n/** Unified candle shape returned by this hook. All times in seconds. */\nexport interface LiveCandle {\n time: number;\n o: number;\n h: number;\n l: number;\n c: number;\n v: number | null;\n venue?: string;\n source: \"rest\" | \"live\";\n}\n\nexport interface UseLiveCandlesOptions {\n /** The VenueMarket to show candles for. Contains id, marketId, venue, matchedVenueMarkets. */\n market: VenueMarket | null;\n /** Candle interval. Default \"5m\". */\n interval?: CandleInterval;\n /** \"venue\" = this venue only, \"aggregate\" = merge all matched venues. */\n mode?: \"venue\" | \"aggregate\";\n /** REST bootstrap time range (ms). */\n startTs?: number;\n endTs?: number;\n}\n\nexport interface UseLiveCandlesResult {\n /** Merged candles (REST historical + live computed), sorted by time asc. */\n candles: LiveCandle[];\n /** Currently forming candle. null if no live data yet. */\n liveCandle: LiveCandle | null;\n isLoading: boolean;\n}\n\nfunction candleToLive(c: Candle, source: \"rest\" | \"live\"): LiveCandle {\n return { time: c.openTime, o: c.o, h: c.h, l: c.l, c: c.c, v: c.v, source };\n}\n\n/**\n * Combines REST bootstrap candles with live CandleBuilder-computed candles.\n *\n * - REST provides historical candles from Postgres (fetched once).\n * - CandleBuilder computes live candles from orderbook delta midpoints + trades.\n * - Dedup: when a live candle has the same openTime as a REST candle, live wins.\n * - mode \"venue\": reads from a single CandleBuilder.\n * - mode \"aggregate\": merges CandleBuilders from all matched venue markets.\n */\nexport function useLiveCandles(options: UseLiveCandlesOptions): UseLiveCandlesResult {\n const { market, interval = \"5m\", mode = \"venue\", startTs, endTs } = options;\n\n // Resolve venue_market_ids to subscribe to\n const venueMarketIds = useMemo(() => {\n if (!market) return [];\n if (mode === \"venue\") return [market.id];\n // Aggregate: this market + all matched siblings\n const ids = [market.id];\n if (market.matchedVenueMarkets) {\n for (const m of market.matchedVenueMarkets) {\n ids.push(m.id);\n }\n }\n return ids;\n }, [market, mode]);\n\n // Each venue_market_id gets its own CandleBuilder, all accumulating in parallel\n const builders = useLiveMarketStores(venueMarketIds);\n\n // REST bootstrap — use canonical marketId for chart endpoint\n const restMarketId = market?.marketId ?? null;\n const { data: chartData, isLoading } = useMarketChart({\n marketId: restMarketId,\n interval,\n startTs: startTs ?? null,\n endTs: endTs ?? null,\n enabled: !!restMarketId && startTs != null && endTs != null,\n });\n\n // Live candles from CandleBuilder(s)\n const liveData = useMemo(() => {\n if (builders.length === 0) return { closed: [] as Candle[], forming: null as Candle | null };\n\n if (mode === \"venue\" || builders.length === 1) {\n return {\n closed: builders[0].getClosed(interval),\n forming: builders[0].getForming(interval),\n };\n }\n\n // Aggregate: merge across matched venue builders\n return {\n closed: mergeClosedCandles(builders.map((b) => b.getClosed(interval))),\n forming: mergeCandles(builders.map((b) => b.getForming(interval))),\n };\n // builders array identity changes on every render from useLiveMarketStores (forceRender),\n // which is the re-render trigger we need\n }, [builders, interval, mode]);\n\n // Merge REST + live by openTime (live wins on collision)\n const candles = useMemo(() => {\n const byTime = new Map<number, LiveCandle>();\n\n // REST candles from chart cache (times already in seconds)\n if (chartData) {\n const venueEntries = Object.values(chartData.venues);\n for (const venueData of venueEntries) {\n for (const c of venueData.candles) {\n byTime.set(c.time, {\n time: c.time,\n o: c.open,\n h: c.high,\n l: c.low,\n c: c.close,\n v: c.volume,\n source: \"rest\",\n });\n }\n }\n }\n\n // Live closed candles overwrite REST on collision\n for (const c of liveData.closed) {\n byTime.set(c.openTime, candleToLive(c, \"live\"));\n }\n\n const merged = Array.from(byTime.values());\n merged.sort((a, b) => a.time - b.time);\n return merged;\n }, [chartData, liveData.closed]);\n\n // Forming candle\n const liveCandle = useMemo((): LiveCandle | null => {\n if (!liveData.forming) return null;\n return candleToLive(liveData.forming, \"live\");\n }, [liveData.forming]);\n\n return { candles, liveCandle, isLoading };\n}\n","import { useCallback, useMemo } from \"react\";\nimport type { CandleInterval, VenueMarket } from \"@agg-build/sdk\";\nimport { useLiveCandles, type LiveCandle } from \"./use-live-candles\";\n\nexport interface ScaledCandlePoint {\n time: number;\n open: number;\n high: number;\n low: number;\n close: number;\n v: number | null;\n}\n\nexport interface UseLiveCandleOverlayOptions {\n market: VenueMarket | null;\n interval?: CandleInterval;\n mode?: \"venue\" | \"aggregate\";\n startTs?: number;\n endTs?: number;\n enabled?: boolean;\n scale?: number;\n}\n\nexport interface UseLiveCandleOverlayResult {\n liveCandle: ScaledCandlePoint | null;\n scaledCandles: ScaledCandlePoint[];\n lineValue: number | undefined;\n live: boolean;\n isLoading: boolean;\n}\n\nexport function timeRangeToInterval(range: string): CandleInterval {\n switch (range) {\n case \"1H\":\n return \"1m\";\n case \"6H\":\n return \"5m\";\n case \"1D\":\n return \"5m\";\n case \"1W\":\n return \"1h\";\n case \"1M\":\n return \"1h\";\n case \"ALL\":\n return \"1h\";\n default:\n return \"5m\";\n }\n}\n\nexport function useLiveCandleOverlay(\n options: UseLiveCandleOverlayOptions,\n): UseLiveCandleOverlayResult {\n const {\n market,\n interval = \"5m\",\n mode = \"venue\",\n startTs,\n endTs,\n enabled = true,\n scale = 100,\n } = options;\n\n const {\n candles: rawCandles,\n liveCandle: rawLive,\n isLoading,\n } = useLiveCandles({\n market: enabled ? market : null,\n interval,\n mode,\n startTs,\n endTs,\n });\n\n const scaleCandle = useCallback(\n (candle: LiveCandle): ScaledCandlePoint => ({\n time: candle.time,\n open: candle.o * scale,\n high: candle.h * scale,\n low: candle.l * scale,\n close: candle.c * scale,\n v: candle.v,\n }),\n [scale],\n );\n\n const scaledCandles = useMemo(() => rawCandles.map(scaleCandle), [rawCandles, scaleCandle]);\n const liveCandle = useMemo(() => (rawLive ? scaleCandle(rawLive) : null), [rawLive, scaleCandle]);\n\n return {\n liveCandle,\n scaledCandles,\n lineValue: liveCandle?.close ?? scaledCandles[scaledCandles.length - 1]?.close,\n live: liveCandle != null,\n isLoading,\n };\n}\n","import { useEffect, useMemo } from \"react\";\nimport type { VenueMarket } from \"@agg-build/sdk\";\nimport { useAggUiConfig } from \"./core/provider\";\nimport { useAggWebSocket } from \"./core/providers/ws-provider\";\n\n// ── Pure helpers (exported for unit tests) ─────────────────────────────────\n\nexport function extractSelectedOutcomeIds(selectedMarket: VenueMarket | null): string[] {\n if (!selectedMarket) return [];\n const ids = new Set<string>();\n for (const outcome of selectedMarket.venueMarketOutcomes ?? []) {\n if (outcome.id) ids.add(outcome.id);\n }\n // Include cross-venue matched markets so a 2-venue market subscribes to all\n // 4 outcome ids (2 per venue). The engine emits per-outcome deltas, so\n // missing any one venue's ids leaves `useLiveOutcomePrices` blind to that\n // venue's live book.\n for (const matched of selectedMarket.matchedVenueMarkets ?? []) {\n for (const outcome of matched.venueMarketOutcomes ?? []) {\n if (outcome.id) ids.add(outcome.id);\n }\n }\n return [...ids].sort();\n}\n\n// ── Hook ───────────────────────────────────────────────────────────────────\n\n/**\n * Subscribes to live orderbook updates for the selected market's outcomes —\n * including the outcomes of any cross-venue matched twins — so the live cache\n * fills for every venue the user is actively looking at.\n *\n * Each caller owns only this selected group. The event hero owns its selection;\n * the market list enables separate callers for its bounded visible cards and\n * retained selection. Other groups use the surrounding components' REST\n * midpoint fallback until a view owns their live stream.\n *\n * Honors the `enableLiveUpdates` feature flag.\n */\nexport function useEventOrderbookData(\n venueMarkets: VenueMarket[] | null | undefined,\n selectedMarketId: string | null,\n): void {\n const ws = useAggWebSocket();\n const {\n features: { enableLiveUpdates },\n } = useAggUiConfig();\n\n const selectedMarket = useMemo(() => {\n if (!selectedMarketId || !venueMarkets?.length) return null;\n return venueMarkets.find((m) => m.id === selectedMarketId) ?? null;\n }, [venueMarkets, selectedMarketId]);\n\n const selectedOutcomeIds = useMemo(\n () => extractSelectedOutcomeIds(selectedMarket),\n [selectedMarket],\n );\n const selectedKey = selectedOutcomeIds.join(\"|\");\n\n useEffect(() => {\n if (!ws || !enableLiveUpdates || !selectedOutcomeIds.length) return;\n const unsubscribers = selectedOutcomeIds.map((id) => ws.subscribe(id, \"orderbook\"));\n return () => {\n for (const unsub of unsubscribers) unsub();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [ws, selectedKey, enableLiveUpdates]);\n}\n","import type {\n OrderbookLevel,\n OrderbookState,\n OutcomeOrderbookResponse,\n VenueOrderbookLevel,\n} from \"@agg-build/sdk\";\n/**\n * Convert a single-outcome REST snapshot into the WS-style `OrderbookState`\n * shape used by chart / depth UIs. The REST endpoint returns a per-venue\n * book (single venue) — we attribute every level to that one venue so the\n * resulting state is a valid (if narrower) `OrderbookState` consumers can\n * render. WS deltas overwrite this state on first frame.\n */\n/** Current REST wire timestamps are ms; tolerate older partner fixtures in seconds. */\nexport const orderbookTimestampSeconds = (timestamp: number): number =>\n timestamp >= 1_000_000_000_000 ? timestamp / 1000 : timestamp;\n\nexport function outcomeOrderbookToState(\n response: OutcomeOrderbookResponse,\n marketId: string,\n): OrderbookState {\n const { venue, orderbook, midpoint, spread, seq, checksum, timestamp, venueMarketOutcomeId } =\n response;\n const attribute = (l: { price: number; size: number }): OrderbookLevel => ({\n price: l.price,\n size: l.size,\n venues: { [venue]: l.size },\n });\n const venueLevels = (l: { price: number; size: number }): VenueOrderbookLevel => ({\n price: l.price,\n size: l.size,\n });\n return {\n marketId,\n outcomeId: venueMarketOutcomeId,\n bids: orderbook.bids.map(attribute),\n asks: orderbook.asks.map(attribute),\n venueOrderbooks: {\n [venue]: {\n bids: orderbook.bids.map(venueLevels),\n asks: orderbook.asks.map(venueLevels),\n },\n },\n venues: {\n [venue]: {\n bestBid: orderbook.bids[0]?.price ?? null,\n bestAsk: orderbook.asks[0]?.price ?? null,\n },\n },\n midpoint,\n spread,\n seq,\n checksum,\n timestamp: orderbookTimestampSeconds(timestamp),\n };\n}\n","import type { Orderbook, AggregatedOrderbookResponse, OrderbookState } from \"@agg-build/sdk\";\n\nexport type MarketOrderbookIntegrity = \"ok\" | \"resyncing\";\n\nexport interface MarketOrderbookData {\n marketId: string;\n orderbook: AggregatedOrderbookResponse[\"orderbook\"];\n venueOrderbooks: AggregatedOrderbookResponse[\"venueOrderbooks\"];\n venues: AggregatedOrderbookResponse[\"venues\"];\n midpoint: number | null;\n spread: number | null;\n timestamp: number;\n snapshotVersion?: number;\n seq?: number;\n checksum?: number | null;\n matchedMarkets?: AggregatedOrderbookResponse[\"matchedMarkets\"];\n integrity: MarketOrderbookIntegrity;\n}\n\nconst truncateLevels = <T extends { price: number; size: number }>(\n levels: T[],\n depth?: number | null,\n): T[] => {\n if (depth == null) return levels;\n return levels.slice(0, Math.max(0, depth));\n};\n\nconst truncateVenueOrderbooks = (\n venueOrderbooks: MarketOrderbookData[\"venueOrderbooks\"],\n depth?: number | null,\n): MarketOrderbookData[\"venueOrderbooks\"] => {\n if (depth == null) return venueOrderbooks;\n\n return Object.fromEntries(\n Object.entries(venueOrderbooks).map(([venue, book]) => [\n venue,\n {\n bids: truncateLevels(book.bids, depth),\n asks: truncateLevels(book.asks, depth),\n },\n ]),\n );\n};\n\nexport const createMarketOrderbookDataFromResponse = (\n response: AggregatedOrderbookResponse,\n): MarketOrderbookData => {\n return {\n marketId: response.venueMarketId,\n orderbook: response.orderbook,\n venueOrderbooks: response.venueOrderbooks,\n venues: response.venues,\n midpoint: response.midpoint,\n spread: response.spread,\n timestamp: response.timestamp,\n snapshotVersion: 0,\n seq: response.seq,\n checksum: response.checksum,\n matchedMarkets: \"matchedMarkets\" in response ? response.matchedMarkets : undefined,\n integrity: \"ok\",\n };\n};\n\nconst aggregateVenueLevels = (\n venueOrderbooks: MarketOrderbookData[\"venueOrderbooks\"],\n side: \"bids\" | \"asks\",\n): MarketOrderbookData[\"orderbook\"][\"bids\"] => {\n const levelsByPrice = new Map<\n number,\n {\n price: number;\n size: number;\n venues: Record<string, number>;\n }\n >();\n\n for (const [venue, orderbook] of Object.entries(venueOrderbooks)) {\n for (const level of orderbook[side]) {\n const currentLevel = levelsByPrice.get(level.price);\n\n if (currentLevel) {\n currentLevel.size += level.size;\n currentLevel.venues[venue] = (currentLevel.venues[venue] ?? 0) + level.size;\n continue;\n }\n\n levelsByPrice.set(level.price, {\n price: level.price,\n size: level.size,\n venues: {\n [venue]: level.size,\n },\n });\n }\n }\n\n return [...levelsByPrice.values()].sort((left, right) =>\n side === \"bids\" ? right.price - left.price : left.price - right.price,\n );\n};\n\nexport const createMarketOrderbookDataFromVenueOrderbooks = ({\n marketId,\n venueOrderbooks,\n timestamp = Math.floor(Date.now() / 1000),\n}: {\n marketId: string;\n venueOrderbooks: Record<string, Orderbook>;\n timestamp?: number;\n}): MarketOrderbookData => {\n const bids = aggregateVenueLevels(venueOrderbooks, \"bids\");\n const asks = aggregateVenueLevels(venueOrderbooks, \"asks\");\n const bestBid = bids[0]?.price ?? null;\n const bestAsk = asks[0]?.price ?? null;\n\n return {\n marketId,\n orderbook: {\n bids,\n asks,\n },\n venueOrderbooks,\n venues: Object.fromEntries(\n Object.entries(venueOrderbooks).map(([venue, orderbook]) => [\n venue,\n {\n bestBid: orderbook.bids[0]?.price ?? null,\n bestAsk: orderbook.asks[0]?.price ?? null,\n },\n ]),\n ),\n midpoint: bestBid != null && bestAsk != null ? (bestBid + bestAsk) / 2 : null,\n spread: bestBid != null && bestAsk != null ? bestAsk - bestBid : null,\n timestamp,\n snapshotVersion: 0,\n integrity: \"ok\",\n };\n};\n\nexport const createMarketOrderbookDataFromState = (\n state: OrderbookState,\n options?: { snapshotVersion?: number },\n): MarketOrderbookData => {\n return {\n marketId: state.marketId,\n orderbook: {\n bids: state.bids,\n asks: state.asks,\n },\n venueOrderbooks: state.venueOrderbooks,\n venues: state.venues,\n midpoint: state.midpoint,\n spread: state.spread,\n timestamp: state.timestamp,\n snapshotVersion: options?.snapshotVersion ?? 0,\n seq: state.seq,\n checksum: state.checksum,\n integrity: \"ok\",\n };\n};\n\nexport const marketOrderbookDataToResponse = (\n data: MarketOrderbookData,\n): AggregatedOrderbookResponse => {\n return {\n venueMarketId: data.marketId,\n orderbook: data.orderbook,\n venueOrderbooks: data.venueOrderbooks,\n venues: data.venues,\n midpoint: data.midpoint,\n spread: data.spread,\n timestamp: data.timestamp,\n seq: data.seq,\n checksum: data.checksum,\n matchedMarkets: data.matchedMarkets,\n };\n};\n\nexport const marketOrderbookDataToState = (data: MarketOrderbookData): OrderbookState => {\n return {\n marketId: data.marketId,\n bids: data.orderbook.bids,\n asks: data.orderbook.asks,\n venueOrderbooks: data.venueOrderbooks,\n venues: data.venues,\n midpoint: data.midpoint,\n spread: data.spread,\n timestamp: data.timestamp,\n seq: data.seq ?? 0,\n checksum: data.checksum ?? 0,\n };\n};\n\nexport const withOrderbookIntegrity = (\n data: MarketOrderbookData | null | undefined,\n integrity: MarketOrderbookIntegrity,\n): MarketOrderbookData | null | undefined => {\n if (!data) return data;\n if (data.integrity === integrity) return data;\n return {\n ...data,\n integrity,\n };\n};\n\nexport const applyOrderbookDepth = (\n data: MarketOrderbookData,\n depth?: number | null,\n): MarketOrderbookData => {\n if (depth == null) return data;\n\n return {\n ...data,\n orderbook: {\n bids: truncateLevels(data.orderbook.bids, depth),\n asks: truncateLevels(data.orderbook.asks, depth),\n },\n venueOrderbooks: truncateVenueOrderbooks(data.venueOrderbooks, depth),\n };\n};\n","import { computeChecksum, type AggClient, type OutcomeOrderbookResponse } from \"@agg-build/sdk\";\nimport { type MarketLiveStore } from \"./live-store\";\n\nimport { outcomeOrderbookToState } from \"./orderbook-snapshot\";\n\nconst SOCKET_GRACE_MS = 200;\nconst REST_BUDGET_MS = 1500;\nconst MAX_SEED_AGE_MS = 5000;\nexport function hasFreshSnapshot(store: MarketLiveStore, id: string, now = Date.now()): boolean {\n const state = store.get(id);\n return (\n !!state.orderbook &&\n state.integrity === \"ok\" &&\n now - state.orderbook.timestamp * 1000 <= MAX_SEED_AGE_MS &&\n state.orderbook.timestamp * 1000 <= now + 1000\n );\n}\n\n/** Keep cached query closures separate from the hook render's deep live books and React results. */\nexport function createOrderbookSnapshotQuery(\n client: Pick<AggClient, \"getOutcomeOrderbooks\">,\n store: MarketLiveStore,\n ids: string[],\n socketHealthy: boolean,\n): (context: { signal: AbortSignal }) => Promise<Record<string, OutcomeOrderbookResponse>> {\n // Native binding survives production minifier inlining; an arrow factory can be folded back\n // into the hook and share its render context (including retired deep books).\n return fetchSnapshotQuery.bind(null, client, store, ids, socketHealthy);\n}\n\nfunction fetchSnapshotQuery(\n client: Pick<AggClient, \"getOutcomeOrderbooks\">,\n store: MarketLiveStore,\n ids: string[],\n socketHealthy: boolean,\n { signal }: { signal: AbortSignal },\n): Promise<Record<string, OutcomeOrderbookResponse>> {\n return selectOrderbookSnapshots(client, store, ids, socketHealthy, signal);\n}\n\n/** One selection per sorted query key; TanStack deduplicates concurrent consumers. */\nexport async function selectOrderbookSnapshots(\n client: Pick<AggClient, \"getOutcomeOrderbooks\">,\n store: MarketLiveStore,\n ids: string[],\n socketHealthy: boolean,\n signal: AbortSignal,\n): Promise<Record<string, OutcomeOrderbookResponse>> {\n if (ids.length > 100) throw new Error(\"Orderbook snapshot batch exceeds 100 outcomes\");\n const missing = () => ids.filter((id) => !hasFreshSnapshot(store, id));\n if (!missing().length || signal.aborted) return {};\n if (socketHealthy) {\n await new Promise<void>((resolve) => {\n let unsubscribe = () => {};\n const finish = () => {\n clearTimeout(timer);\n unsubscribe();\n signal.removeEventListener(\"abort\", finish);\n resolve();\n };\n const timer = setTimeout(finish, SOCKET_GRACE_MS);\n unsubscribe = store.subscribe(ids, () => {\n if (!missing().length) finish();\n });\n signal.addEventListener(\"abort\", finish, { once: true });\n });\n }\n const requested = missing();\n if (!requested.length || signal.aborted) return {};\n const initialStates = new Map(requested.map((id) => [id, store.get(id)]));\n const controller = new AbortController();\n const abort = () => controller.abort();\n signal.addEventListener(\"abort\", abort, { once: true });\n const timer = setTimeout(abort, REST_BUDGET_MS);\n const unsubscribe = store.subscribe(requested, () => {\n if (!missing().length) controller.abort();\n });\n try {\n const response = await client.getOutcomeOrderbooks(\n { venueMarketOutcomeIds: requested },\n { signal: controller.signal },\n );\n if (signal.aborted) return {};\n return Object.fromEntries(\n response.data.flatMap((book, index) => {\n const id = requested[index];\n if (!book || !id || hasFreshSnapshot(store, id)) return [];\n if (book.venueMarketOutcomeId !== id)\n throw new Error(\"Orderbook snapshot identity mismatch\");\n if (\n !Number.isFinite(book.timestamp) ||\n !Number.isSafeInteger(book.seq) ||\n book.seq < 0 ||\n !Number.isInteger(book.checksum)\n )\n throw new Error(\"Invalid orderbook snapshot metadata\");\n const snapshot = outcomeOrderbookToState(book, id);\n if (\n ![...snapshot.bids, ...snapshot.asks].every(\n (level) =>\n Number.isFinite(level.price) && Number.isFinite(level.size) && level.size >= 0,\n )\n )\n throw new Error(\"Invalid orderbook snapshot levels\");\n const projectedChecksum = (book as OutcomeOrderbookResponse & { snapshotChecksum?: number })\n .snapshotChecksum;\n if (projectedChecksum != null && computeChecksum(snapshot) !== projectedChecksum)\n throw new Error(\"Orderbook snapshot checksum mismatch\");\n const current = store.get(id);\n const live = current.orderbook;\n // Any socket/seed update received after this request started takes precedence,\n // including fresh snapshots whose source timestamp is unchanged on a quiet market.\n const initial = initialStates.get(id)!;\n const initialBook = initial.orderbook;\n if (\n current.orderbookSnapshotVersion !== initial.orderbookSnapshotVersion ||\n !!live !== !!initialBook ||\n (live &&\n initialBook &&\n (live.seq !== initialBook.seq ||\n live.checksum !== initialBook.checksum ||\n live.timestamp !== initialBook.timestamp))\n )\n return [];\n if (live) {\n const sameGeneration =\n current.isConnected &&\n current.integrity === \"ok\" &&\n current.orderbookGeneration === current.connectionGeneration;\n if (snapshot.timestamp < live.timestamp || (sameGeneration && snapshot.seq <= live.seq))\n return [];\n // Restart/disconnect recovery may reset the engine sequence; require a newer\n // source timestamp before replacing an existing book from that older generation.\n if (!sameGeneration && snapshot.timestamp <= live.timestamp) return [];\n }\n store.update(id, (previous) => ({\n ...previous,\n orderbook: snapshot,\n integrity: \"ok\",\n orderbookError: null,\n }));\n return [[id, book]];\n }),\n );\n } catch (error) {\n if (signal.aborted || !missing().length) return {};\n throw error;\n } finally {\n clearTimeout(timer);\n unsubscribe();\n signal.removeEventListener(\"abort\", abort);\n }\n}\n","import { useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport type { VenueMarket } from \"@agg-build/sdk\";\nimport { useAggWebSocket, useAggWebSocketConnectionState } from \"./core/providers/ws-provider\";\nimport { useAggClient, useAggUiConfig } from \"./core/provider\";\nimport { outcomeOrderbookToState } from \"./market-data/orderbook-snapshot\";\nimport {\n applyOrderbookDepth,\n createMarketOrderbookDataFromState,\n type MarketOrderbookData,\n} from \"./market-data/orderbook-cache\";\nimport { getMarketLiveStore, useLiveStates } from \"./market-data/live-store\";\nimport { createOrderbookSnapshotQuery } from \"./market-data/snapshot-selection\";\nimport { useMarketDataSubscription } from \"./market-data/subscription\";\nimport { createMarketLiveState } from \"./market-data/live-cache\";\n\nexport interface UseMarketOrderbookVenueOutcome {\n venue: VenueMarket[\"venue\"];\n venueMarketOutcomeId: string;\n}\n\nexport interface UseMarketOrderbookOptions {\n /**\n * The venueMarketOutcomeId to subscribe to (the `outcomes[].id` on REST\n * market responses). Orderbooks are keyed per-outcome on the WS gateway —\n * a venueMarketId here will never resolve to a book.\n */\n venueMarketOutcomeId?: string | null;\n /** @deprecated Misleading name — this has always been a venueMarketOutcomeId.\n * Use `venueMarketOutcomeId` instead. */\n marketId?: string | null;\n depth?: number;\n enabled?: boolean;\n venueOutcomes?: UseMarketOrderbookVenueOutcome[];\n /** Override live subscription. When false, skips the internal WS subscription\n * (useful when a parent already manages subscriptions for this market). */\n live?: boolean;\n}\n\nexport interface UseMarketOrderbookResult {\n data: MarketOrderbookData | null;\n dataById: Record<string, MarketOrderbookData>;\n isLoading: boolean;\n error: Error | null;\n isLive: boolean;\n refetch: () => Promise<unknown>;\n}\n\n/**\n * Subscribe to a live orderbook for the selected outcome(s).\n *\n * WS-driven in steady state: subscribes to outcome IDs, receives snapshots\n * + deltas via the gateway, reads from the React Query live cache.\n *\n * REST-seeds `GET /orderbook/outcome/:id` so the book still renders when the\n * websocket is down or the snapshot never arrives. WS overwrites the seed.\n */\nexport function useMarketOrderbook(options: UseMarketOrderbookOptions): UseMarketOrderbookResult {\n const queryClient = useQueryClient();\n const client = useAggClient();\n const ws = useAggWebSocket();\n const isConnected = useAggWebSocketConnectionState();\n const {\n features: { enableLiveUpdates },\n } = useAggUiConfig();\n const { venueMarketOutcomeId, marketId, depth, enabled = true, venueOutcomes, live } = options;\n // `marketId` is the deprecated alias — it always carried an outcome id.\n const selectedId = venueMarketOutcomeId ?? marketId ?? null;\n const liveEnabled = live ?? enableLiveUpdates;\n\n // Subscribe to outcome IDs for live WS updates.\n // Always subscribe when enabled — this hook is WS-only so the subscription\n // is the sole data source regardless of the `live` flag.\n const outcomeIds = venueOutcomes?.map((v) => v.venueMarketOutcomeId).filter(Boolean);\n const subscriptionIds = outcomeIds?.length\n ? [...new Set(outcomeIds)]\n : selectedId\n ? [selectedId]\n : [];\n const selectedOutcomeId = subscriptionIds[0] ?? null;\n\n useMarketDataSubscription({\n marketId: selectedOutcomeId,\n additionalMarketIds: subscriptionIds.slice(1),\n enabled: enabled && !!selectedOutcomeId,\n orderbook: true,\n });\n\n const store = getMarketLiveStore(queryClient);\n const liveQueries = useLiveStates(enabled ? subscriptionIds : []);\n const sortedIds = [...subscriptionIds].sort();\n // Allow bounded first-connect startup; a previously connected transport now offline skips grace.\n const preferSocket =\n enabled &&\n Boolean(ws) &&\n (isConnected || subscriptionIds.every((id) => (store.get(id).connectionGeneration ?? 0) === 0));\n const seedQuery = useQuery({\n queryKey: [\"market-orderbook-seed\", sortedIds],\n queryFn: createOrderbookSnapshotQuery(client, store, sortedIds, preferSocket),\n enabled: enabled && subscriptionIds.length > 0,\n staleTime: 5000,\n gcTime: 60_000,\n refetchOnWindowFocus: false,\n retry: false,\n });\n\n const liveStates = subscriptionIds.map((subscriptionId, index) => {\n return (\n liveQueries[index]?.data ??\n store.peek(subscriptionId) ??\n createMarketLiveState(subscriptionId)\n );\n });\n const seededOrderbooks = subscriptionIds.map((subscriptionId, index) => {\n const liveBook = liveStates[index]?.orderbook ?? null;\n if (liveBook) return liveBook;\n const seed = seedQuery.data?.[subscriptionId];\n return seed?.orderbook?.bids && seed.orderbook.asks\n ? outcomeOrderbookToState(seed, subscriptionId)\n : null;\n });\n const primaryOrderbook = seededOrderbooks[0] ?? null;\n const primarySnapshotVersion = liveStates[0]?.orderbookSnapshotVersion ?? 0;\n\n // Transform OrderbookState → MarketOrderbookData (what the UI component expects)\n const data: MarketOrderbookData | null = primaryOrderbook\n ? applyOrderbookDepth(\n createMarketOrderbookDataFromState(primaryOrderbook, {\n snapshotVersion: primarySnapshotVersion,\n }),\n depth,\n )\n : null;\n const dataById = Object.fromEntries(\n seededOrderbooks.flatMap((orderbook, index) => {\n if (!orderbook) return [];\n\n return [\n [\n subscriptionIds[index],\n applyOrderbookDepth(\n createMarketOrderbookDataFromState(orderbook, {\n snapshotVersion: liveStates[index]?.orderbookSnapshotVersion,\n }),\n depth,\n ),\n ],\n ];\n }),\n ) as Record<string, MarketOrderbookData>;\n const hasAnyOrderbook = seededOrderbooks.some((orderbook) => orderbook != null);\n const seedLoading = seedQuery.isLoading;\n const liveOrderbookErrorMessage =\n enabled && liveEnabled && !hasAnyOrderbook\n ? (liveStates.find(\n (liveState) =>\n typeof liveState.orderbookError === \"string\" && liveState.orderbookError.length > 0,\n )?.orderbookError ?? null)\n : null;\n\n return {\n data,\n dataById,\n isLoading: enabled && !hasAnyOrderbook && liveOrderbookErrorMessage == null && seedLoading,\n error: liveOrderbookErrorMessage\n ? new Error(liveOrderbookErrorMessage)\n : !hasAnyOrderbook && seedQuery.error instanceof Error\n ? seedQuery.error\n : null,\n isLive: Boolean(enabled && liveEnabled && selectedOutcomeId && isConnected),\n refetch: async () => {\n if (!enabled) return;\n if (subscriptionIds.length === 0) return;\n\n // Reset live error so UI can leave error state while we request a fresh snapshot.\n subscriptionIds.forEach((subscriptionId) =>\n store.update(subscriptionId, (previous) => ({ ...previous, orderbookError: null })),\n );\n\n ws?.resnapshot(subscriptionIds);\n return seedQuery.refetch();\n },\n };\n}\n","import type { OrderbookState, WsTrade } from \"@agg-build/sdk\";\nimport { useAggUiConfig } from \"./core/provider\";\nimport { useAggWebSocketConnectionState } from \"./core/providers/ws-provider\";\nimport { useLiveStates } from \"./market-data/live-store\";\nimport { useMarketOrderbook } from \"./use-market-orderbook\";\n\nexport interface UseLiveMarketResult {\n orderbook: OrderbookState | null;\n trades: WsTrade[];\n isConnected: boolean;\n integrity: \"ok\" | \"resyncing\";\n}\n\nexport { outcomeOrderbookToState } from \"./market-data/orderbook-snapshot\";\n\nexport function useLiveMarket(canonicalMarketId: string | null): UseLiveMarketResult {\n const {\n features: { enableLiveUpdates },\n } = useAggUiConfig();\n const connected = useAggWebSocketConnectionState();\n const [snapshot] = useLiveStates([canonicalMarketId ?? \"__disabled__\"]);\n useMarketOrderbook({\n venueMarketOutcomeId: canonicalMarketId,\n enabled: !!canonicalMarketId,\n live: enableLiveUpdates,\n });\n const data = snapshot!.data;\n return {\n orderbook: data.orderbook,\n trades: data.trades,\n isConnected: !!canonicalMarketId && enableLiveUpdates && connected,\n integrity: data.integrity,\n };\n}\n","import { useMemo, useRef } from \"react\";\nimport type { VenueMarket } from \"@agg-build/sdk\";\nimport { useLiveStates } from \"./market-data/live-store\";\nimport { useAggUiConfig } from \"./core/provider\";\nimport { type MarketLiveState } from \"./market-data/live-cache\";\n\nconst EMPTY_PRICES = new Map<string, number>();\n\n/**\n * Build a stable fingerprint from query results so useMemo only recomputes\n * when actual midpoint values change.\n */\nconst buildMidpointFingerprint = (\n outcomeIds: string[],\n queries: Array<{ data?: MarketLiveState }>,\n): string => {\n const parts: string[] = [];\n for (let i = 0; i < outcomeIds.length; i++) {\n const midpoint = queries[i]?.data?.orderbook?.midpoint;\n parts.push(`${outcomeIds[i]}:${midpoint ?? \"_\"}`);\n }\n return parts.join(\"|\");\n};\n\n/**\n * Derive live display prices for every outcome across the given venue markets.\n *\n * Each outcome has its own live orderbook (the engine emits per-outcome deltas\n * on `agg.orderbook.outcome`). The midpoint from each outcome's book is its\n * price — no complement derivation needed.\n *\n * Returns a stable Map<outcomeId, price> that updates only when cache entries\n * change.\n */\nexport function useLiveOutcomePrices(\n venueMarkets: VenueMarket[] | null | undefined,\n): Map<string, number> {\n const {\n features: { enableLiveUpdates },\n } = useAggUiConfig();\n\n // Collect all outcome IDs across venue markets\n const outcomeIds = useMemo(() => {\n if (!venueMarkets?.length) return [];\n const ids = new Set<string>();\n for (const vm of venueMarkets) {\n for (const outcome of vm.venueMarketOutcomes ?? []) {\n if (outcome.id) ids.add(outcome.id);\n for (const ref of outcome.matchedVenueMarketOutcomes ?? []) {\n if (ref.venueMarketOutcomeId) ids.add(ref.venueMarketOutcomeId);\n }\n }\n }\n return [...ids].sort();\n }, [venueMarkets]);\n\n // Query the live cache for each outcome's orderbook\n const queries = useLiveStates(outcomeIds);\n\n const fingerprint = buildMidpointFingerprint(outcomeIds, queries);\n const prevRef = useRef<{ fingerprint: string; prices: Map<string, number> }>({\n fingerprint: \"\",\n prices: EMPTY_PRICES,\n });\n\n const data = useMemo(() => {\n if (!venueMarkets?.length) return EMPTY_PRICES;\n\n if (fingerprint === prevRef.current.fingerprint) {\n return prevRef.current.prices;\n }\n\n const prices = new Map<string, number>();\n\n // Build outcome ID → live midpoint map\n const liveByOutcomeId = new Map<string, number | null>();\n for (let i = 0; i < outcomeIds.length; i++) {\n const state = queries[i]?.data as MarketLiveState | undefined;\n liveByOutcomeId.set(outcomeIds[i], state?.orderbook?.midpoint ?? null);\n }\n\n if (!enableLiveUpdates) return prices;\n\n for (const outcomeId of outcomeIds) {\n // Only set when there is an actual live WS midpoint — skip discovery-price\n // fallbacks so REST midpoints can surface through consuming components.\n const liveMidpoint = liveByOutcomeId.get(outcomeId);\n if (liveMidpoint != null) prices.set(outcomeId, liveMidpoint);\n }\n\n prevRef.current = { fingerprint, prices };\n return prices;\n }, [venueMarkets, enableLiveUpdates, fingerprint, outcomeIds, queries]);\n\n return data;\n}\n\n/**\n * Look up the live price for a given outcome ID.\n * Returns undefined when the ID is not found in the map.\n */\nexport function findLivePriceById(livePrices: Map<string, number>, id: string): number | undefined {\n return livePrices.get(id);\n}\n\n/**\n * Look up the average live price across venues for a given outcome label.\n * Returns undefined when no matching outcomes are found in the map.\n */\nexport function findLivePriceForLabel(\n livePrices: Map<string, number>,\n venueMarkets: VenueMarket[],\n label: string,\n): number | undefined {\n const normalizedLabel = label.trim().toLowerCase();\n let sum = 0;\n let count = 0;\n\n for (const vm of venueMarkets) {\n for (const outcome of vm.venueMarketOutcomes) {\n if (outcome.label.trim().toLowerCase() !== normalizedLabel) continue;\n const price = livePrices.get(outcome.id);\n if (price == null) continue;\n sum += price;\n count += 1;\n }\n }\n\n return count > 0 ? sum / count : undefined;\n}\n","import { useMemo, useRef } from \"react\";\nimport type { VenueMarket } from \"@agg-build/sdk\";\nimport { useLiveStates } from \"./market-data/live-store\";\nimport { useAggUiConfig } from \"./core/provider\";\nimport { type MarketLiveState } from \"./market-data/live-cache\";\n\nexport type LiveBestPrices = ReadonlyMap<string, { bestBid?: number; bestAsk?: number }>;\n\n/**\n * A WS-derived best-price candidate for one outcome, carrying the venue that\n * produced each side *and* a freshness stamp. This is the richer companion to\n * {@link LiveBestPrices}: it keeps the venue attribution that the bare\n * `{ bestBid, bestAsk }` map throws away, so display surfaces can switch the\n * venue logo to whichever venue currently owns the best live price — keeping\n * the logo paired with the price instead of pinned to the REST snapshot.\n */\nexport interface LiveBestPriceCandidate {\n bestBid?: number;\n bestAsk?: number;\n /** Venue that owns the cross-venue best bid (best place to sell). */\n bestBidVenue?: string;\n /** Venue that owns the cross-venue best ask (cheapest place to buy). */\n bestAskVenue?: string;\n midpoint?: number;\n /** Venue the midpoint is attributed to (cheapest-ask side, then best-bid). */\n midpointVenue?: string;\n /** Orderbook timestamp (seconds) of the freshest book backing this candidate. */\n updatedAt?: number;\n}\n\nexport type LiveBestPriceCandidates = ReadonlyMap<string, LiveBestPriceCandidate>;\n\nconst EMPTY: LiveBestPrices = new Map();\nconst EMPTY_CANDIDATES: LiveBestPriceCandidates = new Map();\n\n// Top-of-aggregated-book per outcome — the engine already cross-venue aggregates\n// within an outcome's own snapshot, so `bids[0]` / `asks[0]` already represent\n// the best level across that outcome's venues.\nconst extractOutcomeBestPrices = (\n state: MarketLiveState | undefined,\n): { bestBid?: number; bestAsk?: number } => {\n const ob = state?.orderbook;\n if (!ob) return {};\n const bestBid = ob.bids[0]?.price;\n const bestAsk = ob.asks[0]?.price;\n return {\n bestBid: bestBid != null ? bestBid : undefined,\n bestAsk: bestAsk != null ? bestAsk : undefined,\n };\n};\n\n// Fingerprint so useMemo only recomputes when actual top-of-book moves.\nconst buildFingerprint = (\n outcomeIds: string[],\n queries: Array<{ data?: MarketLiveState }>,\n): string => {\n const parts: string[] = [];\n for (let i = 0; i < outcomeIds.length; i++) {\n const ob = queries[i]?.data?.orderbook;\n const bid = ob?.bids[0]?.price;\n const ask = ob?.asks[0]?.price;\n parts.push(`${outcomeIds[i]}:${bid ?? \"_\"}:${ask ?? \"_\"}`);\n }\n return parts.join(\"|\");\n};\n\n/**\n * WS-derived cross-venue + cross-outcome best bid/ask per outcome.\n *\n * For each outcome in `venueMarkets` (plus matched twins via MVMO refs):\n * - bestBid/bestAsk taken from the per-outcome aggregated top of book.\n * - Then folded across MVMO groups: lowest bestAsk wins (cheapest to buy),\n * highest bestBid wins (best to sell). The chosen best is broadcast to\n * every member of the group so display surfaces pick it up regardless\n * of which outcome they look up.\n *\n * Empty until WS snapshots/deltas land for the subscribed outcomes. Designed\n * to merge as overrides on top of REST `bestPrices` from `useMidpoints`, with\n * WS winning where present.\n */\nexport function useLiveBestPrices(venueMarkets: VenueMarket[] | null | undefined): LiveBestPrices {\n const {\n features: { enableLiveUpdates },\n } = useAggUiConfig();\n\n const outcomeIds = useMemo(() => {\n if (!venueMarkets?.length) return [];\n const ids = new Set<string>();\n for (const vm of venueMarkets) {\n for (const outcome of vm.venueMarketOutcomes ?? []) {\n if (outcome.id) ids.add(outcome.id);\n for (const ref of outcome.matchedVenueMarketOutcomes ?? []) {\n if (ref.venueMarketOutcomeId) ids.add(ref.venueMarketOutcomeId);\n }\n }\n }\n return [...ids].sort();\n }, [venueMarkets]);\n\n const queries = useLiveStates(outcomeIds);\n\n const fingerprint = buildFingerprint(outcomeIds, queries);\n const prevRef = useRef<{ fingerprint: string; result: LiveBestPrices }>({\n fingerprint: \"\",\n result: EMPTY,\n });\n\n return useMemo(() => {\n if (!venueMarkets?.length || !enableLiveUpdates) return EMPTY;\n if (fingerprint === prevRef.current.fingerprint) return prevRef.current.result;\n\n // Pass 1: per-outcome bestBid/bestAsk from each outcome's aggregated book.\n const perOutcome = new Map<string, { bestBid?: number; bestAsk?: number }>();\n for (let i = 0; i < outcomeIds.length; i++) {\n const state = queries[i]?.data as MarketLiveState | undefined;\n const best = extractOutcomeBestPrices(state);\n if (best.bestBid != null || best.bestAsk != null) {\n perOutcome.set(outcomeIds[i], best);\n }\n }\n\n if (perOutcome.size === 0) {\n prevRef.current = { fingerprint, result: EMPTY };\n return EMPTY;\n }\n\n const result = new Map<string, { bestBid?: number; bestAsk?: number }>(perOutcome);\n\n // Pass 2: fold across MVMO groups so every member of a cluster gets the\n // cross-outcome best. Lowest ask wins for \"cheapest buy\"; highest bid wins\n // for \"best sell\". Mirrors the REST cross-venue logic in `useMidpoints`\n // so display surfaces see consistent semantics regardless of source.\n for (const vm of venueMarkets) {\n for (const outcome of vm.venueMarketOutcomes ?? []) {\n const refs = outcome.matchedVenueMarketOutcomes ?? [];\n if (!refs.length) continue;\n\n const group = [outcome.id, ...refs.map((ref) => ref.venueMarketOutcomeId)];\n let groupBestAsk: number | undefined;\n let groupBestBid: number | undefined;\n for (const id of group) {\n const entry = perOutcome.get(id);\n if (!entry) continue;\n if (entry.bestAsk != null && (groupBestAsk == null || entry.bestAsk < groupBestAsk)) {\n groupBestAsk = entry.bestAsk;\n }\n if (entry.bestBid != null && (groupBestBid == null || entry.bestBid > groupBestBid)) {\n groupBestBid = entry.bestBid;\n }\n }\n if (groupBestAsk == null && groupBestBid == null) continue;\n\n for (const id of group) {\n const prev = result.get(id) ?? {};\n const nextBid = groupBestBid ?? prev.bestBid;\n const nextAsk = groupBestAsk ?? prev.bestAsk;\n if (nextBid == null && nextAsk == null) continue;\n result.set(id, {\n ...(nextBid != null ? { bestBid: nextBid } : {}),\n ...(nextAsk != null ? { bestAsk: nextAsk } : {}),\n });\n }\n }\n }\n\n prevRef.current = { fingerprint, result };\n return result;\n }, [venueMarkets, enableLiveUpdates, fingerprint, outcomeIds, queries]);\n}\n\n/**\n * Merge WS bestBid/bestAsk over a REST `bestPrices` map, WS values winning\n * where present. Returns the REST map unchanged when WS is empty. Designed\n * for callers that need to pass a single `bestPrices` map to display logic.\n */\nexport function mergeBestPricesPreferringLive(\n rest: ReadonlyMap<string, { bestBid?: number; bestAsk?: number }> | null | undefined,\n live: LiveBestPrices,\n): ReadonlyMap<string, { bestBid?: number; bestAsk?: number }> {\n if (!live.size) return rest ?? EMPTY;\n if (!rest || !rest.size) return live;\n\n const merged = new Map<string, { bestBid?: number; bestAsk?: number }>(rest);\n for (const [id, liveEntry] of live) {\n const prev = merged.get(id) ?? {};\n merged.set(id, {\n bestBid: liveEntry.bestBid ?? prev.bestBid,\n bestAsk: liveEntry.bestAsk ?? prev.bestAsk,\n });\n }\n return merged;\n}\n\n// ── Venue-attributed live best-price candidates ────────────────────────────\n\n/**\n * Attribute the venue that owns a given side of the aggregated top of book.\n *\n * The engine's per-outcome book already merges that outcome's venues, exposing\n * each venue's best bid/ask in `orderbook.venues`. The owner of the best bid is\n * the venue with the highest bid; the owner of the best ask is the venue with\n * the lowest ask. Falls back to the level's own per-venue size attribution\n * (largest contributor) when `venues` is absent — e.g. single-venue books.\n */\nconst pickSideVenue = (\n venues: Record<string, { bestBid: number | null; bestAsk: number | null }> | undefined,\n level: { venues?: Record<string, number> } | undefined,\n side: \"bid\" | \"ask\",\n): string | undefined => {\n if (venues) {\n let bestVenue: string | undefined;\n let bestValue: number | undefined;\n for (const [venue, info] of Object.entries(venues)) {\n const value = side === \"bid\" ? info.bestBid : info.bestAsk;\n if (value == null) continue;\n const wins = bestValue == null || (side === \"bid\" ? value > bestValue : value < bestValue);\n if (wins) {\n bestValue = value;\n bestVenue = venue;\n }\n }\n if (bestVenue != null) return bestVenue;\n }\n\n if (level?.venues) {\n let bestVenue: string | undefined;\n let bestSize = -Infinity;\n for (const [venue, size] of Object.entries(level.venues)) {\n if (size > bestSize) {\n bestSize = size;\n bestVenue = venue;\n }\n }\n if (bestVenue != null) return bestVenue;\n }\n\n return undefined;\n};\n\n/**\n * Pull the per-outcome best bid/ask, attributed venues, midpoint and freshness\n * out of a single live orderbook state. Pure — exported for unit tests.\n */\nexport const extractOutcomeBestCandidate = (\n state: MarketLiveState | undefined,\n): LiveBestPriceCandidate => {\n const ob = state?.orderbook;\n if (!ob) return {};\n\n const candidate: LiveBestPriceCandidate = {};\n const bidLevel = ob.bids[0];\n const askLevel = ob.asks[0];\n\n if (bidLevel?.price != null) {\n candidate.bestBid = bidLevel.price;\n const venue = pickSideVenue(ob.venues, bidLevel, \"bid\");\n if (venue) candidate.bestBidVenue = venue;\n }\n if (askLevel?.price != null) {\n candidate.bestAsk = askLevel.price;\n const venue = pickSideVenue(ob.venues, askLevel, \"ask\");\n if (venue) candidate.bestAskVenue = venue;\n }\n if (ob.midpoint != null) {\n candidate.midpoint = ob.midpoint;\n // The pill defaults to \"buy\" intent, so attribute the midpoint to the\n // cheapest-ask venue first, then the best-bid venue.\n const midVenue = candidate.bestAskVenue ?? candidate.bestBidVenue;\n if (midVenue) candidate.midpointVenue = midVenue;\n }\n if (ob.timestamp != null) candidate.updatedAt = ob.timestamp;\n\n return candidate;\n};\n\n/**\n * Cross-venue + cross-outcome venue-attributed best-price candidates.\n *\n * Pure (no React) so the cross-venue fold can be unit-tested directly:\n * - Pass 1: per-outcome candidate from each outcome's own aggregated book.\n * - Pass 2: fold across MVMO groups. Lowest ask wins (cheapest to buy),\n * highest bid wins (best to sell), and the *winning venue* + freshest\n * timestamp travel with the chosen price to every member of the group.\n * This is what lets a different venue's live book switch both the price\n * and the venue logo on every WS update.\n *\n * Mirrors the price fold in {@link useLiveBestPrices} and the REST fold in\n * `useMidpoints.extractBestPrices`, but additionally tracks venue + freshness.\n */\nexport function buildLiveBestPriceCandidates(\n outcomeIds: string[],\n states: Array<MarketLiveState | undefined>,\n venueMarkets: VenueMarket[] | null | undefined,\n): Map<string, LiveBestPriceCandidate> {\n const perOutcome = new Map<string, LiveBestPriceCandidate>();\n for (let i = 0; i < outcomeIds.length; i++) {\n const candidate = extractOutcomeBestCandidate(states[i]);\n if (candidate.bestBid != null || candidate.bestAsk != null || candidate.midpoint != null) {\n perOutcome.set(outcomeIds[i], candidate);\n }\n }\n\n if (perOutcome.size === 0 || !venueMarkets?.length) {\n return perOutcome;\n }\n\n const result = new Map<string, LiveBestPriceCandidate>(perOutcome);\n\n for (const vm of venueMarkets) {\n for (const outcome of vm.venueMarketOutcomes ?? []) {\n const refs = outcome.matchedVenueMarketOutcomes ?? [];\n if (!refs.length) continue;\n\n const group = [outcome.id, ...refs.map((ref) => ref.venueMarketOutcomeId)];\n let groupBestAsk: number | undefined;\n let groupBestAskVenue: string | undefined;\n let groupBestBid: number | undefined;\n let groupBestBidVenue: string | undefined;\n let groupUpdatedAt: number | undefined;\n for (const id of group) {\n const entry = perOutcome.get(id);\n if (!entry) continue;\n if (entry.bestAsk != null && (groupBestAsk == null || entry.bestAsk < groupBestAsk)) {\n groupBestAsk = entry.bestAsk;\n groupBestAskVenue = entry.bestAskVenue;\n }\n if (entry.bestBid != null && (groupBestBid == null || entry.bestBid > groupBestBid)) {\n groupBestBid = entry.bestBid;\n groupBestBidVenue = entry.bestBidVenue;\n }\n if (\n entry.updatedAt != null &&\n (groupUpdatedAt == null || entry.updatedAt > groupUpdatedAt)\n ) {\n groupUpdatedAt = entry.updatedAt;\n }\n }\n if (groupBestAsk == null && groupBestBid == null) continue;\n\n for (const id of group) {\n const prev = result.get(id) ?? {};\n const next: LiveBestPriceCandidate = { ...prev };\n if (groupBestBid != null) {\n next.bestBid = groupBestBid;\n if (groupBestBidVenue) next.bestBidVenue = groupBestBidVenue;\n }\n if (groupBestAsk != null) {\n next.bestAsk = groupBestAsk;\n if (groupBestAskVenue) next.bestAskVenue = groupBestAskVenue;\n }\n if (groupUpdatedAt != null) next.updatedAt = groupUpdatedAt;\n result.set(id, next);\n }\n }\n }\n\n return result;\n}\n\n// Fingerprint includes venue attribution + timestamp so the memo recomputes\n// (and the venue logo can switch) whenever any of those move, not just price.\nconst buildCandidateFingerprint = (\n outcomeIds: string[],\n queries: Array<{ data?: MarketLiveState }>,\n): string => {\n const parts: string[] = [];\n for (let i = 0; i < outcomeIds.length; i++) {\n const ob = queries[i]?.data?.orderbook;\n const bid = ob?.bids[0]?.price;\n const ask = ob?.asks[0]?.price;\n const mid = ob?.midpoint;\n const ts = ob?.timestamp;\n const venues = ob?.venues ? Object.keys(ob.venues).sort().join(\",\") : \"\";\n parts.push(`${outcomeIds[i]}:${bid ?? \"_\"}:${ask ?? \"_\"}:${mid ?? \"_\"}:${ts ?? \"_\"}:${venues}`);\n }\n return parts.join(\"|\");\n};\n\n/**\n * React hook companion to {@link useLiveBestPrices} that additionally carries\n * venue attribution + freshness per outcome. Recomputes on every WS update\n * (snapshot/delta) that moves price, venue ownership, or timestamp.\n *\n * Empty until WS books land for the subscribed outcomes. Designed to feed a\n * unified price+venue selector so the venue logo always follows the live price.\n */\nexport function useLiveBestPriceCandidates(\n venueMarkets: VenueMarket[] | null | undefined,\n): LiveBestPriceCandidates {\n const {\n features: { enableLiveUpdates },\n } = useAggUiConfig();\n\n const outcomeIds = useMemo(() => {\n if (!venueMarkets?.length) return [];\n const ids = new Set<string>();\n for (const vm of venueMarkets) {\n for (const outcome of vm.venueMarketOutcomes ?? []) {\n if (outcome.id) ids.add(outcome.id);\n for (const ref of outcome.matchedVenueMarketOutcomes ?? []) {\n if (ref.venueMarketOutcomeId) ids.add(ref.venueMarketOutcomeId);\n }\n }\n }\n return [...ids].sort();\n }, [venueMarkets]);\n\n const queries = useLiveStates(outcomeIds);\n\n const fingerprint = buildCandidateFingerprint(outcomeIds, queries);\n const prevRef = useRef<{ fingerprint: string; result: LiveBestPriceCandidates }>({\n fingerprint: \"\",\n result: EMPTY_CANDIDATES,\n });\n\n return useMemo(() => {\n if (!venueMarkets?.length || !enableLiveUpdates) return EMPTY_CANDIDATES;\n if (fingerprint === prevRef.current.fingerprint) return prevRef.current.result;\n\n const states = outcomeIds.map((_, i) => queries[i]?.data as MarketLiveState | undefined);\n const result = buildLiveBestPriceCandidates(outcomeIds, states, venueMarkets);\n prevRef.current = { fingerprint, result };\n return result;\n }, [venueMarkets, enableLiveUpdates, fingerprint, outcomeIds, queries]);\n}\n","import type { WsTrade } from \"@agg-build/sdk\";\nimport { useAggUiConfig } from \"./core/provider\";\nimport { useLiveMarket } from \"./use-live-market\";\nimport { useMarketDataSubscription } from \"./market-data/subscription\";\n\n/**\n * Subscribe to real-time trade feed for a canonical market.\n * Manages a separate trade subscription on the WS (trades use a different channel).\n * Returns a bounded array of recent trades (max 50, newest first).\n */\nexport function useLiveTrades(canonicalMarketId: string | null): WsTrade[] {\n const {\n features: { enableLiveUpdates },\n } = useAggUiConfig();\n const { trades } = useLiveMarket(canonicalMarketId);\n\n useMarketDataSubscription({\n marketId: canonicalMarketId,\n enabled: Boolean(canonicalMarketId && enableLiveUpdates),\n orderbook: false,\n trades: true,\n });\n\n return trades;\n}\n","import type { MidpointItem, VenueMarket } from \"@agg-build/sdk\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport { useMemo } from \"react\";\nimport { useAggClient, useAggUiConfig } from \"./core/provider\";\n\nexport interface UseMidpointsOptions {\n maxMidpointIdsPerRequest?: number;\n}\n\nexport interface UseMidpointsResult {\n /** Map of outcomeId → price. Empty while loading. */\n prices: Map<string, number>;\n /**\n * Map of outcomeId → lowest midpoint available for that exact semantic outcome\n * across the selected market cluster. Alias of `prices`, exposed under a\n * clearer name for display surfaces that want a single source of truth.\n */\n bestMidpointsByOutcomeId: Map<string, number>;\n /** Venue-local midpoint for each outcome before cross-venue best-price folding. */\n currentMidpointsByOutcomeId?: Map<string, number>;\n /**\n * Map of outcomeId → venue name that provided the price in `prices`.\n * When a matched sibling offers a lower midpoint for the same semantic\n * side, this records that sibling's venue so callers can show the\n * correct venue logo alongside the best price.\n * Empty while loading or when the API response omits `venue` fields.\n */\n venueByOutcomeId: Map<string, string>;\n /**\n * Map of outcomeId → { bestBid?, bestAsk? }. Top-of-book prices extracted\n * from the midpoints response when bestPrice=true. Empty while loading\n * or when bestPrice data is unavailable.\n */\n bestPrices: Map<string, { bestBid?: number; bestAsk?: number }>;\n /**\n * Map of outcomeId → { bestBidVenue?, bestAskVenue? }. Tracks which venue\n * supplied the winning side of the book across the MVMO group so display\n * surfaces can pair the logo with the price. Distinct per side because\n * \"best buy\" and \"best sell\" can come from different venues.\n */\n bestPriceVenuesByOutcomeId: Map<string, { bestBidVenue?: string; bestAskVenue?: string }>;\n /** True while the midpoints fetch is in flight. */\n isLoading: boolean;\n /** Best midpoint value across all venues. Undefined while loading. */\n bestMidpoint: number | undefined;\n /**\n * Venue that produced `bestMidpoint`. Paired with `bestMidpoint` from the\n * same winning outcome so display surfaces can render a matching logo +\n * price. Undefined when no candidate produced a price or when the\n * response lacked a `venue` field.\n */\n bestMidpointVenue: string | undefined;\n}\n\nconst normalizeVenueMarketIds = (venueMarkets: VenueMarket[] | null | undefined): string[] => {\n const ids = new Set<string>();\n for (const market of venueMarkets ?? []) {\n if (market.id) ids.add(market.id);\n // Include matched (cross-venue) sibling markets so the engine returns\n // top-of-book bestAsk/bestBid data for them — otherwise the response\n // only contains nested mid-points for siblings and best-price selection\n // can miss the lower side of the book.\n for (const sibling of market.matchedVenueMarkets ?? []) {\n if (sibling.id) ids.add(sibling.id);\n }\n }\n return [...ids].sort((left, right) => left.localeCompare(right));\n};\n\n/** Re-poll cadence while a requested market still has no price (e.g. a cold book). */\nexport const EMPTY_MIDPOINTS_POLL_MS = 5_000;\n/** Stop re-polling after this many fetches; a remount can still refetch. */\nexport const EMPTY_MIDPOINTS_MAX_FETCHES = 12;\n\nconst hasUsableMidpoint = (item: MidpointItem | undefined): boolean => {\n if (!item) return false;\n if (item.midpoint != null) return true;\n return (item.outcomes ?? []).some(\n (outcome) => outcome.midpoint != null || outcome.bestBid != null || outcome.bestAsk != null,\n );\n};\n\n/**\n * True when every requested primary market came back with a usable price.\n * Some venues (e.g. BETDEX) only publish midpoints after their book is read,\n * so a first response can be empty; an incomplete response must not be cached\n * as final.\n */\nexport const isMidpointResponseComplete = (\n data: { data?: MidpointItem[] } | undefined,\n primaryVenueMarketIds: readonly string[],\n): boolean => {\n if (!data?.data) return false;\n const itemByMarketId = new Map(data.data.map((item) => [item.venueMarketId, item]));\n return primaryVenueMarketIds.every((id) => hasUsableMidpoint(itemByMarketId.get(id)));\n};\n\nconst normalizeOutcomeLabel = (label: string | null | undefined): string => {\n return typeof label === \"string\" ? label.trim().toLowerCase() : \"\";\n};\n\nconst normalizeSemanticOutcomeLabel = (label: string | null | undefined): string => {\n const normalizedLabel = normalizeOutcomeLabel(label);\n if (!normalizedLabel) return \"\";\n if (normalizedLabel === \"y\") return \"yes\";\n if (normalizedLabel === \"n\") return \"no\";\n return normalizedLabel;\n};\n\nconst outcomeMatchesSemanticSide = (\n left: { label?: string | null; title?: string | null },\n right: { label?: string | null; title?: string | null },\n): boolean => {\n const leftCandidates = [left.label, left.title]\n .map((value) => normalizeSemanticOutcomeLabel(value))\n .filter(Boolean);\n const rightCandidates = [right.label, right.title]\n .map((value) => normalizeSemanticOutcomeLabel(value))\n .filter(Boolean);\n\n return leftCandidates.some((candidate) => rightCandidates.includes(candidate));\n};\n\nconst resolveBestMidpointCandidateOutcomeIds = (\n venueMarkets: VenueMarket[] | null | undefined,\n): string[] => {\n if (!venueMarkets?.length) return [];\n\n const candidateIds: string[] = [];\n for (const market of venueMarkets) {\n const outcomes = market.venueMarketOutcomes ?? [];\n const yesOutcome = outcomes.find((outcome) => normalizeOutcomeLabel(outcome.label) === \"yes\");\n if (yesOutcome?.id) {\n candidateIds.push(yesOutcome.id);\n continue;\n }\n\n const firstOutcomeId = outcomes[0]?.id;\n if (firstOutcomeId) {\n candidateIds.push(firstOutcomeId);\n }\n }\n\n return [...new Set(candidateIds)];\n};\n\n/**\n * Find the per-outcome sibling midpoint matching a parent outcome's MVMO\n * reference. Returns `null` when the engine response doesn't carry the\n * per-outcome alignment (older builds or markets without MVMO rows).\n */\nconst resolveSiblingOutcomeMidpoint = (\n matched: MidpointItem[\"matched\"] | undefined,\n ref: { venueMarketId: string; venueMarketOutcomeId: string },\n): { midpoint: number; venue: string | null } | null => {\n if (!matched?.length) return null;\n const sibling = matched.find((m) => m.venueMarketId === ref.venueMarketId);\n if (!sibling?.outcomes?.length) return null;\n const sibOutcome = sibling.outcomes.find(\n (o) => o.venueMarketOutcomeId === ref.venueMarketOutcomeId,\n );\n if (sibOutcome?.midpoint == null) return null;\n return { midpoint: sibOutcome.midpoint, venue: sibling.venue ?? null };\n};\n\nconst resolveSemanticFallbackMidpoint = ({\n marketById,\n outcome,\n matched,\n}: {\n marketById: Map<string, VenueMarket>;\n outcome: VenueMarket[\"venueMarketOutcomes\"][number];\n matched: MidpointItem[\"matched\"] | undefined;\n}): { midpoint: number; venue: string | null } | null => {\n if (!matched?.length) return null;\n\n let best: { midpoint: number; venue: string | null } | null = null;\n\n for (const sibling of matched) {\n const siblingMarket = marketById.get(sibling.venueMarketId);\n if (!siblingMarket?.venueMarketOutcomes?.length) continue;\n\n for (const siblingOutcome of siblingMarket.venueMarketOutcomes) {\n if (!outcomeMatchesSemanticSide(outcome, siblingOutcome)) continue;\n\n const candidate = resolveSiblingOutcomeMidpoint(matched, {\n venueMarketId: sibling.venueMarketId,\n venueMarketOutcomeId: siblingOutcome.id,\n });\n if (candidate == null) continue;\n if (best == null || candidate.midpoint < best.midpoint) {\n best = candidate;\n }\n }\n }\n\n return best;\n};\n\n/**\n * Build a per-outcome bestBid/bestAsk map from the midpoint response, with\n * cross-venue best-price selection applied.\n *\n * Rules:\n * - Pass 1: collect each outcome's own bestBid/bestAsk from `data[].outcomes`\n * and record the venue that supplied it.\n * - Pass 2: collect bestBid/bestAsk for any matched-only outcome that\n * appears under `data[].matched[].outcomes` (no top-level row of its own).\n * - Pass 3: for every parent outcome that lists `matchedVenueMarketOutcomes`,\n * fold the sibling outcomes' bestBid/bestAsk into the parent and pick the\n * \"best\" of each side — lowest bestAsk (cheapest to buy) and highest\n * bestBid (best to sell). The sibling's entry is updated symmetrically so\n * that whichever side of the pair the UI looks up, it reads the same\n * trusted cross-venue best — *and* the venue that produced each winning\n * side is recorded so the UI can pair the logo with the right price.\n */\nconst extractBestPrices = (\n data: MidpointItem[] | undefined,\n venueMarkets: VenueMarket[] | null | undefined,\n): {\n bestPrices: Map<string, { bestBid?: number; bestAsk?: number }>;\n bestPriceVenuesByOutcomeId: Map<string, { bestBidVenue?: string; bestAskVenue?: string }>;\n} => {\n const bestPrices = new Map<string, { bestBid?: number; bestAsk?: number }>();\n const venuesByOutcome = new Map<string, { bestBidVenue?: string; bestAskVenue?: string }>();\n if (!data?.length) return { bestPrices, bestPriceVenuesByOutcomeId: venuesByOutcome };\n\n const setEntry = (\n outcomeId: string,\n next: {\n bestBid?: number | null;\n bestAsk?: number | null;\n bestBidVenue?: string | null;\n bestAskVenue?: string | null;\n },\n ): void => {\n const prev = bestPrices.get(outcomeId);\n const merged: { bestBid?: number; bestAsk?: number } = { ...(prev ?? {}) };\n if (next.bestBid != null) merged.bestBid = next.bestBid;\n if (next.bestAsk != null) merged.bestAsk = next.bestAsk;\n if (merged.bestBid != null || merged.bestAsk != null) bestPrices.set(outcomeId, merged);\n\n const prevVenues = venuesByOutcome.get(outcomeId);\n const mergedVenues: { bestBidVenue?: string; bestAskVenue?: string } = {\n ...(prevVenues ?? {}),\n };\n if (next.bestBidVenue != null) mergedVenues.bestBidVenue = next.bestBidVenue;\n if (next.bestAskVenue != null) mergedVenues.bestAskVenue = next.bestAskVenue;\n if (mergedVenues.bestBidVenue || mergedVenues.bestAskVenue) {\n venuesByOutcome.set(outcomeId, mergedVenues);\n }\n };\n\n // Pass 1 — own per-outcome best prices, tagged with the row's venue.\n for (const item of data) {\n const venue = item.venue ?? null;\n for (const o of item.outcomes ?? []) {\n if (o.bestBid != null || o.bestAsk != null) {\n setEntry(o.venueMarketOutcomeId, {\n bestBid: o.bestBid,\n bestAsk: o.bestAsk,\n bestBidVenue: o.bestBid != null ? venue : null,\n bestAskVenue: o.bestAsk != null ? venue : null,\n });\n }\n }\n }\n\n // Pass 2 — matched-only outcomes (no top-level row of their own).\n for (const item of data) {\n for (const m of item.matched ?? []) {\n const venue = m.venue ?? null;\n for (const o of m.outcomes ?? []) {\n if (bestPrices.has(o.venueMarketOutcomeId)) continue;\n if (o.bestBid != null || o.bestAsk != null) {\n setEntry(o.venueMarketOutcomeId, {\n bestBid: o.bestBid,\n bestAsk: o.bestAsk,\n bestBidVenue: o.bestBid != null ? venue : null,\n bestAskVenue: o.bestAsk != null ? venue : null,\n });\n }\n }\n }\n }\n\n // Pass 3 — cross-venue best per logical outcome via MVMO refs on the parent\n // markets. Lowest bestAsk wins (cheapest place to buy that semantic side);\n // highest bestBid wins (best place to sell). Apply the chosen best to every\n // outcome ID in the MVMO group along with the venue that produced it so any\n // display surface that looks up either the primary or the matched outcome\n // ID gets the same trusted price *and* the matching venue logo.\n if (venueMarkets?.length) {\n for (const market of venueMarkets) {\n for (const outcome of market.venueMarketOutcomes ?? []) {\n const refs = outcome.matchedVenueMarketOutcomes ?? [];\n if (!refs.length) continue;\n\n const group = [outcome.id, ...refs.map((ref) => ref.venueMarketOutcomeId)];\n let bestAsk: number | undefined;\n let bestBid: number | undefined;\n let bestAskVenue: string | undefined;\n let bestBidVenue: string | undefined;\n for (const id of group) {\n const entry = bestPrices.get(id);\n const venues = venuesByOutcome.get(id);\n if (!entry) continue;\n if (entry.bestAsk != null && (bestAsk == null || entry.bestAsk < bestAsk)) {\n bestAsk = entry.bestAsk;\n bestAskVenue = venues?.bestAskVenue ?? bestAskVenue;\n }\n if (entry.bestBid != null && (bestBid == null || entry.bestBid > bestBid)) {\n bestBid = entry.bestBid;\n bestBidVenue = venues?.bestBidVenue ?? bestBidVenue;\n }\n }\n if (bestAsk == null && bestBid == null) continue;\n for (const id of group) {\n setEntry(id, {\n bestBid,\n bestAsk,\n bestBidVenue,\n bestAskVenue,\n });\n }\n }\n }\n }\n\n return { bestPrices, bestPriceVenuesByOutcomeId: venuesByOutcome };\n};\n\n/**\n * Fetches live midpoints for the given venue markets.\n *\n * Returns { prices, isLoading } so callers can show a skeleton while loading.\n *\n * Cross-venue best-price selection walks each parent outcome's\n * `matchedVenueMarketOutcomes` (MVMO references) and looks up the matched\n * counterpart's per-outcome midpoint in `matched[].outcomes`. The lowest\n * midpoint wins per outcome — semantically correct for both Yes and No\n * sides because MVMO links same-side counterparts regardless of label\n * inversion. No label heuristics; no `1 - midpoint` flips.\n */\nexport function useMidpoints(\n venueMarkets: VenueMarket[] | null | undefined,\n options?: UseMidpointsOptions,\n): UseMidpointsResult {\n const client = useAggClient();\n const {\n market: { maxMidpointIdsPerRequest: configuredMaxMidpointIdsPerRequest },\n } = useAggUiConfig();\n const maxMidpointIdsPerRequest =\n options?.maxMidpointIdsPerRequest ?? configuredMaxMidpointIdsPerRequest;\n\n const ids = useMemo(() => normalizeVenueMarketIds(venueMarkets), [venueMarkets]);\n const bestMidpointCandidateOutcomeIds = useMemo(\n () => resolveBestMidpointCandidateOutcomeIds(venueMarkets),\n [venueMarkets],\n );\n\n const primaryVenueMarketIds = useMemo(\n () => (venueMarkets ?? []).map((market) => market.id).filter(Boolean),\n [venueMarkets],\n );\n\n const { data, isLoading } = useQuery({\n queryKey: [\"midpoints\", ids, maxMidpointIdsPerRequest],\n queryFn: () => client.getMidpoints(ids, { bestPrice: true, maxMidpointIdsPerRequest }),\n enabled: ids.length > 0,\n // Complete responses stay cached for the session (unchanged behavior).\n // Incomplete ones are stale, so a remount refetches them and a short,\n // bounded poll picks up prices once a cold venue book warms.\n staleTime: (query) =>\n isMidpointResponseComplete(query.state.data, primaryVenueMarketIds) ? Infinity : 0,\n refetchInterval: (query) =>\n !isMidpointResponseComplete(query.state.data, primaryVenueMarketIds) &&\n query.state.dataUpdateCount < EMPTY_MIDPOINTS_MAX_FETCHES\n ? EMPTY_MIDPOINTS_POLL_MS\n : false,\n gcTime: 30 * 60_000,\n refetchOnMount: true,\n refetchOnWindowFocus: false,\n refetchOnReconnect: false,\n });\n\n const result = useMemo(() => {\n const map = new Map<string, number>();\n const currentMap = new Map<string, number>();\n const venueMap = new Map<string, string>();\n if (!data?.data || !venueMarkets) return { map, currentMap, venueMap };\n\n const itemByMarketId = new Map(data.data.map((item) => [item.venueMarketId, item]));\n const marketById = new Map(venueMarkets.map((market) => [market.id, market]));\n\n // Pass 1 — own per-outcome midpoints. Always prefer these over the\n // legacy market-level midpoint; the engine's per-outcome data sidesteps\n // any primary-outcome inversion.\n for (const item of data.data) {\n if (!item.outcomes?.length) continue;\n for (const o of item.outcomes) {\n if (o.midpoint == null) continue;\n map.set(o.venueMarketOutcomeId, o.midpoint);\n currentMap.set(o.venueMarketOutcomeId, o.midpoint);\n if (item.venue) venueMap.set(o.venueMarketOutcomeId, item.venue);\n }\n }\n\n // Pass 2 — cross-venue best-price per outcome via MVMO references on\n // the parent outcome. Lowest midpoint wins (cheapest place to buy\n // that semantic side). For sparse related markets that arrive without\n // MVMO refs, fall back to same-side sibling matching within the already\n // fetched matched rows so the UI can render a price instead of \"-\".\n for (const market of venueMarkets) {\n const item = itemByMarketId.get(market.id);\n if (!item) continue;\n for (const outcome of market.venueMarketOutcomes) {\n const refs = outcome.matchedVenueMarketOutcomes ?? [];\n let best: number | null = map.get(outcome.id) ?? null;\n let bestVenue: string | null = item.venue ?? null;\n if (refs.length > 0) {\n for (const ref of refs) {\n const sib = resolveSiblingOutcomeMidpoint(item.matched, ref);\n if (sib == null) continue;\n currentMap.set(ref.venueMarketOutcomeId, sib.midpoint);\n if (best == null || sib.midpoint < best) {\n best = sib.midpoint;\n bestVenue = sib.venue ?? bestVenue;\n }\n }\n } else if (best == null) {\n const fallback = resolveSemanticFallbackMidpoint({\n marketById,\n outcome,\n matched: item.matched,\n });\n if (fallback != null) {\n best = fallback.midpoint;\n bestVenue = fallback.venue ?? bestVenue;\n }\n }\n if (best != null) {\n map.set(outcome.id, best);\n if (bestVenue) venueMap.set(outcome.id, bestVenue);\n }\n }\n }\n\n return { map, currentMap, venueMap };\n }, [data, venueMarkets]);\n\n const { bestMidpoint, bestMidpointVenue } = useMemo(() => {\n // Walk the preferred (Yes-side) candidates first so the winning venue is\n // paired with the same outcome whose midpoint we expose as `bestMidpoint`.\n // Falling back to the full map keeps parity with the legacy behavior when\n // no candidate produced a price.\n let value: number | undefined;\n let venue: string | undefined;\n\n for (const outcomeId of bestMidpointCandidateOutcomeIds) {\n const midpoint = result.map.get(outcomeId);\n if (midpoint == null) continue;\n if (value == null || midpoint < value) {\n value = midpoint;\n venue = result.venueMap.get(outcomeId);\n }\n }\n\n if (value == null) {\n for (const [outcomeId, midpoint] of result.map) {\n if (value == null || midpoint < value) {\n value = midpoint;\n venue = result.venueMap.get(outcomeId);\n }\n }\n }\n\n return { bestMidpoint: value, bestMidpointVenue: venue };\n }, [bestMidpointCandidateOutcomeIds, result.map, result.venueMap]);\n\n const { bestPrices, bestPriceVenuesByOutcomeId } = useMemo(\n () => extractBestPrices(data?.data, venueMarkets),\n [data?.data, venueMarkets],\n );\n\n return {\n prices: result.map,\n bestMidpointsByOutcomeId: result.map,\n currentMidpointsByOutcomeId: result.currentMap,\n venueByOutcomeId: result.venueMap,\n bestPrices,\n bestPriceVenuesByOutcomeId,\n isLoading: isLoading && ids.length > 0,\n bestMidpoint,\n bestMidpointVenue,\n };\n}\n","import type { WsCandleInterval } from \"@agg-build/sdk\";\nimport { useEffect, useMemo, useState } from \"react\";\nimport type { ChartTimeRange } from \"./core/ui-config/types\";\nimport { getIntervalSeconds } from \"./market-data/chart-cache\";\nimport { timeRangeToInterval } from \"./use-live-candle-overlay\";\n\nexport interface UseRollingChartWindowOptions {\n range: ChartTimeRange;\n /**\n * Override the WS candle interval. Defaults to the canonical mapping from\n * `timeRangeToInterval`. Tests use this to inject a deterministic value.\n */\n interval?: WsCandleInterval;\n /**\n * Tick cadence for `nowSec`, in milliseconds. Defaults to 1s. The query\n * boundary (`endTs`) is bucketized so React Query only refetches when the\n * candle bucket advances, not on every tick.\n */\n tickMs?: number;\n /**\n * Read of `Date.now()` (ms). Overridable for tests.\n */\n nowMs?: () => number;\n}\n\nexport interface RollingChartWindow {\n range: ChartTimeRange;\n interval: WsCandleInterval;\n /** Width of the visible/rolling domain in seconds. */\n rangeSeconds: number;\n /** Width of one closed bar in seconds. */\n intervalSeconds: number;\n /**\n * Current wall-clock seconds, updated on every tick. The visible domain is\n * always `[nowSec - rangeSeconds, nowSec]` — use this for filtering points\n * to the rolling window.\n */\n nowSec: number;\n /**\n * Bucketized end of the rolling window. Snaps to the next interval\n * boundary so the React Query key (and therefore REST refetch) only\n * advances when a new candle bucket starts. Use this as `endTs` for the\n * REST query.\n */\n endTs: number;\n /**\n * Bucketized start: `endTs - rangeSeconds`. Use as `startTs` for the\n * REST query.\n */\n startTs: number;\n /**\n * Refetch interval to pass to React Query, in milliseconds. Matches one\n * candle bucket so historical bars roll in cleanly even without WS.\n */\n refetchIntervalMs: number;\n}\n\nconst RANGE_SECONDS_BY_RANGE: Record<ChartTimeRange, number> = {\n \"1H\": 60 * 60,\n \"6H\": 6 * 60 * 60,\n \"1D\": 24 * 60 * 60,\n \"1W\": 7 * 24 * 60 * 60,\n \"1M\": 30 * 24 * 60 * 60,\n ALL: 6 * 30 * 24 * 60 * 60,\n};\n\nexport const rangeToSeconds = (range: ChartTimeRange): number => RANGE_SECONDS_BY_RANGE[range];\n\n/**\n * Pure resolver for the rolling window, factored out of `useRollingChartWindow`\n * so the time-math can be unit-tested without rendering React.\n *\n * Invariants:\n * - `nowSec - rangeSeconds === domainStartTs` (the visible domain is\n * always exactly `rangeSeconds` wide regardless of how long mounted).\n * - `endTs - startTs === rangeSeconds` (the bucketized query window is\n * also exactly `rangeSeconds` wide; only the alignment to bucket\n * boundaries differs from the visible domain).\n * - `endTs % intervalSeconds === 0` (snaps to next bucket boundary so\n * the React Query key stays stable between bucket rollovers).\n */\nexport const resolveRollingWindow = (params: {\n range: ChartTimeRange;\n nowSec: number;\n interval?: WsCandleInterval;\n}): RollingChartWindow => {\n const interval = params.interval ?? timeRangeToInterval(params.range);\n const intervalSeconds = getIntervalSeconds(interval);\n const rangeSeconds = rangeToSeconds(params.range);\n const endTs = Math.ceil(params.nowSec / intervalSeconds) * intervalSeconds;\n return {\n range: params.range,\n interval,\n rangeSeconds,\n intervalSeconds,\n nowSec: params.nowSec,\n endTs,\n startTs: endTs - rangeSeconds,\n refetchIntervalMs: intervalSeconds * 1000,\n };\n};\n\n/**\n * Drives a rolling time domain `[nowSec - rangeSeconds, nowSec]` that ticks\n * while the chart is mounted.\n *\n * Why two timestamps (`nowSec` vs `endTs`):\n * - `nowSec` updates every `tickMs` (default 1s) so the visible domain\n * stays exactly `rangeSeconds` wide. Series points outside that domain\n * should be filtered out by the caller.\n * - `endTs` is bucketized to the next interval boundary so React Query's\n * key only changes when a new candle bucket actually starts. Without\n * this, the chart would refetch every tick.\n *\n * The bucket advance is also what drives REST refetches that backfill any\n * closed bars the WebSocket missed. WS updates feed the in-flight candle\n * and promote it on rollover (see `chart-cache.applyMidpointToMarketChart`);\n * the REST refetch only matters when WS is disconnected or quiet.\n */\nexport const useRollingChartWindow = (\n options: UseRollingChartWindowOptions,\n): RollingChartWindow => {\n const tickMs = options.tickMs ?? 1000;\n // Stabilize the `nowMs` reader. Inline fallbacks (`?? (() => Date.now())`)\n // create a fresh function on every render, which would invalidate the\n // useEffect deps and tear down/re-create the interval continuously.\n const optionsNowMs = options.nowMs;\n const nowMs = useMemo(() => optionsNowMs ?? (() => Date.now()), [optionsNowMs]);\n\n const [nowSec, setNowSec] = useState<number>(() => Math.floor(nowMs() / 1000));\n\n useEffect(() => {\n setNowSec(Math.floor(nowMs() / 1000));\n const handle = setInterval(() => {\n setNowSec(Math.floor(nowMs() / 1000));\n }, tickMs);\n return () => clearInterval(handle);\n }, [tickMs, nowMs]);\n\n return useMemo<RollingChartWindow>(\n () => resolveRollingWindow({ range: options.range, nowSec, interval: options.interval }),\n [options.range, options.interval, nowSec],\n );\n};\n","import { useEffect, useRef, useState } from \"react\";\nimport type { WsArbFeedBatch, WsArbMarketUpdate } from \"@agg-build/sdk\";\nimport { useAggWebSocket } from \"./core/providers/ws-provider\";\n\n// ── Types ──────────────────────────────────────────────────────────────────────\n\nexport interface UseMarketArbResult {\n /** Live arbReturn for the market, or null if no data received yet. */\n arbReturn: number | null;\n /** True once at least one live update (or a cached seed) has been received. */\n isLive: boolean;\n}\n\nexport interface UseArbFeedResult {\n /**\n * Live arbReturn keyed by marketId.\n * Values are the most-recently received arbReturn for each market.\n */\n byMarket: Map<string, number>;\n /**\n * MAX arbReturn keyed by venueEventId.\n * Derived from byMarket by scanning all markets that share a venueEventId and\n * taking the maximum. Rebuilt fully on every batch so it is correct even when\n * a market's arb DROPS between batches.\n */\n byEvent: Map<string, number>;\n}\n\n// ── Internal state shapes ──────────────────────────────────────────────────────\n\ninterface MarketArbState {\n arbReturn: number | null;\n isLive: boolean;\n}\n\n/** Internal: stores arb + its venueEventId together so byEvent can be recomputed. */\ninterface ArbFeedState {\n byMarket: Map<string, { arb: number; eventId: string | null }>;\n byEvent: Map<string, number>;\n}\n\n// ── useMarketArb ───────────────────────────────────────────────────────────────\n\n/**\n * Subscribe to real-time arbReturn updates for a single market.\n *\n * Seeds initial state from the WS cache (`ws.getArb`) if available, then\n * streams live updates via `ws.subscribeArb`. Unsubscribes on unmount or when\n * `marketId` changes.\n *\n * Returns `{ arbReturn: number | null; isLive: boolean }`.\n * `isLive` is true once at least one value (cached or live) is received.\n */\nexport function useMarketArb(marketId: string | null): UseMarketArbResult {\n const ws = useAggWebSocket();\n const [state, setState] = useState<MarketArbState>({ arbReturn: null, isLive: false });\n\n useEffect(() => {\n if (!ws || !marketId) return;\n\n // Seed from cache immediately if available.\n const cached = ws.getArb(marketId);\n if (cached != null) {\n setState({ arbReturn: cached.arbReturn, isLive: true });\n }\n\n const off = ws.subscribeArb(marketId, (msg: WsArbMarketUpdate) => {\n setState({ arbReturn: msg.arbReturn, isLive: true });\n });\n\n return off;\n }, [ws, marketId]);\n\n return state;\n}\n\n// ── useArbFeed ─────────────────────────────────────────────────────────────────\n\nconst EMPTY_ARB_FEED: ArbFeedState = {\n byMarket: new Map(),\n byEvent: new Map(),\n};\n\n/**\n * Subscribe to the coalesced arb-return feed.\n *\n * Maintains a `byMarket` map (marketId → arbReturn) and derives a `byEvent`\n * map (venueEventId → max arbReturn across all markets in that event).\n *\n * `byEvent` is ALWAYS fully rebuilt from `byMarket` on each batch so that\n * dropping arb values (e.g. m2 goes from 0.30 → 0.02) are reflected correctly\n * — there is no stale running-max accumulation.\n *\n * Returns `{ byMarket: Map<string, number>; byEvent: Map<string, number> }`.\n */\nexport function useArbFeed(): UseArbFeedResult {\n const ws = useAggWebSocket();\n const [state, setState] = useState<ArbFeedState>(EMPTY_ARB_FEED);\n // Keep a stable ref to state for the subscription callback closure.\n // This avoids stale-closure issues without listing state in deps.\n const stateRef = useRef<ArbFeedState>(state);\n stateRef.current = state;\n\n useEffect(() => {\n if (!ws) return;\n\n const off = ws.subscribeArbFeed((batch: WsArbFeedBatch) => {\n setState((prev) => {\n // Merge incoming entries into a new byMarket.\n const nextByMarket = new Map(prev.byMarket);\n for (const entry of batch.entries) {\n nextByMarket.set(entry.marketId, {\n arb: entry.arbReturn,\n eventId: entry.venueEventId,\n });\n }\n\n // Fully rebuild byEvent from nextByMarket so that value drops are correct.\n const nextByEvent = new Map<string, number>();\n for (const { arb, eventId } of nextByMarket.values()) {\n if (eventId == null) continue;\n const current = nextByEvent.get(eventId);\n if (current == null || arb > current) {\n nextByEvent.set(eventId, arb);\n }\n }\n\n return { byMarket: nextByMarket, byEvent: nextByEvent };\n });\n });\n\n return off;\n }, [ws]);\n\n // Project the internal state shape (which stores eventId alongside arb) to\n // the public shape (byMarket: Map<marketId, number>).\n const publicByMarket = new Map<string, number>();\n for (const [marketId, { arb }] of state.byMarket) {\n publicByMarket.set(marketId, arb);\n }\n\n return { byMarket: publicByMarket, byEvent: state.byEvent };\n}\n","import type {\n Orderbook,\n VenueMarketOutcome,\n VenueMarket,\n AggClient,\n AggregatedOrderbookResponse,\n} from \"@agg-build/sdk\";\nimport { keepPreviousData, useQuery } from \"@tanstack/react-query\";\nimport { useAggClient } from \"./core/provider\";\nimport { marketOrderbookDataToResponse } from \"./market-data/orderbook-cache\";\nimport { useMarketOrderbook } from \"./use-market-orderbook\";\n\nexport interface OrderbookResult {\n market: VenueMarket;\n outcome: VenueMarketOutcome;\n orderbook: Orderbook;\n}\n\nexport interface UseOrderBookOptions {\n orderbooks: {\n market: VenueMarket;\n outcome: VenueMarketOutcome;\n }[];\n enabled?: boolean;\n canonicalMarketId?: string | null;\n}\n\n// Cached query functions must not share the render context containing canonicalResult's deep book.\nconst fetchBatchBookQuery = (\n client: AggClient,\n venueMarketIds: string[],\n { signal }: { signal: AbortSignal },\n) => client.getOrderbooks({ venueMarketIds }, { signal });\nconst createBatchBookQuery = (client: AggClient, venueMarketIds: string[]) =>\n fetchBatchBookQuery.bind(null, client, venueMarketIds);\n\nexport function useOrderBook(options: UseOrderBookOptions) {\n const client = useAggClient();\n const { orderbooks, enabled = true, canonicalMarketId } = options;\n const requestedVenueMarketIds = [...new Set(orderbooks.map(({ market }) => market.id))];\n\n const canonicalResult = useMarketOrderbook({\n marketId: canonicalMarketId ?? null,\n enabled: enabled && !!canonicalMarketId && orderbooks.length > 0,\n venueOutcomes: canonicalMarketId\n ? orderbooks.map(({ market, outcome }) => ({\n venue: market.venue,\n venueMarketOutcomeId: outcome.id,\n }))\n : undefined,\n });\n\n const batchedResult = useQuery({\n queryKey: requestedVenueMarketIds.length\n ? ([\"orderbooks\", requestedVenueMarketIds, null] as const)\n : ([\"orderbooks\", \"__disabled__\", null] as const),\n queryFn: createBatchBookQuery(client, requestedVenueMarketIds),\n enabled: enabled && !canonicalMarketId && requestedVenueMarketIds.length > 0,\n staleTime: 10_000,\n gcTime: 5 * 60_000,\n refetchOnWindowFocus: false,\n retry: 1,\n placeholderData: keepPreviousData,\n });\n\n const data: OrderbookResult[] | undefined = (() => {\n if (canonicalMarketId) {\n const canonicalData = canonicalResult.data;\n if (!canonicalData) return undefined;\n\n const merged = orderbooks.flatMap(({ market, outcome }) => {\n const venueBook = canonicalData.venueOrderbooks[market.venue];\n if (!venueBook) return [];\n\n return [\n {\n market,\n outcome,\n orderbook: {\n bids: venueBook.bids,\n asks: venueBook.asks,\n },\n },\n ];\n });\n\n return merged.length === orderbooks.length ? merged : undefined;\n }\n\n const liveBooksByMarketId = new Map(\n (batchedResult.data?.data ?? [])\n .filter((item) => item.status === \"ok\")\n .map((item) => [item.venueMarketId, item]),\n );\n\n const merged = orderbooks.flatMap(({ market, outcome }, index) => {\n void index;\n const item = liveBooksByMarketId.get(market.id);\n const orderbook = item?.venueOrderbooks[market.venue]?.orderbook as Orderbook | undefined;\n if (!orderbook) return [];\n\n return [\n {\n market,\n outcome,\n orderbook,\n },\n ];\n });\n\n return merged.length === orderbooks.length ? merged : undefined;\n })();\n\n const aggregated: AggregatedOrderbookResponse | null = canonicalResult.data\n ? marketOrderbookDataToResponse(canonicalResult.data)\n : null;\n const error = canonicalMarketId ? canonicalResult.error : batchedResult.error;\n\n return {\n data,\n isLoading: canonicalMarketId ? canonicalResult.isLoading : batchedResult.isLoading,\n error: error instanceof Error ? error : error ? new Error(String(error)) : null,\n results: [batchedResult],\n aggregated,\n isLive: canonicalResult.isLive,\n };\n}\n","import type { OrderbookQuoteResponse } from \"@agg-build/sdk\";\nimport { keepPreviousData, useQuery } from \"@tanstack/react-query\";\nimport { useAggClient } from \"./core/provider\";\nimport { createMarketOrderbookDataFromVenueOrderbooks } from \"./market-data/orderbook-cache\";\nimport { marketDataKeys } from \"./market-data/query-keys\";\nimport { useDebouncedValue } from \"./use-debounced-value\";\n\nexport interface UseOrderbookQuoteOptions {\n marketId: string | null;\n side: \"buy\" | \"sell\";\n size: number;\n enabled?: boolean;\n}\n\nexport interface UseOrderbookQuoteResult {\n data: OrderbookQuoteResponse | null;\n isLoading: boolean;\n isFetching: boolean;\n error: Error | null;\n}\n\nconst QUOTE_DEBOUNCE_MS = 300;\n\nconst createUnavailableOrderbookError = (message: string, code?: string, retryable?: boolean) => {\n const error = new Error(message) as Error & {\n status: number;\n code?: string;\n retryable?: boolean;\n };\n error.status = 404;\n if (code) error.code = code;\n if (retryable !== undefined) error.retryable = retryable;\n return error;\n};\n\nconst quoteVenueOrderbooks = ({\n marketId,\n side,\n requestedSize,\n venueOrderbooks,\n}: {\n marketId: string;\n side: \"buy\" | \"sell\";\n requestedSize: number;\n venueOrderbooks: Record<\n string,\n { bids: Array<{ price: number; size: number }>; asks: Array<{ price: number; size: number }> }\n >;\n}): OrderbookQuoteResponse => {\n const marketData = createMarketOrderbookDataFromVenueOrderbooks({\n marketId,\n venueOrderbooks,\n });\n const levels = side === \"buy\" ? marketData.orderbook.asks : marketData.orderbook.bids;\n\n let remaining = requestedSize;\n const fillsByVenue = new Map<string, { size: number; cost: number }>();\n\n for (const level of levels) {\n if (remaining <= 0) break;\n\n for (const [venue, venueSize] of Object.entries(level.venues)) {\n if (remaining <= 0) break;\n\n const fillSize = Math.min(remaining, venueSize);\n const fillCost = fillSize * level.price;\n remaining -= fillSize;\n\n const existing = fillsByVenue.get(venue) ?? { size: 0, cost: 0 };\n existing.size += fillSize;\n existing.cost += fillCost;\n fillsByVenue.set(venue, existing);\n }\n }\n\n const filledSize = requestedSize - Math.max(0, remaining);\n const totalCost = [...fillsByVenue.values()].reduce((sum, fill) => sum + fill.cost, 0);\n const avgPrice = filledSize > 0 ? totalCost / filledSize : null;\n const slippage =\n avgPrice !== null && marketData.midpoint !== null\n ? side === \"buy\"\n ? avgPrice - marketData.midpoint\n : marketData.midpoint - avgPrice\n : null;\n\n return {\n marketId,\n side,\n requestedSize,\n filledSize,\n avgPrice,\n totalCost,\n slippage,\n fills: [...fillsByVenue.entries()].map(([venue, fill]) => ({\n venue,\n size: fill.size,\n avgPrice: fill.size > 0 ? fill.cost / fill.size : 0,\n cost: fill.cost,\n })),\n };\n};\n\nexport function useOrderbookQuote(options: UseOrderbookQuoteOptions): UseOrderbookQuoteResult {\n const client = useAggClient();\n const { marketId, side, size, enabled = true } = options;\n const debouncedSize = useDebouncedValue(size, QUOTE_DEBOUNCE_MS);\n const shouldFetch = enabled && !!marketId && debouncedSize > 0;\n\n const query = useQuery({\n queryKey: marketId\n ? marketDataKeys.orderbookQuote(marketId, side, debouncedSize)\n : ([\"market-data\", \"orderbook-quote\", \"__disabled__\"] as const),\n queryFn: async () => {\n const response = await client.getOrderbooks({\n venueMarketIds: [marketId!],\n });\n\n const item = response.data.find((entry) => entry.venueMarketId === marketId!);\n if (!item) {\n throw createUnavailableOrderbookError(`No orderbook payload returned for ${marketId!}.`);\n }\n\n if (item.status !== \"ok\") {\n throw createUnavailableOrderbookError(\n item.error?.message ?? `No live orderbook is available for ${marketId!}.`,\n item.error?.code,\n item.error?.retryable,\n );\n }\n\n return quoteVenueOrderbooks({\n marketId: marketId!,\n side,\n requestedSize: debouncedSize,\n venueOrderbooks: Object.fromEntries(\n Object.entries(item.venueOrderbooks).map(([venue, entry]) => [venue, entry.orderbook]),\n ),\n });\n },\n enabled: shouldFetch && debouncedSize > 0,\n staleTime: 10_000,\n gcTime: 5 * 60_000,\n retry: 1,\n placeholderData: keepPreviousData,\n });\n\n return {\n data: query.data ?? null,\n isLoading: query.isLoading,\n isFetching: query.isFetching,\n error:\n query.error instanceof Error\n ? query.error\n : query.error\n ? new Error(String(query.error))\n : null,\n };\n}\n","import { useQuery } from \"@tanstack/react-query\";\nimport type { OrderListQuery, TradeExecutorOrder } from \"@agg-build/sdk\";\nimport { useAggClient } from \"./core/provider\";\n\nexport interface UseOrdersOptions extends OrderListQuery {\n enabled?: boolean;\n}\n\nexport function useOrders(options: UseOrdersOptions = {}) {\n const client = useAggClient();\n const { userId, status, limit = 50, offset = 0, enabled = true } = options;\n\n const query = useQuery({\n queryKey: [\"orders\", userId ?? \"me\", status ?? \"all\", limit, offset],\n queryFn: () =>\n client.getOrders({\n userId,\n status,\n limit,\n offset,\n }),\n enabled,\n });\n\n return {\n ...query,\n orders: (query.data?.orders ?? []) as TradeExecutorOrder[],\n total: query.data?.total ?? 0,\n };\n}\n","import type { MarketStatus, VenueEvent } from \"@agg-build/sdk\";\nimport {\n QueryClient,\n QueryClientContext,\n keepPreviousData,\n useInfiniteQuery,\n} from \"@tanstack/react-query\";\nimport { useContext, useEffect, useState } from \"react\";\nimport { withReadRetry } from \"./read-retry\";\nimport { AggClientContext } from \"./core/providers/contexts\";\n\nexport interface UseSearchOptions {\n /** Search query string. The query is disabled when empty. */\n q: string;\n /** Search type: \"events\" or \"markets\". */\n type: \"events\" | \"markets\";\n /** Optional category ID filter. */\n categoryIds?: string[];\n /** Filter by status — pass [\"open\"] for tradeable-only results. */\n status?: MarketStatus[];\n /** Page size. Default 20. */\n limit?: number;\n /** If provided, enable/disable the query. Defaults to true. */\n enabled?: boolean;\n /**\n * Opt in to the server-side reranker for higher-quality top results.\n *\n * Recommended for the full search-results page (submit / Enter) and NOT\n * for debounced typeahead — the latter shouldn't pay reranker latency on\n * every keystroke. The flag is baked into the query cache key, so deep\n * and light variants of the same query never share results. Default false.\n */\n deep?: boolean;\n /** Indexed title/question suggestions; full remains the compatibility default. */\n mode?: \"instant\" | \"full\";\n}\n\n/**\n * Search events or markets via the /search endpoint with cursor-based pagination.\n * Uses `useInfiniteQuery` for \"Load more\" support. Disabled when `q` is empty.\n *\n * Pass a type parameter to narrow the result type, e.g.:\n * ```ts\n * const { data } = useSearch<VenueEventWithMarkets>({ q: \"...\", type: \"events\" });\n * ```\n *\n * For typeahead + full-results in one hook, prefer `useMarketSearch` — it\n * wires up the debounce, submit, and cancellation semantics out of the box.\n */\nexport function useSearch<T = VenueEvent>(options: UseSearchOptions) {\n const client = useContext(AggClientContext);\n const queryClient = useContext(QueryClientContext);\n const [fallbackQueryClient] = useState(() => new QueryClient());\n const {\n q,\n type,\n categoryIds,\n status,\n limit = 20,\n enabled = true,\n deep = false,\n mode = \"full\",\n } = options;\n const isEnabled = enabled && q.length > 0;\n\n useEffect(() => {\n if (queryClient) return undefined;\n\n fallbackQueryClient.mount();\n return () => {\n fallbackQueryClient.unmount();\n };\n }, [fallbackQueryClient, queryClient]);\n\n if (isEnabled && !client) {\n throw new Error(\"useSearch must be used within an <AggProvider>\");\n }\n\n const queryKey = [\n \"search\",\n q,\n type,\n categoryIds?.join(\",\") ?? \"\",\n status?.join(\",\") ?? \"\",\n limit,\n deep,\n mode,\n ];\n const effectiveQueryClient = queryClient ?? fallbackQueryClient;\n const retryOptions = withReadRetry(effectiveQueryClient.defaultQueryOptions({ queryKey }));\n\n const query = useInfiniteQuery(\n {\n // deep is part of the key — TanStack treats deep vs light as\n // independent queries so users can have both modes cached side-by-side.\n queryKey,\n queryFn: async ({ pageParam, signal }) => {\n if (!client) {\n throw new Error(\"useSearch must be used within an <AggProvider>\");\n }\n\n const res = await client.search<T>(\n {\n q,\n type,\n categoryIds,\n status,\n limit,\n cursor: pageParam as string | undefined,\n deep,\n mode,\n },\n { signal },\n );\n return res;\n },\n initialPageParam: undefined as string | undefined,\n getNextPageParam: (lastPage) => {\n if (!lastPage.hasMore) return undefined;\n return lastPage.nextCursor ?? undefined;\n },\n placeholderData: keepPreviousData,\n ...retryOptions,\n enabled: isEnabled && !!client,\n },\n effectiveQueryClient,\n );\n\n const data: T[] = query.data?.pages.flatMap((page) => page.data) ?? [];\n\n return {\n data,\n isLoading: query.isLoading,\n isError: query.isError,\n error: query.error,\n hasNextPage: !!query.hasNextPage,\n fetchNextPage: query.fetchNextPage,\n isFetchingNextPage: query.isFetchingNextPage,\n isPlaceholderData: query.isPlaceholderData,\n };\n}\n","import type { MarketStatus, VenueEvent } from \"@agg-build/sdk\";\nimport { useCallback, useState } from \"react\";\nimport { useDebouncedValue } from \"./use-debounced-value\";\nimport { useSearch } from \"./use-search\";\n\nexport interface UseMarketSearchOptions {\n /** Search type: \"events\" or \"markets\". */\n type: \"events\" | \"markets\";\n /** Optional category ID filter. */\n categoryIds?: string[];\n /** Filter by status — pass [\"open\"] for tradeable-only results. */\n status?: MarketStatus[];\n /** Page size for both modes. Default 20. */\n limit?: number;\n /**\n * Debounce delay applied to the typeahead/light query, in ms. The submit\n * path bypasses debounce entirely. Default 200.\n */\n debounceMs?: number;\n /**\n * Set to `false` to disable the typeahead/light query (no /search call\n * while the user types). The submit path still fires full searches.\n * Default true.\n */\n enableSuggestions?: boolean;\n /**\n * Minimum query length before the typeahead fires. Default 1 — set higher\n * (e.g. 3) if `/search` cost per keystroke is a concern. The submit path\n * ignores this threshold.\n */\n minLength?: number;\n}\n\n/**\n * Combined typeahead + submit hook for the canonical search UX.\n *\n * ┌─────────────────────────────┐\n * │ user types \"tru\" │ → debounced light /search → suggestions[]\n * │ user types \"trum\" │ → debounced light /search → suggestions[]\n * │ user presses Enter │ → deep /search → results[]\n * └─────────────────────────────┘\n *\n * Typeahead (`suggestions`) and submit-results (`results`) are cached under\n * separate TanStack Query keys, so navigating away and back doesn't lose\n * either. Server-side the same separation holds: the `deep` flag is part of\n * the cache key, so the two modes never collide.\n *\n * ```tsx\n * const { query, setQuery, submit, suggestions, results } = useMarketSearch({\n * type: \"markets\",\n * });\n *\n * <input\n * value={query}\n * onChange={(e) => setQuery(e.target.value)}\n * onKeyDown={(e) => { if (e.key === \"Enter\") submit(); }}\n * />\n * {suggestions.data.map(...)} // dropdown\n * {results.data.map(...)} // full page after Enter\n * ```\n */\nexport function useMarketSearch<T = VenueEvent>(options: UseMarketSearchOptions) {\n const {\n type,\n categoryIds,\n status,\n limit = 20,\n debounceMs = 200,\n enableSuggestions = true,\n minLength = 1,\n } = options;\n\n // Input value the user is currently typing. The component owns the\n // controlled <input> via setQuery; the hook owns the debounced + submitted\n // derivations.\n const [query, setQueryState] = useState(\"\");\n // Snapshot of the query at the moment `submit()` was called. Driving the\n // full search off a separate state value means typing more after submitting\n // doesn't blow away the results until the next submit.\n const [submittedQuery, setSubmittedQuery] = useState<string | null>(null);\n\n const debouncedQuery = useDebouncedValue(query, debounceMs);\n const trimmedDebounced = debouncedQuery.trim();\n const suggestionsEnabled = enableSuggestions && trimmedDebounced.length >= minLength;\n\n // Light: typeahead. Fires after debounceMs of input stability.\n const suggestionsQuery = useSearch<T>({\n q: trimmedDebounced,\n type,\n categoryIds,\n status,\n limit,\n enabled: suggestionsEnabled,\n mode: \"instant\",\n });\n\n // Full results. Fires on submit and stays mounted across subsequent\n // typing — the user can scroll the page-1 results while they refine the query.\n const submittedQ = submittedQuery?.trim() ?? \"\";\n const resultsQuery = useSearch<T>({\n q: submittedQ,\n type,\n categoryIds,\n status,\n limit,\n enabled: submittedQ.length > 0,\n });\n\n const setQuery = useCallback((value: string) => {\n setQueryState(value);\n }, []);\n\n /** Submit a query for a full-page search. Falls back to the current\n * input value if no argument is passed — matches the \"user presses Enter\n * in the input\" UX. Trims whitespace; empty strings are no-ops. */\n const submit = useCallback(\n (q?: string) => {\n const target = (q ?? query).trim();\n if (target.length === 0) return;\n setSubmittedQuery(target);\n },\n [query],\n );\n\n /** Reset both the input value and the submitted-search state. */\n const clear = useCallback(() => {\n setQueryState(\"\");\n setSubmittedQuery(null);\n }, []);\n\n return {\n /** Current input value (controlled). */\n query,\n /** Update the input value. Triggers the debounced typeahead. */\n setQuery,\n /** The query value that produced the current `results`, or null if none. */\n submittedQuery,\n /** Fire a full-page search. Use this on Enter / Search button. */\n submit,\n /** Reset both input and results state. */\n clear,\n /**\n * Typeahead state. Backed by a light /search call (no reranker).\n * `data` is paginated like `useSearch.data` (flattened across pages).\n */\n suggestions: {\n data: suggestionsQuery.data,\n isLoading: suggestionsQuery.isLoading,\n isError: suggestionsQuery.isError,\n error: suggestionsQuery.error,\n },\n /**\n * Full-page results state. Backed by a deep /search call (reranker on).\n * Cursor pagination is exposed via `fetchNextPage` / `hasNextPage`.\n */\n results: {\n data: resultsQuery.data,\n isLoading: resultsQuery.isLoading,\n isError: resultsQuery.isError,\n error: resultsQuery.error,\n hasNextPage: resultsQuery.hasNextPage,\n fetchNextPage: resultsQuery.fetchNextPage,\n isFetchingNextPage: resultsQuery.isFetchingNextPage,\n },\n };\n}\n","import type { SmartRouteResponse } from \"@agg-build/sdk\";\n\nexport const THIN_SMART_ROUTE_REFETCH_INTERVAL_MS = 5_000;\nexport const SMART_ROUTE_REFRESH_DEADLINE_BUFFER_MS = 4_000;\nexport const SMART_ROUTE_MIN_REFETCH_INTERVAL_MS = 5_000;\nexport const SMART_ROUTE_MAX_REFETCH_INTERVAL_MS = 20_000;\nexport const SMART_ROUTE_HIGH_SLIPPAGE_BPS = 75;\nexport const SMART_ROUTE_SHALLOW_TOP_LEVEL_RATIO = 0.7;\nexport const SMART_ROUTE_DEEP_FILL_LEVEL_COUNT = 3;\n\nconst LIQUIDITY_CONSTRAINED_STATUSES = new Set<SmartRouteResponse[\"status\"]>([\n \"infeasible\",\n \"no_orderbooks\",\n \"insufficient_depth\",\n \"no_bids_above_min_price\",\n]);\n\nconst THIN_LIQUIDITY_WARNING_PATTERN =\n /partial(?:[_\\s-]?fill)?|insufficient(?:[_\\s-]?liquidity|[_\\s-]?depth)|shallow|price moved|no active quote path|couldn'?t fill|unable to fill|quote stale|stale/i;\n\nexport type ThinSmartRouteLiquidityReason =\n | \"deep_fill_levels\"\n | \"high_slippage\"\n | \"liquidity_status\"\n | \"refresh_due_soon\"\n | \"shallow_top_level\"\n | \"warning_signal\";\n\nexport interface SmartRouteThinLiquidityAssessment {\n isThin: boolean;\n reasons: ThinSmartRouteLiquidityReason[];\n}\n\nexport interface ResolveSmartRouteRefetchIntervalArgs {\n data: SmartRouteResponse | null | undefined;\n defaultIntervalMs: number;\n aggressiveIntervalMs?: number;\n /** Keep sell fan-out on its normal cadence while honoring venue cooldowns. */\n adaptive?: boolean;\n isDocumentVisible: boolean;\n isEditing?: boolean;\n isInputValid: boolean;\n isMarketOpen: boolean;\n isPanelActive: boolean;\n isSubmitting: boolean;\n queryEnabled: boolean;\n}\n\nconst resolveMsUntilIsoTimestamp = (value: string | undefined, nowMs: number): number | null => {\n if (!value) return null;\n const parsedValue = Date.parse(value);\n if (!Number.isFinite(parsedValue)) return null;\n return parsedValue - nowMs;\n};\n\nconst clampIntervalToRefreshDeadline = ({\n intervalMs,\n refreshAt,\n nowMs,\n}: {\n intervalMs: number;\n refreshAt: string | undefined;\n nowMs: number;\n}): number => {\n const msUntilRefresh = resolveMsUntilIsoTimestamp(refreshAt, nowMs);\n if (msUntilRefresh == null || msUntilRefresh <= 0) {\n return Math.min(\n SMART_ROUTE_MAX_REFETCH_INTERVAL_MS,\n Math.max(SMART_ROUTE_MIN_REFETCH_INTERVAL_MS, intervalMs),\n );\n }\n\n return Math.max(\n SMART_ROUTE_MIN_REFETCH_INTERVAL_MS,\n Math.min(SMART_ROUTE_MAX_REFETCH_INTERVAL_MS, intervalMs, Math.floor(msUntilRefresh)),\n );\n};\n\nexport const assessThinSmartRouteLiquidity = (\n quote: SmartRouteResponse | null | undefined,\n nowMs = Date.now(),\n): SmartRouteThinLiquidityAssessment => {\n if (!quote) {\n return {\n isThin: false,\n reasons: [],\n };\n }\n\n const reasons = new Set<ThinSmartRouteLiquidityReason>();\n\n if (LIQUIDITY_CONSTRAINED_STATUSES.has(quote.status)) {\n reasons.add(\"liquidity_status\");\n }\n\n if (\n typeof quote.slippage?.slippageBps === \"number\" &&\n Number.isFinite(quote.slippage.slippageBps) &&\n quote.slippage.slippageBps >= SMART_ROUTE_HIGH_SLIPPAGE_BPS\n ) {\n reasons.add(\"high_slippage\");\n }\n\n const msUntilRefresh = resolveMsUntilIsoTimestamp(quote.refreshAt, nowMs);\n if (msUntilRefresh != null && msUntilRefresh <= SMART_ROUTE_REFRESH_DEADLINE_BUFFER_MS) {\n reasons.add(\"refresh_due_soon\");\n }\n\n const hasShallowTopLevel = quote.fills.some((fill) => {\n if (fill.fills.length <= 1 || fill.venueQty <= 0) return false;\n\n const topLevelSize = fill.fills[0]?.size ?? 0;\n if (!Number.isFinite(topLevelSize) || topLevelSize <= 0) return false;\n\n return topLevelSize / fill.venueQty < SMART_ROUTE_SHALLOW_TOP_LEVEL_RATIO;\n });\n if (hasShallowTopLevel) {\n reasons.add(\"shallow_top_level\");\n }\n\n const hasDeepFillLevels = quote.fills.some(\n (fill) => fill.fills.length >= SMART_ROUTE_DEEP_FILL_LEVEL_COUNT,\n );\n if (hasDeepFillLevels) {\n reasons.add(\"deep_fill_levels\");\n }\n\n const hasThinWarning = (quote.warnings ?? []).some((warning) =>\n THIN_LIQUIDITY_WARNING_PATTERN.test(warning.reason),\n );\n if (hasThinWarning) {\n reasons.add(\"warning_signal\");\n }\n\n return {\n isThin: reasons.size > 0,\n reasons: [...reasons],\n };\n};\n\nexport const resolveSmartRouteRefetchInterval = (\n args: ResolveSmartRouteRefetchIntervalArgs,\n nowMs = Date.now(),\n): number | false => {\n const {\n aggressiveIntervalMs = THIN_SMART_ROUTE_REFETCH_INTERVAL_MS,\n adaptive = true,\n data,\n defaultIntervalMs,\n isDocumentVisible,\n isEditing = false,\n isInputValid,\n isMarketOpen,\n isPanelActive,\n isSubmitting,\n queryEnabled,\n } = args;\n\n if (defaultIntervalMs <= 0) return false;\n\n const isActivelyViewingQuote = isPanelActive || isEditing;\n if (\n !queryEnabled ||\n !isInputValid ||\n !isActivelyViewingQuote ||\n !isMarketOpen ||\n isSubmitting ||\n !isDocumentVisible\n ) {\n return false;\n }\n\n const primaryUsesProphetx =\n data?.fills?.some((fill) => fill.venue === \"prophetx\") || data?.status !== \"ok\";\n const deadlines = [\n data?.quoteRefreshNotBefore,\n ...(primaryUsesProphetx ? [data?.quoteFailure?.retryAt] : []),\n ]\n .filter((value): value is string => !!value)\n .map(Date.parse)\n .filter((value) => Number.isFinite(value) && value > nowMs);\n if (deadlines.length) return Math.max(...deadlines) - nowMs;\n\n if (!adaptive)\n return clampIntervalToRefreshDeadline({\n intervalMs: defaultIntervalMs,\n refreshAt: undefined,\n nowMs,\n });\n\n const defaultInterval = clampIntervalToRefreshDeadline({\n intervalMs: defaultIntervalMs,\n refreshAt: data?.refreshAt,\n nowMs,\n });\n if (!data) return defaultInterval;\n\n const thinLiquidity = assessThinSmartRouteLiquidity(data, nowMs);\n if (!thinLiquidity.isThin) return defaultInterval;\n\n return clampIntervalToRefreshDeadline({\n intervalMs: aggressiveIntervalMs,\n refreshAt: data.refreshAt,\n nowMs,\n });\n};\n","import type { ExecutionMode, SmartRouteResponse, SmartRouteSide } from \"@agg-build/sdk\";\nimport { keepPreviousData, useQuery } from \"@tanstack/react-query\";\nimport { useAggClient } from \"./core/provider\";\nimport { resolveSmartRouteRefetchInterval } from \"./smart-route-refresh-policy\";\n\n/**\n * Smart-route quotes expire on the server after 45s. Refetch at 20s so a fresh\n * quote is always in hand by the time the user clicks the CTA.\n */\nexport const SMART_ROUTE_STALE_TIME_MS = 20_000;\n\nexport interface UseSmartRouteOptions {\n /** Venue market outcome ID used by the smart-route endpoint. */\n venueMarketOutcomeId?: string | null;\n /** @deprecated Use venueMarketOutcomeId. */\n venueMarketId?: string | null;\n /** @deprecated Use venueMarketOutcomeId. */\n outcomeId?: string | null;\n /** @deprecated Side is ignored for routing and echoed back only for legacy consumers. */\n side?: SmartRouteSide | null;\n /** Trade direction: \"buy\" (default) or \"sell\". */\n tradeSide?: \"buy\" | \"sell\" | null;\n /** Trading mode. Defaults to live. */\n mode?: ExecutionMode | null;\n /** Maximum USDC spend for the quote. Required for buy; optional for sell when sellShares is given. */\n maxSpend?: number;\n /** Sell only: target number of contracts to sell. */\n sellShares?: number;\n /** Per-chain USD balances. JSON-serialized in query. */\n chainBalances?: Record<string, number>;\n /** Maximum slippage in basis points. */\n slipCapBps?: number;\n /** Include venue-by-venue comparison quotes. */\n compareVenues?: boolean;\n /**\n * Sell-only cache scope. Position freshness and account identity affect the\n * server-side sellable inventory even when the requested amount is unchanged.\n */\n sellCacheScope?: {\n accountId?: string | null;\n positionVersion?: number | null;\n };\n /** Account balance freshness affects whether a server quote is executable. */\n balanceCacheScope?: {\n accountId?: string | null;\n balanceVersion?: number | null;\n /** Semantic funds/holds identity. When provided, unchanged polling timestamps\n * must not cancel an in-flight quote; this takes precedence over balanceVersion. */\n balanceKey?: string;\n };\n /**\n * Opt in to the deep cost-estimate surface — response `feeBreakdown`\n * gains `setupCosts` (chain approvals + Kalshi ATAs) with `alreadyPaid`\n * flags from prior trade history, and `setupCostsTotal` is folded into\n * `totalCostIncFees` (with `estimatedProfit` / `returnPct` recomputed).\n * Buy-only.\n */\n deepEstimate?: boolean;\n /** Enable/disable the query. Default true. */\n enabled?: boolean;\n /** Cache freshness and polling interval in milliseconds. Defaults to SMART_ROUTE_STALE_TIME_MS. */\n staleTimeMs?: number;\n /**\n * UI activity hints used by the centralized refresh policy. These do not\n * affect the fetched payload, only whether quote polling should stay active\n * and whether thin-liquidity quotes should refresh more aggressively.\n */\n refreshContext?: {\n /** True when the quote panel is the visible/active surface. Defaults to true. */\n isPanelActive?: boolean;\n /** True while the user is actively editing the quote inputs. Defaults to false. */\n isEditing?: boolean;\n /** True when the market is open for trading. Defaults to true. */\n isMarketOpen?: boolean;\n /** True while the trade is being submitted or executed. Defaults to false. */\n isSubmitting?: boolean;\n };\n}\n\n/**\n * Why the smart route query is currently loading.\n * - `\"finding-best-odds\"` — first fetch, no prior data in cache\n * - `\"updating-route\"` — query key changed (e.g. amount changed), placeholder data shown\n * - `\"refreshing-quotes\"` — background poll/revalidation with existing data\n */\nexport type SmartRouteLoadingReason = \"finding-best-odds\" | \"updating-route\" | \"refreshing-quotes\";\n\nexport interface UseSmartRouteResult {\n data: SmartRouteResponse | null;\n isLoading: boolean;\n isFetching: boolean;\n error: Error | null;\n refetch: () => Promise<unknown>;\n /** Null when not loading. See {@link SmartRouteLoadingReason}. */\n loadingReason: SmartRouteLoadingReason | null;\n}\n\nconst getIsDocumentVisible = (): boolean => {\n if (typeof document === \"undefined\") return true;\n return document.visibilityState !== \"hidden\";\n};\n\n/**\n * Compute optimal order routing across venues via the MILP solver.\n * Returns a user-scoped quote with per-venue fills and verification timing.\n *\n * The query re-fetches when venueMarketOutcomeId, maxSpend, or chainBalances change.\n * Uses keepPreviousData to avoid flicker during re-computation.\n */\nexport function useSmartRoute(options: UseSmartRouteOptions): UseSmartRouteResult {\n const client = useAggClient();\n const {\n venueMarketOutcomeId,\n venueMarketId,\n outcomeId,\n side,\n tradeSide,\n mode,\n maxSpend,\n sellShares,\n chainBalances,\n slipCapBps,\n compareVenues,\n sellCacheScope,\n balanceCacheScope,\n deepEstimate,\n enabled = true,\n staleTimeMs = SMART_ROUTE_STALE_TIME_MS,\n refreshContext,\n } = options;\n const resolvedVenueMarketOutcomeId = venueMarketOutcomeId ?? venueMarketId ?? outcomeId;\n const hasValidInput = (maxSpend ?? 0) > 0 || (sellShares ?? 0) > 0;\n const queryEnabled = enabled && !!resolvedVenueMarketOutcomeId && hasValidInput;\n\n const query = useQuery({\n queryKey: [\n \"smart-route\",\n resolvedVenueMarketOutcomeId,\n side ?? null,\n tradeSide ?? null,\n ...(mode ? [mode] : []),\n maxSpend ?? null,\n sellShares ?? null,\n chainBalances ? JSON.stringify(chainBalances) : null,\n slipCapBps ?? null,\n compareVenues ?? false,\n deepEstimate ?? false,\n ...(balanceCacheScope\n ? [\n balanceCacheScope.accountId ?? null,\n balanceCacheScope.balanceKey ?? balanceCacheScope.balanceVersion ?? null,\n ]\n : []),\n ...(tradeSide === \"sell\"\n ? [sellCacheScope?.accountId ?? null, sellCacheScope?.positionVersion ?? null]\n : []),\n ] as const,\n queryFn: async ({ signal }) => {\n return client.getSmartRoute(\n {\n venueMarketOutcomeId: resolvedVenueMarketOutcomeId!,\n side: side ?? undefined,\n tradeSide: tradeSide ?? undefined,\n ...(mode ? { mode } : {}),\n maxSpend,\n sellShares,\n chainBalances,\n slipCapBps,\n compareVenues,\n deepEstimate,\n },\n { signal },\n );\n },\n enabled: queryEnabled,\n staleTime: staleTimeMs,\n refetchInterval: (queryState) =>\n resolveSmartRouteRefetchInterval({\n // SELL already fans out into one quote per venue. Keep that group on a\n // stable cadence instead of multiplying the adaptive 5s/refreshAt poll.\n data: queryState.state.data as SmartRouteResponse | null | undefined,\n adaptive: tradeSide !== \"sell\",\n defaultIntervalMs: staleTimeMs,\n isDocumentVisible: getIsDocumentVisible(),\n isEditing: refreshContext?.isEditing ?? false,\n isInputValid: hasValidInput,\n isMarketOpen: refreshContext?.isMarketOpen ?? true,\n isPanelActive: refreshContext?.isPanelActive ?? true,\n isSubmitting: refreshContext?.isSubmitting ?? false,\n queryEnabled,\n }),\n gcTime: 60_000,\n refetchOnWindowFocus: false,\n refetchIntervalInBackground: false,\n retry: 1,\n // A previous SELL quote can carry a quoteId and position availability for\n // a different amount or position snapshot. Never expose it under a new\n // sell key while the replacement request is in flight. BUY retains the\n // existing no-flicker behavior.\n placeholderData: tradeSide === \"sell\" ? undefined : keepPreviousData,\n });\n\n const error = query.error;\n\n let loadingReason: SmartRouteLoadingReason | null = null;\n if (query.isFetching) {\n if (query.isPlaceholderData) {\n // Query key changed (e.g. amount) and keepPreviousData is showing the\n // previous key's quote. In v5 this reports isLoading=false, so it must be\n // checked explicitly or it would be mistaken for a background poll.\n loadingReason = \"updating-route\";\n } else if (query.isLoading) {\n // isLoading = isPending && isFetching: very first fetch, no prior data.\n loadingReason = query.data != null ? \"updating-route\" : \"finding-best-odds\";\n } else {\n // Same key re-fetching in the background (poll / revalidation).\n loadingReason = \"refreshing-quotes\";\n }\n }\n\n return {\n data: query.data ?? null,\n isLoading: query.isLoading,\n isFetching: query.isFetching,\n error: error instanceof Error ? error : error ? new Error(String(error)) : null,\n refetch: query.refetch,\n loadingReason,\n };\n}\n","import type {\n BatchOrderbooksResponse,\n ExecutionMode,\n SmartRouteResponse,\n Venue,\n} from \"@agg-build/sdk\";\nimport { keepPreviousData, useQueries, useQuery } from \"@tanstack/react-query\";\nimport { useAggClient } from \"./core/provider\";\nimport { resolveSmartRouteRefetchInterval } from \"./smart-route-refresh-policy\";\nimport { SMART_ROUTE_STALE_TIME_MS, type UseSmartRouteOptions } from \"./use-smart-route\";\n\nexport interface LimitOrderVenueQuoteRequest {\n venue: Venue;\n venueMarketOutcomeId: string;\n /** The venue's own market; its tick and size rules are fetched with the selected market's. */\n venueMarketId?: string;\n}\n\nexport interface UseLimitOrderVenueQuotesOptions {\n requests: LimitOrderVenueQuoteRequest[];\n tradeSide: \"buy\" | \"sell\";\n amount?: number;\n marketId?: string | null;\n accountId?: string | null;\n chainBalances?: Record<string, number>;\n mode?: ExecutionMode | null;\n slipCapBps?: number;\n enabled?: boolean;\n staleTimeMs?: number;\n refreshContext?: UseSmartRouteOptions[\"refreshContext\"];\n}\n\nexport interface LimitOrderVenueQuoteResult {\n request: LimitOrderVenueQuoteRequest;\n data: SmartRouteResponse | null;\n tickSize?: number | null;\n /** Limit size step, raw 6-dec shares, from orderbook metadata. Null = 1-raw step. */\n sizeStepRaw?: string | null;\n /** Limit size minimum, raw 6-dec shares, from orderbook metadata. Null = none known. */\n minSizeRaw?: string | null;\n isLoading: boolean;\n isFetching: boolean;\n error: Error | null;\n refetch: () => Promise<unknown>;\n}\n\nexport interface UseLimitOrderVenueQuotesResult {\n quotes: LimitOrderVenueQuoteResult[];\n /** The market's orderbook metadata (ticks, size rules) has not loaded yet. */\n isMetadataPending: boolean;\n isLoading: boolean;\n isFetching: boolean;\n error: Error | null;\n refetch: () => Promise<unknown>;\n}\n\nconst getIsDocumentVisible = (): boolean => {\n if (typeof document === \"undefined\") return true;\n return document.visibilityState !== \"hidden\";\n};\n\n// The batch orderbooks endpoint accepts at most 20 venueMarketIds.\nconst MAX_ORDERBOOK_METADATA_MARKET_IDS = 20;\n\nconst getUniqueVenueRequests = (\n requests: LimitOrderVenueQuoteRequest[],\n): LimitOrderVenueQuoteRequest[] => {\n const requestsByVenue = new Map<Venue, LimitOrderVenueQuoteRequest>();\n for (const request of requests) {\n if (!request.venueMarketOutcomeId || requestsByVenue.has(request.venue)) continue;\n requestsByVenue.set(request.venue, request);\n }\n return [...requestsByVenue.values()].sort((left, right) => left.venue.localeCompare(right.venue));\n};\n\nexport const resolveLimitOrderTickSizesByVenue = (\n response: BatchOrderbooksResponse | null | undefined,\n): Map<Venue, number> => {\n const tickSizes = new Map<Venue, number>();\n const setTickSize = (venue: string, tickSize: number | null | undefined): void => {\n if (tickSizes.has(venue as Venue)) return;\n if (typeof tickSize !== \"number\" || !Number.isFinite(tickSize) || tickSize <= 0) return;\n tickSizes.set(venue as Venue, tickSize);\n };\n\n for (const item of response?.data ?? []) {\n for (const [venue, entry] of Object.entries(item.venueOrderbooks)) {\n setTickSize(venue, entry.tick ?? entry.tickSize);\n }\n for (const market of item.matchedMarkets) {\n setTickSize(market.venue, market.tickSize);\n }\n if (item.requestedMarket) {\n setTickSize(item.requestedMarket.venue, item.requestedMarket.tickSize);\n }\n }\n\n return tickSizes;\n};\n\nexport interface LimitOrderSizeRules {\n sizeStepRaw?: string;\n minSizeRaw?: string;\n}\n\n/** Per-venue limit size rules from the same batch orderbook metadata as ticks. */\nexport const resolveLimitOrderSizeRulesByVenue = (\n response: BatchOrderbooksResponse | null | undefined,\n): Map<Venue, LimitOrderSizeRules> => {\n const rulesByVenue = new Map<Venue, LimitOrderSizeRules>();\n const setRules = (venue: string, entry: LimitOrderSizeRules): void => {\n if (rulesByVenue.has(venue as Venue)) return;\n if (!entry.sizeStepRaw && !entry.minSizeRaw) return;\n rulesByVenue.set(venue as Venue, {\n ...(entry.sizeStepRaw ? { sizeStepRaw: entry.sizeStepRaw } : {}),\n ...(entry.minSizeRaw ? { minSizeRaw: entry.minSizeRaw } : {}),\n });\n };\n\n for (const item of response?.data ?? []) {\n for (const [venue, entry] of Object.entries(item.venueOrderbooks)) setRules(venue, entry);\n for (const market of item.matchedMarkets) setRules(market.venue, market);\n if (item.requestedMarket) setRules(item.requestedMarket.venue, item.requestedMarket);\n }\n\n return rulesByVenue;\n};\n\n/**\n * Fetches informational single-venue quotes for limit-order routing cards.\n * Quote IDs are intentionally not consumed by the limit-order execution flow.\n */\nexport const useLimitOrderVenueQuotes = (\n options: UseLimitOrderVenueQuotesOptions,\n): UseLimitOrderVenueQuotesResult => {\n const client = useAggClient();\n const {\n requests,\n tradeSide,\n amount,\n marketId,\n accountId,\n chainBalances,\n mode,\n slipCapBps,\n enabled = true,\n staleTimeMs = SMART_ROUTE_STALE_TIME_MS,\n refreshContext,\n } = options;\n const uniqueRequests = getUniqueVenueRequests(requests);\n const hasValidInput = typeof amount === \"number\" && Number.isFinite(amount) && amount > 0;\n const hasRequiredAccount = tradeSide === \"buy\" || Boolean(accountId);\n const queryEnabled = enabled && hasValidInput && hasRequiredAccount;\n const serializedChainBalances = chainBalances ? JSON.stringify(chainBalances) : null;\n\n // The selected market's orderbook does not always list every matched venue,\n // so each venue's own market is batched into the same single request.\n const metadataMarketIds = marketId\n ? [\n ...new Set([\n marketId,\n ...uniqueRequests.flatMap((request) =>\n request.venueMarketId ? [request.venueMarketId] : [],\n ),\n ]),\n ].slice(0, MAX_ORDERBOOK_METADATA_MARKET_IDS)\n : [];\n const tickMetadataQuery = useQuery({\n queryKey: [\n \"orderbooks\",\n marketId ?? \"__disabled__\",\n \"limit-order-ticks\",\n metadataMarketIds,\n ] as const,\n queryFn: ({ signal }: { signal: AbortSignal }) =>\n client.getOrderbooks({ venueMarketIds: metadataMarketIds }, { signal }),\n enabled: enabled && Boolean(marketId),\n staleTime: 60_000,\n gcTime: 5 * 60_000,\n refetchOnWindowFocus: false,\n retry: 1,\n });\n\n const queries = useQueries({\n queries: uniqueRequests.map((request) => ({\n queryKey: [\n \"smart-route\",\n request.venueMarketOutcomeId,\n \"limit-order-venue-info\",\n {\n venue: request.venue,\n tradeSide,\n amount: amount ?? null,\n // The quote endpoint does not use limit price, so it must not be\n // part of this key or trigger a new informational quote.\n marketId: marketId ?? null,\n accountId: accountId ?? null,\n chainBalances: serializedChainBalances,\n mode: mode ?? null,\n slipCapBps: slipCapBps ?? null,\n },\n ] as const,\n queryFn: async ({ signal }: { signal: AbortSignal }) =>\n client.getSmartRoute(\n {\n venueMarketOutcomeId: request.venueMarketOutcomeId,\n tradeSide,\n ...(tradeSide === \"buy\" ? { maxSpend: amount } : { sellShares: amount }),\n ...(chainBalances ? { chainBalances } : {}),\n ...(mode ? { mode } : {}),\n slipCapBps,\n allowedVenues: [request.venue],\n },\n { signal },\n ),\n enabled: queryEnabled,\n placeholderData: keepPreviousData,\n staleTime: staleTimeMs,\n refetchInterval: (queryState: { state: { data?: SmartRouteResponse | null } }) =>\n resolveSmartRouteRefetchInterval({\n data: queryState.state.data,\n defaultIntervalMs: staleTimeMs,\n isDocumentVisible: getIsDocumentVisible(),\n isEditing: refreshContext?.isEditing ?? false,\n isInputValid: hasValidInput,\n isMarketOpen: refreshContext?.isMarketOpen ?? true,\n isPanelActive: refreshContext?.isPanelActive ?? true,\n isSubmitting: refreshContext?.isSubmitting ?? false,\n queryEnabled,\n }),\n gcTime: 60_000,\n refetchOnWindowFocus: false,\n refetchIntervalInBackground: false,\n retry: 1,\n })),\n });\n\n const tickSizesByVenue = resolveLimitOrderTickSizesByVenue(tickMetadataQuery.data);\n const sizeRulesByVenue = resolveLimitOrderSizeRulesByVenue(tickMetadataQuery.data);\n const quotes = queries.map<LimitOrderVenueQuoteResult>((query, index) => {\n const queryError = query.error;\n const request = uniqueRequests[index]!;\n return {\n request,\n data: query.data ?? null,\n tickSize: tickSizesByVenue.get(request.venue) ?? null,\n sizeStepRaw: sizeRulesByVenue.get(request.venue)?.sizeStepRaw ?? null,\n minSizeRaw: sizeRulesByVenue.get(request.venue)?.minSizeRaw ?? null,\n isLoading: query.isLoading,\n isFetching: query.isFetching,\n error:\n queryError instanceof Error\n ? queryError\n : queryError\n ? new Error(String(queryError))\n : null,\n refetch: query.refetch,\n };\n });\n\n return {\n quotes,\n // A failed metadata read is not pending: callers fall back to 1-raw sizing.\n isMetadataPending: Boolean(marketId) && tickMetadataQuery.isPending === true,\n isLoading: quotes.some((quote) => quote.isLoading),\n isFetching: quotes.some((quote) => quote.isFetching),\n error: quotes.find((quote) => quote.error)?.error ?? null,\n refetch: () =>\n Promise.all([\n ...(marketId ? [tickMetadataQuery.refetch()] : []),\n ...quotes.map((quote) => quote.refetch()),\n ]),\n };\n};\n","import type { ExecutionMode, SmartRouteResponse, Venue } from \"@agg-build/sdk\";\nimport { useQueries } from \"@tanstack/react-query\";\nimport { useAggClient } from \"./core/provider\";\nimport { resolveSmartRouteRefetchInterval } from \"./smart-route-refresh-policy\";\nimport { SMART_ROUTE_STALE_TIME_MS, type UseSmartRouteOptions } from \"./use-smart-route\";\n\nexport interface VenueSellQuoteRequest {\n venue: Venue;\n requestedSellShares: number;\n sellShares: number;\n availableShares: number;\n}\n\nexport interface UseVenueSellQuotesOptions {\n venueMarketOutcomeId?: string | null;\n accountId?: string | null;\n positionVersion?: number | null;\n requests: VenueSellQuoteRequest[];\n mode?: ExecutionMode | null;\n slipCapBps?: number;\n enabled?: boolean;\n staleTimeMs?: number;\n refreshContext?: UseSmartRouteOptions[\"refreshContext\"];\n}\n\nexport interface VenueSellQuoteResult {\n request: VenueSellQuoteRequest;\n data: SmartRouteResponse | null;\n isLoading: boolean;\n isFetching: boolean;\n error: Error | null;\n refetch: () => Promise<unknown>;\n}\n\nexport interface UseVenueSellQuotesResult {\n quotes: VenueSellQuoteResult[];\n isLoading: boolean;\n isFetching: boolean;\n error: Error | null;\n refetch: () => Promise<unknown>;\n}\n\nconst getIsDocumentVisible = (): boolean => {\n if (typeof document === \"undefined\") return true;\n return document.visibilityState !== \"hidden\";\n};\n\nconst getUniqueVenueRequests = (requests: VenueSellQuoteRequest[]): VenueSellQuoteRequest[] => {\n const requestsByVenue = new Map<Venue, VenueSellQuoteRequest>();\n for (const request of requests) {\n if (\n request.requestedSellShares <= 0 ||\n request.sellShares <= 0 ||\n request.availableShares <= 0\n ) {\n continue;\n }\n if (requestsByVenue.has(request.venue)) continue;\n requestsByVenue.set(request.venue, request);\n }\n return [...requestsByVenue.values()].sort((left, right) => left.venue.localeCompare(right.venue));\n};\n\n/**\n * Fetches one independently executable SELL quote for every eligible venue.\n * Each query owns its quoteId and is cache-scoped to the exact account,\n * position snapshot, venue, requested amount, and clamped venue amount.\n */\nexport const useVenueSellQuotes = (\n options: UseVenueSellQuotesOptions,\n): UseVenueSellQuotesResult => {\n const client = useAggClient();\n const {\n venueMarketOutcomeId,\n accountId,\n positionVersion,\n requests,\n mode,\n slipCapBps,\n enabled = true,\n staleTimeMs = SMART_ROUTE_STALE_TIME_MS,\n refreshContext,\n } = options;\n const uniqueRequests = getUniqueVenueRequests(requests);\n\n const queries = useQueries({\n queries: uniqueRequests.map((request) => {\n const hasValidInput =\n request.requestedSellShares > 0 && request.sellShares > 0 && request.availableShares > 0;\n const queryEnabled = enabled && !!venueMarketOutcomeId && !!accountId && hasValidInput;\n\n return {\n queryKey: [\n \"smart-route\",\n venueMarketOutcomeId,\n \"venue-sell\",\n {\n accountId: accountId ?? null,\n positionVersion: positionVersion ?? null,\n requestedSellShares: request.requestedSellShares,\n sellShares: request.sellShares,\n availableShares: request.availableShares,\n allowedVenues: [request.venue],\n compareVenues: false,\n tradeSide: \"sell\",\n mode: mode ?? null,\n slipCapBps: slipCapBps ?? null,\n },\n ] as const,\n queryFn: async ({ signal }: { signal: AbortSignal }) =>\n client.getSmartRoute(\n {\n venueMarketOutcomeId: venueMarketOutcomeId!,\n tradeSide: \"sell\",\n ...(mode ? { mode } : {}),\n sellShares: request.sellShares,\n slipCapBps,\n allowedVenues: [request.venue],\n },\n { signal },\n ),\n enabled: queryEnabled,\n staleTime: staleTimeMs,\n refetchInterval: (queryState: { state: { data?: SmartRouteResponse | null } }) =>\n resolveSmartRouteRefetchInterval({\n // Venue quotes are display companions to the aggregate SELL quote.\n // Poll them at the normal cadence rather than independently\n // accelerating every venue to the thin-liquidity interval.\n data: queryState.state.data,\n adaptive: false,\n defaultIntervalMs: staleTimeMs,\n isDocumentVisible: getIsDocumentVisible(),\n isEditing: refreshContext?.isEditing ?? false,\n isInputValid: hasValidInput,\n isMarketOpen: refreshContext?.isMarketOpen ?? true,\n isPanelActive: refreshContext?.isPanelActive ?? true,\n isSubmitting: refreshContext?.isSubmitting ?? false,\n queryEnabled,\n }),\n gcTime: 60_000,\n refetchOnWindowFocus: false,\n refetchIntervalInBackground: false,\n retry: 1,\n };\n }),\n });\n\n const quotes = queries.map<VenueSellQuoteResult>((query, index) => {\n const queryError = query.error;\n return {\n request: uniqueRequests[index]!,\n data: query.data ?? null,\n isLoading: query.isLoading,\n isFetching: query.isFetching,\n error:\n queryError instanceof Error\n ? queryError\n : queryError\n ? new Error(String(queryError))\n : null,\n refetch: query.refetch,\n };\n });\n\n return {\n quotes,\n isLoading: quotes.some((quote) => quote.isLoading),\n isFetching: quotes.some((quote) => quote.isFetching),\n error: quotes.find((quote) => quote.error)?.error ?? null,\n refetch: () => Promise.all(quotes.map((quote) => quote.refetch())),\n };\n};\n","import { useInfiniteQuery } from \"@tanstack/react-query\";\nimport { Venue } from \"@agg-build/sdk\";\nimport { useAggClient } from \"./core/provider\";\n\nexport interface UseUserHoldingsOptions {\n venue: Venue;\n venueMarketId?: string;\n venueEventId?: string;\n enabled?: boolean;\n limit?: number;\n}\n\n/**\n * Fetch user holdings (positions) for a single venue with cursor-based pagination.\n * The backend resolves venue-specific identifiers (e.g. conditionId for Polymarket).\n */\nexport function useUserHoldings(options: UseUserHoldingsOptions) {\n const client = useAggClient();\n const { venue, venueMarketId, venueEventId, enabled = true } = options;\n\n const query = useInfiniteQuery({\n queryKey: [\"user-holdings\", venue, venueMarketId, venueEventId],\n queryFn: async ({ pageParam }) => {\n return client.getUserHoldings({\n venue,\n venueMarketId,\n venueEventId,\n cursor: pageParam as string | undefined,\n });\n },\n initialPageParam: undefined as string | undefined,\n getNextPageParam: (lastPage) => lastPage.nextCursor ?? undefined,\n enabled,\n });\n\n const holdings = query.data?.pages.flatMap((p) => p.data) ?? [];\n const hasNextPage = !!query.hasNextPage;\n\n return {\n ...query,\n holdings,\n hasNextPage,\n };\n}\n","import { MarketStatus } from \"@agg-build/sdk\";\nimport type {\n AggClient,\n RecurringCryptoDuration,\n RecurringCryptoVenueMarket,\n RecurringCryptoWindowMarket,\n} from \"@agg-build/sdk\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport { useAggClient } from \"./core/provider\";\nimport type { VenueEventWithMarkets } from \"./core/ui-config/types\";\n\nconst RESOLVING_POLL_INTERVAL_MS = 15_000;\nconst FALLBACK_VENUE_EVENT_PAGE_LIMIT = 100;\nconst FALLBACK_VENUE_EVENT_MAX_PAGES = 5;\nconst FALLBACK_TARGET_WINDOW_COUNT = 5;\nconst RECURRING_MARKET_STATUSES = [\n MarketStatus.open,\n MarketStatus.closed,\n MarketStatus.resolved,\n MarketStatus.unopened,\n MarketStatus.paused,\n];\n\nconst RECURRING_DURATION_MS: Record<RecurringCryptoDuration, number> = {\n PT5M: 5 * 60_000,\n PT15M: 15 * 60_000,\n PT30M: 30 * 60_000,\n PT1H: 60 * 60_000,\n PT4H: 4 * 60 * 60_000,\n P1D: 24 * 60 * 60_000,\n};\n\nconst RECURRING_SLUG_DURATION: Record<string, RecurringCryptoDuration> = {\n \"5m\": \"PT5M\",\n \"15m\": \"PT15M\",\n \"30m\": \"PT30M\",\n \"1h\": \"PT1H\",\n \"4h\": \"PT4H\",\n \"1d\": \"P1D\",\n};\n\nconst RECURRING_DURATION_AGG_KEY_SEGMENT: Partial<Record<RecurringCryptoDuration, string>> = {\n PT5M: \"5m\",\n PT15M: \"15m\",\n PT30M: \"30m\",\n PT1H: \"1h\",\n PT4H: \"4h\",\n};\n\nconst RECURRING_CRYPTO_SLUG_PATTERN = /^([a-z0-9]+)-updown-(5m|15m|30m|1h|4h|1d)-(\\d+)$/i;\nconst RECURRING_CRYPTO_AGG_KEY_PATTERN =\n /^agg_ud_([a-z0-9]+)_(5m|15m|30m|1h|4h)_(\\d{2})(\\d{2})(\\d{2})T(\\d{2})(\\d{2})$/i;\nconst RECURRING_CRYPTO_DAILY_AGG_KEY_PATTERN = /^agg_ud_([a-z0-9]+)_1d_(\\d{2})(\\d{2})(\\d{2})$/i;\n\nexport type RecurringCryptoIdentity = {\n asset: string | null;\n duration: RecurringCryptoDuration;\n windowStart: number | null;\n};\n\nexport type RecurringCryptoMarketInstance = {\n id: string;\n asset: string;\n duration: RecurringCryptoDuration;\n windowStart: string;\n windowEnd: string;\n status: MarketStatus;\n venueEventId: string;\n venueMarketId: string;\n venue: RecurringCryptoVenueMarket[\"venue\"];\n};\n\nexport type RecurringCryptoTimeline = {\n all: RecurringCryptoMarketInstance[];\n visible: RecurringCryptoMarketInstance[];\n ended: RecurringCryptoMarketInstance | null;\n live: RecurringCryptoMarketInstance | null;\n upcoming: RecurringCryptoMarketInstance[];\n viewed: RecurringCryptoMarketInstance | null;\n};\n\nexport type UseRecurringCryptoMarketsOptions = {\n event: VenueEventWithMarkets | undefined;\n enabled?: boolean;\n};\n\nconst isRecurringCryptoDuration = (\n value: string | null | undefined,\n): value is RecurringCryptoDuration =>\n value != null && Object.prototype.hasOwnProperty.call(RECURRING_DURATION_MS, value);\n\nconst parseTimestamp = (value: string | null | undefined): number | null => {\n if (!value) return null;\n const timestamp = Date.parse(value);\n return Number.isFinite(timestamp) ? timestamp : null;\n};\n\nconst hasCryptoCategory = (event: VenueEventWithMarkets): boolean =>\n event.categories.some(({ category }) =>\n [category.name, category.displayName].some((value) => value?.trim().toLowerCase() === \"crypto\"),\n );\n\nconst resolveWindowStartFromEnd = (\n event: VenueEventWithMarkets,\n duration: RecurringCryptoDuration,\n): number | null => {\n const end =\n parseTimestamp(event.endDate) ??\n event.venueMarkets\n .map((market) => parseTimestamp(market.endDate))\n .find((value) => value != null) ??\n null;\n if (end != null) return end - RECURRING_DURATION_MS[duration];\n\n return parseTimestamp(event.startDate);\n};\n\nconst parseAggKeyWindowStart = (match: RegExpMatchArray): number | null => {\n const year = 2_000 + Number(match[3]);\n const monthIndex = Number(match[4]) - 1;\n const day = Number(match[5]);\n const hour = Number(match[6]);\n const minute = Number(match[7]);\n const timestamp = Date.UTC(year, monthIndex, day, hour, minute);\n const parsed = new Date(timestamp);\n\n if (\n parsed.getUTCFullYear() !== year ||\n parsed.getUTCMonth() !== monthIndex ||\n parsed.getUTCDate() !== day ||\n parsed.getUTCHours() !== hour ||\n parsed.getUTCMinutes() !== minute\n ) {\n return null;\n }\n\n return timestamp;\n};\n\nexport const resolveRecurringCryptoIdentity = (\n event: VenueEventWithMarkets,\n): RecurringCryptoIdentity | null => {\n const slugMatch = event.slug?.match(RECURRING_CRYPTO_SLUG_PATTERN);\n if (slugMatch && hasCryptoCategory(event)) {\n const [, asset, durationSegment, epochSeconds] = slugMatch;\n const duration = RECURRING_SLUG_DURATION[durationSegment.toLowerCase()];\n const parsedEpochSeconds = Number(epochSeconds);\n const windowStart = parsedEpochSeconds * 1_000;\n\n if (duration && Number.isSafeInteger(parsedEpochSeconds) && Number.isFinite(windowStart)) {\n return { asset: asset.toUpperCase(), duration, windowStart };\n }\n }\n\n const aggKeyMatch = event.aggKey?.match(RECURRING_CRYPTO_AGG_KEY_PATTERN);\n if (aggKeyMatch) {\n const [, asset, durationSegment] = aggKeyMatch;\n const duration = RECURRING_SLUG_DURATION[durationSegment.toLowerCase()];\n const windowStart = parseAggKeyWindowStart(aggKeyMatch);\n\n if (duration && windowStart != null) {\n return { asset: asset.toUpperCase(), duration, windowStart };\n }\n }\n\n const dailyAggKeyMatch = event.aggKey?.match(RECURRING_CRYPTO_DAILY_AGG_KEY_PATTERN);\n if (dailyAggKeyMatch) {\n return {\n asset: dailyAggKeyMatch[1].toUpperCase(),\n duration: \"P1D\",\n windowStart: resolveWindowStartFromEnd(event, \"P1D\"),\n };\n }\n\n if (!isRecurringCryptoDuration(event.recurrence)) return null;\n\n return {\n asset: slugMatch?.[1]?.toUpperCase() ?? aggKeyMatch?.[1]?.toUpperCase() ?? null,\n duration: event.recurrence,\n windowStart: resolveWindowStartFromEnd(event, event.recurrence),\n };\n};\n\nconst mergeWindowMarkets = (\n current: RecurringCryptoVenueMarket[],\n incoming: RecurringCryptoVenueMarket[],\n): RecurringCryptoVenueMarket[] => {\n const marketsById = new Map(\n current.map((market) => [\n `${market.venue}:${market.venueEventId}:${market.venueMarketId}`,\n market,\n ]),\n );\n\n incoming.forEach((market) => {\n marketsById.set(`${market.venue}:${market.venueEventId}:${market.venueMarketId}`, market);\n });\n\n return [...marketsById.values()];\n};\n\nexport const mergeRecurringCryptoWindows = (\n windows: RecurringCryptoWindowMarket[],\n): RecurringCryptoWindowMarket[] => {\n const windowsById = new Map<string, RecurringCryptoWindowMarket>();\n\n windows.forEach((windowMarket) => {\n const existing = windowsById.get(windowMarket.id);\n if (!existing) {\n windowsById.set(windowMarket.id, windowMarket);\n return;\n }\n\n windowsById.set(windowMarket.id, {\n ...existing,\n ...windowMarket,\n markets: mergeWindowMarkets(existing.markets, windowMarket.markets),\n });\n });\n\n return [...windowsById.values()].sort(\n (left, right) =>\n (parseTimestamp(left.windowStart) ?? 0) - (parseTimestamp(right.windowStart) ?? 0),\n );\n};\n\nconst selectNavigableMarket = (\n markets: RecurringCryptoVenueMarket[],\n event: VenueEventWithMarkets,\n): RecurringCryptoVenueMarket | null => {\n const navigableMarkets = markets.filter((market) => market.priceSource === \"snag\");\n return (\n navigableMarkets.find((market) => market.venueEventId === event.id) ??\n navigableMarkets.find((market) => market.venue === event.venue) ??\n navigableMarkets[0] ??\n null\n );\n};\n\nexport const resolveRecurringCryptoTimeline = (\n windows: RecurringCryptoWindowMarket[],\n event: VenueEventWithMarkets,\n now: number,\n): RecurringCryptoTimeline => {\n const all = mergeRecurringCryptoWindows(windows).flatMap((windowMarket) => {\n const windowStart = parseTimestamp(windowMarket.windowStart);\n const windowEnd = parseTimestamp(windowMarket.windowEnd);\n const market = selectNavigableMarket(windowMarket.markets, event);\n if (windowStart == null || windowEnd == null || windowEnd <= windowStart || !market) return [];\n\n return [\n {\n id: windowMarket.id,\n asset: windowMarket.asset,\n duration: windowMarket.duration,\n windowStart: windowMarket.windowStart,\n windowEnd: windowMarket.windowEnd,\n status: market.status,\n venueEventId: market.venueEventId,\n venueMarketId: market.venueMarketId,\n venue: market.venue,\n } satisfies RecurringCryptoMarketInstance,\n ];\n });\n\n const viewed = all.find((market) => market.venueEventId === event.id) ?? null;\n const live =\n all.find((market) => {\n const startsAt = parseTimestamp(market.windowStart);\n const endsAt = parseTimestamp(market.windowEnd);\n return (\n market.status === MarketStatus.open &&\n startsAt != null &&\n endsAt != null &&\n startsAt <= now &&\n now < endsAt\n );\n }) ?? null;\n const endedMarkets = all.filter(\n (market) => (parseTimestamp(market.windowEnd) ?? Infinity) <= now,\n );\n const ended = endedMarkets[endedMarkets.length - 1] ?? null;\n const upcoming = all\n .filter((market) => (parseTimestamp(market.windowStart) ?? -Infinity) > now)\n .slice(0, 3);\n const defaultVisible = [ended, live, ...upcoming].filter(\n (market, index, values): market is RecurringCryptoMarketInstance =>\n market != null && values.findIndex((candidate) => candidate?.id === market.id) === index,\n );\n let visible = defaultVisible;\n\n if (viewed && !defaultVisible.some((market) => market.id === viewed.id)) {\n const viewedStart = Date.parse(viewed.windowStart);\n const viewedEnd = Date.parse(viewed.windowEnd);\n const marketToReplace =\n viewedEnd <= now\n ? ended\n : viewedStart > now\n ? upcoming[upcoming.length - 1]\n : (ended ?? upcoming[upcoming.length - 1]);\n\n visible = [\n ...defaultVisible.filter((market) => market.id !== marketToReplace?.id),\n viewed,\n ].sort(\n (left, right) =>\n (parseTimestamp(left.windowStart) ?? 0) - (parseTimestamp(right.windowStart) ?? 0),\n );\n }\n\n return { all, visible, ended, live, upcoming, viewed };\n};\n\nconst fetchRecurringCryptoPage = async (\n client: AggClient,\n options: NonNullable<Parameters<AggClient[\"listRecurringCryptoMarkets\"]>[0]>,\n signal: AbortSignal,\n) =>\n client.listRecurringCryptoMarkets({\n ...options,\n status: options.status ?? RECURRING_MARKET_STATUSES,\n includeOrderbookPrices: false,\n includeReferencePrices: false,\n includeDirectVenueMarkets: options.includeDirectVenueMarkets,\n limit: 100,\n signal,\n });\n\nconst createEmptyPriceComparison =\n (): RecurringCryptoWindowMarket[\"comparisons\"][\"referencePrice\"] => ({\n count: 0,\n min: null,\n max: null,\n spread: null,\n spreadBps: null,\n byVenue: [],\n });\n\nconst normalizeFallbackVenueEvent = (\n candidate: VenueEventWithMarkets,\n identity: RecurringCryptoIdentity,\n): RecurringCryptoWindowMarket | null => {\n const candidateIdentity = resolveRecurringCryptoIdentity(candidate);\n const venueMarket = candidate.venueMarkets[0];\n if (\n !candidateIdentity?.asset ||\n !identity.asset ||\n candidateIdentity.asset !== identity.asset ||\n candidateIdentity.duration !== identity.duration ||\n candidateIdentity.windowStart == null ||\n !venueMarket\n ) {\n return null;\n }\n\n const status = candidate.status ?? venueMarket.status ?? MarketStatus.unopened;\n const windowStart = candidateIdentity.windowStart;\n\n return {\n id: `${candidateIdentity.asset}:${candidateIdentity.duration}:${new Date(windowStart).toISOString()}`,\n asset: candidateIdentity.asset,\n quoteAsset: \"USD\",\n duration: candidateIdentity.duration,\n windowStart: new Date(windowStart).toISOString(),\n windowEnd: new Date(windowStart + RECURRING_DURATION_MS[identity.duration]).toISOString(),\n status,\n markets: [\n {\n venue: candidate.venue,\n venueEventId: candidate.id,\n venueMarketId: venueMarket.id,\n externalEventId: candidate.externalIdentifier,\n externalMarketId: venueMarket.externalIdentifier,\n question: venueMarket.question,\n status,\n priceSource: \"snag\",\n routeable: false,\n splitOrdersAllowed: false,\n outcomes: (venueMarket.venueMarketOutcomes ?? []).map((outcome) => ({\n venueMarketOutcomeId: outcome.id,\n externalOutcomeId: outcome.externalIdentifier ?? null,\n routeable: false,\n splitOrdersAllowed: false,\n label: outcome.label,\n title: outcome.title ?? null,\n midpoint: null,\n bestBid: null,\n bestAsk: null,\n markSource: null,\n lastKnownPrice: null,\n orderbookDepth: null,\n })),\n metrics: {\n volume: venueMarket.volume ?? null,\n volume24h: null,\n openInterest: null,\n liquidity: null,\n spread: null,\n },\n resolution: {\n sourceName: null,\n sourceUrl: null,\n sourceDomain: null,\n rawCriteria: null,\n confidence: \"missing\",\n },\n referencePrice: {\n asset: candidateIdentity.asset,\n quoteAsset: \"USD\",\n raw: null,\n decimals: null,\n normalized: null,\n timestamp: null,\n provider: null,\n providerMarketId: null,\n confidence: \"missing\",\n },\n },\n ],\n comparisons: {\n referencePrice: createEmptyPriceComparison(),\n outcomePrices: {\n up: createEmptyPriceComparison(),\n down: createEmptyPriceComparison(),\n },\n },\n };\n};\n\nconst formatCanonicalRecurringAggKey = (\n asset: string,\n duration: RecurringCryptoDuration,\n windowStart: number,\n): string | null => {\n const durationSegment = RECURRING_DURATION_AGG_KEY_SEGMENT[duration];\n if (!durationSegment) return null;\n\n const date = new Date(windowStart);\n if (Number.isNaN(date.getTime())) return null;\n\n const twoDigits = (value: number): string => String(value).padStart(2, \"0\");\n const timestamp = [\n twoDigits(date.getUTCFullYear() % 100),\n twoDigits(date.getUTCMonth() + 1),\n twoDigits(date.getUTCDate()),\n \"T\",\n twoDigits(date.getUTCHours()),\n twoDigits(date.getUTCMinutes()),\n ].join(\"\");\n\n return `agg_ud_${asset.toLowerCase()}_${durationSegment}_${timestamp}`;\n};\n\nconst fetchCanonicalAggKeyWindows = async (\n client: AggClient,\n event: VenueEventWithMarkets,\n identity: RecurringCryptoIdentity,\n signal: AbortSignal,\n now: number,\n): Promise<RecurringCryptoWindowMarket[]> => {\n const aggKeyMatch = event.aggKey?.match(RECURRING_CRYPTO_AGG_KEY_PATTERN);\n const asset = identity.asset;\n if (!aggKeyMatch || !asset) return [];\n\n const durationMs = RECURRING_DURATION_MS[identity.duration];\n const currentWindowStart = Math.floor(now / durationMs) * durationMs;\n const windowStarts = new Set([\n currentWindowStart - durationMs,\n currentWindowStart,\n currentWindowStart + durationMs,\n currentWindowStart + durationMs * 2,\n currentWindowStart + durationMs * 3,\n identity.windowStart,\n ]);\n const aggKeys = [...windowStarts].flatMap((windowStart) => {\n if (windowStart == null) return [];\n const aggKey = formatCanonicalRecurringAggKey(asset, identity.duration, windowStart);\n return aggKey ? [aggKey] : [];\n });\n if (!aggKeys.length) return [];\n\n const response = await client.getVenueEvents({\n venues: [event.venue],\n aggKey: aggKeys,\n limit: 100,\n signal,\n });\n\n return mergeRecurringCryptoWindows(\n response.data.flatMap((candidate) => {\n const normalized = normalizeFallbackVenueEvent(candidate as VenueEventWithMarkets, identity);\n return normalized ? [normalized] : [];\n }),\n );\n};\n\nconst fetchFallbackVenueEventWindows = async (\n client: AggClient,\n event: VenueEventWithMarkets,\n identity: RecurringCryptoIdentity,\n signal: AbortSignal,\n now: number,\n): Promise<RecurringCryptoWindowMarket[]> => {\n const durationMs = RECURRING_DURATION_MS[identity.duration];\n const categoryIds = event.categories\n .filter(({ category }) =>\n [category.name, category.displayName].some(\n (value) => value?.trim().toLowerCase() === \"crypto\",\n ),\n )\n .map(({ category }) => category.id);\n const windowStarts = new Set([(identity.windowStart ?? now) - durationMs, now - durationMs * 2]);\n const responses = await Promise.all(\n [...windowStarts].map(async (windowStart) => {\n const windows: RecurringCryptoWindowMarket[] = [];\n const seenCursors = new Set<string>();\n let cursor: string | undefined;\n\n for (let page = 0; page < FALLBACK_VENUE_EVENT_MAX_PAGES; page += 1) {\n const response = await client.getVenueEvents({\n venues: [event.venue],\n categoryIds,\n status: RECURRING_MARKET_STATUSES,\n sortBy: \"endDate\",\n sortDir: \"asc\",\n endDateFrom: new Date(windowStart).toISOString(),\n limit: FALLBACK_VENUE_EVENT_PAGE_LIMIT,\n cursor,\n signal,\n });\n\n response.data.forEach((candidate) => {\n const normalized = normalizeFallbackVenueEvent(\n candidate as VenueEventWithMarkets,\n identity,\n );\n if (normalized) windows.push(normalized);\n });\n\n if (mergeRecurringCryptoWindows(windows).length >= FALLBACK_TARGET_WINDOW_COUNT) break;\n\n const nextCursor = response.hasMore ? (response.nextCursor ?? undefined) : undefined;\n if (!nextCursor || seenCursors.has(nextCursor)) break;\n seenCursors.add(nextCursor);\n cursor = nextCursor;\n }\n\n return windows;\n }),\n );\n\n return mergeRecurringCryptoWindows(responses.flat());\n};\n\nexport const fetchRecurringCryptoMarkets = async (\n client: AggClient,\n event: VenueEventWithMarkets,\n signal: AbortSignal,\n now = Date.now(),\n): Promise<RecurringCryptoWindowMarket[]> => {\n const identity = resolveRecurringCryptoIdentity(event);\n if (!identity) return [];\n\n const { asset, duration, windowStart: anchorStart } = identity;\n const queryAssets = event.aggKey?.match(RECURRING_CRYPTO_DAILY_AGG_KEY_PATTERN)\n ? undefined\n : asset\n ? [asset]\n : undefined;\n const canonicalAggKeyWindowsPromise = fetchCanonicalAggKeyWindows(\n client,\n event,\n identity,\n signal,\n now,\n ).catch(() => []);\n const anchorOptions: Parameters<AggClient[\"listRecurringCryptoMarkets\"]>[0] =\n anchorStart == null\n ? {\n assets: queryAssets,\n durations: [duration],\n venues: [event.venue],\n window: \"current\",\n includeDirectVenueMarkets: duration === \"P1D\",\n }\n : {\n assets: queryAssets,\n durations: [duration],\n venues: [event.venue],\n windowStartFrom: new Date(anchorStart - 1_000).toISOString(),\n windowStartTo: new Date(anchorStart + 1_000).toISOString(),\n includeDirectVenueMarkets: duration === \"P1D\",\n };\n let anchorResponse = await fetchRecurringCryptoPage(client, anchorOptions, signal);\n let anchor = anchorResponse.data.find((windowMarket) =>\n windowMarket.markets.some((market) => market.venueEventId === event.id),\n );\n let timelineVenues: [typeof event.venue] | undefined = [event.venue];\n let canonicalAggKeyWindows: RecurringCryptoWindowMarket[] | null = null;\n\n if (!anchor) {\n canonicalAggKeyWindows = await canonicalAggKeyWindowsPromise;\n if (\n canonicalAggKeyWindows.some((windowMarket) =>\n windowMarket.markets.some((market) => market.venueEventId === event.id),\n )\n ) {\n return canonicalAggKeyWindows;\n }\n }\n\n if (!anchor && asset && anchorStart != null) {\n const unscopedAnchorResponse = await fetchRecurringCryptoPage(\n client,\n { ...anchorOptions, venues: undefined },\n signal,\n );\n const matchingWindow = unscopedAnchorResponse.data.find(\n (windowMarket) =>\n windowMarket.asset === asset &&\n windowMarket.duration === duration &&\n parseTimestamp(windowMarket.windowStart) === anchorStart,\n );\n const viewedWindow = normalizeFallbackVenueEvent(event, identity);\n\n if (matchingWindow && viewedWindow) {\n anchorResponse = unscopedAnchorResponse;\n anchor = {\n ...matchingWindow,\n markets: mergeWindowMarkets(matchingWindow.markets, viewedWindow.markets),\n };\n timelineVenues = undefined;\n }\n }\n\n if (!anchor) {\n return fetchFallbackVenueEventWindows(client, event, identity, signal, now);\n }\n\n const timelineStart = now - RECURRING_DURATION_MS[duration] * 2;\n const windows = [\n anchor,\n ...anchorResponse.data.filter(\n (windowMarket) => windowMarket.asset === anchor.asset && windowMarket.duration === duration,\n ),\n ];\n const seenCursors = new Set<string>();\n let cursor: string | undefined;\n\n do {\n const response = await fetchRecurringCryptoPage(\n client,\n {\n assets: [anchor.asset],\n durations: [duration],\n venues: timelineVenues,\n windowStartFrom: new Date(timelineStart).toISOString(),\n includeDirectVenueMarkets: duration === \"P1D\",\n cursor,\n },\n signal,\n );\n windows.push(...response.data);\n const nextCursor = response.hasMore ? (response.nextCursor ?? undefined) : undefined;\n if (!nextCursor || seenCursors.has(nextCursor)) break;\n seenCursors.add(nextCursor);\n cursor = nextCursor;\n } while (cursor);\n\n windows.push(...(canonicalAggKeyWindows ?? (await canonicalAggKeyWindowsPromise)));\n\n return mergeRecurringCryptoWindows(windows);\n};\n\nexport const recurringCryptoTransitionPollInterval = (\n windows: RecurringCryptoWindowMarket[] | undefined,\n event: VenueEventWithMarkets,\n now = Date.now(),\n): number | false => {\n if (!windows) return false;\n const timeline = resolveRecurringCryptoTimeline(windows, event, now);\n const viewedEnd = parseTimestamp(timeline.viewed?.windowEnd ?? event.endDate);\n return viewedEnd != null && viewedEnd <= now && !timeline.live\n ? RESOLVING_POLL_INTERVAL_MS\n : false;\n};\n\nexport const useRecurringCryptoMarkets = ({\n event,\n enabled = true,\n}: UseRecurringCryptoMarketsOptions) => {\n const client = useAggClient();\n const identity = event ? resolveRecurringCryptoIdentity(event) : null;\n const isEnabled = enabled && event != null && identity != null;\n const query = useQuery({\n queryKey: [\n \"recurring-crypto-markets\",\n event?.id,\n identity?.asset,\n identity?.duration,\n identity?.windowStart,\n event?.venue,\n ],\n queryFn: ({ signal }) => fetchRecurringCryptoMarkets(client, event!, signal),\n enabled: isEnabled,\n staleTime: 10_000,\n gcTime: 5 * 60_000,\n refetchOnWindowFocus: true,\n refetchOnReconnect: true,\n refetchOnMount: true,\n refetchInterval: (queryState) =>\n event\n ? recurringCryptoTransitionPollInterval(\n queryState.state.data as RecurringCryptoWindowMarket[] | undefined,\n event,\n )\n : false,\n retry: 1,\n });\n\n return {\n ...query,\n windows: (query.data as RecurringCryptoWindowMarket[] | undefined) ?? [],\n isRecurringCryptoMarket: isEnabled,\n };\n};\n","import { MarketStatus } from \"@agg-build/sdk\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport { useAggClient } from \"./core/provider\";\nimport type { VenueEventWithMarkets } from \"./core/ui-config/types\";\nimport { resolveRecurringCryptoIdentity } from \"./use-recurring-crypto-markets\";\n\nexport interface UseVenueEventOptions {\n /** The VenueEvent ID to fetch. */\n eventId: string;\n /** Enable/disable the query. Default true. */\n enabled?: boolean;\n /**\n * Scope `marketCount` and the rolled-up `volume` to the whole matched cluster\n * (default) or to this one venue event (`false`). Pair it with the same value\n * on `useVenueMarkets` so the count matches the market list you render.\n */\n cluster?: boolean;\n /**\n * Lifetime-volume floor. Scopes `marketCount` to the markets `useVenueMarkets`\n * returns with the same `minVolume`. Unset = no filter.\n */\n minVolume?: number;\n}\n\nconst RESOLUTION_POLL_MS = 15_000;\nconst RESOLUTION_POLL_MAX_PAST_END_MS = 60 * 60_000;\n\n/**\n * Poll while a market lingers \"open\" past its endDate, and keep polling an\n * explicitly closed recurring-crypto event until settlement is authoritative.\n * This prevents short-cadence markets from staying stale through rollover or\n * delayed resolution when the WebSocket notification is unavailable.\n *\n * endDate is a hint, not truth — some venues have historically reported\n * kickoff as endDate — so it never gates trading; it only triggers refetches\n * and the server's status stays authoritative. The one-hour guard applies to\n * stale open dates; an explicit recurring closed status remains pollable until\n * the backend changes it to resolved.\n */\nexport function resolutionPollInterval(event: VenueEventWithMarkets | undefined): number | false {\n if (!event) return false;\n const now = Date.now();\n const isRecurringCryptoMarket = resolveRecurringCryptoIdentity(event) != null;\n if (isRecurringCryptoMarket && event.status === MarketStatus.resolved) return false;\n if (isRecurringCryptoMarket && event.status === MarketStatus.closed) {\n return RESOLUTION_POLL_MS;\n }\n\n const eventEndsAt = event.endDate ? Date.parse(event.endDate) : Number.NaN;\n if (\n isRecurringCryptoMarket &&\n event.status === MarketStatus.paused &&\n Number.isFinite(eventEndsAt) &&\n eventEndsAt <= now\n ) {\n return RESOLUTION_POLL_MS;\n }\n\n const shouldPoll = event.venueMarkets.some((market) => {\n if (!market.endDate) return false;\n const endsAt = new Date(market.endDate).getTime();\n if (\n isRecurringCryptoMarket &&\n (market.status === MarketStatus.closed || market.status === MarketStatus.paused) &&\n Number.isFinite(endsAt) &&\n endsAt <= now\n ) {\n return true;\n }\n if (market.status !== MarketStatus.open) return false;\n return (\n Number.isFinite(endsAt) && now > endsAt && now < endsAt + RESOLUTION_POLL_MAX_PAST_END_MS\n );\n });\n\n if (shouldPoll) return RESOLUTION_POLL_MS;\n if (!isRecurringCryptoMarket || event.status !== MarketStatus.open) return false;\n if (!Number.isFinite(eventEndsAt)) return false;\n if (now <= eventEndsAt || now >= eventEndsAt + RESOLUTION_POLL_MAX_PAST_END_MS) return false;\n\n return RESOLUTION_POLL_MS;\n}\n\n/**\n * Fetch a single venue event by ID via the API.\n * Returns the event with nested venueMarkets.\n */\nexport function useVenueEvent(options: UseVenueEventOptions) {\n const client = useAggClient();\n const { eventId, enabled = true, cluster, minVolume } = options;\n\n const query = useQuery({\n queryKey: [\"venue-event\", eventId, cluster === false ? \"no-cluster\" : \"\", minVolume ?? \"\"],\n queryFn: async ({ signal }) => {\n return client.getVenueEventById(eventId, { signal, cluster, minVolume });\n },\n enabled: enabled && !!eventId,\n staleTime: 5 * 60_000,\n gcTime: 5 * 60_000,\n refetchOnWindowFocus: true,\n refetchOnReconnect: true,\n refetchOnMount: true,\n refetchInterval: (query) =>\n resolutionPollInterval(query.state.data as VenueEventWithMarkets | undefined),\n retry: 1,\n });\n\n return {\n ...query,\n event: (query.data as VenueEventWithMarkets | undefined) ?? undefined,\n };\n}\n","import type { MarketStatus, MatchStatus, Venue } from \"@agg-build/sdk\";\nimport { QueryClient, QueryClientContext, useInfiniteQuery } from \"@tanstack/react-query\";\nimport { useContext, useEffect, useState } from \"react\";\nimport { AggClientContext } from \"./core/providers/contexts\";\n\nexport interface UseVenueMarketsOptions {\n /** Filter by venue. */\n venue?: Venue;\n /** Filter by parent VenueEvent ID. */\n venueEventId?: string;\n /**\n * Scope `venueEventId` to the whole matched cluster (default) or to that one\n * venue event (`false`). Ignored without `venueEventId`.\n */\n cluster?: boolean;\n /** Search by question text. */\n search?: string;\n /** Filter by market status. */\n status?: MarketStatus;\n /** Filter by match status. */\n matchStatus?: MatchStatus;\n /** Canonical game or market key filter. */\n aggKey?: string[];\n /** Sports section filter: moneyline, spread, total, prop, ... */\n sportsMarketType?: string[];\n /** Sports period filter: full, 1h, 2h, q1, ... */\n period?: string[];\n /** Sports prop-category filter: corners, goals, assists, ... */\n marketCategory?: string[];\n /** Sports section/tab grouping filter: game_lines, spreads, totals, player_props, ... */\n marketGroup?: string[];\n /** Page size when using cursor pagination. Default 20. */\n limit?: number;\n /** Eagerly fetch every page until exhausted (no scroll wiring needed). */\n fetchAll?: boolean;\n /** Enable/disable the query. Default true. */\n enabled?: boolean;\n /** Sort by this field. */\n sortBy?: \"volume\" | \"volume24hr\" | \"createdAt\" | \"updatedAt\";\n /** Sort direction: \"asc\" or \"desc\". */\n sortDir?: \"asc\" | \"desc\";\n /** Sort surface. \"list\" makes axis/dates events sort by volume (matches the\n * tile top-3); omit or \"detail\" on the detail page to keep structured order. */\n context?: \"list\" | \"detail\";\n /** Text projection, independent of sort. Omit to preserve existing responses. */\n projection?: \"summary\" | \"full\";\n /** Lifetime-volume floor (USD). Omit or 0 = no filter. */\n minVolume?: number;\n}\n\n/**\n * Fetch venue markets with cursor-based pagination.\n * Use fetchNextPage for \"Load more\".\n */\nexport function useVenueMarkets(options?: UseVenueMarketsOptions) {\n const client = useContext(AggClientContext);\n const queryClient = useContext(QueryClientContext);\n const [fallbackQueryClient] = useState(() => new QueryClient());\n const venue = options?.venue;\n const venueEventId = options?.venueEventId;\n const cluster = options?.cluster;\n const search = options?.search;\n const matchStatus = options?.matchStatus;\n const status = options?.status;\n const aggKey = options?.aggKey;\n const sportsMarketType = options?.sportsMarketType;\n const period = options?.period;\n const marketCategory = options?.marketCategory;\n const marketGroup = options?.marketGroup;\n const enabled = options?.enabled ?? true;\n const limit = options?.limit ?? 20;\n const sortBy = options?.sortBy;\n const sortDir = options?.sortDir;\n const context = options?.context;\n const projection = options?.projection;\n const minVolume = options?.minVolume;\n\n useEffect(() => {\n if (queryClient) return undefined;\n\n fallbackQueryClient.mount();\n return () => {\n fallbackQueryClient.unmount();\n };\n }, [fallbackQueryClient, queryClient]);\n\n if (enabled && !client) {\n throw new Error(\"useVenueMarkets must be used within an <AggProvider>\");\n }\n\n const query = useInfiniteQuery(\n {\n queryKey: [\n \"venue-markets\",\n venue ?? \"\",\n venueEventId ?? \"\",\n cluster === false ? \"no-cluster\" : \"\",\n search ?? \"\",\n matchStatus ?? \"\",\n status ?? \"\",\n aggKey?.join(\",\") ?? \"\",\n sportsMarketType?.join(\",\") ?? \"\",\n period?.join(\",\") ?? \"\",\n marketCategory?.join(\",\") ?? \"\",\n marketGroup?.join(\",\") ?? \"\",\n limit,\n sortBy ?? \"\",\n sortDir ?? \"\",\n context ?? \"\",\n minVolume ?? \"\",\n projection ?? \"\",\n ],\n queryFn: async ({ pageParam, signal }) => {\n if (!client) {\n throw new Error(\"useVenueMarkets must be used within an <AggProvider>\");\n }\n\n const res = await client.getVenueMarkets(\n {\n venue,\n venueEventId,\n cluster,\n search,\n matchStatus,\n status,\n aggKey,\n sportsMarketType,\n period,\n marketCategory,\n marketGroup,\n limit,\n cursor: pageParam as string | undefined,\n sortBy,\n sortDir,\n context,\n projection,\n minVolume,\n },\n { signal },\n );\n return res;\n },\n initialPageParam: undefined as string | undefined,\n getNextPageParam: (lastPage) => {\n if (!lastPage.hasMore) return undefined;\n return lastPage.nextCursor ?? undefined;\n },\n enabled: enabled && !!client,\n },\n queryClient ?? fallbackQueryClient,\n );\n\n const markets = query.data?.pages.flatMap((page) => page.data) ?? [];\n const hasNextPage = !!query.hasNextPage;\n\n const { fetchNextPage, isFetchingNextPage } = query;\n const fetchAll = options?.fetchAll ?? false;\n useEffect(() => {\n if (!enabled || !client || !fetchAll || !hasNextPage || isFetchingNextPage) return;\n void fetchNextPage();\n }, [enabled, client, fetchAll, hasNextPage, isFetchingNextPage, fetchNextPage]);\n\n return {\n ...query,\n markets,\n hasNextPage,\n };\n}\n","import { MarketStatus, type VenueMarket } from \"@agg-build/sdk\";\nimport { useMemo } from \"react\";\nimport type { VenueEventWithMarkets } from \"./core/ui-config/types\";\nimport { useVenueEvent, type UseVenueEventOptions } from \"./use-venue-event\";\nimport { useVenueMarkets } from \"./use-venue-markets\";\n\n/**\n * Replaces the event's minimal venueMarkets with full versions from the\n * /venue-markets endpoint, preserving the original ordering.\n */\nexport function mergeEventWithFullMarkets(\n event: VenueEventWithMarkets,\n fullMarkets: VenueMarket[],\n): VenueEventWithMarkets {\n if (fullMarkets.length === 0) return event;\n\n const fullById = new Map(fullMarkets.map((m) => [m.id, m]));\n\n // Lean event responses (GET /venue-events/:id?expand=) omit the embedded\n // venueMarkets preview; when it's absent, adopt the full /venue-markets list\n // directly instead of mapping over an empty array (which would drop them).\n const ordering = event.venueMarkets.length > 0 ? event.venueMarkets : fullMarkets;\n const mergedMarkets = ordering.map((minimal) => fullById.get(minimal.id) ?? minimal);\n\n return { ...event, venueMarkets: mergedMarkets };\n}\n\nexport type UseEnrichedVenueEventOptions = UseVenueEventOptions & {\n progressive?: boolean;\n /** Summary keeps structured order and demand-loads text in detail consumers. */\n projection?: \"summary\" | \"full\";\n /** Lifetime-volume floor for the open-markets list (the all-status fallback ignores it). */\n minVolume?: number;\n};\n\n/**\n * Fetches a venue event and enriches its venueMarkets with full data\n * (description, rulesPrimary, rulesSecondary, etc.) from the /venue-markets endpoint.\n *\n * The useVenueMarkets call shares the same React Query cache key as MarketDetailsList,\n * so no extra HTTP request is made.\n */\nexport function useEnrichedVenueEvent(options: UseEnrichedVenueEventOptions) {\n const { event, isLoading, error, ...rest } = useVenueEvent(options);\n const eventEndedAt =\n event?.endDate && Number.isFinite(Date.parse(event.endDate)) ? Date.parse(event.endDate) : null;\n const shouldFetchOnlyOpenMarkets = eventEndedAt == null || eventEndedAt >= Date.now();\n\n const openQuery = useVenueMarkets({\n venueEventId: options.eventId,\n cluster: options.cluster,\n enabled: (options.enabled ?? true) && !!event,\n status: shouldFetchOnlyOpenMarkets ? MarketStatus.open : undefined,\n // No explicit sortBy: event-scoped /venue-markets sorts by the event's\n // type-aware order (structureOrderBy). Keeping this in lockstep with\n // MarketDetailsList (including limit, part of the query key) preserves the\n // shared React Query cache key and the event-type ordering.\n limit: 100,\n projection: options.projection,\n fetchAll: !options.progressive,\n minVolume: options.minVolume,\n });\n const { markets: openMarkets, isLoading: isEnrichingOpenMarkets } = openQuery;\n const shouldFetchAllMarketsFallback =\n (options.enabled ?? true) &&\n !!event &&\n shouldFetchOnlyOpenMarkets &&\n !isEnrichingOpenMarkets &&\n openMarkets.length === 0;\n const fallbackQuery = useVenueMarkets({\n venueEventId: options.eventId,\n cluster: options.cluster,\n enabled: shouldFetchAllMarketsFallback,\n // No status filter on fallback: if an active event temporarily has only\n // closed/resolved markets, still render the event page instead of the\n // unavailable state.\n // No minVolume on fallback: an event whose open markets are all below the\n // floor must still render (mirrors the bootstrap endpoint's fallback).\n limit: 100,\n projection: options.projection,\n fetchAll: !options.progressive,\n });\n const { markets: fallbackMarkets, isLoading: isEnrichingFallbackMarkets } = fallbackQuery;\n const activeQuery = shouldFetchAllMarketsFallback ? fallbackQuery : openQuery;\n const markets = fallbackMarkets.length > 0 ? fallbackMarkets : openMarkets;\n const isEnriching = isEnrichingOpenMarkets || isEnrichingFallbackMarkets;\n\n const enrichedEvent = useMemo(() => {\n if (!event) return undefined;\n if (markets.length === 0) return event;\n return mergeEventWithFullMarkets(event, markets);\n }, [event, markets]);\n\n return {\n ...rest,\n event: enrichedEvent,\n isLoading,\n isEnriching,\n hasMoreMarkets: !!activeQuery.hasNextPage,\n loadMoreMarkets: activeQuery.fetchNextPage,\n isLoadingMoreMarkets: !!activeQuery.isFetchingNextPage,\n error,\n };\n}\n","import type { MarketStatus, MatchStatus, Venue, RecurrenceFilter } from \"@agg-build/sdk\";\nimport {\n QueryClient,\n QueryClientContext,\n keepPreviousData,\n useInfiniteQuery,\n} from \"@tanstack/react-query\";\nimport { useContext, useEffect, useMemo, useRef, useState } from \"react\";\nimport { AggClientContext } from \"./core/providers/contexts\";\nimport type { VenueEventWithMarkets } from \"./core/ui-config/types\";\n\nexport interface UseVenueEventsOptions {\n /** Optional query-key scope to isolate caches across different surfaces. */\n queryKeyScope?: string;\n /** If provided, fetch events only from these providers. Omit or empty = both. */\n venues?: Venue[];\n /** If provided, filter/search events by this query (relayed to each provider). */\n search?: string;\n /** If provided, filter events by category IDs. */\n categoryIds?: string[];\n /** If provided, filter by match status. */\n matchStatus?: MatchStatus[];\n /** If provided, filter by market status. */\n status?: MarketStatus[];\n /** If provided, sort results by this field (e.g. \"volume\"). */\n sortBy?: string;\n /** Sort direction: \"asc\" or \"desc\". */\n sortDir?: string;\n /** Recurrence filter. Uses public ISO-8601 cadence enum values, or \"null\" for one-off events. */\n recurrence?: RecurrenceFilter | RecurrenceFilter[];\n /** If provided, enable the query. */\n enabled?: boolean;\n /** Page size when using cursor pagination. Default 20. */\n limit?: number;\n /** Lifetime-volume floor (USD). Omit or 0 = no filter. */\n minVolume?: number;\n /** If provided, filter by minimum yes price. */\n minYesPrice?: number;\n /** If provided, filter by maximum yes price. */\n maxYesPrice?: number;\n /** ISO-8601 timestamp. When set, hides events with endDate <= value; NULL-endDate events are kept. */\n endDateFrom?: string;\n /**\n * When true, fold same-venue companion events into one tile per game\n * (`groupParentId IS NULL`). Default (omitted/false) = ungrouped.\n */\n grouped?: boolean;\n /**\n * When restoring from a navigation snapshot, eagerly fetch this many pages\n * on mount (pages are likely cached by React Query from the prior visit).\n * Only runs once per mount. Ignored when <= 1.\n */\n initialPages?: number;\n}\n\n/**\n * Fetch venue events from one or both providers (Kalshi, Polymarket) via the API\n * with cursor-based pagination. Use fetchNextPage for \"Load more\".\n */\nexport function useVenueEvents(options?: UseVenueEventsOptions) {\n const client = useContext(AggClientContext);\n const queryClient = useContext(QueryClientContext);\n const [fallbackQueryClient] = useState(() => new QueryClient());\n const venues = options?.venues;\n const search = options?.search;\n const categoryIds = options?.categoryIds;\n const matchStatus = options?.matchStatus ?? [];\n const enabled = options?.enabled ?? true;\n const limit = options?.limit ?? 20;\n const status = options?.status;\n const sortBy = options?.sortBy;\n const sortDir = options?.sortDir;\n const recurrence = options?.recurrence;\n const queryKeyScope = options?.queryKeyScope ?? \"events\";\n const minVolume = options?.minVolume;\n const minYesPrice = options?.minYesPrice;\n const maxYesPrice = options?.maxYesPrice;\n const endDateFrom = options?.endDateFrom;\n const grouped = options?.grouped;\n const initialPages = options?.initialPages;\n\n useEffect(() => {\n if (queryClient) return undefined;\n\n fallbackQueryClient.mount();\n return () => {\n fallbackQueryClient.unmount();\n };\n }, [fallbackQueryClient, queryClient]);\n\n if (enabled && !client) {\n throw new Error(\"useVenueEvents must be used within an <AggProvider>\");\n }\n\n const query = useInfiniteQuery(\n {\n queryKey: [\n queryKeyScope,\n venues ?? [],\n search ?? \"\",\n categoryIds?.join(\",\") ?? \"\",\n matchStatus?.join(\",\") ?? \"\",\n status?.join(\",\") ?? \"\",\n sortBy ?? \"\",\n sortDir ?? \"\",\n recurrence ?? \"\",\n minYesPrice ?? \"\",\n maxYesPrice ?? \"\",\n endDateFrom ?? \"\",\n grouped ?? false,\n minVolume ?? \"\",\n limit,\n ],\n queryFn: async ({ pageParam, signal }) => {\n if (!client) {\n throw new Error(\"useVenueEvents must be used within an <AggProvider>\");\n }\n\n const res = await client.getVenueEvents({\n venues,\n search,\n categoryIds,\n matchStatus,\n status,\n sortBy,\n sortDir,\n recurrence,\n limit,\n minVolume,\n minYesPrice,\n maxYesPrice,\n endDateFrom,\n grouped,\n cursor: pageParam as string | undefined,\n signal,\n });\n return res;\n },\n initialPageParam: undefined as string | undefined,\n getNextPageParam: (lastPage) => {\n if (!lastPage.hasMore) return undefined;\n return lastPage.nextCursor ?? undefined;\n },\n // TODO: RMIK - Comment out to show skeletons on category switch\n placeholderData: keepPreviousData,\n enabled: enabled && !!client,\n },\n queryClient ?? fallbackQueryClient,\n );\n\n // Eagerly prefetch pages on mount when restoring from a navigation snapshot.\n // Pages are typically already in React Query's cache, so this is near-instant.\n const prefetchedRef = useRef(false);\n useEffect(() => {\n if (!enabled || !client) return;\n if (prefetchedRef.current) return;\n if (!initialPages || initialPages <= 1) return;\n if (query.isLoading || query.isFetching || query.isError || query.isPlaceholderData) return;\n\n const pagesLoaded = query.data?.pages.length ?? 0;\n if (pagesLoaded >= initialPages || !query.hasNextPage) {\n prefetchedRef.current = true;\n return;\n }\n\n void query.fetchNextPage();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [\n enabled,\n client,\n initialPages,\n query.isLoading,\n query.isFetching,\n query.isError,\n query.isPlaceholderData,\n query.data?.pages.length,\n query.hasNextPage,\n query.fetchNextPage,\n ]);\n\n // Memoize the flattened events so downstream consumers (filters, sorting,\n // per-card memoized values) don't recompute on every render just because a\n // new array was allocated.\n const events = useMemo(\n () => query.data?.pages.flatMap((page) => page.data) ?? [],\n [query.data?.pages],\n );\n const hasNextPage = !!query.hasNextPage;\n const loadedPageCount = query.data?.pages.length ?? 0;\n\n return {\n ...query,\n events: events as VenueEventWithMarkets[],\n hasNextPage,\n loadedPageCount,\n isPlaceholderData: query.isPlaceholderData,\n };\n}\n","import type { SportsLiveResponse, SportsLiveState } from \"@agg-build/sdk\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport { useAggClient } from \"./core/provider\";\n\nexport type {\n SportsGameStatus,\n SportsLiveParticipant,\n SportsLiveResponse,\n SportsLiveState,\n} from \"@agg-build/sdk\";\n\nexport const SPORTS_LIVE_POLL_INTERVAL_MS = 5_000;\nexport const SPORTS_SCHEDULED_POLL_INTERVAL_MS = 30_000;\n\nexport const sportsLiveQueryKey = (sortedEventIds: readonly string[]) =>\n [\"sports-live\", ...sortedEventIds] as const;\n\nexport const sportsLiveRefetchInterval = (\n response: SportsLiveResponse | undefined,\n): number | false => {\n if (!response) return false;\n if (response.data.some((state) => state.status === \"live\" || state.status === \"paused\")) {\n return SPORTS_LIVE_POLL_INTERVAL_MS;\n }\n if (response.data.some((state) => state.status === \"scheduled\")) {\n return SPORTS_SCHEDULED_POLL_INTERVAL_MS;\n }\n return false;\n};\n\nexport const useSportsLive = (eventIds: readonly string[], enabled: boolean = true) => {\n const client = useAggClient();\n const sortedEventIds = [\n ...new Set(eventIds.map((eventId) => eventId.trim()).filter(Boolean)),\n ].sort();\n\n const query = useQuery({\n queryKey: sportsLiveQueryKey(sortedEventIds),\n queryFn: ({ signal }): Promise<SportsLiveResponse> =>\n client.getSportsLive(sortedEventIds, { signal }),\n enabled: enabled && sortedEventIds.length > 0,\n refetchInterval: (queryState) => sportsLiveRefetchInterval(queryState.state.data),\n refetchIntervalInBackground: false,\n refetchOnWindowFocus: true,\n });\n\n const states = query.data?.data ?? [];\n const stateByEventId = new Map<string, SportsLiveState>(\n states.map((state) => [state.eventId, state]),\n );\n\n return {\n ...query,\n states,\n stateByEventId,\n missingEventIds: query.data?.missingEventIds ?? [],\n };\n};\n","import type { BatchMidpointsResponse, MidpointRow } from \"@agg-build/sdk\";\nimport { keepPreviousData, useQuery } from \"@tanstack/react-query\";\nimport { useAggClient, useAggUiConfig } from \"./core/provider\";\n\nconst normalizeVenueMarketIds = (venueMarketIds: string[]): string[] => {\n return [\n ...new Set(venueMarketIds.map((venueMarketId) => venueMarketId.trim()).filter(Boolean)),\n ].sort((left, right) => left.localeCompare(right));\n};\n\nconst mapMidpointsByVenueMarketId = (\n rows: Array<\n MidpointRow & {\n matched: MidpointRow[];\n }\n >,\n): Map<string, number | null> => {\n const mappedMidpoints = new Map<string, number | null>();\n\n rows.forEach((row) => {\n mappedMidpoints.set(row.venueMarketId, row.midpoint);\n\n row.matched.forEach((matchedRow) => {\n if (mappedMidpoints.has(matchedRow.venueMarketId)) return;\n mappedMidpoints.set(matchedRow.venueMarketId, matchedRow.midpoint);\n });\n });\n\n return mappedMidpoints;\n};\n\nconst mapArbReturnByVenueMarketId = (\n rows: Array<\n MidpointRow & {\n matched: MidpointRow[];\n }\n >,\n): Map<string, number | null> => {\n const mappedArbReturns = new Map<string, number | null>();\n\n rows.forEach((row) => {\n mappedArbReturns.set(row.venueMarketId, row.arbReturn ?? null);\n\n row.matched.forEach((matchedRow) => {\n if (mappedArbReturns.has(matchedRow.venueMarketId)) return;\n mappedArbReturns.set(matchedRow.venueMarketId, matchedRow.arbReturn ?? null);\n });\n });\n\n return mappedArbReturns;\n};\n\nexport interface UseVenueMarketMidpointsOptions {\n venueMarketIds: string[];\n enabled?: boolean;\n maxMidpointIdsPerRequest?: number;\n}\n\nexport function useVenueMarketMidpoints(options: UseVenueMarketMidpointsOptions) {\n const client = useAggClient();\n const {\n market: { maxMidpointIdsPerRequest: configuredMaxMidpointIdsPerRequest },\n } = useAggUiConfig();\n const enabled = options.enabled ?? true;\n const requestedVenueMarketIds = normalizeVenueMarketIds(options.venueMarketIds);\n const maxMidpointIdsPerRequest =\n options.maxMidpointIdsPerRequest ?? configuredMaxMidpointIdsPerRequest;\n\n const query = useQuery({\n queryKey: requestedVenueMarketIds.length\n ? ([\"venue-market-midpoints\", requestedVenueMarketIds, maxMidpointIdsPerRequest] as const)\n : ([\"venue-market-midpoints\", \"__disabled__\"] as const),\n queryFn: async ({ signal }) => {\n if (requestedVenueMarketIds.length === 0) {\n return { data: [] } satisfies BatchMidpointsResponse;\n }\n\n return client.getMidpoints(\n { venueMarketIds: requestedVenueMarketIds, bestPrice: true },\n { signal, maxMidpointIdsPerRequest },\n );\n },\n enabled: enabled && requestedVenueMarketIds.length > 0,\n staleTime: 10_000,\n gcTime: 5 * 60_000,\n refetchOnWindowFocus: false,\n retry: 1,\n placeholderData: keepPreviousData,\n });\n\n const midpointRows = query.data?.data ?? [];\n const midpointsByVenueMarketId = mapMidpointsByVenueMarketId(midpointRows);\n const arbReturnByVenueMarketId = mapArbReturnByVenueMarketId(midpointRows);\n\n return {\n ...query,\n midpointRows,\n midpointsByVenueMarketId,\n arbReturnByVenueMarketId,\n requestedVenueMarketIds,\n };\n}\n","import type { VenueMarket } from \"@agg-build/sdk\";\n\nexport const MIN_PRICE_GAP_PCT = 3;\nexport const MAX_PRICE_GAP_PCT = 50;\n\nexport type PriceGapValue = number;\n\nexport type ComputePriceGapsOptions = {\n markets: readonly VenueMarket[];\n midpointsByVenueMarketId: ReadonlyMap<string, number | null | undefined>;\n};\n\nconst normalizeMidpoint = (value: number | null | undefined): number | undefined => {\n if (typeof value !== \"number\" || !Number.isFinite(value)) return undefined;\n if (value <= 0) return undefined;\n if (value > 1) return undefined;\n return value;\n};\n\nconst collectMarketMidpoints = (\n market: VenueMarket,\n midpointsByVenueMarketId: ReadonlyMap<string, number | null | undefined>,\n): number[] => {\n const midpoints: number[] = [];\n const marketMidpoint = normalizeMidpoint(midpointsByVenueMarketId.get(market.id));\n\n if (marketMidpoint != null) {\n midpoints.push(marketMidpoint);\n }\n\n for (const matchedMarket of market.matchedVenueMarkets ?? []) {\n const matchedMidpoint = normalizeMidpoint(midpointsByVenueMarketId.get(matchedMarket.id));\n if (matchedMidpoint == null) continue;\n\n midpoints.push(matchedMidpoint);\n }\n\n return midpoints;\n};\n\nconst computePriceGapPct = (midpoints: readonly number[]): number | undefined => {\n if (midpoints.length < 2) return undefined;\n\n const minMidpoint = Math.min(...midpoints);\n const maxMidpoint = Math.max(...midpoints);\n if (minMidpoint <= 0 || maxMidpoint <= minMidpoint) return undefined;\n\n const gapPct = (maxMidpoint - minMidpoint) * 100;\n if (gapPct < MIN_PRICE_GAP_PCT) return undefined;\n if (gapPct > MAX_PRICE_GAP_PCT) return undefined;\n\n return gapPct;\n};\n\nexport const computePriceGaps = ({\n markets,\n midpointsByVenueMarketId,\n}: ComputePriceGapsOptions): Map<string, PriceGapValue> => {\n const gapsByVenueMarketId = new Map<string, PriceGapValue>();\n\n for (const market of markets) {\n const gapPct = computePriceGapPct(collectMarketMidpoints(market, midpointsByVenueMarketId));\n if (gapPct == null) continue;\n\n gapsByVenueMarketId.set(market.id, gapPct);\n }\n\n return gapsByVenueMarketId;\n};\n","import { useEffect, useMemo, useRef, useState } from \"react\";\nimport type { VenueMarket } from \"@agg-build/sdk\";\nimport { useAggClient, useAggUiConfig } from \"./core/provider\";\n\n/** Cached row for a single fetched venueMarketId. Per-outcome midpoints\n * come from the engine's `outcomes[]` array (own) and per matched\n * sibling's `outcomes[]` array (cross-venue alignment via MVMO). All\n * cross-venue best-price selection runs off these — no labels. */\ninterface CachedMidpoint {\n /** Primary venue that produced this row. */\n venue?: string;\n /** Per-outcome midpoints from this market's own orderbook, keyed by\n * `venueMarketOutcomeId`. */\n ownOutcomes: Map<string, number>;\n /** Matched siblings, each with their own per-outcome midpoints aligned\n * via MVMO (sibling outcome id → midpoint). */\n matched: Array<{\n venueMarketId: string;\n venue?: string;\n outcomes: Map<string, number>;\n }>;\n}\n\ntype MidpointRowWithMatches = {\n venueMarketId: string;\n venue?: string;\n outcomes?: Array<{\n venueMarketOutcomeId: string;\n midpoint: number | null;\n }>;\n matched?: Array<{\n venueMarketId: string;\n venue?: string;\n outcomes?: Array<{\n venueMarketOutcomeId: string;\n midpoint: number | null;\n }>;\n }>;\n};\n\nconst buildOutcomeMidpointMap = (\n outcomes: Array<{ venueMarketOutcomeId: string; midpoint: number | null }> | undefined,\n): Map<string, number> => {\n const m = new Map<string, number>();\n if (!outcomes) return m;\n for (const o of outcomes) {\n if (o.midpoint != null) m.set(o.venueMarketOutcomeId, o.midpoint);\n }\n return m;\n};\n\nexport const resolveUncachedVisibleMarketIds = (\n visibleMarkets: VenueMarket[],\n cache: Map<string, CachedMidpoint>,\n inFlightIds: Set<string>,\n): string[] => {\n const seen = new Set<string>();\n const idsToFetch: string[] = [];\n const consider = (id: string | undefined | null): void => {\n if (!id) return;\n if (seen.has(id)) return;\n if (inFlightIds.has(id)) return;\n if (cache.has(id)) return;\n seen.add(id);\n idsToFetch.push(id);\n };\n for (const market of visibleMarkets) {\n consider(market.id);\n // Include matched (cross-venue) sibling markets so the engine returns\n // top-of-book data for the full MVMO group. Without this the URL only\n // lists the primary venue's market ID and cross-venue best-price\n // resolution sees a half-empty book.\n for (const sibling of market.matchedVenueMarkets ?? []) {\n consider(sibling.id);\n }\n }\n return idsToFetch;\n};\n\nexport const buildCachedMidpointEntries = (\n requestedVenueMarketIds: string[],\n rows: MidpointRowWithMatches[],\n): Map<string, CachedMidpoint> => {\n const rowsByVenueMarketId = new Map(rows.map((item) => [item.venueMarketId, item]));\n const nextCacheEntries = new Map<string, CachedMidpoint>();\n\n for (const venueMarketId of requestedVenueMarketIds) {\n const item = rowsByVenueMarketId.get(venueMarketId);\n nextCacheEntries.set(venueMarketId, {\n ...(item?.venue ? { venue: item.venue } : {}),\n ownOutcomes: buildOutcomeMidpointMap(item?.outcomes),\n matched: (item?.matched ?? []).map((sib) => ({\n venueMarketId: sib.venueMarketId,\n ...(sib.venue ? { venue: sib.venue } : {}),\n outcomes: buildOutcomeMidpointMap(sib.outcomes),\n })),\n });\n }\n\n return nextCacheEntries;\n};\n\n/**\n * Fetch REST midpoints for a *dynamic* set of venue markets and cache them\n * for the hook lifetime.\n *\n * Designed for viewport-driven use cases (e.g. an IntersectionObserver-gated\n * list) where `visibleMarkets` changes as the user scrolls. Guarantees:\n *\n * • A market that was already fetched in this hook instance is **not**\n * refetched when the visible set changes — scrolling out and back in\n * reuses the cached value instead of re-hitting the network.\n * • Markets that become visible for the first time are batched into a\n * single request on the next render.\n *\n * Cross-venue best-price selection walks each parent outcome's\n * `matchedVenueMarketOutcomes` (MVMO references) and looks up the matched\n * counterpart's per-outcome midpoint. The lowest midpoint wins per\n * outcome — semantically correct for both Yes and No sides because MVMO\n * links same-side counterparts regardless of label inversion.\n */\nexport interface UseViewportMidpointsOptions {\n maxMidpointIdsPerRequest?: number;\n}\n\nexport function useViewportMidpoints(\n visibleMarkets: VenueMarket[],\n options?: UseViewportMidpointsOptions,\n): {\n prices: Map<string, number>;\n /**\n * Map of outcomeId → venue name that provided the price in `prices`.\n * Populated when a matched sibling offers a lower midpoint for the same\n * semantic side.\n */\n venueByOutcomeId: Map<string, string>;\n} {\n const client = useAggClient();\n const {\n market: { maxMidpointIdsPerRequest: configuredMaxMidpointIdsPerRequest },\n } = useAggUiConfig();\n const maxMidpointIdsPerRequest =\n options?.maxMidpointIdsPerRequest ?? configuredMaxMidpointIdsPerRequest;\n const [cache, setCache] = useState<Map<string, CachedMidpoint>>(() => new Map());\n const inFlightRef = useRef<Set<string>>(new Set());\n const visibleRef = useRef<VenueMarket[]>(visibleMarkets);\n visibleRef.current = visibleMarkets;\n\n const visibleFp = useMemo(\n () => [...new Set(visibleMarkets.map((m) => m.id))].sort().join(\"|\"),\n [visibleMarkets],\n );\n\n // Fetch only uncached ids when the visible set changes.\n useEffect(() => {\n const toFetch = resolveUncachedVisibleMarketIds(visibleRef.current, cache, inFlightRef.current);\n if (!toFetch.length) return;\n\n let cancelled = false;\n for (const id of toFetch) inFlightRef.current.add(id);\n\n client\n .getMidpoints(toFetch, { bestPrice: true, maxMidpointIdsPerRequest })\n .then((resp) => {\n if (cancelled) return;\n const nextCacheEntries = buildCachedMidpointEntries(toFetch, resp.data ?? []);\n setCache((prev) => {\n const next = new Map(prev);\n for (const [venueMarketId, entry] of nextCacheEntries) {\n next.set(venueMarketId, entry);\n }\n return next;\n });\n })\n .catch(() => {\n // Swallow: we only retry when the visible set changes.\n })\n .finally(() => {\n for (const id of toFetch) inFlightRef.current.delete(id);\n });\n\n return () => {\n cancelled = true;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [visibleFp, cache, maxMidpointIdsPerRequest]);\n\n const { prices, venueByOutcomeId } = useMemo(() => {\n const map = new Map<string, number>();\n const venueMap = new Map<string, string>();\n for (const market of visibleMarkets) {\n const entry = cache.get(market.id);\n if (!entry) continue;\n const ownVenue = entry.venue ?? market.venue;\n\n for (const outcome of market.venueMarketOutcomes) {\n // Start with this outcome's own midpoint (if any).\n let best: number | null = entry.ownOutcomes.get(outcome.id) ?? null;\n let bestVenue: string | null = best != null ? ownVenue : null;\n\n // Walk MVMO refs to compare per-outcome cross-venue midpoints.\n for (const ref of outcome.matchedVenueMarketOutcomes ?? []) {\n const sib = entry.matched.find((m) => m.venueMarketId === ref.venueMarketId);\n if (!sib) continue;\n const sibMidpoint = sib.outcomes.get(ref.venueMarketOutcomeId);\n if (sibMidpoint == null) continue;\n if (best == null || sibMidpoint < best) {\n best = sibMidpoint;\n bestVenue = sib.venue ?? bestVenue;\n }\n }\n\n if (best != null) {\n map.set(outcome.id, best);\n if (bestVenue) venueMap.set(outcome.id, bestVenue);\n }\n }\n }\n return { prices: map, venueByOutcomeId: venueMap };\n }, [cache, visibleMarkets]);\n\n return { prices, venueByOutcomeId };\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\";\n\nexport interface UseVisibleIdsOptions {\n /** IntersectionObserver root margin. Expand to pre-fetch just off-screen. */\n rootMargin?: string;\n /** IntersectionObserver threshold. Default 0 (fires on any overlap). */\n threshold?: number | number[];\n}\n\nexport interface UseVisibleIdsResult {\n /** Ids whose observed elements currently intersect the viewport. */\n visibleIds: Set<string>;\n /**\n * Returns a React callback ref for the element keyed by `id`. Attach it to\n * the card's DOM root; detaching (null) removes the id from observation.\n */\n register: (id: string) => (el: Element | null) => void;\n}\n\n/**\n * Track which ids are currently visible via IntersectionObserver. Useful for\n * gating expensive per-item work (e.g. polling) to on-screen items only.\n *\n * Callers pass a stable `id` per registered element; `visibleIds` updates as\n * elements enter and leave the viewport.\n */\nexport function useVisibleIds(options: UseVisibleIdsOptions = {}): UseVisibleIdsResult {\n const { rootMargin = \"0px\", threshold = 0 } = options;\n const [visibleIds, setVisibleIds] = useState<Set<string>>(() => new Set());\n\n const observerRef = useRef<IntersectionObserver | null>(null);\n const elementsRef = useRef<Map<string, Element>>(new Map());\n const elementIdRef = useRef<WeakMap<Element, string>>(new WeakMap());\n // Cache the callback ref per id so consumers pass a *stable* ref to React.\n // Without this, `register(id)` returns a new function each call and React\n // treats every render as a ref change — detach/attach on every render keeps\n // firing the observer, which re-triggers setVisibleIds, re-renders, loops.\n const callbackRefsRef = useRef<Map<string, (el: Element | null) => void>>(new Map());\n\n useEffect(() => {\n if (typeof IntersectionObserver === \"undefined\") return;\n\n const observer = new IntersectionObserver(\n (entries) => {\n setVisibleIds((prev) => {\n let changed = false;\n const next = new Set(prev);\n for (const entry of entries) {\n const id = elementIdRef.current.get(entry.target);\n if (!id) continue;\n if (entry.isIntersecting) {\n if (!next.has(id)) {\n next.add(id);\n changed = true;\n }\n } else if (next.has(id)) {\n next.delete(id);\n changed = true;\n }\n }\n return changed ? next : prev;\n });\n },\n { rootMargin, threshold },\n );\n\n observerRef.current = observer;\n for (const el of elementsRef.current.values()) observer.observe(el);\n\n return () => {\n observer.disconnect();\n observerRef.current = null;\n };\n }, [rootMargin, threshold]);\n\n const register = useCallback((id: string) => {\n const existing = callbackRefsRef.current.get(id);\n if (existing) return existing;\n\n const callback = (el: Element | null) => {\n const prev = elementsRef.current.get(id);\n if (prev === el) return;\n\n if (prev) {\n observerRef.current?.unobserve(prev);\n elementIdRef.current.delete(prev);\n elementsRef.current.delete(id);\n setVisibleIds((curr) => {\n if (!curr.has(id)) return curr;\n const next = new Set(curr);\n next.delete(id);\n return next;\n });\n }\n\n if (el) {\n elementsRef.current.set(id, el);\n elementIdRef.current.set(el, id);\n observerRef.current?.observe(el);\n } else {\n callbackRefsRef.current.delete(id);\n }\n };\n\n callbackRefsRef.current.set(id, callback);\n return callback;\n }, []);\n\n return { visibleIds, register };\n}\n","import { useCallback, useEffect, useState } from \"react\";\nimport { useAggAuthContext } from \"./core/provider\";\nimport { useResolvedExecutionMode } from \"./use-resolved-execution-mode\";\n\nconst STORAGE_KEY = \"agg_paper_onboarding_seen\";\n\nconst isBrowser = (): boolean => typeof window !== \"undefined\" && \"localStorage\" in window;\n\n/**\n * Per-user key. Two users on one browser (shared laptop, a tester switching\n * wallets) must each get the intro once — a single global flag would silently\n * swallow it for everyone after the first.\n */\nconst seenKey = (userId: string): string => `${STORAGE_KEY}:${userId}`;\n\nconst hasSeen = (userId: string): boolean => {\n if (!isBrowser()) return false;\n try {\n return window.localStorage.getItem(seenKey(userId)) === \"1\";\n } catch {\n // Private mode / storage disabled. Treat as \"already seen\" rather than\n // \"never seen\": re-showing the intro on every page load is far worse than\n // not showing it at all.\n return true;\n }\n};\n\nconst markSeen = (userId: string): void => {\n if (!isBrowser()) return;\n try {\n window.localStorage.setItem(seenKey(userId), \"1\");\n } catch {\n // Nothing to do — worst case the user sees it again next session.\n }\n};\n\nexport interface UsePaperOnboardingResult {\n /** Whether the intro should be on screen right now. */\n isOpen: boolean;\n /** Dismiss and never show again for this user. Idempotent. */\n dismiss: () => void;\n}\n\n/**\n * Decides whether to show the paper-trading intro.\n *\n * Shown once per user, and only in a paper app. All four conditions must hold:\n *\n * 1. the app resolved to paper mode (never in a live app),\n * 2. mode resolution has finished (otherwise a live app flashes the intro\n * before `/app/config` answers),\n * 3. the user is signed in and we know who they are (the flag is per-user),\n * 4. that user has not dismissed it before.\n */\nexport function usePaperOnboarding(): UsePaperOnboardingResult {\n const { isPaperMode, isResolving } = useResolvedExecutionMode();\n const { isAuthenticated, user } = useAggAuthContext();\n const userId = user?.id;\n\n const [dismissed, setDismissed] = useState(false);\n // Read storage in an effect, not during render: localStorage is unavailable\n // during SSR, and reading it inline would desync server and client HTML.\n const [seen, setSeen] = useState<boolean | null>(null);\n\n useEffect(() => {\n if (!userId) {\n setSeen(null);\n return;\n }\n setSeen(hasSeen(userId));\n }, [userId]);\n\n // A different user signing in on the same browser gets their own showing.\n useEffect(() => {\n setDismissed(false);\n }, [userId]);\n\n const dismiss = useCallback(() => {\n setDismissed(true);\n if (userId) markSeen(userId);\n }, [userId]);\n\n const isOpen =\n isPaperMode &&\n !isResolving &&\n isAuthenticated &&\n Boolean(userId) &&\n seen === false &&\n !dismissed;\n\n return { isOpen, dismiss };\n}\n","import { useQuery } from \"@tanstack/react-query\";\nimport type { VenueMarket } from \"@agg-build/sdk\";\nimport { useAggClient } from \"./core/provider\";\n\nexport interface UseSettlementDetailsDataOptions {\n eventId: string;\n /** Omit when only the event's details (description, settlementDiff) are needed. */\n market?: Pick<VenueMarket, \"id\" | \"venue\" | \"externalIdentifier\" | \"venueEventId\">;\n enabled: boolean;\n needsEvent: boolean;\n needsMarket: boolean;\n}\n/** Demand-load full settlement text for only the visible selected market and its permitted siblings. */\nexport function useSettlementDetailsData(options: UseSettlementDetailsDataOptions) {\n const client = useAggClient();\n const { eventId, market, enabled, needsEvent, needsMarket } = options;\n const eventQuery = useQuery({\n queryKey: [\"settlement-details\", \"event\", client.appId, eventId],\n queryFn: ({ signal }) => client.getVenueEventById(eventId, { signal }),\n enabled: enabled && needsEvent,\n staleTime: 5 * 60_000,\n gcTime: 10 * 60_000,\n retry: false,\n });\n const marketQuery = useQuery({\n queryKey: [\"settlement-details\", \"market\", client.appId, market?.id],\n queryFn: async ({ signal }) => {\n if (!market) throw new Error(\"Selected market details unavailable\");\n // Use the selected market's native identity and own event when available.\n // Explicit full projection restores text even when that event id is absent;\n // the displayed event may belong to a different cluster member.\n const response = await client.getVenueMarkets(\n {\n venue: market.venue,\n venueEventId: market.venueEventId ?? undefined,\n externalIdentifier: [market.externalIdentifier],\n limit: 1,\n projection: \"full\",\n },\n { signal },\n );\n const selected = response.data.find((candidate) => candidate.id === market.id);\n if (!selected) throw new Error(\"Selected market details unavailable\");\n return { selected, markets: response.data };\n },\n enabled: enabled && needsMarket && market != null,\n staleTime: 5 * 60_000,\n gcTime: 10 * 60_000,\n retry: false,\n });\n return { eventQuery, marketQuery };\n}\n","import { useEffect, useRef, useState } from \"react\";\nimport { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport type { HostedVenueWithdrawal, HostedVenueWithdrawalRequest } from \"@agg-build/sdk\";\nimport { useAggAuthContext, useAggClient } from \"./core/provider\";\nimport { useResolvedExecutionMode } from \"./use-resolved-execution-mode\";\nimport { hostedVenueAccountQueryKeys } from \"./use-hosted-venue-account\";\nimport { invalidateBalanceQueries } from \"./execution/balance-invalidation\";\n\ntype Journal = { request: HostedVenueWithdrawalRequest; withdrawalId?: string };\ntype Environment = \"production\" | \"sandbox\";\nconst validRequest = (value: unknown): value is Journal => {\n const row = value as Journal | null;\n return (\n !!row &&\n row.request?.mode === \"live\" &&\n /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(\n row.request.requestId,\n ) &&\n /^[1-9][0-9]{0,31}$/.test(row.request.amountRaw) &&\n /^[1-9A-HJ-NP-Za-km-z]{32,44}$/.test(row.request.destinationAddress) &&\n (row.withdrawalId === undefined || /^[a-zA-Z0-9_-]{1,256}$/.test(row.withdrawalId))\n );\n};\n\n/** Explicit hosted transfers, bound to the current user and persisted before dispatch.\n * Reloads may read status; they never automatically submit or retry a withdrawal.\n */\nexport function useHostedVenueTransfers(accountId: string, environment: Environment) {\n const client = useAggClient();\n const { user, isAuthenticated } = useAggAuthContext();\n const { executionMode, isResolving } = useResolvedExecutionMode();\n const queryClient = useQueryClient();\n const userId = user?.id ?? null;\n const permitted = isAuthenticated && !!userId && !isResolving && executionMode === \"live\";\n const scope = JSON.stringify([userId, accountId, environment]);\n const storageKey = \"agg:betdex-withdrawal:\" + scope;\n const [entry, setEntry] = useState<{\n scope: string;\n ready: boolean;\n journal: Journal | null;\n invalid: boolean;\n }>({\n scope: \"\",\n ready: false,\n journal: null,\n invalid: false,\n });\n const session = useRef({ client, scope, permitted });\n session.current = { client, scope, permitted };\n const mounted = useRef(true);\n const dispatching = useRef(false);\n const intent = useRef<{ scope: string; journal: Journal } | null>(null);\n const current = entry.scope === scope ? entry : null;\n const journal = current?.journal ?? null;\n const assertSession = () => {\n if (\n !mounted.current ||\n !permitted ||\n !session.current.permitted ||\n session.current.client !== client ||\n session.current.scope !== scope\n )\n throw new Error(\"Hosted transfers are unavailable for this session\");\n };\n const save = (next: Journal) => {\n localStorage.setItem(storageKey, JSON.stringify(next));\n if (mounted.current && session.current.scope === scope) {\n intent.current = { scope, journal: next };\n setEntry({ scope, ready: true, journal: next, invalid: false });\n }\n };\n const assertResult = (result: { accountId: string; environment: string }) => {\n if (result.accountId !== accountId || result.environment !== environment)\n throw new Error(\"Hosted transfer identity mismatch\");\n };\n const invalidate = () => {\n void queryClient.invalidateQueries({\n queryKey: hostedVenueAccountQueryKeys.account(\"betdex\", userId, \"live\"),\n });\n invalidateBalanceQueries(queryClient);\n };\n const deposit = useMutation({\n mutationFn: async () => {\n assertSession();\n const result = await client.getHostedVenueDepositAddress(\"betdex\", { mode: \"live\" });\n assertResult(result);\n assertSession();\n return { scope, result };\n },\n retry: false,\n });\n const withdrawal = useMutation({\n mutationFn: async (request: Journal) => {\n assertSession();\n if (dispatching.current) throw new Error(\"Withdrawal request is already pending\");\n dispatching.current = true;\n try {\n // Saving must succeed before the first network request.\n save(request);\n const result = request.withdrawalId\n ? await client.getHostedVenueWithdrawal(\"betdex\", request.withdrawalId, { mode: \"live\" })\n : await client.withdrawHostedVenue(\"betdex\", request.request);\n assertResult(result);\n save({ ...request, withdrawalId: result.id });\n assertSession();\n invalidate();\n return { scope, result };\n } finally {\n dispatching.current = false;\n }\n },\n retry: false,\n });\n const status = useQuery({\n queryKey: [\"agg\", \"hosted-venue-withdrawal\", scope, journal?.withdrawalId],\n queryFn: async () => {\n assertSession();\n if (!journal?.withdrawalId) throw new Error(\"Withdrawal identity is unavailable\");\n const result = await client.getHostedVenueWithdrawal(\"betdex\", journal.withdrawalId, {\n mode: \"live\",\n });\n assertResult(result);\n assertSession();\n if (result.status === \"confirmed\" || result.status === \"failed\") invalidate();\n return result;\n },\n enabled: permitted && !!journal?.withdrawalId,\n retry: false,\n refetchInterval: (query) => (query.state.data?.status === \"processing\" ? 2000 : false),\n refetchIntervalInBackground: false,\n });\n useEffect(() => {\n mounted.current = true;\n return () => {\n mounted.current = false;\n };\n }, []);\n const resetDeposit = deposit.reset;\n const resetWithdrawal = withdrawal.reset;\n useEffect(() => {\n resetDeposit();\n resetWithdrawal();\n if (!permitted) return;\n try {\n const text = localStorage.getItem(storageKey);\n const value: unknown = text ? JSON.parse(text) : null;\n if (value !== null && !validRequest(value)) throw new Error(\"Invalid saved withdrawal\");\n intent.current = value ? { scope, journal: value as Journal } : null;\n setEntry({ scope, ready: true, journal: value as Journal | null, invalid: false });\n } catch {\n setEntry({ scope, ready: false, journal: null, invalid: true });\n }\n }, [storageKey, scope, permitted, resetDeposit, resetWithdrawal]);\n\n const result: HostedVenueWithdrawal | undefined =\n status.data ?? (withdrawal.data?.scope === scope ? withdrawal.data.result : undefined);\n const terminal = result?.status === \"confirmed\" || result?.status === \"failed\";\n return {\n isAvailable: permitted,\n ready: !!current?.ready,\n storageError: !!current?.invalid,\n deposit: { ...deposit, data: deposit.data?.scope === scope ? deposit.data.result : undefined },\n withdrawal: { ...withdrawal, data: result, isError: withdrawal.isError || status.isError },\n request: journal?.request,\n submit: async (amountRaw: string, destinationAddress: string) => {\n assertSession();\n if (!current?.ready || current.invalid || journal || intent.current?.scope === scope)\n throw new Error(\"Resolve the existing withdrawal first\");\n const request = {\n mode: \"live\" as const,\n requestId: crypto.randomUUID(),\n amountRaw,\n destinationAddress,\n };\n if (!validRequest({ request })) throw new Error(\"Invalid withdrawal request\");\n // Set the durable intent synchronously, before React renders the mutation state.\n save({ request });\n return withdrawal.mutateAsync({ request });\n },\n check: async () => {\n assertSession();\n if (!journal || !current?.ready) throw new Error(\"No saved withdrawal\");\n return withdrawal.mutateAsync(journal);\n },\n clear: () => {\n assertSession();\n if (!terminal || dispatching.current || intent.current?.journal.withdrawalId !== result?.id)\n throw new Error(\"Withdrawal is not terminal\");\n localStorage.removeItem(storageKey);\n intent.current = null;\n setEntry({ scope, ready: true, journal: null, invalid: false });\n withdrawal.reset();\n },\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["UserProfile","AggClient","QueryClient","CURRENT_USER_QUERY_KEY","const","CURRENT_USER_STALE_TIME_MS","getCurrentUserQueryKey","queryKeyScope","fetchCurrentUserProfile","queryClient","client","queryKey","Promise","fetchQuery","queryFn","getCurrentUser","staleTime","UserProfile","AggAuthStartBody","AggAuthStartResult","AggClientSessionInput","AccountType","AccountProvider","TurnstileChallengeError","AggAuthSignInOptions","BrowserAuthLocation","domain","uri","AuthCallbackTokens","accessToken","refreshToken","tokenType","userId","AuthCodeExchangeResult","user","WalletAuthResult","WalletAuthClient","authStart","body","Promise","buildSiweMessage","params","address","chainId","issuedAt","nonce","statement","buildSiwsMessage","verify","args","message","signature","AuthCallbackClient","exchangeAuthCode","code","LinkConfirmCallbackClient","linkAccountConfirm","token","createPlaceholderUserProfile","input","id","username","avatarUrl","externalId","isLocationBlocked","venueAccounts","accounts","wallets","createWalletSessionUser","type","siwe","provider","wallet","providerAccountId","getBrowserAuthLocation","window","location","host","origin","resolveAuthCallbackUrl","callbackUrl","URL","href","parseAuthCallbackCode","resolvedUrl","searchParams","get","parseLinkConfirmToken","AUTH_METHOD_IDS","const","AggAuthMethodId","EXISTING_METHOD_NAMES","email","google","apple","AggIdentityExistsError","Error","constructor","existingMethod","attemptedMethod","name","IDENTITY_EXISTS_PARAMS","parseAuthCallbackIdentityExists","find","getAuthCallbackCleanupPath","URLSearchParams","search","delete","toString","pathname","exchangeAuthCallbackCode","client","cleanupPath","result","confirmLinkAccountCallback","parseAuthCallbackTokens","hash","startsWith","slice","undefined","createAuthCallbackSession","tokens","executeWalletAuthFlow","options","trim","chain","startResult","turnstileToken","siteKey","signMessage","TurnstileChallengeError","UserProfile","AggClient","QueryClient","QueryClientContext","useCallback","useContext","useEffect","useMemo","useState","ReactNode","fetchCurrentUserProfile","confirmLinkAccountCallback","createAuthCallbackSession","exchangeAuthCallbackCode","executeWalletAuthFlow","getAuthCallbackCleanupPath","parseAuthCallbackIdentityExists","parseAuthCallbackTokens","AggAuthContext","AggClientContext","AggAuthContextValue","AggAuthSignInOptions","AuthSnapshot","isAuthenticated","user","getClientAuthSnapshot","client","AggAuthProviderProps","children","toError","value","Error","String","replaceAuthCallbackUrl","cleanupPath","window","history","replaceState","AggAuthProvider","React","JSX","Element","queryClientFromContext","fallbackQueryClient","queryClient","snapshot","setIsAuthenticated","setUser","isLoading","setIsLoading","error","setError","isWeb3User","accounts","Array","isArray","some","account","provider","toLowerCase","refreshCurrentUser","targetClient","Promise","fullUser","state","catch","clearAccessToken","authStatus","refreshAccessToken","then","onAuthStateChange","authenticated","signIn","options","missingClientError","address","trim","missingAddressError","result","setSession","signInError","resolvedError","startAuth","authStart","startAuthError","session","resolvedUser","sessionError","undefined","handleAuthCallback","callbackUrl","identityError","exchangedSession","confirmedLink","tokens","callbackError","signOut","clearError","QueryClient","useContext","AppTradingMode","useAggUiConfig","AggExecutionModeContext","UseResolvedExecutionModeResult","executionMode","isPaperMode","isResolving","useResolvedExecutionMode","override","serverConfig","tradingMode","isLoading","trading","configuredExecutionMode","localMode","undefined","UnifiedBalanceResponse","Venue","useQuery","useCallback","useContext","useMemo","ReactNode","balanceQueryKeys","useResolvedExecutionMode","resolveAggUiLabels","AggAuthContext","AggBalanceContext","AggClientContext","AggBalanceBreakdownItem","AggBalanceContextValue","CHAIN_LABELS","Record","chainLabelFromId","chainId","toTokenUnits","raw","decimals","numeric","Number","isFinite","isUsdBasedToken","tokenSymbol","toUpperCase","includes","EMPTY_MANAGED_BALANCES","cash","positions","AggBalanceProviderProps","children","AggBalanceProvider","React","JSX","Element","client","authContext","executionMode","Error","isAuthenticated","queryExecutionMode","undefined","balancesQuery","queryKey","provider","queryFn","Promise","getManagedBalances","mode","enabled","Boolean","staleTime","refetchInterval","refetchIntervalInBackground","refetchOnWindowFocus","refetchOnReconnect","managedBalancesData","data","managedBalances","connectedVenues","Array","from","Set","map","position","venue","sort","a","b","localeCompare","balancesError","error","isBalancesLoading","isLoading","refetchBalances","refetch","totalBalance","reduce","sum","token","tokenAcrossChains","chains","chainSum","chain","balanceRaw","availableBalance","availableRaw","reservedBalance","reservedRaw","heldRaw","buildBalanceBreakdown","rawForChain","bySource","Map","chainVenues","filter","native","custodyKind","key","JSON","stringify","venueAccountId","externalAccountId","String","current","get","label","venues","userProfile","balance","venueAccount","accountCount","length","isFresh","set","values","balanceBreakdown","availableBalanceBreakdown","positionsBalanceTotal","actualPositionsBalance","kalshiVenueCash","venueCash","find","item","venueCashBalances","Object","fromEntries","balanceCents","kalshiBalance","kalshiPortfolioValue","portfolioValueCents","betdexCash","accountModel","hostedUsd","test","value","betdexBalance","betdexAvailableBalance","refetchConnectionStatus","getCurrentUser","dataUpdatedAt","AggClient","ReactNode","AggClientContext","AggClientProviderProps","client","children","AggClientProvider","t0","$","_c","t1","t2","_c","AppClientConfigResponse","useQuery","useQueryClient","useAggClient","useOptionalAggClient","FIVE_MINUTES","NO_APP_SCOPE","appConfigQueryKey","appId","const","UseAppConfigResult","prophetxExecutionMode","novigExecutionMode","disabledVenues","disabledCategoryPresets","earlyAccessEnabled","authOptions","tradingMode","paperStartingBalance","isLoading","error","useAppConfig","client","query","queryKey","queryFn","getAppConfig","staleTime","refetchInterval","toAppConfigResult","data","useCachedAppConfig","queryClient","enabled","initialData","getQueryData","undefined","useQueryClient","useMemo","ReactNode","useAppConfig","AggExecutionModeContext","AggExecutionModeProvider","children","React","JSX","Element","tradingMode","paperStartingBalance","isLoading","value","createContext","useCallback","useContext","useRef","ReactNode","STALENESS_THRESHOLD_MS","MAX_INITIAL_PAGES","EventListStateSnapshot","categoryTab","venueTab","scrollY","loadedPageCount","capturedAt","EventListStateContextValue","capture","state","Omit","consume","EventListStateContext","EventListStateProvider","children","React","JSX","Element","snapshotRef","current","Math","min","Date","now","snapshot","age","value","stableValue","args","useEventListState","context","Error","ChartTimeRange","DEFAULT_AGG_ROOT_CLASS_NAME","CHART_TIME_RANGES","AggUiGeneralConfig","AggUiPersistedConfig","ChartTimeRange","ThemeMode","CHART_TIME_RANGES","STORAGE_KEY","isBrowser","window","normalizeTheme","value","undefined","normalizeChartTimeRange","includes","loadPersistedConfig","raw","localStorage","getItem","parsed","JSON","parse","locale","general","theme","selectedChartTimeRange","chart","result","PersistConfigPayload","persistConfig","config","payload","setItem","stringify","STORAGE_KEY","isBrowser","ThemeMode","applyThemeToDocument","theme","document","isDark","documentElement","dataset","aggTheme","classList","toggle","aggRoots","querySelectorAll","HTMLElement","forEach","rootElement","MarketStatus","VenueEventWithMarkets","VenueMarket","VenueMarketOutcome","createContext","useCallback","useContext","useMemo","useReducer","useRef","TradingStateKind","TradingStateBase","kind","status","isOpen","isTradingDisabled","startsAt","endsAt","resolvesAt","winningOutcome","MarketTradingState","market","EventTradingState","displayMarkets","tradableMarkets","marketStates","Array","state","primaryMarket","OrderEligibilityReason","OrderEligibility","canPlaceOrder","reason","OPEN_TRADING_STATE","open","resolveTradingStateKind","Exclude","resolved","paused","unopened","resolveMarketWinningOutcome","localWinningOutcome","venueMarketOutcomes","find","outcome","winner","matchedVenueMarkets","length","matchedRefs","matchedVenueMarketOutcomes","ref","matchedMarket","item","id","venueMarketId","matchedOutcome","venueMarketOutcomeId","AFFIRMATIVE_WINNER_LABELS","Set","isAffirmativeWinnerLabel","label","has","trim","toLowerCase","resolvePreferredWinningMarket","marketWithAffirmativeWinner","resolveMarketTradingState","startDate","endDate","resolutionDate","deriveEventTradingStateKind","some","marketState","every","resolveEventStateStatus","event","closed","resolveEventWinningOutcome","preferredMarket","resolveEventTradingState","venueMarkets","map","derivedKind","explicitKind","preferredWinningMarket","filter","toEventReason","mapped","Record","unavailable","toMarketReason","resolveOrderEligibility","params","eventTradingState","eventState","resolveDefaultMarket","tradableMarket","resolveDefaultTradingMarket","resolveDefaultOutcome","yesOutcome","o","findMarketById","marketId","m","findOutcomeById","outcomeId","findOutcomeAcrossMarkets","TradeSide","Buy","Sell","const","TradingState","tradeSide","TradingAction","type","tradingReducer","action","previousMarketId","previousOutcomeId","syncedMarket","syncedOutcome","outcomeInCurrentMarket","found","targetMarketState","_exhaustive","logAction","actionType","payload","prev","next","enableLogs","console","group","log","eventId","marketIds","outcomeIds","flatMap","selectedMarketId","selectedOutcomeId","groupEnd","EventTradingContextValue","selectedEvent","selectedMarket","selectedOutcome","selectedEventId","selectedVenue","setTradeSide","initializeFromEvent","syncEvent","selectMarket","selectOutcome","selectMarketAndOutcome","initialState","EventTradingContext","undefined","useEventTradingContext","EventTradingProviderProps","children","React","ReactNode","EventTradingProvider","JSX","Element","rawDispatch","stateRef","pendingAtomicSelectionRef","current","pendingAtomicSelection","dispatch","value","venue","MarketStatus","_exhaustive","useCallback","useEffect","useMemo","useState","DEFAULT_AGG_ROOT_CLASS_NAME","loadPersistedConfig","persistConfig","applyThemeToDocument","AggUiConfig","ChartTimeRange","SdkUiProviderProps","VenueEventWithMarkets","mergeAggUiConfig","AggLabelsContext","AggUiContext","EventTradingProvider","hasWarnedMissingAggStyles","warnIfAggStylesAreMissing","window","document","rootElement","querySelector","HTMLElement","computedStyle","getComputedStyle","hasSemanticColorToken","getPropertyValue","trim","length","hasTailwindColorToken","hasTailwindRadiusToken","console","warn","logConfig","config","enableLogs","group","log","groupEnd","SearchSelectState","Pick","value","getSearchStateAfterSelect","selectedEvent","result","isShowingAllResults","AggUiProvider","children","React","JSX","Element","persisted","mergedConfig","selectedChartTimeRange","setSelectedChartTimeRange","chart","handleSetSelectedChartTimeRange","range","searchValue","setSearchValue","search","searchResult","setSearchResult","setIsShowingAllResults","handleSearchChange","onChange","handleSearchSelect","nextSearchState","onSelect","handleOpenResults","openResults","handleCloseResults","closeResults","resolvedConfig","locale","general","theme","resolvedRootClassName","rootClassName","filter","Boolean","join","labels","features","enableAnimations","enableGradients","useQueryClient","AggAuthProvider","AggBalanceProvider","AggClientProvider","AggExecutionModeProvider","EventListStateProvider","AggWebSocketProvider","AggProviderProps","AggUiProvider","hasWarnedMissingQueryClient","useQueryClientCheck","console","error","AggProvider","client","config","children","React","JSX","Element","Error","useMutation","useQueryClient","ExecuteManagedParams","ExecuteManagedResponse","SmartRouteResponse","useAggClient","executionKeys","invalidateBalanceQueries","UseExecuteManagedOptions","onSuccess","data","onError","error","Error","useExecuteManaged","options","client","queryClient","mutationFn","params","executeManaged","setQueriesData","queryKey","route","consumedPrimary","quoteId","consumedComparison","venueSoloQuotes","some","quote","map","invalidateQueries","ordersPrefix","positionsPrefix","useQueryClient","useMutation","useQueryClient","PlaceLimitOrderParams","PlaceLimitOrderResponse","useAggClient","invalidateBalanceQueries","executionKeys","UsePlaceLimitOrderOptions","onSuccess","data","onError","error","Error","usePlaceLimitOrder","options","client","queryClient","mutationFn","params","placeLimitOrder","invalidateQueries","queryKey","ordersPrefix","positionsPrefix","useQueryClient","useMutation","useQueryClient","CancelManagedExecutionResponse","useAggClient","invalidateBalanceQueries","invalidatePositionQueries","invalidateUserActivityQueries","executionKeys","UseCancelManagedOrderOptions","onSuccess","data","orderId","onError","error","Error","useCancelManagedOrder","options","client","queryClient","mutationFn","cancelManagedOrder","invalidateQueries","queryKey","ordersPrefix","useQueryClient","useQuery","GetPositionsParams","useAggClient","executionKeys","UsePositionsOptions","enabled","usePositions","options","client","cursor","limit","status","mode","query","queryKey","positions","queryFn","getPositions","staleTime","gcTime","retry","data","nextCursor","hasMore","useCallback","useEffect","useRef","useState","ExecutionStatusOrder","ExecutionStatusResponse","ExecutionStatusStep","WsBalanceUpdate","WsOrderEvent","WsOrderSubmitted","useAggClient","useOnBalanceUpdate","useOnOrderEvent","useOnOrderSubmitted","TERMINAL_ORDER_STATUSES","Set","ORDER_POLL_INTERVAL_MS","mapOrderStatusToTerminalEvent","status","ExecutionTerminalOrderEvent","mergeTerminalOrderEvents","currentEvents","incomingEvents","mergedByOrderId","Map","map","event","orderId","incomingEvent","currentEvent","get","set","timestamp","values","sort","left","right","ExecutionProgressPhase","DagStepProgress","dagRunId","totalSteps","currentSequence","currentStepType","completedSequences","stepTypes","Record","errorReason","venue","filledAmountRaw","remainingAmountRaw","actualSharesRaw","actualToWinRaw","quotedSharesRaw","quotedToWinRaw","executionPriceRaw","quotedPriceRaw","ExecutionStepProgress","ExecutionRawStepProgress","Pick","EXECUTION_STEP_STATUS_RANK","pending","in_progress","failed","completed","skipped","getExecutionStepIdentity","step","groupId","sequence","stepType","orderIds","join","getExecutionGroupAttempt","steps","reduce","highestAttempt","Math","max","attempt","groupExecutionStepsByGroupId","groupedSteps","existingSteps","push","pickExecutionGroupPresentation","groupStatus","label","bridge","mergeExecutionStepProgress","previous","incoming","previousByGroupId","incomingByGroupId","mergedByIdentity","identity","current","groupPresentation","groupIds","keys","previousGroup","incomingGroup","previousStep","incomingStep","isNewerAttempt","shouldUseIncoming","Array","from","localeCompare","mergeRawExecutionStepProgress","mergedBySequence","mergeExecutionStatusOrders","order","Date","updatedAt","getTime","UseExecutionProgressOptions","quoteId","enabled","mode","UseExecutionProgressResult","phase","submittedOrders","latestBalance","dagProgress","terminalOrderEvents","executionSteps","rawExecutionSteps","executionOrders","useExecutionProgress","setPhase","setSubmittedOrders","setLatestBalance","setDagProgress","setTerminalOrderEvents","setExecutionSteps","setRawExecutionSteps","setExecutionOrders","orderIdSetRef","submittedOrderVenueByIdRef","length","handleOrderSubmitted","msg","has","trimmedVenue","trim","prev","handleBalanceUpdate","handleOrderEvent","mappedEvent","resolvedVenue","fallbackErrorReason","undefined","nextTerminalEvent","initialStepTypes","seq","type","Object","entries","Number","startedAt","completedAt","find","toISOString","buildFailedProgress","baseStepTypes","isStatusPolling","isListening","client","terminalOrderIdsRef","pollInFlightRef","buildSubmittedOrdersFromStatus","orders","side","price","size","buildTerminalEventsFromStatus","fallbackOrderIds","fallbackTimestamp","terminalEvents","partialFillReason","filter","terminal","coveredOrderIds","fallbackEvent","overallState","includes","setFatalPollingFailure","message","failedOrderIds","existingByOrderId","now","e","cancelled","timeout","ReturnType","setTimeout","stopPolling","clearTimeout","scheduleNextPoll","delayMs","pollExecutionStatus","Promise","getExecutionStatus","resolvedOrderIds","fromEntries","executionId","nextTerminalEvents","pollAfterMs","error","statusCode","Error","interval","setInterval","clearInterval","reconcile","id","all","res","getExecutionOrders","limit","data","mapped","executionPrice","errorMessage","covered","every","useMutation","useQuery","useQueryClient","CreateBalanceRefillPolicyParams","UpdateBalanceRefillPolicyParams","useAggClient","executionKeys","UseBalanceRefillPoliciesOptions","enabled","useBalanceRefillPolicies","options","client","queryClient","queryKey","balanceRefillPolicies","query","queryFn","getBalanceRefillPolicies","staleTime","refetchInterval","state","data","some","policy","includes","latestAttempt","status","createPolicy","mutationFn","params","createBalanceRefillPolicy","onSuccess","setQueryData","updatePolicy","policyId","updateBalanceRefillPolicy","updated","current","map","id","policies","useQueryClient","PositionGroup","ClosedPositionTotals","totalTraded","amountWon","returnPct","winningOutcomeIds","isPartialWin","computeClosedPositionTotals","group","outcomes","venueMarket","venueMarketOutcomes","isResolved","status","Set","winningCount","settledCount","outcome","avgEntryPrice","totalSize","winner","totalValue","breakdown","venueBreakdown","venueMarketOutcomeId","add","Array","from","useMutation","useQueryClient","RedeemRequest","RedeemResponse","useAggClient","useResolvedExecutionMode","invalidateUserClaimState","RedeemRejectedError","Error","response","constructor","message","name","isLegRejected","status","useRedeem","client","queryClient","executionMode","mutationFn","body","redeem","mode","results","length","every","r","reasons","map","reason","filter","Boolean","join","onSettled","useQueryClient","WsRedeemEvent","useOnRedeemEvent","useOnRedeemEventBase","RedeemEvent","listener","event","useQuery","AggClient","useAggAuthState","useAggClient","executionKeys","CLAIMABLE_COUNT_PAGE_LIMIT","getClaimablePositionsCount","client","Promise","total","cursor","page","getExecutionPositions","status","limit","group","data","redeemStatus","hasMore","nextCursor","undefined","useRedeemEligibleCount","isAuthenticated","query","queryKey","claimablePositionsCount","queryFn","enabled","staleTime","refetchInterval","useEffect","useMemo","useState","WsRedeemEvent","useOnRedeemEvent","RedeemLegLifecycle","status","txHash","errorMessage","RedeemLifecycleState","pending","terminal","allConfirmed","anyFailed","legs","Record","UseRedeemLifecycleInput","redeemId","expectedOutcomeIds","preFailedOutcomeIds","preFailedReasons","preConfirmedOutcomeIds","preConfirmedTxHashes","computeDerivedState","expectedCount","legCount","Object","keys","length","allTerminal","leg","values","seedState","input","id","derived","useRedeemLifecycles","inputs","inputsByRedeemId","map","stateMap","setStateMap","next","entries","prev","changed","existing","event","nextLegs","venueMarketOutcomeId","nextState","useMemo","useRedeemLifecycles","RedeemLifecycleState","UseRedeemLifecycleInput","INITIAL_STATE","pending","terminal","allConfirmed","anyFailed","errorMessage","legs","useRedeemLifecycle","input","inputs","map","redeemId","useContext","AggAuthContext","GeoBlockState","isLocationBlocked","isTradingBlocked","isDepositBlocked","DEFAULT_STATE","useGeoBlock","authContext","process","env","NEXT_PUBLIC_GEO_BLOCK_DISABLE","isBlocked","user","VenueAvailabilityState","normalizeVenueId","venueId","trim","toLowerCase","getDisabledVenueSet","disabledVenues","Set","map","isVenueDisabledByConfig","has","getVisibleVenuesByConfig","id","venues","TVenue","disabledVenueSet","filter","venue","getVisibleVenueIdsByConfig","venueIds","TVenueId","getVenueAvailabilityState","isConfigLoading","isLocationBlocked","Venue","VenueKeyStatus","useQuery","useAggClient","venueKeyQueryKeys","all","const","status","venue","useVenueKeyStatus","enabled","client","queryKey","queryFn","getVenueKeyStatus","useEffect","useRef","useMutation","useQuery","useQueryClient","useAggAuthContext","useAggClient","useResolvedExecutionMode","invalidateBalanceQueries","hostedVenueAccountQueryKeys","all","const","account","venue","userId","mode","useHostedVenueAccount","enabled","client","user","isAuthenticated","executionMode","isResolving","queryClient","id","permitted","queryKey","session","current","assertSession","Error","queryFn","getHostedVenueAccount","staleTime","refetchInterval","refetchIntervalInBackground","retry","provision","mutationFn","request","run","ReturnType","provisionHostedVenueAccount","onSuccess","result","setQueryData","reset","mutate","mutateAsync","isAvailable","useQueryClient","useEffect","useRef","useQuery","useAggAuthContext","useAggClient","useResolvedExecutionMode","hostedVenueAccountQueryKeys","useHostedVenueActivity","venue","page","enabled","client","user","isAuthenticated","executionMode","isResolving","userId","id","permitted","Number","isInteger","session","current","mounted","assertSession","Error","activity","queryKey","all","queryFn","result","getHostedVenueActivity","mode","staleTime","retry","isAvailable","useCallback","useQuery","useAggAuthContext","useAggClient","sharedKycQueryKeys","status","userId","const","useSharedKyc","client","isAuthenticated","user","id","query","queryKey","queryFn","getSharedKycStatus","enabled","staleTime","retry","refetch","refreshStatus","Promise","result","cancelRefetch","error","data","verified","initiateVerification","venue","redirectUri","initiateKyc","isPending","useCallback","UserProfile","useAggAuthContext","UseAggAuthOptions","signMessage","message","Promise","address","chainId","chain","UseAggAuthReturn","isAuthenticated","user","signIn","statement","signOut","isLoading","error","Error","useAggAuth","options","signInWithProvider","useCallback","useState","AggLinkAccountBody","AggLinkAccountConfirmResult","AggLinkAccountResult","AggLinkAccountWalletConfirmBody","useAggClient","UseLinkAccountReturn","startLink","body","Promise","confirmLink","input","isLoading","error","Error","useLinkAccount","client","setIsLoading","setError","run","fn","T","catch","e","err","String","finally","linkAccount","linkAccountConfirm","AUTH_CHOOSER_OPEN_EVENT","AggAuthChooserOpenDetail","highlightMethod","requestAggAuthChooserOpen","detail","window","dispatchEvent","CustomEvent","useInfiniteQuery","useQueries","Category","useAggClient","UseCategoriesOptions","queryKeyScope","parentId","enabled","limit","UseCategoryChildrenOptions","parentIds","useCategories","options","client","query","queryKey","queryFn","pageParam","res","getCategories","cursor","initialPageParam","undefined","getNextPageParam","lastPage","nextCursor","categories","data","pages","flatMap","p","hasNextPage","useCategoryChildren","Array","from","Set","filter","Boolean","queries","map","childrenByParentId","Map","forEach","index","set","isLoading","some","useEffect","useState","useDebouncedValue","value","T","delay","debouncedValue","setDebouncedValue","timeoutId","window","setTimeout","clearTimeout","useInfiniteQuery","GetOrdersQuery","OrderListItem","useAggClient","ExecutionOrderStatusInput","NonNullable","UseExecutionOrdersOptions","Omit","status","enabled","mode","refetchIntervalMs","useExecutionOrders","options","client","orderType","orderId","quoteId","venueMarketIds","limit","venueMarketIdsKey","length","Set","sort","query","queryKey","queryFn","pageParam","getExecutionOrders","cursor","initialPageParam","undefined","getNextPageParam","lastPage","hasMore","nextCursor","refetchInterval","orders","data","pages","flatMap","page","hasNextPage","useQueries","UseQueryResult","GetOrdersQuery","OrderListItem","useMemo","useAggClient","MAX_ORDER_VENUE_MARKET_IDS_PER_REQUEST","DEFAULT_PAGE_LIMIT","DEFAULT_MAX_PAGES_PER_BATCH","UseExecutionOrdersForMarketsOptions","venueMarketIds","ReadonlyArray","status","NonNullable","orderType","mode","limit","maxPagesPerBatch","enabled","UseExecutionOrdersForMarketsResult","orders","isLoading","error","Error","isTruncated","BatchResult","hasMore","combineBatches","results","flatMap","result","data","some","find","chunk","items","T","size","chunks","index","length","push","slice","useExecutionOrdersForMarkets","client","batchKey","Set","sort","join","batches","split","combine","queries","map","batchVenueMarketIds","queryKey","queryFn","Promise","cursor","page","response","getExecutionOrders","nextCursor","undefined","keepPreviousData","useInfiniteQuery","PaginatedResponse","UserActivityItem","UserActivityQuery","UserActivityType","useAggClient","userActivityQueryKeys","UseUserActivityOptions","Omit","enabled","pendingRefetchIntervalMs","DEFAULT_PENDING_REFETCH_INTERVAL_MS","PENDING_ACTIVITY_STATUSES","Set","hasPendingActivity","pages","ReadonlyArray","page","item","data","type","legs","length","every","leg","status","toLowerCase","has","useUserActivity","options","client","limit","query","queryKey","feed","queryFn","pageParam","getUserActivity","cursor","initialPageParam","undefined","getNextPageParam","lastPage","hasMore","nextCursor","placeholderData","refetchInterval","q","state","activities","flatMap","hasNextPage","keepPreviousData","useInfiniteQuery","LeaderboardMetric","LeaderboardRow","PaginatedResponse","useAggClient","LeaderboardPeriod","LEADERBOARD_PERIODS","UseLeaderboardOptions","period","metric","limit","enabled","utcDayKey","d","Date","toISOString","slice","leaderboardRange","now","from","to","spanDays","UTC","getUTCFullYear","getUTCMonth","getUTCDate","leaderboardQueryKeys","all","const","list","LEADERBOARD_STALE_TIME_MS","useLeaderboard","options","client","query","queryKey","queryFn","pageParam","getLeaderboard","cursor","initialPageParam","undefined","getNextPageParam","lastPage","hasMore","nextCursor","placeholderData","staleTime","seen","Set","rows","data","pages","flatMap","page","filter","row","has","userId","add","hasNextPage","UserProfile","useCallback","useState","useAggClient","UseExternalIdOptions","onSuccess","profile","onError","error","Error","UseExternalIdReturn","linkExternalId","assertion","externalId","timestamp","hmac","Promise","isLoading","useExternalId","options","client","onErrorCb","setIsLoading","setError","err","resolvedError","String","useInfiniteQuery","GetPositionsQuery","PositionGroup","useAggClient","executionKeys","UseExecutionPositionsOptions","Omit","enabled","mode","useExecutionPositions","options","client","limit","status","query","queryKey","positions","queryFn","pageParam","getExecutionPositions","cursor","initialPageParam","undefined","getNextPageParam","lastPage","hasMore","nextCursor","data","pages","flatMap","page","hasNextPage","isAggApiError","isServer","QueryObserverOptions","ReadRetryOptions","Pick","MAX_TIMER_DELAY_MS","hint","error","Error","undefined","value","retryAfterMs","Number","isSafeInteger","withReadRetry","options","retry","failureCount","retryDelay","attempt","Math","min","MAX_TIMER_DELAY_MS","ChartBarsMeta","ChartBarsResponse","WsCandleInterval","WsTrade","MarketChartCandle","time","open","high","low","close","mean","volume","source","MarketChartVenueData","venue","outcomeIds","candles","liveCandle","lineValue","lastTrade","lastUpdateTs","MarketChartData","delivery","marketId","primaryVenue","interval","startTs","endTs","venues","Record","MAX_CACHE_RETENTION_SECONDS","getIntervalSeconds","createVenueData","undefined","pruneCandlesBefore","cutoffTs","firstKeptIndex","length","slice","promoteClosedLiveCandle","expectedCandleTime","promoted","some","candle","sortCandles","resolveMaxLastUpdateTs","max","venueData","Object","values","sort","left","right","_upsertFinalCandle","nextCandle","index","findIndex","nextCandles","createMarketChartData","params","response","data","map","Math","floor","t","o","h","l","c","Number","isFinite","v","const","lastCandle","venueMarketOutcomeId","meta","mergeMarketChartData","datasets","Array","from","Set","flatMap","dataset","reduce","acc","entries","existingVenueData","find","MarketChartMidpointUpdate","outcomeId","midpoint","timestamp","applyMidpointToMarketChart","update","targetVenueEntry","includes","targetVenueName","currentVenue","intervalSeconds","promotedCandles","min","nextVenues","applyTradeToMarketChart","trade","price","size","loadImmutableHistory","isAggApiError","AggClient","AggWebSocket","ChartBarsResponse","ChartHistoryManifest","ChartCandle","ChartDeliveryError","Error","constructor","state","NonNullable","retryAfterMs","name","usable","response","data","length","meta","withActualFreshness","serverTime","Number","isFinite","Date","now","lastBarOpenTime","at","t","staleSeconds","Math","max","fetchChartHistory","client","socket","request","Parameters","signal","AbortSignal","onInitial","Promise","readBars","params","getChartBars","decode","text","decodeHistory","throwIfAborted","venueMarketOutcomeId","preferImmutableHistory","verified","manifest","history","getChartHistoryManifest","complete","loadHistory","filter","bar","from","to","error","aborted","status","fullyCovered","finalizedThrough","initial","venue","resolution","tail","countBack","undefined","incomplete","includes","isAggApiError","MarketChartData","ChartDeliveryError","MAX_TIMER_DELAY_MS","notBefore","WeakMap","validDelay","value","Number","isSafeInteger","record","query","delay","set","Math","min","MAX_SAFE_INTEGER","Date","now","delete","chartRetryRemaining","max","get","chartRefetchInterval","interval","remaining","waitForDeadline","signal","AbortSignal","Promise","throwIfAborted","resolve","reject","aborted","clearTimeout","timer","removeEventListener","reason","setTimeout","addEventListener","once","runChartQuery","load","T","data","delivery","complete","includes","state","retryAfterMs","undefined","error","Candle","LiveSnapshot","MarketChartCandle","MarketChartData","closedCaches","WeakMap","key","candles","toChart","candle","time","openTime","open","o","high","h","low","l","close","c","volume","v","source","overlayCandleTail","history","live","rolling","tail","interval","venue","venues","primaryVenue","endTs","Date","now","last","at","Infinity","closed","filter","map","join","cached","get","length","set","forming","lastSourceTime","Math","max","orderbook","timestamp","trades","lastUpdateTs","Number","isFinite","liveCandle","lineValue","lastTrade","useEffect","useMemo","useAggWebSocket","UseMarketDataSubscriptionOptions","marketId","additionalMarketIds","enabled","orderbook","trades","useMarketDataSubscription","ws","allIds","ids","Set","add","id","stableKey","join","length","unsubscribers","Array","unsub","subscribe","push","ChartBarsMeta","WsCandleInterval","keepPreviousData","useQueries","useQueryClient","withReadRetry","useAggClient","useAggUiConfig","useAggWebSocket","useAggWebSocketConnectionState","createMarketChartData","mergeMarketChartData","MarketChartData","marketDataKeys","runChartQuery","chartRefetchInterval","ChartDeliveryError","fetchChartHistory","useLiveStates","overlayCandleTail","useMarketDataSubscription","UseMarketChartOptions","marketId","venueMarketIds","visibleVenue","liveOutcomeIds","interval","startTs","endTs","countBack","enabled","live","refetchIntervalMs","staleTimeMs","rangeKey","MarketChartAvailability","Partial","state","NonNullable","complete","UseMarketChartResult","availability","Record","data","isLoading","error","Error","isLive","refetch","Promise","useMarketChartQueries","options","client","queryClient","socket","isConnected","features","enableLiveUpdates","resolvedRangeKey","liveEnabled","outcomeIds","ids","Set","add","venueMarketId","sort","primaryOutcomeId","find","Boolean","isQueryEnabled","length","subscribedIds","filter","id","includes","subscribedPrimaryId","additionalMarketIds","orderbook","trades","queries","map","outcomeId","queryKey","chart","queryFn","signal","AbortSignal","owner","getQueryCache","exact","response","venueMarketOutcomeId","resolution","from","undefined","to","initial","aborted","setQueryData","meta","chartWindow","chartEndTs","staleTime","query","gcTime","refetchOnWindowFocus","retry","failureCount","retryDelay","_attempt","retryAfterMs","Math","min","max","placeholderData","refetchInterval","refetchIntervalInBackground","liveStates","overlaid","index","forEach","sameOutcome","metadata","delivery","pending","isPlaceholderData","isFetching","Object","values","venues","some","venue","candles","liveCandle","UseMarketChartsResult","charts","errors","useMarketCharts","String","all","useMarketChart","successfulDatasets","flatMap","datasets","hasPendingQuery","firstError","isInRange","candle","time","hasVisibleHistory","entries","venueName","useQueryClient","useEffect","useMemo","useReducer","useRef","CandleBuilder","useAggWebSocket","getOrCreateBuilder","useLiveMarketStores","venueMarketIds","ws","forceRender","c","subsRef","Map","unsub","unlisten","stableKey","slice","sort","join","length","current","desired","Set","id","sub","has","delete","builder","subscribe","onChange","set","clear","map","useMemo","Candle","CandleInterval","mergeCandles","mergeClosedCandles","VenueMarket","useMarketChart","useLiveMarketStores","LiveCandle","time","o","h","l","c","v","venue","source","UseLiveCandlesOptions","market","interval","mode","startTs","endTs","UseLiveCandlesResult","candles","liveCandle","isLoading","candleToLive","openTime","useLiveCandles","options","venueMarketIds","id","ids","matchedVenueMarkets","m","push","builders","restMarketId","marketId","data","chartData","enabled","liveData","length","closed","forming","getClosed","getForming","map","b","byTime","Map","venueEntries","Object","values","venues","venueData","set","open","high","low","close","volume","merged","Array","from","sort","a","useCallback","useMemo","CandleInterval","VenueMarket","useLiveCandles","LiveCandle","ScaledCandlePoint","time","open","high","low","close","v","UseLiveCandleOverlayOptions","market","interval","mode","startTs","endTs","enabled","scale","UseLiveCandleOverlayResult","liveCandle","scaledCandles","lineValue","live","isLoading","timeRangeToInterval","range","useLiveCandleOverlay","options","candles","rawCandles","rawLive","scaleCandle","candle","o","h","l","c","map","length","useEffect","useMemo","VenueMarket","useAggUiConfig","useAggWebSocket","extractSelectedOutcomeIds","selectedMarket","ids","Set","outcome","venueMarketOutcomes","id","add","matched","matchedVenueMarkets","sort","useEventOrderbookData","venueMarkets","selectedMarketId","ws","features","enableLiveUpdates","length","find","m","selectedOutcomeIds","selectedKey","join","unsubscribers","map","subscribe","unsub","OrderbookLevel","OrderbookState","OutcomeOrderbookResponse","VenueOrderbookLevel","orderbookTimestampSeconds","timestamp","outcomeOrderbookToState","response","marketId","venue","orderbook","midpoint","spread","seq","checksum","venueMarketOutcomeId","attribute","l","price","size","venues","venueLevels","outcomeId","bids","map","asks","venueOrderbooks","bestBid","bestAsk","Orderbook","AggregatedOrderbookResponse","OrderbookState","MarketOrderbookIntegrity","MarketOrderbookData","marketId","orderbook","venueOrderbooks","venues","midpoint","spread","timestamp","snapshotVersion","seq","checksum","matchedMarkets","integrity","truncateLevels","price","size","levels","T","depth","slice","Math","max","truncateVenueOrderbooks","Object","fromEntries","entries","map","venue","book","bids","asks","createMarketOrderbookDataFromResponse","response","venueMarketId","undefined","aggregateVenueLevels","side","levelsByPrice","Map","Record","level","currentLevel","get","set","values","sort","left","right","createMarketOrderbookDataFromVenueOrderbooks","floor","Date","now","bestBid","bestAsk","createMarketOrderbookDataFromState","state","options","marketOrderbookDataToResponse","data","marketOrderbookDataToState","withOrderbookIntegrity","applyOrderbookDepth","computeChecksum","AggClient","OutcomeOrderbookResponse","MarketLiveStore","outcomeOrderbookToState","SOCKET_GRACE_MS","REST_BUDGET_MS","MAX_SEED_AGE_MS","hasFreshSnapshot","store","id","now","Date","state","get","orderbook","integrity","timestamp","createOrderbookSnapshotQuery","client","Pick","ids","socketHealthy","context","signal","AbortSignal","Promise","Record","fetchSnapshotQuery","bind","selectOrderbookSnapshots","length","Error","missing","filter","aborted","resolve","unsubscribe","finish","clearTimeout","timer","removeEventListener","setTimeout","subscribe","addEventListener","once","requested","initialStates","Map","map","controller","AbortController","abort","response","getOutcomeOrderbooks","venueMarketOutcomeIds","Object","fromEntries","data","flatMap","book","index","venueMarketOutcomeId","Number","isFinite","isSafeInteger","seq","isInteger","checksum","snapshot","bids","asks","every","level","price","size","projectedChecksum","snapshotChecksum","current","live","initial","initialBook","orderbookSnapshotVersion","sameGeneration","isConnected","orderbookGeneration","connectionGeneration","update","previous","orderbookError","error","useQuery","useQueryClient","VenueMarket","useAggWebSocket","useAggWebSocketConnectionState","useAggClient","useAggUiConfig","outcomeOrderbookToState","applyOrderbookDepth","createMarketOrderbookDataFromState","MarketOrderbookData","getMarketLiveStore","useLiveStates","createOrderbookSnapshotQuery","useMarketDataSubscription","createMarketLiveState","UseMarketOrderbookVenueOutcome","venue","venueMarketOutcomeId","UseMarketOrderbookOptions","marketId","depth","enabled","venueOutcomes","live","UseMarketOrderbookResult","data","dataById","Record","isLoading","error","Error","isLive","refetch","Promise","useMarketOrderbook","options","queryClient","client","ws","isConnected","features","enableLiveUpdates","selectedId","liveEnabled","outcomeIds","map","v","filter","Boolean","subscriptionIds","length","Set","selectedOutcomeId","additionalMarketIds","slice","orderbook","store","liveQueries","sortedIds","sort","preferSocket","every","id","get","connectionGeneration","seedQuery","queryKey","queryFn","staleTime","gcTime","refetchOnWindowFocus","retry","liveStates","subscriptionId","index","peek","seededOrderbooks","liveBook","seed","bids","asks","primaryOrderbook","primarySnapshotVersion","orderbookSnapshotVersion","snapshotVersion","Object","fromEntries","flatMap","hasAnyOrderbook","some","seedLoading","liveOrderbookErrorMessage","find","liveState","orderbookError","forEach","update","previous","resnapshot","useQueryClient","OrderbookState","WsTrade","useAggUiConfig","useAggWebSocketConnectionState","useLiveStates","useMarketOrderbook","UseLiveMarketResult","orderbook","trades","isConnected","integrity","outcomeOrderbookToState","useLiveMarket","canonicalMarketId","features","enableLiveUpdates","connected","snapshot","venueMarketOutcomeId","enabled","live","data","useMemo","useRef","VenueMarket","useLiveStates","useAggUiConfig","MarketLiveState","EMPTY_PRICES","Map","buildMidpointFingerprint","outcomeIds","queries","Array","data","parts","i","length","midpoint","orderbook","push","join","useLiveOutcomePrices","venueMarkets","features","enableLiveUpdates","ids","Set","vm","outcome","venueMarketOutcomes","id","add","ref","matchedVenueMarketOutcomes","venueMarketOutcomeId","sort","fingerprint","prevRef","prices","current","liveByOutcomeId","state","set","outcomeId","liveMidpoint","get","findLivePriceById","livePrices","findLivePriceForLabel","label","normalizedLabel","trim","toLowerCase","sum","count","price","undefined","useMemo","useRef","VenueMarket","useLiveStates","useAggUiConfig","MarketLiveState","LiveBestPrices","ReadonlyMap","bestBid","bestAsk","LiveBestPriceCandidate","bestBidVenue","bestAskVenue","midpoint","midpointVenue","updatedAt","LiveBestPriceCandidates","EMPTY","Map","EMPTY_CANDIDATES","extractOutcomeBestPrices","state","ob","orderbook","bids","price","asks","undefined","buildFingerprint","outcomeIds","queries","Array","data","parts","i","length","bid","ask","push","join","useLiveBestPrices","venueMarkets","features","enableLiveUpdates","ids","Set","vm","outcome","venueMarketOutcomes","id","add","ref","matchedVenueMarketOutcomes","venueMarketOutcomeId","sort","fingerprint","prevRef","result","current","perOutcome","best","set","size","refs","group","map","groupBestAsk","groupBestBid","entry","get","prev","nextBid","nextAsk","mergeBestPricesPreferringLive","rest","live","merged","liveEntry","pickSideVenue","venues","Record","level","side","bestVenue","bestValue","venue","info","Object","entries","value","wins","bestSize","Infinity","extractOutcomeBestCandidate","candidate","bidLevel","askLevel","midVenue","timestamp","buildLiveBestPriceCandidates","states","groupBestAskVenue","groupBestBidVenue","groupUpdatedAt","next","buildCandidateFingerprint","mid","ts","keys","useLiveBestPriceCandidates","_","WsTrade","useAggUiConfig","useLiveMarket","useMarketDataSubscription","useLiveTrades","canonicalMarketId","features","enableLiveUpdates","trades","marketId","enabled","Boolean","orderbook","MidpointItem","VenueMarket","useQuery","useMemo","useAggClient","useAggUiConfig","UseMidpointsOptions","maxMidpointIdsPerRequest","UseMidpointsResult","prices","Map","bestMidpointsByOutcomeId","currentMidpointsByOutcomeId","venueByOutcomeId","bestPrices","bestBid","bestAsk","bestPriceVenuesByOutcomeId","bestBidVenue","bestAskVenue","isLoading","bestMidpoint","bestMidpointVenue","normalizeVenueMarketIds","venueMarkets","ids","Set","market","id","add","sibling","matchedVenueMarkets","sort","left","right","localeCompare","EMPTY_MIDPOINTS_POLL_MS","EMPTY_MIDPOINTS_MAX_FETCHES","hasUsableMidpoint","item","midpoint","outcomes","some","outcome","isMidpointResponseComplete","data","primaryVenueMarketIds","itemByMarketId","map","venueMarketId","every","get","normalizeOutcomeLabel","label","trim","toLowerCase","normalizeSemanticOutcomeLabel","normalizedLabel","outcomeMatchesSemanticSide","title","leftCandidates","value","filter","Boolean","rightCandidates","candidate","includes","resolveBestMidpointCandidateOutcomeIds","length","candidateIds","venueMarketOutcomes","yesOutcome","find","push","firstOutcomeId","resolveSiblingOutcomeMidpoint","matched","ref","venueMarketOutcomeId","venue","m","sibOutcome","o","resolveSemanticFallbackMidpoint","marketById","best","siblingMarket","siblingOutcome","extractBestPrices","venuesByOutcome","setEntry","outcomeId","next","prev","merged","set","prevVenues","mergedVenues","has","refs","matchedVenueMarketOutcomes","group","entry","venues","useMidpoints","options","client","configuredMaxMidpointIdsPerRequest","bestMidpointCandidateOutcomeIds","queryKey","queryFn","getMidpoints","bestPrice","enabled","staleTime","query","state","Infinity","refetchInterval","dataUpdateCount","gcTime","refetchOnMount","refetchOnWindowFocus","refetchOnReconnect","result","currentMap","venueMap","bestVenue","sib","fallback","normalizeVenueMarketIds","WsCandleInterval","useEffect","useMemo","useState","ChartTimeRange","getIntervalSeconds","timeRangeToInterval","UseRollingChartWindowOptions","range","interval","tickMs","nowMs","RollingChartWindow","rangeSeconds","intervalSeconds","nowSec","endTs","startTs","refetchIntervalMs","RANGE_SECONDS_BY_RANGE","Record","ALL","rangeToSeconds","resolveRollingWindow","params","Math","ceil","useRollingChartWindow","options","optionsNowMs","Date","now","setNowSec","floor","handle","setInterval","clearInterval","useEffect","useRef","useState","WsArbFeedBatch","WsArbMarketUpdate","useAggWebSocket","UseMarketArbResult","arbReturn","isLive","UseArbFeedResult","byMarket","Map","byEvent","MarketArbState","ArbFeedState","arb","eventId","useMarketArb","marketId","ws","state","setState","cached","getArb","off","subscribeArb","msg","EMPTY_ARB_FEED","useArbFeed","stateRef","current","subscribeArbFeed","batch","prev","nextByMarket","entry","entries","set","venueEventId","nextByEvent","values","get","publicByMarket","Orderbook","VenueMarketOutcome","VenueMarket","AggClient","AggregatedOrderbookResponse","keepPreviousData","useQuery","useAggClient","marketOrderbookDataToResponse","useMarketOrderbook","OrderbookResult","market","outcome","orderbook","UseOrderBookOptions","orderbooks","enabled","canonicalMarketId","fetchBatchBookQuery","client","venueMarketIds","signal","AbortSignal","getOrderbooks","createBatchBookQuery","bind","useOrderBook","options","requestedVenueMarketIds","Set","map","id","canonicalResult","marketId","length","venueOutcomes","venue","venueMarketOutcomeId","undefined","batchedResult","queryKey","const","queryFn","staleTime","gcTime","refetchOnWindowFocus","retry","placeholderData","data","canonicalData","merged","flatMap","venueBook","venueOrderbooks","bids","asks","liveBooksByMarketId","Map","filter","item","status","venueMarketId","index","get","aggregated","error","isLoading","Error","String","results","isLive","OrderbookQuoteResponse","keepPreviousData","useQuery","useAggClient","createMarketOrderbookDataFromVenueOrderbooks","marketDataKeys","useDebouncedValue","UseOrderbookQuoteOptions","marketId","side","size","enabled","UseOrderbookQuoteResult","data","isLoading","isFetching","error","Error","QUOTE_DEBOUNCE_MS","createUnavailableOrderbookError","message","code","retryable","status","undefined","quoteVenueOrderbooks","requestedSize","venueOrderbooks","Record","bids","Array","price","asks","marketData","levels","orderbook","remaining","fillsByVenue","Map","cost","level","venue","venueSize","Object","entries","venues","fillSize","Math","min","fillCost","existing","get","set","filledSize","max","totalCost","values","reduce","sum","fill","avgPrice","slippage","midpoint","fills","map","useOrderbookQuote","options","client","debouncedSize","shouldFetch","query","queryKey","orderbookQuote","const","queryFn","response","getOrderbooks","venueMarketIds","item","find","entry","venueMarketId","fromEntries","staleTime","gcTime","retry","placeholderData","String","useQuery","OrderListQuery","TradeExecutorOrder","useAggClient","UseOrdersOptions","enabled","useOrders","options","client","userId","status","limit","offset","query","queryKey","queryFn","getOrders","orders","data","total","MarketStatus","VenueEvent","QueryClient","QueryClientContext","keepPreviousData","useInfiniteQuery","useContext","useEffect","useState","withReadRetry","AggClientContext","UseSearchOptions","q","type","categoryIds","status","limit","enabled","deep","mode","useSearch","options","client","queryClient","fallbackQueryClient","isEnabled","length","undefined","mount","unmount","Error","queryKey","join","effectiveQueryClient","retryOptions","defaultQueryOptions","query","queryFn","pageParam","signal","res","search","T","cursor","initialPageParam","getNextPageParam","lastPage","hasMore","nextCursor","placeholderData","data","pages","flatMap","page","isLoading","isError","error","hasNextPage","fetchNextPage","isFetchingNextPage","isPlaceholderData","QueryClient","MarketStatus","VenueEvent","useCallback","useState","useDebouncedValue","useSearch","UseMarketSearchOptions","type","categoryIds","status","limit","debounceMs","enableSuggestions","minLength","useMarketSearch","options","query","setQueryState","submittedQuery","setSubmittedQuery","debouncedQuery","trimmedDebounced","trim","suggestionsEnabled","length","suggestionsQuery","T","q","enabled","mode","submittedQ","resultsQuery","setQuery","value","submit","target","clear","suggestions","data","isLoading","isError","error","results","hasNextPage","fetchNextPage","isFetchingNextPage","SmartRouteResponse","THIN_SMART_ROUTE_REFETCH_INTERVAL_MS","SMART_ROUTE_REFRESH_DEADLINE_BUFFER_MS","SMART_ROUTE_MIN_REFETCH_INTERVAL_MS","SMART_ROUTE_MAX_REFETCH_INTERVAL_MS","SMART_ROUTE_HIGH_SLIPPAGE_BPS","SMART_ROUTE_SHALLOW_TOP_LEVEL_RATIO","SMART_ROUTE_DEEP_FILL_LEVEL_COUNT","LIQUIDITY_CONSTRAINED_STATUSES","Set","THIN_LIQUIDITY_WARNING_PATTERN","ThinSmartRouteLiquidityReason","SmartRouteThinLiquidityAssessment","isThin","reasons","ResolveSmartRouteRefetchIntervalArgs","data","defaultIntervalMs","aggressiveIntervalMs","adaptive","isDocumentVisible","isEditing","isInputValid","isMarketOpen","isPanelActive","isSubmitting","queryEnabled","resolveMsUntilIsoTimestamp","value","nowMs","parsedValue","Date","parse","Number","isFinite","clampIntervalToRefreshDeadline","intervalMs","refreshAt","msUntilRefresh","Math","min","max","floor","assessThinSmartRouteLiquidity","quote","now","has","status","add","slippage","slippageBps","hasShallowTopLevel","fills","some","fill","length","venueQty","topLevelSize","size","hasDeepFillLevels","hasThinWarning","warnings","warning","test","reason","resolveSmartRouteRefetchInterval","args","isActivelyViewingQuote","primaryUsesProphetx","venue","deadlines","quoteRefreshNotBefore","quoteFailure","retryAt","filter","map","undefined","defaultInterval","thinLiquidity","ExecutionMode","SmartRouteResponse","SmartRouteSide","keepPreviousData","useQuery","useAggClient","resolveSmartRouteRefetchInterval","SMART_ROUTE_STALE_TIME_MS","UseSmartRouteOptions","venueMarketOutcomeId","venueMarketId","outcomeId","side","tradeSide","mode","maxSpend","sellShares","chainBalances","Record","slipCapBps","compareVenues","sellCacheScope","accountId","positionVersion","balanceCacheScope","balanceVersion","balanceKey","deepEstimate","enabled","staleTimeMs","refreshContext","isPanelActive","isEditing","isMarketOpen","isSubmitting","SmartRouteLoadingReason","UseSmartRouteResult","data","isLoading","isFetching","error","Error","refetch","Promise","loadingReason","getIsDocumentVisible","document","visibilityState","useSmartRoute","options","client","resolvedVenueMarketOutcomeId","hasValidInput","queryEnabled","query","queryKey","JSON","stringify","const","queryFn","signal","getSmartRoute","undefined","staleTime","refetchInterval","queryState","state","adaptive","defaultIntervalMs","isDocumentVisible","isInputValid","gcTime","refetchOnWindowFocus","refetchIntervalInBackground","retry","placeholderData","isPlaceholderData","String","getIsDocumentVisible","BatchOrderbooksResponse","ExecutionMode","SmartRouteResponse","Venue","keepPreviousData","useQueries","useQuery","useAggClient","resolveSmartRouteRefetchInterval","SMART_ROUTE_STALE_TIME_MS","UseSmartRouteOptions","LimitOrderVenueQuoteRequest","venue","venueMarketOutcomeId","venueMarketId","UseLimitOrderVenueQuotesOptions","requests","tradeSide","amount","marketId","accountId","chainBalances","Record","mode","slipCapBps","enabled","staleTimeMs","refreshContext","LimitOrderVenueQuoteResult","request","data","tickSize","sizeStepRaw","minSizeRaw","isLoading","isFetching","error","Error","refetch","Promise","UseLimitOrderVenueQuotesResult","quotes","isMetadataPending","getIsDocumentVisible","document","visibilityState","MAX_ORDERBOOK_METADATA_MARKET_IDS","getUniqueVenueRequests","requestsByVenue","Map","has","set","values","sort","left","right","localeCompare","resolveLimitOrderTickSizesByVenue","response","tickSizes","setTickSize","Number","isFinite","item","entry","Object","entries","venueOrderbooks","tick","market","matchedMarkets","requestedMarket","LimitOrderSizeRules","resolveLimitOrderSizeRulesByVenue","rulesByVenue","setRules","useLimitOrderVenueQuotes","options","client","uniqueRequests","hasValidInput","hasRequiredAccount","Boolean","queryEnabled","serializedChainBalances","JSON","stringify","metadataMarketIds","Set","flatMap","slice","tickMetadataQuery","queryKey","const","queryFn","signal","AbortSignal","getOrderbooks","venueMarketIds","staleTime","gcTime","refetchOnWindowFocus","retry","queries","map","getSmartRoute","maxSpend","sellShares","allowedVenues","placeholderData","refetchInterval","queryState","state","defaultIntervalMs","isDocumentVisible","isEditing","isInputValid","isMarketOpen","isPanelActive","isSubmitting","refetchIntervalInBackground","tickSizesByVenue","sizeRulesByVenue","query","index","queryError","get","String","isPending","some","quote","find","all","getIsDocumentVisible","getUniqueVenueRequests","ExecutionMode","SmartRouteResponse","Venue","useQueries","useAggClient","resolveSmartRouteRefetchInterval","SMART_ROUTE_STALE_TIME_MS","UseSmartRouteOptions","VenueSellQuoteRequest","venue","requestedSellShares","sellShares","availableShares","UseVenueSellQuotesOptions","venueMarketOutcomeId","accountId","positionVersion","requests","mode","slipCapBps","enabled","staleTimeMs","refreshContext","VenueSellQuoteResult","request","data","isLoading","isFetching","error","Error","refetch","Promise","UseVenueSellQuotesResult","quotes","getIsDocumentVisible","document","visibilityState","getUniqueVenueRequests","requestsByVenue","Map","has","set","values","sort","left","right","localeCompare","useVenueSellQuotes","options","client","uniqueRequests","queries","map","hasValidInput","queryEnabled","queryKey","allowedVenues","compareVenues","tradeSide","const","queryFn","signal","AbortSignal","getSmartRoute","staleTime","refetchInterval","queryState","state","adaptive","defaultIntervalMs","isDocumentVisible","isEditing","isInputValid","isMarketOpen","isPanelActive","isSubmitting","gcTime","refetchOnWindowFocus","refetchIntervalInBackground","retry","query","index","queryError","String","some","quote","find","all","useInfiniteQuery","Venue","useAggClient","UseUserHoldingsOptions","venue","venueMarketId","venueEventId","enabled","limit","useUserHoldings","options","client","query","queryKey","queryFn","pageParam","getUserHoldings","cursor","initialPageParam","undefined","getNextPageParam","lastPage","nextCursor","holdings","data","pages","flatMap","p","hasNextPage","MarketStatus","AggClient","RecurringCryptoDuration","RecurringCryptoVenueMarket","RecurringCryptoWindowMarket","useQuery","useAggClient","VenueEventWithMarkets","RESOLVING_POLL_INTERVAL_MS","FALLBACK_VENUE_EVENT_PAGE_LIMIT","FALLBACK_VENUE_EVENT_MAX_PAGES","FALLBACK_TARGET_WINDOW_COUNT","TIMELINE_FUTURE_WINDOWS","RECURRING_MARKET_STATUSES","open","closed","resolved","unopened","paused","RECURRING_DURATION_MS","Record","PT5M","PT15M","PT30M","PT1H","PT4H","P1D","RECURRING_SLUG_DURATION","RECURRING_DURATION_AGG_KEY_SEGMENT","Partial","RECURRING_CRYPTO_SLUG_PATTERN","RECURRING_CRYPTO_AGG_KEY_PATTERN","RECURRING_CRYPTO_DAILY_AGG_KEY_PATTERN","RecurringCryptoIdentity","asset","duration","windowStart","RecurringCryptoMarketInstance","id","windowEnd","status","venueEventId","venueMarketId","venue","RecurringCryptoTimeline","all","visible","ended","live","upcoming","viewed","UseRecurringCryptoMarketsOptions","event","enabled","isRecurringCryptoDuration","value","Object","prototype","hasOwnProperty","call","parseTimestamp","timestamp","Date","parse","Number","isFinite","hasCryptoCategory","categories","some","category","name","displayName","trim","toLowerCase","resolveWindowStartFromEnd","end","endDate","venueMarkets","map","market","find","startDate","parseAggKeyWindowStart","match","RegExpMatchArray","year","monthIndex","day","hour","minute","UTC","parsed","getUTCFullYear","getUTCMonth","getUTCDate","getUTCHours","getUTCMinutes","resolveRecurringCryptoIdentity","slugMatch","slug","durationSegment","epochSeconds","parsedEpochSeconds","isSafeInteger","toUpperCase","aggKeyMatch","aggKey","dailyAggKeyMatch","recurrence","mergeWindowMarkets","current","incoming","marketsById","Map","forEach","set","values","mergeRecurringCryptoWindows","windows","windowsById","windowMarket","existing","get","markets","sort","left","right","selectNavigableMarket","navigableMarkets","filter","priceSource","resolveRecurringCryptoTimeline","now","flatMap","startsAt","endsAt","endedMarkets","Infinity","length","slice","defaultVisible","index","findIndex","candidate","viewedStart","viewedEnd","marketToReplace","fetchRecurringCryptoPage","client","options","NonNullable","Parameters","signal","AbortSignal","listRecurringCryptoMarkets","includeOrderbookPrices","includeReferencePrices","includeDirectVenueMarkets","limit","createEmptyPriceComparison","count","min","max","spread","spreadBps","byVenue","normalizeFallbackVenueEvent","identity","candidateIdentity","venueMarket","toISOString","quoteAsset","externalEventId","externalIdentifier","externalMarketId","question","routeable","splitOrdersAllowed","outcomes","venueMarketOutcomes","outcome","venueMarketOutcomeId","externalOutcomeId","label","title","midpoint","bestBid","bestAsk","markSource","lastKnownPrice","orderbookDepth","metrics","volume","volume24h","openInterest","liquidity","resolution","sourceName","sourceUrl","sourceDomain","rawCriteria","confidence","referencePrice","raw","decimals","normalized","provider","providerMarketId","comparisons","outcomePrices","up","down","formatCanonicalRecurringAggKey","date","isNaN","getTime","twoDigits","String","padStart","join","fetchCanonicalAggKeyWindows","Promise","durationMs","currentWindowStart","Math","floor","windowStarts","Set","aggKeys","response","getVenueEvents","venues","data","fetchFallbackVenueEventWindows","categoryIds","responses","seenCursors","cursor","page","sortBy","sortDir","endDateFrom","push","nextCursor","hasMore","undefined","has","add","flat","fetchRecurringCryptoMarkets","anchorStart","queryAssets","canonicalAggKeyWindowsPromise","catch","timelineStart","timelineEnd","anchorInTimeline","anchorOptions","assets","durations","window","windowStartFrom","windowStartTo","anchorResponse","anchor","timelineVenues","canonicalAggKeyWindows","unscopedAnchorResponse","matchingWindow","viewedWindow","recurringCryptoTransitionPollInterval","timeline","useRecurringCryptoMarkets","isEnabled","query","queryKey","queryFn","staleTime","gcTime","refetchOnWindowFocus","refetchOnReconnect","refetchOnMount","refetchInterval","queryState","state","retry","isRecurringCryptoMarket","MarketStatus","MarketStatus","useQuery","useAggClient","VenueEventWithMarkets","resolveRecurringCryptoIdentity","UseVenueEventOptions","eventId","enabled","cluster","minVolume","RESOLUTION_POLL_MS","RESOLUTION_POLL_MAX_PAST_END_MS","resolutionPollInterval","event","now","Date","isRecurringCryptoMarket","status","resolved","closed","eventEndsAt","endDate","parse","Number","NaN","paused","isFinite","shouldPoll","venueMarkets","some","market","endsAt","getTime","open","useVenueEvent","options","client","query","queryKey","queryFn","signal","getVenueEventById","staleTime","gcTime","refetchOnWindowFocus","refetchOnReconnect","refetchOnMount","refetchInterval","state","data","retry","undefined","MarketStatus","MarketStatus","MatchStatus","Venue","QueryClient","QueryClientContext","useInfiniteQuery","useContext","useEffect","useState","AggClientContext","UseVenueMarketsOptions","venue","venueEventId","cluster","search","status","matchStatus","aggKey","sportsMarketType","period","marketCategory","marketGroup","limit","fetchAll","enabled","sortBy","sortDir","context","projection","minVolume","useVenueMarkets","options","client","queryClient","fallbackQueryClient","undefined","mount","unmount","Error","query","queryKey","join","queryFn","pageParam","signal","res","getVenueMarkets","cursor","initialPageParam","getNextPageParam","lastPage","hasMore","nextCursor","markets","data","pages","flatMap","page","hasNextPage","fetchNextPage","isFetchingNextPage","QueryClient","MarketStatus","VenueMarket","useMemo","VenueEventWithMarkets","useVenueEvent","UseVenueEventOptions","useVenueMarkets","mergeEventWithFullMarkets","event","fullMarkets","length","fullById","Map","map","m","id","ordering","venueMarkets","mergedMarkets","minimal","get","UseEnrichedVenueEventOptions","progressive","projection","minVolume","useEnrichedVenueEvent","options","isLoading","error","rest","eventEndedAt","endDate","Number","isFinite","Date","parse","shouldFetchOnlyOpenMarkets","now","openQuery","venueEventId","eventId","cluster","enabled","status","open","undefined","limit","fetchAll","markets","openMarkets","isEnrichingOpenMarkets","shouldFetchAllMarketsFallback","fallbackQuery","fallbackMarkets","isEnrichingFallbackMarkets","activeQuery","isEnriching","enrichedEvent","hasMoreMarkets","hasNextPage","loadMoreMarkets","fetchNextPage","isLoadingMoreMarkets","isFetchingNextPage","MarketStatus","MarketStatus","MatchStatus","Venue","RecurrenceFilter","QueryClient","QueryClientContext","keepPreviousData","useInfiniteQuery","useContext","useEffect","useMemo","useRef","useState","AggClientContext","VenueEventWithMarkets","UseVenueEventsOptions","queryKeyScope","venues","search","categoryIds","matchStatus","status","sortBy","sortDir","recurrence","enabled","limit","minVolume","minYesPrice","maxYesPrice","endDateFrom","grouped","initialPages","useVenueEvents","options","client","queryClient","fallbackQueryClient","undefined","mount","unmount","Error","query","queryKey","join","queryFn","pageParam","signal","res","getVenueEvents","cursor","initialPageParam","getNextPageParam","lastPage","hasMore","nextCursor","placeholderData","prefetchedRef","current","isLoading","isFetching","isError","isPlaceholderData","pagesLoaded","data","pages","length","hasNextPage","fetchNextPage","events","flatMap","page","loadedPageCount","QueryClient","SportsLiveResponse","SportsLiveState","useQuery","useAggClient","SportsGameStatus","SportsLiveParticipant","SPORTS_LIVE_POLL_INTERVAL_MS","SPORTS_SCHEDULED_POLL_INTERVAL_MS","sportsLiveQueryKey","sortedEventIds","const","sportsLiveRefetchInterval","response","data","some","state","status","useSportsLive","eventIds","enabled","client","Set","map","eventId","trim","filter","Boolean","sort","query","queryKey","queryFn","signal","Promise","getSportsLive","length","refetchInterval","queryState","refetchIntervalInBackground","refetchOnWindowFocus","states","stateByEventId","Map","missingEventIds","BatchMidpointsResponse","MidpointRow","keepPreviousData","useQuery","useAggClient","useAggUiConfig","normalizeVenueMarketIds","venueMarketIds","Set","map","venueMarketId","trim","filter","Boolean","sort","left","right","localeCompare","mapMidpointsByVenueMarketId","rows","Array","matched","Map","mappedMidpoints","forEach","row","set","midpoint","matchedRow","has","mapArbReturnByVenueMarketId","mappedArbReturns","arbReturn","UseVenueMarketMidpointsOptions","enabled","maxMidpointIdsPerRequest","useVenueMarketMidpoints","options","client","market","configuredMaxMidpointIdsPerRequest","requestedVenueMarketIds","query","queryKey","length","const","queryFn","signal","data","getMidpoints","bestPrice","staleTime","gcTime","refetchOnWindowFocus","retry","placeholderData","midpointRows","midpointsByVenueMarketId","arbReturnByVenueMarketId","VenueMarket","MIN_PRICE_GAP_PCT","MAX_PRICE_GAP_PCT","PriceGapValue","ComputePriceGapsOptions","markets","midpointsByVenueMarketId","ReadonlyMap","normalizeMidpoint","value","Number","isFinite","undefined","collectMarketMidpoints","market","midpoints","marketMidpoint","get","id","push","matchedMarket","matchedVenueMarkets","matchedMidpoint","computePriceGapPct","length","minMidpoint","Math","min","maxMidpoint","max","gapPct","computePriceGaps","Map","gapsByVenueMarketId","set","useEffect","useMemo","useRef","useState","VenueMarket","useAggClient","useAggUiConfig","CachedMidpoint","venue","ownOutcomes","Map","matched","Array","venueMarketId","outcomes","MidpointRowWithMatches","venueMarketOutcomeId","midpoint","buildOutcomeMidpointMap","m","o","set","resolveUncachedVisibleMarketIds","visibleMarkets","cache","inFlightIds","Set","seen","idsToFetch","consider","id","has","add","push","market","sibling","matchedVenueMarkets","buildCachedMidpointEntries","requestedVenueMarketIds","rows","rowsByVenueMarketId","map","item","nextCacheEntries","get","sib","UseViewportMidpointsOptions","maxMidpointIdsPerRequest","useViewportMidpoints","options","prices","venueByOutcomeId","client","configuredMaxMidpointIdsPerRequest","setCache","inFlightRef","visibleRef","current","visibleFp","sort","join","toFetch","length","cancelled","getMidpoints","bestPrice","then","resp","data","prev","next","entry","catch","finally","delete","venueMap","ownVenue","outcome","venueMarketOutcomes","best","bestVenue","ref","matchedVenueMarketOutcomes","find","sibMidpoint","useCallback","useEffect","useRef","useState","UseVisibleIdsOptions","rootMargin","threshold","UseVisibleIdsResult","visibleIds","Set","register","id","el","Element","useVisibleIds","options","setVisibleIds","observerRef","IntersectionObserver","elementsRef","Map","elementIdRef","WeakMap","callbackRefsRef","observer","entries","prev","changed","next","entry","current","get","target","isIntersecting","has","add","delete","values","observe","disconnect","existing","callback","unobserve","curr","set","useCallback","useEffect","useState","useAggAuthContext","useResolvedExecutionMode","STORAGE_KEY","isBrowser","window","seenKey","userId","hasSeen","localStorage","getItem","markSeen","setItem","UsePaperOnboardingResult","isOpen","dismiss","usePaperOnboarding","isPaperMode","isResolving","isAuthenticated","user","id","dismissed","setDismissed","seen","setSeen","Boolean","useQuery","VenueMarket","useAggClient","UseSettlementDetailsDataOptions","eventId","market","Pick","enabled","needsEvent","needsMarket","useSettlementDetailsData","options","client","eventQuery","queryKey","appId","queryFn","signal","getVenueEventById","staleTime","gcTime","retry","marketQuery","id","Error","response","getVenueMarkets","venue","venueEventId","undefined","externalIdentifier","limit","projection","selected","data","find","candidate","markets","useEffect","useRef","useState","useMutation","useQuery","useQueryClient","HostedVenueWithdrawal","HostedVenueWithdrawalRequest","useAggAuthContext","useAggClient","useResolvedExecutionMode","hostedVenueAccountQueryKeys","invalidateBalanceQueries","Journal","request","withdrawalId","Environment","validRequest","value","row","mode","test","requestId","amountRaw","destinationAddress","undefined","useHostedVenueTransfers","accountId","environment","client","user","isAuthenticated","executionMode","isResolving","queryClient","userId","id","permitted","scope","JSON","stringify","storageKey","entry","setEntry","ready","journal","invalid","session","current","mounted","dispatching","intent","assertSession","Error","save","next","localStorage","setItem","assertResult","result","invalidate","invalidateQueries","queryKey","account","deposit","mutationFn","getHostedVenueDepositAddress","retry","withdrawal","getHostedVenueWithdrawal","withdrawHostedVenue","status","queryFn","enabled","refetchInterval","query","state","data","refetchIntervalInBackground","resetDeposit","reset","resetWithdrawal","text","getItem","parse","terminal","isAvailable","storageError","isError","submit","const","crypto","randomUUID","mutateAsync","check","clear","removeItem","useQueryClient"],"sources":["../src/current-user-query.ts","../src/core/providers/auth-utils.ts","../src/core/providers/auth-provider.tsx","../src/use-resolved-execution-mode.ts","../src/core/providers/balance-provider.tsx","../src/core/providers/client-provider.tsx","../src/use-app-config.ts","../src/core/providers/execution-mode-provider.tsx","../src/core/providers/event-list-state-context.tsx","../src/core/ui-config/constants.ts","../src/core/ui-config/storage.ts","../src/core/ui-config/theme-utils.ts","../src/core/providers/event-trading-context.tsx","../src/core/providers/ui-provider.tsx","../src/core/providers/agg-provider.tsx","../src/execution/use-execute-managed.ts","../src/execution/use-place-limit-order.ts","../src/execution/use-cancel-managed-order.ts","../src/execution/use-positions.ts","../src/execution/use-execution-progress.ts","../src/execution/use-balance-refill-policies.ts","../src/execution/compute-closed-position-totals.ts","../src/execution/use-redeem.ts","../src/execution/use-on-redeem-event.ts","../src/execution/use-redeem-eligible-count.ts","../src/execution/use-redeem-lifecycles.ts","../src/execution/use-redeem-lifecycle.ts","../src/use-geo-block.ts","../src/venue-availability.ts","../src/use-venue-key-status.ts","../src/use-hosted-venue-account.ts","../src/use-hosted-venue-activity.ts","../src/use-shared-kyc.ts","../src/use-agg-auth.ts","../src/use-link-account.ts","../src/auth-chooser-events.ts","../src/use-categories.ts","../src/use-debounced-value.ts","../src/use-execution-orders.ts","../src/use-execution-orders-for-markets.ts","../src/use-user-activity.ts","../src/use-leaderboard.ts","../src/use-external-id.ts","../src/use-execution-positions.ts","../src/read-retry.ts","../src/market-data/chart-cache.ts","../src/market-data/chart-history.ts","../src/market-data/chart-retry-gate.ts","../src/market-data/chart-tail.ts","../src/market-data/subscription.ts","../src/use-market-chart.ts","../src/use-live-market-stores.ts","../src/use-live-candles.ts","../src/use-live-candle-overlay.ts","../src/use-event-orderbook-data.ts","../src/market-data/orderbook-snapshot.ts","../src/market-data/orderbook-cache.ts","../src/market-data/snapshot-selection.ts","../src/use-market-orderbook.ts","../src/use-live-market.ts","../src/use-live-outcome-prices.ts","../src/use-live-best-prices.ts","../src/use-live-trades.ts","../src/use-midpoints.ts","../src/use-rolling-chart-window.ts","../src/use-arb.ts","../src/use-order-book.ts","../src/use-orderbook-quote.ts","../src/use-orders.ts","../src/use-search.ts","../src/use-market-search.ts","../src/smart-route-refresh-policy.ts","../src/use-smart-route.ts","../src/use-limit-order-venue-quotes.ts","../src/use-venue-sell-quotes.ts","../src/use-user-holdings.ts","../src/use-recurring-crypto-markets.ts","../src/use-venue-event.ts","../src/use-venue-markets.ts","../src/use-enriched-venue-event.ts","../src/use-venue-events.ts","../src/use-sports-live.ts","../src/use-venue-market-midpoints.ts","../src/utils/compute-price-gaps.ts","../src/use-viewport-midpoints.ts","../src/use-visible-ids.ts","../src/use-paper-onboarding.ts","../src/use-settlement-details-data.ts","../src/use-hosted-venue-transfers.ts"],"sourcesContent":["import type { UserProfile, AggClient } from \"@agg-build/sdk\";\nimport type { QueryClient } from \"@tanstack/react-query\";\n\nexport const CURRENT_USER_QUERY_KEY = [\"current-user\"] as const;\nexport const CURRENT_USER_STALE_TIME_MS = 60_000;\n\nexport const getCurrentUserQueryKey = (\n queryKeyScope: string = CURRENT_USER_QUERY_KEY[0],\n): [string] => {\n return [queryKeyScope];\n};\n\nexport const fetchCurrentUserProfile = (\n queryClient: QueryClient,\n client: AggClient,\n queryKey = CURRENT_USER_QUERY_KEY,\n): Promise<UserProfile> => {\n return queryClient.fetchQuery({\n queryKey,\n queryFn: () => client.getCurrentUser(),\n staleTime: CURRENT_USER_STALE_TIME_MS,\n });\n};\n","import type {\n UserProfile,\n AggAuthStartBody,\n AggAuthStartResult,\n AggClientSessionInput,\n} from \"@agg-build/sdk\";\nimport { AccountType, AccountProvider, TurnstileChallengeError } from \"@agg-build/sdk\";\nimport type { AggAuthSignInOptions } from \"./types\";\n\nexport interface BrowserAuthLocation {\n domain: string;\n uri: string;\n}\n\nexport interface AuthCallbackTokens {\n accessToken: string;\n refreshToken: string;\n tokenType?: string;\n userId?: string;\n}\n\ntype AuthCodeExchangeResult = {\n accessToken: string;\n refreshToken?: string;\n user: UserProfile;\n};\n\ntype WalletAuthResult = {\n accessToken: string;\n refreshToken?: string;\n user: UserProfile;\n};\n\ntype WalletAuthClient = {\n authStart: (body: AggAuthStartBody) => Promise<AggAuthStartResult>;\n buildSiweMessage: (params: {\n address: string;\n chainId?: number;\n domain: string;\n issuedAt?: string;\n nonce: string;\n statement?: string;\n uri: string;\n }) => string;\n buildSiwsMessage: (params: {\n address: string;\n chainId?: string;\n domain: string;\n issuedAt?: string;\n nonce: string;\n statement?: string;\n uri: string;\n }) => string;\n verify: (args: { message: string; signature: string }) => Promise<WalletAuthResult>;\n};\n\ntype AuthCallbackClient = {\n exchangeAuthCode: (code: string) => Promise<AuthCodeExchangeResult>;\n};\n\ntype LinkConfirmCallbackClient = {\n linkAccountConfirm: (token: string) => Promise<unknown>;\n};\n\nexport const createPlaceholderUserProfile = (input: { id: string }): UserProfile => {\n return {\n id: input.id,\n username: null,\n avatarUrl: null,\n externalId: null,\n isLocationBlocked: false,\n venueAccounts: null,\n accounts: [],\n wallets: [],\n };\n};\n\nexport const createWalletSessionUser = (input: { address: string; id: string }): UserProfile => {\n return {\n ...createPlaceholderUserProfile({ id: input.id }),\n accounts: [\n {\n type: AccountType.siwe,\n provider: AccountProvider.wallet,\n providerAccountId: input.address,\n },\n ],\n };\n};\n\nexport const getBrowserAuthLocation = (): BrowserAuthLocation => {\n if (typeof window === \"undefined\") {\n return {\n domain: \"localhost\",\n uri: \"http://localhost\",\n };\n }\n\n return {\n domain: window.location.host,\n uri: window.location.origin,\n };\n};\n\nconst resolveAuthCallbackUrl = (callbackUrl?: string | URL): URL | null => {\n return callbackUrl instanceof URL\n ? callbackUrl\n : typeof callbackUrl === \"string\"\n ? new URL(\n callbackUrl,\n typeof window === \"undefined\" ? \"http://localhost\" : window.location.origin,\n )\n : typeof window === \"undefined\"\n ? null\n : new URL(window.location.href);\n};\n\nexport const parseAuthCallbackCode = (callbackUrl?: string | URL): string | null => {\n const resolvedUrl = resolveAuthCallbackUrl(callbackUrl);\n return resolvedUrl?.searchParams.get(\"code\") ?? null;\n};\n\nexport const parseLinkConfirmToken = (callbackUrl?: string | URL): string | null => {\n const resolvedUrl = resolveAuthCallbackUrl(callbackUrl);\n return resolvedUrl?.searchParams.get(\"link_confirm_token\") ?? null;\n};\n\nconst AUTH_METHOD_IDS = [\"siwe\", \"siws\", \"google\", \"twitter\", \"apple\", \"email\"] as const;\ntype AggAuthMethodId = (typeof AUTH_METHOD_IDS)[number];\n\nconst EXISTING_METHOD_NAMES = { email: \"an email link\", google: \"Google\", apple: \"Apple\" } as const;\n\nexport class AggIdentityExistsError extends Error {\n readonly code = \"identity_exists\";\n constructor(\n message: string,\n readonly existingMethod: \"email\" | \"google\" | \"apple\",\n readonly attemptedMethod: AggAuthMethodId,\n ) {\n super(message);\n this.name = \"AggIdentityExistsError\";\n }\n}\n\nconst IDENTITY_EXISTS_PARAMS = [\"error\", \"message\", \"existing_method\", \"attempted_method\"];\n\nexport const parseAuthCallbackIdentityExists = (\n callbackUrl?: string | URL,\n): AggIdentityExistsError | null => {\n const params = resolveAuthCallbackUrl(callbackUrl)?.searchParams;\n if (params?.get(\"error\") !== \"identity_exists\") return null;\n\n const existingMethod = params.get(\"existing_method\");\n if (existingMethod !== \"email\" && existingMethod !== \"google\" && existingMethod !== \"apple\") {\n return null;\n }\n const attemptedMethod = AUTH_METHOD_IDS.find((id) => id === params.get(\"attempted_method\"));\n if (!attemptedMethod) return null;\n\n // The `message` query param is attacker-controllable; never display it.\n const name = EXISTING_METHOD_NAMES[existingMethod];\n return new AggIdentityExistsError(\n `You've signed in with ${name} before. Please continue with ${name}.`,\n existingMethod,\n attemptedMethod,\n );\n};\n\nexport const getAuthCallbackCleanupPath = (callbackUrl?: string | URL): string | null => {\n const resolvedUrl = resolveAuthCallbackUrl(callbackUrl);\n if (!resolvedUrl) return null;\n\n const params = new URLSearchParams(resolvedUrl.search);\n params.delete(\"code\");\n params.delete(\"link_confirm_token\");\n if (params.get(\"error\") === \"identity_exists\") {\n for (const name of IDENTITY_EXISTS_PARAMS) params.delete(name);\n }\n const search = params.toString();\n\n return `${resolvedUrl.pathname}${search ? `?${search}` : \"\"}`;\n};\n\nexport const exchangeAuthCallbackCode = async (\n client: AuthCallbackClient,\n callbackUrl?: string | URL,\n): Promise<{ cleanupPath: string | null; user: UserProfile } | null> => {\n const code = parseAuthCallbackCode(callbackUrl);\n if (!code) return null;\n\n const result = await client.exchangeAuthCode(code);\n\n return {\n cleanupPath: getAuthCallbackCleanupPath(callbackUrl),\n user: result.user,\n };\n};\n\n/**\n * Confirm an account-link round-trip. After `linkAccount()` → provider OAuth, the\n * browser lands back on `redirectUrl` with a `?link_confirm_token=` param; this\n * exchanges it for the persisted Account row. Returns null when no link token is\n * present (not a link callback). Throws (HTTP 409) when the identity is already\n * linked to a DIFFERENT principal — the caller surfaces it as the callback error;\n * `already_linked_same` (same principal) resolves idempotently.\n */\nexport const confirmLinkAccountCallback = async (\n client: LinkConfirmCallbackClient,\n callbackUrl?: string | URL,\n): Promise<{ cleanupPath: string | null } | null> => {\n const token = parseLinkConfirmToken(callbackUrl);\n if (!token) return null;\n\n await client.linkAccountConfirm(token);\n\n return { cleanupPath: getAuthCallbackCleanupPath(callbackUrl) };\n};\n\nexport const parseAuthCallbackTokens = (callbackUrl?: string | URL): AuthCallbackTokens | null => {\n const resolvedUrl = resolveAuthCallbackUrl(callbackUrl);\n if (!resolvedUrl) return null;\n\n const hash = resolvedUrl.hash.startsWith(\"#\") ? resolvedUrl.hash.slice(1) : resolvedUrl.hash;\n if (!hash) return null;\n\n const params = new URLSearchParams(hash);\n const accessToken = params.get(\"access_token\");\n const refreshToken = params.get(\"refresh_token\");\n\n if (!accessToken || !refreshToken) return null;\n\n const userId = params.get(\"user_id\") ?? undefined;\n const tokenType = params.get(\"token_type\") ?? undefined;\n\n return {\n accessToken,\n refreshToken,\n tokenType,\n userId,\n };\n};\n\nexport const createAuthCallbackSession = (tokens: AuthCallbackTokens): AggClientSessionInput => {\n return {\n accessToken: tokens.accessToken,\n refreshToken: tokens.refreshToken,\n user: tokens.userId ? createPlaceholderUserProfile({ id: tokens.userId }) : undefined,\n };\n};\n\nexport const executeWalletAuthFlow = async (input: {\n client: WalletAuthClient;\n location?: BrowserAuthLocation;\n options: AggAuthSignInOptions;\n}): Promise<WalletAuthResult> => {\n const address = input.options.address.trim();\n const chain = input.options.chain ?? \"ethereum\";\n const provider = chain === \"solana\" ? \"siws\" : \"siwe\";\n const location = input.location ?? getBrowserAuthLocation();\n const startResult = await input.client.authStart({\n provider,\n ...(input.options.turnstileToken ? { turnstileToken: input.options.turnstileToken } : {}),\n });\n\n if (startResult.type === \"challenge_required\") {\n if (!startResult.siteKey) {\n throw new Error(\"Server returned challenge_required but no siteKey was provided.\");\n }\n // Throw a typed error so the auth package can catch it, render the Turnstile\n // widget, and retry with the resulting token.\n throw new TurnstileChallengeError(startResult.siteKey);\n }\n\n if (startResult.type !== \"nonce\") {\n throw new Error(`AGG auth start returned an unexpected \"${startResult.type}\" response`);\n }\n\n const message =\n chain === \"solana\"\n ? input.client.buildSiwsMessage({\n domain: location.domain,\n address,\n uri: location.uri,\n nonce: startResult.nonce,\n chainId: typeof input.options.chainId === \"string\" ? input.options.chainId : \"mainnet\",\n statement: startResult.statement ?? input.options.statement,\n })\n : input.client.buildSiweMessage({\n domain: location.domain,\n // Any casing: `buildSiweMessage` applies the EIP-55 checksum itself.\n address,\n uri: location.uri,\n nonce: startResult.nonce,\n chainId: typeof input.options.chainId === \"number\" ? input.options.chainId : undefined,\n statement: startResult.statement ?? input.options.statement,\n });\n\n const signature = await input.options.signMessage(message);\n const result = await input.client.verify({ message, signature });\n\n return {\n accessToken: result.accessToken,\n refreshToken: result.refreshToken,\n user: createWalletSessionUser({\n id: result.user.id,\n address,\n }),\n };\n};\n","import type { UserProfile, AggClient } from \"@agg-build/sdk\";\nimport { QueryClient, QueryClientContext } from \"@tanstack/react-query\";\nimport { useCallback, useContext, useEffect, useMemo, useState, type ReactNode } from \"react\";\nimport { fetchCurrentUserProfile } from \"../../current-user-query\";\nimport {\n confirmLinkAccountCallback,\n createAuthCallbackSession,\n exchangeAuthCallbackCode,\n executeWalletAuthFlow,\n getAuthCallbackCleanupPath,\n parseAuthCallbackIdentityExists,\n parseAuthCallbackTokens,\n} from \"./auth-utils\";\nimport { AggAuthContext, AggClientContext } from \"./contexts\";\nimport type { AggAuthContextValue, AggAuthSignInOptions } from \"./types\";\n\ninterface AuthSnapshot {\n isAuthenticated: boolean;\n user: UserProfile | undefined;\n}\n\nconst getClientAuthSnapshot = (client: AggClient | null): AuthSnapshot => {\n return {\n isAuthenticated: client?.isAuthenticated ?? false,\n user: client?.user,\n };\n};\n\ninterface AggAuthProviderProps {\n children: ReactNode;\n}\n\nconst toError = (value: unknown): Error => {\n return value instanceof Error ? value : new Error(String(value));\n};\n\nconst replaceAuthCallbackUrl = (cleanupPath: string | null): void => {\n if (!cleanupPath || typeof window === \"undefined\") return;\n window.history.replaceState(null, \"\", cleanupPath);\n};\n\nexport function AggAuthProvider({ children }: AggAuthProviderProps): React.JSX.Element {\n const client = useContext(AggClientContext);\n const queryClientFromContext = useContext(QueryClientContext);\n const fallbackQueryClient = useMemo(() => new QueryClient(), []);\n const queryClient =\n queryClientFromContext && \"fetchQuery\" in queryClientFromContext\n ? queryClientFromContext\n : fallbackQueryClient;\n const snapshot = getClientAuthSnapshot(client);\n const [isAuthenticated, setIsAuthenticated] = useState(snapshot.isAuthenticated);\n const [user, setUser] = useState<UserProfile | undefined>(snapshot.user);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const isWeb3User = useMemo<boolean>(() => {\n const accounts = user?.accounts;\n if (!Array.isArray(accounts)) return true;\n return accounts.some((account) => {\n const provider = String(account.provider ?? \"\").toLowerCase();\n return provider === \"wallet\" || provider === \"solana_wallet\";\n });\n }, [user]);\n\n const refreshCurrentUser = useCallback(\n async (targetClient: AggClient): Promise<UserProfile> => {\n const fullUser = await fetchCurrentUserProfile(queryClient, targetClient);\n setIsAuthenticated(true);\n setUser(fullUser);\n return fullUser;\n },\n [queryClient],\n );\n\n useEffect(() => {\n const state = getClientAuthSnapshot(client);\n setIsAuthenticated(state.isAuthenticated);\n setUser(state.user);\n setIsLoading(false);\n setError(null);\n\n if (!client) return;\n\n if (state.isAuthenticated) {\n // Token already in memory — validate it and hydrate the full profile.\n refreshCurrentUser(client).catch(() => {\n client.clearAccessToken();\n });\n } else if (client.authStatus === \"unknown\") {\n // Bootstrap hint found but no token in memory — attempt silent refresh.\n // This succeeds with cookie-refresh delivery (HttpOnly cookie carries the refresh token).\n // With body delivery the refresh token is lost on reload and this safely falls through to unauthenticated.\n client\n .refreshAccessToken()\n .then(() => refreshCurrentUser(client))\n .catch(() => {\n client.clearAccessToken();\n });\n }\n }, [client, refreshCurrentUser]);\n\n useEffect(() => {\n if (!client) return;\n\n return client.onAuthStateChange((authenticated) => {\n setIsAuthenticated(authenticated);\n setUser(client.user);\n if (!authenticated) {\n setIsLoading(false);\n setError(null);\n }\n });\n }, [client]);\n\n const signIn = useCallback(\n async (options: AggAuthSignInOptions): Promise<void> => {\n if (!client) {\n const missingClientError = new Error(\"Agg client is not configured in <AggProvider>\");\n setError(missingClientError);\n throw missingClientError;\n }\n\n const address = options.address.trim();\n if (!address) {\n const missingAddressError = new Error(\"Wallet address is required\");\n setError(missingAddressError);\n throw missingAddressError;\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n const result = await executeWalletAuthFlow({\n client,\n options: {\n ...options,\n address,\n },\n });\n\n client.setSession(result);\n setIsAuthenticated(true);\n setUser(result.user);\n await refreshCurrentUser(client);\n } catch (signInError) {\n const resolvedError = toError(signInError);\n setError(resolvedError);\n throw resolvedError;\n } finally {\n setIsLoading(false);\n }\n },\n [client, refreshCurrentUser],\n );\n\n const startAuth = useCallback<AggAuthContextValue[\"startAuth\"]>(\n async (options) => {\n if (!client) {\n const missingClientError = new Error(\"Agg client is not configured in <AggProvider>\");\n setError(missingClientError);\n throw missingClientError;\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n return await client.authStart(options);\n } catch (startAuthError) {\n const resolvedError = toError(startAuthError);\n setError(resolvedError);\n throw resolvedError;\n } finally {\n setIsLoading(false);\n }\n },\n [client],\n );\n\n const setSession = useCallback<AggAuthContextValue[\"setSession\"]>(\n async (session) => {\n if (!client) {\n const missingClientError = new Error(\"Agg client is not configured in <AggProvider>\");\n setError(missingClientError);\n throw missingClientError;\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n client.setSession(session);\n const resolvedUser = await refreshCurrentUser(client);\n setIsAuthenticated(true);\n setUser(resolvedUser);\n return resolvedUser;\n } catch (sessionError) {\n client.clearAccessToken();\n setIsAuthenticated(false);\n setUser(undefined);\n const resolvedError = toError(sessionError);\n setError(resolvedError);\n throw resolvedError;\n } finally {\n setIsLoading(false);\n }\n },\n [client, refreshCurrentUser],\n );\n\n const handleAuthCallback = useCallback<AggAuthContextValue[\"handleAuthCallback\"]>(\n async (callbackUrl) => {\n if (!client) {\n const missingClientError = new Error(\"Agg client is not configured in <AggProvider>\");\n setError(missingClientError);\n throw missingClientError;\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n const identityError = parseAuthCallbackIdentityExists(callbackUrl);\n if (identityError) {\n if (callbackUrl === undefined) {\n replaceAuthCallbackUrl(getAuthCallbackCleanupPath(callbackUrl));\n }\n throw identityError;\n }\n\n const exchangedSession = await exchangeAuthCallbackCode(client, callbackUrl);\n if (exchangedSession) {\n const resolvedUser = await refreshCurrentUser(client);\n\n if (callbackUrl === undefined) {\n replaceAuthCallbackUrl(exchangedSession.cleanupPath);\n }\n\n return resolvedUser;\n }\n\n // Account-link callback: the caller was already authenticated and just\n // authorized a provider — confirm the link and refresh, don't re-session.\n const confirmedLink = await confirmLinkAccountCallback(client, callbackUrl);\n if (confirmedLink) {\n const resolvedUser = await refreshCurrentUser(client);\n\n if (callbackUrl === undefined) {\n replaceAuthCallbackUrl(confirmedLink.cleanupPath);\n }\n\n return resolvedUser;\n }\n\n const tokens = parseAuthCallbackTokens(callbackUrl);\n if (!tokens) return null;\n\n client.setSession(createAuthCallbackSession(tokens));\n setIsAuthenticated(client.isAuthenticated);\n setUser(client.user);\n const resolvedUser = await refreshCurrentUser(client);\n\n if (callbackUrl === undefined) {\n replaceAuthCallbackUrl(getAuthCallbackCleanupPath(callbackUrl));\n }\n\n return resolvedUser;\n } catch (callbackError) {\n const resolvedError = toError(callbackError);\n setError(resolvedError);\n throw resolvedError;\n } finally {\n setIsLoading(false);\n }\n },\n [client, refreshCurrentUser],\n );\n\n const signOut = useCallback(async (): Promise<void> => {\n await client?.signOut();\n setIsAuthenticated(false);\n setUser(undefined);\n setError(null);\n }, [client]);\n\n const clearError = useCallback((): void => {\n setError(null);\n }, []);\n\n const value = useMemo<AggAuthContextValue>(() => {\n return {\n isAuthenticated,\n isWeb3User,\n user,\n isLoading,\n error,\n signIn,\n startAuth,\n setSession,\n handleAuthCallback,\n signOut,\n clearError,\n };\n }, [\n clearError,\n error,\n handleAuthCallback,\n isAuthenticated,\n isWeb3User,\n isLoading,\n setSession,\n signIn,\n signOut,\n startAuth,\n user,\n ]);\n\n return <AggAuthContext.Provider value={value}>{children}</AggAuthContext.Provider>;\n}\n","import { useContext } from \"react\";\nimport type { AppTradingMode } from \"@agg-build/sdk\";\nimport { useAggUiConfig } from \"./core/provider\";\nimport { AggExecutionModeContext } from \"./core/providers/contexts\";\n\nexport interface UseResolvedExecutionModeResult {\n /**\n * The mode every execution surface must trade against. Once `/app/config`\n * resolves this is the server's value, unconditionally.\n */\n executionMode: AppTradingMode;\n /** Convenience for the common branch. */\n isPaperMode: boolean;\n /**\n * True while `/app/config` is still in flight, so the value above is a\n * locally-configured guess rather than the server's answer. Surfaces that\n * render mode-specific chrome (a paper badge, a hidden Limit tab, hidden\n * deposit controls) should hold or skeleton until this is false — otherwise\n * a paper app briefly paints live chrome, and vice versa.\n */\n isResolving: boolean;\n}\n\n/**\n * Resolve the app's execution mode with the server as the source of truth.\n *\n * Paper/live is an app-level setting owned by the partner admin (SNA-2964);\n * end users cannot change it, and a partner's own `trading.executionMode`\n * provider config cannot override it. That local value survives only as the\n * pre-resolution guess and as the answer for callers running without a\n * reachable `/app/config`.\n *\n * The API enforces the same decision independently — a client that ignores\n * this hook still cannot place a live order against a paper app.\n */\nexport function useResolvedExecutionMode(\n /**\n * Per-surface `executionMode` prop, where one exists (`EventMarketPage`,\n * `UserProfilePage`, `PlaceOrder`, …). Kept for source compatibility and\n * honoured only BEFORE the server answers — an app-level mode cannot be\n * overridden per surface, so the documented \"live panel inside a paper app\"\n * pattern no longer applies.\n */\n override?: AppTradingMode,\n): UseResolvedExecutionModeResult {\n // Read from context, never fetch here: a surface rendered under a bare\n // <AggUiProvider> (Storybook, tests, hand-composed partner layouts) has no\n // client to fetch with, and must degrade to local config instead of throwing.\n const serverConfig = useContext(AggExecutionModeContext);\n const tradingMode = serverConfig?.tradingMode;\n const isLoading = serverConfig?.isLoading ?? false;\n const {\n trading: { executionMode: configuredExecutionMode },\n } = useAggUiConfig();\n\n // Precedence, highest first: server → per-surface prop → provider config →\n // live. The server wins the moment it has spoken; everything below it only\n // exists to keep first paint from flashing the wrong chrome.\n const localMode = override ?? configuredExecutionMode;\n const executionMode: AppTradingMode = tradingMode ?? (localMode === \"paper\" ? \"paper\" : \"live\");\n\n return {\n executionMode,\n isPaperMode: executionMode === \"paper\",\n isResolving: tradingMode === undefined && isLoading,\n };\n}\n","import type { UnifiedBalanceResponse, Venue } from \"@agg-build/sdk\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport { useCallback, useContext, useMemo, type ReactNode } from \"react\";\nimport { balanceQueryKeys } from \"../../execution/balance-invalidation\";\nimport { useResolvedExecutionMode } from \"../../use-resolved-execution-mode\";\nimport { resolveAggUiLabels } from \"../ui-config/labels\";\nimport { AggAuthContext, AggBalanceContext, AggClientContext } from \"./contexts\";\nimport type { AggBalanceBreakdownItem, AggBalanceContextValue } from \"./types\";\n\nconst CHAIN_LABELS: Record<number, string> = {\n 0: \"Paper\",\n 1: \"Ethereum\",\n 10: \"Optimism\",\n 56: \"BNB\",\n 137: \"Polygon\",\n 1337: \"Hyperliquid\",\n 8453: \"Base\",\n 42161: \"Arbitrum\",\n 43114: \"Avalanche\",\n 11155111: \"Sepolia\",\n 792703809: \"Solana\",\n};\n\nconst chainLabelFromId = (chainId: number): string => {\n return CHAIN_LABELS[chainId] ?? `Chain ${chainId}`;\n};\n\nconst toTokenUnits = (raw: string, decimals: number): number => {\n const numeric = Number(raw);\n if (!Number.isFinite(numeric)) return 0;\n return numeric / 10 ** decimals;\n};\n\nconst isUsdBasedToken = (tokenSymbol: string): boolean => {\n return tokenSymbol?.toUpperCase()?.includes(\"USD\");\n};\n\nconst EMPTY_MANAGED_BALANCES: UnifiedBalanceResponse = {\n cash: [],\n positions: [],\n};\n\ninterface AggBalanceProviderProps {\n children: ReactNode;\n}\n\nexport function AggBalanceProvider({ children }: AggBalanceProviderProps): React.JSX.Element {\n const client = useContext(AggClientContext);\n const authContext = useContext(AggAuthContext);\n // App-level paper/live, server-owned. Reading local ui-config here would\n // leave a paper app fetching live balances for its header chips and\n // profile totals.\n const { executionMode } = useResolvedExecutionMode();\n\n if (!authContext) {\n throw new Error(\"AggBalanceProvider must be used within an <AggAuthProvider>\");\n }\n\n const { isAuthenticated } = authContext;\n const queryExecutionMode = executionMode === \"paper\" ? \"paper\" : undefined;\n\n const balancesQuery = useQuery({\n queryKey: balanceQueryKeys.provider(queryExecutionMode),\n queryFn: async (): Promise<UnifiedBalanceResponse> => {\n if (!client || !isAuthenticated) {\n return EMPTY_MANAGED_BALANCES;\n }\n\n return client.getManagedBalances(\n queryExecutionMode ? { mode: queryExecutionMode } : undefined,\n );\n },\n enabled: Boolean(client && isAuthenticated),\n staleTime: 60 * 1000,\n // A matched fill can precede settlement and the API's next balance snapshot.\n // Keep visible clients converging even if that first invalidation reads old cash.\n refetchInterval: queryExecutionMode === \"paper\" ? false : 5_000,\n refetchIntervalInBackground: false,\n refetchOnWindowFocus: \"always\",\n refetchOnReconnect: \"always\",\n });\n\n const managedBalancesData = balancesQuery.data;\n const managedBalances = useMemo(\n () => managedBalancesData ?? EMPTY_MANAGED_BALANCES,\n [managedBalancesData],\n );\n const connectedVenues = useMemo(() => {\n return Array.from(new Set(managedBalances.positions.map((position) => position.venue))).sort(\n (a, b) => a.localeCompare(b),\n ) as Venue[];\n }, [managedBalances.positions]);\n // A failed background refetch must not replace a previously loaded balance\n // snapshot with a fatal error state. React Query keeps the cached data usable\n // while it retries (including after an automatic access-token refresh).\n const balancesError = managedBalancesData === undefined ? balancesQuery.error : null;\n const isBalancesLoading = balancesQuery.isLoading;\n const refetchBalances = balancesQuery.refetch;\n\n const totalBalance = useMemo((): number => {\n const cash = managedBalances.cash;\n return cash.reduce((sum, token) => {\n if (!isUsdBasedToken(token.tokenSymbol)) return sum;\n const tokenAcrossChains = token.chains.reduce(\n (chainSum, chain) =>\n chainSum + toTokenUnits(chain.balanceRaw, chain.decimals ?? token.decimals),\n 0,\n );\n return sum + tokenAcrossChains;\n }, 0);\n }, [managedBalances]);\n\n const availableBalance = useMemo((): number => {\n return managedBalances.cash.reduce((sum, token) => {\n if (!isUsdBasedToken(token.tokenSymbol)) return sum;\n if (token.availableRaw != null) {\n return sum + toTokenUnits(token.availableRaw, token.decimals);\n }\n return (\n sum +\n token.chains.reduce(\n (chainSum, chain) =>\n chainSum +\n toTokenUnits(chain.availableRaw ?? chain.balanceRaw, chain.decimals ?? token.decimals),\n 0,\n )\n );\n }, 0);\n }, [managedBalances]);\n\n const reservedBalance = useMemo((): number => {\n return managedBalances.cash.reduce((sum, token) => {\n if (!isUsdBasedToken(token.tokenSymbol)) return sum;\n if (token.reservedRaw != null) {\n return sum + toTokenUnits(token.reservedRaw, token.decimals);\n }\n return (\n sum +\n token.chains.reduce(\n (chainSum, chain) =>\n chainSum + toTokenUnits(chain.heldRaw ?? \"0\", chain.decimals ?? token.decimals),\n 0,\n )\n );\n }, 0);\n }, [managedBalances]);\n\n const buildBalanceBreakdown = useCallback(\n (rawForChain: (chain: UnifiedBalanceResponse[\"cash\"][number][\"chains\"][number]) => string) => {\n const bySource = new Map<string, AggBalanceBreakdownItem>();\n const cash = managedBalances.cash;\n // Hosted BETDEX collateral is not spendable from any user's chain wallet.\n const chainVenues = connectedVenues.filter((venue) => venue !== \"betdex\");\n\n for (const token of cash) {\n if (!isUsdBasedToken(token.tokenSymbol)) continue;\n for (const chain of token.chains) {\n const native = chain.custodyKind === \"VENUE_ACCOUNT\";\n const key = native\n ? JSON.stringify([\n \"venue-account\",\n chain.venue,\n chain.venueAccountId,\n chain.externalAccountId,\n chain.chainId,\n ])\n : String(chain.chainId);\n const current = bySource.get(key) ?? {\n key,\n label: native\n ? chain.venue\n ? resolveAggUiLabels(\"en\").venues[chain.venue]\n : resolveAggUiLabels(\"en\").userProfile.balance.venueAccount\n : chainLabelFromId(chain.chainId),\n balance: 0,\n accountCount: 0,\n venues:\n native && chain.venue\n ? [chain.venue]\n : chainVenues.length > 0\n ? chainVenues\n : undefined,\n ...(native\n ? {\n venue: chain.venue,\n venueAccountId: chain.venueAccountId,\n externalAccountId: chain.externalAccountId,\n isFresh: chain.isFresh === true,\n }\n : {}),\n };\n current.balance += toTokenUnits(rawForChain(chain), chain.decimals ?? token.decimals);\n current.accountCount += 1;\n if (native) current.isFresh = current.isFresh === true && chain.isFresh === true;\n bySource.set(key, current);\n }\n }\n\n return Array.from(bySource.values()).sort((a, b) => a.label.localeCompare(b.label));\n },\n [connectedVenues, managedBalances.cash],\n );\n\n const balanceBreakdown = useMemo((): AggBalanceBreakdownItem[] => {\n return buildBalanceBreakdown((chain) => chain.balanceRaw);\n }, [buildBalanceBreakdown]);\n\n const availableBalanceBreakdown = useMemo((): AggBalanceBreakdownItem[] => {\n return buildBalanceBreakdown((chain) => chain.availableRaw ?? chain.balanceRaw);\n }, [buildBalanceBreakdown]);\n\n const positionsBalanceTotal = useMemo((): number => {\n const positions = managedBalances.positions;\n const actualPositionsBalance = positions.reduce(\n (sum, position) => sum + (Number.isFinite(position.balance) ? position.balance : 0),\n 0,\n );\n return actualPositionsBalance + reservedBalance;\n }, [managedBalances.positions, reservedBalance]);\n\n const kalshiVenueCash = managedBalances.venueCash?.find((item) => item.venue === \"kalshi\");\n const venueCashBalances = useMemo(\n () =>\n Object.fromEntries(\n (managedBalances.venueCash ?? []).map((item) => [item.venue, item.balanceCents / 100]),\n ),\n [managedBalances.venueCash],\n );\n const kalshiBalance = kalshiVenueCash ? kalshiVenueCash.balanceCents / 100 : null;\n const kalshiPortfolioValue =\n kalshiVenueCash?.portfolioValueCents == null ? null : kalshiVenueCash.portfolioValueCents / 100;\n\n const betdexCash = managedBalances.venueCash?.find(\n (item) => item.venue === \"betdex\" && item.accountModel === \"platform-hosted\",\n );\n const hostedUsd = (raw: string | undefined): number | null => {\n if (raw === undefined || !/^-?\\d+$/.test(raw)) return null;\n const value = Number(raw) / 1_000_000;\n return Number.isFinite(value) ? value : null;\n };\n const betdexBalance = betdexCash?.decimals === 6 ? hostedUsd(betdexCash.balanceRaw) : null;\n const betdexAvailableBalance =\n betdexCash?.decimals === 6 ? hostedUsd(betdexCash.availableRaw) : null;\n\n const refetch = useCallback((): void => {\n if (!isAuthenticated) return;\n void refetchBalances();\n }, [isAuthenticated, refetchBalances]);\n\n const refetchConnectionStatus = useCallback((): void => {\n if (!client || !isAuthenticated) return;\n void client.getCurrentUser();\n }, [client, isAuthenticated]);\n\n const value = useMemo<AggBalanceContextValue>(() => {\n if (!isAuthenticated) {\n return {\n managedBalances,\n dataUpdatedAt: 0,\n totalBalance: 0,\n availableBalance: 0,\n reservedBalance: 0,\n positionsBalanceTotal: 0,\n kalshiBalance: null,\n kalshiPortfolioValue: null,\n betdexBalance: null,\n betdexAvailableBalance: null,\n balanceBreakdown: [],\n availableBalanceBreakdown: [],\n connectedVenues: [],\n isLoading: false,\n error: null,\n refetch,\n refetchConnectionStatus,\n };\n }\n\n const error =\n balancesError instanceof Error\n ? balancesError\n : balancesError\n ? new Error(String(balancesError))\n : null;\n\n return {\n managedBalances,\n dataUpdatedAt: balancesQuery.dataUpdatedAt,\n totalBalance,\n availableBalance,\n reservedBalance,\n positionsBalanceTotal,\n kalshiBalance,\n venueCashBalances,\n kalshiPortfolioValue,\n betdexBalance,\n betdexAvailableBalance,\n balanceBreakdown,\n availableBalanceBreakdown,\n connectedVenues,\n isLoading: isBalancesLoading,\n error,\n refetch,\n refetchConnectionStatus,\n };\n }, [\n balanceBreakdown,\n availableBalance,\n availableBalanceBreakdown,\n balancesError,\n connectedVenues,\n isBalancesLoading,\n isAuthenticated,\n kalshiBalance,\n venueCashBalances,\n kalshiPortfolioValue,\n betdexBalance,\n betdexAvailableBalance,\n managedBalances,\n balancesQuery.dataUpdatedAt,\n positionsBalanceTotal,\n refetch,\n refetchConnectionStatus,\n reservedBalance,\n totalBalance,\n ]);\n\n return <AggBalanceContext.Provider value={value}>{children}</AggBalanceContext.Provider>;\n}\n","import type { AggClient } from \"@agg-build/sdk\";\nimport type { ReactNode } from \"react\";\nimport { AggClientContext } from \"./contexts\";\n\ninterface AggClientProviderProps {\n client?: AggClient;\n children: ReactNode;\n}\n\nexport function AggClientProvider({ client, children }: AggClientProviderProps): React.JSX.Element {\n \"use memo\";\n return <AggClientContext.Provider value={client ?? null}>{children}</AggClientContext.Provider>;\n}\n","import type { AppClientConfigResponse } from \"@agg-build/sdk\";\nimport { useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { useAggClient, useOptionalAggClient } from \"./core/provider\";\n\nconst FIVE_MINUTES = 5 * 60 * 1000;\n\n/**\n * Stands in for the appId on an admin-key-only client, so those entries get\n * their own cache slot instead of colliding with a real App's config.\n */\nconst NO_APP_SCOPE = \"__no-app__\";\n\n/**\n * App config is per-App data, and `tradingMode` on it is the client-side\n * trading authority (SNA-2964). Two `AggClient`s for different Apps under one\n * `QueryClient` — a partner switching Apps, an admin previewing one — must not\n * read each other's entry, or a live app paints paper chrome and vice versa.\n */\nexport const appConfigQueryKey = (appId: string | undefined) =>\n [\"agg\", \"app-config\", appId ?? NO_APP_SCOPE] as const;\n\nexport interface UseAppConfigResult {\n prophetxExecutionMode?: \"clearinghouse\" | \"direct\";\n novigExecutionMode?: \"clearinghouse\" | \"direct\";\n disabledVenues: AppClientConfigResponse[\"disabledVenues\"];\n disabledCategoryPresets: AppClientConfigResponse[\"disabledCategoryPresets\"];\n earlyAccessEnabled: AppClientConfigResponse[\"earlyAccessEnabled\"];\n authOptions: AppClientConfigResponse[\"authOptions\"];\n /**\n * Server-owned paper/live mode. `undefined` until `/app/config` resolves —\n * deliberately NOT defaulted here, so callers can tell \"not loaded yet\"\n * apart from \"the server said live\". Resolve it via\n * `useResolvedExecutionMode`, not by reading this directly.\n */\n tradingMode: AppClientConfigResponse[\"tradingMode\"] | undefined;\n /** One-time paper grant in dollars; `undefined` until config resolves. */\n paperStartingBalance: number | undefined;\n isLoading: boolean;\n error: unknown;\n}\n\n/**\n * Fetch the current App's UI config (disabled venues, category presets, and\n * the server-owned paper/live mode).\n *\n * Cadence is deliberately the 5 minutes this hook has always used. Execution\n * settings can change at runtime; stale cached settings affect presentation,\n * while the server remains authoritative: the API resolves mode from the App on every request\n * (`resolveTradingMode`), so a client that still believes the old value\n * renders the wrong chrome but cannot execute in the wrong mode or spend real\n * funds. That does not justify polling a partner's app every minute.\n *\n * A bounded `refetchInterval` is still worth having — without one, a tab left\n * open on a single screen never learns about a flip at all — but it matches\n * `staleTime` rather than undercutting it.\n *\n * `refetchOnWindowFocus`/`refetchOnReconnect` are deliberately left at the\n * host's defaults. Forcing `\"always\"` here would override a partner's own\n * `QueryClient` settings (the demo sets `refetchOnWindowFocus: false`), which\n * is not this hook's call to make.\n */\nexport function useAppConfig(): UseAppConfigResult {\n const client = useAggClient();\n\n const query = useQuery<AppClientConfigResponse>({\n queryKey: appConfigQueryKey(client.appId),\n queryFn: () => client.getAppConfig(),\n staleTime: FIVE_MINUTES,\n // Skipped entirely while the tab is unfocused — query-core only fires the\n // interval when `refetchIntervalInBackground` is set or the window is\n // focused — so a background tab costs nothing.\n refetchInterval: FIVE_MINUTES,\n });\n\n return toAppConfigResult({\n data: query.data,\n isLoading: query.isLoading,\n error: query.error,\n });\n}\n\n/**\n * Read the current App's UI config from the React Query cache without starting a fetch.\n * Use this in surfaces that open after config has already been loaded by a parent screen.\n */\nexport function useCachedAppConfig(): UseAppConfigResult {\n const queryClient = useQueryClient();\n // Optional, not `useAggClient()`: this hook must keep working under a bare\n // <AggUiProvider> with no client, where it simply finds nothing cached.\n const client = useOptionalAggClient();\n const queryKey = appConfigQueryKey(client?.appId);\n const query = useQuery<AppClientConfigResponse>({\n queryKey,\n enabled: false,\n initialData: () => queryClient.getQueryData<AppClientConfigResponse>(queryKey),\n staleTime: FIVE_MINUTES,\n });\n\n return toAppConfigResult({\n data: query.data,\n isLoading: query.isLoading,\n error: query.error,\n });\n}\n\nconst toAppConfigResult = (query: {\n data?: AppClientConfigResponse;\n isLoading: boolean;\n error: unknown;\n}): UseAppConfigResult => {\n return {\n prophetxExecutionMode: query.data\n ? (query.data.prophetxExecutionMode ?? \"clearinghouse\")\n : undefined,\n novigExecutionMode: query.data ? (query.data.novigExecutionMode ?? \"clearinghouse\") : undefined,\n disabledVenues: query.data?.disabledVenues ?? [],\n disabledCategoryPresets: query.data?.disabledCategoryPresets ?? [],\n earlyAccessEnabled: query.data?.earlyAccessEnabled ?? false,\n authOptions: query.data?.authOptions ?? [],\n tradingMode: query.data?.tradingMode,\n paperStartingBalance: query.data?.paperStartingBalance,\n isLoading: query.isLoading,\n error: query.error,\n };\n};\n","import { useMemo, type ReactNode } from \"react\";\nimport { useAppConfig } from \"../../use-app-config\";\nimport { AggExecutionModeContext } from \"./contexts\";\n\n/**\n * Resolves app-level paper/live mode once, from `/app/config`, and publishes\n * it to every surface below.\n *\n * Mounted inside `AggProvider`, where a client and a QueryClient are\n * guaranteed. Deliberately a provider rather than a hook each surface calls:\n * a surface calling `useAppConfig` directly would hard-require an\n * `<AggProvider>` ancestor, breaking components that legitimately render\n * under a bare `<AggUiProvider>` — Storybook stories, unit tests, and\n * partners composing pieces by hand.\n */\nexport function AggExecutionModeProvider({ children }: { children: ReactNode }): React.JSX.Element {\n const { tradingMode, paperStartingBalance, isLoading } = useAppConfig();\n\n const value = useMemo(\n () => ({ tradingMode, paperStartingBalance, isLoading }),\n [tradingMode, paperStartingBalance, isLoading],\n );\n\n return (\n <AggExecutionModeContext.Provider value={value}>{children}</AggExecutionModeContext.Provider>\n );\n}\n","import { createContext, useCallback, useContext, useRef, type ReactNode } from \"react\";\n\nconst STALENESS_THRESHOLD_MS = 5 * 60 * 1000; // 5 minutes\nconst MAX_INITIAL_PAGES = 10;\n\nexport type EventListStateSnapshot = {\n /** Category tab selected in HomePage */\n categoryTab: string | null;\n /** Venue/provider tab selected in EventList */\n venueTab: string | null;\n /** Scroll offset (pixels from top of document) */\n scrollY: number;\n /** Number of infinite query pages that were loaded */\n loadedPageCount: number;\n /** Timestamp when state was captured */\n capturedAt: number;\n};\n\nexport type EventListStateContextValue = {\n /** Store a snapshot of the current list state (called before navigating away) */\n capture: (state: Omit<EventListStateSnapshot, \"capturedAt\">) => void;\n /** Return the stored snapshot and clear it (one-time read). Returns null if no snapshot or stale. */\n consume: () => EventListStateSnapshot | null;\n};\n\nconst EventListStateContext = createContext<EventListStateContextValue | null>(null);\n\nexport function EventListStateProvider({ children }: { children: ReactNode }): React.JSX.Element {\n const snapshotRef = useRef<EventListStateSnapshot | null>(null);\n\n const capture = useCallback((state: Omit<EventListStateSnapshot, \"capturedAt\">) => {\n snapshotRef.current = {\n ...state,\n loadedPageCount: Math.min(state.loadedPageCount, MAX_INITIAL_PAGES),\n capturedAt: Date.now(),\n };\n }, []);\n\n const consume = useCallback((): EventListStateSnapshot | null => {\n const snapshot = snapshotRef.current;\n snapshotRef.current = null;\n\n if (!snapshot) return null;\n\n const age = Date.now() - snapshot.capturedAt;\n if (age > STALENESS_THRESHOLD_MS) return null;\n\n return snapshot;\n }, []);\n\n const value = useRef<EventListStateContextValue>({ capture, consume });\n value.current.capture = capture;\n value.current.consume = consume;\n\n // Stable reference to avoid re-renders\n const stableValue = useRef<EventListStateContextValue>({\n capture: (...args) => value.current.capture(...args),\n consume: () => value.current.consume(),\n }).current;\n\n return (\n <EventListStateContext.Provider value={stableValue}>{children}</EventListStateContext.Provider>\n );\n}\n\nexport function useEventListState(): EventListStateContextValue {\n const context = useContext(EventListStateContext);\n\n if (!context) {\n throw new Error(\"useEventListState must be used within an <AggProvider>\");\n }\n\n return context;\n}\n","import type { ChartTimeRange } from \"./types\";\n\nexport const DEFAULT_AGG_ROOT_CLASS_NAME = \"agg-root\";\n\nexport const CHART_TIME_RANGES: ChartTimeRange[] = [\"1H\", \"6H\", \"1D\", \"1W\", \"1M\", \"ALL\"];\n","import type { AggUiGeneralConfig, AggUiPersistedConfig, ChartTimeRange, ThemeMode } from \"./types\";\nimport { CHART_TIME_RANGES } from \"./constants\";\n\nconst STORAGE_KEY = \"agg_sdk_ui\";\n\nconst isBrowser = (): boolean => typeof window !== \"undefined\" && \"localStorage\" in window;\n\nconst normalizeTheme = (value: unknown): ThemeMode | undefined => {\n if (value === \"light\" || value === \"dark\") {\n return value;\n }\n return undefined;\n};\n\nconst normalizeChartTimeRange = (value: unknown): ChartTimeRange | undefined => {\n if (typeof value === \"string\" && CHART_TIME_RANGES.includes(value as ChartTimeRange)) {\n return value as ChartTimeRange;\n }\n return undefined;\n};\n\nexport const loadPersistedConfig = (): AggUiPersistedConfig => {\n if (!isBrowser()) return {};\n try {\n const raw = window.localStorage.getItem(STORAGE_KEY);\n if (!raw) return {};\n const parsed = JSON.parse(raw) as AggUiPersistedConfig;\n const locale = typeof parsed.general?.locale === \"string\" ? parsed.general.locale : undefined;\n const theme = normalizeTheme(parsed.general?.theme);\n const selectedChartTimeRange = normalizeChartTimeRange(parsed.chart?.selectedChartTimeRange);\n\n const result: AggUiPersistedConfig = {};\n\n if (locale || theme) {\n result.general = { locale, theme };\n }\n\n if (selectedChartTimeRange) {\n result.chart = { selectedChartTimeRange };\n }\n\n return result;\n } catch {\n return {};\n }\n};\n\nexport interface PersistConfigPayload {\n locale: AggUiGeneralConfig[\"locale\"];\n theme: AggUiGeneralConfig[\"theme\"];\n selectedChartTimeRange?: ChartTimeRange;\n}\n\nexport const persistConfig = (config: PersistConfigPayload): void => {\n if (!isBrowser()) return;\n const theme = normalizeTheme(config.theme);\n const selectedChartTimeRange = normalizeChartTimeRange(config.selectedChartTimeRange);\n const payload: AggUiPersistedConfig = {\n general: {\n locale: config.locale,\n theme,\n },\n ...(selectedChartTimeRange ? { chart: { selectedChartTimeRange } } : {}),\n };\n try {\n window.localStorage.setItem(STORAGE_KEY, JSON.stringify(payload));\n } catch {\n // ignore storage errors\n }\n};\n","import type { ThemeMode } from \"./types\";\n\nexport const applyThemeToDocument = (theme: ThemeMode): void => {\n if (typeof document === \"undefined\") return;\n const isDark = theme === \"dark\";\n\n // Ancestor-based selectors (.dark .agg-root)\n document.documentElement.dataset.aggTheme = theme;\n document.documentElement.classList.toggle(\"dark\", isDark);\n document.documentElement.classList.toggle(\"agg-dark\", isDark);\n document.documentElement.classList.toggle(\"light\", !isDark);\n\n // Self-based selectors (.agg-root.dark, .agg-root[data-agg-theme=\"dark\"])\n const aggRoots = document.querySelectorAll<HTMLElement>(\".agg-root\");\n aggRoots.forEach((rootElement) => {\n rootElement.dataset.aggTheme = theme;\n rootElement.classList.toggle(\"dark\", isDark);\n rootElement.classList.toggle(\"agg-dark\", isDark);\n rootElement.classList.toggle(\"light\", !isDark);\n });\n};\n","import {\n MarketStatus,\n type VenueEventWithMarkets,\n type VenueMarket,\n type VenueMarketOutcome,\n} from \"@agg-build/sdk\";\nimport { createContext, useCallback, useContext, useMemo, useReducer, useRef } from \"react\";\n\n// ── Trading state types ──\n\nexport type TradingStateKind =\n | \"open\"\n | \"closed\"\n | \"resolved\"\n | \"paused\"\n | \"unopened\"\n | \"unavailable\";\n\nexport type TradingStateBase = {\n kind: TradingStateKind;\n status: MarketStatus | null;\n isOpen: boolean;\n isTradingDisabled: boolean;\n startsAt: string | null;\n endsAt: string | null;\n resolvesAt: string | null;\n winningOutcome: VenueMarketOutcome | null;\n};\n\nexport type MarketTradingState = TradingStateBase & {\n market: VenueMarket | null;\n};\n\nexport type EventTradingState = TradingStateBase & {\n displayMarkets: VenueMarket[];\n tradableMarkets: VenueMarket[];\n marketStates: Array<{ market: VenueMarket; state: MarketTradingState }>;\n primaryMarket: VenueMarket | null;\n};\n\n// ── Order eligibility ──\n\nexport type OrderEligibilityReason =\n | \"eligible\"\n | \"no_event_selected\"\n | \"no_market_selected\"\n | \"no_outcome_selected\"\n | \"event_resolved\"\n | \"event_closed\"\n | \"event_paused\"\n | \"event_unopened\"\n | \"event_unavailable\"\n | \"market_resolved\"\n | \"market_closed\"\n | \"market_paused\"\n | \"market_unopened\"\n | \"market_unavailable\";\n\nexport type OrderEligibility = {\n canPlaceOrder: boolean;\n reason: OrderEligibilityReason;\n};\n\n// ── Trading state helpers ──\n\nconst OPEN_TRADING_STATE: TradingStateBase = {\n kind: \"open\",\n status: MarketStatus.open,\n isOpen: true,\n isTradingDisabled: false,\n startsAt: null,\n endsAt: null,\n resolvesAt: null,\n winningOutcome: null,\n};\n\nexport const resolveTradingStateKind = (\n status?: MarketStatus | null,\n): Exclude<TradingStateKind, \"unavailable\"> => {\n if (!status || status === MarketStatus.open) return \"open\";\n if (status === MarketStatus.resolved) return \"resolved\";\n if (status === MarketStatus.paused) return \"paused\";\n if (status === MarketStatus.unopened) return \"unopened\";\n return \"closed\";\n};\n\nexport const resolveMarketWinningOutcome = (\n market?: VenueMarket | null,\n): VenueMarketOutcome | null => {\n if (!market) return null;\n\n const localWinningOutcome =\n market.venueMarketOutcomes.find((outcome) => outcome.winner === true) ?? null;\n if (localWinningOutcome) return localWinningOutcome;\n\n const matchedVenueMarkets = market.matchedVenueMarkets ?? [];\n if (!matchedVenueMarkets.length) return null;\n\n for (const outcome of market.venueMarketOutcomes) {\n const matchedRefs = outcome.matchedVenueMarketOutcomes ?? [];\n for (const ref of matchedRefs) {\n const matchedMarket = matchedVenueMarkets.find((item) => item.id === ref.venueMarketId);\n if (!matchedMarket) continue;\n\n const matchedOutcome = matchedMarket.venueMarketOutcomes?.find(\n (item) => item.id === ref.venueMarketOutcomeId,\n );\n if (matchedOutcome?.winner === true) {\n return outcome;\n }\n }\n }\n\n return null;\n};\n\nconst AFFIRMATIVE_WINNER_LABELS = new Set([\"yes\", \"up\", \"buy\", \"long\", \"true\"]);\n\nconst isAffirmativeWinnerLabel = (label: string | null | undefined): boolean => {\n if (!label) return false;\n return AFFIRMATIVE_WINNER_LABELS.has(label.trim().toLowerCase());\n};\n\nconst resolvePreferredWinningMarket = (\n marketStates: Array<{ market: VenueMarket; state: MarketTradingState }>,\n): VenueMarket | null => {\n const marketWithAffirmativeWinner = marketStates.find((item) =>\n isAffirmativeWinnerLabel(item.state.winningOutcome?.label),\n );\n\n if (marketWithAffirmativeWinner) {\n return marketWithAffirmativeWinner.market;\n }\n\n return marketStates.find((item) => item.state.winningOutcome)?.market ?? null;\n};\n\nexport const resolveMarketTradingState = (market?: VenueMarket | null): MarketTradingState => {\n if (!market) {\n return {\n ...OPEN_TRADING_STATE,\n kind: \"unavailable\",\n status: null,\n isOpen: false,\n isTradingDisabled: true,\n market: null,\n };\n }\n\n const kind = resolveTradingStateKind(market.status);\n\n return {\n kind,\n status: market.status ?? (kind === \"open\" ? MarketStatus.open : null),\n isOpen: kind === \"open\",\n isTradingDisabled: kind !== \"open\",\n startsAt: market.startDate ?? null,\n endsAt: market.endDate ?? null,\n resolvesAt: market.resolutionDate ?? null,\n market,\n winningOutcome: resolveMarketWinningOutcome(market),\n };\n};\n\nconst deriveEventTradingStateKind = (marketStates: MarketTradingState[]): TradingStateKind => {\n if (marketStates.length === 0) return \"unavailable\";\n if (marketStates.some((marketState) => marketState.kind === \"open\")) return \"open\";\n if (marketStates.every((marketState) => marketState.kind === \"resolved\")) return \"resolved\";\n if (marketStates.every((marketState) => marketState.kind === \"paused\")) return \"paused\";\n if (marketStates.every((marketState) => marketState.kind === \"unopened\")) return \"unopened\";\n return \"closed\";\n};\n\nconst resolveEventStateStatus = (\n event: VenueEventWithMarkets,\n kind: TradingStateKind,\n): MarketStatus | null => {\n if (event.status) return event.status;\n if (kind === \"unavailable\") return null;\n if (kind === \"open\") return MarketStatus.open;\n if (kind === \"resolved\") return MarketStatus.resolved;\n if (kind === \"paused\") return MarketStatus.paused;\n if (kind === \"unopened\") return MarketStatus.unopened;\n return MarketStatus.closed;\n};\n\nconst resolveEventWinningOutcome = (\n marketStates: Array<{ market: VenueMarket; state: MarketTradingState }>,\n preferredMarket: VenueMarket | null,\n): VenueMarketOutcome | null => {\n if (preferredMarket) {\n return (\n marketStates.find((item) => item.market.id === preferredMarket.id)?.state.winningOutcome ??\n null\n );\n }\n\n return marketStates.find((item) => item.state.winningOutcome)?.state.winningOutcome ?? null;\n};\n\nexport const resolveEventTradingState = (\n event?: VenueEventWithMarkets | null,\n): EventTradingState => {\n if (!event?.venueMarkets.length) {\n return {\n ...OPEN_TRADING_STATE,\n kind: \"unavailable\",\n status: event?.status ?? null,\n isOpen: false,\n isTradingDisabled: true,\n startsAt: event?.startDate ?? null,\n endsAt: event?.endDate ?? null,\n displayMarkets: [],\n tradableMarkets: [],\n marketStates: [],\n primaryMarket: null,\n };\n }\n\n const marketStates = event.venueMarkets.map((market) => ({\n market,\n state: resolveMarketTradingState(market),\n }));\n const derivedKind = deriveEventTradingStateKind(marketStates.map((item) => item.state));\n const explicitKind = event.status ? resolveTradingStateKind(event.status) : null;\n const kind =\n explicitKind && (explicitKind !== \"open\" || derivedKind === \"open\")\n ? explicitKind\n : derivedKind;\n const preferredWinningMarket = resolvePreferredWinningMarket(marketStates);\n const tradableMarkets = marketStates\n .filter((item) => item.state.isOpen)\n .map((item) => item.market);\n const displayMarkets = kind === \"open\" ? tradableMarkets : event.venueMarkets;\n const primaryMarket =\n (kind !== \"open\" ? preferredWinningMarket : null) ??\n displayMarkets[0] ??\n tradableMarkets[0] ??\n event.venueMarkets[0] ??\n null;\n\n return {\n kind,\n status: resolveEventStateStatus(event, kind),\n isOpen: kind === \"open\",\n isTradingDisabled: kind !== \"open\",\n startsAt: event.startDate ?? primaryMarket?.startDate ?? null,\n endsAt: event.endDate ?? primaryMarket?.endDate ?? null,\n resolvesAt:\n marketStates.find((item) => item.state.resolvesAt)?.state.resolvesAt ??\n primaryMarket?.resolutionDate ??\n null,\n winningOutcome: resolveEventWinningOutcome(marketStates, preferredWinningMarket),\n displayMarkets,\n tradableMarkets,\n marketStates,\n primaryMarket,\n };\n};\n\n// ── Order eligibility helpers ──\n\nconst toEventReason = (kind: TradingStateKind): OrderEligibilityReason => {\n const mapped: Record<Exclude<TradingStateKind, \"open\">, OrderEligibilityReason> = {\n resolved: \"event_resolved\",\n closed: \"event_closed\",\n paused: \"event_paused\",\n unopened: \"event_unopened\",\n unavailable: \"event_unavailable\",\n };\n return mapped[kind as Exclude<TradingStateKind, \"open\">] ?? \"event_unavailable\";\n};\n\nconst toMarketReason = (kind: TradingStateKind): OrderEligibilityReason => {\n const mapped: Record<Exclude<TradingStateKind, \"open\">, OrderEligibilityReason> = {\n resolved: \"market_resolved\",\n closed: \"market_closed\",\n paused: \"market_paused\",\n unopened: \"market_unopened\",\n unavailable: \"market_unavailable\",\n };\n return mapped[kind as Exclude<TradingStateKind, \"open\">] ?? \"market_unavailable\";\n};\n\nexport const resolveOrderEligibility = (params: {\n event: VenueEventWithMarkets | null;\n market: VenueMarket | null;\n outcome: VenueMarketOutcome | null;\n eventTradingState?: EventTradingState;\n}): OrderEligibility => {\n if (!params.event) return { canPlaceOrder: false, reason: \"no_event_selected\" };\n if (!params.market) return { canPlaceOrder: false, reason: \"no_market_selected\" };\n if (!params.outcome) return { canPlaceOrder: false, reason: \"no_outcome_selected\" };\n\n const eventState = params.eventTradingState ?? resolveEventTradingState(params.event);\n if (eventState.isTradingDisabled) {\n return { canPlaceOrder: false, reason: toEventReason(eventState.kind) };\n }\n\n const marketState = resolveMarketTradingState(params.market);\n if (marketState.isTradingDisabled) {\n return { canPlaceOrder: false, reason: toMarketReason(marketState.kind) };\n }\n\n return { canPlaceOrder: true, reason: \"eligible\" };\n};\n\n// ── Selection helpers ──\n\nexport function resolveDefaultMarket(event: VenueEventWithMarkets | null): VenueMarket | null {\n if (!event?.venueMarkets.length) return null;\n const tradableMarket = event.venueMarkets.find(\n (market) => resolveMarketTradingState(market).isOpen,\n );\n if (tradableMarket) return tradableMarket;\n\n const marketStates = event.venueMarkets.map((market) => ({\n market,\n state: resolveMarketTradingState(market),\n }));\n const preferredWinningMarket = resolvePreferredWinningMarket(marketStates);\n\n return preferredWinningMarket ?? event.venueMarkets[0] ?? null;\n}\n\nexport { resolveDefaultMarket as resolveDefaultTradingMarket };\n\nexport function resolveDefaultOutcome(market: VenueMarket | null): VenueMarketOutcome | null {\n const yesOutcome = market?.venueMarketOutcomes.find((o) => o?.label?.toLowerCase() === \"yes\");\n if (yesOutcome) return yesOutcome;\n return market?.venueMarketOutcomes?.[0] ?? null;\n}\n\nexport function findMarketById(\n event: VenueEventWithMarkets | null,\n marketId: string,\n): VenueMarket | null {\n if (!event) return null;\n return event.venueMarkets.find((m) => m.id === marketId) ?? null;\n}\n\nexport function findOutcomeById(\n market: VenueMarket | null,\n outcomeId: string,\n): VenueMarketOutcome | null {\n if (!market) return null;\n return market.venueMarketOutcomes.find((o) => o.id === outcomeId) ?? null;\n}\n\nexport function findOutcomeAcrossMarkets(\n event: VenueEventWithMarkets | null,\n outcomeId: string,\n): { market: VenueMarket; outcome: VenueMarketOutcome } | null {\n if (!event) return null;\n for (const market of event.venueMarkets) {\n const outcome = market.venueMarketOutcomes.find((o) => o.id === outcomeId);\n if (outcome) return { market, outcome };\n }\n return null;\n}\n\n// ── State ──\n\n/**\n * Active trade side. Modeled as a frozen const-object so callers can use\n * enum-style access (`TradeSide.Buy`, `TradeSide.Sell`) while the resulting\n * type is still the plain `\"buy\" | \"sell\"` string union — interoperable\n * everywhere a literal is expected (URL params, JSON payloads, helper\n * function signatures).\n */\nexport const TradeSide = {\n Buy: \"buy\",\n Sell: \"sell\",\n} as const;\nexport type TradeSide = (typeof TradeSide)[keyof typeof TradeSide];\n\nexport interface TradingState {\n event: VenueEventWithMarkets | null;\n market: VenueMarket | null;\n outcome: VenueMarketOutcome | null;\n /**\n * Currently selected buy/sell side. Optional in shape (older fixtures and\n * snapshots may omit it) — readers should treat `undefined` as `Buy`.\n */\n tradeSide?: TradeSide;\n}\n\n// ── Actions ──\n\nexport type TradingAction =\n | { type: \"INITIALIZE_EVENT\"; event: VenueEventWithMarkets | null }\n | { type: \"SYNC_EVENT\"; event: VenueEventWithMarkets }\n | { type: \"SELECT_MARKET\"; marketId: string; market?: VenueMarket }\n | { type: \"SELECT_OUTCOME\"; outcomeId: string }\n | { type: \"SELECT_MARKET_AND_OUTCOME\"; marketId: string; outcomeId: string }\n | { type: \"SET_TRADE_SIDE\"; tradeSide: TradeSide };\n\n// ── Reducer ──\n\nexport function tradingReducer(state: TradingState, action: TradingAction): TradingState {\n switch (action.type) {\n case \"INITIALIZE_EVENT\": {\n // Always snap the trade side back to Buy when an event is (re)initialised\n // — including the `null` case (user navigating to the home view). This\n // ensures the home grid and any newly opened event start in Buy mode\n // regardless of where the side was left previously.\n if (!action.event) {\n return { event: null, market: null, outcome: null, tradeSide: TradeSide.Buy };\n }\n return {\n event: action.event,\n market: null,\n outcome: null,\n tradeSide: TradeSide.Buy,\n };\n }\n\n case \"SYNC_EVENT\": {\n const previousMarketId = state.market?.id ?? null;\n const previousOutcomeId = state.outcome?.id ?? null;\n const syncedMarket = previousMarketId ? findMarketById(action.event, previousMarketId) : null;\n\n if (!syncedMarket || resolveMarketTradingState(syncedMarket).isTradingDisabled) {\n return {\n event: action.event,\n market: null,\n outcome: null,\n tradeSide: state.tradeSide ?? TradeSide.Buy,\n };\n }\n\n const syncedOutcome = previousOutcomeId\n ? findOutcomeById(syncedMarket, previousOutcomeId)\n : null;\n\n return {\n event: action.event,\n market: syncedMarket,\n outcome: syncedOutcome,\n tradeSide: state.tradeSide ?? TradeSide.Buy,\n };\n }\n\n case \"SET_TRADE_SIDE\": {\n if ((state.tradeSide ?? TradeSide.Buy) === action.tradeSide) return state;\n return { ...state, tradeSide: action.tradeSide };\n }\n\n case \"SELECT_MARKET\": {\n const market = findMarketById(state.event, action.marketId) ?? action.market ?? null;\n if (!market) return state;\n if (resolveMarketTradingState(market).kind === \"resolved\") return state;\n return {\n ...state,\n market,\n outcome: resolveDefaultOutcome(market),\n };\n }\n\n case \"SELECT_OUTCOME\": {\n if (state.outcome?.id === action.outcomeId) {\n return state;\n }\n\n // Fast path: check current market first\n if (state.market) {\n const outcomeInCurrentMarket = findOutcomeById(state.market, action.outcomeId);\n if (outcomeInCurrentMarket) {\n if (resolveMarketTradingState(state.market).kind === \"resolved\") {\n return state;\n }\n return { ...state, outcome: outcomeInCurrentMarket };\n }\n }\n\n // Cross-market search — block jump to non-tradable markets\n const found = findOutcomeAcrossMarkets(state.event, action.outcomeId);\n if (!found) return state;\n\n const targetMarketState = resolveMarketTradingState(found.market);\n if (targetMarketState.isTradingDisabled) return state;\n\n return {\n ...state,\n market: found.market,\n outcome: found.outcome,\n };\n }\n\n case \"SELECT_MARKET_AND_OUTCOME\": {\n const market = findMarketById(state.event, action.marketId);\n if (!market) return state;\n if (resolveMarketTradingState(market).kind === \"resolved\") return state;\n\n const outcome = findOutcomeById(market, action.outcomeId);\n if (!outcome) return state;\n\n return { ...state, market, outcome };\n }\n\n default: {\n const _exhaustive: never = action;\n return _exhaustive;\n }\n }\n}\n\nfunction logAction(\n actionType: string,\n payload: unknown,\n prev: TradingState,\n next: TradingState,\n enableLogs: boolean,\n): void {\n if (!enableLogs) return;\n\n console.group(`[EventTrading] ${actionType}`);\n console.log(\"payload\", payload);\n console.log(\"prev\", prev);\n console.log(\"next\", next);\n console.log(\"IDS\", {\n eventId: next.event?.id,\n marketIds: next.event?.venueMarkets.map((m) => m.id),\n outcomeIds: next.event?.venueMarkets.flatMap((m) => m.venueMarketOutcomes.map((o) => o.id)),\n selectedMarketId: next.market?.id,\n selectedOutcomeId: next.outcome?.id,\n });\n console.groupEnd();\n}\n\n// ── Context ──\n\nexport interface EventTradingContextValue {\n selectedEvent: VenueEventWithMarkets | null;\n selectedMarket: VenueMarket | null;\n selectedOutcome: VenueMarketOutcome | null;\n\n selectedEventId: string | null;\n selectedMarketId: string | null;\n selectedOutcomeId: string | null;\n selectedVenue: string | null;\n\n /**\n * Currently selected trade side. Drives `bestAsk` vs `bestBid` selection\n * across all price-display surfaces (home tile, event details, market\n * details, place-order outcome buttons) so flipping Buy/Sell in PlaceOrder\n * is reflected everywhere. Defaults to `\"buy\"`.\n */\n tradeSide: TradeSide;\n setTradeSide: (tradeSide: TradeSide) => void;\n\n initializeFromEvent: (event: VenueEventWithMarkets | null) => void;\n syncEvent: (event: VenueEventWithMarkets) => void;\n selectMarket: (marketId: string, market?: VenueMarket) => void;\n selectOutcome: (outcomeId: string) => void;\n selectMarketAndOutcome: (marketId: string, outcomeId: string) => void;\n}\n\nconst initialState: TradingState = {\n event: null,\n market: null,\n outcome: null,\n tradeSide: TradeSide.Buy,\n};\n\nexport const EventTradingContext = createContext<EventTradingContextValue | undefined>(undefined);\n\nexport const useEventTradingContext = (): EventTradingContextValue | undefined => {\n return useContext(EventTradingContext);\n};\n\ninterface EventTradingProviderProps {\n children: React.ReactNode;\n enableLogs?: boolean;\n}\n\nexport const EventTradingProvider = ({\n children,\n enableLogs = false,\n}: EventTradingProviderProps): React.JSX.Element => {\n const [state, rawDispatch] = useReducer(tradingReducer, initialState);\n const stateRef = useRef(state);\n const pendingAtomicSelectionRef = useRef<{ marketId: string; outcomeId: string } | null>(null);\n stateRef.current = state;\n\n const pendingAtomicSelection = pendingAtomicSelectionRef.current;\n if (\n pendingAtomicSelection &&\n state.market?.id === pendingAtomicSelection.marketId &&\n state.outcome?.id === pendingAtomicSelection.outcomeId\n ) {\n pendingAtomicSelectionRef.current = null;\n }\n\n const dispatch = useCallback(\n (action: TradingAction) => {\n const prev = stateRef.current;\n rawDispatch(action);\n\n // Log after dispatch — next state is computed synchronously by React\n // We re-compute it here for logging only; the real state update is in rawDispatch\n const next = tradingReducer(prev, action);\n logAction(action.type, action, prev, next, enableLogs);\n },\n [enableLogs],\n );\n\n const initializeFromEvent = useCallback(\n (event: VenueEventWithMarkets | null) => dispatch({ type: \"INITIALIZE_EVENT\", event }),\n [dispatch],\n );\n\n const syncEvent = useCallback(\n (event: VenueEventWithMarkets) => dispatch({ type: \"SYNC_EVENT\", event }),\n [dispatch],\n );\n\n const selectMarket = useCallback(\n (marketId: string, market?: VenueMarket) =>\n dispatch({ type: \"SELECT_MARKET\", marketId, market }),\n [dispatch],\n );\n\n const selectOutcome = useCallback(\n (outcomeId: string) => {\n if (stateRef.current.outcome?.id === outcomeId) return;\n if (pendingAtomicSelectionRef.current?.outcomeId === outcomeId) return;\n dispatch({ type: \"SELECT_OUTCOME\", outcomeId });\n },\n [dispatch],\n );\n\n const selectMarketAndOutcome = useCallback(\n (marketId: string, outcomeId: string) => {\n if (stateRef.current.market?.id === marketId && stateRef.current.outcome?.id === outcomeId) {\n return;\n }\n if (\n pendingAtomicSelectionRef.current?.marketId === marketId &&\n pendingAtomicSelectionRef.current?.outcomeId === outcomeId\n ) {\n return;\n }\n pendingAtomicSelectionRef.current = { marketId, outcomeId };\n dispatch({ type: \"SELECT_MARKET_AND_OUTCOME\", marketId, outcomeId });\n },\n [dispatch],\n );\n\n const setTradeSide = useCallback(\n (tradeSide: TradeSide) => dispatch({ type: \"SET_TRADE_SIDE\", tradeSide }),\n [dispatch],\n );\n\n const value = useMemo<EventTradingContextValue>(\n () => ({\n selectedEvent: state.event,\n selectedMarket: state.market,\n selectedOutcome: state.outcome,\n\n selectedEventId: state.event?.id ?? null,\n selectedMarketId: state.market?.id ?? null,\n selectedOutcomeId: state.outcome?.id ?? null,\n selectedVenue: state.market?.venue ?? null,\n\n tradeSide: state.tradeSide ?? TradeSide.Buy,\n setTradeSide,\n\n initializeFromEvent,\n syncEvent,\n selectMarket,\n selectOutcome,\n selectMarketAndOutcome,\n }),\n [\n state,\n initializeFromEvent,\n syncEvent,\n selectMarket,\n selectOutcome,\n selectMarketAndOutcome,\n setTradeSide,\n ],\n );\n\n return <EventTradingContext.Provider value={value}>{children}</EventTradingContext.Provider>;\n};\n","import { useCallback, useEffect, useMemo, useState } from \"react\";\nimport { DEFAULT_AGG_ROOT_CLASS_NAME } from \"../ui-config/constants\";\nimport { loadPersistedConfig, persistConfig } from \"../ui-config/storage\";\nimport { applyThemeToDocument } from \"../ui-config/theme-utils\";\nimport type {\n AggUiConfig,\n ChartTimeRange,\n SdkUiProviderProps,\n VenueEventWithMarkets,\n} from \"../ui-config/types\";\nimport { mergeAggUiConfig } from \"../ui-config/utils\";\nimport { AggLabelsContext, AggUiContext } from \"./contexts\";\nimport { EventTradingProvider } from \"./event-trading-context\";\n\nlet hasWarnedMissingAggStyles = false;\n\nconst warnIfAggStylesAreMissing = (): void => {\n if (hasWarnedMissingAggStyles) return;\n if (typeof window === \"undefined\" || typeof document === \"undefined\") return;\n const rootElement = document.querySelector<HTMLElement>(`.${DEFAULT_AGG_ROOT_CLASS_NAME}`);\n if (!rootElement) return;\n\n const computedStyle = window.getComputedStyle(rootElement);\n const hasSemanticColorToken =\n computedStyle.getPropertyValue(\"--agg-color-primary\").trim().length > 0;\n const hasTailwindColorToken =\n computedStyle.getPropertyValue(\"--color-agg-primary\").trim().length > 0;\n const hasTailwindRadiusToken =\n computedStyle.getPropertyValue(\"--radius-agg-md\").trim().length > 0;\n\n if (hasSemanticColorToken && hasTailwindColorToken && hasTailwindRadiusToken) {\n return;\n }\n\n hasWarnedMissingAggStyles = true;\n\n console.warn(\n '[agg] Missing AGG UI styles. Import \"@agg-build/ui/styles.css\" once at your app entrypoint so agg token utilities resolve correctly.',\n );\n};\n\nfunction logConfig(config: AggUiConfig, enableLogs: boolean): void {\n if (!enableLogs) return;\n\n console.group(`[AggUiProvider]`);\n console.log(\"config\", config);\n console.groupEnd();\n}\n\ntype SearchSelectState = Pick<AggUiConfig[\"search\"], \"result\" | \"isShowingAllResults\"> & {\n value: string;\n};\n\nexport const getSearchStateAfterSelect = (\n selectedEvent: VenueEventWithMarkets,\n): SearchSelectState => {\n return {\n value: \"\",\n result: selectedEvent,\n isShowingAllResults: false,\n };\n};\n\nexport const AggUiProvider = ({ config, children }: SdkUiProviderProps): React.JSX.Element => {\n const persisted = useMemo(() => loadPersistedConfig(), []);\n const mergedConfig = useMemo(() => mergeAggUiConfig(persisted, config), [persisted, config]);\n const [selectedChartTimeRange, setSelectedChartTimeRange] = useState<ChartTimeRange>(\n mergedConfig.chart.selectedChartTimeRange,\n );\n\n const handleSetSelectedChartTimeRange = useCallback((range: ChartTimeRange): void => {\n setSelectedChartTimeRange(range);\n }, []);\n\n const [searchValue, setSearchValue] = useState(mergedConfig.search.value);\n const [searchResult, setSearchResult] = useState(mergedConfig.search.result);\n const [isShowingAllResults, setIsShowingAllResults] = useState(\n mergedConfig.search.isShowingAllResults,\n );\n\n useEffect(() => {\n setSearchValue(mergedConfig.search.value);\n }, [mergedConfig.search.value]);\n\n useEffect(() => {\n setSearchResult(mergedConfig.search.result);\n }, [mergedConfig.search.result]);\n\n useEffect(() => {\n setIsShowingAllResults(mergedConfig.search.isShowingAllResults);\n }, [mergedConfig.search.isShowingAllResults]);\n\n const handleSearchChange = useCallback(\n (value: string): void => {\n setSearchValue(value);\n setSearchResult(null);\n setIsShowingAllResults(false);\n mergedConfig.search.onChange?.(value);\n },\n [mergedConfig.search],\n );\n\n const handleSearchSelect = useCallback(\n (value: VenueEventWithMarkets): void => {\n const nextSearchState = getSearchStateAfterSelect(value);\n setSearchValue(nextSearchState.value);\n setSearchResult(nextSearchState.result);\n setIsShowingAllResults(nextSearchState.isShowingAllResults);\n mergedConfig.search.onSelect?.(value);\n },\n [mergedConfig.search],\n );\n\n const handleOpenResults = useCallback((): void => {\n setIsShowingAllResults(true);\n mergedConfig.search.openResults?.();\n }, [mergedConfig.search]);\n\n const handleCloseResults = useCallback((): void => {\n setIsShowingAllResults(false);\n mergedConfig.search.closeResults?.();\n }, [mergedConfig.search]);\n\n const resolvedConfig = useMemo(() => {\n return {\n ...mergedConfig,\n chart: {\n ...mergedConfig.chart,\n selectedChartTimeRange,\n setSelectedChartTimeRange: handleSetSelectedChartTimeRange,\n },\n search: {\n ...mergedConfig.search,\n value: searchValue,\n onChange: handleSearchChange,\n onSelect: handleSearchSelect,\n openResults: handleOpenResults,\n closeResults: handleCloseResults,\n result: searchResult,\n isShowingAllResults,\n },\n };\n }, [\n handleCloseResults,\n handleOpenResults,\n handleSearchChange,\n handleSearchSelect,\n handleSetSelectedChartTimeRange,\n isShowingAllResults,\n mergedConfig,\n searchResult,\n searchValue,\n selectedChartTimeRange,\n ]);\n\n useEffect(() => {\n persistConfig({\n locale: resolvedConfig.general.locale,\n theme: resolvedConfig.general.theme,\n selectedChartTimeRange: resolvedConfig.chart.selectedChartTimeRange,\n });\n }, [\n resolvedConfig.general.locale,\n resolvedConfig.general.theme,\n resolvedConfig.chart.selectedChartTimeRange,\n ]);\n\n useEffect(() => {\n applyThemeToDocument(resolvedConfig.general.theme);\n }, [resolvedConfig.general.theme]);\n\n useEffect(() => {\n warnIfAggStylesAreMissing();\n }, []);\n\n const resolvedRootClassName = [\n DEFAULT_AGG_ROOT_CLASS_NAME,\n resolvedConfig.general.theme === \"dark\" ? \"dark\" : null,\n resolvedConfig.general.rootClassName,\n ]\n .filter(Boolean)\n .join(\" \");\n\n logConfig(resolvedConfig, resolvedConfig.enableLogs);\n\n return (\n <AggLabelsContext.Provider value={resolvedConfig.general.labels}>\n <AggUiContext.Provider value={resolvedConfig}>\n <EventTradingProvider enableLogs={resolvedConfig.enableLogs}>\n <div\n className={resolvedRootClassName}\n data-agg-animations={resolvedConfig.features.enableAnimations ? \"true\" : \"false\"}\n data-agg-gradients={resolvedConfig.features.enableGradients ? \"true\" : \"false\"}\n data-agg-theme={resolvedConfig.general.theme}\n >\n {children}\n </div>\n </EventTradingProvider>\n </AggUiContext.Provider>\n </AggLabelsContext.Provider>\n );\n};\n","import { useQueryClient } from \"@tanstack/react-query\";\nimport { AggAuthProvider } from \"./auth-provider\";\nimport { AggBalanceProvider } from \"./balance-provider\";\nimport { AggClientProvider } from \"./client-provider\";\nimport { AggExecutionModeProvider } from \"./execution-mode-provider\";\nimport { EventListStateProvider } from \"./event-list-state-context\";\nimport { AggWebSocketProvider } from \"./ws-provider\";\nimport type { AggProviderProps } from \"./types\";\nimport { AggUiProvider } from \"./ui-provider\";\n\nlet hasWarnedMissingQueryClient = false;\n\nfunction useQueryClientCheck(): void {\n try {\n useQueryClient();\n } catch {\n if (!hasWarnedMissingQueryClient) {\n hasWarnedMissingQueryClient = true;\n console.error(\n \"[agg] AggProvider requires a QueryClientProvider ancestor. \" +\n \"Wrap AggProvider in a <QueryClientProvider client={queryClient}>.\",\n );\n }\n }\n}\n\nexport const AggProvider = ({ client, config, children }: AggProviderProps): React.JSX.Element => {\n useQueryClientCheck();\n\n if (!client) {\n throw new Error(\n \"AggProvider requires a valid AggClient instance. \" +\n \"Create one with createAggClient() and pass it via the 'client' prop.\",\n );\n }\n\n return (\n <AggClientProvider client={client}>\n <AggUiProvider config={config}>\n {/* Above the balance provider: paper/live decides which balances to\n fetch, so the mode must be resolved before that query is keyed. */}\n <AggExecutionModeProvider>\n <EventListStateProvider>\n <AggWebSocketProvider>\n <AggAuthProvider>\n <AggBalanceProvider>{children}</AggBalanceProvider>\n </AggAuthProvider>\n </AggWebSocketProvider>\n </EventListStateProvider>\n </AggExecutionModeProvider>\n </AggUiProvider>\n </AggClientProvider>\n );\n};\n","import { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport type {\n ExecuteManagedParams,\n ExecuteManagedResponse,\n SmartRouteResponse,\n} from \"@agg-build/sdk\";\nimport { useAggClient } from \"../core/provider\";\nimport { executionKeys } from \"./query-keys\";\nimport { invalidateBalanceQueries } from \"./balance-invalidation\";\n\nexport interface UseExecuteManagedOptions {\n onSuccess?: (data: ExecuteManagedResponse) => void;\n onError?: (error: Error) => void;\n}\n\n/**\n * Mutation hook for executing a previously quoted managed trade.\n * On success, invalidates orders, positions, and balances queries.\n */\nexport function useExecuteManaged(options?: UseExecuteManagedOptions) {\n const client = useAggClient();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: (params: ExecuteManagedParams) => client.executeManaged(params),\n onSuccess: (data) => {\n // The progress surface retains the accepted execution. Remove its consumed\n // ticket from every matching route cache before the order form reappears.\n queryClient.setQueriesData<SmartRouteResponse>({ queryKey: [\"smart-route\"] }, (route) => {\n if (!route) return route;\n const consumedPrimary = route.quoteId === data.quoteId;\n const consumedComparison = route.venueSoloQuotes?.some(\n (quote) => quote.quoteId === data.quoteId,\n );\n if (!consumedPrimary && !consumedComparison) return route;\n return {\n ...route,\n ...(consumedPrimary ? { quoteId: \"\" } : {}),\n ...(consumedComparison\n ? {\n venueSoloQuotes: route.venueSoloQuotes!.map((quote) =>\n quote.quoteId === data.quoteId ? { ...quote, quoteId: \"\" } : quote,\n ),\n }\n : {}),\n };\n });\n queryClient.invalidateQueries({ queryKey: executionKeys.ordersPrefix() });\n queryClient.invalidateQueries({ queryKey: executionKeys.positionsPrefix() });\n invalidateBalanceQueries(queryClient);\n options?.onSuccess?.(data);\n },\n onError: options?.onError,\n });\n}\n","import { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport type { PlaceLimitOrderParams, PlaceLimitOrderResponse } from \"@agg-build/sdk\";\nimport { useAggClient } from \"../core/provider\";\nimport { invalidateBalanceQueries } from \"./balance-invalidation\";\nimport { executionKeys } from \"./query-keys\";\n\nexport interface UsePlaceLimitOrderOptions {\n onSuccess?: (data: PlaceLimitOrderResponse) => void;\n onError?: (error: Error) => void;\n}\n\nexport function usePlaceLimitOrder(options?: UsePlaceLimitOrderOptions) {\n const client = useAggClient();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: (params: PlaceLimitOrderParams) => client.placeLimitOrder(params),\n onSuccess: (data) => {\n queryClient.invalidateQueries({ queryKey: executionKeys.ordersPrefix() });\n queryClient.invalidateQueries({ queryKey: [\"execution-orders\"] });\n queryClient.invalidateQueries({ queryKey: executionKeys.positionsPrefix() });\n invalidateBalanceQueries(queryClient);\n options?.onSuccess?.(data);\n },\n onError: options?.onError,\n });\n}\n","import { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport type { CancelManagedExecutionResponse } from \"@agg-build/sdk\";\nimport { useAggClient } from \"../core/provider\";\nimport {\n invalidateBalanceQueries,\n invalidatePositionQueries,\n invalidateUserActivityQueries,\n} from \"./balance-invalidation\";\nimport { executionKeys } from \"./query-keys\";\n\nexport interface UseCancelManagedOrderOptions {\n onSuccess?: (data: CancelManagedExecutionResponse, orderId: string) => void;\n onError?: (error: Error, orderId: string) => void;\n}\n\nexport function useCancelManagedOrder(options?: UseCancelManagedOrderOptions) {\n const client = useAggClient();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: (orderId: string) => client.cancelManagedOrder(orderId),\n onSuccess: (data, orderId) => {\n queryClient.invalidateQueries({ queryKey: executionKeys.ordersPrefix() });\n queryClient.invalidateQueries({ queryKey: [\"execution-orders\"] });\n invalidatePositionQueries(queryClient);\n invalidateBalanceQueries(queryClient);\n invalidateUserActivityQueries(queryClient);\n options?.onSuccess?.(data, orderId);\n },\n onError: (error, orderId) => {\n options?.onError?.(error, orderId);\n },\n });\n}\n","import { useQuery } from \"@tanstack/react-query\";\nimport type { GetPositionsParams } from \"@agg-build/sdk\";\nimport { useAggClient } from \"../core/provider\";\nimport { executionKeys } from \"./query-keys\";\n\nexport interface UsePositionsOptions extends GetPositionsParams {\n enabled?: boolean;\n}\n\n/**\n * Query hook for fetching user positions grouped by matched market.\n */\nexport function usePositions(options?: UsePositionsOptions) {\n const client = useAggClient();\n const { enabled = true, cursor, limit, status, mode } = options ?? {};\n\n const query = useQuery({\n queryKey: executionKeys.positions(cursor, limit, status, mode),\n queryFn: () => client.getPositions({ cursor, limit, status, ...(mode ? { mode } : {}) }),\n enabled,\n staleTime: 10_000,\n gcTime: 5 * 60_000,\n retry: 1,\n });\n\n return {\n ...query,\n positions: query.data?.data,\n nextCursor: query.data?.nextCursor,\n hasMore: query.data?.hasMore ?? false,\n };\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\";\nimport type {\n ExecutionStatusOrder,\n ExecutionStatusResponse,\n ExecutionStatusStep,\n WsBalanceUpdate,\n WsOrderEvent,\n WsOrderSubmitted,\n} from \"@agg-build/sdk\";\nimport { useAggClient } from \"../core/providers/hooks\";\nimport {\n useOnBalanceUpdate,\n useOnOrderEvent,\n useOnOrderSubmitted,\n} from \"../core/providers/ws-provider\";\n\n// `expired` is included alongside the venue-fill statuses so the HTTP poll\n// fallback recognises orders that the server timed out before the venue\n// ever submitted them. Without this the modal would keep polling indefinitely\n// when the server-side row settled on `expired` but no terminal WS event\n// landed (reconnect, dropped event, or the row was flipped before the WS\n// subscribe completed). Mirrors the WS-side `expired` handling below.\nconst TERMINAL_ORDER_STATUSES = new Set([\n \"filled\",\n \"partial_fill\",\n \"failed\",\n \"cancelled\",\n \"expired\",\n]);\nconst ORDER_POLL_INTERVAL_MS = 5000;\n\nfunction mapOrderStatusToTerminalEvent(\n status: string,\n): ExecutionTerminalOrderEvent[\"event\"] | null {\n if (status === \"filled\") return \"filled\";\n if (status === \"partial_fill\") return \"partial_fill\";\n if (status === \"failed\" || status === \"cancelled\" || status === \"expired\") return \"failed\";\n return null;\n}\n\nexport const mergeTerminalOrderEvents = (\n currentEvents: ExecutionTerminalOrderEvent[],\n incomingEvents: ExecutionTerminalOrderEvent[],\n): ExecutionTerminalOrderEvent[] => {\n const mergedByOrderId = new Map(currentEvents.map((event) => [event.orderId, event]));\n\n for (const incomingEvent of incomingEvents) {\n const currentEvent = mergedByOrderId.get(incomingEvent.orderId);\n if (!currentEvent) {\n mergedByOrderId.set(incomingEvent.orderId, incomingEvent);\n continue;\n }\n\n // A confirmed full fill is terminal and monotonic. In particular, do not\n // let a delayed HTTP replica/poll response downgrade a WS success.\n if (currentEvent.event === \"filled\") continue;\n if (incomingEvent.event === \"filled\" || incomingEvent.timestamp >= currentEvent.timestamp) {\n mergedByOrderId.set(incomingEvent.orderId, incomingEvent);\n }\n }\n\n return [...mergedByOrderId.values()].sort((left, right) => left.timestamp - right.timestamp);\n};\n\nexport type ExecutionProgressPhase = \"idle\" | \"pending\" | \"order_submitted\" | \"balance_updated\";\n\nexport interface DagStepProgress {\n dagRunId: string;\n totalSteps: number;\n currentSequence: number;\n currentStepType: string | null;\n completedSequences: number[];\n /** Maps sequence number → stepType string for all steps seen so far. */\n stepTypes: Record<number, string>;\n status: \"running\" | \"completed\" | \"failed\";\n errorReason: string | null;\n}\n\nexport interface ExecutionTerminalOrderEvent {\n orderId: string;\n venue: string;\n event: \"filled\" | \"partial_fill\" | \"failed\";\n filledAmountRaw?: string;\n remainingAmountRaw?: string;\n /** Actual shares + payout received, 6-decimal atomic. Set by the venue's\n * finalize handler on filled/partial_fill — the source of truth for the\n * execution summary so it never reuses the stale quote estimate. */\n actualSharesRaw?: string;\n actualToWinRaw?: string;\n /** Quote-time shares + payout, 6-decimal atomic. Snapshot of what the user\n * accepted; surfaced for \"Quoted X / Got Y\" diffs. */\n quotedSharesRaw?: string;\n quotedToWinRaw?: string;\n /** Avg execution price (decimal string). Pair with `quotedPriceRaw`\n * for inline slippage diffs and to derive shares when actual*Raw is absent. */\n executionPriceRaw?: string;\n quotedPriceRaw?: string;\n errorReason?: string;\n timestamp: number;\n}\n\nexport type ExecutionStepProgress = ExecutionStatusStep;\n\nexport type ExecutionRawStepProgress = Pick<\n ExecutionStatusStep,\n \"sequence\" | \"stepType\" | \"status\" | \"attempt\" | \"startedAt\" | \"completedAt\" | \"errorReason\"\n>;\n\nconst EXECUTION_STEP_STATUS_RANK: Record<ExecutionRawStepProgress[\"status\"], number> = {\n pending: 0,\n in_progress: 1,\n failed: 2,\n completed: 3,\n skipped: 3,\n};\n\nconst getExecutionStepIdentity = (step: ExecutionStepProgress): string =>\n [step.groupId, step.sequence, step.stepType, ...step.orderIds].join(\":\");\n\nconst getExecutionGroupAttempt = (steps: ExecutionStepProgress[]): number =>\n steps.reduce((highestAttempt, step) => Math.max(highestAttempt, step.attempt), 0);\n\nconst groupExecutionStepsByGroupId = (\n steps: ExecutionStepProgress[],\n): Map<string, ExecutionStepProgress[]> => {\n const groupedSteps = new Map<string, ExecutionStepProgress[]>();\n for (const step of steps) {\n const existingSteps = groupedSteps.get(step.groupId) ?? [];\n existingSteps.push(step);\n groupedSteps.set(step.groupId, existingSteps);\n }\n return groupedSteps;\n};\n\nconst pickExecutionGroupPresentation = (\n step: ExecutionStepProgress,\n): Pick<ExecutionStepProgress, \"groupStatus\" | \"label\" | \"bridge\"> => ({\n groupStatus: step.groupStatus,\n label: step.label,\n ...(step.bridge ? { bridge: step.bridge } : {}),\n});\n\n/**\n * Merge polling/WS snapshots without letting a delayed response visually move\n * a completed group backwards. Enriched status responses can repeat a raw\n * sequence when shared setup/fill work is copied per venue leg, so sequence\n * alone is not a valid identity here.\n */\nexport const mergeExecutionStepProgress = (\n previous: ExecutionStepProgress[],\n incoming: ExecutionStepProgress[],\n): ExecutionStepProgress[] => {\n const previousByGroupId = groupExecutionStepsByGroupId(previous);\n const incomingByGroupId = groupExecutionStepsByGroupId(incoming);\n const mergedByIdentity = new Map(previous.map((step) => [getExecutionStepIdentity(step), step]));\n\n for (const step of incoming) {\n const identity = getExecutionStepIdentity(step);\n const current = mergedByIdentity.get(identity);\n if (!current || step.attempt > current.attempt) {\n mergedByIdentity.set(identity, step);\n continue;\n }\n\n if (step.attempt < current.attempt) continue;\n if (EXECUTION_STEP_STATUS_RANK[step.status] < EXECUTION_STEP_STATUS_RANK[current.status]) {\n continue;\n }\n\n mergedByIdentity.set(identity, step);\n }\n\n const groupPresentation = new Map<\n string,\n Pick<ExecutionStepProgress, \"groupStatus\" | \"label\" | \"bridge\">\n >();\n const groupIds = new Set([...previousByGroupId.keys(), ...incomingByGroupId.keys()]);\n\n for (const groupId of groupIds) {\n const previousGroup = previousByGroupId.get(groupId) ?? [];\n const incomingGroup = incomingByGroupId.get(groupId) ?? [];\n const previousStep = previousGroup[0];\n const incomingStep = incomingGroup[0];\n if (!previousStep && incomingStep) {\n groupPresentation.set(groupId, pickExecutionGroupPresentation(incomingStep));\n continue;\n }\n if (!incomingStep && previousStep) {\n groupPresentation.set(groupId, pickExecutionGroupPresentation(previousStep));\n continue;\n }\n if (!previousStep || !incomingStep) continue;\n\n const isNewerAttempt =\n getExecutionGroupAttempt(incomingGroup) > getExecutionGroupAttempt(previousGroup);\n const shouldUseIncoming =\n isNewerAttempt ||\n EXECUTION_STEP_STATUS_RANK[incomingStep.groupStatus] >=\n EXECUTION_STEP_STATUS_RANK[previousStep.groupStatus];\n groupPresentation.set(\n groupId,\n pickExecutionGroupPresentation(shouldUseIncoming ? incomingStep : previousStep),\n );\n }\n\n return Array.from(mergedByIdentity.values())\n .map((step) => ({ ...step, ...groupPresentation.get(step.groupId) }))\n .sort((left, right) => {\n if (left.sequence !== right.sequence) return left.sequence - right.sequence;\n return getExecutionStepIdentity(left).localeCompare(getExecutionStepIdentity(right));\n });\n};\n\nexport const mergeRawExecutionStepProgress = (\n previous: ExecutionRawStepProgress[],\n incoming: ExecutionRawStepProgress[],\n): ExecutionRawStepProgress[] => {\n const mergedBySequence = new Map(previous.map((step) => [step.sequence, step]));\n\n for (const step of incoming) {\n const current = mergedBySequence.get(step.sequence);\n if (!current || step.attempt > current.attempt) {\n mergedBySequence.set(step.sequence, step);\n continue;\n }\n if (step.attempt < current.attempt) continue;\n if (EXECUTION_STEP_STATUS_RANK[step.status] < EXECUTION_STEP_STATUS_RANK[current.status]) {\n continue;\n }\n mergedBySequence.set(step.sequence, step);\n }\n\n return Array.from(mergedBySequence.values()).sort(\n (left, right) => left.sequence - right.sequence,\n );\n};\n\nexport const mergeExecutionStatusOrders = (\n previous: ExecutionStatusOrder[],\n incoming: ExecutionStatusOrder[],\n): ExecutionStatusOrder[] => {\n const mergedByOrderId = new Map(previous.map((order) => [order.orderId, order]));\n\n for (const order of incoming) {\n const current = mergedByOrderId.get(order.orderId);\n if (!current || new Date(order.updatedAt).getTime() >= new Date(current.updatedAt).getTime()) {\n mergedByOrderId.set(order.orderId, order);\n }\n }\n\n return Array.from(mergedByOrderId.values());\n};\n\nexport interface UseExecutionProgressOptions {\n orderIds: string[] | null;\n quoteId?: string | null;\n enabled: boolean;\n mode?: \"live\" | \"paper\";\n}\n\nexport interface UseExecutionProgressResult {\n phase: ExecutionProgressPhase;\n submittedOrders: WsOrderSubmitted[];\n latestBalance: WsBalanceUpdate | null;\n dagProgress: DagStepProgress | null;\n terminalOrderEvents: ExecutionTerminalOrderEvent[];\n executionSteps: ExecutionStepProgress[];\n rawExecutionSteps: ExecutionRawStepProgress[];\n executionOrders: ExecutionStatusOrder[];\n}\n\nexport function useExecutionProgress({\n orderIds,\n quoteId,\n enabled,\n mode,\n}: UseExecutionProgressOptions): UseExecutionProgressResult {\n const [phase, setPhase] = useState<ExecutionProgressPhase>(\"idle\");\n const [submittedOrders, setSubmittedOrders] = useState<WsOrderSubmitted[]>([]);\n const [latestBalance, setLatestBalance] = useState<WsBalanceUpdate | null>(null);\n const [dagProgress, setDagProgress] = useState<DagStepProgress | null>(null);\n const [terminalOrderEvents, setTerminalOrderEvents] = useState<ExecutionTerminalOrderEvent[]>([]);\n const [executionSteps, setExecutionSteps] = useState<ExecutionStepProgress[]>([]);\n const [rawExecutionSteps, setRawExecutionSteps] = useState<ExecutionRawStepProgress[]>([]);\n const [executionOrders, setExecutionOrders] = useState<ExecutionStatusOrder[]>([]);\n const orderIdSetRef = useRef(new Set<string>());\n const submittedOrderVenueByIdRef = useRef(new Map<string, string>());\n\n useEffect(() => {\n orderIdSetRef.current = new Set(orderIds ?? []);\n }, [orderIds]);\n\n useEffect(() => {\n if (enabled && orderIds && orderIds.length > 0) {\n setPhase(\"pending\");\n setSubmittedOrders([]);\n setLatestBalance(null);\n setDagProgress(null);\n setTerminalOrderEvents([]);\n setExecutionSteps([]);\n setRawExecutionSteps([]);\n setExecutionOrders([]);\n submittedOrderVenueByIdRef.current = new Map();\n } else if (!enabled) {\n setPhase(\"idle\");\n if (!orderIds || orderIds.length === 0) {\n setSubmittedOrders([]);\n setLatestBalance(null);\n setDagProgress(null);\n setTerminalOrderEvents([]);\n setExecutionSteps([]);\n setRawExecutionSteps([]);\n setExecutionOrders([]);\n }\n submittedOrderVenueByIdRef.current = new Map();\n }\n }, [enabled, orderIds]);\n\n const handleOrderSubmitted = useCallback((msg: WsOrderSubmitted): void => {\n if (!orderIdSetRef.current.has(msg.orderId)) return;\n\n const trimmedVenue = msg.venue.trim();\n if (trimmedVenue) {\n submittedOrderVenueByIdRef.current.set(msg.orderId, trimmedVenue);\n }\n\n setSubmittedOrders((prev) => [...prev, msg]);\n setPhase(\"order_submitted\");\n }, []);\n\n const handleBalanceUpdate = useCallback((msg: WsBalanceUpdate): void => {\n setLatestBalance(msg);\n setPhase((current) => {\n if (current === \"order_submitted\" || current === \"pending\") {\n return \"balance_updated\";\n }\n return current;\n });\n }, []);\n\n const handleOrderEvent = useCallback((msg: WsOrderEvent): void => {\n if (!orderIdSetRef.current.has(msg.orderId)) return;\n\n const trimmedVenue = msg.venue.trim();\n if (trimmedVenue) {\n submittedOrderVenueByIdRef.current.set(msg.orderId, trimmedVenue);\n }\n\n const { event } = msg;\n\n // Terminal-order events: any WS message that means \"this orderId is\n // done, stop waiting on it\". Mapped down to the three SDK-exposed\n // terminal events (`filled` / `partial_fill` / `failed`) so the\n // place-order UI's `deriveAggregateOrderStatus` can read one shape.\n //\n // `expired` and `dag_cancelled` are non-failure terminal shapes that\n // still need to unwedge the UI:\n // - `expired` — server-side admission timeout / staleness sweep.\n // - `dag_cancelled` — operator/manual cancel. The order never made\n // it to the venue, so there is no fill data; surface as `failed`\n // so the modal exits \"pending\" instead of hanging on the hard\n // 60 s client-side timeout (which historically was the only thing\n // that broke users out of this state).\n // `bridge_ws_subscribe_failed` is a venue-agnostic infra failure that\n // also maps to `failed` (kept here to preserve the existing copy).\n if (\n event === \"filled\" ||\n event === \"partial_fill\" ||\n event === \"failed\" ||\n event === \"bridge_ws_subscribe_failed\" ||\n event === \"expired\" ||\n event === \"dag_cancelled\" ||\n event === \"cancelled\"\n ) {\n const mappedEvent: ExecutionTerminalOrderEvent[\"event\"] =\n event === \"filled\" || event === \"partial_fill\" ? event : \"failed\";\n const resolvedVenue =\n trimmedVenue || submittedOrderVenueByIdRef.current.get(msg.orderId) || \"\";\n if (resolvedVenue) {\n submittedOrderVenueByIdRef.current.set(msg.orderId, resolvedVenue);\n }\n\n const fallbackErrorReason =\n event === \"bridge_ws_subscribe_failed\"\n ? \"Bridge event subscription failed.\"\n : event === \"expired\"\n ? \"Order expired before it could be submitted.\"\n : event === \"dag_cancelled\"\n ? \"Order was cancelled before submission.\"\n : undefined;\n\n const nextTerminalEvent: ExecutionTerminalOrderEvent = {\n orderId: msg.orderId,\n venue: resolvedVenue,\n event: mappedEvent,\n filledAmountRaw: msg.filledAmountRaw,\n remainingAmountRaw: msg.remainingAmountRaw,\n actualSharesRaw: msg.actualSharesRaw,\n actualToWinRaw: msg.actualToWinRaw,\n quotedSharesRaw: msg.quotedSharesRaw,\n quotedToWinRaw: msg.quotedToWinRaw,\n executionPriceRaw: msg.executionPriceRaw,\n quotedPriceRaw: msg.quotedPriceRaw,\n errorReason: msg.errorReason ?? fallbackErrorReason,\n timestamp: msg.timestamp,\n };\n\n setTerminalOrderEvents((previous) => mergeTerminalOrderEvents(previous, [nextTerminalEvent]));\n return;\n }\n\n if (event === \"dag_started\") {\n // Pre-populate stepTypes from dag_started so labels are available\n // before each step_started event arrives (avoids \"Step N of M\" flash).\n const initialStepTypes: Record<number, string> = {};\n if (msg.stepTypes) {\n for (const [seq, type] of Object.entries(msg.stepTypes)) {\n initialStepTypes[Number(seq)] = type;\n }\n }\n setDagProgress({\n dagRunId: msg.dagRunId ?? \"\",\n totalSteps: msg.totalSteps ?? 0,\n currentSequence: 0,\n currentStepType: null,\n completedSequences: [],\n stepTypes: initialStepTypes,\n status: \"running\",\n errorReason: null,\n });\n setRawExecutionSteps((previous) =>\n mergeRawExecutionStepProgress(\n previous,\n Object.entries(initialStepTypes).map(([sequence, stepType]) => ({\n sequence: Number(sequence),\n stepType,\n status: \"pending\",\n attempt: 0,\n startedAt: null,\n completedAt: null,\n errorReason: null,\n })),\n ),\n );\n return;\n }\n\n if (event === \"step_started\" || event === \"step_retrying\") {\n setDagProgress((prev) => {\n if (!prev) return prev;\n const seq = msg.sequence ?? prev.currentSequence;\n const stepType = msg.stepType ?? prev.currentStepType;\n return {\n ...prev,\n currentSequence: seq,\n currentStepType: stepType,\n stepTypes: stepType != null ? { ...prev.stepTypes, [seq]: stepType } : prev.stepTypes,\n };\n });\n const { sequence, stepType } = msg;\n if (sequence != null && stepType) {\n setRawExecutionSteps((previous) =>\n mergeRawExecutionStepProgress(previous, [\n {\n sequence,\n stepType,\n status: \"in_progress\",\n attempt:\n msg.attempt ?? previous.find((step) => step.sequence === sequence)?.attempt ?? 0,\n startedAt: new Date(msg.timestamp).toISOString(),\n completedAt: null,\n errorReason: null,\n },\n ]),\n );\n }\n return;\n }\n\n if (event === \"step_waiting\") {\n setDagProgress((prev) => {\n if (!prev) return prev;\n const seq = msg.sequence ?? prev.currentSequence;\n const stepType = msg.stepType ?? prev.currentStepType;\n return {\n ...prev,\n currentSequence: seq,\n currentStepType: stepType,\n stepTypes: stepType != null ? { ...prev.stepTypes, [seq]: stepType } : prev.stepTypes,\n };\n });\n const { sequence, stepType } = msg;\n if (sequence != null && stepType) {\n setRawExecutionSteps((previous) =>\n mergeRawExecutionStepProgress(previous, [\n {\n sequence,\n stepType,\n status: \"in_progress\",\n attempt:\n msg.attempt ?? previous.find((step) => step.sequence === sequence)?.attempt ?? 0,\n startedAt: new Date(msg.timestamp).toISOString(),\n completedAt: null,\n errorReason: null,\n },\n ]),\n );\n }\n return;\n }\n\n if (event === \"step_completed\") {\n setDagProgress((prev) => {\n if (!prev) return prev;\n const seq = msg.sequence;\n const stepType = msg.stepType;\n return {\n ...prev,\n completedSequences:\n seq != null ? [...prev.completedSequences, seq] : prev.completedSequences,\n stepTypes:\n seq != null && stepType != null\n ? { ...prev.stepTypes, [seq]: stepType }\n : prev.stepTypes,\n };\n });\n const { sequence, stepType } = msg;\n if (sequence != null && stepType) {\n const completedAt = new Date(msg.timestamp).toISOString();\n setRawExecutionSteps((previous) =>\n mergeRawExecutionStepProgress(previous, [\n {\n sequence,\n stepType,\n status: \"completed\",\n attempt:\n msg.attempt ?? previous.find((step) => step.sequence === sequence)?.attempt ?? 0,\n startedAt: null,\n completedAt,\n errorReason: null,\n },\n ]),\n );\n }\n return;\n }\n\n if (event === \"dag_completed\") {\n setDagProgress((prev) => {\n if (!prev) return prev;\n return { ...prev, status: \"completed\" };\n });\n return;\n }\n\n // For DAG failure events we can't early-return when `prev` is null:\n // a WS reconnect mid-execution may deliver `step_failed` / `dag_failed`\n // on the new socket without a preceding `dag_started`, which would\n // otherwise leave the modal stuck in \"submitting\" forever. When that\n // happens, we synthesize a minimal failed progress object from whatever\n // metadata the failure event carries so the UI can transition.\n const buildFailedProgress = (prev: DagStepProgress | null): DagStepProgress => {\n const seq = msg.sequence ?? prev?.currentSequence ?? 0;\n const stepType = msg.stepType ?? prev?.currentStepType ?? null;\n const baseStepTypes = prev?.stepTypes ?? {};\n const stepTypes = seq && stepType ? { ...baseStepTypes, [seq]: stepType } : baseStepTypes;\n return {\n dagRunId: msg.dagRunId ?? prev?.dagRunId ?? \"\",\n totalSteps: msg.totalSteps ?? prev?.totalSteps ?? 0,\n currentSequence: seq,\n currentStepType: stepType,\n completedSequences: prev?.completedSequences ?? [],\n stepTypes,\n status: \"failed\",\n errorReason: msg.errorReason ?? prev?.errorReason ?? null,\n };\n };\n\n if (event === \"step_failed\") {\n setDagProgress((prev) => buildFailedProgress(prev));\n const { sequence, stepType } = msg;\n if (sequence != null && stepType) {\n setRawExecutionSteps((previous) =>\n mergeRawExecutionStepProgress(previous, [\n {\n sequence,\n stepType,\n status: \"failed\",\n attempt:\n msg.attempt ?? previous.find((step) => step.sequence === sequence)?.attempt ?? 0,\n startedAt: null,\n completedAt: new Date(msg.timestamp).toISOString(),\n errorReason: msg.errorReason ?? null,\n },\n ]),\n );\n }\n return;\n }\n\n if (event === \"dag_failed\") {\n setDagProgress((prev) => buildFailedProgress(prev));\n return;\n }\n }, []);\n\n const isStatusPolling = enabled && !!quoteId;\n const isListening = enabled && !!orderIds && orderIds.length > 0;\n\n useOnOrderSubmitted(isListening ? handleOrderSubmitted : null);\n useOnBalanceUpdate(isListening ? handleBalanceUpdate : null);\n useOnOrderEvent(isListening ? handleOrderEvent : null);\n\n // Race mitigation + ongoing reconcile: WS listener subscribes only after\n // `orderIds` are known (post place-order response), but DAG events can fire\n // within ~500ms inside the place-order handler, and `ws-gateway` fan-out is\n // unbuffered. We fire an immediate HTTP reconcile on subscribe, then poll\n // every ORDER_POLL_INTERVAL_MS for any orderId that hasn't reached a\n // terminal event yet, so transient WS drops don't leave the modal hung.\n const client = useAggClient();\n const terminalOrderIdsRef = useRef<Set<string>>(new Set());\n const pollInFlightRef = useRef(false);\n\n const buildSubmittedOrdersFromStatus = useCallback(\n (orders: ExecutionStatusOrder[]): WsOrderSubmitted[] => {\n return orders.map((order) => ({\n type: \"order_submitted\",\n venue: order.venue,\n orderId: order.orderId,\n side: \"\",\n price: Number(order.executionPriceRaw ?? order.quotedPriceRaw ?? 0),\n size: 0,\n timestamp: new Date(order.updatedAt).getTime() / 1000,\n }));\n },\n [],\n );\n\n const buildTerminalEventsFromStatus = useCallback(\n (\n status: ExecutionStatusResponse,\n fallbackOrderIds: string[],\n fallbackTimestamp: number,\n ): ExecutionTerminalOrderEvent[] => {\n const terminalEvents = status.orders\n .map((order) => {\n const mappedEvent = order.event ?? mapOrderStatusToTerminalEvent(order.status);\n if (!mappedEvent) return null;\n\n return {\n orderId: order.orderId,\n venue: order.venue,\n event: mappedEvent,\n filledAmountRaw: order.filledAmountRaw,\n remainingAmountRaw: order.remainingAmountRaw,\n actualSharesRaw: order.actualSharesRaw,\n actualToWinRaw: order.actualToWinRaw,\n quotedSharesRaw: order.quotedSharesRaw,\n quotedToWinRaw: order.quotedToWinRaw,\n executionPriceRaw: order.executionPriceRaw,\n quotedPriceRaw: order.quotedPriceRaw,\n errorReason: order.errorReason ?? order.partialFillReason,\n timestamp: new Date(order.updatedAt).getTime() || fallbackTimestamp,\n };\n })\n .filter((order) => order != null) as ExecutionTerminalOrderEvent[];\n\n if (!status.terminal) {\n return terminalEvents;\n }\n\n const coveredOrderIds = new Set(terminalEvents.map((event) => event.orderId));\n const fallbackEvent: ExecutionTerminalOrderEvent[\"event\"] | null =\n status.overallState === \"filled\"\n ? \"filled\"\n : status.overallState === \"partially_filled\"\n ? \"partial_fill\"\n : [\"failed\", \"cancelled\", \"expired\"].includes(status.overallState)\n ? \"failed\"\n : null;\n if (!fallbackEvent) return terminalEvents;\n\n return [\n ...terminalEvents,\n ...fallbackOrderIds\n .filter((orderId) => !coveredOrderIds.has(orderId))\n .map((orderId) => ({\n orderId,\n venue: \"\",\n event: fallbackEvent,\n errorReason:\n fallbackEvent === \"failed\" ? (status.errorReason ?? \"Execution failed.\") : undefined,\n timestamp: fallbackTimestamp,\n })),\n ];\n },\n [],\n );\n\n const setFatalPollingFailure = useCallback((message: string, failedOrderIds: string[]): void => {\n setDagProgress((prev) => ({\n dagRunId: prev?.dagRunId ?? \"\",\n totalSteps: prev?.totalSteps ?? 0,\n currentSequence: prev?.currentSequence ?? 0,\n currentStepType: prev?.currentStepType ?? null,\n completedSequences: prev?.completedSequences ?? [],\n stepTypes: prev?.stepTypes ?? {},\n status: \"failed\",\n errorReason: message,\n }));\n\n setTerminalOrderEvents((prev) => {\n const existingByOrderId = new Map(prev.map((event) => [event.orderId, event]));\n const timestamp = Date.now();\n\n for (const orderId of failedOrderIds) {\n if (existingByOrderId.has(orderId)) continue;\n existingByOrderId.set(orderId, {\n orderId,\n venue: \"\",\n event: \"failed\",\n errorReason: message,\n timestamp,\n });\n }\n\n return Array.from(existingByOrderId.values()).sort(\n (left, right) => left.timestamp - right.timestamp,\n );\n });\n }, []);\n\n useEffect(() => {\n terminalOrderIdsRef.current = new Set(terminalOrderEvents.map((e) => e.orderId));\n }, [terminalOrderEvents]);\n\n useEffect(() => {\n if (!isStatusPolling || !quoteId) return;\n\n let cancelled = false;\n let timeout: ReturnType<typeof setTimeout> | null = null;\n\n const stopPolling = (): void => {\n if (timeout !== null) {\n clearTimeout(timeout);\n timeout = null;\n }\n };\n\n const scheduleNextPoll = (delayMs: number | null | undefined): void => {\n if (cancelled) return;\n timeout = setTimeout(() => {\n void pollExecutionStatus();\n }, delayMs ?? ORDER_POLL_INTERVAL_MS);\n };\n\n const pollExecutionStatus = async (): Promise<void> => {\n if (cancelled || pollInFlightRef.current) return;\n\n pollInFlightRef.current = true;\n try {\n const status = await client.getExecutionStatus({\n quoteId,\n ...(mode ? { mode } : {}),\n });\n if (cancelled) return;\n\n const resolvedOrderIds = status.orderIds.length > 0 ? status.orderIds : (orderIds ?? []);\n\n if (resolvedOrderIds.length > 0) {\n setPhase(\"order_submitted\");\n }\n\n setSubmittedOrders(buildSubmittedOrdersFromStatus(status.orders));\n setExecutionOrders((previous) => mergeExecutionStatusOrders(previous, status.orders));\n\n if (status.dagProgress) {\n setDagProgress({\n ...status.dagProgress,\n stepTypes: Object.fromEntries(\n Object.entries(status.dagProgress.stepTypes).map(([sequence, stepType]) => [\n Number(sequence),\n stepType,\n ]),\n ),\n });\n } else if (\n status.terminal &&\n [\"failed\", \"cancelled\", \"expired\"].includes(status.overallState)\n ) {\n setDagProgress((prev) => ({\n dagRunId: prev?.dagRunId ?? status.executionId ?? \"\",\n totalSteps: prev?.totalSteps ?? status.steps.length,\n currentSequence: prev?.currentSequence ?? 0,\n currentStepType: prev?.currentStepType ?? null,\n completedSequences: prev?.completedSequences ?? [],\n stepTypes: prev?.stepTypes ?? {},\n status: \"failed\",\n errorReason: status.errorReason,\n }));\n }\n\n setExecutionSteps((previous) => mergeExecutionStepProgress(previous, status.steps));\n setRawExecutionSteps((previous) =>\n mergeRawExecutionStepProgress(\n previous,\n status.steps.map((step) => ({\n sequence: step.sequence,\n stepType: step.stepType,\n status: step.status,\n attempt: step.attempt,\n startedAt: step.startedAt,\n completedAt: step.completedAt,\n errorReason: step.errorReason,\n })),\n ),\n );\n\n const fallbackTimestamp = Date.now();\n const nextTerminalEvents = buildTerminalEventsFromStatus(\n status,\n resolvedOrderIds,\n fallbackTimestamp,\n );\n setTerminalOrderEvents((previous) =>\n mergeTerminalOrderEvents(previous, nextTerminalEvents),\n );\n\n if (status.terminal) {\n stopPolling();\n return;\n }\n\n scheduleNextPoll(status.pollAfterMs);\n } catch (error) {\n if (cancelled) return;\n\n const statusCode =\n typeof error === \"object\" &&\n error != null &&\n \"status\" in error &&\n typeof (error as { status?: unknown }).status === \"number\"\n ? (error as { status: number }).status\n : null;\n\n if (statusCode === 400 || statusCode === 401 || statusCode === 403) {\n setFatalPollingFailure(\n error instanceof Error ? error.message : \"Execution status polling failed.\",\n orderIds ?? [],\n );\n stopPolling();\n return;\n }\n\n scheduleNextPoll(ORDER_POLL_INTERVAL_MS);\n } finally {\n pollInFlightRef.current = false;\n }\n };\n\n void pollExecutionStatus();\n\n return () => {\n cancelled = true;\n stopPolling();\n };\n }, [\n buildSubmittedOrdersFromStatus,\n buildTerminalEventsFromStatus,\n client,\n isStatusPolling,\n mode,\n orderIds,\n quoteId,\n setFatalPollingFailure,\n ]);\n\n useEffect(() => {\n if (isStatusPolling) return;\n if (!isListening || !orderIds?.length) return;\n\n let cancelled = false;\n let interval: ReturnType<typeof setInterval> | null = null;\n\n const stopPolling = (): void => {\n if (interval !== null) {\n clearInterval(interval);\n interval = null;\n }\n };\n\n const reconcile = async (): Promise<void> => {\n if (cancelled || pollInFlightRef.current) return;\n const pending = orderIds.filter((id) => !terminalOrderIdsRef.current.has(id));\n if (pending.length === 0) {\n stopPolling();\n return;\n }\n\n pollInFlightRef.current = true;\n try {\n const orders = await Promise.all(\n pending.map(async (orderId) => {\n try {\n const res = await client.getExecutionOrders({\n orderId,\n limit: 1,\n ...(mode ? { mode } : {}),\n });\n return res.data?.[0] ?? null;\n } catch {\n return null;\n }\n }),\n );\n if (cancelled) return;\n\n const terminalEvents: ExecutionTerminalOrderEvent[] = [];\n for (const order of orders) {\n if (!order) continue;\n if (!TERMINAL_ORDER_STATUSES.has(order.status)) continue;\n const mapped = mapOrderStatusToTerminalEvent(order.status);\n if (!mapped) continue;\n terminalEvents.push({\n orderId: order.id,\n venue: order.venue ?? \"\",\n event: mapped,\n filledAmountRaw: order.filledAmountRaw ?? undefined,\n actualSharesRaw: order.actualSharesRaw ?? undefined,\n actualToWinRaw: order.actualToWinRaw ?? undefined,\n quotedSharesRaw: order.quotedSharesRaw ?? undefined,\n quotedToWinRaw: order.quotedToWinRaw ?? undefined,\n executionPriceRaw: order.executionPrice ?? undefined,\n quotedPriceRaw: order.quotedPriceRaw ?? undefined,\n errorReason: order.errorMessage ?? undefined,\n timestamp: new Date(order.updatedAt).getTime() || Date.now(),\n });\n }\n if (terminalEvents.length > 0) {\n setTerminalOrderEvents((previous) => mergeTerminalOrderEvents(previous, terminalEvents));\n }\n\n // Stop polling immediately when this fetch covers all remaining\n // orders, rather than waiting for the ref sync + next tick.\n const covered = new Set([\n ...terminalOrderIdsRef.current,\n ...terminalEvents.map((e) => e.orderId),\n ]);\n if (orderIds.every((id) => covered.has(id))) {\n stopPolling();\n }\n } finally {\n pollInFlightRef.current = false;\n }\n };\n\n void reconcile();\n interval = setInterval(() => {\n void reconcile();\n }, ORDER_POLL_INTERVAL_MS);\n\n return () => {\n cancelled = true;\n stopPolling();\n };\n }, [client, isListening, isStatusPolling, mode, orderIds]);\n\n return {\n phase,\n submittedOrders,\n latestBalance,\n dagProgress,\n terminalOrderEvents,\n executionSteps,\n rawExecutionSteps,\n executionOrders,\n };\n}\n","import { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport type {\n CreateBalanceRefillPolicyParams,\n UpdateBalanceRefillPolicyParams,\n} from \"@agg-build/sdk\";\nimport { useAggClient } from \"../core/provider\";\nimport { executionKeys } from \"./query-keys\";\n\nexport interface UseBalanceRefillPoliciesOptions {\n enabled?: boolean;\n}\n\nexport function useBalanceRefillPolicies(options?: UseBalanceRefillPoliciesOptions) {\n const client = useAggClient();\n const queryClient = useQueryClient();\n const queryKey = executionKeys.balanceRefillPolicies();\n const query = useQuery({\n queryKey,\n queryFn: () => client.getBalanceRefillPolicies(),\n enabled: options?.enabled ?? true,\n staleTime: 15_000,\n refetchInterval: (state) =>\n state.state.data?.some((policy) =>\n [\"reserved\", \"executing\"].includes(policy.latestAttempt?.status ?? \"\"),\n )\n ? 5_000\n : false,\n });\n\n const createPolicy = useMutation({\n mutationFn: (params: CreateBalanceRefillPolicyParams) =>\n client.createBalanceRefillPolicy(params),\n onSuccess: (policy) => {\n queryClient.setQueryData(queryKey, [policy]);\n },\n });\n const updatePolicy = useMutation({\n mutationFn: ({\n policyId,\n params,\n }: {\n policyId: string;\n params: UpdateBalanceRefillPolicyParams;\n }) => client.updateBalanceRefillPolicy(policyId, params),\n onSuccess: (updated) => {\n queryClient.setQueryData(queryKey, (current: typeof query.data) =>\n (current ?? []).map((policy) => (policy.id === updated.id ? updated : policy)),\n );\n },\n });\n\n return {\n ...query,\n policies: query.data ?? [],\n createPolicy,\n updatePolicy,\n };\n}\n","import type { PositionGroup } from \"@agg-build/sdk\";\n\nexport interface ClosedPositionTotals {\n totalTraded: number;\n amountWon: number;\n returnPct: number;\n winningOutcomeIds: string[];\n isPartialWin: boolean;\n}\n\nexport const computeClosedPositionTotals = (group: PositionGroup): ClosedPositionTotals => {\n const outcomes = group.venueMarket.venueMarketOutcomes;\n // When the market hasn't resolved yet (e.g. user-closed exit on an open market),\n // the \"Amount won\" column reflects the realized/current value, not winner-only payouts.\n const isResolved = group.venueMarket.status === \"resolved\";\n let totalTraded = 0;\n let amountWon = 0;\n const winningOutcomeIds = new Set<string>();\n let winningCount = 0;\n let settledCount = 0;\n\n for (const outcome of outcomes) {\n totalTraded += outcome.avgEntryPrice * outcome.totalSize;\n\n if (isResolved) {\n if (outcome.winner === true) {\n amountWon += outcome.totalValue;\n winningCount += 1;\n\n for (const breakdown of outcome.venueBreakdown) {\n if (breakdown.venueMarketOutcomeId) {\n winningOutcomeIds.add(breakdown.venueMarketOutcomeId);\n }\n }\n }\n } else {\n amountWon += outcome.totalValue;\n }\n\n if (outcome.winner !== null) {\n settledCount += 1;\n }\n }\n\n const returnPct = totalTraded === 0 ? 0 : (amountWon - totalTraded) / totalTraded;\n\n return {\n totalTraded,\n amountWon,\n returnPct,\n winningOutcomeIds: Array.from(winningOutcomeIds),\n isPartialWin: winningCount > 0 && winningCount < settledCount,\n };\n};\n","import { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport type { RedeemRequest, RedeemResponse } from \"@agg-build/sdk\";\nimport { useAggClient } from \"../core/provider\";\nimport { useResolvedExecutionMode } from \"../use-resolved-execution-mode\";\nimport { invalidateUserClaimState } from \"./balance-invalidation\";\n\nexport class RedeemRejectedError extends Error {\n readonly response: RedeemResponse;\n\n constructor(message: string, response: RedeemResponse) {\n super(message);\n this.name = \"RedeemRejectedError\";\n this.response = response;\n }\n}\n\nconst isLegRejected = (status: RedeemResponse[\"results\"][number][\"status\"]): boolean =>\n status === \"ineligible\" || status === \"rejected\";\n\nexport const useRedeem = () => {\n const client = useAggClient();\n const queryClient = useQueryClient();\n const { executionMode } = useResolvedExecutionMode();\n\n return useMutation<RedeemResponse, Error, RedeemRequest>({\n mutationFn: async (body) => {\n // State the mode explicitly, like the other execution calls. A paper\n // app ignores it and settles on paper regardless, so the pre-resolution\n // window — where this is still the locally-configured guess — cannot\n // redeem against the wrong ledger.\n const response = await client.redeem({ mode: executionMode, ...body });\n if (response.results.length > 0 && response.results.every((r) => isLegRejected(r.status))) {\n const reasons = response.results\n .map((r) => r.reason)\n .filter((r): r is string => Boolean(r));\n const message = reasons.length > 0 ? reasons.join(\"; \") : \"Redeem rejected\";\n throw new RedeemRejectedError(message, response);\n }\n return response;\n },\n onSettled: () => {\n invalidateUserClaimState(queryClient);\n },\n });\n};\n","import type { WsRedeemEvent } from \"@agg-build/sdk\";\nimport { useOnRedeemEvent as useOnRedeemEventBase } from \"../core/providers/ws-provider\";\n\nexport type RedeemEvent = WsRedeemEvent;\n\nexport const useOnRedeemEvent = (listener: ((event: RedeemEvent) => void) | null): void => {\n useOnRedeemEventBase(listener);\n};\n","import { useQuery } from \"@tanstack/react-query\";\nimport type { AggClient } from \"@agg-build/sdk\";\nimport { useAggAuthState, useAggClient } from \"../core/provider\";\nimport { executionKeys } from \"./query-keys\";\n\nconst CLAIMABLE_COUNT_PAGE_LIMIT = 100;\n\nconst getClaimablePositionsCount = async (client: AggClient): Promise<number> => {\n let total = 0;\n let cursor: string | undefined;\n\n // Claimable (redeemStatus \"eligible\") groups live in the ACTIVE bucket:\n // a won-but-unclaimed position stays Active until the redeem stamps\n // `redeemedAt` (server bucket rule since 2026-05-14 — see\n // VenueMarketPositionService.getPositions). Closed-bucket groups are\n // redeemed, lost, or dust — \"eligible\" there would need ≥10 unredeemed\n // dust legs summing past the redeem threshold, which doesn't occur in\n // practice. This previously walked status:\"closed\" and therefore always\n // counted ~0. Walk the active cursor until exhausted so the badge is exact.\n do {\n const page = await client.getExecutionPositions({\n status: \"active\",\n limit: CLAIMABLE_COUNT_PAGE_LIMIT,\n cursor,\n });\n\n for (const group of page.data) {\n if (group.redeemStatus === \"eligible\") {\n total += 1;\n }\n }\n\n cursor = page.hasMore ? (page.nextCursor ?? undefined) : undefined;\n } while (cursor);\n\n return total;\n};\n\nexport const useRedeemEligibleCount = (): number => {\n const client = useAggClient();\n const { isAuthenticated } = useAggAuthState();\n\n const query = useQuery({\n queryKey: executionKeys.claimablePositionsCount(),\n queryFn: () => getClaimablePositionsCount(client),\n enabled: isAuthenticated,\n staleTime: 30_000,\n refetchInterval: isAuthenticated ? 45_000 : false,\n });\n\n if (!isAuthenticated) return 0;\n return query.data ?? 0;\n};\n","import { useEffect, useMemo, useState } from \"react\";\nimport type { WsRedeemEvent } from \"@agg-build/sdk\";\nimport { useOnRedeemEvent } from \"../core/providers/ws-provider\";\n\nexport interface RedeemLegLifecycle {\n status: \"submitted\" | \"confirmed\" | \"failed\";\n txHash: string | null;\n errorMessage: string | null;\n}\n\nexport interface RedeemLifecycleState {\n /** True until terminal — drives the claim button spinner. */\n pending: boolean;\n /** True once every expected leg has flipped to confirmed or failed. */\n terminal: boolean;\n /** True iff terminal AND every leg.status === \"confirmed\". */\n allConfirmed: boolean;\n /** True iff any leg.status === \"failed\" (including pre-failed legs). */\n anyFailed: boolean;\n /** First non-null leg.errorMessage when anyFailed; null otherwise. */\n errorMessage: string | null;\n /** Per-leg lifecycle keyed by venueMarketOutcomeId. */\n legs: Record<string, RedeemLegLifecycle>;\n}\n\nexport interface UseRedeemLifecycleInput {\n redeemId: string;\n /**\n * Legs the API returned with status === \"submitted\" (EVM async path).\n * Each receives a redeem_event with status confirmed or failed.\n */\n expectedOutcomeIds: string[];\n /**\n * Legs the API returned with status === \"ineligible\" or \"rejected\".\n * Pre-seeded into legs as terminal-failed; no WS event will ever arrive.\n */\n preFailedOutcomeIds?: string[];\n /** Optional pre-seeded errorMessage per pre-failed leg, indexed by venueMarketOutcomeId. */\n preFailedReasons?: Record<string, string | null>;\n /**\n * Legs the API returned with status === \"confirmed\" (SVM sync path:\n * tx landed inline inside the HTTP call, VMP.redeemedAt already set\n * server-side). Pre-seeded into legs as terminal-confirmed; no WS\n * event will ever arrive.\n */\n preConfirmedOutcomeIds?: string[];\n /** Optional pre-seeded txHash per pre-confirmed leg, indexed by venueMarketOutcomeId. */\n preConfirmedTxHashes?: Record<string, string | null>;\n}\n\nconst computeDerivedState = (\n legs: Record<string, RedeemLegLifecycle>,\n expectedCount: number,\n): {\n terminal: boolean;\n allConfirmed: boolean;\n anyFailed: boolean;\n errorMessage: string | null;\n} => {\n const legCount = Object.keys(legs).length;\n let allTerminal = legCount === expectedCount;\n let allConfirmed = allTerminal;\n let anyFailed = false;\n let errorMessage: string | null = null;\n for (const leg of Object.values(legs)) {\n if (leg.status === \"submitted\") allTerminal = false;\n if (leg.status !== \"confirmed\") allConfirmed = false;\n if (leg.status === \"failed\") {\n anyFailed = true;\n if (errorMessage === null && leg.errorMessage) errorMessage = leg.errorMessage;\n }\n }\n return {\n terminal: allTerminal,\n allConfirmed: allTerminal && allConfirmed,\n anyFailed,\n errorMessage,\n };\n};\n\nconst seedState = (input: UseRedeemLifecycleInput): RedeemLifecycleState => {\n const legs: Record<string, RedeemLegLifecycle> = {};\n for (const id of input.preFailedOutcomeIds ?? []) {\n legs[id] = {\n status: \"failed\",\n txHash: null,\n errorMessage: input.preFailedReasons?.[id] ?? null,\n };\n }\n for (const id of input.preConfirmedOutcomeIds ?? []) {\n legs[id] = {\n status: \"confirmed\",\n txHash: input.preConfirmedTxHashes?.[id] ?? null,\n errorMessage: null,\n };\n }\n const expectedCount =\n input.expectedOutcomeIds.length +\n (input.preFailedOutcomeIds?.length ?? 0) +\n (input.preConfirmedOutcomeIds?.length ?? 0);\n const derived = computeDerivedState(legs, expectedCount);\n return {\n pending: !derived.terminal,\n terminal: derived.terminal,\n allConfirmed: derived.allConfirmed,\n anyFailed: derived.anyFailed,\n errorMessage: derived.errorMessage,\n legs,\n };\n};\n\n/**\n * Subscribes once to `redeem_event` WS events and materializes a per-`redeemId`\n * lifecycle record for every in-flight redeem the caller is tracking.\n *\n * **Input shape** — the caller passes one {@link UseRedeemLifecycleInput} entry\n * per in-flight redeem. Legs are split into three buckets:\n * - `expectedOutcomeIds` — the EVM async path. The API returned these legs with\n * `status === \"submitted\"`; each will eventually receive a `redeem_event` WS\n * message with `status === \"confirmed\"` or `\"failed\"`.\n * - `preFailedOutcomeIds` — legs the API returned as `\"ineligible\"` or\n * `\"rejected\"` at submit time. Pre-seeded into the returned state as\n * terminal-failed; no WS event will ever arrive for them.\n * - `preConfirmedOutcomeIds` — the SVM sync path. The transaction landed inline\n * inside the HTTP call so `VenueMarketPosition.redeemedAt` is already set\n * server-side before the response returns. Pre-seeded as terminal-confirmed;\n * no WS event will ever arrive.\n *\n * **Entry lifecycle** — when the caller drops a `redeemId` from `inputs`, its\n * entry disappears from the returned record on the next render. There is no\n * tombstone or TTL — the lifecycle is purely driven by what is in `inputs`.\n *\n * **Performance** — the `inputs` array's reference identity matters. The hook\n * re-derives the internal `redeemId → input` map on every render where\n * `inputs` is a new reference. Callers should memoize the array via `useMemo`\n * to avoid the re-derivation overhead. A common pattern:\n * ```ts\n * const inputs = useMemo(\n * () => Object.values(activeRedeems).map(toLifecycleInput),\n * [activeRedeems],\n * );\n * ```\n *\n * **New-entry gap** — when the caller adds a new `redeemId` to `inputs`, the\n * returned record does not include it for the render where it was added. The\n * seed entry is written inside a `useEffect` (which runs after paint). Treat a\n * missing entry as \"pending / not terminal yet\" — the same as\n * `state.pending === true`.\n *\n * **No REST backfill** — if the WS subscription drops mid-flight (page refresh,\n * disconnect), the in-memory lifecycle state is lost. Redeems typically settle\n * in seconds and each position's `redeemStatus` is polled separately, so no\n * REST backfill is provided here.\n */\nexport function useRedeemLifecycles(\n inputs: UseRedeemLifecycleInput[],\n): Record<string, RedeemLifecycleState> {\n const inputsByRedeemId = useMemo<Record<string, UseRedeemLifecycleInput>>(() => {\n const map: Record<string, UseRedeemLifecycleInput> = {};\n for (const input of inputs) {\n map[input.redeemId] = input;\n }\n return map;\n }, [inputs]);\n\n const [stateMap, setStateMap] = useState<Record<string, RedeemLifecycleState>>(() => {\n const next: Record<string, RedeemLifecycleState> = {};\n for (const [id, input] of Object.entries(inputsByRedeemId)) {\n next[id] = seedState(input);\n }\n return next;\n });\n\n // Backfill seed state for redeemIds added after the first render. The\n // `useState` lazy initializer only runs once (on mount), so any redeemId\n // that arrives later is absent from the returned record until this effect\n // fires (after the next paint). During that render-to-effect window,\n // consumers should treat a missing entry as pending — the same as\n // `state.pending === true`.\n useEffect(() => {\n setStateMap((prev) => {\n let changed = false;\n const next: Record<string, RedeemLifecycleState> = {};\n for (const [id, input] of Object.entries(inputsByRedeemId)) {\n const existing = prev[id];\n if (existing) {\n next[id] = existing;\n } else {\n next[id] = seedState(input);\n changed = true;\n }\n }\n if (Object.keys(next).length !== Object.keys(prev).length) changed = true;\n return changed ? next : prev;\n });\n }, [inputsByRedeemId]);\n\n useOnRedeemEvent(\n useMemo(() => {\n if (Object.keys(inputsByRedeemId).length === 0) return null;\n return (event: WsRedeemEvent) => {\n const input = inputsByRedeemId[event.redeemId];\n if (!input) return;\n setStateMap((prev) => {\n const existing = prev[event.redeemId];\n if (!existing) return prev;\n const nextLegs: Record<string, RedeemLegLifecycle> = {\n ...existing.legs,\n [event.venueMarketOutcomeId]: {\n status: event.status,\n txHash: event.txHash,\n errorMessage: event.errorMessage,\n },\n };\n const expectedCount =\n input.expectedOutcomeIds.length +\n (input.preFailedOutcomeIds?.length ?? 0) +\n (input.preConfirmedOutcomeIds?.length ?? 0);\n const derived = computeDerivedState(nextLegs, expectedCount);\n const nextState: RedeemLifecycleState = {\n pending: !derived.terminal,\n terminal: derived.terminal,\n allConfirmed: derived.allConfirmed,\n anyFailed: derived.anyFailed,\n errorMessage: derived.errorMessage,\n legs: nextLegs,\n };\n return { ...prev, [event.redeemId]: nextState };\n });\n };\n }, [inputsByRedeemId]),\n );\n\n return stateMap;\n}\n","import { useMemo } from \"react\";\nimport {\n useRedeemLifecycles,\n type RedeemLifecycleState,\n type UseRedeemLifecycleInput,\n} from \"./use-redeem-lifecycles\";\n\nconst INITIAL_STATE: RedeemLifecycleState = {\n pending: true,\n terminal: false,\n allConfirmed: false,\n anyFailed: false,\n errorMessage: null,\n legs: {},\n};\n\nexport function useRedeemLifecycle(input: UseRedeemLifecycleInput | null): RedeemLifecycleState {\n const inputs = useMemo(() => (input ? [input] : []), [input]);\n const map = useRedeemLifecycles(inputs);\n if (!input) return INITIAL_STATE;\n return map[input.redeemId] ?? INITIAL_STATE;\n}\n","import { useContext } from \"react\";\nimport { AggAuthContext } from \"./core/providers/contexts\";\n\nexport interface GeoBlockState {\n /** Whether the user's location is blocked at the platform level. */\n isLocationBlocked: boolean;\n /** Whether trading is blocked for the user's location. */\n isTradingBlocked: boolean;\n /** Whether deposits are blocked for the user's location. */\n isDepositBlocked: boolean;\n}\n\nconst DEFAULT_STATE: GeoBlockState = {\n isLocationBlocked: false,\n isTradingBlocked: false,\n isDepositBlocked: false,\n};\n\n/**\n * Reads geo-block state from the authenticated user's profile.\n * Returns all-false when the user is not authenticated (no profile available).\n */\nexport function useGeoBlock(): GeoBlockState {\n const authContext = useContext(AggAuthContext);\n\n if (process.env.NEXT_PUBLIC_GEO_BLOCK_DISABLE === \"true\") return DEFAULT_STATE;\n\n const isBlocked = authContext?.user?.isLocationBlocked ?? false;\n\n if (!isBlocked) return DEFAULT_STATE;\n\n return {\n isLocationBlocked: true,\n isTradingBlocked: true,\n isDepositBlocked: true,\n };\n}\n","export type VenueAvailabilityState = \"available\" | \"geoblocked\" | \"hidden\";\n\nexport const normalizeVenueId = (venueId: string): string => venueId.trim().toLowerCase();\n\nconst getDisabledVenueSet = (disabledVenues?: readonly string[]): Set<string> => {\n return new Set((disabledVenues ?? []).map(normalizeVenueId));\n};\n\nexport const isVenueDisabledByConfig = (\n venueId: string,\n disabledVenues?: readonly string[],\n): boolean => {\n return getDisabledVenueSet(disabledVenues).has(normalizeVenueId(venueId));\n};\n\nexport const getVisibleVenuesByConfig = <TVenue extends { id: string }>(\n venues: readonly TVenue[],\n disabledVenues?: readonly string[],\n): TVenue[] => {\n const disabledVenueSet = getDisabledVenueSet(disabledVenues);\n\n return venues.filter((venue) => !disabledVenueSet.has(normalizeVenueId(venue.id)));\n};\n\nexport const getVisibleVenueIdsByConfig = <TVenueId extends string>(\n venueIds: readonly TVenueId[],\n disabledVenues?: readonly string[],\n): TVenueId[] => {\n const disabledVenueSet = getDisabledVenueSet(disabledVenues);\n\n return venueIds.filter((venueId) => !disabledVenueSet.has(normalizeVenueId(venueId)));\n};\n\nexport const getVenueAvailabilityState = ({\n venueId,\n disabledVenues,\n isConfigLoading,\n isLocationBlocked,\n}: {\n venueId: string;\n disabledVenues?: readonly string[];\n /**\n * Treat unresolved app configuration as hidden so venue-specific UI does not\n * flash before `/app/config` resolves.\n */\n isConfigLoading?: boolean;\n isLocationBlocked?: boolean;\n}): VenueAvailabilityState => {\n if (isConfigLoading) return \"hidden\";\n if (isVenueDisabledByConfig(venueId, disabledVenues)) return \"hidden\";\n if (isLocationBlocked) return \"geoblocked\";\n return \"available\";\n};\n","import type { Venue, VenueKeyStatus } from \"@agg-build/sdk\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport { useAggClient } from \"./core/provider\";\n\nexport const venueKeyQueryKeys = {\n all: [\"agg\", \"venue-keys\"] as const,\n status: (venue: Venue) => [...venueKeyQueryKeys.all, venue, \"status\"] as const,\n};\n\nexport const useVenueKeyStatus = (venue: Venue, enabled = true) => {\n const client = useAggClient();\n\n return useQuery<VenueKeyStatus>({\n queryKey: venueKeyQueryKeys.status(venue),\n queryFn: () => client.getVenueKeyStatus(venue),\n enabled,\n });\n};\n","import { useEffect, useRef } from \"react\";\nimport { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { useAggAuthContext, useAggClient } from \"./core/provider\";\nimport { useResolvedExecutionMode } from \"./use-resolved-execution-mode\";\nimport { invalidateBalanceQueries } from \"./execution/balance-invalidation\";\n\nexport const hostedVenueAccountQueryKeys = {\n all: [\"agg\", \"hosted-venue-account\"] as const,\n account: (venue: \"betdex\", userId: string | null, mode: string) =>\n [\"agg\", \"hosted-venue-account\", venue, userId, mode] as const,\n};\n\nexport function useHostedVenueAccount(venue: \"betdex\", enabled = true) {\n const client = useAggClient();\n const { user, isAuthenticated } = useAggAuthContext();\n const { executionMode, isResolving } = useResolvedExecutionMode();\n const queryClient = useQueryClient();\n const userId = user?.id ?? null;\n const permitted =\n enabled && isAuthenticated && userId !== null && !isResolving && executionMode === \"live\";\n const queryKey = hostedVenueAccountQueryKeys.account(venue, userId, executionMode);\n const session = useRef({ client, userId, executionMode, permitted });\n session.current = { client, userId, executionMode, permitted };\n const assertSession = () => {\n const current = session.current;\n if (\n !permitted ||\n !current.permitted ||\n current.client !== client ||\n current.userId !== userId ||\n current.executionMode !== executionMode\n )\n throw new Error(\"Hosted custody is unavailable for this session\");\n };\n const account = useQuery({\n queryKey,\n queryFn: () => {\n assertSession();\n return client.getHostedVenueAccount(venue, { mode: executionMode });\n },\n enabled: permitted,\n staleTime: 3_000,\n refetchInterval: permitted ? 5_000 : false,\n refetchIntervalInBackground: false,\n retry: false,\n });\n const provision = useMutation({\n mutationFn: (request: {\n run: () => ReturnType<typeof client.provisionHostedVenueAccount>;\n queryKey: typeof queryKey;\n }) => request.run(),\n // Retain the dispatch-time user key even if the observer changes users.\n onSuccess: (result, request) => {\n queryClient.setQueryData(request.queryKey, result);\n invalidateBalanceQueries(queryClient);\n },\n retry: false,\n });\n const { reset } = provision;\n useEffect(() => {\n reset();\n }, [userId, executionMode, reset]);\n const request = () => ({\n queryKey,\n run: () => {\n assertSession();\n return client.provisionHostedVenueAccount(venue, { mode: \"live\" });\n },\n });\n return {\n account,\n provision: {\n ...provision,\n mutate: () => provision.mutate(request()),\n mutateAsync: () => provision.mutateAsync(request()),\n },\n isAvailable: permitted,\n };\n}\n","import { useEffect, useRef } from \"react\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport { useAggAuthContext, useAggClient } from \"./core/provider\";\nimport { useResolvedExecutionMode } from \"./use-resolved-execution-mode\";\nimport { hostedVenueAccountQueryKeys } from \"./use-hosted-venue-account\";\n\n/** Display-only, explicitly requested pages. No automatic background polling. */\nexport function useHostedVenueActivity(venue: \"betdex\", page = 0, enabled = true) {\n const client = useAggClient();\n const { user, isAuthenticated } = useAggAuthContext();\n const { executionMode, isResolving } = useResolvedExecutionMode();\n const userId = user?.id ?? null;\n const permitted =\n enabled &&\n isAuthenticated &&\n userId !== null &&\n !isResolving &&\n executionMode === \"live\" &&\n Number.isInteger(page) &&\n page >= 0 &&\n page <= 9999;\n const session = useRef({ client, userId, executionMode, permitted });\n session.current = { client, userId, executionMode, permitted };\n const mounted = useRef(true);\n useEffect(() => {\n mounted.current = true;\n return () => {\n mounted.current = false;\n };\n }, []);\n const assertSession = () => {\n const current = session.current;\n if (\n !mounted.current ||\n !permitted ||\n !current.permitted ||\n current.client !== client ||\n current.userId !== userId ||\n current.executionMode !== executionMode\n )\n throw new Error(\"Hosted activity is unavailable for this session\");\n };\n const activity = useQuery({\n queryKey: [...hostedVenueAccountQueryKeys.all, \"activity\", venue, userId, executionMode, page],\n queryFn: async () => {\n assertSession();\n const result = await client.getHostedVenueActivity(venue, { mode: executionMode, page });\n assertSession();\n return result;\n },\n enabled: permitted,\n staleTime: 3000,\n retry: false,\n });\n return { activity, isAvailable: permitted };\n}\n","import { useCallback } from \"react\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport { useAggAuthContext, useAggClient } from \"./core/provider\";\n\nexport const sharedKycQueryKeys = {\n status: (userId: string | null) => [\"agg\", \"shared-kyc\", userId] as const,\n};\n\n/** Shared CH-backed identity state; legacy venue flags and callback query strings are not approval. */\nexport const useSharedKyc = () => {\n const client = useAggClient();\n const { isAuthenticated, user } = useAggAuthContext();\n const userId = user?.id ?? null;\n const query = useQuery({\n queryKey: sharedKycQueryKeys.status(userId),\n queryFn: () => client.getSharedKycStatus(),\n enabled: isAuthenticated && userId !== null,\n staleTime: 15_000,\n retry: false,\n });\n const { refetch } = query;\n\n const refreshStatus = useCallback(async (): Promise<\"verified\" | \"unverified\"> => {\n if (!isAuthenticated || !userId) return \"unverified\";\n const result = await refetch({ cancelRefetch: false });\n if (result.error) throw result.error;\n return result.data?.verified === true ? \"verified\" : \"unverified\";\n }, [isAuthenticated, userId, refetch]);\n\n const initiateVerification = useCallback(\n ({ venue, redirectUri }: { venue: string; redirectUri: string }) =>\n client.initiateKyc(venue, redirectUri),\n [client],\n );\n\n const status: \"loading\" | \"unverified\" | \"verified\" = !isAuthenticated\n ? \"unverified\"\n : !userId || query.isPending\n ? \"loading\"\n : query.data?.verified === true\n ? \"verified\"\n : \"unverified\";\n\n return { status, refreshStatus, initiateVerification };\n};\n","import { useCallback } from \"react\";\nimport type { UserProfile } from \"@agg-build/sdk\";\nimport { useAggAuthContext } from \"./core/provider\";\n\nexport interface UseAggAuthOptions {\n signMessage?: (message: string) => Promise<string>;\n address?: string;\n chainId?: number | string;\n /** Wallet chain — \"ethereum\" (default) or \"solana\". */\n chain?: \"ethereum\" | \"solana\";\n}\n\nexport interface UseAggAuthReturn {\n isAuthenticated: boolean;\n user: UserProfile | undefined;\n signIn: (statement?: string) => Promise<void>;\n signOut: () => Promise<void>;\n isLoading: boolean;\n error: Error | null;\n}\n\nexport function useAggAuth(options: UseAggAuthOptions = {}): UseAggAuthReturn {\n const {\n isAuthenticated,\n user,\n isLoading,\n error,\n signIn: signInWithProvider,\n signOut,\n } = useAggAuthContext();\n\n const signIn = useCallback(\n async (statement?: string) => {\n if (!options.signMessage) {\n throw new Error(\n \"signMessage is required to call signIn. Pass wallet options to useAggAuth().\",\n );\n }\n if (!options.address) {\n throw new Error(\"address is required to call signIn. Pass wallet options to useAggAuth().\");\n }\n\n await signInWithProvider({\n signMessage: options.signMessage,\n address: options.address,\n chainId: options.chainId,\n chain: options.chain,\n statement,\n });\n },\n [options.address, options.chain, options.chainId, options.signMessage, signInWithProvider],\n );\n\n return { isAuthenticated, user, signIn, signOut, isLoading, error };\n}\n","import { useCallback, useState } from \"react\";\nimport type {\n AggLinkAccountBody,\n AggLinkAccountConfirmResult,\n AggLinkAccountResult,\n AggLinkAccountWalletConfirmBody,\n} from \"@agg-build/sdk\";\nimport { useAggClient } from \"./core/provider\";\n\nexport interface UseLinkAccountReturn {\n startLink: (body: AggLinkAccountBody) => Promise<AggLinkAccountResult>;\n confirmLink: (\n input: string | AggLinkAccountWalletConfirmBody,\n ) => Promise<AggLinkAccountConfirmResult>;\n isLoading: boolean;\n error: Error | null;\n}\n\n/**\n * Hook for initiating and completing an account-link flow (OAuth / email / wallet).\n *\n * After an OAuth/email `startLink` call, the provider callback redirects the browser\n * back to the app's `redirectUrl` with a `link_confirm_token` query param. Read that\n * param on the redirect target route and pass it to `confirmLink`.\n *\n * Wallet providers (`siwe`/`siws`) instead return `{ type: \"wallet_challenge\", message }`\n * from `startLink`; sign that `message` verbatim and pass\n * `{ kind: \"wallet_signature\", message, signature }` to `confirmLink`.\n */\nexport function useLinkAccount(): UseLinkAccountReturn {\n const client = useAggClient();\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const run = <T>(fn: () => Promise<T>): Promise<T> => {\n setIsLoading(true);\n setError(null);\n return fn()\n .catch((e: unknown) => {\n const err = e instanceof Error ? e : new Error(String(e));\n setError(err);\n throw err;\n })\n .finally(() => setIsLoading(false));\n };\n\n const startLink = useCallback(\n (body: AggLinkAccountBody) => run(() => client.linkAccount(body)),\n [client],\n );\n\n const confirmLink = useCallback(\n (input: string | AggLinkAccountWalletConfirmBody) =>\n run(() => client.linkAccountConfirm(input)),\n [client],\n );\n\n return { startLink, confirmLink, isLoading, error };\n}\n","export const AUTH_CHOOSER_OPEN_EVENT = \"agg-auth:open-chooser\";\n\nexport interface AggAuthChooserOpenDetail {\n highlightMethod?: \"siwe\" | \"siws\" | \"google\" | \"twitter\" | \"apple\" | \"email\";\n}\n\nexport const requestAggAuthChooserOpen = (detail: AggAuthChooserOpenDetail = {}): void => {\n if (typeof window === \"undefined\") return;\n\n window.dispatchEvent(\n new CustomEvent<AggAuthChooserOpenDetail>(AUTH_CHOOSER_OPEN_EVENT, { detail }),\n );\n};\n","import { useInfiniteQuery, useQueries } from \"@tanstack/react-query\";\nimport type { Category } from \"@agg-build/sdk\";\nimport { useAggClient } from \"./core/provider\";\n\nexport interface UseCategoriesOptions {\n /** Optional query-key scope to isolate caches across different surfaces. */\n queryKeyScope?: string;\n /** Fetch child categories for a parent category id. Omit for top-level categories. */\n parentId?: string | null;\n enabled?: boolean;\n /** Page size when using cursor pagination. Default 20. */\n limit?: number;\n}\n\nexport interface UseCategoryChildrenOptions {\n /** Optional query-key scope to isolate caches across different surfaces. */\n queryKeyScope?: string;\n /** Parent category ids whose first child page should be fetched. */\n parentIds?: readonly (string | null | undefined)[];\n enabled?: boolean;\n /** Page size for each child query. Default 20. */\n limit?: number;\n}\n\n/**\n * Fetch categories via the API with cursor-based pagination.\n * Use fetchNextPage for \"Load more\". Same pattern as useVenueEvents.\n */\nexport function useCategories(options?: UseCategoriesOptions) {\n const client = useAggClient();\n const queryKeyScope = options?.queryKeyScope ?? \"categories\";\n const parentId = options?.parentId ?? null;\n const enabled = options?.enabled ?? true;\n const limit = options?.limit ?? 20;\n\n const query = useInfiniteQuery({\n queryKey: [queryKeyScope, \"parent\", parentId ?? \"__root__\", limit],\n queryFn: async ({ pageParam }) => {\n const res = await client.getCategories({\n limit,\n cursor: pageParam as string | undefined,\n ...(parentId != null ? { parentId } : {}),\n });\n return res;\n },\n initialPageParam: undefined as string | undefined,\n getNextPageParam: (lastPage) => lastPage.nextCursor ?? undefined,\n enabled,\n });\n\n const categories = query.data?.pages.flatMap((p) => p.data) ?? [];\n const hasNextPage = !!query.hasNextPage;\n\n return {\n ...query,\n categories,\n hasNextPage,\n };\n}\n\n/**\n * Fetch the first page of children for multiple parent categories.\n * This is intentionally first-page only: it is used to render folder affordances\n * and keep already-open branches visible without issuing one-off queries inside\n * the component tree for every rendered row.\n */\nexport function useCategoryChildren(options?: UseCategoryChildrenOptions) {\n const client = useAggClient();\n const queryKeyScope = options?.queryKeyScope ?? \"category-children\";\n const enabled = options?.enabled ?? true;\n const limit = options?.limit ?? 20;\n const parentIds = Array.from(\n new Set((options?.parentIds ?? []).filter((parentId): parentId is string => Boolean(parentId))),\n );\n\n const queries = useQueries({\n queries: parentIds.map((parentId) => ({\n queryKey: [queryKeyScope, \"parent\", parentId, limit],\n queryFn: async () => {\n return client.getCategories({\n limit,\n cursor: undefined,\n parentId,\n });\n },\n enabled,\n })),\n });\n\n const childrenByParentId = new Map<string, Category[]>();\n\n queries.forEach((query, index) => {\n const parentId = parentIds[index];\n if (!parentId) return;\n childrenByParentId.set(parentId, query.data?.data ?? []);\n });\n\n return {\n queries,\n childrenByParentId,\n isLoading: queries.some((query) => query.isLoading),\n };\n}\n","import { useEffect, useState } from \"react\";\n\nexport function useDebouncedValue<T>(value: T, delay: number): T {\n const [debouncedValue, setDebouncedValue] = useState(value);\n\n useEffect(() => {\n const timeoutId = window.setTimeout(() => {\n setDebouncedValue(value);\n }, delay);\n\n return () => {\n window.clearTimeout(timeoutId);\n };\n }, [value, delay]);\n\n return debouncedValue;\n}\n","import { useInfiniteQuery } from \"@tanstack/react-query\";\nimport type { GetOrdersQuery, OrderListItem } from \"@agg-build/sdk\";\nimport { useAggClient } from \"./core/provider\";\n\ntype ExecutionOrderStatusInput =\n | NonNullable<GetOrdersQuery[\"status\"]>\n | `${NonNullable<GetOrdersQuery[\"status\"]>}`;\n\nexport interface UseExecutionOrdersOptions extends Omit<GetOrdersQuery, \"cursor\" | \"status\"> {\n status?: ExecutionOrderStatusInput;\n enabled?: boolean;\n mode?: \"live\" | \"paper\";\n refetchIntervalMs?: number | false;\n}\n\nexport function useExecutionOrders(options: UseExecutionOrdersOptions = {}) {\n const client = useAggClient();\n const {\n status,\n orderType,\n orderId,\n quoteId,\n venueMarketIds,\n mode,\n limit = 50,\n enabled = true,\n refetchIntervalMs = false,\n } = options;\n\n // Sorted + deduped so the same set of markets in any order shares one cache\n // entry; empty means \"no filter\", matching the API.\n const venueMarketIdsKey = venueMarketIds?.length ? [...new Set(venueMarketIds)].sort() : null;\n\n const query = useInfiniteQuery({\n // quoteId + orderId are part of the cache key — different filters\n // produce different result sets, so they have to vary the key.\n queryKey: [\n \"execution-orders\",\n status ?? \"all\",\n quoteId ?? null,\n orderId ?? null,\n ...(venueMarketIdsKey ? [{ venueMarketIds: venueMarketIdsKey }] : []),\n ...(orderType ? [orderType] : []),\n ...(mode ? [mode] : []),\n limit,\n ],\n queryFn: ({ pageParam }) =>\n client.getExecutionOrders({\n status: status as GetOrdersQuery[\"status\"],\n orderType,\n orderId,\n quoteId,\n ...(venueMarketIdsKey ? { venueMarketIds: venueMarketIdsKey } : {}),\n ...(mode ? { mode } : {}),\n limit,\n cursor: pageParam as string | undefined,\n }),\n initialPageParam: undefined as string | undefined,\n getNextPageParam: (lastPage) =>\n lastPage.hasMore ? (lastPage.nextCursor ?? undefined) : undefined,\n enabled,\n refetchInterval: refetchIntervalMs,\n });\n\n const orders = query.data?.pages.flatMap((page) => page.data) ?? [];\n const hasNextPage = !!query.hasNextPage;\n\n return {\n ...query,\n orders: orders as OrderListItem[],\n hasNextPage,\n };\n}\n","import { useQueries, type UseQueryResult } from \"@tanstack/react-query\";\nimport type { GetOrdersQuery, OrderListItem } from \"@agg-build/sdk\";\nimport { useMemo } from \"react\";\nimport { useAggClient } from \"./core/provider\";\n\n/**\n * Market ids sent per `GET /execution/orders` request. The API has no cap; this\n * keeps the repeated-param URL under common CDN limits — the same batch size\n * `getMidpoints` uses.\n */\nexport const MAX_ORDER_VENUE_MARKET_IDS_PER_REQUEST = 75;\n\nconst DEFAULT_PAGE_LIMIT = 100;\nconst DEFAULT_MAX_PAGES_PER_BATCH = 5;\n\nexport interface UseExecutionOrdersForMarketsOptions {\n /** Any number of venue markets — split into batches of 75, one request each. */\n venueMarketIds: ReadonlyArray<string>;\n status?: GetOrdersQuery[\"status\"] | `${NonNullable<GetOrdersQuery[\"status\"]>}`;\n orderType?: \"market\" | \"limit\";\n mode?: \"live\" | \"paper\";\n /** Page size per request, max 100. */\n limit?: number;\n /**\n * Pages read per batch before giving up. Orders come newest first across\n * every status, so a long history on these markets can outrun one page.\n */\n maxPagesPerBatch?: number;\n enabled?: boolean;\n}\n\nexport interface UseExecutionOrdersForMarketsResult {\n orders: OrderListItem[];\n isLoading: boolean;\n error: Error | null;\n /** A batch still had pages left at `maxPagesPerBatch` — the list may be incomplete. */\n isTruncated: boolean;\n}\n\ntype BatchResult = { orders: OrderListItem[]; hasMore: boolean };\n\n/** Module-level so React Query can keep its result stable between renders. */\nconst combineBatches = (\n results: UseQueryResult<BatchResult, Error>[],\n): UseExecutionOrdersForMarketsResult => ({\n orders: results.flatMap((result) => result.data?.orders ?? []),\n isLoading: results.some((result) => result.isLoading),\n error: results.find((result) => result.error)?.error ?? null,\n isTruncated: results.some((result) => result.data?.hasMore === true),\n});\n\nconst chunk = <T>(items: T[], size: number): T[][] => {\n const chunks: T[][] = [];\n for (let index = 0; index < items.length; index += size) {\n chunks.push(items.slice(index, index + size));\n }\n return chunks;\n};\n\n/**\n * The user's orders on a set of venue markets, however many there are. Long\n * lists are split into batches of 75 to keep each URL short; the batches run\n * in parallel, each reading its own pages, and the results are merged.\n *\n * Query keys start with `\"execution-orders\"`, so placing or cancelling an\n * order invalidates these along with `useExecutionOrders`.\n */\nexport function useExecutionOrdersForMarkets({\n venueMarketIds,\n status,\n orderType,\n mode,\n limit = DEFAULT_PAGE_LIMIT,\n maxPagesPerBatch = DEFAULT_MAX_PAGES_PER_BATCH,\n enabled = true,\n}: UseExecutionOrdersForMarketsOptions): UseExecutionOrdersForMarketsResult {\n const client = useAggClient();\n\n // Sorted + deduped first so the same markets in any order produce the same\n // batches, and so the same cache entries.\n const batchKey = [...new Set(venueMarketIds)].sort().join(\",\");\n const batches = useMemo(\n () => (batchKey ? chunk(batchKey.split(\",\"), MAX_ORDER_VENUE_MARKET_IDS_PER_REQUEST) : []),\n [batchKey],\n );\n\n return useQueries({\n combine: combineBatches,\n queries: batches.map((batchVenueMarketIds) => ({\n queryKey: [\n \"execution-orders\",\n \"by-markets\",\n batchVenueMarketIds,\n status ?? \"all\",\n orderType ?? null,\n mode ?? null,\n limit,\n maxPagesPerBatch,\n ],\n queryFn: async (): Promise<BatchResult> => {\n const orders: OrderListItem[] = [];\n let cursor: string | undefined;\n\n for (let page = 0; page < maxPagesPerBatch; page += 1) {\n const response = await client.getExecutionOrders({\n venueMarketIds: batchVenueMarketIds,\n status: status as GetOrdersQuery[\"status\"],\n orderType,\n ...(mode ? { mode } : {}),\n limit,\n ...(cursor ? { cursor } : {}),\n });\n orders.push(...(response.data as OrderListItem[]));\n cursor = response.hasMore ? (response.nextCursor ?? undefined) : undefined;\n if (!cursor) return { orders, hasMore: false };\n }\n\n return { orders, hasMore: true };\n },\n enabled,\n })),\n });\n}\n","import { keepPreviousData, useInfiniteQuery } from \"@tanstack/react-query\";\nimport type {\n PaginatedResponse,\n UserActivityItem,\n UserActivityQuery,\n UserActivityType,\n} from \"@agg-build/sdk\";\nimport { useAggClient } from \"./core/provider\";\nimport { userActivityQueryKeys } from \"./execution/balance-invalidation\";\n\nexport interface UseUserActivityOptions extends Omit<UserActivityQuery, \"cursor\"> {\n enabled?: boolean;\n /**\n * Poll interval (ms) used while any cached activity row is mid-lifecycle\n * (deposit pending, withdrawal bridging, trade submitted, etc.). Idle\n * feeds — every row in a terminal state — don't poll. Set to `false` to\n * disable the lifecycle-aware poll entirely.\n *\n * Defaults to 15s.\n */\n pendingRefetchIntervalMs?: number | false;\n}\n\nconst DEFAULT_PENDING_REFETCH_INTERVAL_MS = 15_000;\n\n/**\n * Non-terminal status strings seen across the three activity-item shapes the\n * profile feed renders (`trade`, `deposit`, `withdrawal`). Anything in this\n * set means the backend will eventually flip the row to a terminal state, so\n * the feed should poll until it does.\n *\n * Kept lowercase for case-insensitive matching against `item.status`.\n */\nconst PENDING_ACTIVITY_STATUSES = new Set<string>([\n \"pending\",\n // trade pre-fill lifecycle\n \"signing\",\n \"pending_bridge\",\n \"submitting\",\n \"submitted\",\n // withdrawal lifecycle\n \"bridging\",\n \"transferring\",\n]);\n\nconst hasPendingActivity = (\n pages: ReadonlyArray<PaginatedResponse<UserActivityItem>> | undefined,\n): boolean => {\n if (!pages) return false;\n for (const page of pages) {\n for (const item of page.data) {\n if (\n item.type === \"redeem\" &&\n item.legs.length > 0 &&\n item.legs.every((leg) => leg.status.toLowerCase() === \"confirmed\")\n ) {\n continue;\n }\n if (PENDING_ACTIVITY_STATUSES.has(item.status.toLowerCase())) return true;\n }\n }\n return false;\n};\n\nexport function useUserActivity(options: UseUserActivityOptions = {}) {\n const client = useAggClient();\n const {\n type,\n limit = 50,\n enabled = true,\n pendingRefetchIntervalMs = DEFAULT_PENDING_REFETCH_INTERVAL_MS,\n } = options;\n\n const query = useInfiniteQuery({\n queryKey: userActivityQueryKeys.feed(type, limit),\n queryFn: ({ pageParam }) =>\n client.getUserActivity({\n type: type as UserActivityType | undefined,\n limit,\n cursor: pageParam as string | undefined,\n }),\n initialPageParam: undefined as string | undefined,\n getNextPageParam: (lastPage) =>\n lastPage.hasMore ? (lastPage.nextCursor ?? undefined) : undefined,\n enabled,\n // Keep the previously-loaded pages visible while a refetch is in\n // flight (typically after a deposit / withdraw cache invalidation).\n // Without this the feed flashes to the skeleton mid-session, which\n // is worse UX than briefly showing slightly-stale rows.\n placeholderData: keepPreviousData,\n refetchInterval: (q) => {\n if (pendingRefetchIntervalMs === false) return false;\n const data = q.state.data as { pages: PaginatedResponse<UserActivityItem>[] } | undefined;\n return hasPendingActivity(data?.pages) ? pendingRefetchIntervalMs : false;\n },\n });\n\n const activities = query.data?.pages.flatMap((page) => page.data) ?? [];\n const hasNextPage = !!query.hasNextPage;\n\n return {\n ...query,\n activities: activities as UserActivityItem[],\n hasNextPage,\n };\n}\n","import { keepPreviousData, useInfiniteQuery } from \"@tanstack/react-query\";\nimport type { LeaderboardMetric, LeaderboardRow, PaginatedResponse } from \"@agg-build/sdk\";\nimport { useAggClient } from \"./core/provider\";\n\n/** Preset ranges the leaderboard UI offers. The API itself takes any from/to. */\nexport type LeaderboardPeriod = \"1d\" | \"7d\" | \"30d\" | \"all\";\nexport const LEADERBOARD_PERIODS: readonly LeaderboardPeriod[] = [\"1d\", \"7d\", \"30d\", \"all\"];\n\nexport interface UseLeaderboardOptions {\n /** Default `30d`. */\n period?: LeaderboardPeriod;\n /** Default `realizedPnl`. */\n metric?: LeaderboardMetric;\n /** Page size, 1..100. Default 50. */\n limit?: number;\n enabled?: boolean;\n}\n\nconst utcDayKey = (d: Date): string => d.toISOString().slice(0, 10);\n\n/**\n * Inclusive UTC day range for a preset. `1d` is today, `7d` is the last 7\n * UTC days including today, `30d` the last 30. `all` returns no bounds.\n */\nexport function leaderboardRange(\n period: LeaderboardPeriod,\n now: Date = new Date(),\n): { from?: string; to?: string } {\n if (period === \"all\") return {};\n const spanDays = period === \"1d\" ? 0 : period === \"7d\" ? 6 : 29;\n const from = new Date(\n Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate() - spanDays),\n );\n return { from: utcDayKey(from), to: utcDayKey(now) };\n}\n\nexport const leaderboardQueryKeys = {\n all: () => [\"leaderboard\"] as const,\n list: (period: LeaderboardPeriod, metric: LeaderboardMetric, limit: number) =>\n [\"leaderboard\", period, metric, limit] as const,\n};\n\n/** 60 s: the API caches leaderboard responses for the same window. */\nconst LEADERBOARD_STALE_TIME_MS = 60_000;\n\nexport function useLeaderboard(options: UseLeaderboardOptions = {}) {\n const client = useAggClient();\n const { period = \"30d\", metric = \"realizedPnl\", limit = 50, enabled = true } = options;\n\n const query = useInfiniteQuery({\n queryKey: leaderboardQueryKeys.list(period, metric, limit),\n queryFn: ({ pageParam }) =>\n client.getLeaderboard({\n ...leaderboardRange(period),\n metric,\n limit,\n cursor: pageParam as string | undefined,\n }),\n initialPageParam: undefined as string | undefined,\n getNextPageParam: (lastPage: PaginatedResponse<LeaderboardRow>) =>\n lastPage.hasMore ? (lastPage.nextCursor ?? undefined) : undefined,\n enabled,\n // Keep the previous list on screen while a period/metric switch loads.\n placeholderData: keepPreviousData,\n staleTime: LEADERBOARD_STALE_TIME_MS,\n });\n\n // A trader can move across a page boundary between fetches; keep the first\n // occurrence so row keys stay unique.\n const seen = new Set<string>();\n const rows = (query.data?.pages.flatMap((page) => page.data) ?? []).filter((row) => {\n if (seen.has(row.userId)) return false;\n seen.add(row.userId);\n return true;\n });\n\n return {\n ...query,\n rows: rows as LeaderboardRow[],\n hasNextPage: !!query.hasNextPage,\n };\n}\n","import type { UserProfile } from \"@agg-build/sdk\";\nimport { useCallback, useState } from \"react\";\nimport { useAggClient } from \"./core/provider\";\n\nexport interface UseExternalIdOptions {\n onSuccess?: (profile: UserProfile) => void;\n onError?: (error: Error) => void;\n}\n\nexport interface UseExternalIdReturn {\n linkExternalId: (assertion: {\n externalId: string;\n timestamp: number;\n hmac: string;\n }) => Promise<UserProfile>;\n isLoading: boolean;\n error: Error | null;\n}\n\nexport function useExternalId(options: UseExternalIdOptions = {}): UseExternalIdReturn {\n const client = useAggClient();\n const { onSuccess, onError: onErrorCb } = options;\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const linkExternalId = useCallback(\n async (assertion: {\n externalId: string;\n timestamp: number;\n hmac: string;\n }): Promise<UserProfile> => {\n setIsLoading(true);\n setError(null);\n\n try {\n const profile = await client.linkExternalId(assertion);\n onSuccess?.(profile);\n return profile;\n } catch (err) {\n const resolvedError = err instanceof Error ? err : new Error(String(err));\n setError(resolvedError);\n onErrorCb?.(resolvedError);\n throw resolvedError;\n } finally {\n setIsLoading(false);\n }\n },\n [client, onErrorCb, onSuccess],\n );\n\n return { linkExternalId, isLoading, error };\n}\n","import { useInfiniteQuery } from \"@tanstack/react-query\";\nimport type { GetPositionsQuery, PositionGroup } from \"@agg-build/sdk\";\nimport { useAggClient } from \"./core/provider\";\nimport { executionKeys } from \"./execution/query-keys\";\n\nexport interface UseExecutionPositionsOptions extends Omit<GetPositionsQuery, \"cursor\"> {\n enabled?: boolean;\n mode?: \"live\" | \"paper\";\n}\n\nexport function useExecutionPositions(options: UseExecutionPositionsOptions = {}) {\n const client = useAggClient();\n const { limit = 50, status, mode, enabled = true } = options;\n\n const query = useInfiniteQuery({\n queryKey: executionKeys.positions(null, limit, status ?? null, mode ?? null),\n queryFn: ({ pageParam }) =>\n client.getExecutionPositions({\n limit,\n status,\n ...(mode ? { mode } : {}),\n cursor: pageParam as string | undefined,\n }),\n initialPageParam: undefined as string | undefined,\n getNextPageParam: (lastPage) =>\n lastPage.hasMore ? (lastPage.nextCursor ?? undefined) : undefined,\n enabled,\n });\n\n const positions = query.data?.pages.flatMap((page) => page.data) ?? [];\n const hasNextPage = !!query.hasNextPage;\n\n return {\n ...query,\n positions: positions as PositionGroup[],\n hasNextPage,\n };\n}\n","import { isAggApiError } from \"@agg-build/sdk\";\nimport { isServer, type QueryObserverOptions } from \"@tanstack/react-query\";\n\ntype ReadRetryOptions = Pick<QueryObserverOptions, \"retry\" | \"retryDelay\">;\nconst MAX_TIMER_DELAY_MS = 2_147_483_647;\nconst hint = (error: Error): number | undefined => {\n if (!isAggApiError(error)) return undefined;\n const value = error.retryAfterMs;\n return typeof value === \"number\" && Number.isSafeInteger(value) && value >= 0 ? value : undefined;\n};\n\n/** Read-query policy only: retain configured retry counts, honoring API delays without retrying early. */\nexport function withReadRetry(options: ReadRetryOptions): {\n retry: (failureCount: number, error: Error) => boolean;\n retryDelay: (attempt: number, error: Error) => number;\n} {\n return {\n retry: (failureCount, error) => {\n // Oversized setTimeout delays overflow to ~1ms in supported runtimes. Stop instead.\n if ((hint(error) ?? 0) > MAX_TIMER_DELAY_MS) return false;\n const retry = options.retry ?? (isServer ? 0 : 3);\n return typeof retry === \"function\"\n ? retry(failureCount, error)\n : retry === true || (typeof retry === \"number\" && failureCount < retry);\n },\n retryDelay: (attempt, error) =>\n hint(error) ??\n (typeof options.retryDelay === \"function\"\n ? options.retryDelay(attempt, error)\n : (options.retryDelay ?? Math.min(1000 * 2 ** attempt, 30_000))),\n };\n}\n","import type { ChartBarsMeta, ChartBarsResponse, WsCandleInterval, WsTrade } from \"@agg-build/sdk\";\n\nexport interface MarketChartCandle {\n time: number;\n open: number;\n high: number;\n low: number;\n close: number;\n mean?: number;\n volume: number | null;\n source: \"rest\" | \"ws\" | \"trade\" | \"midpoint\";\n}\n\nexport interface MarketChartVenueData {\n venue: string;\n /** Venue-scoped outcome IDs that contributed to this venue series. */\n outcomeIds: string[];\n candles: MarketChartCandle[];\n liveCandle: MarketChartCandle | null;\n lineValue: number | undefined;\n lastTrade: WsTrade | null;\n /**\n * Epoch seconds of the most recent real REST or WS update that touched this\n * venue (REST candle, trade, or midpoint). Used by the renderer's stale-data\n * indicator — independent of any synthetic point that `extendSeriesToNow`\n * projects onto the line. `null` when nothing has been seen yet.\n */\n lastUpdateTs: number | null;\n}\n\nexport interface MarketChartData {\n /** Delivery availability/freshness from the history source, unaffected by stream ticks. */\n delivery?: ChartBarsMeta;\n marketId: string;\n /** All venue-scoped outcome IDs that were requested for this chart selection. */\n outcomeIds: string[];\n /** Venue key for the canonical historical bar series returned by GET /charts/bars. */\n primaryVenue: string;\n interval: WsCandleInterval;\n startTs: number | null;\n endTs: number | null;\n /** Per-venue chart state. The primary venue contains the canonical REST history. */\n venues: Record<string, MarketChartVenueData>;\n /**\n * Max of `lastUpdateTs` across all venues. Surfaced separately so the\n * renderer can show a stale indicator without crawling the venues map.\n */\n lastUpdateTs: number | null;\n}\n\n/**\n * Largest range we support (`ALL` ≈ 6 months) plus a generous buffer. The\n * cache prunes closed candles older than this so a long-lived session\n * doesn't grow the array unboundedly as WS pushes new bars over hours/days.\n */\nexport const MAX_CACHE_RETENTION_SECONDS = 7 * 30 * 24 * 60 * 60 + 14 * 24 * 60 * 60;\n\nexport const getIntervalSeconds = (interval: WsCandleInterval): number => {\n switch (interval) {\n case \"1m\":\n return 60;\n case \"5m\":\n return 5 * 60;\n case \"1h\":\n return 60 * 60;\n case \"1d\":\n return 24 * 60 * 60;\n }\n};\n\nconst createVenueData = (venue: string, outcomeIds: string[] = []): MarketChartVenueData => ({\n venue,\n outcomeIds,\n candles: [],\n liveCandle: null,\n lineValue: undefined,\n lastTrade: null,\n lastUpdateTs: null,\n});\n\nconst pruneCandlesBefore = (\n candles: MarketChartCandle[],\n cutoffTs: number,\n): MarketChartCandle[] => {\n if (cutoffTs <= 0) return candles;\n let firstKeptIndex = 0;\n while (firstKeptIndex < candles.length && candles[firstKeptIndex].time < cutoffTs) {\n firstKeptIndex += 1;\n }\n if (firstKeptIndex === 0) return candles;\n return candles.slice(firstKeptIndex);\n};\n\n/**\n * If `liveCandle` belongs to a strictly earlier bucket than `expectedCandleTime`,\n * the bar has closed. Promote it onto the end of `candles[]` (deduped by time)\n * so the now-closed bar persists in history instead of being thrown away when\n * the next bucket starts forming.\n */\nconst promoteClosedLiveCandle = (\n candles: MarketChartCandle[],\n liveCandle: MarketChartCandle | null,\n expectedCandleTime: number,\n): { candles: MarketChartCandle[]; promoted: boolean } => {\n if (!liveCandle || liveCandle.time >= expectedCandleTime) {\n return { candles, promoted: false };\n }\n if (candles.some((candle) => candle.time === liveCandle.time)) {\n return { candles, promoted: false };\n }\n return { candles: sortCandles([...candles, liveCandle]), promoted: true };\n};\n\nconst resolveMaxLastUpdateTs = (venues: Record<string, MarketChartVenueData>): number | null => {\n let max: number | null = null;\n for (const venueData of Object.values(venues)) {\n if (venueData.lastUpdateTs != null && (max == null || venueData.lastUpdateTs > max)) {\n max = venueData.lastUpdateTs;\n }\n }\n return max;\n};\n\nconst sortCandles = (candles: MarketChartCandle[]): MarketChartCandle[] => {\n return [...candles].sort((left, right) => left.time - right.time);\n};\n\nconst _upsertFinalCandle = (\n candles: MarketChartCandle[],\n nextCandle: MarketChartCandle,\n): MarketChartCandle[] => {\n const index = candles.findIndex((candle) => candle.time === nextCandle.time);\n if (index < 0) return sortCandles([...candles, nextCandle]);\n\n const nextCandles = [...candles];\n nextCandles[index] = nextCandle;\n return nextCandles;\n};\n\nexport const createMarketChartData = (params: {\n marketId: string;\n interval: WsCandleInterval;\n startTs: number | null;\n endTs: number | null;\n response: ChartBarsResponse;\n}): MarketChartData => {\n const candles = sortCandles(\n params.response.data.map((candle) => ({\n time: Math.floor(candle.t / 1000),\n open: candle.o,\n high: candle.h,\n low: candle.l,\n close: candle.c,\n ...(Number.isFinite(candle.mean) ? { mean: candle.mean } : {}),\n volume: candle.v,\n source: \"rest\" as const,\n })),\n );\n const lastCandle = candles[candles.length - 1];\n const lastUpdateTs = lastCandle?.time ?? null;\n const venues = {\n [params.response.venue]: {\n venue: params.response.venue,\n outcomeIds: [params.response.venueMarketOutcomeId],\n candles,\n liveCandle: null,\n lineValue: lastCandle?.close,\n lastTrade: null,\n lastUpdateTs,\n } satisfies MarketChartVenueData,\n };\n\n return {\n marketId: params.marketId,\n delivery: params.response.meta,\n outcomeIds: [params.response.venueMarketOutcomeId],\n primaryVenue: params.response.venue,\n interval: params.interval,\n startTs: params.startTs,\n endTs: params.endTs,\n venues,\n lastUpdateTs,\n };\n};\n\nexport const mergeMarketChartData = (params: {\n marketId: string;\n interval: WsCandleInterval;\n startTs: number | null;\n endTs: number | null;\n datasets: MarketChartData[];\n}): MarketChartData | null => {\n if (params.datasets.length === 0) {\n return null;\n }\n\n const primaryVenue = params.datasets[0]?.primaryVenue ?? \"aggregate\";\n const outcomeIds = Array.from(\n new Set(\n params.datasets.flatMap((dataset) => {\n return dataset.outcomeIds.length > 0 ? dataset.outcomeIds : [dataset.marketId];\n }),\n ),\n );\n\n const venues = params.datasets.reduce<Record<string, MarketChartVenueData>>((acc, dataset) => {\n for (const [venue, venueData] of Object.entries(dataset.venues)) {\n const existingVenueData = acc[venue];\n\n // We expect one logical outcome series per venue for this chart flow.\n // If that assumption changes, the aggregation layer should be extended\n // to merge duplicate venue keys instead of overwriting them here.\n acc[venue] = existingVenueData\n ? {\n ...venueData,\n outcomeIds: Array.from(\n new Set([...existingVenueData.outcomeIds, ...venueData.outcomeIds]),\n ),\n }\n : venueData;\n }\n\n return acc;\n }, {});\n\n return {\n marketId: params.marketId,\n delivery:\n params.datasets.find((dataset) => dataset.marketId === params.marketId)?.delivery ??\n params.datasets[0]?.delivery,\n outcomeIds,\n primaryVenue,\n interval: params.interval,\n startTs: params.startTs,\n endTs: params.endTs,\n venues,\n lastUpdateTs: resolveMaxLastUpdateTs(venues),\n };\n};\n\nexport interface MarketChartMidpointUpdate {\n outcomeId: string;\n midpoint: number;\n /** Seconds since epoch. */\n timestamp: number;\n}\n\n/**\n * Apply an orderbook midpoint to the chart cache.\n *\n * Why: trades are the canonical source of price movement, but many markets\n * trade rarely. The orderbook ticks every few seconds via deltas; reflecting\n * the midpoint into a forming candle keeps the chart line moving in sync\n * with the orderbook UI rather than freezing at the last REST close.\n *\n * The midpoint never overrides a candle that has already received a real\n * trade in the same bucket — trades win on close/high/low/volume. Midpoint\n * updates only seed an empty bucket or extend a midpoint-sourced candle.\n *\n * Each chart cache entry is keyed by a single venue-scoped outcomeId, so the\n * target venue is the one whose `outcomeIds` contains `update.outcomeId`.\n * REST bootstrap always seeds exactly that one venue, so this lookup is\n * deterministic.\n */\nexport const applyMidpointToMarketChart = (\n data: MarketChartData | null | undefined,\n update: MarketChartMidpointUpdate,\n): MarketChartData | null | undefined => {\n if (!data || !Number.isFinite(update.midpoint)) {\n return data;\n }\n\n const targetVenueEntry = Object.entries(data.venues).find(([, venueData]) =>\n venueData.outcomeIds.includes(update.outcomeId),\n );\n\n if (!targetVenueEntry && data.marketId !== update.outcomeId) {\n return data;\n }\n\n const [targetVenueName, currentVenue] = targetVenueEntry ?? [\n data.primaryVenue,\n data.venues[data.primaryVenue] ?? createVenueData(data.primaryVenue, [update.outcomeId]),\n ];\n const intervalSeconds = getIntervalSeconds(data.interval);\n const expectedCandleTime = update.timestamp - (update.timestamp % intervalSeconds);\n\n let liveCandle = currentVenue.liveCandle;\n // Promote any closed (earlier-bucket) liveCandle into history before\n // starting/updating the current bucket. Without this, an older liveCandle\n // would be discarded when the next bucket's first update arrives.\n const { candles: promotedCandles } = promoteClosedLiveCandle(\n currentVenue.candles,\n liveCandle,\n expectedCandleTime,\n );\n // Drop closed bars older than our retention horizon so a long-lived\n // session can't grow the array unboundedly.\n const nextCandles = pruneCandlesBefore(\n promotedCandles,\n update.timestamp - MAX_CACHE_RETENTION_SECONDS,\n );\n\n if (liveCandle && liveCandle.time === expectedCandleTime) {\n if (liveCandle.source === \"trade\") {\n // Trades dominate: only roll the close so the line tracks the latest\n // mid, but do not stomp the trade-derived high/low/volume.\n liveCandle = {\n ...liveCandle,\n close: update.midpoint,\n };\n } else {\n liveCandle = {\n ...liveCandle,\n close: update.midpoint,\n high: Math.max(liveCandle.high, update.midpoint),\n low: Math.min(liveCandle.low, update.midpoint),\n source: \"midpoint\",\n };\n }\n } else {\n liveCandle = {\n time: expectedCandleTime,\n open: update.midpoint,\n high: update.midpoint,\n low: update.midpoint,\n close: update.midpoint,\n volume: 0,\n source: \"midpoint\",\n };\n }\n\n const nextVenues = {\n ...data.venues,\n [targetVenueName]: {\n ...currentVenue,\n outcomeIds: currentVenue.outcomeIds.includes(update.outcomeId)\n ? currentVenue.outcomeIds\n : [...currentVenue.outcomeIds, update.outcomeId],\n candles: nextCandles,\n liveCandle,\n lineValue: update.midpoint,\n lastUpdateTs: update.timestamp,\n },\n };\n\n return {\n ...data,\n venues: nextVenues,\n lastUpdateTs: resolveMaxLastUpdateTs(nextVenues),\n };\n};\n\nexport const applyTradeToMarketChart = (\n data: MarketChartData | null | undefined,\n trade: WsTrade,\n): MarketChartData | null | undefined => {\n if (!data || data.marketId !== trade.outcomeId) {\n return data;\n }\n\n const currentVenue = data.venues[trade.venue] ?? createVenueData(trade.venue);\n const intervalSeconds = getIntervalSeconds(data.interval);\n const expectedCandleTime = trade.timestamp - (trade.timestamp % intervalSeconds);\n\n let liveCandle = currentVenue.liveCandle;\n const { candles: promotedCandles } = promoteClosedLiveCandle(\n currentVenue.candles,\n liveCandle,\n expectedCandleTime,\n );\n const nextCandles = pruneCandlesBefore(\n promotedCandles,\n trade.timestamp - MAX_CACHE_RETENTION_SECONDS,\n );\n\n if (liveCandle && liveCandle.time === expectedCandleTime) {\n liveCandle = {\n ...liveCandle,\n close: trade.price,\n high: Math.max(liveCandle.high, trade.price),\n low: Math.min(liveCandle.low, trade.price),\n volume: (liveCandle.volume ?? 0) + trade.size,\n source: \"trade\",\n };\n } else if (!liveCandle || liveCandle.time !== expectedCandleTime) {\n liveCandle = {\n time: expectedCandleTime,\n open: trade.price,\n high: trade.price,\n low: trade.price,\n close: trade.price,\n volume: trade.size,\n source: \"trade\",\n };\n }\n\n const nextVenues = {\n ...data.venues,\n [trade.venue]: {\n ...currentVenue,\n outcomeIds: currentVenue.outcomeIds.includes(trade.outcomeId)\n ? currentVenue.outcomeIds\n : [...currentVenue.outcomeIds, trade.outcomeId],\n candles: nextCandles,\n liveCandle,\n lineValue: liveCandle?.close ?? trade.price,\n lastTrade: trade,\n lastUpdateTs: trade.timestamp,\n },\n };\n\n return {\n ...data,\n venues: nextVenues,\n lastUpdateTs: resolveMaxLastUpdateTs(nextVenues),\n };\n};\n","import {\n loadImmutableHistory,\n isAggApiError,\n type AggClient,\n type AggWebSocket,\n type ChartBarsResponse,\n type ChartHistoryManifest,\n type ChartCandle,\n} from \"@agg-build/sdk\";\n\nexport class ChartDeliveryError extends Error {\n constructor(\n readonly state: NonNullable<ChartBarsResponse[\"meta\"][\"state\"]>,\n readonly retryAfterMs?: number,\n ) {\n super(`Chart delivery ${state}`);\n this.name = \"ChartDeliveryError\";\n }\n}\nconst usable = (response: ChartBarsResponse): ChartBarsResponse => {\n if (response.data.length === 0 && response.meta?.state && response.meta.state !== \"empty\")\n throw new ChartDeliveryError(response.meta.state, response.meta.retryAfterMs);\n return response;\n};\nconst withActualFreshness = (response: ChartBarsResponse): ChartBarsResponse => {\n const serverTime = Number.isFinite(response.meta.serverTime)\n ? response.meta.serverTime\n : Date.now();\n const lastBarOpenTime = response.data.at(-1)?.t ?? null;\n return {\n ...response,\n meta: {\n ...response.meta,\n serverTime,\n lastBarOpenTime,\n staleSeconds:\n lastBarOpenTime == null ? null : Math.max(0, (serverTime - lastBarOpenTime) / 1000),\n },\n };\n};\n\n/** API checks app visibility; finalized objects and dynamic JSON decode are processed in the Worker. */\nexport async function fetchChartHistory(\n client: AggClient,\n socket: AggWebSocket | null,\n request: Parameters<AggClient[\"getChartBars\"]>[0],\n signal?: AbortSignal,\n onInitial?: (response: ChartBarsResponse) => void,\n): Promise<ChartBarsResponse> {\n const readBars = async (params: typeof request): Promise<ChartBarsResponse> => {\n const response = await client.getChartBars(params, {\n signal,\n ...(socket ? { decode: (text: string) => socket.decodeHistory(text) } : {}),\n });\n signal?.throwIfAborted();\n if (response.venueMarketOutcomeId !== request.venueMarketOutcomeId)\n throw new Error(\"Chart history identity mismatch\");\n return response;\n };\n if (!client.preferImmutableHistory) return usable(await readBars(request));\n\n let verified: { manifest: ChartHistoryManifest; history: ChartCandle[] } | undefined;\n try {\n const manifest = await client.getChartHistoryManifest(request, { signal });\n if (manifest.venueMarketOutcomeId !== request.venueMarketOutcomeId)\n throw new Error(\"Chart manifest identity mismatch\");\n if (manifest.meta.complete) {\n const history = await (socket\n ? socket.loadHistory(manifest, { signal })\n : loadImmutableHistory({ manifest, signal }));\n verified = {\n manifest,\n history: history.filter(\n (bar) => (request.from == null || bar.t >= request.from) && bar.t < request.to,\n ),\n };\n }\n } catch (error) {\n if (signal?.aborted || (isAggApiError(error) && (error.status === 429 || error.status === 503)))\n throw error;\n }\n // Only absent/unverified immutable history needs a full origin fallback.\n signal?.throwIfAborted();\n if (!verified) return usable(await readBars(request));\n\n const { manifest, history } = verified;\n const fullyCovered = manifest.finalizedThrough >= request.to;\n const initial = withActualFreshness({\n venueMarketOutcomeId: manifest.venueMarketOutcomeId,\n venue: manifest.venue,\n resolution: manifest.resolution,\n data: history,\n meta: {\n ...manifest.meta,\n state: fullyCovered ? (history.length ? \"ready\" : \"empty\") : \"warming\",\n complete: fullyCovered,\n },\n });\n if (fullyCovered) return usable(initial);\n\n // Publish verified nonempty history before requesting the forming tail. The caller's\n // original query promise remains active, preserving cancellation on range changes.\n if (history.length > 0) onInitial?.(initial);\n signal?.throwIfAborted();\n try {\n const tail = await readBars({\n ...request,\n resolution: manifest.resolution,\n from: Math.max(request.from ?? 0, manifest.finalizedThrough),\n countBack: undefined,\n });\n if (tail.venue !== manifest.venue || tail.resolution !== manifest.resolution)\n throw new Error(\"Chart tail series mismatch\");\n const data = [\n ...history,\n ...tail.data.filter((bar) => bar.t >= manifest.finalizedThrough && bar.t < request.to),\n ];\n const incomplete =\n tail.meta.complete === false ||\n [\"warming\", \"failed\", \"unsupported\"].includes(tail.meta.state ?? \"\");\n return usable(\n withActualFreshness({\n ...tail,\n resolution: manifest.resolution,\n data,\n meta: {\n ...initial.meta,\n ...tail.meta,\n complete: !incomplete,\n state: incomplete ? (tail.meta.state ?? \"warming\") : data.length ? \"ready\" : \"empty\",\n },\n }),\n );\n } catch (error) {\n if (signal?.aborted) throw error;\n // A failed mutable tail cannot discard or re-fetch a verified immutable prefix.\n return usable(\n withActualFreshness({\n ...initial,\n meta: {\n ...initial.meta,\n state: error instanceof ChartDeliveryError ? error.state : \"failed\",\n complete: false,\n ...((error instanceof ChartDeliveryError || isAggApiError(error)) &&\n error.retryAfterMs != null\n ? { retryAfterMs: error.retryAfterMs }\n : {}),\n },\n }),\n );\n }\n}\n","import { isAggApiError } from \"@agg-build/sdk\";\nimport type { MarketChartData } from \"./chart-cache\";\nimport { ChartDeliveryError } from \"./chart-history\";\n\nconst MAX_TIMER_DELAY_MS = 2_147_483_647;\n// Query ownership preserves a deadline through observers/remounts without retaining evicted queries.\nconst notBefore = new WeakMap<object, number>();\nconst validDelay = (value: unknown): value is number =>\n typeof value === \"number\" && Number.isSafeInteger(value) && value >= 0;\n\nfunction record(query: object, delay: unknown): void {\n if (validDelay(delay) && delay > 0)\n notBefore.set(query, Math.min(Number.MAX_SAFE_INTEGER, Date.now() + delay));\n else notBefore.delete(query);\n}\n\nexport function chartRetryRemaining(query: object): number {\n return Math.max(0, (notBefore.get(query) ?? 0) - Date.now());\n}\n\n/** TanStack owns this interval; long server hints must not overflow a browser timer into an early poll. */\nexport function chartRefetchInterval(query: object, interval: number | false): number | false {\n if (interval === false) return false;\n const remaining = chartRetryRemaining(query);\n return remaining > MAX_TIMER_DELAY_MS ? false : Math.max(interval, remaining);\n}\n\nasync function waitForDeadline(query: object, signal: AbortSignal): Promise<void> {\n while (chartRetryRemaining(query) > 0) {\n signal.throwIfAborted();\n await new Promise<void>((resolve, reject) => {\n const aborted = () => {\n clearTimeout(timer);\n signal.removeEventListener(\"abort\", aborted);\n reject(signal.reason);\n };\n const timer = setTimeout(\n () => {\n signal.removeEventListener(\"abort\", aborted);\n resolve();\n },\n Math.min(chartRetryRemaining(query), MAX_TIMER_DELAY_MS),\n );\n signal.addEventListener(\"abort\", aborted, { once: true });\n if (signal.aborted) aborted();\n });\n }\n signal.throwIfAborted();\n}\n\n/** Guard every query execution, including manual refetch and invalidation; never schedule background work. */\nexport async function runChartQuery<T extends MarketChartData>(\n query: object,\n signal: AbortSignal,\n load: () => Promise<T>,\n): Promise<T> {\n await waitForDeadline(query, signal);\n try {\n const data = await load();\n signal.throwIfAborted();\n const delivery = data.delivery;\n // Only a fresh source result can establish a deadline. Reading retained data/ticks cannot extend it.\n record(\n query,\n delivery && delivery.complete !== true && ![\"ready\", \"empty\"].includes(delivery.state ?? \"\")\n ? delivery.retryAfterMs\n : undefined,\n );\n return data;\n } catch (error) {\n if (!signal.aborted) {\n const delay = isAggApiError(error)\n ? error.retryAfterMs\n : error instanceof ChartDeliveryError && validDelay(error.retryAfterMs)\n ? error.retryAfterMs\n : undefined;\n record(query, delay);\n }\n throw error;\n }\n}\n","import type { Candle } from \"@agg-build/sdk\";\nimport type { LiveSnapshot } from \"./live-store\";\nimport type { MarketChartCandle, MarketChartData } from \"./chart-cache\";\n\nconst closedCaches = new WeakMap<MarketChartData, { key: string; candles: MarketChartCandle[] }>();\nconst toChart = (candle: Candle): MarketChartCandle => ({\n time: candle.openTime,\n open: candle.o,\n high: candle.h,\n low: candle.l,\n close: candle.c,\n volume: candle.v,\n source: \"ws\",\n});\n\n/** Overlay only active views. Retained TanStack histories keep their own freshness and array identity. */\nexport function overlayCandleTail(\n history: MarketChartData,\n live: LiveSnapshot | undefined,\n rolling: boolean,\n): MarketChartData {\n const tail = live?.candles?.[history.interval];\n const venue = history.venues[history.primaryVenue];\n if (!tail || !venue || (!rolling && history.endTs != null && history.endTs < Date.now()))\n return history;\n const last = venue.candles.at(-1)?.time ?? -Infinity;\n const closed = tail.closed.filter((candle) => candle.openTime > last);\n const key = closed.map((candle) => `${candle.openTime}:${candle.c}:${candle.v}`).join(\"|\");\n let cached = closedCaches.get(history);\n if (!cached || cached.key !== key) {\n cached = {\n key,\n candles: closed.length ? [...venue.candles, ...closed.map(toChart)] : venue.candles,\n };\n closedCaches.set(history, cached);\n }\n const forming = tail.forming && tail.forming.openTime >= last ? toChart(tail.forming) : null;\n const lastSourceTime = Math.max(\n live.orderbook?.timestamp ?? -Infinity,\n live.trades[0]?.timestamp ?? -Infinity,\n venue.lastUpdateTs ?? -Infinity,\n );\n const lastUpdateTs = Number.isFinite(lastSourceTime) ? lastSourceTime : null;\n return {\n ...history,\n lastUpdateTs,\n venues: {\n ...history.venues,\n [history.primaryVenue]: {\n ...venue,\n candles: cached.candles,\n liveCandle: forming,\n lineValue: forming?.close ?? venue.lineValue,\n lastTrade: live.trades[0] ?? venue.lastTrade,\n lastUpdateTs,\n },\n },\n };\n}\n","import { useEffect, useMemo } from \"react\";\nimport { useAggWebSocket } from \"../core/providers/ws-provider\";\n\nexport interface UseMarketDataSubscriptionOptions {\n marketId: string | null;\n /** Additional market IDs to subscribe alongside `marketId` (e.g. other venues in the same group). */\n additionalMarketIds?: string[];\n enabled?: boolean;\n orderbook?: boolean;\n trades?: boolean;\n}\n\nexport function useMarketDataSubscription({\n marketId,\n additionalMarketIds,\n enabled = true,\n orderbook = true,\n trades = false,\n}: UseMarketDataSubscriptionOptions): void {\n const ws = useAggWebSocket();\n\n const allIds = useMemo(() => {\n const ids = new Set<string>();\n if (marketId) ids.add(marketId);\n if (additionalMarketIds) {\n for (const id of additionalMarketIds) {\n if (id) ids.add(id);\n }\n }\n return [...ids];\n }, [marketId, additionalMarketIds]);\n\n const stableKey = allIds.join(\"|\");\n\n useEffect(() => {\n if (!ws || !allIds.length || !enabled || (!orderbook && !trades)) return;\n\n const unsubscribers: Array<() => void> = [];\n\n for (const id of allIds) {\n if (orderbook) {\n const unsub = ws.subscribe(id, \"orderbook\");\n unsubscribers.push(unsub);\n }\n if (trades) {\n const unsub = ws.subscribe(id, \"trades\");\n unsubscribers.push(unsub);\n }\n }\n\n return () => {\n for (const unsub of unsubscribers) {\n unsub();\n }\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [enabled, stableKey, orderbook, trades, ws]);\n}\n","import type { ChartBarsMeta, WsCandleInterval } from \"@agg-build/sdk\";\nimport { keepPreviousData, useQueries, useQueryClient } from \"@tanstack/react-query\";\nimport { withReadRetry } from \"./read-retry\";\nimport { useAggClient, useAggUiConfig } from \"./core/provider\";\nimport { useAggWebSocket, useAggWebSocketConnectionState } from \"./core/providers/ws-provider\";\nimport {\n createMarketChartData,\n mergeMarketChartData,\n type MarketChartData,\n} from \"./market-data/chart-cache\";\nimport { marketDataKeys } from \"./market-data/query-keys\";\nimport { runChartQuery, chartRefetchInterval } from \"./market-data/chart-retry-gate\";\nimport { ChartDeliveryError, fetchChartHistory } from \"./market-data/chart-history\";\nimport { useLiveStates } from \"./market-data/live-store\";\nimport { overlayCandleTail } from \"./market-data/chart-tail\";\nimport { useMarketDataSubscription } from \"./market-data/subscription\";\n\nexport interface UseMarketChartOptions {\n /** VenueMarketOutcome.id */\n marketId: string | null;\n /** Additional venue market outcome IDs to subscribe for WS updates. */\n venueMarketIds?: string[];\n /** Scope readiness to the visible venue while retaining other requested histories. */\n visibleVenue?: string | null;\n /** Optional live subset; settled outcomes can keep cached history without stream subscriptions. */\n liveOutcomeIds?: string[];\n interval?: WsCandleInterval;\n startTs?: number | null;\n endTs?: number | null;\n countBack?: number | null;\n enabled?: boolean;\n /** Enable live WS updates. Defaults to the global `enableLiveUpdates` config. */\n live?: boolean;\n /**\n * Auto-refetch the REST history at this cadence (ms). Pair with a rolling\n * window whose `endTs` advances at the same bucket interval — each tick\n * refetches the latest window under a stable cache key, so closed bars\n * the WebSocket missed are backfilled. `null`/omitted disables auto-refetch.\n */\n refetchIntervalMs?: number | null;\n /** Optional history freshness duration; live stream writes do not extend it. */\n staleTimeMs?: number;\n /**\n * Stable identifier for the user-selected range (e.g. `\"1H\"`, `\"6H\"`).\n * Used as the React Query cache key so the entry survives bucket rollovers\n * and tab/page revisits. The concrete `startTs`/`endTs` advance under the\n * same key and are passed to the fetch via closure.\n *\n * If omitted, includes the requested start/end timestamps so different fixed\n * historical windows never share data. Note that 6H and 1D both use a 5m\n * interval, so callers using rolling windows should pass an explicit\n * `rangeKey` to keep their cache entries separate.\n */\n rangeKey?: string;\n}\n\nexport type MarketChartAvailability = Partial<ChartBarsMeta> & {\n state: NonNullable<ChartBarsMeta[\"state\"]>;\n complete: boolean;\n};\n\nexport interface UseMarketChartResult {\n /** Per-outcome delivery state remains available when another venue can already render. */\n availability?: Record<string, MarketChartAvailability>;\n data: MarketChartData | null;\n isLoading: boolean;\n error: Error | null;\n isLive: boolean;\n refetch: () => Promise<unknown>;\n}\n\nfunction useMarketChartQueries(options: UseMarketChartOptions) {\n const client = useAggClient();\n const queryClient = useQueryClient();\n const socket = useAggWebSocket();\n const isConnected = useAggWebSocketConnectionState();\n const {\n features: { enableLiveUpdates },\n } = useAggUiConfig();\n const {\n marketId,\n venueMarketIds,\n liveOutcomeIds,\n interval = \"5m\",\n startTs = null,\n endTs = null,\n countBack = null,\n enabled = true,\n live,\n refetchIntervalMs = null,\n staleTimeMs,\n rangeKey,\n } = options;\n\n const resolvedRangeKey = rangeKey ?? `${interval}:${startTs ?? \"count\"}:${endTs ?? \"unset\"}`;\n\n const liveEnabled = live ?? enableLiveUpdates;\n\n // Stabilize outcomeIds order across renders. Callers (e.g. event-details)\n // derive `venueMarketIds` from a live-price-sorted array; every WS midpoint\n // can reorder it. If we mirrored that order into useQueries, the slot at\n // index 0 would point to a different outcome on each WS tick, churning\n // observer wiring and (in the worst case) firing extra fetches before\n // React Query's per-slot dedup catches up. Sorting lexicographically gives\n // every render the same slot assignment regardless of input order.\n //\n // `primaryOutcomeId` keeps the caller's intent: `marketId` first if\n // provided, otherwise the first non-empty entry of `venueMarketIds`.\n const outcomeIds = (() => {\n const ids = new Set<string>();\n if (marketId) ids.add(marketId);\n if (venueMarketIds) {\n for (const venueMarketId of venueMarketIds) {\n if (venueMarketId) ids.add(venueMarketId);\n }\n }\n return [...ids].sort();\n })();\n const primaryOutcomeId = marketId ?? venueMarketIds?.find(Boolean) ?? null;\n const isQueryEnabled =\n enabled && outcomeIds.length > 0 && endTs != null && (startTs != null || countBack != null);\n\n const subscribedIds = liveOutcomeIds\n ? outcomeIds.filter((id) => liveOutcomeIds.includes(id))\n : outcomeIds;\n const subscribedPrimaryId =\n primaryOutcomeId && subscribedIds.includes(primaryOutcomeId)\n ? primaryOutcomeId\n : (subscribedIds[0] ?? null);\n useMarketDataSubscription({\n marketId: subscribedPrimaryId,\n additionalMarketIds: subscribedIds.filter((id) => id !== subscribedPrimaryId),\n enabled: Boolean(isQueryEnabled && liveEnabled && subscribedIds.length > 0),\n orderbook: true,\n trades: true,\n });\n\n const queries = useQueries({\n queries: outcomeIds.map((outcomeId) => ({\n // Cache key is intentionally time-free. The rolling window's\n // startTs/endTs advance on every bucket but the user expects the same\n // chart on revisit — see comment on `marketDataKeys.chart`. queryFn\n // closes over the current window so refetches still fetch fresh data.\n queryKey: marketDataKeys.chart(outcomeId, interval, resolvedRangeKey, countBack),\n queryFn: async ({ signal }: { signal: AbortSignal }): Promise<MarketChartData> => {\n const owner = queryClient.getQueryCache().find({\n queryKey: marketDataKeys.chart(outcomeId, interval, resolvedRangeKey, countBack),\n exact: true,\n });\n if (!owner) throw new Error(\"Chart query was removed before fetching\");\n return runChartQuery(owner, signal, async () => {\n const response = await fetchChartHistory(\n client,\n socket,\n {\n venueMarketOutcomeId: outcomeId,\n resolution: interval,\n from: startTs ?? undefined,\n to: endTs!,\n countBack: countBack ?? undefined,\n },\n signal,\n (initial) => {\n if (signal.aborted) return;\n queryClient.setQueryData(\n marketDataKeys.chart(outcomeId, interval, resolvedRangeKey, countBack),\n createMarketChartData({\n marketId: outcomeId,\n interval: initial.resolution ?? interval,\n startTs,\n endTs,\n response: initial,\n }),\n );\n },\n );\n\n return createMarketChartData({\n marketId: outcomeId,\n interval: response.resolution ?? interval,\n startTs,\n endTs,\n response,\n });\n });\n },\n enabled: isQueryEnabled,\n meta: { chartWindow: rangeKey ? \"rolling\" : \"fixed\", chartEndTs: endTs },\n // Treat data as fresh for one bucket — within that window the\n // existing entry serves remounts without a refetch, and the\n // `refetchInterval` below schedules the next bucket's refresh.\n staleTime: (query: { state: { data?: MarketChartData } }) => {\n // A remount after the rolling bucket advances needs its missing history.\n if (\n rangeKey &&\n endTs != null &&\n query.state.data?.endTs != null &&\n query.state.data.endTs < endTs\n )\n return 0;\n return (\n staleTimeMs ??\n (refetchIntervalMs != null && refetchIntervalMs > 0 ? refetchIntervalMs : 30_000)\n );\n },\n // 60 min — survives typical tab/page revisits without re-fetching.\n gcTime: 60 * 60_000,\n refetchOnWindowFocus: false,\n ...withReadRetry({\n retry: (failureCount: number, error: Error) => {\n if (error instanceof ChartDeliveryError) {\n if (error.state === \"unsupported\") return false;\n if (error.state === \"warming\") return failureCount < 8;\n }\n return failureCount < 1;\n },\n retryDelay: (_attempt: number, error: Error) =>\n error instanceof ChartDeliveryError && error.retryAfterMs != null\n ? Math.min(error.state === \"warming\" ? 1000 : 5000, Math.max(0, error.retryAfterMs))\n : 1000,\n }),\n placeholderData: keepPreviousData,\n refetchInterval: (query: object) =>\n chartRefetchInterval(\n query,\n refetchIntervalMs != null && refetchIntervalMs > 0 ? refetchIntervalMs : false,\n ),\n refetchIntervalInBackground: false,\n })),\n });\n\n // Disabled chart consumers keep their REST cache but must not retain live\n // listeners. `live:false` still permits an enabled view to observe a stream\n // owned by its parent; it controls subscription ownership above.\n const liveStates = useLiveStates(isQueryEnabled ? outcomeIds : []);\n const overlaid = queries.map((query, index) => ({\n ...query,\n data:\n query.data?.marketId === outcomeIds[index]\n ? overlayCandleTail(query.data, liveStates[index]?.data, !!rangeKey)\n : undefined,\n }));\n const availability: Record<string, MarketChartAvailability> = {};\n if (isQueryEnabled)\n queries.forEach((query, index) => {\n const sameOutcome = query.data?.marketId === outcomeIds[index];\n const metadata = sameOutcome ? query.data?.delivery : undefined;\n const error = query.error;\n const pending = query.isLoading || query.isPlaceholderData || query.isFetching;\n const state: MarketChartAvailability[\"state\"] =\n error instanceof ChartDeliveryError\n ? error.state\n : error\n ? \"failed\"\n : pending || !sameOutcome\n ? \"warming\"\n : (metadata?.state ??\n (Object.values(query.data!.venues).some(\n (venue) => venue.candles.length > 0 || venue.liveCandle,\n )\n ? \"ready\"\n : \"empty\"));\n availability[outcomeIds[index]!] = {\n ...metadata,\n state,\n complete: (state === \"ready\" || state === \"empty\") && (metadata?.complete ?? true),\n ...(error instanceof ChartDeliveryError && error.retryAfterMs != null\n ? { retryAfterMs: error.retryAfterMs }\n : {}),\n };\n });\n return {\n queries: overlaid,\n availability,\n outcomeIds,\n primaryOutcomeId,\n interval,\n startTs,\n endTs,\n isQueryEnabled,\n liveEnabled: liveEnabled && subscribedIds.length > 0,\n isConnected,\n };\n}\n\n/** Independent outcome histories, including multiple markets on the same venue. */\nexport interface UseMarketChartsResult {\n availability?: Record<string, MarketChartAvailability>;\n charts: Record<string, MarketChartData>;\n errors: Record<string, Error>;\n isLoading: boolean;\n isLive: boolean;\n refetch: () => Promise<unknown>;\n}\n\nexport function useMarketCharts(options: UseMarketChartOptions): UseMarketChartsResult {\n const { queries, availability, outcomeIds, isQueryEnabled, liveEnabled, isConnected } =\n useMarketChartQueries(options);\n const charts: Record<string, MarketChartData> = {};\n const errors: Record<string, Error> = {};\n queries.forEach((query, index) => {\n const outcomeId = outcomeIds[index]!;\n // A previous query slot may belong to a different outcome after a venue switch.\n if (query.data?.marketId === outcomeId && !query.isPlaceholderData)\n charts[outcomeId] = query.data;\n if (query.error)\n errors[outcomeId] =\n query.error instanceof Error ? query.error : new Error(String(query.error));\n });\n return {\n availability,\n charts,\n errors,\n isLoading: Boolean(\n isQueryEnabled && queries.some((query) => query.isLoading || query.isPlaceholderData),\n ),\n isLive: Boolean(isQueryEnabled && liveEnabled && isConnected),\n refetch: async () => Promise.all(queries.map((query) => query.refetch())),\n };\n}\n\nexport function useMarketChart(options: UseMarketChartOptions): UseMarketChartResult {\n const {\n queries,\n availability,\n primaryOutcomeId,\n interval,\n startTs,\n endTs,\n isQueryEnabled,\n liveEnabled,\n isConnected,\n } = useMarketChartQueries(options);\n const successfulDatasets = queries.flatMap((query) => {\n return query.data ? [query.data] : [];\n });\n const data =\n primaryOutcomeId && successfulDatasets.length > 0\n ? mergeMarketChartData({\n marketId: primaryOutcomeId,\n interval: successfulDatasets[0]?.interval ?? interval,\n startTs,\n endTs,\n datasets: successfulDatasets,\n })\n : null;\n\n const hasPendingQuery = queries.some((query) => query.isLoading || query.isPlaceholderData);\n const firstError = queries.find((query) => query.error != null)?.error ?? null;\n const error =\n data == null && !hasPendingQuery\n ? firstError instanceof Error\n ? firstError\n : firstError\n ? new Error(String(firstError))\n : null\n : null;\n // Show any usable in-range history immediately, but do not let an early empty\n // or out-of-range response trigger ALL fallback while another venue is warming.\n const isInRange = (candle: { time: number }): boolean =>\n (startTs == null || candle.time >= startTs / 1000) &&\n (endTs == null || candle.time <= endTs / 1000);\n const hasVisibleHistory = queries.some(\n (query) =>\n !query.isPlaceholderData &&\n query.data &&\n Object.entries(query.data.venues).some(\n ([venueName, venue]) =>\n (!options.visibleVenue || venueName === options.visibleVenue) &&\n (venue.candles.some(isInRange) ||\n (venue.liveCandle != null && isInRange(venue.liveCandle))),\n ),\n );\n const isLoading = Boolean(isQueryEnabled && hasPendingQuery && !hasVisibleHistory);\n\n return {\n data,\n availability,\n isLoading,\n error,\n isLive: Boolean(isQueryEnabled && liveEnabled && primaryOutcomeId && isConnected),\n refetch: async () => Promise.all(queries.map((query) => query.refetch())),\n };\n}\n","import { useEffect, useMemo, useReducer, useRef } from \"react\";\nimport type { CandleBuilder } from \"@agg-build/sdk\";\nimport { useAggWebSocket } from \"./core/providers/ws-provider\";\nimport { getOrCreateBuilder } from \"./candle-store\";\n\n/**\n * Subscribe to multiple venue markets and return their CandleBuilder instances.\n * Each market gets its own WS subscription (refcounted) and CandleBuilder.\n * Re-renders when ANY builder's onChange fires (batched at ~16ms by CandleBuilder).\n */\nexport function useLiveMarketStores(venueMarketIds: string[]): CandleBuilder[] {\n const ws = useAggWebSocket();\n const [, forceRender] = useReducer((c: number) => c + 1, 0);\n const subsRef = useRef(new Map<string, { unsub: () => void; unlisten: () => void }>());\n\n const stableKey = useMemo(() => venueMarketIds.slice().sort().join(\"|\"), [venueMarketIds]);\n\n useEffect(() => {\n if (!ws || venueMarketIds.length === 0) return;\n\n const current = subsRef.current;\n const desired = new Set(venueMarketIds);\n\n // Unsubscribe removed markets\n for (const [id, sub] of current) {\n if (!desired.has(id)) {\n sub.unsub();\n sub.unlisten();\n current.delete(id);\n }\n }\n\n // Subscribe new markets\n for (const id of desired) {\n if (!current.has(id)) {\n const builder = getOrCreateBuilder(id);\n const unsub = ws.subscribe(id, \"orderbook\");\n const unlisten = builder.onChange(forceRender);\n current.set(id, { unsub, unlisten });\n }\n }\n\n return () => {\n for (const [, sub] of current) {\n sub.unsub();\n sub.unlisten();\n }\n current.clear();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [ws, stableKey]);\n\n return venueMarketIds.map((id) => getOrCreateBuilder(id));\n}\n","import { useMemo } from \"react\";\nimport {\n type Candle,\n type CandleInterval,\n mergeCandles,\n mergeClosedCandles,\n VenueMarket,\n} from \"@agg-build/sdk\";\nimport { useMarketChart } from \"./use-market-chart\";\nimport { useLiveMarketStores } from \"./use-live-market-stores\";\n\n/** Unified candle shape returned by this hook. All times in seconds. */\nexport interface LiveCandle {\n time: number;\n o: number;\n h: number;\n l: number;\n c: number;\n v: number | null;\n venue?: string;\n source: \"rest\" | \"live\";\n}\n\nexport interface UseLiveCandlesOptions {\n /** The VenueMarket to show candles for. Contains id, marketId, venue, matchedVenueMarkets. */\n market: VenueMarket | null;\n /** Candle interval. Default \"5m\". */\n interval?: CandleInterval;\n /** \"venue\" = this venue only, \"aggregate\" = merge all matched venues. */\n mode?: \"venue\" | \"aggregate\";\n /** REST bootstrap time range (ms). */\n startTs?: number;\n endTs?: number;\n}\n\nexport interface UseLiveCandlesResult {\n /** Merged candles (REST historical + live computed), sorted by time asc. */\n candles: LiveCandle[];\n /** Currently forming candle. null if no live data yet. */\n liveCandle: LiveCandle | null;\n isLoading: boolean;\n}\n\nfunction candleToLive(c: Candle, source: \"rest\" | \"live\"): LiveCandle {\n return { time: c.openTime, o: c.o, h: c.h, l: c.l, c: c.c, v: c.v, source };\n}\n\n/**\n * Combines REST bootstrap candles with live CandleBuilder-computed candles.\n *\n * - REST provides historical candles from Postgres (fetched once).\n * - CandleBuilder computes live candles from orderbook delta midpoints + trades.\n * - Dedup: when a live candle has the same openTime as a REST candle, live wins.\n * - mode \"venue\": reads from a single CandleBuilder.\n * - mode \"aggregate\": merges CandleBuilders from all matched venue markets.\n */\nexport function useLiveCandles(options: UseLiveCandlesOptions): UseLiveCandlesResult {\n const { market, interval = \"5m\", mode = \"venue\", startTs, endTs } = options;\n\n // Resolve venue_market_ids to subscribe to\n const venueMarketIds = useMemo(() => {\n if (!market) return [];\n if (mode === \"venue\") return [market.id];\n // Aggregate: this market + all matched siblings\n const ids = [market.id];\n if (market.matchedVenueMarkets) {\n for (const m of market.matchedVenueMarkets) {\n ids.push(m.id);\n }\n }\n return ids;\n }, [market, mode]);\n\n // Each venue_market_id gets its own CandleBuilder, all accumulating in parallel\n const builders = useLiveMarketStores(venueMarketIds);\n\n // REST bootstrap — use canonical marketId for chart endpoint\n const restMarketId = market?.marketId ?? null;\n const { data: chartData, isLoading } = useMarketChart({\n marketId: restMarketId,\n interval,\n startTs: startTs ?? null,\n endTs: endTs ?? null,\n enabled: !!restMarketId && startTs != null && endTs != null,\n });\n\n // Live candles from CandleBuilder(s)\n const liveData = useMemo(() => {\n if (builders.length === 0) return { closed: [] as Candle[], forming: null as Candle | null };\n\n if (mode === \"venue\" || builders.length === 1) {\n return {\n closed: builders[0].getClosed(interval),\n forming: builders[0].getForming(interval),\n };\n }\n\n // Aggregate: merge across matched venue builders\n return {\n closed: mergeClosedCandles(builders.map((b) => b.getClosed(interval))),\n forming: mergeCandles(builders.map((b) => b.getForming(interval))),\n };\n // builders array identity changes on every render from useLiveMarketStores (forceRender),\n // which is the re-render trigger we need\n }, [builders, interval, mode]);\n\n // Merge REST + live by openTime (live wins on collision)\n const candles = useMemo(() => {\n const byTime = new Map<number, LiveCandle>();\n\n // REST candles from chart cache (times already in seconds)\n if (chartData) {\n const venueEntries = Object.values(chartData.venues);\n for (const venueData of venueEntries) {\n for (const c of venueData.candles) {\n byTime.set(c.time, {\n time: c.time,\n o: c.open,\n h: c.high,\n l: c.low,\n c: c.close,\n v: c.volume,\n source: \"rest\",\n });\n }\n }\n }\n\n // Live closed candles overwrite REST on collision\n for (const c of liveData.closed) {\n byTime.set(c.openTime, candleToLive(c, \"live\"));\n }\n\n const merged = Array.from(byTime.values());\n merged.sort((a, b) => a.time - b.time);\n return merged;\n }, [chartData, liveData.closed]);\n\n // Forming candle\n const liveCandle = useMemo((): LiveCandle | null => {\n if (!liveData.forming) return null;\n return candleToLive(liveData.forming, \"live\");\n }, [liveData.forming]);\n\n return { candles, liveCandle, isLoading };\n}\n","import { useCallback, useMemo } from \"react\";\nimport type { CandleInterval, VenueMarket } from \"@agg-build/sdk\";\nimport { useLiveCandles, type LiveCandle } from \"./use-live-candles\";\n\nexport interface ScaledCandlePoint {\n time: number;\n open: number;\n high: number;\n low: number;\n close: number;\n v: number | null;\n}\n\nexport interface UseLiveCandleOverlayOptions {\n market: VenueMarket | null;\n interval?: CandleInterval;\n mode?: \"venue\" | \"aggregate\";\n startTs?: number;\n endTs?: number;\n enabled?: boolean;\n scale?: number;\n}\n\nexport interface UseLiveCandleOverlayResult {\n liveCandle: ScaledCandlePoint | null;\n scaledCandles: ScaledCandlePoint[];\n lineValue: number | undefined;\n live: boolean;\n isLoading: boolean;\n}\n\nexport function timeRangeToInterval(range: string): CandleInterval {\n switch (range) {\n case \"1H\":\n return \"1m\";\n case \"6H\":\n return \"5m\";\n case \"1D\":\n return \"5m\";\n case \"1W\":\n return \"1h\";\n case \"1M\":\n return \"1h\";\n case \"ALL\":\n return \"1h\";\n default:\n return \"5m\";\n }\n}\n\nexport function useLiveCandleOverlay(\n options: UseLiveCandleOverlayOptions,\n): UseLiveCandleOverlayResult {\n const {\n market,\n interval = \"5m\",\n mode = \"venue\",\n startTs,\n endTs,\n enabled = true,\n scale = 100,\n } = options;\n\n const {\n candles: rawCandles,\n liveCandle: rawLive,\n isLoading,\n } = useLiveCandles({\n market: enabled ? market : null,\n interval,\n mode,\n startTs,\n endTs,\n });\n\n const scaleCandle = useCallback(\n (candle: LiveCandle): ScaledCandlePoint => ({\n time: candle.time,\n open: candle.o * scale,\n high: candle.h * scale,\n low: candle.l * scale,\n close: candle.c * scale,\n v: candle.v,\n }),\n [scale],\n );\n\n const scaledCandles = useMemo(() => rawCandles.map(scaleCandle), [rawCandles, scaleCandle]);\n const liveCandle = useMemo(() => (rawLive ? scaleCandle(rawLive) : null), [rawLive, scaleCandle]);\n\n return {\n liveCandle,\n scaledCandles,\n lineValue: liveCandle?.close ?? scaledCandles[scaledCandles.length - 1]?.close,\n live: liveCandle != null,\n isLoading,\n };\n}\n","import { useEffect, useMemo } from \"react\";\nimport type { VenueMarket } from \"@agg-build/sdk\";\nimport { useAggUiConfig } from \"./core/provider\";\nimport { useAggWebSocket } from \"./core/providers/ws-provider\";\n\n// ── Pure helpers (exported for unit tests) ─────────────────────────────────\n\nexport function extractSelectedOutcomeIds(selectedMarket: VenueMarket | null): string[] {\n if (!selectedMarket) return [];\n const ids = new Set<string>();\n for (const outcome of selectedMarket.venueMarketOutcomes ?? []) {\n if (outcome.id) ids.add(outcome.id);\n }\n // Include cross-venue matched markets so a 2-venue market subscribes to all\n // 4 outcome ids (2 per venue). The engine emits per-outcome deltas, so\n // missing any one venue's ids leaves `useLiveOutcomePrices` blind to that\n // venue's live book.\n for (const matched of selectedMarket.matchedVenueMarkets ?? []) {\n for (const outcome of matched.venueMarketOutcomes ?? []) {\n if (outcome.id) ids.add(outcome.id);\n }\n }\n return [...ids].sort();\n}\n\n// ── Hook ───────────────────────────────────────────────────────────────────\n\n/**\n * Subscribes to live orderbook updates for the selected market's outcomes —\n * including the outcomes of any cross-venue matched twins — so the live cache\n * fills for every venue the user is actively looking at.\n *\n * Each caller owns only this selected group. The event hero owns its selection;\n * the market list enables separate callers for its bounded visible cards and\n * retained selection. Other groups use the surrounding components' REST\n * midpoint fallback until a view owns their live stream.\n *\n * Honors the `enableLiveUpdates` feature flag.\n */\nexport function useEventOrderbookData(\n venueMarkets: VenueMarket[] | null | undefined,\n selectedMarketId: string | null,\n): void {\n const ws = useAggWebSocket();\n const {\n features: { enableLiveUpdates },\n } = useAggUiConfig();\n\n const selectedMarket = useMemo(() => {\n if (!selectedMarketId || !venueMarkets?.length) return null;\n return venueMarkets.find((m) => m.id === selectedMarketId) ?? null;\n }, [venueMarkets, selectedMarketId]);\n\n const selectedOutcomeIds = useMemo(\n () => extractSelectedOutcomeIds(selectedMarket),\n [selectedMarket],\n );\n const selectedKey = selectedOutcomeIds.join(\"|\");\n\n useEffect(() => {\n if (!ws || !enableLiveUpdates || !selectedOutcomeIds.length) return;\n const unsubscribers = selectedOutcomeIds.map((id) => ws.subscribe(id, \"orderbook\"));\n return () => {\n for (const unsub of unsubscribers) unsub();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [ws, selectedKey, enableLiveUpdates]);\n}\n","import type {\n OrderbookLevel,\n OrderbookState,\n OutcomeOrderbookResponse,\n VenueOrderbookLevel,\n} from \"@agg-build/sdk\";\n/**\n * Convert a single-outcome REST snapshot into the WS-style `OrderbookState`\n * shape used by chart / depth UIs. The REST endpoint returns a per-venue\n * book (single venue) — we attribute every level to that one venue so the\n * resulting state is a valid (if narrower) `OrderbookState` consumers can\n * render. WS deltas overwrite this state on first frame.\n */\n/** Current REST wire timestamps are ms; tolerate older partner fixtures in seconds. */\nexport const orderbookTimestampSeconds = (timestamp: number): number =>\n timestamp >= 1_000_000_000_000 ? timestamp / 1000 : timestamp;\n\nexport function outcomeOrderbookToState(\n response: OutcomeOrderbookResponse,\n marketId: string,\n): OrderbookState {\n const { venue, orderbook, midpoint, spread, seq, checksum, timestamp, venueMarketOutcomeId } =\n response;\n const attribute = (l: { price: number; size: number }): OrderbookLevel => ({\n price: l.price,\n size: l.size,\n venues: { [venue]: l.size },\n });\n const venueLevels = (l: { price: number; size: number }): VenueOrderbookLevel => ({\n price: l.price,\n size: l.size,\n });\n return {\n marketId,\n outcomeId: venueMarketOutcomeId,\n bids: orderbook.bids.map(attribute),\n asks: orderbook.asks.map(attribute),\n venueOrderbooks: {\n [venue]: {\n bids: orderbook.bids.map(venueLevels),\n asks: orderbook.asks.map(venueLevels),\n },\n },\n venues: {\n [venue]: {\n bestBid: orderbook.bids[0]?.price ?? null,\n bestAsk: orderbook.asks[0]?.price ?? null,\n },\n },\n midpoint,\n spread,\n seq,\n checksum,\n timestamp: orderbookTimestampSeconds(timestamp),\n };\n}\n","import type { Orderbook, AggregatedOrderbookResponse, OrderbookState } from \"@agg-build/sdk\";\n\nexport type MarketOrderbookIntegrity = \"ok\" | \"resyncing\";\n\nexport interface MarketOrderbookData {\n marketId: string;\n orderbook: AggregatedOrderbookResponse[\"orderbook\"];\n venueOrderbooks: AggregatedOrderbookResponse[\"venueOrderbooks\"];\n venues: AggregatedOrderbookResponse[\"venues\"];\n midpoint: number | null;\n spread: number | null;\n timestamp: number;\n snapshotVersion?: number;\n seq?: number;\n checksum?: number | null;\n matchedMarkets?: AggregatedOrderbookResponse[\"matchedMarkets\"];\n integrity: MarketOrderbookIntegrity;\n}\n\nconst truncateLevels = <T extends { price: number; size: number }>(\n levels: T[],\n depth?: number | null,\n): T[] => {\n if (depth == null) return levels;\n return levels.slice(0, Math.max(0, depth));\n};\n\nconst truncateVenueOrderbooks = (\n venueOrderbooks: MarketOrderbookData[\"venueOrderbooks\"],\n depth?: number | null,\n): MarketOrderbookData[\"venueOrderbooks\"] => {\n if (depth == null) return venueOrderbooks;\n\n return Object.fromEntries(\n Object.entries(venueOrderbooks).map(([venue, book]) => [\n venue,\n {\n bids: truncateLevels(book.bids, depth),\n asks: truncateLevels(book.asks, depth),\n },\n ]),\n );\n};\n\nexport const createMarketOrderbookDataFromResponse = (\n response: AggregatedOrderbookResponse,\n): MarketOrderbookData => {\n return {\n marketId: response.venueMarketId,\n orderbook: response.orderbook,\n venueOrderbooks: response.venueOrderbooks,\n venues: response.venues,\n midpoint: response.midpoint,\n spread: response.spread,\n timestamp: response.timestamp,\n snapshotVersion: 0,\n seq: response.seq,\n checksum: response.checksum,\n matchedMarkets: \"matchedMarkets\" in response ? response.matchedMarkets : undefined,\n integrity: \"ok\",\n };\n};\n\nconst aggregateVenueLevels = (\n venueOrderbooks: MarketOrderbookData[\"venueOrderbooks\"],\n side: \"bids\" | \"asks\",\n): MarketOrderbookData[\"orderbook\"][\"bids\"] => {\n const levelsByPrice = new Map<\n number,\n {\n price: number;\n size: number;\n venues: Record<string, number>;\n }\n >();\n\n for (const [venue, orderbook] of Object.entries(venueOrderbooks)) {\n for (const level of orderbook[side]) {\n const currentLevel = levelsByPrice.get(level.price);\n\n if (currentLevel) {\n currentLevel.size += level.size;\n currentLevel.venues[venue] = (currentLevel.venues[venue] ?? 0) + level.size;\n continue;\n }\n\n levelsByPrice.set(level.price, {\n price: level.price,\n size: level.size,\n venues: {\n [venue]: level.size,\n },\n });\n }\n }\n\n return [...levelsByPrice.values()].sort((left, right) =>\n side === \"bids\" ? right.price - left.price : left.price - right.price,\n );\n};\n\nexport const createMarketOrderbookDataFromVenueOrderbooks = ({\n marketId,\n venueOrderbooks,\n timestamp = Math.floor(Date.now() / 1000),\n}: {\n marketId: string;\n venueOrderbooks: Record<string, Orderbook>;\n timestamp?: number;\n}): MarketOrderbookData => {\n const bids = aggregateVenueLevels(venueOrderbooks, \"bids\");\n const asks = aggregateVenueLevels(venueOrderbooks, \"asks\");\n const bestBid = bids[0]?.price ?? null;\n const bestAsk = asks[0]?.price ?? null;\n\n return {\n marketId,\n orderbook: {\n bids,\n asks,\n },\n venueOrderbooks,\n venues: Object.fromEntries(\n Object.entries(venueOrderbooks).map(([venue, orderbook]) => [\n venue,\n {\n bestBid: orderbook.bids[0]?.price ?? null,\n bestAsk: orderbook.asks[0]?.price ?? null,\n },\n ]),\n ),\n midpoint: bestBid != null && bestAsk != null ? (bestBid + bestAsk) / 2 : null,\n spread: bestBid != null && bestAsk != null ? bestAsk - bestBid : null,\n timestamp,\n snapshotVersion: 0,\n integrity: \"ok\",\n };\n};\n\nexport const createMarketOrderbookDataFromState = (\n state: OrderbookState,\n options?: { snapshotVersion?: number },\n): MarketOrderbookData => {\n return {\n marketId: state.marketId,\n orderbook: {\n bids: state.bids,\n asks: state.asks,\n },\n venueOrderbooks: state.venueOrderbooks,\n venues: state.venues,\n midpoint: state.midpoint,\n spread: state.spread,\n timestamp: state.timestamp,\n snapshotVersion: options?.snapshotVersion ?? 0,\n seq: state.seq,\n checksum: state.checksum,\n integrity: \"ok\",\n };\n};\n\nexport const marketOrderbookDataToResponse = (\n data: MarketOrderbookData,\n): AggregatedOrderbookResponse => {\n return {\n venueMarketId: data.marketId,\n orderbook: data.orderbook,\n venueOrderbooks: data.venueOrderbooks,\n venues: data.venues,\n midpoint: data.midpoint,\n spread: data.spread,\n timestamp: data.timestamp,\n seq: data.seq,\n checksum: data.checksum,\n matchedMarkets: data.matchedMarkets,\n };\n};\n\nexport const marketOrderbookDataToState = (data: MarketOrderbookData): OrderbookState => {\n return {\n marketId: data.marketId,\n bids: data.orderbook.bids,\n asks: data.orderbook.asks,\n venueOrderbooks: data.venueOrderbooks,\n venues: data.venues,\n midpoint: data.midpoint,\n spread: data.spread,\n timestamp: data.timestamp,\n seq: data.seq ?? 0,\n checksum: data.checksum ?? 0,\n };\n};\n\nexport const withOrderbookIntegrity = (\n data: MarketOrderbookData | null | undefined,\n integrity: MarketOrderbookIntegrity,\n): MarketOrderbookData | null | undefined => {\n if (!data) return data;\n if (data.integrity === integrity) return data;\n return {\n ...data,\n integrity,\n };\n};\n\nexport const applyOrderbookDepth = (\n data: MarketOrderbookData,\n depth?: number | null,\n): MarketOrderbookData => {\n if (depth == null) return data;\n\n return {\n ...data,\n orderbook: {\n bids: truncateLevels(data.orderbook.bids, depth),\n asks: truncateLevels(data.orderbook.asks, depth),\n },\n venueOrderbooks: truncateVenueOrderbooks(data.venueOrderbooks, depth),\n };\n};\n","import { computeChecksum, type AggClient, type OutcomeOrderbookResponse } from \"@agg-build/sdk\";\nimport { type MarketLiveStore } from \"./live-store\";\n\nimport { outcomeOrderbookToState } from \"./orderbook-snapshot\";\n\nconst SOCKET_GRACE_MS = 200;\nconst REST_BUDGET_MS = 1500;\nconst MAX_SEED_AGE_MS = 5000;\nexport function hasFreshSnapshot(store: MarketLiveStore, id: string, now = Date.now()): boolean {\n const state = store.get(id);\n return (\n !!state.orderbook &&\n state.integrity === \"ok\" &&\n now - state.orderbook.timestamp * 1000 <= MAX_SEED_AGE_MS &&\n state.orderbook.timestamp * 1000 <= now + 1000\n );\n}\n\n/** Keep cached query closures separate from the hook render's deep live books and React results. */\nexport function createOrderbookSnapshotQuery(\n client: Pick<AggClient, \"getOutcomeOrderbooks\">,\n store: MarketLiveStore,\n ids: string[],\n socketHealthy: boolean,\n): (context: { signal: AbortSignal }) => Promise<Record<string, OutcomeOrderbookResponse>> {\n // Native binding survives production minifier inlining; an arrow factory can be folded back\n // into the hook and share its render context (including retired deep books).\n return fetchSnapshotQuery.bind(null, client, store, ids, socketHealthy);\n}\n\nfunction fetchSnapshotQuery(\n client: Pick<AggClient, \"getOutcomeOrderbooks\">,\n store: MarketLiveStore,\n ids: string[],\n socketHealthy: boolean,\n { signal }: { signal: AbortSignal },\n): Promise<Record<string, OutcomeOrderbookResponse>> {\n return selectOrderbookSnapshots(client, store, ids, socketHealthy, signal);\n}\n\n/** One selection per sorted query key; TanStack deduplicates concurrent consumers. */\nexport async function selectOrderbookSnapshots(\n client: Pick<AggClient, \"getOutcomeOrderbooks\">,\n store: MarketLiveStore,\n ids: string[],\n socketHealthy: boolean,\n signal: AbortSignal,\n): Promise<Record<string, OutcomeOrderbookResponse>> {\n if (ids.length > 100) throw new Error(\"Orderbook snapshot batch exceeds 100 outcomes\");\n const missing = () => ids.filter((id) => !hasFreshSnapshot(store, id));\n if (!missing().length || signal.aborted) return {};\n if (socketHealthy) {\n await new Promise<void>((resolve) => {\n let unsubscribe = () => {};\n const finish = () => {\n clearTimeout(timer);\n unsubscribe();\n signal.removeEventListener(\"abort\", finish);\n resolve();\n };\n const timer = setTimeout(finish, SOCKET_GRACE_MS);\n unsubscribe = store.subscribe(ids, () => {\n if (!missing().length) finish();\n });\n signal.addEventListener(\"abort\", finish, { once: true });\n });\n }\n const requested = missing();\n if (!requested.length || signal.aborted) return {};\n const initialStates = new Map(requested.map((id) => [id, store.get(id)]));\n const controller = new AbortController();\n const abort = () => controller.abort();\n signal.addEventListener(\"abort\", abort, { once: true });\n const timer = setTimeout(abort, REST_BUDGET_MS);\n const unsubscribe = store.subscribe(requested, () => {\n if (!missing().length) controller.abort();\n });\n try {\n const response = await client.getOutcomeOrderbooks(\n { venueMarketOutcomeIds: requested },\n { signal: controller.signal },\n );\n if (signal.aborted) return {};\n return Object.fromEntries(\n response.data.flatMap((book, index) => {\n const id = requested[index];\n if (!book || !id || hasFreshSnapshot(store, id)) return [];\n if (book.venueMarketOutcomeId !== id)\n throw new Error(\"Orderbook snapshot identity mismatch\");\n if (\n !Number.isFinite(book.timestamp) ||\n !Number.isSafeInteger(book.seq) ||\n book.seq < 0 ||\n !Number.isInteger(book.checksum)\n )\n throw new Error(\"Invalid orderbook snapshot metadata\");\n const snapshot = outcomeOrderbookToState(book, id);\n if (\n ![...snapshot.bids, ...snapshot.asks].every(\n (level) =>\n Number.isFinite(level.price) && Number.isFinite(level.size) && level.size >= 0,\n )\n )\n throw new Error(\"Invalid orderbook snapshot levels\");\n const projectedChecksum = (book as OutcomeOrderbookResponse & { snapshotChecksum?: number })\n .snapshotChecksum;\n if (projectedChecksum != null && computeChecksum(snapshot) !== projectedChecksum)\n throw new Error(\"Orderbook snapshot checksum mismatch\");\n const current = store.get(id);\n const live = current.orderbook;\n // Any socket/seed update received after this request started takes precedence,\n // including fresh snapshots whose source timestamp is unchanged on a quiet market.\n const initial = initialStates.get(id)!;\n const initialBook = initial.orderbook;\n if (\n current.orderbookSnapshotVersion !== initial.orderbookSnapshotVersion ||\n !!live !== !!initialBook ||\n (live &&\n initialBook &&\n (live.seq !== initialBook.seq ||\n live.checksum !== initialBook.checksum ||\n live.timestamp !== initialBook.timestamp))\n )\n return [];\n if (live) {\n const sameGeneration =\n current.isConnected &&\n current.integrity === \"ok\" &&\n current.orderbookGeneration === current.connectionGeneration;\n if (snapshot.timestamp < live.timestamp || (sameGeneration && snapshot.seq <= live.seq))\n return [];\n // Restart/disconnect recovery may reset the engine sequence; require a newer\n // source timestamp before replacing an existing book from that older generation.\n if (!sameGeneration && snapshot.timestamp <= live.timestamp) return [];\n }\n store.update(id, (previous) => ({\n ...previous,\n orderbook: snapshot,\n integrity: \"ok\",\n orderbookError: null,\n }));\n return [[id, book]];\n }),\n );\n } catch (error) {\n if (signal.aborted || !missing().length) return {};\n throw error;\n } finally {\n clearTimeout(timer);\n unsubscribe();\n signal.removeEventListener(\"abort\", abort);\n }\n}\n","import { useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport type { VenueMarket } from \"@agg-build/sdk\";\nimport { useAggWebSocket, useAggWebSocketConnectionState } from \"./core/providers/ws-provider\";\nimport { useAggClient, useAggUiConfig } from \"./core/provider\";\nimport { outcomeOrderbookToState } from \"./market-data/orderbook-snapshot\";\nimport {\n applyOrderbookDepth,\n createMarketOrderbookDataFromState,\n type MarketOrderbookData,\n} from \"./market-data/orderbook-cache\";\nimport { getMarketLiveStore, useLiveStates } from \"./market-data/live-store\";\nimport { createOrderbookSnapshotQuery } from \"./market-data/snapshot-selection\";\nimport { useMarketDataSubscription } from \"./market-data/subscription\";\nimport { createMarketLiveState } from \"./market-data/live-cache\";\n\nexport interface UseMarketOrderbookVenueOutcome {\n venue: VenueMarket[\"venue\"];\n venueMarketOutcomeId: string;\n}\n\nexport interface UseMarketOrderbookOptions {\n /**\n * The venueMarketOutcomeId to subscribe to (the `outcomes[].id` on REST\n * market responses). Orderbooks are keyed per-outcome on the WS gateway —\n * a venueMarketId here will never resolve to a book.\n */\n venueMarketOutcomeId?: string | null;\n /** @deprecated Misleading name — this has always been a venueMarketOutcomeId.\n * Use `venueMarketOutcomeId` instead. */\n marketId?: string | null;\n depth?: number;\n enabled?: boolean;\n venueOutcomes?: UseMarketOrderbookVenueOutcome[];\n /** Override live subscription. When false, skips the internal WS subscription\n * (useful when a parent already manages subscriptions for this market). */\n live?: boolean;\n}\n\nexport interface UseMarketOrderbookResult {\n data: MarketOrderbookData | null;\n dataById: Record<string, MarketOrderbookData>;\n isLoading: boolean;\n error: Error | null;\n isLive: boolean;\n refetch: () => Promise<unknown>;\n}\n\n/**\n * Subscribe to a live orderbook for the selected outcome(s).\n *\n * WS-driven in steady state: subscribes to outcome IDs, receives snapshots\n * + deltas via the gateway, reads from the React Query live cache.\n *\n * REST-seeds `GET /orderbook/outcome/:id` so the book still renders when the\n * websocket is down or the snapshot never arrives. WS overwrites the seed.\n */\nexport function useMarketOrderbook(options: UseMarketOrderbookOptions): UseMarketOrderbookResult {\n const queryClient = useQueryClient();\n const client = useAggClient();\n const ws = useAggWebSocket();\n const isConnected = useAggWebSocketConnectionState();\n const {\n features: { enableLiveUpdates },\n } = useAggUiConfig();\n const { venueMarketOutcomeId, marketId, depth, enabled = true, venueOutcomes, live } = options;\n // `marketId` is the deprecated alias — it always carried an outcome id.\n const selectedId = venueMarketOutcomeId ?? marketId ?? null;\n const liveEnabled = live ?? enableLiveUpdates;\n\n // Subscribe to outcome IDs for live WS updates.\n // Always subscribe when enabled — this hook is WS-only so the subscription\n // is the sole data source regardless of the `live` flag.\n const outcomeIds = venueOutcomes?.map((v) => v.venueMarketOutcomeId).filter(Boolean);\n const subscriptionIds = outcomeIds?.length\n ? [...new Set(outcomeIds)]\n : selectedId\n ? [selectedId]\n : [];\n const selectedOutcomeId = subscriptionIds[0] ?? null;\n\n useMarketDataSubscription({\n marketId: selectedOutcomeId,\n additionalMarketIds: subscriptionIds.slice(1),\n enabled: enabled && !!selectedOutcomeId,\n orderbook: true,\n });\n\n const store = getMarketLiveStore(queryClient);\n const liveQueries = useLiveStates(enabled ? subscriptionIds : []);\n const sortedIds = [...subscriptionIds].sort();\n // Allow bounded first-connect startup; a previously connected transport now offline skips grace.\n const preferSocket =\n enabled &&\n Boolean(ws) &&\n (isConnected || subscriptionIds.every((id) => (store.get(id).connectionGeneration ?? 0) === 0));\n const seedQuery = useQuery({\n queryKey: [\"market-orderbook-seed\", sortedIds],\n queryFn: createOrderbookSnapshotQuery(client, store, sortedIds, preferSocket),\n enabled: enabled && subscriptionIds.length > 0,\n staleTime: 5000,\n gcTime: 60_000,\n refetchOnWindowFocus: false,\n retry: false,\n });\n\n const liveStates = subscriptionIds.map((subscriptionId, index) => {\n return (\n liveQueries[index]?.data ??\n store.peek(subscriptionId) ??\n createMarketLiveState(subscriptionId)\n );\n });\n const seededOrderbooks = subscriptionIds.map((subscriptionId, index) => {\n const liveBook = liveStates[index]?.orderbook ?? null;\n if (liveBook) return liveBook;\n const seed = seedQuery.data?.[subscriptionId];\n return seed?.orderbook?.bids && seed.orderbook.asks\n ? outcomeOrderbookToState(seed, subscriptionId)\n : null;\n });\n const primaryOrderbook = seededOrderbooks[0] ?? null;\n const primarySnapshotVersion = liveStates[0]?.orderbookSnapshotVersion ?? 0;\n\n // Transform OrderbookState → MarketOrderbookData (what the UI component expects)\n const data: MarketOrderbookData | null = primaryOrderbook\n ? applyOrderbookDepth(\n createMarketOrderbookDataFromState(primaryOrderbook, {\n snapshotVersion: primarySnapshotVersion,\n }),\n depth,\n )\n : null;\n const dataById = Object.fromEntries(\n seededOrderbooks.flatMap((orderbook, index) => {\n if (!orderbook) return [];\n\n return [\n [\n subscriptionIds[index],\n applyOrderbookDepth(\n createMarketOrderbookDataFromState(orderbook, {\n snapshotVersion: liveStates[index]?.orderbookSnapshotVersion,\n }),\n depth,\n ),\n ],\n ];\n }),\n ) as Record<string, MarketOrderbookData>;\n const hasAnyOrderbook = seededOrderbooks.some((orderbook) => orderbook != null);\n const seedLoading = seedQuery.isLoading;\n const liveOrderbookErrorMessage =\n enabled && liveEnabled && !hasAnyOrderbook\n ? (liveStates.find(\n (liveState) =>\n typeof liveState.orderbookError === \"string\" && liveState.orderbookError.length > 0,\n )?.orderbookError ?? null)\n : null;\n\n return {\n data,\n dataById,\n isLoading: enabled && !hasAnyOrderbook && liveOrderbookErrorMessage == null && seedLoading,\n error: liveOrderbookErrorMessage\n ? new Error(liveOrderbookErrorMessage)\n : !hasAnyOrderbook && seedQuery.error instanceof Error\n ? seedQuery.error\n : null,\n isLive: Boolean(enabled && liveEnabled && selectedOutcomeId && isConnected),\n refetch: async () => {\n if (!enabled) return;\n if (subscriptionIds.length === 0) return;\n\n // Reset live error so UI can leave error state while we request a fresh snapshot.\n subscriptionIds.forEach((subscriptionId) =>\n store.update(subscriptionId, (previous) => ({ ...previous, orderbookError: null })),\n );\n\n ws?.resnapshot(subscriptionIds);\n return seedQuery.refetch();\n },\n };\n}\n","import type { OrderbookState, WsTrade } from \"@agg-build/sdk\";\nimport { useAggUiConfig } from \"./core/provider\";\nimport { useAggWebSocketConnectionState } from \"./core/providers/ws-provider\";\nimport { useLiveStates } from \"./market-data/live-store\";\nimport { useMarketOrderbook } from \"./use-market-orderbook\";\n\nexport interface UseLiveMarketResult {\n orderbook: OrderbookState | null;\n trades: WsTrade[];\n isConnected: boolean;\n integrity: \"ok\" | \"resyncing\";\n}\n\nexport { outcomeOrderbookToState } from \"./market-data/orderbook-snapshot\";\n\nexport function useLiveMarket(canonicalMarketId: string | null): UseLiveMarketResult {\n const {\n features: { enableLiveUpdates },\n } = useAggUiConfig();\n const connected = useAggWebSocketConnectionState();\n const [snapshot] = useLiveStates([canonicalMarketId ?? \"__disabled__\"]);\n useMarketOrderbook({\n venueMarketOutcomeId: canonicalMarketId,\n enabled: !!canonicalMarketId,\n live: enableLiveUpdates,\n });\n const data = snapshot!.data;\n return {\n orderbook: data.orderbook,\n trades: data.trades,\n isConnected: !!canonicalMarketId && enableLiveUpdates && connected,\n integrity: data.integrity,\n };\n}\n","import { useMemo, useRef } from \"react\";\nimport type { VenueMarket } from \"@agg-build/sdk\";\nimport { useLiveStates } from \"./market-data/live-store\";\nimport { useAggUiConfig } from \"./core/provider\";\nimport { type MarketLiveState } from \"./market-data/live-cache\";\n\nconst EMPTY_PRICES = new Map<string, number>();\n\n/**\n * Build a stable fingerprint from query results so useMemo only recomputes\n * when actual midpoint values change.\n */\nconst buildMidpointFingerprint = (\n outcomeIds: string[],\n queries: Array<{ data?: MarketLiveState }>,\n): string => {\n const parts: string[] = [];\n for (let i = 0; i < outcomeIds.length; i++) {\n const midpoint = queries[i]?.data?.orderbook?.midpoint;\n parts.push(`${outcomeIds[i]}:${midpoint ?? \"_\"}`);\n }\n return parts.join(\"|\");\n};\n\n/**\n * Derive live display prices for every outcome across the given venue markets.\n *\n * Each outcome has its own live orderbook (the engine emits per-outcome deltas\n * on `agg.orderbook.outcome`). The midpoint from each outcome's book is its\n * price — no complement derivation needed.\n *\n * Returns a stable Map<outcomeId, price> that updates only when cache entries\n * change.\n */\nexport function useLiveOutcomePrices(\n venueMarkets: VenueMarket[] | null | undefined,\n): Map<string, number> {\n const {\n features: { enableLiveUpdates },\n } = useAggUiConfig();\n\n // Collect all outcome IDs across venue markets\n const outcomeIds = useMemo(() => {\n if (!venueMarkets?.length) return [];\n const ids = new Set<string>();\n for (const vm of venueMarkets) {\n for (const outcome of vm.venueMarketOutcomes ?? []) {\n if (outcome.id) ids.add(outcome.id);\n for (const ref of outcome.matchedVenueMarketOutcomes ?? []) {\n if (ref.venueMarketOutcomeId) ids.add(ref.venueMarketOutcomeId);\n }\n }\n }\n return [...ids].sort();\n }, [venueMarkets]);\n\n // Query the live cache for each outcome's orderbook\n const queries = useLiveStates(outcomeIds);\n\n const fingerprint = buildMidpointFingerprint(outcomeIds, queries);\n const prevRef = useRef<{ fingerprint: string; prices: Map<string, number> }>({\n fingerprint: \"\",\n prices: EMPTY_PRICES,\n });\n\n const data = useMemo(() => {\n if (!venueMarkets?.length) return EMPTY_PRICES;\n\n if (fingerprint === prevRef.current.fingerprint) {\n return prevRef.current.prices;\n }\n\n const prices = new Map<string, number>();\n\n // Build outcome ID → live midpoint map\n const liveByOutcomeId = new Map<string, number | null>();\n for (let i = 0; i < outcomeIds.length; i++) {\n const state = queries[i]?.data as MarketLiveState | undefined;\n liveByOutcomeId.set(outcomeIds[i], state?.orderbook?.midpoint ?? null);\n }\n\n if (!enableLiveUpdates) return prices;\n\n for (const outcomeId of outcomeIds) {\n // Only set when there is an actual live WS midpoint — skip discovery-price\n // fallbacks so REST midpoints can surface through consuming components.\n const liveMidpoint = liveByOutcomeId.get(outcomeId);\n if (liveMidpoint != null) prices.set(outcomeId, liveMidpoint);\n }\n\n prevRef.current = { fingerprint, prices };\n return prices;\n }, [venueMarkets, enableLiveUpdates, fingerprint, outcomeIds, queries]);\n\n return data;\n}\n\n/**\n * Look up the live price for a given outcome ID.\n * Returns undefined when the ID is not found in the map.\n */\nexport function findLivePriceById(livePrices: Map<string, number>, id: string): number | undefined {\n return livePrices.get(id);\n}\n\n/**\n * Look up the average live price across venues for a given outcome label.\n * Returns undefined when no matching outcomes are found in the map.\n */\nexport function findLivePriceForLabel(\n livePrices: Map<string, number>,\n venueMarkets: VenueMarket[],\n label: string,\n): number | undefined {\n const normalizedLabel = label.trim().toLowerCase();\n let sum = 0;\n let count = 0;\n\n for (const vm of venueMarkets) {\n for (const outcome of vm.venueMarketOutcomes) {\n if (outcome.label.trim().toLowerCase() !== normalizedLabel) continue;\n const price = livePrices.get(outcome.id);\n if (price == null) continue;\n sum += price;\n count += 1;\n }\n }\n\n return count > 0 ? sum / count : undefined;\n}\n","import { useMemo, useRef } from \"react\";\nimport type { VenueMarket } from \"@agg-build/sdk\";\nimport { useLiveStates } from \"./market-data/live-store\";\nimport { useAggUiConfig } from \"./core/provider\";\nimport { type MarketLiveState } from \"./market-data/live-cache\";\n\nexport type LiveBestPrices = ReadonlyMap<string, { bestBid?: number; bestAsk?: number }>;\n\n/**\n * A WS-derived best-price candidate for one outcome, carrying the venue that\n * produced each side *and* a freshness stamp. This is the richer companion to\n * {@link LiveBestPrices}: it keeps the venue attribution that the bare\n * `{ bestBid, bestAsk }` map throws away, so display surfaces can switch the\n * venue logo to whichever venue currently owns the best live price — keeping\n * the logo paired with the price instead of pinned to the REST snapshot.\n */\nexport interface LiveBestPriceCandidate {\n bestBid?: number;\n bestAsk?: number;\n /** Venue that owns the cross-venue best bid (best place to sell). */\n bestBidVenue?: string;\n /** Venue that owns the cross-venue best ask (cheapest place to buy). */\n bestAskVenue?: string;\n midpoint?: number;\n /** Venue the midpoint is attributed to (cheapest-ask side, then best-bid). */\n midpointVenue?: string;\n /** Orderbook timestamp (seconds) of the freshest book backing this candidate. */\n updatedAt?: number;\n}\n\nexport type LiveBestPriceCandidates = ReadonlyMap<string, LiveBestPriceCandidate>;\n\nconst EMPTY: LiveBestPrices = new Map();\nconst EMPTY_CANDIDATES: LiveBestPriceCandidates = new Map();\n\n// Top-of-aggregated-book per outcome — the engine already cross-venue aggregates\n// within an outcome's own snapshot, so `bids[0]` / `asks[0]` already represent\n// the best level across that outcome's venues.\nconst extractOutcomeBestPrices = (\n state: MarketLiveState | undefined,\n): { bestBid?: number; bestAsk?: number } => {\n const ob = state?.orderbook;\n if (!ob) return {};\n const bestBid = ob.bids[0]?.price;\n const bestAsk = ob.asks[0]?.price;\n return {\n bestBid: bestBid != null ? bestBid : undefined,\n bestAsk: bestAsk != null ? bestAsk : undefined,\n };\n};\n\n// Fingerprint so useMemo only recomputes when actual top-of-book moves.\nconst buildFingerprint = (\n outcomeIds: string[],\n queries: Array<{ data?: MarketLiveState }>,\n): string => {\n const parts: string[] = [];\n for (let i = 0; i < outcomeIds.length; i++) {\n const ob = queries[i]?.data?.orderbook;\n const bid = ob?.bids[0]?.price;\n const ask = ob?.asks[0]?.price;\n parts.push(`${outcomeIds[i]}:${bid ?? \"_\"}:${ask ?? \"_\"}`);\n }\n return parts.join(\"|\");\n};\n\n/**\n * WS-derived cross-venue + cross-outcome best bid/ask per outcome.\n *\n * For each outcome in `venueMarkets` (plus matched twins via MVMO refs):\n * - bestBid/bestAsk taken from the per-outcome aggregated top of book.\n * - Then folded across MVMO groups: lowest bestAsk wins (cheapest to buy),\n * highest bestBid wins (best to sell). The chosen best is broadcast to\n * every member of the group so display surfaces pick it up regardless\n * of which outcome they look up.\n *\n * Empty until WS snapshots/deltas land for the subscribed outcomes. Designed\n * to merge as overrides on top of REST `bestPrices` from `useMidpoints`, with\n * WS winning where present.\n */\nexport function useLiveBestPrices(venueMarkets: VenueMarket[] | null | undefined): LiveBestPrices {\n const {\n features: { enableLiveUpdates },\n } = useAggUiConfig();\n\n const outcomeIds = useMemo(() => {\n if (!venueMarkets?.length) return [];\n const ids = new Set<string>();\n for (const vm of venueMarkets) {\n for (const outcome of vm.venueMarketOutcomes ?? []) {\n if (outcome.id) ids.add(outcome.id);\n for (const ref of outcome.matchedVenueMarketOutcomes ?? []) {\n if (ref.venueMarketOutcomeId) ids.add(ref.venueMarketOutcomeId);\n }\n }\n }\n return [...ids].sort();\n }, [venueMarkets]);\n\n const queries = useLiveStates(outcomeIds);\n\n const fingerprint = buildFingerprint(outcomeIds, queries);\n const prevRef = useRef<{ fingerprint: string; result: LiveBestPrices }>({\n fingerprint: \"\",\n result: EMPTY,\n });\n\n return useMemo(() => {\n if (!venueMarkets?.length || !enableLiveUpdates) return EMPTY;\n if (fingerprint === prevRef.current.fingerprint) return prevRef.current.result;\n\n // Pass 1: per-outcome bestBid/bestAsk from each outcome's aggregated book.\n const perOutcome = new Map<string, { bestBid?: number; bestAsk?: number }>();\n for (let i = 0; i < outcomeIds.length; i++) {\n const state = queries[i]?.data as MarketLiveState | undefined;\n const best = extractOutcomeBestPrices(state);\n if (best.bestBid != null || best.bestAsk != null) {\n perOutcome.set(outcomeIds[i], best);\n }\n }\n\n if (perOutcome.size === 0) {\n prevRef.current = { fingerprint, result: EMPTY };\n return EMPTY;\n }\n\n const result = new Map<string, { bestBid?: number; bestAsk?: number }>(perOutcome);\n\n // Pass 2: fold across MVMO groups so every member of a cluster gets the\n // cross-outcome best. Lowest ask wins for \"cheapest buy\"; highest bid wins\n // for \"best sell\". Mirrors the REST cross-venue logic in `useMidpoints`\n // so display surfaces see consistent semantics regardless of source.\n for (const vm of venueMarkets) {\n for (const outcome of vm.venueMarketOutcomes ?? []) {\n const refs = outcome.matchedVenueMarketOutcomes ?? [];\n if (!refs.length) continue;\n\n const group = [outcome.id, ...refs.map((ref) => ref.venueMarketOutcomeId)];\n let groupBestAsk: number | undefined;\n let groupBestBid: number | undefined;\n for (const id of group) {\n const entry = perOutcome.get(id);\n if (!entry) continue;\n if (entry.bestAsk != null && (groupBestAsk == null || entry.bestAsk < groupBestAsk)) {\n groupBestAsk = entry.bestAsk;\n }\n if (entry.bestBid != null && (groupBestBid == null || entry.bestBid > groupBestBid)) {\n groupBestBid = entry.bestBid;\n }\n }\n if (groupBestAsk == null && groupBestBid == null) continue;\n\n for (const id of group) {\n const prev = result.get(id) ?? {};\n const nextBid = groupBestBid ?? prev.bestBid;\n const nextAsk = groupBestAsk ?? prev.bestAsk;\n if (nextBid == null && nextAsk == null) continue;\n result.set(id, {\n ...(nextBid != null ? { bestBid: nextBid } : {}),\n ...(nextAsk != null ? { bestAsk: nextAsk } : {}),\n });\n }\n }\n }\n\n prevRef.current = { fingerprint, result };\n return result;\n }, [venueMarkets, enableLiveUpdates, fingerprint, outcomeIds, queries]);\n}\n\n/**\n * Merge WS bestBid/bestAsk over a REST `bestPrices` map, WS values winning\n * where present. Returns the REST map unchanged when WS is empty. Designed\n * for callers that need to pass a single `bestPrices` map to display logic.\n */\nexport function mergeBestPricesPreferringLive(\n rest: ReadonlyMap<string, { bestBid?: number; bestAsk?: number }> | null | undefined,\n live: LiveBestPrices,\n): ReadonlyMap<string, { bestBid?: number; bestAsk?: number }> {\n if (!live.size) return rest ?? EMPTY;\n if (!rest || !rest.size) return live;\n\n const merged = new Map<string, { bestBid?: number; bestAsk?: number }>(rest);\n for (const [id, liveEntry] of live) {\n const prev = merged.get(id) ?? {};\n merged.set(id, {\n bestBid: liveEntry.bestBid ?? prev.bestBid,\n bestAsk: liveEntry.bestAsk ?? prev.bestAsk,\n });\n }\n return merged;\n}\n\n// ── Venue-attributed live best-price candidates ────────────────────────────\n\n/**\n * Attribute the venue that owns a given side of the aggregated top of book.\n *\n * The engine's per-outcome book already merges that outcome's venues, exposing\n * each venue's best bid/ask in `orderbook.venues`. The owner of the best bid is\n * the venue with the highest bid; the owner of the best ask is the venue with\n * the lowest ask. Falls back to the level's own per-venue size attribution\n * (largest contributor) when `venues` is absent — e.g. single-venue books.\n */\nconst pickSideVenue = (\n venues: Record<string, { bestBid: number | null; bestAsk: number | null }> | undefined,\n level: { venues?: Record<string, number> } | undefined,\n side: \"bid\" | \"ask\",\n): string | undefined => {\n if (venues) {\n let bestVenue: string | undefined;\n let bestValue: number | undefined;\n for (const [venue, info] of Object.entries(venues)) {\n const value = side === \"bid\" ? info.bestBid : info.bestAsk;\n if (value == null) continue;\n const wins = bestValue == null || (side === \"bid\" ? value > bestValue : value < bestValue);\n if (wins) {\n bestValue = value;\n bestVenue = venue;\n }\n }\n if (bestVenue != null) return bestVenue;\n }\n\n if (level?.venues) {\n let bestVenue: string | undefined;\n let bestSize = -Infinity;\n for (const [venue, size] of Object.entries(level.venues)) {\n if (size > bestSize) {\n bestSize = size;\n bestVenue = venue;\n }\n }\n if (bestVenue != null) return bestVenue;\n }\n\n return undefined;\n};\n\n/**\n * Pull the per-outcome best bid/ask, attributed venues, midpoint and freshness\n * out of a single live orderbook state. Pure — exported for unit tests.\n */\nexport const extractOutcomeBestCandidate = (\n state: MarketLiveState | undefined,\n): LiveBestPriceCandidate => {\n const ob = state?.orderbook;\n if (!ob) return {};\n\n const candidate: LiveBestPriceCandidate = {};\n const bidLevel = ob.bids[0];\n const askLevel = ob.asks[0];\n\n if (bidLevel?.price != null) {\n candidate.bestBid = bidLevel.price;\n const venue = pickSideVenue(ob.venues, bidLevel, \"bid\");\n if (venue) candidate.bestBidVenue = venue;\n }\n if (askLevel?.price != null) {\n candidate.bestAsk = askLevel.price;\n const venue = pickSideVenue(ob.venues, askLevel, \"ask\");\n if (venue) candidate.bestAskVenue = venue;\n }\n if (ob.midpoint != null) {\n candidate.midpoint = ob.midpoint;\n // The pill defaults to \"buy\" intent, so attribute the midpoint to the\n // cheapest-ask venue first, then the best-bid venue.\n const midVenue = candidate.bestAskVenue ?? candidate.bestBidVenue;\n if (midVenue) candidate.midpointVenue = midVenue;\n }\n if (ob.timestamp != null) candidate.updatedAt = ob.timestamp;\n\n return candidate;\n};\n\n/**\n * Cross-venue + cross-outcome venue-attributed best-price candidates.\n *\n * Pure (no React) so the cross-venue fold can be unit-tested directly:\n * - Pass 1: per-outcome candidate from each outcome's own aggregated book.\n * - Pass 2: fold across MVMO groups. Lowest ask wins (cheapest to buy),\n * highest bid wins (best to sell), and the *winning venue* + freshest\n * timestamp travel with the chosen price to every member of the group.\n * This is what lets a different venue's live book switch both the price\n * and the venue logo on every WS update.\n *\n * Mirrors the price fold in {@link useLiveBestPrices} and the REST fold in\n * `useMidpoints.extractBestPrices`, but additionally tracks venue + freshness.\n */\nexport function buildLiveBestPriceCandidates(\n outcomeIds: string[],\n states: Array<MarketLiveState | undefined>,\n venueMarkets: VenueMarket[] | null | undefined,\n): Map<string, LiveBestPriceCandidate> {\n const perOutcome = new Map<string, LiveBestPriceCandidate>();\n for (let i = 0; i < outcomeIds.length; i++) {\n const candidate = extractOutcomeBestCandidate(states[i]);\n if (candidate.bestBid != null || candidate.bestAsk != null || candidate.midpoint != null) {\n perOutcome.set(outcomeIds[i], candidate);\n }\n }\n\n if (perOutcome.size === 0 || !venueMarkets?.length) {\n return perOutcome;\n }\n\n const result = new Map<string, LiveBestPriceCandidate>(perOutcome);\n\n for (const vm of venueMarkets) {\n for (const outcome of vm.venueMarketOutcomes ?? []) {\n const refs = outcome.matchedVenueMarketOutcomes ?? [];\n if (!refs.length) continue;\n\n const group = [outcome.id, ...refs.map((ref) => ref.venueMarketOutcomeId)];\n let groupBestAsk: number | undefined;\n let groupBestAskVenue: string | undefined;\n let groupBestBid: number | undefined;\n let groupBestBidVenue: string | undefined;\n let groupUpdatedAt: number | undefined;\n for (const id of group) {\n const entry = perOutcome.get(id);\n if (!entry) continue;\n if (entry.bestAsk != null && (groupBestAsk == null || entry.bestAsk < groupBestAsk)) {\n groupBestAsk = entry.bestAsk;\n groupBestAskVenue = entry.bestAskVenue;\n }\n if (entry.bestBid != null && (groupBestBid == null || entry.bestBid > groupBestBid)) {\n groupBestBid = entry.bestBid;\n groupBestBidVenue = entry.bestBidVenue;\n }\n if (\n entry.updatedAt != null &&\n (groupUpdatedAt == null || entry.updatedAt > groupUpdatedAt)\n ) {\n groupUpdatedAt = entry.updatedAt;\n }\n }\n if (groupBestAsk == null && groupBestBid == null) continue;\n\n for (const id of group) {\n const prev = result.get(id) ?? {};\n const next: LiveBestPriceCandidate = { ...prev };\n if (groupBestBid != null) {\n next.bestBid = groupBestBid;\n if (groupBestBidVenue) next.bestBidVenue = groupBestBidVenue;\n }\n if (groupBestAsk != null) {\n next.bestAsk = groupBestAsk;\n if (groupBestAskVenue) next.bestAskVenue = groupBestAskVenue;\n }\n if (groupUpdatedAt != null) next.updatedAt = groupUpdatedAt;\n result.set(id, next);\n }\n }\n }\n\n return result;\n}\n\n// Fingerprint includes venue attribution + timestamp so the memo recomputes\n// (and the venue logo can switch) whenever any of those move, not just price.\nconst buildCandidateFingerprint = (\n outcomeIds: string[],\n queries: Array<{ data?: MarketLiveState }>,\n): string => {\n const parts: string[] = [];\n for (let i = 0; i < outcomeIds.length; i++) {\n const ob = queries[i]?.data?.orderbook;\n const bid = ob?.bids[0]?.price;\n const ask = ob?.asks[0]?.price;\n const mid = ob?.midpoint;\n const ts = ob?.timestamp;\n const venues = ob?.venues ? Object.keys(ob.venues).sort().join(\",\") : \"\";\n parts.push(`${outcomeIds[i]}:${bid ?? \"_\"}:${ask ?? \"_\"}:${mid ?? \"_\"}:${ts ?? \"_\"}:${venues}`);\n }\n return parts.join(\"|\");\n};\n\n/**\n * React hook companion to {@link useLiveBestPrices} that additionally carries\n * venue attribution + freshness per outcome. Recomputes on every WS update\n * (snapshot/delta) that moves price, venue ownership, or timestamp.\n *\n * Empty until WS books land for the subscribed outcomes. Designed to feed a\n * unified price+venue selector so the venue logo always follows the live price.\n */\nexport function useLiveBestPriceCandidates(\n venueMarkets: VenueMarket[] | null | undefined,\n): LiveBestPriceCandidates {\n const {\n features: { enableLiveUpdates },\n } = useAggUiConfig();\n\n const outcomeIds = useMemo(() => {\n if (!venueMarkets?.length) return [];\n const ids = new Set<string>();\n for (const vm of venueMarkets) {\n for (const outcome of vm.venueMarketOutcomes ?? []) {\n if (outcome.id) ids.add(outcome.id);\n for (const ref of outcome.matchedVenueMarketOutcomes ?? []) {\n if (ref.venueMarketOutcomeId) ids.add(ref.venueMarketOutcomeId);\n }\n }\n }\n return [...ids].sort();\n }, [venueMarkets]);\n\n const queries = useLiveStates(outcomeIds);\n\n const fingerprint = buildCandidateFingerprint(outcomeIds, queries);\n const prevRef = useRef<{ fingerprint: string; result: LiveBestPriceCandidates }>({\n fingerprint: \"\",\n result: EMPTY_CANDIDATES,\n });\n\n return useMemo(() => {\n if (!venueMarkets?.length || !enableLiveUpdates) return EMPTY_CANDIDATES;\n if (fingerprint === prevRef.current.fingerprint) return prevRef.current.result;\n\n const states = outcomeIds.map((_, i) => queries[i]?.data as MarketLiveState | undefined);\n const result = buildLiveBestPriceCandidates(outcomeIds, states, venueMarkets);\n prevRef.current = { fingerprint, result };\n return result;\n }, [venueMarkets, enableLiveUpdates, fingerprint, outcomeIds, queries]);\n}\n","import type { WsTrade } from \"@agg-build/sdk\";\nimport { useAggUiConfig } from \"./core/provider\";\nimport { useLiveMarket } from \"./use-live-market\";\nimport { useMarketDataSubscription } from \"./market-data/subscription\";\n\n/**\n * Subscribe to real-time trade feed for a canonical market.\n * Manages a separate trade subscription on the WS (trades use a different channel).\n * Returns a bounded array of recent trades (max 50, newest first).\n */\nexport function useLiveTrades(canonicalMarketId: string | null): WsTrade[] {\n const {\n features: { enableLiveUpdates },\n } = useAggUiConfig();\n const { trades } = useLiveMarket(canonicalMarketId);\n\n useMarketDataSubscription({\n marketId: canonicalMarketId,\n enabled: Boolean(canonicalMarketId && enableLiveUpdates),\n orderbook: false,\n trades: true,\n });\n\n return trades;\n}\n","import type { MidpointItem, VenueMarket } from \"@agg-build/sdk\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport { useMemo } from \"react\";\nimport { useAggClient, useAggUiConfig } from \"./core/provider\";\n\nexport interface UseMidpointsOptions {\n maxMidpointIdsPerRequest?: number;\n}\n\nexport interface UseMidpointsResult {\n /** Map of outcomeId → price. Empty while loading. */\n prices: Map<string, number>;\n /**\n * Map of outcomeId → lowest midpoint available for that exact semantic outcome\n * across the selected market cluster. Alias of `prices`, exposed under a\n * clearer name for display surfaces that want a single source of truth.\n */\n bestMidpointsByOutcomeId: Map<string, number>;\n /** Venue-local midpoint for each outcome before cross-venue best-price folding. */\n currentMidpointsByOutcomeId?: Map<string, number>;\n /**\n * Map of outcomeId → venue name that provided the price in `prices`.\n * When a matched sibling offers a lower midpoint for the same semantic\n * side, this records that sibling's venue so callers can show the\n * correct venue logo alongside the best price.\n * Empty while loading or when the API response omits `venue` fields.\n */\n venueByOutcomeId: Map<string, string>;\n /**\n * Map of outcomeId → { bestBid?, bestAsk? }. Top-of-book prices extracted\n * from the midpoints response when bestPrice=true. Empty while loading\n * or when bestPrice data is unavailable.\n */\n bestPrices: Map<string, { bestBid?: number; bestAsk?: number }>;\n /**\n * Map of outcomeId → { bestBidVenue?, bestAskVenue? }. Tracks which venue\n * supplied the winning side of the book across the MVMO group so display\n * surfaces can pair the logo with the price. Distinct per side because\n * \"best buy\" and \"best sell\" can come from different venues.\n */\n bestPriceVenuesByOutcomeId: Map<string, { bestBidVenue?: string; bestAskVenue?: string }>;\n /** True while the midpoints fetch is in flight. */\n isLoading: boolean;\n /** Best midpoint value across all venues. Undefined while loading. */\n bestMidpoint: number | undefined;\n /**\n * Venue that produced `bestMidpoint`. Paired with `bestMidpoint` from the\n * same winning outcome so display surfaces can render a matching logo +\n * price. Undefined when no candidate produced a price or when the\n * response lacked a `venue` field.\n */\n bestMidpointVenue: string | undefined;\n}\n\nconst normalizeVenueMarketIds = (venueMarkets: VenueMarket[] | null | undefined): string[] => {\n const ids = new Set<string>();\n for (const market of venueMarkets ?? []) {\n if (market.id) ids.add(market.id);\n // Include matched (cross-venue) sibling markets so the engine returns\n // top-of-book bestAsk/bestBid data for them — otherwise the response\n // only contains nested mid-points for siblings and best-price selection\n // can miss the lower side of the book.\n for (const sibling of market.matchedVenueMarkets ?? []) {\n if (sibling.id) ids.add(sibling.id);\n }\n }\n return [...ids].sort((left, right) => left.localeCompare(right));\n};\n\n/** Re-poll cadence while a requested market still has no price (e.g. a cold book). */\nexport const EMPTY_MIDPOINTS_POLL_MS = 5_000;\n/** Stop re-polling after this many fetches; a remount can still refetch. */\nexport const EMPTY_MIDPOINTS_MAX_FETCHES = 12;\n\nconst hasUsableMidpoint = (item: MidpointItem | undefined): boolean => {\n if (!item) return false;\n if (item.midpoint != null) return true;\n return (item.outcomes ?? []).some(\n (outcome) => outcome.midpoint != null || outcome.bestBid != null || outcome.bestAsk != null,\n );\n};\n\n/**\n * True when every requested primary market came back with a usable price.\n * Some venues (e.g. BETDEX) only publish midpoints after their book is read,\n * so a first response can be empty; an incomplete response must not be cached\n * as final.\n */\nexport const isMidpointResponseComplete = (\n data: { data?: MidpointItem[] } | undefined,\n primaryVenueMarketIds: readonly string[],\n): boolean => {\n if (!data?.data) return false;\n const itemByMarketId = new Map(data.data.map((item) => [item.venueMarketId, item]));\n return primaryVenueMarketIds.every((id) => hasUsableMidpoint(itemByMarketId.get(id)));\n};\n\nconst normalizeOutcomeLabel = (label: string | null | undefined): string => {\n return typeof label === \"string\" ? label.trim().toLowerCase() : \"\";\n};\n\nconst normalizeSemanticOutcomeLabel = (label: string | null | undefined): string => {\n const normalizedLabel = normalizeOutcomeLabel(label);\n if (!normalizedLabel) return \"\";\n if (normalizedLabel === \"y\") return \"yes\";\n if (normalizedLabel === \"n\") return \"no\";\n return normalizedLabel;\n};\n\nconst outcomeMatchesSemanticSide = (\n left: { label?: string | null; title?: string | null },\n right: { label?: string | null; title?: string | null },\n): boolean => {\n const leftCandidates = [left.label, left.title]\n .map((value) => normalizeSemanticOutcomeLabel(value))\n .filter(Boolean);\n const rightCandidates = [right.label, right.title]\n .map((value) => normalizeSemanticOutcomeLabel(value))\n .filter(Boolean);\n\n return leftCandidates.some((candidate) => rightCandidates.includes(candidate));\n};\n\nconst resolveBestMidpointCandidateOutcomeIds = (\n venueMarkets: VenueMarket[] | null | undefined,\n): string[] => {\n if (!venueMarkets?.length) return [];\n\n const candidateIds: string[] = [];\n for (const market of venueMarkets) {\n const outcomes = market.venueMarketOutcomes ?? [];\n const yesOutcome = outcomes.find((outcome) => normalizeOutcomeLabel(outcome.label) === \"yes\");\n if (yesOutcome?.id) {\n candidateIds.push(yesOutcome.id);\n continue;\n }\n\n const firstOutcomeId = outcomes[0]?.id;\n if (firstOutcomeId) {\n candidateIds.push(firstOutcomeId);\n }\n }\n\n return [...new Set(candidateIds)];\n};\n\n/**\n * Find the per-outcome sibling midpoint matching a parent outcome's MVMO\n * reference. Returns `null` when the engine response doesn't carry the\n * per-outcome alignment (older builds or markets without MVMO rows).\n */\nconst resolveSiblingOutcomeMidpoint = (\n matched: MidpointItem[\"matched\"] | undefined,\n ref: { venueMarketId: string; venueMarketOutcomeId: string },\n): { midpoint: number; venue: string | null } | null => {\n if (!matched?.length) return null;\n const sibling = matched.find((m) => m.venueMarketId === ref.venueMarketId);\n if (!sibling?.outcomes?.length) return null;\n const sibOutcome = sibling.outcomes.find(\n (o) => o.venueMarketOutcomeId === ref.venueMarketOutcomeId,\n );\n if (sibOutcome?.midpoint == null) return null;\n return { midpoint: sibOutcome.midpoint, venue: sibling.venue ?? null };\n};\n\nconst resolveSemanticFallbackMidpoint = ({\n marketById,\n outcome,\n matched,\n}: {\n marketById: Map<string, VenueMarket>;\n outcome: VenueMarket[\"venueMarketOutcomes\"][number];\n matched: MidpointItem[\"matched\"] | undefined;\n}): { midpoint: number; venue: string | null } | null => {\n if (!matched?.length) return null;\n\n let best: { midpoint: number; venue: string | null } | null = null;\n\n for (const sibling of matched) {\n const siblingMarket = marketById.get(sibling.venueMarketId);\n if (!siblingMarket?.venueMarketOutcomes?.length) continue;\n\n for (const siblingOutcome of siblingMarket.venueMarketOutcomes) {\n if (!outcomeMatchesSemanticSide(outcome, siblingOutcome)) continue;\n\n const candidate = resolveSiblingOutcomeMidpoint(matched, {\n venueMarketId: sibling.venueMarketId,\n venueMarketOutcomeId: siblingOutcome.id,\n });\n if (candidate == null) continue;\n if (best == null || candidate.midpoint < best.midpoint) {\n best = candidate;\n }\n }\n }\n\n return best;\n};\n\n/**\n * Build a per-outcome bestBid/bestAsk map from the midpoint response, with\n * cross-venue best-price selection applied.\n *\n * Rules:\n * - Pass 1: collect each outcome's own bestBid/bestAsk from `data[].outcomes`\n * and record the venue that supplied it.\n * - Pass 2: collect bestBid/bestAsk for any matched-only outcome that\n * appears under `data[].matched[].outcomes` (no top-level row of its own).\n * - Pass 3: for every parent outcome that lists `matchedVenueMarketOutcomes`,\n * fold the sibling outcomes' bestBid/bestAsk into the parent and pick the\n * \"best\" of each side — lowest bestAsk (cheapest to buy) and highest\n * bestBid (best to sell). The sibling's entry is updated symmetrically so\n * that whichever side of the pair the UI looks up, it reads the same\n * trusted cross-venue best — *and* the venue that produced each winning\n * side is recorded so the UI can pair the logo with the right price.\n */\nconst extractBestPrices = (\n data: MidpointItem[] | undefined,\n venueMarkets: VenueMarket[] | null | undefined,\n): {\n bestPrices: Map<string, { bestBid?: number; bestAsk?: number }>;\n bestPriceVenuesByOutcomeId: Map<string, { bestBidVenue?: string; bestAskVenue?: string }>;\n} => {\n const bestPrices = new Map<string, { bestBid?: number; bestAsk?: number }>();\n const venuesByOutcome = new Map<string, { bestBidVenue?: string; bestAskVenue?: string }>();\n if (!data?.length) return { bestPrices, bestPriceVenuesByOutcomeId: venuesByOutcome };\n\n const setEntry = (\n outcomeId: string,\n next: {\n bestBid?: number | null;\n bestAsk?: number | null;\n bestBidVenue?: string | null;\n bestAskVenue?: string | null;\n },\n ): void => {\n const prev = bestPrices.get(outcomeId);\n const merged: { bestBid?: number; bestAsk?: number } = { ...(prev ?? {}) };\n if (next.bestBid != null) merged.bestBid = next.bestBid;\n if (next.bestAsk != null) merged.bestAsk = next.bestAsk;\n if (merged.bestBid != null || merged.bestAsk != null) bestPrices.set(outcomeId, merged);\n\n const prevVenues = venuesByOutcome.get(outcomeId);\n const mergedVenues: { bestBidVenue?: string; bestAskVenue?: string } = {\n ...(prevVenues ?? {}),\n };\n if (next.bestBidVenue != null) mergedVenues.bestBidVenue = next.bestBidVenue;\n if (next.bestAskVenue != null) mergedVenues.bestAskVenue = next.bestAskVenue;\n if (mergedVenues.bestBidVenue || mergedVenues.bestAskVenue) {\n venuesByOutcome.set(outcomeId, mergedVenues);\n }\n };\n\n // Pass 1 — own per-outcome best prices, tagged with the row's venue.\n for (const item of data) {\n const venue = item.venue ?? null;\n for (const o of item.outcomes ?? []) {\n if (o.bestBid != null || o.bestAsk != null) {\n setEntry(o.venueMarketOutcomeId, {\n bestBid: o.bestBid,\n bestAsk: o.bestAsk,\n bestBidVenue: o.bestBid != null ? venue : null,\n bestAskVenue: o.bestAsk != null ? venue : null,\n });\n }\n }\n }\n\n // Pass 2 — matched-only outcomes (no top-level row of their own).\n for (const item of data) {\n for (const m of item.matched ?? []) {\n const venue = m.venue ?? null;\n for (const o of m.outcomes ?? []) {\n if (bestPrices.has(o.venueMarketOutcomeId)) continue;\n if (o.bestBid != null || o.bestAsk != null) {\n setEntry(o.venueMarketOutcomeId, {\n bestBid: o.bestBid,\n bestAsk: o.bestAsk,\n bestBidVenue: o.bestBid != null ? venue : null,\n bestAskVenue: o.bestAsk != null ? venue : null,\n });\n }\n }\n }\n }\n\n // Pass 3 — cross-venue best per logical outcome via MVMO refs on the parent\n // markets. Lowest bestAsk wins (cheapest place to buy that semantic side);\n // highest bestBid wins (best place to sell). Apply the chosen best to every\n // outcome ID in the MVMO group along with the venue that produced it so any\n // display surface that looks up either the primary or the matched outcome\n // ID gets the same trusted price *and* the matching venue logo.\n if (venueMarkets?.length) {\n for (const market of venueMarkets) {\n for (const outcome of market.venueMarketOutcomes ?? []) {\n const refs = outcome.matchedVenueMarketOutcomes ?? [];\n if (!refs.length) continue;\n\n const group = [outcome.id, ...refs.map((ref) => ref.venueMarketOutcomeId)];\n let bestAsk: number | undefined;\n let bestBid: number | undefined;\n let bestAskVenue: string | undefined;\n let bestBidVenue: string | undefined;\n for (const id of group) {\n const entry = bestPrices.get(id);\n const venues = venuesByOutcome.get(id);\n if (!entry) continue;\n if (entry.bestAsk != null && (bestAsk == null || entry.bestAsk < bestAsk)) {\n bestAsk = entry.bestAsk;\n bestAskVenue = venues?.bestAskVenue ?? bestAskVenue;\n }\n if (entry.bestBid != null && (bestBid == null || entry.bestBid > bestBid)) {\n bestBid = entry.bestBid;\n bestBidVenue = venues?.bestBidVenue ?? bestBidVenue;\n }\n }\n if (bestAsk == null && bestBid == null) continue;\n for (const id of group) {\n setEntry(id, {\n bestBid,\n bestAsk,\n bestBidVenue,\n bestAskVenue,\n });\n }\n }\n }\n }\n\n return { bestPrices, bestPriceVenuesByOutcomeId: venuesByOutcome };\n};\n\n/**\n * Fetches live midpoints for the given venue markets.\n *\n * Returns { prices, isLoading } so callers can show a skeleton while loading.\n *\n * Cross-venue best-price selection walks each parent outcome's\n * `matchedVenueMarketOutcomes` (MVMO references) and looks up the matched\n * counterpart's per-outcome midpoint in `matched[].outcomes`. The lowest\n * midpoint wins per outcome — semantically correct for both Yes and No\n * sides because MVMO links same-side counterparts regardless of label\n * inversion. No label heuristics; no `1 - midpoint` flips.\n */\nexport function useMidpoints(\n venueMarkets: VenueMarket[] | null | undefined,\n options?: UseMidpointsOptions,\n): UseMidpointsResult {\n const client = useAggClient();\n const {\n market: { maxMidpointIdsPerRequest: configuredMaxMidpointIdsPerRequest },\n } = useAggUiConfig();\n const maxMidpointIdsPerRequest =\n options?.maxMidpointIdsPerRequest ?? configuredMaxMidpointIdsPerRequest;\n\n const ids = useMemo(() => normalizeVenueMarketIds(venueMarkets), [venueMarkets]);\n const bestMidpointCandidateOutcomeIds = useMemo(\n () => resolveBestMidpointCandidateOutcomeIds(venueMarkets),\n [venueMarkets],\n );\n\n const primaryVenueMarketIds = useMemo(\n () => (venueMarkets ?? []).map((market) => market.id).filter(Boolean),\n [venueMarkets],\n );\n\n const { data, isLoading } = useQuery({\n queryKey: [\"midpoints\", ids, maxMidpointIdsPerRequest],\n queryFn: () => client.getMidpoints(ids, { bestPrice: true, maxMidpointIdsPerRequest }),\n enabled: ids.length > 0,\n // Complete responses stay cached for the session (unchanged behavior).\n // Incomplete ones are stale, so a remount refetches them and a short,\n // bounded poll picks up prices once a cold venue book warms.\n staleTime: (query) =>\n isMidpointResponseComplete(query.state.data, primaryVenueMarketIds) ? Infinity : 0,\n refetchInterval: (query) =>\n !isMidpointResponseComplete(query.state.data, primaryVenueMarketIds) &&\n query.state.dataUpdateCount < EMPTY_MIDPOINTS_MAX_FETCHES\n ? EMPTY_MIDPOINTS_POLL_MS\n : false,\n gcTime: 30 * 60_000,\n refetchOnMount: true,\n refetchOnWindowFocus: false,\n refetchOnReconnect: false,\n });\n\n const result = useMemo(() => {\n const map = new Map<string, number>();\n const currentMap = new Map<string, number>();\n const venueMap = new Map<string, string>();\n if (!data?.data || !venueMarkets) return { map, currentMap, venueMap };\n\n const itemByMarketId = new Map(data.data.map((item) => [item.venueMarketId, item]));\n const marketById = new Map(venueMarkets.map((market) => [market.id, market]));\n\n // Pass 1 — own per-outcome midpoints. Always prefer these over the\n // legacy market-level midpoint; the engine's per-outcome data sidesteps\n // any primary-outcome inversion.\n for (const item of data.data) {\n if (!item.outcomes?.length) continue;\n for (const o of item.outcomes) {\n if (o.midpoint == null) continue;\n map.set(o.venueMarketOutcomeId, o.midpoint);\n currentMap.set(o.venueMarketOutcomeId, o.midpoint);\n if (item.venue) venueMap.set(o.venueMarketOutcomeId, item.venue);\n }\n }\n\n // Pass 2 — cross-venue best-price per outcome via MVMO references on\n // the parent outcome. Lowest midpoint wins (cheapest place to buy\n // that semantic side). For sparse related markets that arrive without\n // MVMO refs, fall back to same-side sibling matching within the already\n // fetched matched rows so the UI can render a price instead of \"-\".\n for (const market of venueMarkets) {\n const item = itemByMarketId.get(market.id);\n if (!item) continue;\n for (const outcome of market.venueMarketOutcomes) {\n const refs = outcome.matchedVenueMarketOutcomes ?? [];\n let best: number | null = map.get(outcome.id) ?? null;\n let bestVenue: string | null = item.venue ?? null;\n if (refs.length > 0) {\n for (const ref of refs) {\n const sib = resolveSiblingOutcomeMidpoint(item.matched, ref);\n if (sib == null) continue;\n currentMap.set(ref.venueMarketOutcomeId, sib.midpoint);\n if (best == null || sib.midpoint < best) {\n best = sib.midpoint;\n bestVenue = sib.venue ?? bestVenue;\n }\n }\n } else if (best == null) {\n const fallback = resolveSemanticFallbackMidpoint({\n marketById,\n outcome,\n matched: item.matched,\n });\n if (fallback != null) {\n best = fallback.midpoint;\n bestVenue = fallback.venue ?? bestVenue;\n }\n }\n if (best != null) {\n map.set(outcome.id, best);\n if (bestVenue) venueMap.set(outcome.id, bestVenue);\n }\n }\n }\n\n return { map, currentMap, venueMap };\n }, [data, venueMarkets]);\n\n const { bestMidpoint, bestMidpointVenue } = useMemo(() => {\n // Walk the preferred (Yes-side) candidates first so the winning venue is\n // paired with the same outcome whose midpoint we expose as `bestMidpoint`.\n // Falling back to the full map keeps parity with the legacy behavior when\n // no candidate produced a price.\n let value: number | undefined;\n let venue: string | undefined;\n\n for (const outcomeId of bestMidpointCandidateOutcomeIds) {\n const midpoint = result.map.get(outcomeId);\n if (midpoint == null) continue;\n if (value == null || midpoint < value) {\n value = midpoint;\n venue = result.venueMap.get(outcomeId);\n }\n }\n\n if (value == null) {\n for (const [outcomeId, midpoint] of result.map) {\n if (value == null || midpoint < value) {\n value = midpoint;\n venue = result.venueMap.get(outcomeId);\n }\n }\n }\n\n return { bestMidpoint: value, bestMidpointVenue: venue };\n }, [bestMidpointCandidateOutcomeIds, result.map, result.venueMap]);\n\n const { bestPrices, bestPriceVenuesByOutcomeId } = useMemo(\n () => extractBestPrices(data?.data, venueMarkets),\n [data?.data, venueMarkets],\n );\n\n return {\n prices: result.map,\n bestMidpointsByOutcomeId: result.map,\n currentMidpointsByOutcomeId: result.currentMap,\n venueByOutcomeId: result.venueMap,\n bestPrices,\n bestPriceVenuesByOutcomeId,\n isLoading: isLoading && ids.length > 0,\n bestMidpoint,\n bestMidpointVenue,\n };\n}\n","import type { WsCandleInterval } from \"@agg-build/sdk\";\nimport { useEffect, useMemo, useState } from \"react\";\nimport type { ChartTimeRange } from \"./core/ui-config/types\";\nimport { getIntervalSeconds } from \"./market-data/chart-cache\";\nimport { timeRangeToInterval } from \"./use-live-candle-overlay\";\n\nexport interface UseRollingChartWindowOptions {\n range: ChartTimeRange;\n /**\n * Override the WS candle interval. Defaults to the canonical mapping from\n * `timeRangeToInterval`. Tests use this to inject a deterministic value.\n */\n interval?: WsCandleInterval;\n /**\n * Tick cadence for `nowSec`, in milliseconds. Defaults to 1s. The query\n * boundary (`endTs`) is bucketized so React Query only refetches when the\n * candle bucket advances, not on every tick.\n */\n tickMs?: number;\n /**\n * Read of `Date.now()` (ms). Overridable for tests.\n */\n nowMs?: () => number;\n}\n\nexport interface RollingChartWindow {\n range: ChartTimeRange;\n interval: WsCandleInterval;\n /** Width of the visible/rolling domain in seconds. */\n rangeSeconds: number;\n /** Width of one closed bar in seconds. */\n intervalSeconds: number;\n /**\n * Current wall-clock seconds, updated on every tick. The visible domain is\n * always `[nowSec - rangeSeconds, nowSec]` — use this for filtering points\n * to the rolling window.\n */\n nowSec: number;\n /**\n * Bucketized end of the rolling window. Snaps to the next interval\n * boundary so the React Query key (and therefore REST refetch) only\n * advances when a new candle bucket starts. Use this as `endTs` for the\n * REST query.\n */\n endTs: number;\n /**\n * Bucketized start: `endTs - rangeSeconds`. Use as `startTs` for the\n * REST query.\n */\n startTs: number;\n /**\n * Refetch interval to pass to React Query, in milliseconds. Matches one\n * candle bucket so historical bars roll in cleanly even without WS.\n */\n refetchIntervalMs: number;\n}\n\nconst RANGE_SECONDS_BY_RANGE: Record<ChartTimeRange, number> = {\n \"1H\": 60 * 60,\n \"6H\": 6 * 60 * 60,\n \"1D\": 24 * 60 * 60,\n \"1W\": 7 * 24 * 60 * 60,\n \"1M\": 30 * 24 * 60 * 60,\n ALL: 6 * 30 * 24 * 60 * 60,\n};\n\nexport const rangeToSeconds = (range: ChartTimeRange): number => RANGE_SECONDS_BY_RANGE[range];\n\n/**\n * Pure resolver for the rolling window, factored out of `useRollingChartWindow`\n * so the time-math can be unit-tested without rendering React.\n *\n * Invariants:\n * - `nowSec - rangeSeconds === domainStartTs` (the visible domain is\n * always exactly `rangeSeconds` wide regardless of how long mounted).\n * - `endTs - startTs === rangeSeconds` (the bucketized query window is\n * also exactly `rangeSeconds` wide; only the alignment to bucket\n * boundaries differs from the visible domain).\n * - `endTs % intervalSeconds === 0` (snaps to next bucket boundary so\n * the React Query key stays stable between bucket rollovers).\n */\nexport const resolveRollingWindow = (params: {\n range: ChartTimeRange;\n nowSec: number;\n interval?: WsCandleInterval;\n}): RollingChartWindow => {\n const interval = params.interval ?? timeRangeToInterval(params.range);\n const intervalSeconds = getIntervalSeconds(interval);\n const rangeSeconds = rangeToSeconds(params.range);\n const endTs = Math.ceil(params.nowSec / intervalSeconds) * intervalSeconds;\n return {\n range: params.range,\n interval,\n rangeSeconds,\n intervalSeconds,\n nowSec: params.nowSec,\n endTs,\n startTs: endTs - rangeSeconds,\n refetchIntervalMs: intervalSeconds * 1000,\n };\n};\n\n/**\n * Drives a rolling time domain `[nowSec - rangeSeconds, nowSec]` that ticks\n * while the chart is mounted.\n *\n * Why two timestamps (`nowSec` vs `endTs`):\n * - `nowSec` updates every `tickMs` (default 1s) so the visible domain\n * stays exactly `rangeSeconds` wide. Series points outside that domain\n * should be filtered out by the caller.\n * - `endTs` is bucketized to the next interval boundary so React Query's\n * key only changes when a new candle bucket actually starts. Without\n * this, the chart would refetch every tick.\n *\n * The bucket advance is also what drives REST refetches that backfill any\n * closed bars the WebSocket missed. WS updates feed the in-flight candle\n * and promote it on rollover (see `chart-cache.applyMidpointToMarketChart`);\n * the REST refetch only matters when WS is disconnected or quiet.\n */\nexport const useRollingChartWindow = (\n options: UseRollingChartWindowOptions,\n): RollingChartWindow => {\n const tickMs = options.tickMs ?? 1000;\n // Stabilize the `nowMs` reader. Inline fallbacks (`?? (() => Date.now())`)\n // create a fresh function on every render, which would invalidate the\n // useEffect deps and tear down/re-create the interval continuously.\n const optionsNowMs = options.nowMs;\n const nowMs = useMemo(() => optionsNowMs ?? (() => Date.now()), [optionsNowMs]);\n\n const [nowSec, setNowSec] = useState<number>(() => Math.floor(nowMs() / 1000));\n\n useEffect(() => {\n setNowSec(Math.floor(nowMs() / 1000));\n const handle = setInterval(() => {\n setNowSec(Math.floor(nowMs() / 1000));\n }, tickMs);\n return () => clearInterval(handle);\n }, [tickMs, nowMs]);\n\n return useMemo<RollingChartWindow>(\n () => resolveRollingWindow({ range: options.range, nowSec, interval: options.interval }),\n [options.range, options.interval, nowSec],\n );\n};\n","import { useEffect, useRef, useState } from \"react\";\nimport type { WsArbFeedBatch, WsArbMarketUpdate } from \"@agg-build/sdk\";\nimport { useAggWebSocket } from \"./core/providers/ws-provider\";\n\n// ── Types ──────────────────────────────────────────────────────────────────────\n\nexport interface UseMarketArbResult {\n /** Live arbReturn for the market, or null if no data received yet. */\n arbReturn: number | null;\n /** True once at least one live update (or a cached seed) has been received. */\n isLive: boolean;\n}\n\nexport interface UseArbFeedResult {\n /**\n * Live arbReturn keyed by marketId.\n * Values are the most-recently received arbReturn for each market.\n */\n byMarket: Map<string, number>;\n /**\n * MAX arbReturn keyed by venueEventId.\n * Derived from byMarket by scanning all markets that share a venueEventId and\n * taking the maximum. Rebuilt fully on every batch so it is correct even when\n * a market's arb DROPS between batches.\n */\n byEvent: Map<string, number>;\n}\n\n// ── Internal state shapes ──────────────────────────────────────────────────────\n\ninterface MarketArbState {\n arbReturn: number | null;\n isLive: boolean;\n}\n\n/** Internal: stores arb + its venueEventId together so byEvent can be recomputed. */\ninterface ArbFeedState {\n byMarket: Map<string, { arb: number; eventId: string | null }>;\n byEvent: Map<string, number>;\n}\n\n// ── useMarketArb ───────────────────────────────────────────────────────────────\n\n/**\n * Subscribe to real-time arbReturn updates for a single market.\n *\n * Seeds initial state from the WS cache (`ws.getArb`) if available, then\n * streams live updates via `ws.subscribeArb`. Unsubscribes on unmount or when\n * `marketId` changes.\n *\n * Returns `{ arbReturn: number | null; isLive: boolean }`.\n * `isLive` is true once at least one value (cached or live) is received.\n */\nexport function useMarketArb(marketId: string | null): UseMarketArbResult {\n const ws = useAggWebSocket();\n const [state, setState] = useState<MarketArbState>({ arbReturn: null, isLive: false });\n\n useEffect(() => {\n if (!ws || !marketId) return;\n\n // Seed from cache immediately if available.\n const cached = ws.getArb(marketId);\n if (cached != null) {\n setState({ arbReturn: cached.arbReturn, isLive: true });\n }\n\n const off = ws.subscribeArb(marketId, (msg: WsArbMarketUpdate) => {\n setState({ arbReturn: msg.arbReturn, isLive: true });\n });\n\n return off;\n }, [ws, marketId]);\n\n return state;\n}\n\n// ── useArbFeed ─────────────────────────────────────────────────────────────────\n\nconst EMPTY_ARB_FEED: ArbFeedState = {\n byMarket: new Map(),\n byEvent: new Map(),\n};\n\n/**\n * Subscribe to the coalesced arb-return feed.\n *\n * Maintains a `byMarket` map (marketId → arbReturn) and derives a `byEvent`\n * map (venueEventId → max arbReturn across all markets in that event).\n *\n * `byEvent` is ALWAYS fully rebuilt from `byMarket` on each batch so that\n * dropping arb values (e.g. m2 goes from 0.30 → 0.02) are reflected correctly\n * — there is no stale running-max accumulation.\n *\n * Returns `{ byMarket: Map<string, number>; byEvent: Map<string, number> }`.\n */\nexport function useArbFeed(): UseArbFeedResult {\n const ws = useAggWebSocket();\n const [state, setState] = useState<ArbFeedState>(EMPTY_ARB_FEED);\n // Keep a stable ref to state for the subscription callback closure.\n // This avoids stale-closure issues without listing state in deps.\n const stateRef = useRef<ArbFeedState>(state);\n stateRef.current = state;\n\n useEffect(() => {\n if (!ws) return;\n\n const off = ws.subscribeArbFeed((batch: WsArbFeedBatch) => {\n setState((prev) => {\n // Merge incoming entries into a new byMarket.\n const nextByMarket = new Map(prev.byMarket);\n for (const entry of batch.entries) {\n nextByMarket.set(entry.marketId, {\n arb: entry.arbReturn,\n eventId: entry.venueEventId,\n });\n }\n\n // Fully rebuild byEvent from nextByMarket so that value drops are correct.\n const nextByEvent = new Map<string, number>();\n for (const { arb, eventId } of nextByMarket.values()) {\n if (eventId == null) continue;\n const current = nextByEvent.get(eventId);\n if (current == null || arb > current) {\n nextByEvent.set(eventId, arb);\n }\n }\n\n return { byMarket: nextByMarket, byEvent: nextByEvent };\n });\n });\n\n return off;\n }, [ws]);\n\n // Project the internal state shape (which stores eventId alongside arb) to\n // the public shape (byMarket: Map<marketId, number>).\n const publicByMarket = new Map<string, number>();\n for (const [marketId, { arb }] of state.byMarket) {\n publicByMarket.set(marketId, arb);\n }\n\n return { byMarket: publicByMarket, byEvent: state.byEvent };\n}\n","import type {\n Orderbook,\n VenueMarketOutcome,\n VenueMarket,\n AggClient,\n AggregatedOrderbookResponse,\n} from \"@agg-build/sdk\";\nimport { keepPreviousData, useQuery } from \"@tanstack/react-query\";\nimport { useAggClient } from \"./core/provider\";\nimport { marketOrderbookDataToResponse } from \"./market-data/orderbook-cache\";\nimport { useMarketOrderbook } from \"./use-market-orderbook\";\n\nexport interface OrderbookResult {\n market: VenueMarket;\n outcome: VenueMarketOutcome;\n orderbook: Orderbook;\n}\n\nexport interface UseOrderBookOptions {\n orderbooks: {\n market: VenueMarket;\n outcome: VenueMarketOutcome;\n }[];\n enabled?: boolean;\n canonicalMarketId?: string | null;\n}\n\n// Cached query functions must not share the render context containing canonicalResult's deep book.\nconst fetchBatchBookQuery = (\n client: AggClient,\n venueMarketIds: string[],\n { signal }: { signal: AbortSignal },\n) => client.getOrderbooks({ venueMarketIds }, { signal });\nconst createBatchBookQuery = (client: AggClient, venueMarketIds: string[]) =>\n fetchBatchBookQuery.bind(null, client, venueMarketIds);\n\nexport function useOrderBook(options: UseOrderBookOptions) {\n const client = useAggClient();\n const { orderbooks, enabled = true, canonicalMarketId } = options;\n const requestedVenueMarketIds = [...new Set(orderbooks.map(({ market }) => market.id))];\n\n const canonicalResult = useMarketOrderbook({\n marketId: canonicalMarketId ?? null,\n enabled: enabled && !!canonicalMarketId && orderbooks.length > 0,\n venueOutcomes: canonicalMarketId\n ? orderbooks.map(({ market, outcome }) => ({\n venue: market.venue,\n venueMarketOutcomeId: outcome.id,\n }))\n : undefined,\n });\n\n const batchedResult = useQuery({\n queryKey: requestedVenueMarketIds.length\n ? ([\"orderbooks\", requestedVenueMarketIds, null] as const)\n : ([\"orderbooks\", \"__disabled__\", null] as const),\n queryFn: createBatchBookQuery(client, requestedVenueMarketIds),\n enabled: enabled && !canonicalMarketId && requestedVenueMarketIds.length > 0,\n staleTime: 10_000,\n gcTime: 5 * 60_000,\n refetchOnWindowFocus: false,\n retry: 1,\n placeholderData: keepPreviousData,\n });\n\n const data: OrderbookResult[] | undefined = (() => {\n if (canonicalMarketId) {\n const canonicalData = canonicalResult.data;\n if (!canonicalData) return undefined;\n\n const merged = orderbooks.flatMap(({ market, outcome }) => {\n const venueBook = canonicalData.venueOrderbooks[market.venue];\n if (!venueBook) return [];\n\n return [\n {\n market,\n outcome,\n orderbook: {\n bids: venueBook.bids,\n asks: venueBook.asks,\n },\n },\n ];\n });\n\n return merged.length === orderbooks.length ? merged : undefined;\n }\n\n const liveBooksByMarketId = new Map(\n (batchedResult.data?.data ?? [])\n .filter((item) => item.status === \"ok\")\n .map((item) => [item.venueMarketId, item]),\n );\n\n const merged = orderbooks.flatMap(({ market, outcome }, index) => {\n void index;\n const item = liveBooksByMarketId.get(market.id);\n const orderbook = item?.venueOrderbooks[market.venue]?.orderbook as Orderbook | undefined;\n if (!orderbook) return [];\n\n return [\n {\n market,\n outcome,\n orderbook,\n },\n ];\n });\n\n return merged.length === orderbooks.length ? merged : undefined;\n })();\n\n const aggregated: AggregatedOrderbookResponse | null = canonicalResult.data\n ? marketOrderbookDataToResponse(canonicalResult.data)\n : null;\n const error = canonicalMarketId ? canonicalResult.error : batchedResult.error;\n\n return {\n data,\n isLoading: canonicalMarketId ? canonicalResult.isLoading : batchedResult.isLoading,\n error: error instanceof Error ? error : error ? new Error(String(error)) : null,\n results: [batchedResult],\n aggregated,\n isLive: canonicalResult.isLive,\n };\n}\n","import type { OrderbookQuoteResponse } from \"@agg-build/sdk\";\nimport { keepPreviousData, useQuery } from \"@tanstack/react-query\";\nimport { useAggClient } from \"./core/provider\";\nimport { createMarketOrderbookDataFromVenueOrderbooks } from \"./market-data/orderbook-cache\";\nimport { marketDataKeys } from \"./market-data/query-keys\";\nimport { useDebouncedValue } from \"./use-debounced-value\";\n\nexport interface UseOrderbookQuoteOptions {\n marketId: string | null;\n side: \"buy\" | \"sell\";\n size: number;\n enabled?: boolean;\n}\n\nexport interface UseOrderbookQuoteResult {\n data: OrderbookQuoteResponse | null;\n isLoading: boolean;\n isFetching: boolean;\n error: Error | null;\n}\n\nconst QUOTE_DEBOUNCE_MS = 300;\n\nconst createUnavailableOrderbookError = (message: string, code?: string, retryable?: boolean) => {\n const error = new Error(message) as Error & {\n status: number;\n code?: string;\n retryable?: boolean;\n };\n error.status = 404;\n if (code) error.code = code;\n if (retryable !== undefined) error.retryable = retryable;\n return error;\n};\n\nconst quoteVenueOrderbooks = ({\n marketId,\n side,\n requestedSize,\n venueOrderbooks,\n}: {\n marketId: string;\n side: \"buy\" | \"sell\";\n requestedSize: number;\n venueOrderbooks: Record<\n string,\n { bids: Array<{ price: number; size: number }>; asks: Array<{ price: number; size: number }> }\n >;\n}): OrderbookQuoteResponse => {\n const marketData = createMarketOrderbookDataFromVenueOrderbooks({\n marketId,\n venueOrderbooks,\n });\n const levels = side === \"buy\" ? marketData.orderbook.asks : marketData.orderbook.bids;\n\n let remaining = requestedSize;\n const fillsByVenue = new Map<string, { size: number; cost: number }>();\n\n for (const level of levels) {\n if (remaining <= 0) break;\n\n for (const [venue, venueSize] of Object.entries(level.venues)) {\n if (remaining <= 0) break;\n\n const fillSize = Math.min(remaining, venueSize);\n const fillCost = fillSize * level.price;\n remaining -= fillSize;\n\n const existing = fillsByVenue.get(venue) ?? { size: 0, cost: 0 };\n existing.size += fillSize;\n existing.cost += fillCost;\n fillsByVenue.set(venue, existing);\n }\n }\n\n const filledSize = requestedSize - Math.max(0, remaining);\n const totalCost = [...fillsByVenue.values()].reduce((sum, fill) => sum + fill.cost, 0);\n const avgPrice = filledSize > 0 ? totalCost / filledSize : null;\n const slippage =\n avgPrice !== null && marketData.midpoint !== null\n ? side === \"buy\"\n ? avgPrice - marketData.midpoint\n : marketData.midpoint - avgPrice\n : null;\n\n return {\n marketId,\n side,\n requestedSize,\n filledSize,\n avgPrice,\n totalCost,\n slippage,\n fills: [...fillsByVenue.entries()].map(([venue, fill]) => ({\n venue,\n size: fill.size,\n avgPrice: fill.size > 0 ? fill.cost / fill.size : 0,\n cost: fill.cost,\n })),\n };\n};\n\nexport function useOrderbookQuote(options: UseOrderbookQuoteOptions): UseOrderbookQuoteResult {\n const client = useAggClient();\n const { marketId, side, size, enabled = true } = options;\n const debouncedSize = useDebouncedValue(size, QUOTE_DEBOUNCE_MS);\n const shouldFetch = enabled && !!marketId && debouncedSize > 0;\n\n const query = useQuery({\n queryKey: marketId\n ? marketDataKeys.orderbookQuote(marketId, side, debouncedSize)\n : ([\"market-data\", \"orderbook-quote\", \"__disabled__\"] as const),\n queryFn: async () => {\n const response = await client.getOrderbooks({\n venueMarketIds: [marketId!],\n });\n\n const item = response.data.find((entry) => entry.venueMarketId === marketId!);\n if (!item) {\n throw createUnavailableOrderbookError(`No orderbook payload returned for ${marketId!}.`);\n }\n\n if (item.status !== \"ok\") {\n throw createUnavailableOrderbookError(\n item.error?.message ?? `No live orderbook is available for ${marketId!}.`,\n item.error?.code,\n item.error?.retryable,\n );\n }\n\n return quoteVenueOrderbooks({\n marketId: marketId!,\n side,\n requestedSize: debouncedSize,\n venueOrderbooks: Object.fromEntries(\n Object.entries(item.venueOrderbooks).map(([venue, entry]) => [venue, entry.orderbook]),\n ),\n });\n },\n enabled: shouldFetch && debouncedSize > 0,\n staleTime: 10_000,\n gcTime: 5 * 60_000,\n retry: 1,\n placeholderData: keepPreviousData,\n });\n\n return {\n data: query.data ?? null,\n isLoading: query.isLoading,\n isFetching: query.isFetching,\n error:\n query.error instanceof Error\n ? query.error\n : query.error\n ? new Error(String(query.error))\n : null,\n };\n}\n","import { useQuery } from \"@tanstack/react-query\";\nimport type { OrderListQuery, TradeExecutorOrder } from \"@agg-build/sdk\";\nimport { useAggClient } from \"./core/provider\";\n\nexport interface UseOrdersOptions extends OrderListQuery {\n enabled?: boolean;\n}\n\nexport function useOrders(options: UseOrdersOptions = {}) {\n const client = useAggClient();\n const { userId, status, limit = 50, offset = 0, enabled = true } = options;\n\n const query = useQuery({\n queryKey: [\"orders\", userId ?? \"me\", status ?? \"all\", limit, offset],\n queryFn: () =>\n client.getOrders({\n userId,\n status,\n limit,\n offset,\n }),\n enabled,\n });\n\n return {\n ...query,\n orders: (query.data?.orders ?? []) as TradeExecutorOrder[],\n total: query.data?.total ?? 0,\n };\n}\n","import type { MarketStatus, VenueEvent } from \"@agg-build/sdk\";\nimport {\n QueryClient,\n QueryClientContext,\n keepPreviousData,\n useInfiniteQuery,\n} from \"@tanstack/react-query\";\nimport { useContext, useEffect, useState } from \"react\";\nimport { withReadRetry } from \"./read-retry\";\nimport { AggClientContext } from \"./core/providers/contexts\";\n\nexport interface UseSearchOptions {\n /** Search query string. The query is disabled when empty. */\n q: string;\n /** Search type: \"events\" or \"markets\". */\n type: \"events\" | \"markets\";\n /** Optional category ID filter. */\n categoryIds?: string[];\n /** Filter by status — pass [\"open\"] for tradeable-only results. */\n status?: MarketStatus[];\n /** Page size. Default 20. */\n limit?: number;\n /** If provided, enable/disable the query. Defaults to true. */\n enabled?: boolean;\n /**\n * Opt in to the server-side reranker for higher-quality top results.\n *\n * Recommended for the full search-results page (submit / Enter) and NOT\n * for debounced typeahead — the latter shouldn't pay reranker latency on\n * every keystroke. The flag is baked into the query cache key, so deep\n * and light variants of the same query never share results. Default false.\n */\n deep?: boolean;\n /** Indexed title/question suggestions; full remains the compatibility default. */\n mode?: \"instant\" | \"full\";\n}\n\n/**\n * Search events or markets via the /search endpoint with cursor-based pagination.\n * Uses `useInfiniteQuery` for \"Load more\" support. Disabled when `q` is empty.\n *\n * Pass a type parameter to narrow the result type, e.g.:\n * ```ts\n * const { data } = useSearch<VenueEventWithMarkets>({ q: \"...\", type: \"events\" });\n * ```\n *\n * For typeahead + full-results in one hook, prefer `useMarketSearch` — it\n * wires up the debounce, submit, and cancellation semantics out of the box.\n */\nexport function useSearch<T = VenueEvent>(options: UseSearchOptions) {\n const client = useContext(AggClientContext);\n const queryClient = useContext(QueryClientContext);\n const [fallbackQueryClient] = useState(() => new QueryClient());\n const {\n q,\n type,\n categoryIds,\n status,\n limit = 20,\n enabled = true,\n deep = false,\n mode = \"full\",\n } = options;\n const isEnabled = enabled && q.length > 0;\n\n useEffect(() => {\n if (queryClient) return undefined;\n\n fallbackQueryClient.mount();\n return () => {\n fallbackQueryClient.unmount();\n };\n }, [fallbackQueryClient, queryClient]);\n\n if (isEnabled && !client) {\n throw new Error(\"useSearch must be used within an <AggProvider>\");\n }\n\n const queryKey = [\n \"search\",\n q,\n type,\n categoryIds?.join(\",\") ?? \"\",\n status?.join(\",\") ?? \"\",\n limit,\n deep,\n mode,\n ];\n const effectiveQueryClient = queryClient ?? fallbackQueryClient;\n const retryOptions = withReadRetry(effectiveQueryClient.defaultQueryOptions({ queryKey }));\n\n const query = useInfiniteQuery(\n {\n // deep is part of the key — TanStack treats deep vs light as\n // independent queries so users can have both modes cached side-by-side.\n queryKey,\n queryFn: async ({ pageParam, signal }) => {\n if (!client) {\n throw new Error(\"useSearch must be used within an <AggProvider>\");\n }\n\n const res = await client.search<T>(\n {\n q,\n type,\n categoryIds,\n status,\n limit,\n cursor: pageParam as string | undefined,\n deep,\n mode,\n },\n { signal },\n );\n return res;\n },\n initialPageParam: undefined as string | undefined,\n getNextPageParam: (lastPage) => {\n if (!lastPage.hasMore) return undefined;\n return lastPage.nextCursor ?? undefined;\n },\n placeholderData: keepPreviousData,\n ...retryOptions,\n enabled: isEnabled && !!client,\n },\n effectiveQueryClient,\n );\n\n const data: T[] = query.data?.pages.flatMap((page) => page.data) ?? [];\n\n return {\n data,\n isLoading: query.isLoading,\n isError: query.isError,\n error: query.error,\n hasNextPage: !!query.hasNextPage,\n fetchNextPage: query.fetchNextPage,\n isFetchingNextPage: query.isFetchingNextPage,\n isPlaceholderData: query.isPlaceholderData,\n };\n}\n","import type { MarketStatus, VenueEvent } from \"@agg-build/sdk\";\nimport { useCallback, useState } from \"react\";\nimport { useDebouncedValue } from \"./use-debounced-value\";\nimport { useSearch } from \"./use-search\";\n\nexport interface UseMarketSearchOptions {\n /** Search type: \"events\" or \"markets\". */\n type: \"events\" | \"markets\";\n /** Optional category ID filter. */\n categoryIds?: string[];\n /** Filter by status — pass [\"open\"] for tradeable-only results. */\n status?: MarketStatus[];\n /** Page size for both modes. Default 20. */\n limit?: number;\n /**\n * Debounce delay applied to the typeahead/light query, in ms. The submit\n * path bypasses debounce entirely. Default 200.\n */\n debounceMs?: number;\n /**\n * Set to `false` to disable the typeahead/light query (no /search call\n * while the user types). The submit path still fires full searches.\n * Default true.\n */\n enableSuggestions?: boolean;\n /**\n * Minimum query length before the typeahead fires. Default 1 — set higher\n * (e.g. 3) if `/search` cost per keystroke is a concern. The submit path\n * ignores this threshold.\n */\n minLength?: number;\n}\n\n/**\n * Combined typeahead + submit hook for the canonical search UX.\n *\n * ┌─────────────────────────────┐\n * │ user types \"tru\" │ → debounced light /search → suggestions[]\n * │ user types \"trum\" │ → debounced light /search → suggestions[]\n * │ user presses Enter │ → deep /search → results[]\n * └─────────────────────────────┘\n *\n * Typeahead (`suggestions`) and submit-results (`results`) are cached under\n * separate TanStack Query keys, so navigating away and back doesn't lose\n * either. Server-side the same separation holds: the `deep` flag is part of\n * the cache key, so the two modes never collide.\n *\n * ```tsx\n * const { query, setQuery, submit, suggestions, results } = useMarketSearch({\n * type: \"markets\",\n * });\n *\n * <input\n * value={query}\n * onChange={(e) => setQuery(e.target.value)}\n * onKeyDown={(e) => { if (e.key === \"Enter\") submit(); }}\n * />\n * {suggestions.data.map(...)} // dropdown\n * {results.data.map(...)} // full page after Enter\n * ```\n */\nexport function useMarketSearch<T = VenueEvent>(options: UseMarketSearchOptions) {\n const {\n type,\n categoryIds,\n status,\n limit = 20,\n debounceMs = 200,\n enableSuggestions = true,\n minLength = 1,\n } = options;\n\n // Input value the user is currently typing. The component owns the\n // controlled <input> via setQuery; the hook owns the debounced + submitted\n // derivations.\n const [query, setQueryState] = useState(\"\");\n // Snapshot of the query at the moment `submit()` was called. Driving the\n // full search off a separate state value means typing more after submitting\n // doesn't blow away the results until the next submit.\n const [submittedQuery, setSubmittedQuery] = useState<string | null>(null);\n\n const debouncedQuery = useDebouncedValue(query, debounceMs);\n const trimmedDebounced = debouncedQuery.trim();\n const suggestionsEnabled = enableSuggestions && trimmedDebounced.length >= minLength;\n\n // Light: typeahead. Fires after debounceMs of input stability.\n const suggestionsQuery = useSearch<T>({\n q: trimmedDebounced,\n type,\n categoryIds,\n status,\n limit,\n enabled: suggestionsEnabled,\n mode: \"instant\",\n });\n\n // Full results. Fires on submit and stays mounted across subsequent\n // typing — the user can scroll the page-1 results while they refine the query.\n const submittedQ = submittedQuery?.trim() ?? \"\";\n const resultsQuery = useSearch<T>({\n q: submittedQ,\n type,\n categoryIds,\n status,\n limit,\n enabled: submittedQ.length > 0,\n });\n\n const setQuery = useCallback((value: string) => {\n setQueryState(value);\n }, []);\n\n /** Submit a query for a full-page search. Falls back to the current\n * input value if no argument is passed — matches the \"user presses Enter\n * in the input\" UX. Trims whitespace; empty strings are no-ops. */\n const submit = useCallback(\n (q?: string) => {\n const target = (q ?? query).trim();\n if (target.length === 0) return;\n setSubmittedQuery(target);\n },\n [query],\n );\n\n /** Reset both the input value and the submitted-search state. */\n const clear = useCallback(() => {\n setQueryState(\"\");\n setSubmittedQuery(null);\n }, []);\n\n return {\n /** Current input value (controlled). */\n query,\n /** Update the input value. Triggers the debounced typeahead. */\n setQuery,\n /** The query value that produced the current `results`, or null if none. */\n submittedQuery,\n /** Fire a full-page search. Use this on Enter / Search button. */\n submit,\n /** Reset both input and results state. */\n clear,\n /**\n * Typeahead state. Backed by a light /search call (no reranker).\n * `data` is paginated like `useSearch.data` (flattened across pages).\n */\n suggestions: {\n data: suggestionsQuery.data,\n isLoading: suggestionsQuery.isLoading,\n isError: suggestionsQuery.isError,\n error: suggestionsQuery.error,\n },\n /**\n * Full-page results state. Backed by a deep /search call (reranker on).\n * Cursor pagination is exposed via `fetchNextPage` / `hasNextPage`.\n */\n results: {\n data: resultsQuery.data,\n isLoading: resultsQuery.isLoading,\n isError: resultsQuery.isError,\n error: resultsQuery.error,\n hasNextPage: resultsQuery.hasNextPage,\n fetchNextPage: resultsQuery.fetchNextPage,\n isFetchingNextPage: resultsQuery.isFetchingNextPage,\n },\n };\n}\n","import type { SmartRouteResponse } from \"@agg-build/sdk\";\n\nexport const THIN_SMART_ROUTE_REFETCH_INTERVAL_MS = 5_000;\nexport const SMART_ROUTE_REFRESH_DEADLINE_BUFFER_MS = 4_000;\nexport const SMART_ROUTE_MIN_REFETCH_INTERVAL_MS = 5_000;\nexport const SMART_ROUTE_MAX_REFETCH_INTERVAL_MS = 20_000;\nexport const SMART_ROUTE_HIGH_SLIPPAGE_BPS = 75;\nexport const SMART_ROUTE_SHALLOW_TOP_LEVEL_RATIO = 0.7;\nexport const SMART_ROUTE_DEEP_FILL_LEVEL_COUNT = 3;\n\nconst LIQUIDITY_CONSTRAINED_STATUSES = new Set<SmartRouteResponse[\"status\"]>([\n \"infeasible\",\n \"no_orderbooks\",\n \"insufficient_depth\",\n \"no_bids_above_min_price\",\n]);\n\nconst THIN_LIQUIDITY_WARNING_PATTERN =\n /partial(?:[_\\s-]?fill)?|insufficient(?:[_\\s-]?liquidity|[_\\s-]?depth)|shallow|price moved|no active quote path|couldn'?t fill|unable to fill|quote stale|stale/i;\n\nexport type ThinSmartRouteLiquidityReason =\n | \"deep_fill_levels\"\n | \"high_slippage\"\n | \"liquidity_status\"\n | \"refresh_due_soon\"\n | \"shallow_top_level\"\n | \"warning_signal\";\n\nexport interface SmartRouteThinLiquidityAssessment {\n isThin: boolean;\n reasons: ThinSmartRouteLiquidityReason[];\n}\n\nexport interface ResolveSmartRouteRefetchIntervalArgs {\n data: SmartRouteResponse | null | undefined;\n defaultIntervalMs: number;\n aggressiveIntervalMs?: number;\n /** Keep sell fan-out on its normal cadence while honoring venue cooldowns. */\n adaptive?: boolean;\n isDocumentVisible: boolean;\n isEditing?: boolean;\n isInputValid: boolean;\n isMarketOpen: boolean;\n isPanelActive: boolean;\n isSubmitting: boolean;\n queryEnabled: boolean;\n}\n\nconst resolveMsUntilIsoTimestamp = (value: string | undefined, nowMs: number): number | null => {\n if (!value) return null;\n const parsedValue = Date.parse(value);\n if (!Number.isFinite(parsedValue)) return null;\n return parsedValue - nowMs;\n};\n\nconst clampIntervalToRefreshDeadline = ({\n intervalMs,\n refreshAt,\n nowMs,\n}: {\n intervalMs: number;\n refreshAt: string | undefined;\n nowMs: number;\n}): number => {\n const msUntilRefresh = resolveMsUntilIsoTimestamp(refreshAt, nowMs);\n if (msUntilRefresh == null || msUntilRefresh <= 0) {\n return Math.min(\n SMART_ROUTE_MAX_REFETCH_INTERVAL_MS,\n Math.max(SMART_ROUTE_MIN_REFETCH_INTERVAL_MS, intervalMs),\n );\n }\n\n return Math.max(\n SMART_ROUTE_MIN_REFETCH_INTERVAL_MS,\n Math.min(SMART_ROUTE_MAX_REFETCH_INTERVAL_MS, intervalMs, Math.floor(msUntilRefresh)),\n );\n};\n\nexport const assessThinSmartRouteLiquidity = (\n quote: SmartRouteResponse | null | undefined,\n nowMs = Date.now(),\n): SmartRouteThinLiquidityAssessment => {\n if (!quote) {\n return {\n isThin: false,\n reasons: [],\n };\n }\n\n const reasons = new Set<ThinSmartRouteLiquidityReason>();\n\n if (LIQUIDITY_CONSTRAINED_STATUSES.has(quote.status)) {\n reasons.add(\"liquidity_status\");\n }\n\n if (\n typeof quote.slippage?.slippageBps === \"number\" &&\n Number.isFinite(quote.slippage.slippageBps) &&\n quote.slippage.slippageBps >= SMART_ROUTE_HIGH_SLIPPAGE_BPS\n ) {\n reasons.add(\"high_slippage\");\n }\n\n const msUntilRefresh = resolveMsUntilIsoTimestamp(quote.refreshAt, nowMs);\n if (msUntilRefresh != null && msUntilRefresh <= SMART_ROUTE_REFRESH_DEADLINE_BUFFER_MS) {\n reasons.add(\"refresh_due_soon\");\n }\n\n const hasShallowTopLevel = quote.fills.some((fill) => {\n if (fill.fills.length <= 1 || fill.venueQty <= 0) return false;\n\n const topLevelSize = fill.fills[0]?.size ?? 0;\n if (!Number.isFinite(topLevelSize) || topLevelSize <= 0) return false;\n\n return topLevelSize / fill.venueQty < SMART_ROUTE_SHALLOW_TOP_LEVEL_RATIO;\n });\n if (hasShallowTopLevel) {\n reasons.add(\"shallow_top_level\");\n }\n\n const hasDeepFillLevels = quote.fills.some(\n (fill) => fill.fills.length >= SMART_ROUTE_DEEP_FILL_LEVEL_COUNT,\n );\n if (hasDeepFillLevels) {\n reasons.add(\"deep_fill_levels\");\n }\n\n const hasThinWarning = (quote.warnings ?? []).some((warning) =>\n THIN_LIQUIDITY_WARNING_PATTERN.test(warning.reason),\n );\n if (hasThinWarning) {\n reasons.add(\"warning_signal\");\n }\n\n return {\n isThin: reasons.size > 0,\n reasons: [...reasons],\n };\n};\n\nexport const resolveSmartRouteRefetchInterval = (\n args: ResolveSmartRouteRefetchIntervalArgs,\n nowMs = Date.now(),\n): number | false => {\n const {\n aggressiveIntervalMs = THIN_SMART_ROUTE_REFETCH_INTERVAL_MS,\n adaptive = true,\n data,\n defaultIntervalMs,\n isDocumentVisible,\n isEditing = false,\n isInputValid,\n isMarketOpen,\n isPanelActive,\n isSubmitting,\n queryEnabled,\n } = args;\n\n if (defaultIntervalMs <= 0) return false;\n\n const isActivelyViewingQuote = isPanelActive || isEditing;\n if (\n !queryEnabled ||\n !isInputValid ||\n !isActivelyViewingQuote ||\n !isMarketOpen ||\n isSubmitting ||\n !isDocumentVisible\n ) {\n return false;\n }\n\n const primaryUsesProphetx =\n data?.fills?.some((fill) => fill.venue === \"prophetx\") || data?.status !== \"ok\";\n const deadlines = [\n data?.quoteRefreshNotBefore,\n ...(primaryUsesProphetx ? [data?.quoteFailure?.retryAt] : []),\n ]\n .filter((value): value is string => !!value)\n .map(Date.parse)\n .filter((value) => Number.isFinite(value) && value > nowMs);\n if (deadlines.length) return Math.max(...deadlines) - nowMs;\n\n if (!adaptive)\n return clampIntervalToRefreshDeadline({\n intervalMs: defaultIntervalMs,\n refreshAt: undefined,\n nowMs,\n });\n\n const defaultInterval = clampIntervalToRefreshDeadline({\n intervalMs: defaultIntervalMs,\n refreshAt: data?.refreshAt,\n nowMs,\n });\n if (!data) return defaultInterval;\n\n const thinLiquidity = assessThinSmartRouteLiquidity(data, nowMs);\n if (!thinLiquidity.isThin) return defaultInterval;\n\n return clampIntervalToRefreshDeadline({\n intervalMs: aggressiveIntervalMs,\n refreshAt: data.refreshAt,\n nowMs,\n });\n};\n","import type { ExecutionMode, SmartRouteResponse, SmartRouteSide } from \"@agg-build/sdk\";\nimport { keepPreviousData, useQuery } from \"@tanstack/react-query\";\nimport { useAggClient } from \"./core/provider\";\nimport { resolveSmartRouteRefetchInterval } from \"./smart-route-refresh-policy\";\n\n/**\n * Smart-route quotes expire on the server after 45s. Refetch at 20s so a fresh\n * quote is always in hand by the time the user clicks the CTA.\n */\nexport const SMART_ROUTE_STALE_TIME_MS = 20_000;\n\nexport interface UseSmartRouteOptions {\n /** Venue market outcome ID used by the smart-route endpoint. */\n venueMarketOutcomeId?: string | null;\n /** @deprecated Use venueMarketOutcomeId. */\n venueMarketId?: string | null;\n /** @deprecated Use venueMarketOutcomeId. */\n outcomeId?: string | null;\n /** @deprecated Side is ignored for routing and echoed back only for legacy consumers. */\n side?: SmartRouteSide | null;\n /** Trade direction: \"buy\" (default) or \"sell\". */\n tradeSide?: \"buy\" | \"sell\" | null;\n /** Trading mode. Defaults to live. */\n mode?: ExecutionMode | null;\n /** Maximum USDC spend for the quote. Required for buy; optional for sell when sellShares is given. */\n maxSpend?: number;\n /** Sell only: target number of contracts to sell. */\n sellShares?: number;\n /** Per-chain USD balances. JSON-serialized in query. */\n chainBalances?: Record<string, number>;\n /** Maximum slippage in basis points. */\n slipCapBps?: number;\n /** Include venue-by-venue comparison quotes. */\n compareVenues?: boolean;\n /**\n * Sell-only cache scope. Position freshness and account identity affect the\n * server-side sellable inventory even when the requested amount is unchanged.\n */\n sellCacheScope?: {\n accountId?: string | null;\n positionVersion?: number | null;\n };\n /** Account balance freshness affects whether a server quote is executable. */\n balanceCacheScope?: {\n accountId?: string | null;\n balanceVersion?: number | null;\n /** Semantic funds/holds identity. When provided, unchanged polling timestamps\n * must not cancel an in-flight quote; this takes precedence over balanceVersion. */\n balanceKey?: string;\n };\n /**\n * Opt in to the deep cost-estimate surface — response `feeBreakdown`\n * gains `setupCosts` (chain approvals + Kalshi ATAs) with `alreadyPaid`\n * flags from prior trade history, and `setupCostsTotal` is folded into\n * `totalCostIncFees` (with `estimatedProfit` / `returnPct` recomputed).\n * Buy-only.\n */\n deepEstimate?: boolean;\n /** Enable/disable the query. Default true. */\n enabled?: boolean;\n /** Cache freshness and polling interval in milliseconds. Defaults to SMART_ROUTE_STALE_TIME_MS. */\n staleTimeMs?: number;\n /**\n * UI activity hints used by the centralized refresh policy. These do not\n * affect the fetched payload, only whether quote polling should stay active\n * and whether thin-liquidity quotes should refresh more aggressively.\n */\n refreshContext?: {\n /** True when the quote panel is the visible/active surface. Defaults to true. */\n isPanelActive?: boolean;\n /** True while the user is actively editing the quote inputs. Defaults to false. */\n isEditing?: boolean;\n /** True when the market is open for trading. Defaults to true. */\n isMarketOpen?: boolean;\n /** True while the trade is being submitted or executed. Defaults to false. */\n isSubmitting?: boolean;\n };\n}\n\n/**\n * Why the smart route query is currently loading.\n * - `\"finding-best-odds\"` — first fetch, no prior data in cache\n * - `\"updating-route\"` — query key changed (e.g. amount changed), placeholder data shown\n * - `\"refreshing-quotes\"` — background poll/revalidation with existing data\n */\nexport type SmartRouteLoadingReason = \"finding-best-odds\" | \"updating-route\" | \"refreshing-quotes\";\n\nexport interface UseSmartRouteResult {\n data: SmartRouteResponse | null;\n isLoading: boolean;\n isFetching: boolean;\n error: Error | null;\n refetch: () => Promise<unknown>;\n /** Null when not loading. See {@link SmartRouteLoadingReason}. */\n loadingReason: SmartRouteLoadingReason | null;\n}\n\nconst getIsDocumentVisible = (): boolean => {\n if (typeof document === \"undefined\") return true;\n return document.visibilityState !== \"hidden\";\n};\n\n/**\n * Compute optimal order routing across venues via the MILP solver.\n * Returns a user-scoped quote with per-venue fills and verification timing.\n *\n * The query re-fetches when venueMarketOutcomeId, maxSpend, or chainBalances change.\n * Uses keepPreviousData to avoid flicker during re-computation.\n */\nexport function useSmartRoute(options: UseSmartRouteOptions): UseSmartRouteResult {\n const client = useAggClient();\n const {\n venueMarketOutcomeId,\n venueMarketId,\n outcomeId,\n side,\n tradeSide,\n mode,\n maxSpend,\n sellShares,\n chainBalances,\n slipCapBps,\n compareVenues,\n sellCacheScope,\n balanceCacheScope,\n deepEstimate,\n enabled = true,\n staleTimeMs = SMART_ROUTE_STALE_TIME_MS,\n refreshContext,\n } = options;\n const resolvedVenueMarketOutcomeId = venueMarketOutcomeId ?? venueMarketId ?? outcomeId;\n const hasValidInput = (maxSpend ?? 0) > 0 || (sellShares ?? 0) > 0;\n const queryEnabled = enabled && !!resolvedVenueMarketOutcomeId && hasValidInput;\n\n const query = useQuery({\n queryKey: [\n \"smart-route\",\n resolvedVenueMarketOutcomeId,\n side ?? null,\n tradeSide ?? null,\n ...(mode ? [mode] : []),\n maxSpend ?? null,\n sellShares ?? null,\n chainBalances ? JSON.stringify(chainBalances) : null,\n slipCapBps ?? null,\n compareVenues ?? false,\n deepEstimate ?? false,\n ...(balanceCacheScope\n ? [\n balanceCacheScope.accountId ?? null,\n balanceCacheScope.balanceKey ?? balanceCacheScope.balanceVersion ?? null,\n ]\n : []),\n ...(tradeSide === \"sell\"\n ? [sellCacheScope?.accountId ?? null, sellCacheScope?.positionVersion ?? null]\n : []),\n ] as const,\n queryFn: async ({ signal }) => {\n return client.getSmartRoute(\n {\n venueMarketOutcomeId: resolvedVenueMarketOutcomeId!,\n side: side ?? undefined,\n tradeSide: tradeSide ?? undefined,\n ...(mode ? { mode } : {}),\n maxSpend,\n sellShares,\n chainBalances,\n slipCapBps,\n compareVenues,\n deepEstimate,\n },\n { signal },\n );\n },\n enabled: queryEnabled,\n staleTime: staleTimeMs,\n refetchInterval: (queryState) =>\n resolveSmartRouteRefetchInterval({\n // SELL already fans out into one quote per venue. Keep that group on a\n // stable cadence instead of multiplying the adaptive 5s/refreshAt poll.\n data: queryState.state.data as SmartRouteResponse | null | undefined,\n adaptive: tradeSide !== \"sell\",\n defaultIntervalMs: staleTimeMs,\n isDocumentVisible: getIsDocumentVisible(),\n isEditing: refreshContext?.isEditing ?? false,\n isInputValid: hasValidInput,\n isMarketOpen: refreshContext?.isMarketOpen ?? true,\n isPanelActive: refreshContext?.isPanelActive ?? true,\n isSubmitting: refreshContext?.isSubmitting ?? false,\n queryEnabled,\n }),\n gcTime: 60_000,\n refetchOnWindowFocus: false,\n refetchIntervalInBackground: false,\n retry: 1,\n // A previous SELL quote can carry a quoteId and position availability for\n // a different amount or position snapshot. Never expose it under a new\n // sell key while the replacement request is in flight. BUY retains the\n // existing no-flicker behavior.\n placeholderData: tradeSide === \"sell\" ? undefined : keepPreviousData,\n });\n\n const error = query.error;\n\n let loadingReason: SmartRouteLoadingReason | null = null;\n if (query.isFetching) {\n if (query.isPlaceholderData) {\n // Query key changed (e.g. amount) and keepPreviousData is showing the\n // previous key's quote. In v5 this reports isLoading=false, so it must be\n // checked explicitly or it would be mistaken for a background poll.\n loadingReason = \"updating-route\";\n } else if (query.isLoading) {\n // isLoading = isPending && isFetching: very first fetch, no prior data.\n loadingReason = query.data != null ? \"updating-route\" : \"finding-best-odds\";\n } else {\n // Same key re-fetching in the background (poll / revalidation).\n loadingReason = \"refreshing-quotes\";\n }\n }\n\n return {\n data: query.data ?? null,\n isLoading: query.isLoading,\n isFetching: query.isFetching,\n error: error instanceof Error ? error : error ? new Error(String(error)) : null,\n refetch: query.refetch,\n loadingReason,\n };\n}\n","import type {\n BatchOrderbooksResponse,\n ExecutionMode,\n SmartRouteResponse,\n Venue,\n} from \"@agg-build/sdk\";\nimport { keepPreviousData, useQueries, useQuery } from \"@tanstack/react-query\";\nimport { useAggClient } from \"./core/provider\";\nimport { resolveSmartRouteRefetchInterval } from \"./smart-route-refresh-policy\";\nimport { SMART_ROUTE_STALE_TIME_MS, type UseSmartRouteOptions } from \"./use-smart-route\";\n\nexport interface LimitOrderVenueQuoteRequest {\n venue: Venue;\n venueMarketOutcomeId: string;\n /** The venue's own market; its tick and size rules are fetched with the selected market's. */\n venueMarketId?: string;\n}\n\nexport interface UseLimitOrderVenueQuotesOptions {\n requests: LimitOrderVenueQuoteRequest[];\n tradeSide: \"buy\" | \"sell\";\n amount?: number;\n marketId?: string | null;\n accountId?: string | null;\n chainBalances?: Record<string, number>;\n mode?: ExecutionMode | null;\n slipCapBps?: number;\n enabled?: boolean;\n staleTimeMs?: number;\n refreshContext?: UseSmartRouteOptions[\"refreshContext\"];\n}\n\nexport interface LimitOrderVenueQuoteResult {\n request: LimitOrderVenueQuoteRequest;\n data: SmartRouteResponse | null;\n tickSize?: number | null;\n /** Limit size step, raw 6-dec shares, from orderbook metadata. Null = 1-raw step. */\n sizeStepRaw?: string | null;\n /** Limit size minimum, raw 6-dec shares, from orderbook metadata. Null = none known. */\n minSizeRaw?: string | null;\n isLoading: boolean;\n isFetching: boolean;\n error: Error | null;\n refetch: () => Promise<unknown>;\n}\n\nexport interface UseLimitOrderVenueQuotesResult {\n quotes: LimitOrderVenueQuoteResult[];\n /** The market's orderbook metadata (ticks, size rules) has not loaded yet. */\n isMetadataPending: boolean;\n isLoading: boolean;\n isFetching: boolean;\n error: Error | null;\n refetch: () => Promise<unknown>;\n}\n\nconst getIsDocumentVisible = (): boolean => {\n if (typeof document === \"undefined\") return true;\n return document.visibilityState !== \"hidden\";\n};\n\n// The batch orderbooks endpoint accepts at most 20 venueMarketIds.\nconst MAX_ORDERBOOK_METADATA_MARKET_IDS = 20;\n\nconst getUniqueVenueRequests = (\n requests: LimitOrderVenueQuoteRequest[],\n): LimitOrderVenueQuoteRequest[] => {\n const requestsByVenue = new Map<Venue, LimitOrderVenueQuoteRequest>();\n for (const request of requests) {\n if (!request.venueMarketOutcomeId || requestsByVenue.has(request.venue)) continue;\n requestsByVenue.set(request.venue, request);\n }\n return [...requestsByVenue.values()].sort((left, right) => left.venue.localeCompare(right.venue));\n};\n\nexport const resolveLimitOrderTickSizesByVenue = (\n response: BatchOrderbooksResponse | null | undefined,\n): Map<Venue, number> => {\n const tickSizes = new Map<Venue, number>();\n const setTickSize = (venue: string, tickSize: number | null | undefined): void => {\n if (tickSizes.has(venue as Venue)) return;\n if (typeof tickSize !== \"number\" || !Number.isFinite(tickSize) || tickSize <= 0) return;\n tickSizes.set(venue as Venue, tickSize);\n };\n\n for (const item of response?.data ?? []) {\n for (const [venue, entry] of Object.entries(item.venueOrderbooks)) {\n setTickSize(venue, entry.tick ?? entry.tickSize);\n }\n for (const market of item.matchedMarkets) {\n setTickSize(market.venue, market.tickSize);\n }\n if (item.requestedMarket) {\n setTickSize(item.requestedMarket.venue, item.requestedMarket.tickSize);\n }\n }\n\n return tickSizes;\n};\n\nexport interface LimitOrderSizeRules {\n sizeStepRaw?: string;\n minSizeRaw?: string;\n}\n\n/** Per-venue limit size rules from the same batch orderbook metadata as ticks. */\nexport const resolveLimitOrderSizeRulesByVenue = (\n response: BatchOrderbooksResponse | null | undefined,\n): Map<Venue, LimitOrderSizeRules> => {\n const rulesByVenue = new Map<Venue, LimitOrderSizeRules>();\n const setRules = (venue: string, entry: LimitOrderSizeRules): void => {\n if (rulesByVenue.has(venue as Venue)) return;\n if (!entry.sizeStepRaw && !entry.minSizeRaw) return;\n rulesByVenue.set(venue as Venue, {\n ...(entry.sizeStepRaw ? { sizeStepRaw: entry.sizeStepRaw } : {}),\n ...(entry.minSizeRaw ? { minSizeRaw: entry.minSizeRaw } : {}),\n });\n };\n\n for (const item of response?.data ?? []) {\n for (const [venue, entry] of Object.entries(item.venueOrderbooks)) setRules(venue, entry);\n for (const market of item.matchedMarkets) setRules(market.venue, market);\n if (item.requestedMarket) setRules(item.requestedMarket.venue, item.requestedMarket);\n }\n\n return rulesByVenue;\n};\n\n/**\n * Fetches informational single-venue quotes for limit-order routing cards.\n * Quote IDs are intentionally not consumed by the limit-order execution flow.\n */\nexport const useLimitOrderVenueQuotes = (\n options: UseLimitOrderVenueQuotesOptions,\n): UseLimitOrderVenueQuotesResult => {\n const client = useAggClient();\n const {\n requests,\n tradeSide,\n amount,\n marketId,\n accountId,\n chainBalances,\n mode,\n slipCapBps,\n enabled = true,\n staleTimeMs = SMART_ROUTE_STALE_TIME_MS,\n refreshContext,\n } = options;\n const uniqueRequests = getUniqueVenueRequests(requests);\n const hasValidInput = typeof amount === \"number\" && Number.isFinite(amount) && amount > 0;\n const hasRequiredAccount = tradeSide === \"buy\" || Boolean(accountId);\n const queryEnabled = enabled && hasValidInput && hasRequiredAccount;\n const serializedChainBalances = chainBalances ? JSON.stringify(chainBalances) : null;\n\n // The selected market's orderbook does not always list every matched venue,\n // so each venue's own market is batched into the same single request.\n const metadataMarketIds = marketId\n ? [\n ...new Set([\n marketId,\n ...uniqueRequests.flatMap((request) =>\n request.venueMarketId ? [request.venueMarketId] : [],\n ),\n ]),\n ].slice(0, MAX_ORDERBOOK_METADATA_MARKET_IDS)\n : [];\n const tickMetadataQuery = useQuery({\n queryKey: [\n \"orderbooks\",\n marketId ?? \"__disabled__\",\n \"limit-order-ticks\",\n metadataMarketIds,\n ] as const,\n queryFn: ({ signal }: { signal: AbortSignal }) =>\n client.getOrderbooks({ venueMarketIds: metadataMarketIds }, { signal }),\n enabled: enabled && Boolean(marketId),\n staleTime: 60_000,\n gcTime: 5 * 60_000,\n refetchOnWindowFocus: false,\n retry: 1,\n });\n\n const queries = useQueries({\n queries: uniqueRequests.map((request) => ({\n queryKey: [\n \"smart-route\",\n request.venueMarketOutcomeId,\n \"limit-order-venue-info\",\n {\n venue: request.venue,\n tradeSide,\n amount: amount ?? null,\n // The quote endpoint does not use limit price, so it must not be\n // part of this key or trigger a new informational quote.\n marketId: marketId ?? null,\n accountId: accountId ?? null,\n chainBalances: serializedChainBalances,\n mode: mode ?? null,\n slipCapBps: slipCapBps ?? null,\n },\n ] as const,\n queryFn: async ({ signal }: { signal: AbortSignal }) =>\n client.getSmartRoute(\n {\n venueMarketOutcomeId: request.venueMarketOutcomeId,\n tradeSide,\n ...(tradeSide === \"buy\" ? { maxSpend: amount } : { sellShares: amount }),\n ...(chainBalances ? { chainBalances } : {}),\n ...(mode ? { mode } : {}),\n slipCapBps,\n allowedVenues: [request.venue],\n },\n { signal },\n ),\n enabled: queryEnabled,\n placeholderData: keepPreviousData,\n staleTime: staleTimeMs,\n refetchInterval: (queryState: { state: { data?: SmartRouteResponse | null } }) =>\n resolveSmartRouteRefetchInterval({\n data: queryState.state.data,\n defaultIntervalMs: staleTimeMs,\n isDocumentVisible: getIsDocumentVisible(),\n isEditing: refreshContext?.isEditing ?? false,\n isInputValid: hasValidInput,\n isMarketOpen: refreshContext?.isMarketOpen ?? true,\n isPanelActive: refreshContext?.isPanelActive ?? true,\n isSubmitting: refreshContext?.isSubmitting ?? false,\n queryEnabled,\n }),\n gcTime: 60_000,\n refetchOnWindowFocus: false,\n refetchIntervalInBackground: false,\n retry: 1,\n })),\n });\n\n const tickSizesByVenue = resolveLimitOrderTickSizesByVenue(tickMetadataQuery.data);\n const sizeRulesByVenue = resolveLimitOrderSizeRulesByVenue(tickMetadataQuery.data);\n const quotes = queries.map<LimitOrderVenueQuoteResult>((query, index) => {\n const queryError = query.error;\n const request = uniqueRequests[index]!;\n return {\n request,\n data: query.data ?? null,\n tickSize: tickSizesByVenue.get(request.venue) ?? null,\n sizeStepRaw: sizeRulesByVenue.get(request.venue)?.sizeStepRaw ?? null,\n minSizeRaw: sizeRulesByVenue.get(request.venue)?.minSizeRaw ?? null,\n isLoading: query.isLoading,\n isFetching: query.isFetching,\n error:\n queryError instanceof Error\n ? queryError\n : queryError\n ? new Error(String(queryError))\n : null,\n refetch: query.refetch,\n };\n });\n\n return {\n quotes,\n // A failed metadata read is not pending: callers fall back to 1-raw sizing.\n isMetadataPending: Boolean(marketId) && tickMetadataQuery.isPending === true,\n isLoading: quotes.some((quote) => quote.isLoading),\n isFetching: quotes.some((quote) => quote.isFetching),\n error: quotes.find((quote) => quote.error)?.error ?? null,\n refetch: () =>\n Promise.all([\n ...(marketId ? [tickMetadataQuery.refetch()] : []),\n ...quotes.map((quote) => quote.refetch()),\n ]),\n };\n};\n","import type { ExecutionMode, SmartRouteResponse, Venue } from \"@agg-build/sdk\";\nimport { useQueries } from \"@tanstack/react-query\";\nimport { useAggClient } from \"./core/provider\";\nimport { resolveSmartRouteRefetchInterval } from \"./smart-route-refresh-policy\";\nimport { SMART_ROUTE_STALE_TIME_MS, type UseSmartRouteOptions } from \"./use-smart-route\";\n\nexport interface VenueSellQuoteRequest {\n venue: Venue;\n requestedSellShares: number;\n sellShares: number;\n availableShares: number;\n}\n\nexport interface UseVenueSellQuotesOptions {\n venueMarketOutcomeId?: string | null;\n accountId?: string | null;\n positionVersion?: number | null;\n requests: VenueSellQuoteRequest[];\n mode?: ExecutionMode | null;\n slipCapBps?: number;\n enabled?: boolean;\n staleTimeMs?: number;\n refreshContext?: UseSmartRouteOptions[\"refreshContext\"];\n}\n\nexport interface VenueSellQuoteResult {\n request: VenueSellQuoteRequest;\n data: SmartRouteResponse | null;\n isLoading: boolean;\n isFetching: boolean;\n error: Error | null;\n refetch: () => Promise<unknown>;\n}\n\nexport interface UseVenueSellQuotesResult {\n quotes: VenueSellQuoteResult[];\n isLoading: boolean;\n isFetching: boolean;\n error: Error | null;\n refetch: () => Promise<unknown>;\n}\n\nconst getIsDocumentVisible = (): boolean => {\n if (typeof document === \"undefined\") return true;\n return document.visibilityState !== \"hidden\";\n};\n\nconst getUniqueVenueRequests = (requests: VenueSellQuoteRequest[]): VenueSellQuoteRequest[] => {\n const requestsByVenue = new Map<Venue, VenueSellQuoteRequest>();\n for (const request of requests) {\n if (\n request.requestedSellShares <= 0 ||\n request.sellShares <= 0 ||\n request.availableShares <= 0\n ) {\n continue;\n }\n if (requestsByVenue.has(request.venue)) continue;\n requestsByVenue.set(request.venue, request);\n }\n return [...requestsByVenue.values()].sort((left, right) => left.venue.localeCompare(right.venue));\n};\n\n/**\n * Fetches one independently executable SELL quote for every eligible venue.\n * Each query owns its quoteId and is cache-scoped to the exact account,\n * position snapshot, venue, requested amount, and clamped venue amount.\n */\nexport const useVenueSellQuotes = (\n options: UseVenueSellQuotesOptions,\n): UseVenueSellQuotesResult => {\n const client = useAggClient();\n const {\n venueMarketOutcomeId,\n accountId,\n positionVersion,\n requests,\n mode,\n slipCapBps,\n enabled = true,\n staleTimeMs = SMART_ROUTE_STALE_TIME_MS,\n refreshContext,\n } = options;\n const uniqueRequests = getUniqueVenueRequests(requests);\n\n const queries = useQueries({\n queries: uniqueRequests.map((request) => {\n const hasValidInput =\n request.requestedSellShares > 0 && request.sellShares > 0 && request.availableShares > 0;\n const queryEnabled = enabled && !!venueMarketOutcomeId && !!accountId && hasValidInput;\n\n return {\n queryKey: [\n \"smart-route\",\n venueMarketOutcomeId,\n \"venue-sell\",\n {\n accountId: accountId ?? null,\n positionVersion: positionVersion ?? null,\n requestedSellShares: request.requestedSellShares,\n sellShares: request.sellShares,\n availableShares: request.availableShares,\n allowedVenues: [request.venue],\n compareVenues: false,\n tradeSide: \"sell\",\n mode: mode ?? null,\n slipCapBps: slipCapBps ?? null,\n },\n ] as const,\n queryFn: async ({ signal }: { signal: AbortSignal }) =>\n client.getSmartRoute(\n {\n venueMarketOutcomeId: venueMarketOutcomeId!,\n tradeSide: \"sell\",\n ...(mode ? { mode } : {}),\n sellShares: request.sellShares,\n slipCapBps,\n allowedVenues: [request.venue],\n },\n { signal },\n ),\n enabled: queryEnabled,\n staleTime: staleTimeMs,\n refetchInterval: (queryState: { state: { data?: SmartRouteResponse | null } }) =>\n resolveSmartRouteRefetchInterval({\n // Venue quotes are display companions to the aggregate SELL quote.\n // Poll them at the normal cadence rather than independently\n // accelerating every venue to the thin-liquidity interval.\n data: queryState.state.data,\n adaptive: false,\n defaultIntervalMs: staleTimeMs,\n isDocumentVisible: getIsDocumentVisible(),\n isEditing: refreshContext?.isEditing ?? false,\n isInputValid: hasValidInput,\n isMarketOpen: refreshContext?.isMarketOpen ?? true,\n isPanelActive: refreshContext?.isPanelActive ?? true,\n isSubmitting: refreshContext?.isSubmitting ?? false,\n queryEnabled,\n }),\n gcTime: 60_000,\n refetchOnWindowFocus: false,\n refetchIntervalInBackground: false,\n retry: 1,\n };\n }),\n });\n\n const quotes = queries.map<VenueSellQuoteResult>((query, index) => {\n const queryError = query.error;\n return {\n request: uniqueRequests[index]!,\n data: query.data ?? null,\n isLoading: query.isLoading,\n isFetching: query.isFetching,\n error:\n queryError instanceof Error\n ? queryError\n : queryError\n ? new Error(String(queryError))\n : null,\n refetch: query.refetch,\n };\n });\n\n return {\n quotes,\n isLoading: quotes.some((quote) => quote.isLoading),\n isFetching: quotes.some((quote) => quote.isFetching),\n error: quotes.find((quote) => quote.error)?.error ?? null,\n refetch: () => Promise.all(quotes.map((quote) => quote.refetch())),\n };\n};\n","import { useInfiniteQuery } from \"@tanstack/react-query\";\nimport { Venue } from \"@agg-build/sdk\";\nimport { useAggClient } from \"./core/provider\";\n\nexport interface UseUserHoldingsOptions {\n venue: Venue;\n venueMarketId?: string;\n venueEventId?: string;\n enabled?: boolean;\n limit?: number;\n}\n\n/**\n * Fetch user holdings (positions) for a single venue with cursor-based pagination.\n * The backend resolves venue-specific identifiers (e.g. conditionId for Polymarket).\n */\nexport function useUserHoldings(options: UseUserHoldingsOptions) {\n const client = useAggClient();\n const { venue, venueMarketId, venueEventId, enabled = true } = options;\n\n const query = useInfiniteQuery({\n queryKey: [\"user-holdings\", venue, venueMarketId, venueEventId],\n queryFn: async ({ pageParam }) => {\n return client.getUserHoldings({\n venue,\n venueMarketId,\n venueEventId,\n cursor: pageParam as string | undefined,\n });\n },\n initialPageParam: undefined as string | undefined,\n getNextPageParam: (lastPage) => lastPage.nextCursor ?? undefined,\n enabled,\n });\n\n const holdings = query.data?.pages.flatMap((p) => p.data) ?? [];\n const hasNextPage = !!query.hasNextPage;\n\n return {\n ...query,\n holdings,\n hasNextPage,\n };\n}\n","import { MarketStatus } from \"@agg-build/sdk\";\nimport type {\n AggClient,\n RecurringCryptoDuration,\n RecurringCryptoVenueMarket,\n RecurringCryptoWindowMarket,\n} from \"@agg-build/sdk\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport { useAggClient } from \"./core/provider\";\nimport type { VenueEventWithMarkets } from \"./core/ui-config/types\";\n\nconst RESOLVING_POLL_INTERVAL_MS = 15_000;\nconst FALLBACK_VENUE_EVENT_PAGE_LIMIT = 100;\nconst FALLBACK_VENUE_EVENT_MAX_PAGES = 5;\nconst FALLBACK_TARGET_WINDOW_COUNT = 5;\nconst TIMELINE_FUTURE_WINDOWS = 4;\nconst RECURRING_MARKET_STATUSES = [\n MarketStatus.open,\n MarketStatus.closed,\n MarketStatus.resolved,\n MarketStatus.unopened,\n MarketStatus.paused,\n];\n\nconst RECURRING_DURATION_MS: Record<RecurringCryptoDuration, number> = {\n PT5M: 5 * 60_000,\n PT15M: 15 * 60_000,\n PT30M: 30 * 60_000,\n PT1H: 60 * 60_000,\n PT4H: 4 * 60 * 60_000,\n P1D: 24 * 60 * 60_000,\n};\n\nconst RECURRING_SLUG_DURATION: Record<string, RecurringCryptoDuration> = {\n \"5m\": \"PT5M\",\n \"15m\": \"PT15M\",\n \"30m\": \"PT30M\",\n \"1h\": \"PT1H\",\n \"4h\": \"PT4H\",\n \"1d\": \"P1D\",\n};\n\nconst RECURRING_DURATION_AGG_KEY_SEGMENT: Partial<Record<RecurringCryptoDuration, string>> = {\n PT5M: \"5m\",\n PT15M: \"15m\",\n PT30M: \"30m\",\n PT1H: \"1h\",\n PT4H: \"4h\",\n};\n\nconst RECURRING_CRYPTO_SLUG_PATTERN = /^([a-z0-9]+)-updown-(5m|15m|30m|1h|4h|1d)-(\\d+)$/i;\nconst RECURRING_CRYPTO_AGG_KEY_PATTERN =\n /^agg_ud_([a-z0-9]+)_(5m|15m|30m|1h|4h)_(\\d{2})(\\d{2})(\\d{2})T(\\d{2})(\\d{2})$/i;\nconst RECURRING_CRYPTO_DAILY_AGG_KEY_PATTERN = /^agg_ud_([a-z0-9]+)_1d_(\\d{2})(\\d{2})(\\d{2})$/i;\n\nexport type RecurringCryptoIdentity = {\n asset: string | null;\n duration: RecurringCryptoDuration;\n windowStart: number | null;\n};\n\nexport type RecurringCryptoMarketInstance = {\n id: string;\n asset: string;\n duration: RecurringCryptoDuration;\n windowStart: string;\n windowEnd: string;\n status: MarketStatus;\n venueEventId: string;\n venueMarketId: string;\n venue: RecurringCryptoVenueMarket[\"venue\"];\n};\n\nexport type RecurringCryptoTimeline = {\n all: RecurringCryptoMarketInstance[];\n visible: RecurringCryptoMarketInstance[];\n ended: RecurringCryptoMarketInstance | null;\n live: RecurringCryptoMarketInstance | null;\n upcoming: RecurringCryptoMarketInstance[];\n viewed: RecurringCryptoMarketInstance | null;\n};\n\nexport type UseRecurringCryptoMarketsOptions = {\n event: VenueEventWithMarkets | undefined;\n enabled?: boolean;\n};\n\nconst isRecurringCryptoDuration = (\n value: string | null | undefined,\n): value is RecurringCryptoDuration =>\n value != null && Object.prototype.hasOwnProperty.call(RECURRING_DURATION_MS, value);\n\nconst parseTimestamp = (value: string | null | undefined): number | null => {\n if (!value) return null;\n const timestamp = Date.parse(value);\n return Number.isFinite(timestamp) ? timestamp : null;\n};\n\nconst hasCryptoCategory = (event: VenueEventWithMarkets): boolean =>\n event.categories.some(({ category }) =>\n [category.name, category.displayName].some((value) => value?.trim().toLowerCase() === \"crypto\"),\n );\n\nconst resolveWindowStartFromEnd = (\n event: VenueEventWithMarkets,\n duration: RecurringCryptoDuration,\n): number | null => {\n const end =\n parseTimestamp(event.endDate) ??\n event.venueMarkets\n .map((market) => parseTimestamp(market.endDate))\n .find((value) => value != null) ??\n null;\n if (end != null) return end - RECURRING_DURATION_MS[duration];\n\n return parseTimestamp(event.startDate);\n};\n\nconst parseAggKeyWindowStart = (match: RegExpMatchArray): number | null => {\n const year = 2_000 + Number(match[3]);\n const monthIndex = Number(match[4]) - 1;\n const day = Number(match[5]);\n const hour = Number(match[6]);\n const minute = Number(match[7]);\n const timestamp = Date.UTC(year, monthIndex, day, hour, minute);\n const parsed = new Date(timestamp);\n\n if (\n parsed.getUTCFullYear() !== year ||\n parsed.getUTCMonth() !== monthIndex ||\n parsed.getUTCDate() !== day ||\n parsed.getUTCHours() !== hour ||\n parsed.getUTCMinutes() !== minute\n ) {\n return null;\n }\n\n return timestamp;\n};\n\nexport const resolveRecurringCryptoIdentity = (\n event: VenueEventWithMarkets,\n): RecurringCryptoIdentity | null => {\n const slugMatch = event.slug?.match(RECURRING_CRYPTO_SLUG_PATTERN);\n if (slugMatch && hasCryptoCategory(event)) {\n const [, asset, durationSegment, epochSeconds] = slugMatch;\n const duration = RECURRING_SLUG_DURATION[durationSegment.toLowerCase()];\n const parsedEpochSeconds = Number(epochSeconds);\n const windowStart = parsedEpochSeconds * 1_000;\n\n if (duration && Number.isSafeInteger(parsedEpochSeconds) && Number.isFinite(windowStart)) {\n return { asset: asset.toUpperCase(), duration, windowStart };\n }\n }\n\n const aggKeyMatch = event.aggKey?.match(RECURRING_CRYPTO_AGG_KEY_PATTERN);\n if (aggKeyMatch) {\n const [, asset, durationSegment] = aggKeyMatch;\n const duration = RECURRING_SLUG_DURATION[durationSegment.toLowerCase()];\n const windowStart = parseAggKeyWindowStart(aggKeyMatch);\n\n if (duration && windowStart != null) {\n return { asset: asset.toUpperCase(), duration, windowStart };\n }\n }\n\n const dailyAggKeyMatch = event.aggKey?.match(RECURRING_CRYPTO_DAILY_AGG_KEY_PATTERN);\n if (dailyAggKeyMatch) {\n return {\n asset: dailyAggKeyMatch[1].toUpperCase(),\n duration: \"P1D\",\n windowStart: resolveWindowStartFromEnd(event, \"P1D\"),\n };\n }\n\n if (!isRecurringCryptoDuration(event.recurrence)) return null;\n\n return {\n asset: slugMatch?.[1]?.toUpperCase() ?? aggKeyMatch?.[1]?.toUpperCase() ?? null,\n duration: event.recurrence,\n windowStart: resolveWindowStartFromEnd(event, event.recurrence),\n };\n};\n\nconst mergeWindowMarkets = (\n current: RecurringCryptoVenueMarket[],\n incoming: RecurringCryptoVenueMarket[],\n): RecurringCryptoVenueMarket[] => {\n const marketsById = new Map(\n current.map((market) => [\n `${market.venue}:${market.venueEventId}:${market.venueMarketId}`,\n market,\n ]),\n );\n\n incoming.forEach((market) => {\n marketsById.set(`${market.venue}:${market.venueEventId}:${market.venueMarketId}`, market);\n });\n\n return [...marketsById.values()];\n};\n\nexport const mergeRecurringCryptoWindows = (\n windows: RecurringCryptoWindowMarket[],\n): RecurringCryptoWindowMarket[] => {\n const windowsById = new Map<string, RecurringCryptoWindowMarket>();\n\n windows.forEach((windowMarket) => {\n const existing = windowsById.get(windowMarket.id);\n if (!existing) {\n windowsById.set(windowMarket.id, windowMarket);\n return;\n }\n\n windowsById.set(windowMarket.id, {\n ...existing,\n ...windowMarket,\n markets: mergeWindowMarkets(existing.markets, windowMarket.markets),\n });\n });\n\n return [...windowsById.values()].sort(\n (left, right) =>\n (parseTimestamp(left.windowStart) ?? 0) - (parseTimestamp(right.windowStart) ?? 0),\n );\n};\n\nconst selectNavigableMarket = (\n markets: RecurringCryptoVenueMarket[],\n event: VenueEventWithMarkets,\n): RecurringCryptoVenueMarket | null => {\n const navigableMarkets = markets.filter((market) => market.priceSource === \"snag\");\n return (\n navigableMarkets.find((market) => market.venueEventId === event.id) ??\n navigableMarkets.find((market) => market.venue === event.venue) ??\n navigableMarkets[0] ??\n null\n );\n};\n\nexport const resolveRecurringCryptoTimeline = (\n windows: RecurringCryptoWindowMarket[],\n event: VenueEventWithMarkets,\n now: number,\n): RecurringCryptoTimeline => {\n const all = mergeRecurringCryptoWindows(windows).flatMap((windowMarket) => {\n const windowStart = parseTimestamp(windowMarket.windowStart);\n const windowEnd = parseTimestamp(windowMarket.windowEnd);\n const market = selectNavigableMarket(windowMarket.markets, event);\n if (windowStart == null || windowEnd == null || windowEnd <= windowStart || !market) return [];\n\n return [\n {\n id: windowMarket.id,\n asset: windowMarket.asset,\n duration: windowMarket.duration,\n windowStart: windowMarket.windowStart,\n windowEnd: windowMarket.windowEnd,\n status: market.status,\n venueEventId: market.venueEventId,\n venueMarketId: market.venueMarketId,\n venue: market.venue,\n } satisfies RecurringCryptoMarketInstance,\n ];\n });\n\n const viewed = all.find((market) => market.venueEventId === event.id) ?? null;\n const live =\n all.find((market) => {\n const startsAt = parseTimestamp(market.windowStart);\n const endsAt = parseTimestamp(market.windowEnd);\n return (\n market.status === MarketStatus.open &&\n startsAt != null &&\n endsAt != null &&\n startsAt <= now &&\n now < endsAt\n );\n }) ?? null;\n const endedMarkets = all.filter(\n (market) => (parseTimestamp(market.windowEnd) ?? Infinity) <= now,\n );\n const ended = endedMarkets[endedMarkets.length - 1] ?? null;\n const upcoming = all\n .filter((market) => (parseTimestamp(market.windowStart) ?? -Infinity) > now)\n .slice(0, 3);\n const defaultVisible = [ended, live, ...upcoming].filter(\n (market, index, values): market is RecurringCryptoMarketInstance =>\n market != null && values.findIndex((candidate) => candidate?.id === market.id) === index,\n );\n let visible = defaultVisible;\n\n if (viewed && !defaultVisible.some((market) => market.id === viewed.id)) {\n const viewedStart = Date.parse(viewed.windowStart);\n const viewedEnd = Date.parse(viewed.windowEnd);\n const marketToReplace =\n viewedEnd <= now\n ? ended\n : viewedStart > now\n ? upcoming[upcoming.length - 1]\n : (ended ?? upcoming[upcoming.length - 1]);\n\n visible = [\n ...defaultVisible.filter((market) => market.id !== marketToReplace?.id),\n viewed,\n ].sort(\n (left, right) =>\n (parseTimestamp(left.windowStart) ?? 0) - (parseTimestamp(right.windowStart) ?? 0),\n );\n }\n\n return { all, visible, ended, live, upcoming, viewed };\n};\n\nconst fetchRecurringCryptoPage = async (\n client: AggClient,\n options: NonNullable<Parameters<AggClient[\"listRecurringCryptoMarkets\"]>[0]>,\n signal: AbortSignal,\n) =>\n client.listRecurringCryptoMarkets({\n ...options,\n status: options.status ?? RECURRING_MARKET_STATUSES,\n includeOrderbookPrices: false,\n includeReferencePrices: false,\n includeDirectVenueMarkets: options.includeDirectVenueMarkets,\n limit: 100,\n signal,\n });\n\nconst createEmptyPriceComparison =\n (): RecurringCryptoWindowMarket[\"comparisons\"][\"referencePrice\"] => ({\n count: 0,\n min: null,\n max: null,\n spread: null,\n spreadBps: null,\n byVenue: [],\n });\n\nconst normalizeFallbackVenueEvent = (\n candidate: VenueEventWithMarkets,\n identity: RecurringCryptoIdentity,\n): RecurringCryptoWindowMarket | null => {\n const candidateIdentity = resolveRecurringCryptoIdentity(candidate);\n const venueMarket = candidate.venueMarkets[0];\n if (\n !candidateIdentity?.asset ||\n !identity.asset ||\n candidateIdentity.asset !== identity.asset ||\n candidateIdentity.duration !== identity.duration ||\n candidateIdentity.windowStart == null ||\n !venueMarket\n ) {\n return null;\n }\n\n const status = candidate.status ?? venueMarket.status ?? MarketStatus.unopened;\n const windowStart = candidateIdentity.windowStart;\n\n return {\n id: `${candidateIdentity.asset}:${candidateIdentity.duration}:${new Date(windowStart).toISOString()}`,\n asset: candidateIdentity.asset,\n quoteAsset: \"USD\",\n duration: candidateIdentity.duration,\n windowStart: new Date(windowStart).toISOString(),\n windowEnd: new Date(windowStart + RECURRING_DURATION_MS[identity.duration]).toISOString(),\n status,\n markets: [\n {\n venue: candidate.venue,\n venueEventId: candidate.id,\n venueMarketId: venueMarket.id,\n externalEventId: candidate.externalIdentifier,\n externalMarketId: venueMarket.externalIdentifier,\n question: venueMarket.question,\n status,\n priceSource: \"snag\",\n routeable: false,\n splitOrdersAllowed: false,\n outcomes: (venueMarket.venueMarketOutcomes ?? []).map((outcome) => ({\n venueMarketOutcomeId: outcome.id,\n externalOutcomeId: outcome.externalIdentifier ?? null,\n routeable: false,\n splitOrdersAllowed: false,\n label: outcome.label,\n title: outcome.title ?? null,\n midpoint: null,\n bestBid: null,\n bestAsk: null,\n markSource: null,\n lastKnownPrice: null,\n orderbookDepth: null,\n })),\n metrics: {\n volume: venueMarket.volume ?? null,\n volume24h: null,\n openInterest: null,\n liquidity: null,\n spread: null,\n },\n resolution: {\n sourceName: null,\n sourceUrl: null,\n sourceDomain: null,\n rawCriteria: null,\n confidence: \"missing\",\n },\n referencePrice: {\n asset: candidateIdentity.asset,\n quoteAsset: \"USD\",\n raw: null,\n decimals: null,\n normalized: null,\n timestamp: null,\n provider: null,\n providerMarketId: null,\n confidence: \"missing\",\n },\n },\n ],\n comparisons: {\n referencePrice: createEmptyPriceComparison(),\n outcomePrices: {\n up: createEmptyPriceComparison(),\n down: createEmptyPriceComparison(),\n },\n },\n };\n};\n\nconst formatCanonicalRecurringAggKey = (\n asset: string,\n duration: RecurringCryptoDuration,\n windowStart: number,\n): string | null => {\n const durationSegment = RECURRING_DURATION_AGG_KEY_SEGMENT[duration];\n if (!durationSegment) return null;\n\n const date = new Date(windowStart);\n if (Number.isNaN(date.getTime())) return null;\n\n const twoDigits = (value: number): string => String(value).padStart(2, \"0\");\n const timestamp = [\n twoDigits(date.getUTCFullYear() % 100),\n twoDigits(date.getUTCMonth() + 1),\n twoDigits(date.getUTCDate()),\n \"T\",\n twoDigits(date.getUTCHours()),\n twoDigits(date.getUTCMinutes()),\n ].join(\"\");\n\n return `agg_ud_${asset.toLowerCase()}_${durationSegment}_${timestamp}`;\n};\n\nconst fetchCanonicalAggKeyWindows = async (\n client: AggClient,\n event: VenueEventWithMarkets,\n identity: RecurringCryptoIdentity,\n signal: AbortSignal,\n now: number,\n): Promise<RecurringCryptoWindowMarket[]> => {\n const aggKeyMatch = event.aggKey?.match(RECURRING_CRYPTO_AGG_KEY_PATTERN);\n const asset = identity.asset;\n if (!aggKeyMatch || !asset) return [];\n\n const durationMs = RECURRING_DURATION_MS[identity.duration];\n const currentWindowStart = Math.floor(now / durationMs) * durationMs;\n const windowStarts = new Set([\n currentWindowStart - durationMs,\n currentWindowStart,\n currentWindowStart + durationMs,\n currentWindowStart + durationMs * 2,\n currentWindowStart + durationMs * 3,\n identity.windowStart,\n ]);\n const aggKeys = [...windowStarts].flatMap((windowStart) => {\n if (windowStart == null) return [];\n const aggKey = formatCanonicalRecurringAggKey(asset, identity.duration, windowStart);\n return aggKey ? [aggKey] : [];\n });\n if (!aggKeys.length) return [];\n\n const response = await client.getVenueEvents({\n venues: [event.venue],\n aggKey: aggKeys,\n limit: 100,\n signal,\n });\n\n return mergeRecurringCryptoWindows(\n response.data.flatMap((candidate) => {\n const normalized = normalizeFallbackVenueEvent(candidate as VenueEventWithMarkets, identity);\n return normalized ? [normalized] : [];\n }),\n );\n};\n\nconst fetchFallbackVenueEventWindows = async (\n client: AggClient,\n event: VenueEventWithMarkets,\n identity: RecurringCryptoIdentity,\n signal: AbortSignal,\n now: number,\n): Promise<RecurringCryptoWindowMarket[]> => {\n const durationMs = RECURRING_DURATION_MS[identity.duration];\n const categoryIds = event.categories\n .filter(({ category }) =>\n [category.name, category.displayName].some(\n (value) => value?.trim().toLowerCase() === \"crypto\",\n ),\n )\n .map(({ category }) => category.id);\n const windowStarts = new Set([(identity.windowStart ?? now) - durationMs, now - durationMs * 2]);\n const responses = await Promise.all(\n [...windowStarts].map(async (windowStart) => {\n const windows: RecurringCryptoWindowMarket[] = [];\n const seenCursors = new Set<string>();\n let cursor: string | undefined;\n\n for (let page = 0; page < FALLBACK_VENUE_EVENT_MAX_PAGES; page += 1) {\n const response = await client.getVenueEvents({\n venues: [event.venue],\n categoryIds,\n status: RECURRING_MARKET_STATUSES,\n sortBy: \"endDate\",\n sortDir: \"asc\",\n endDateFrom: new Date(windowStart).toISOString(),\n limit: FALLBACK_VENUE_EVENT_PAGE_LIMIT,\n cursor,\n signal,\n });\n\n response.data.forEach((candidate) => {\n const normalized = normalizeFallbackVenueEvent(\n candidate as VenueEventWithMarkets,\n identity,\n );\n if (normalized) windows.push(normalized);\n });\n\n if (mergeRecurringCryptoWindows(windows).length >= FALLBACK_TARGET_WINDOW_COUNT) break;\n\n const nextCursor = response.hasMore ? (response.nextCursor ?? undefined) : undefined;\n if (!nextCursor || seenCursors.has(nextCursor)) break;\n seenCursors.add(nextCursor);\n cursor = nextCursor;\n }\n\n return windows;\n }),\n );\n\n return mergeRecurringCryptoWindows(responses.flat());\n};\n\nexport const fetchRecurringCryptoMarkets = async (\n client: AggClient,\n event: VenueEventWithMarkets,\n signal: AbortSignal,\n now = Date.now(),\n): Promise<RecurringCryptoWindowMarket[]> => {\n const identity = resolveRecurringCryptoIdentity(event);\n if (!identity) return [];\n\n const { asset, duration, windowStart: anchorStart } = identity;\n const queryAssets = event.aggKey?.match(RECURRING_CRYPTO_DAILY_AGG_KEY_PATTERN)\n ? undefined\n : asset\n ? [asset]\n : undefined;\n const canonicalAggKeyWindowsPromise = fetchCanonicalAggKeyWindows(\n client,\n event,\n identity,\n signal,\n now,\n ).catch(() => []);\n const durationMs = RECURRING_DURATION_MS[duration];\n // The pills show ended + live + 3 upcoming; anything later is never rendered.\n const timelineStart = now - durationMs * 2;\n const timelineEnd = now + durationMs * TIMELINE_FUTURE_WINDOWS;\n // A viewed window inside the timeline is found by the timeline query itself.\n const anchorInTimeline =\n anchorStart != null && anchorStart >= timelineStart && anchorStart <= timelineEnd;\n const anchorOptions: Parameters<AggClient[\"listRecurringCryptoMarkets\"]>[0] =\n anchorStart == null\n ? {\n assets: queryAssets,\n durations: [duration],\n venues: [event.venue],\n window: \"current\",\n includeDirectVenueMarkets: duration === \"P1D\",\n }\n : {\n assets: queryAssets,\n durations: [duration],\n venues: [event.venue],\n windowStartFrom: new Date(\n anchorInTimeline ? timelineStart : anchorStart - 1_000,\n ).toISOString(),\n windowStartTo: new Date(\n anchorInTimeline ? timelineEnd : anchorStart + 1_000,\n ).toISOString(),\n includeDirectVenueMarkets: duration === \"P1D\",\n };\n let anchorResponse = await fetchRecurringCryptoPage(client, anchorOptions, signal);\n let anchor = anchorResponse.data.find((windowMarket) =>\n windowMarket.markets.some((market) => market.venueEventId === event.id),\n );\n let timelineVenues: [typeof event.venue] | undefined = [event.venue];\n let canonicalAggKeyWindows: RecurringCryptoWindowMarket[] | null = null;\n\n if (!anchor) {\n canonicalAggKeyWindows = await canonicalAggKeyWindowsPromise;\n if (\n canonicalAggKeyWindows.some((windowMarket) =>\n windowMarket.markets.some((market) => market.venueEventId === event.id),\n )\n ) {\n return canonicalAggKeyWindows;\n }\n }\n\n if (!anchor && asset && anchorStart != null) {\n const unscopedAnchorResponse = await fetchRecurringCryptoPage(\n client,\n { ...anchorOptions, venues: undefined },\n signal,\n );\n const matchingWindow = unscopedAnchorResponse.data.find(\n (windowMarket) =>\n windowMarket.asset === asset &&\n windowMarket.duration === duration &&\n parseTimestamp(windowMarket.windowStart) === anchorStart,\n );\n const viewedWindow = normalizeFallbackVenueEvent(event, identity);\n\n if (matchingWindow && viewedWindow) {\n anchorResponse = unscopedAnchorResponse;\n anchor = {\n ...matchingWindow,\n markets: mergeWindowMarkets(matchingWindow.markets, viewedWindow.markets),\n };\n timelineVenues = undefined;\n }\n }\n\n if (!anchor) {\n return fetchFallbackVenueEventWindows(client, event, identity, signal, now);\n }\n\n const windows = [\n anchor,\n ...anchorResponse.data.filter(\n (windowMarket) => windowMarket.asset === anchor.asset && windowMarket.duration === duration,\n ),\n ];\n // An in-timeline anchor response already is the timeline unless it was truncated.\n if (!anchorInTimeline || anchorResponse.hasMore) {\n const seenCursors = new Set<string>();\n let cursor: string | undefined;\n\n do {\n const response = await fetchRecurringCryptoPage(\n client,\n {\n assets: [anchor.asset],\n durations: [duration],\n venues: timelineVenues,\n windowStartFrom: new Date(timelineStart).toISOString(),\n windowStartTo: new Date(timelineEnd).toISOString(),\n includeDirectVenueMarkets: duration === \"P1D\",\n cursor,\n },\n signal,\n );\n windows.push(...response.data);\n const nextCursor = response.hasMore ? (response.nextCursor ?? undefined) : undefined;\n if (!nextCursor || seenCursors.has(nextCursor)) break;\n seenCursors.add(nextCursor);\n cursor = nextCursor;\n } while (cursor);\n }\n\n windows.push(...(canonicalAggKeyWindows ?? (await canonicalAggKeyWindowsPromise)));\n\n return mergeRecurringCryptoWindows(windows);\n};\n\nexport const recurringCryptoTransitionPollInterval = (\n windows: RecurringCryptoWindowMarket[] | undefined,\n event: VenueEventWithMarkets,\n now = Date.now(),\n): number | false => {\n if (!windows) return false;\n const timeline = resolveRecurringCryptoTimeline(windows, event, now);\n const viewedEnd = parseTimestamp(timeline.viewed?.windowEnd ?? event.endDate);\n return viewedEnd != null && viewedEnd <= now && !timeline.live\n ? RESOLVING_POLL_INTERVAL_MS\n : false;\n};\n\nexport const useRecurringCryptoMarkets = ({\n event,\n enabled = true,\n}: UseRecurringCryptoMarketsOptions) => {\n const client = useAggClient();\n const identity = event ? resolveRecurringCryptoIdentity(event) : null;\n const isEnabled = enabled && event != null && identity != null;\n const query = useQuery({\n queryKey: [\n \"recurring-crypto-markets\",\n event?.id,\n identity?.asset,\n identity?.duration,\n identity?.windowStart,\n event?.venue,\n ],\n queryFn: ({ signal }) => fetchRecurringCryptoMarkets(client, event!, signal),\n enabled: isEnabled,\n staleTime: 10_000,\n gcTime: 5 * 60_000,\n refetchOnWindowFocus: true,\n refetchOnReconnect: true,\n refetchOnMount: true,\n refetchInterval: (queryState) =>\n event\n ? recurringCryptoTransitionPollInterval(\n queryState.state.data as RecurringCryptoWindowMarket[] | undefined,\n event,\n )\n : false,\n retry: 1,\n });\n\n return {\n ...query,\n windows: (query.data as RecurringCryptoWindowMarket[] | undefined) ?? [],\n isRecurringCryptoMarket: isEnabled,\n };\n};\n","import { MarketStatus } from \"@agg-build/sdk\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport { useAggClient } from \"./core/provider\";\nimport type { VenueEventWithMarkets } from \"./core/ui-config/types\";\nimport { resolveRecurringCryptoIdentity } from \"./use-recurring-crypto-markets\";\n\nexport interface UseVenueEventOptions {\n /** The VenueEvent ID to fetch. */\n eventId: string;\n /** Enable/disable the query. Default true. */\n enabled?: boolean;\n /**\n * Scope `marketCount` and the rolled-up `volume` to the whole matched cluster\n * (default) or to this one venue event (`false`). Pair it with the same value\n * on `useVenueMarkets` so the count matches the market list you render.\n */\n cluster?: boolean;\n /**\n * Lifetime-volume floor. Scopes `marketCount` to the markets `useVenueMarkets`\n * returns with the same `minVolume`. Unset = no filter.\n */\n minVolume?: number;\n}\n\nconst RESOLUTION_POLL_MS = 15_000;\nconst RESOLUTION_POLL_MAX_PAST_END_MS = 60 * 60_000;\n\n/**\n * Poll while a market lingers \"open\" past its endDate, and keep polling an\n * explicitly closed recurring-crypto event until settlement is authoritative.\n * This prevents short-cadence markets from staying stale through rollover or\n * delayed resolution when the WebSocket notification is unavailable.\n *\n * endDate is a hint, not truth — some venues have historically reported\n * kickoff as endDate — so it never gates trading; it only triggers refetches\n * and the server's status stays authoritative. The one-hour guard applies to\n * stale open dates; an explicit recurring closed status remains pollable until\n * the backend changes it to resolved.\n */\nexport function resolutionPollInterval(event: VenueEventWithMarkets | undefined): number | false {\n if (!event) return false;\n const now = Date.now();\n const isRecurringCryptoMarket = resolveRecurringCryptoIdentity(event) != null;\n if (isRecurringCryptoMarket && event.status === MarketStatus.resolved) return false;\n if (isRecurringCryptoMarket && event.status === MarketStatus.closed) {\n return RESOLUTION_POLL_MS;\n }\n\n const eventEndsAt = event.endDate ? Date.parse(event.endDate) : Number.NaN;\n if (\n isRecurringCryptoMarket &&\n event.status === MarketStatus.paused &&\n Number.isFinite(eventEndsAt) &&\n eventEndsAt <= now\n ) {\n return RESOLUTION_POLL_MS;\n }\n\n const shouldPoll = event.venueMarkets.some((market) => {\n if (!market.endDate) return false;\n const endsAt = new Date(market.endDate).getTime();\n if (\n isRecurringCryptoMarket &&\n (market.status === MarketStatus.closed || market.status === MarketStatus.paused) &&\n Number.isFinite(endsAt) &&\n endsAt <= now\n ) {\n return true;\n }\n if (market.status !== MarketStatus.open) return false;\n return (\n Number.isFinite(endsAt) && now > endsAt && now < endsAt + RESOLUTION_POLL_MAX_PAST_END_MS\n );\n });\n\n if (shouldPoll) return RESOLUTION_POLL_MS;\n if (!isRecurringCryptoMarket || event.status !== MarketStatus.open) return false;\n if (!Number.isFinite(eventEndsAt)) return false;\n if (now <= eventEndsAt || now >= eventEndsAt + RESOLUTION_POLL_MAX_PAST_END_MS) return false;\n\n return RESOLUTION_POLL_MS;\n}\n\n/**\n * Fetch a single venue event by ID via the API.\n * Returns the event with nested venueMarkets.\n */\nexport function useVenueEvent(options: UseVenueEventOptions) {\n const client = useAggClient();\n const { eventId, enabled = true, cluster, minVolume } = options;\n\n const query = useQuery({\n queryKey: [\"venue-event\", eventId, cluster === false ? \"no-cluster\" : \"\", minVolume ?? \"\"],\n queryFn: async ({ signal }) => {\n return client.getVenueEventById(eventId, { signal, cluster, minVolume });\n },\n enabled: enabled && !!eventId,\n staleTime: 5 * 60_000,\n gcTime: 5 * 60_000,\n refetchOnWindowFocus: true,\n refetchOnReconnect: true,\n refetchOnMount: true,\n refetchInterval: (query) =>\n resolutionPollInterval(query.state.data as VenueEventWithMarkets | undefined),\n retry: 1,\n });\n\n return {\n ...query,\n event: (query.data as VenueEventWithMarkets | undefined) ?? undefined,\n };\n}\n","import type { MarketStatus, MatchStatus, Venue } from \"@agg-build/sdk\";\nimport { QueryClient, QueryClientContext, useInfiniteQuery } from \"@tanstack/react-query\";\nimport { useContext, useEffect, useState } from \"react\";\nimport { AggClientContext } from \"./core/providers/contexts\";\n\nexport interface UseVenueMarketsOptions {\n /** Filter by venue. */\n venue?: Venue;\n /** Filter by parent VenueEvent ID. */\n venueEventId?: string;\n /**\n * Scope `venueEventId` to the whole matched cluster (default) or to that one\n * venue event (`false`). Ignored without `venueEventId`.\n */\n cluster?: boolean;\n /** Search by question text. */\n search?: string;\n /** Filter by market status. */\n status?: MarketStatus;\n /** Filter by match status. */\n matchStatus?: MatchStatus;\n /** Canonical game or market key filter. */\n aggKey?: string[];\n /** Sports section filter: moneyline, spread, total, prop, ... */\n sportsMarketType?: string[];\n /** Sports period filter: full, 1h, 2h, q1, ... */\n period?: string[];\n /** Sports prop-category filter: corners, goals, assists, ... */\n marketCategory?: string[];\n /** Sports section/tab grouping filter: game_lines, spreads, totals, player_props, ... */\n marketGroup?: string[];\n /** Page size when using cursor pagination. Default 20. */\n limit?: number;\n /** Eagerly fetch every page until exhausted (no scroll wiring needed). */\n fetchAll?: boolean;\n /** Enable/disable the query. Default true. */\n enabled?: boolean;\n /** Sort by this field. */\n sortBy?: \"volume\" | \"volume24hr\" | \"createdAt\" | \"updatedAt\";\n /** Sort direction: \"asc\" or \"desc\". */\n sortDir?: \"asc\" | \"desc\";\n /** Sort surface. \"list\" makes axis/dates events sort by volume (matches the\n * tile top-3); omit or \"detail\" on the detail page to keep structured order. */\n context?: \"list\" | \"detail\";\n /** Text projection, independent of sort. Omit to preserve existing responses. */\n projection?: \"summary\" | \"full\";\n /** Lifetime-volume floor (USD). Omit or 0 = no filter. */\n minVolume?: number;\n}\n\n/**\n * Fetch venue markets with cursor-based pagination.\n * Use fetchNextPage for \"Load more\".\n */\nexport function useVenueMarkets(options?: UseVenueMarketsOptions) {\n const client = useContext(AggClientContext);\n const queryClient = useContext(QueryClientContext);\n const [fallbackQueryClient] = useState(() => new QueryClient());\n const venue = options?.venue;\n const venueEventId = options?.venueEventId;\n const cluster = options?.cluster;\n const search = options?.search;\n const matchStatus = options?.matchStatus;\n const status = options?.status;\n const aggKey = options?.aggKey;\n const sportsMarketType = options?.sportsMarketType;\n const period = options?.period;\n const marketCategory = options?.marketCategory;\n const marketGroup = options?.marketGroup;\n const enabled = options?.enabled ?? true;\n const limit = options?.limit ?? 20;\n const sortBy = options?.sortBy;\n const sortDir = options?.sortDir;\n const context = options?.context;\n const projection = options?.projection;\n const minVolume = options?.minVolume;\n\n useEffect(() => {\n if (queryClient) return undefined;\n\n fallbackQueryClient.mount();\n return () => {\n fallbackQueryClient.unmount();\n };\n }, [fallbackQueryClient, queryClient]);\n\n if (enabled && !client) {\n throw new Error(\"useVenueMarkets must be used within an <AggProvider>\");\n }\n\n const query = useInfiniteQuery(\n {\n queryKey: [\n \"venue-markets\",\n venue ?? \"\",\n venueEventId ?? \"\",\n cluster === false ? \"no-cluster\" : \"\",\n search ?? \"\",\n matchStatus ?? \"\",\n status ?? \"\",\n aggKey?.join(\",\") ?? \"\",\n sportsMarketType?.join(\",\") ?? \"\",\n period?.join(\",\") ?? \"\",\n marketCategory?.join(\",\") ?? \"\",\n marketGroup?.join(\",\") ?? \"\",\n limit,\n sortBy ?? \"\",\n sortDir ?? \"\",\n context ?? \"\",\n minVolume ?? \"\",\n projection ?? \"\",\n ],\n queryFn: async ({ pageParam, signal }) => {\n if (!client) {\n throw new Error(\"useVenueMarkets must be used within an <AggProvider>\");\n }\n\n const res = await client.getVenueMarkets(\n {\n venue,\n venueEventId,\n cluster,\n search,\n matchStatus,\n status,\n aggKey,\n sportsMarketType,\n period,\n marketCategory,\n marketGroup,\n limit,\n cursor: pageParam as string | undefined,\n sortBy,\n sortDir,\n context,\n projection,\n minVolume,\n },\n { signal },\n );\n return res;\n },\n initialPageParam: undefined as string | undefined,\n getNextPageParam: (lastPage) => {\n if (!lastPage.hasMore) return undefined;\n return lastPage.nextCursor ?? undefined;\n },\n enabled: enabled && !!client,\n },\n queryClient ?? fallbackQueryClient,\n );\n\n const markets = query.data?.pages.flatMap((page) => page.data) ?? [];\n const hasNextPage = !!query.hasNextPage;\n\n const { fetchNextPage, isFetchingNextPage } = query;\n const fetchAll = options?.fetchAll ?? false;\n useEffect(() => {\n if (!enabled || !client || !fetchAll || !hasNextPage || isFetchingNextPage) return;\n void fetchNextPage();\n }, [enabled, client, fetchAll, hasNextPage, isFetchingNextPage, fetchNextPage]);\n\n return {\n ...query,\n markets,\n hasNextPage,\n };\n}\n","import { MarketStatus, type VenueMarket } from \"@agg-build/sdk\";\nimport { useMemo } from \"react\";\nimport type { VenueEventWithMarkets } from \"./core/ui-config/types\";\nimport { useVenueEvent, type UseVenueEventOptions } from \"./use-venue-event\";\nimport { useVenueMarkets } from \"./use-venue-markets\";\n\n/**\n * Replaces the event's minimal venueMarkets with full versions from the\n * /venue-markets endpoint, preserving the original ordering.\n */\nexport function mergeEventWithFullMarkets(\n event: VenueEventWithMarkets,\n fullMarkets: VenueMarket[],\n): VenueEventWithMarkets {\n if (fullMarkets.length === 0) return event;\n\n const fullById = new Map(fullMarkets.map((m) => [m.id, m]));\n\n // Lean event responses (GET /venue-events/:id?expand=) omit the embedded\n // venueMarkets preview; when it's absent, adopt the full /venue-markets list\n // directly instead of mapping over an empty array (which would drop them).\n const ordering = event.venueMarkets.length > 0 ? event.venueMarkets : fullMarkets;\n const mergedMarkets = ordering.map((minimal) => fullById.get(minimal.id) ?? minimal);\n\n return { ...event, venueMarkets: mergedMarkets };\n}\n\nexport type UseEnrichedVenueEventOptions = UseVenueEventOptions & {\n progressive?: boolean;\n /** Summary keeps structured order and demand-loads text in detail consumers. */\n projection?: \"summary\" | \"full\";\n /** Lifetime-volume floor for the open-markets list (the all-status fallback ignores it). */\n minVolume?: number;\n};\n\n/**\n * Fetches a venue event and enriches its venueMarkets with full data\n * (description, rulesPrimary, rulesSecondary, etc.) from the /venue-markets endpoint.\n *\n * The useVenueMarkets call shares the same React Query cache key as MarketDetailsList,\n * so no extra HTTP request is made.\n */\nexport function useEnrichedVenueEvent(options: UseEnrichedVenueEventOptions) {\n const { event, isLoading, error, ...rest } = useVenueEvent(options);\n const eventEndedAt =\n event?.endDate && Number.isFinite(Date.parse(event.endDate)) ? Date.parse(event.endDate) : null;\n const shouldFetchOnlyOpenMarkets = eventEndedAt == null || eventEndedAt >= Date.now();\n\n const openQuery = useVenueMarkets({\n venueEventId: options.eventId,\n cluster: options.cluster,\n enabled: (options.enabled ?? true) && !!event,\n status: shouldFetchOnlyOpenMarkets ? MarketStatus.open : undefined,\n // No explicit sortBy: event-scoped /venue-markets sorts by the event's\n // type-aware order (structureOrderBy). Keeping this in lockstep with\n // MarketDetailsList (including limit, part of the query key) preserves the\n // shared React Query cache key and the event-type ordering.\n limit: 100,\n projection: options.projection,\n fetchAll: !options.progressive,\n minVolume: options.minVolume,\n });\n const { markets: openMarkets, isLoading: isEnrichingOpenMarkets } = openQuery;\n const shouldFetchAllMarketsFallback =\n (options.enabled ?? true) &&\n !!event &&\n shouldFetchOnlyOpenMarkets &&\n !isEnrichingOpenMarkets &&\n openMarkets.length === 0;\n const fallbackQuery = useVenueMarkets({\n venueEventId: options.eventId,\n cluster: options.cluster,\n enabled: shouldFetchAllMarketsFallback,\n // No status filter on fallback: if an active event temporarily has only\n // closed/resolved markets, still render the event page instead of the\n // unavailable state.\n // No minVolume on fallback: an event whose open markets are all below the\n // floor must still render (mirrors the bootstrap endpoint's fallback).\n limit: 100,\n projection: options.projection,\n fetchAll: !options.progressive,\n });\n const { markets: fallbackMarkets, isLoading: isEnrichingFallbackMarkets } = fallbackQuery;\n const activeQuery = shouldFetchAllMarketsFallback ? fallbackQuery : openQuery;\n const markets = fallbackMarkets.length > 0 ? fallbackMarkets : openMarkets;\n const isEnriching = isEnrichingOpenMarkets || isEnrichingFallbackMarkets;\n\n const enrichedEvent = useMemo(() => {\n if (!event) return undefined;\n if (markets.length === 0) return event;\n return mergeEventWithFullMarkets(event, markets);\n }, [event, markets]);\n\n return {\n ...rest,\n event: enrichedEvent,\n isLoading,\n isEnriching,\n hasMoreMarkets: !!activeQuery.hasNextPage,\n loadMoreMarkets: activeQuery.fetchNextPage,\n isLoadingMoreMarkets: !!activeQuery.isFetchingNextPage,\n error,\n };\n}\n","import type { MarketStatus, MatchStatus, Venue, RecurrenceFilter } from \"@agg-build/sdk\";\nimport {\n QueryClient,\n QueryClientContext,\n keepPreviousData,\n useInfiniteQuery,\n} from \"@tanstack/react-query\";\nimport { useContext, useEffect, useMemo, useRef, useState } from \"react\";\nimport { AggClientContext } from \"./core/providers/contexts\";\nimport type { VenueEventWithMarkets } from \"./core/ui-config/types\";\n\nexport interface UseVenueEventsOptions {\n /** Optional query-key scope to isolate caches across different surfaces. */\n queryKeyScope?: string;\n /** If provided, fetch events only from these providers. Omit or empty = both. */\n venues?: Venue[];\n /** If provided, filter/search events by this query (relayed to each provider). */\n search?: string;\n /** If provided, filter events by category IDs. */\n categoryIds?: string[];\n /** If provided, filter by match status. */\n matchStatus?: MatchStatus[];\n /** If provided, filter by market status. */\n status?: MarketStatus[];\n /** If provided, sort results by this field (e.g. \"volume\"). */\n sortBy?: string;\n /** Sort direction: \"asc\" or \"desc\". */\n sortDir?: string;\n /** Recurrence filter. Uses public ISO-8601 cadence enum values, or \"null\" for one-off events. */\n recurrence?: RecurrenceFilter | RecurrenceFilter[];\n /** If provided, enable the query. */\n enabled?: boolean;\n /** Page size when using cursor pagination. Default 20. */\n limit?: number;\n /** Lifetime-volume floor (USD). Omit or 0 = no filter. */\n minVolume?: number;\n /** If provided, filter by minimum yes price. */\n minYesPrice?: number;\n /** If provided, filter by maximum yes price. */\n maxYesPrice?: number;\n /** ISO-8601 timestamp. When set, hides events with endDate <= value; NULL-endDate events are kept. */\n endDateFrom?: string;\n /**\n * When true, fold same-venue companion events into one tile per game\n * (`groupParentId IS NULL`). Default (omitted/false) = ungrouped.\n */\n grouped?: boolean;\n /**\n * When restoring from a navigation snapshot, eagerly fetch this many pages\n * on mount (pages are likely cached by React Query from the prior visit).\n * Only runs once per mount. Ignored when <= 1.\n */\n initialPages?: number;\n}\n\n/**\n * Fetch venue events from one or both providers (Kalshi, Polymarket) via the API\n * with cursor-based pagination. Use fetchNextPage for \"Load more\".\n */\nexport function useVenueEvents(options?: UseVenueEventsOptions) {\n const client = useContext(AggClientContext);\n const queryClient = useContext(QueryClientContext);\n const [fallbackQueryClient] = useState(() => new QueryClient());\n const venues = options?.venues;\n const search = options?.search;\n const categoryIds = options?.categoryIds;\n const matchStatus = options?.matchStatus ?? [];\n const enabled = options?.enabled ?? true;\n const limit = options?.limit ?? 20;\n const status = options?.status;\n const sortBy = options?.sortBy;\n const sortDir = options?.sortDir;\n const recurrence = options?.recurrence;\n const queryKeyScope = options?.queryKeyScope ?? \"events\";\n const minVolume = options?.minVolume;\n const minYesPrice = options?.minYesPrice;\n const maxYesPrice = options?.maxYesPrice;\n const endDateFrom = options?.endDateFrom;\n const grouped = options?.grouped;\n const initialPages = options?.initialPages;\n\n useEffect(() => {\n if (queryClient) return undefined;\n\n fallbackQueryClient.mount();\n return () => {\n fallbackQueryClient.unmount();\n };\n }, [fallbackQueryClient, queryClient]);\n\n if (enabled && !client) {\n throw new Error(\"useVenueEvents must be used within an <AggProvider>\");\n }\n\n const query = useInfiniteQuery(\n {\n queryKey: [\n queryKeyScope,\n venues ?? [],\n search ?? \"\",\n categoryIds?.join(\",\") ?? \"\",\n matchStatus?.join(\",\") ?? \"\",\n status?.join(\",\") ?? \"\",\n sortBy ?? \"\",\n sortDir ?? \"\",\n recurrence ?? \"\",\n minYesPrice ?? \"\",\n maxYesPrice ?? \"\",\n endDateFrom ?? \"\",\n grouped ?? false,\n minVolume ?? \"\",\n limit,\n ],\n queryFn: async ({ pageParam, signal }) => {\n if (!client) {\n throw new Error(\"useVenueEvents must be used within an <AggProvider>\");\n }\n\n const res = await client.getVenueEvents({\n venues,\n search,\n categoryIds,\n matchStatus,\n status,\n sortBy,\n sortDir,\n recurrence,\n limit,\n minVolume,\n minYesPrice,\n maxYesPrice,\n endDateFrom,\n grouped,\n cursor: pageParam as string | undefined,\n signal,\n });\n return res;\n },\n initialPageParam: undefined as string | undefined,\n getNextPageParam: (lastPage) => {\n if (!lastPage.hasMore) return undefined;\n return lastPage.nextCursor ?? undefined;\n },\n // TODO: RMIK - Comment out to show skeletons on category switch\n placeholderData: keepPreviousData,\n enabled: enabled && !!client,\n },\n queryClient ?? fallbackQueryClient,\n );\n\n // Eagerly prefetch pages on mount when restoring from a navigation snapshot.\n // Pages are typically already in React Query's cache, so this is near-instant.\n const prefetchedRef = useRef(false);\n useEffect(() => {\n if (!enabled || !client) return;\n if (prefetchedRef.current) return;\n if (!initialPages || initialPages <= 1) return;\n if (query.isLoading || query.isFetching || query.isError || query.isPlaceholderData) return;\n\n const pagesLoaded = query.data?.pages.length ?? 0;\n if (pagesLoaded >= initialPages || !query.hasNextPage) {\n prefetchedRef.current = true;\n return;\n }\n\n void query.fetchNextPage();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [\n enabled,\n client,\n initialPages,\n query.isLoading,\n query.isFetching,\n query.isError,\n query.isPlaceholderData,\n query.data?.pages.length,\n query.hasNextPage,\n query.fetchNextPage,\n ]);\n\n // Memoize the flattened events so downstream consumers (filters, sorting,\n // per-card memoized values) don't recompute on every render just because a\n // new array was allocated.\n const events = useMemo(\n () => query.data?.pages.flatMap((page) => page.data) ?? [],\n [query.data?.pages],\n );\n const hasNextPage = !!query.hasNextPage;\n const loadedPageCount = query.data?.pages.length ?? 0;\n\n return {\n ...query,\n events: events as VenueEventWithMarkets[],\n hasNextPage,\n loadedPageCount,\n isPlaceholderData: query.isPlaceholderData,\n };\n}\n","import type { SportsLiveResponse, SportsLiveState } from \"@agg-build/sdk\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport { useAggClient } from \"./core/provider\";\n\nexport type {\n SportsGameStatus,\n SportsLiveParticipant,\n SportsLiveResponse,\n SportsLiveState,\n} from \"@agg-build/sdk\";\n\nexport const SPORTS_LIVE_POLL_INTERVAL_MS = 5_000;\nexport const SPORTS_SCHEDULED_POLL_INTERVAL_MS = 30_000;\n\nexport const sportsLiveQueryKey = (sortedEventIds: readonly string[]) =>\n [\"sports-live\", ...sortedEventIds] as const;\n\nexport const sportsLiveRefetchInterval = (\n response: SportsLiveResponse | undefined,\n): number | false => {\n if (!response) return false;\n if (response.data.some((state) => state.status === \"live\" || state.status === \"paused\")) {\n return SPORTS_LIVE_POLL_INTERVAL_MS;\n }\n if (response.data.some((state) => state.status === \"scheduled\")) {\n return SPORTS_SCHEDULED_POLL_INTERVAL_MS;\n }\n return false;\n};\n\nexport const useSportsLive = (eventIds: readonly string[], enabled: boolean = true) => {\n const client = useAggClient();\n const sortedEventIds = [\n ...new Set(eventIds.map((eventId) => eventId.trim()).filter(Boolean)),\n ].sort();\n\n const query = useQuery({\n queryKey: sportsLiveQueryKey(sortedEventIds),\n queryFn: ({ signal }): Promise<SportsLiveResponse> =>\n client.getSportsLive(sortedEventIds, { signal }),\n enabled: enabled && sortedEventIds.length > 0,\n refetchInterval: (queryState) => sportsLiveRefetchInterval(queryState.state.data),\n refetchIntervalInBackground: false,\n refetchOnWindowFocus: true,\n });\n\n const states = query.data?.data ?? [];\n const stateByEventId = new Map<string, SportsLiveState>(\n states.map((state) => [state.eventId, state]),\n );\n\n return {\n ...query,\n states,\n stateByEventId,\n missingEventIds: query.data?.missingEventIds ?? [],\n };\n};\n","import type { BatchMidpointsResponse, MidpointRow } from \"@agg-build/sdk\";\nimport { keepPreviousData, useQuery } from \"@tanstack/react-query\";\nimport { useAggClient, useAggUiConfig } from \"./core/provider\";\n\nconst normalizeVenueMarketIds = (venueMarketIds: string[]): string[] => {\n return [\n ...new Set(venueMarketIds.map((venueMarketId) => venueMarketId.trim()).filter(Boolean)),\n ].sort((left, right) => left.localeCompare(right));\n};\n\nconst mapMidpointsByVenueMarketId = (\n rows: Array<\n MidpointRow & {\n matched: MidpointRow[];\n }\n >,\n): Map<string, number | null> => {\n const mappedMidpoints = new Map<string, number | null>();\n\n rows.forEach((row) => {\n mappedMidpoints.set(row.venueMarketId, row.midpoint);\n\n row.matched.forEach((matchedRow) => {\n if (mappedMidpoints.has(matchedRow.venueMarketId)) return;\n mappedMidpoints.set(matchedRow.venueMarketId, matchedRow.midpoint);\n });\n });\n\n return mappedMidpoints;\n};\n\nconst mapArbReturnByVenueMarketId = (\n rows: Array<\n MidpointRow & {\n matched: MidpointRow[];\n }\n >,\n): Map<string, number | null> => {\n const mappedArbReturns = new Map<string, number | null>();\n\n rows.forEach((row) => {\n mappedArbReturns.set(row.venueMarketId, row.arbReturn ?? null);\n\n row.matched.forEach((matchedRow) => {\n if (mappedArbReturns.has(matchedRow.venueMarketId)) return;\n mappedArbReturns.set(matchedRow.venueMarketId, matchedRow.arbReturn ?? null);\n });\n });\n\n return mappedArbReturns;\n};\n\nexport interface UseVenueMarketMidpointsOptions {\n venueMarketIds: string[];\n enabled?: boolean;\n maxMidpointIdsPerRequest?: number;\n}\n\nexport function useVenueMarketMidpoints(options: UseVenueMarketMidpointsOptions) {\n const client = useAggClient();\n const {\n market: { maxMidpointIdsPerRequest: configuredMaxMidpointIdsPerRequest },\n } = useAggUiConfig();\n const enabled = options.enabled ?? true;\n const requestedVenueMarketIds = normalizeVenueMarketIds(options.venueMarketIds);\n const maxMidpointIdsPerRequest =\n options.maxMidpointIdsPerRequest ?? configuredMaxMidpointIdsPerRequest;\n\n const query = useQuery({\n queryKey: requestedVenueMarketIds.length\n ? ([\"venue-market-midpoints\", requestedVenueMarketIds, maxMidpointIdsPerRequest] as const)\n : ([\"venue-market-midpoints\", \"__disabled__\"] as const),\n queryFn: async ({ signal }) => {\n if (requestedVenueMarketIds.length === 0) {\n return { data: [] } satisfies BatchMidpointsResponse;\n }\n\n return client.getMidpoints(\n { venueMarketIds: requestedVenueMarketIds, bestPrice: true },\n { signal, maxMidpointIdsPerRequest },\n );\n },\n enabled: enabled && requestedVenueMarketIds.length > 0,\n staleTime: 10_000,\n gcTime: 5 * 60_000,\n refetchOnWindowFocus: false,\n retry: 1,\n placeholderData: keepPreviousData,\n });\n\n const midpointRows = query.data?.data ?? [];\n const midpointsByVenueMarketId = mapMidpointsByVenueMarketId(midpointRows);\n const arbReturnByVenueMarketId = mapArbReturnByVenueMarketId(midpointRows);\n\n return {\n ...query,\n midpointRows,\n midpointsByVenueMarketId,\n arbReturnByVenueMarketId,\n requestedVenueMarketIds,\n };\n}\n","import type { VenueMarket } from \"@agg-build/sdk\";\n\nexport const MIN_PRICE_GAP_PCT = 3;\nexport const MAX_PRICE_GAP_PCT = 50;\n\nexport type PriceGapValue = number;\n\nexport type ComputePriceGapsOptions = {\n markets: readonly VenueMarket[];\n midpointsByVenueMarketId: ReadonlyMap<string, number | null | undefined>;\n};\n\nconst normalizeMidpoint = (value: number | null | undefined): number | undefined => {\n if (typeof value !== \"number\" || !Number.isFinite(value)) return undefined;\n if (value <= 0) return undefined;\n if (value > 1) return undefined;\n return value;\n};\n\nconst collectMarketMidpoints = (\n market: VenueMarket,\n midpointsByVenueMarketId: ReadonlyMap<string, number | null | undefined>,\n): number[] => {\n const midpoints: number[] = [];\n const marketMidpoint = normalizeMidpoint(midpointsByVenueMarketId.get(market.id));\n\n if (marketMidpoint != null) {\n midpoints.push(marketMidpoint);\n }\n\n for (const matchedMarket of market.matchedVenueMarkets ?? []) {\n const matchedMidpoint = normalizeMidpoint(midpointsByVenueMarketId.get(matchedMarket.id));\n if (matchedMidpoint == null) continue;\n\n midpoints.push(matchedMidpoint);\n }\n\n return midpoints;\n};\n\nconst computePriceGapPct = (midpoints: readonly number[]): number | undefined => {\n if (midpoints.length < 2) return undefined;\n\n const minMidpoint = Math.min(...midpoints);\n const maxMidpoint = Math.max(...midpoints);\n if (minMidpoint <= 0 || maxMidpoint <= minMidpoint) return undefined;\n\n const gapPct = (maxMidpoint - minMidpoint) * 100;\n if (gapPct < MIN_PRICE_GAP_PCT) return undefined;\n if (gapPct > MAX_PRICE_GAP_PCT) return undefined;\n\n return gapPct;\n};\n\nexport const computePriceGaps = ({\n markets,\n midpointsByVenueMarketId,\n}: ComputePriceGapsOptions): Map<string, PriceGapValue> => {\n const gapsByVenueMarketId = new Map<string, PriceGapValue>();\n\n for (const market of markets) {\n const gapPct = computePriceGapPct(collectMarketMidpoints(market, midpointsByVenueMarketId));\n if (gapPct == null) continue;\n\n gapsByVenueMarketId.set(market.id, gapPct);\n }\n\n return gapsByVenueMarketId;\n};\n","import { useEffect, useMemo, useRef, useState } from \"react\";\nimport type { VenueMarket } from \"@agg-build/sdk\";\nimport { useAggClient, useAggUiConfig } from \"./core/provider\";\n\n/** Cached row for a single fetched venueMarketId. Per-outcome midpoints\n * come from the engine's `outcomes[]` array (own) and per matched\n * sibling's `outcomes[]` array (cross-venue alignment via MVMO). All\n * cross-venue best-price selection runs off these — no labels. */\ninterface CachedMidpoint {\n /** Primary venue that produced this row. */\n venue?: string;\n /** Per-outcome midpoints from this market's own orderbook, keyed by\n * `venueMarketOutcomeId`. */\n ownOutcomes: Map<string, number>;\n /** Matched siblings, each with their own per-outcome midpoints aligned\n * via MVMO (sibling outcome id → midpoint). */\n matched: Array<{\n venueMarketId: string;\n venue?: string;\n outcomes: Map<string, number>;\n }>;\n}\n\ntype MidpointRowWithMatches = {\n venueMarketId: string;\n venue?: string;\n outcomes?: Array<{\n venueMarketOutcomeId: string;\n midpoint: number | null;\n }>;\n matched?: Array<{\n venueMarketId: string;\n venue?: string;\n outcomes?: Array<{\n venueMarketOutcomeId: string;\n midpoint: number | null;\n }>;\n }>;\n};\n\nconst buildOutcomeMidpointMap = (\n outcomes: Array<{ venueMarketOutcomeId: string; midpoint: number | null }> | undefined,\n): Map<string, number> => {\n const m = new Map<string, number>();\n if (!outcomes) return m;\n for (const o of outcomes) {\n if (o.midpoint != null) m.set(o.venueMarketOutcomeId, o.midpoint);\n }\n return m;\n};\n\nexport const resolveUncachedVisibleMarketIds = (\n visibleMarkets: VenueMarket[],\n cache: Map<string, CachedMidpoint>,\n inFlightIds: Set<string>,\n): string[] => {\n const seen = new Set<string>();\n const idsToFetch: string[] = [];\n const consider = (id: string | undefined | null): void => {\n if (!id) return;\n if (seen.has(id)) return;\n if (inFlightIds.has(id)) return;\n if (cache.has(id)) return;\n seen.add(id);\n idsToFetch.push(id);\n };\n for (const market of visibleMarkets) {\n consider(market.id);\n // Include matched (cross-venue) sibling markets so the engine returns\n // top-of-book data for the full MVMO group. Without this the URL only\n // lists the primary venue's market ID and cross-venue best-price\n // resolution sees a half-empty book.\n for (const sibling of market.matchedVenueMarkets ?? []) {\n consider(sibling.id);\n }\n }\n return idsToFetch;\n};\n\nexport const buildCachedMidpointEntries = (\n requestedVenueMarketIds: string[],\n rows: MidpointRowWithMatches[],\n): Map<string, CachedMidpoint> => {\n const rowsByVenueMarketId = new Map(rows.map((item) => [item.venueMarketId, item]));\n const nextCacheEntries = new Map<string, CachedMidpoint>();\n\n for (const venueMarketId of requestedVenueMarketIds) {\n const item = rowsByVenueMarketId.get(venueMarketId);\n nextCacheEntries.set(venueMarketId, {\n ...(item?.venue ? { venue: item.venue } : {}),\n ownOutcomes: buildOutcomeMidpointMap(item?.outcomes),\n matched: (item?.matched ?? []).map((sib) => ({\n venueMarketId: sib.venueMarketId,\n ...(sib.venue ? { venue: sib.venue } : {}),\n outcomes: buildOutcomeMidpointMap(sib.outcomes),\n })),\n });\n }\n\n return nextCacheEntries;\n};\n\n/**\n * Fetch REST midpoints for a *dynamic* set of venue markets and cache them\n * for the hook lifetime.\n *\n * Designed for viewport-driven use cases (e.g. an IntersectionObserver-gated\n * list) where `visibleMarkets` changes as the user scrolls. Guarantees:\n *\n * • A market that was already fetched in this hook instance is **not**\n * refetched when the visible set changes — scrolling out and back in\n * reuses the cached value instead of re-hitting the network.\n * • Markets that become visible for the first time are batched into a\n * single request on the next render.\n *\n * Cross-venue best-price selection walks each parent outcome's\n * `matchedVenueMarketOutcomes` (MVMO references) and looks up the matched\n * counterpart's per-outcome midpoint. The lowest midpoint wins per\n * outcome — semantically correct for both Yes and No sides because MVMO\n * links same-side counterparts regardless of label inversion.\n */\nexport interface UseViewportMidpointsOptions {\n maxMidpointIdsPerRequest?: number;\n}\n\nexport function useViewportMidpoints(\n visibleMarkets: VenueMarket[],\n options?: UseViewportMidpointsOptions,\n): {\n prices: Map<string, number>;\n /**\n * Map of outcomeId → venue name that provided the price in `prices`.\n * Populated when a matched sibling offers a lower midpoint for the same\n * semantic side.\n */\n venueByOutcomeId: Map<string, string>;\n} {\n const client = useAggClient();\n const {\n market: { maxMidpointIdsPerRequest: configuredMaxMidpointIdsPerRequest },\n } = useAggUiConfig();\n const maxMidpointIdsPerRequest =\n options?.maxMidpointIdsPerRequest ?? configuredMaxMidpointIdsPerRequest;\n const [cache, setCache] = useState<Map<string, CachedMidpoint>>(() => new Map());\n const inFlightRef = useRef<Set<string>>(new Set());\n const visibleRef = useRef<VenueMarket[]>(visibleMarkets);\n visibleRef.current = visibleMarkets;\n\n const visibleFp = useMemo(\n () => [...new Set(visibleMarkets.map((m) => m.id))].sort().join(\"|\"),\n [visibleMarkets],\n );\n\n // Fetch only uncached ids when the visible set changes.\n useEffect(() => {\n const toFetch = resolveUncachedVisibleMarketIds(visibleRef.current, cache, inFlightRef.current);\n if (!toFetch.length) return;\n\n let cancelled = false;\n for (const id of toFetch) inFlightRef.current.add(id);\n\n client\n .getMidpoints(toFetch, { bestPrice: true, maxMidpointIdsPerRequest })\n .then((resp) => {\n if (cancelled) return;\n const nextCacheEntries = buildCachedMidpointEntries(toFetch, resp.data ?? []);\n setCache((prev) => {\n const next = new Map(prev);\n for (const [venueMarketId, entry] of nextCacheEntries) {\n next.set(venueMarketId, entry);\n }\n return next;\n });\n })\n .catch(() => {\n // Swallow: we only retry when the visible set changes.\n })\n .finally(() => {\n for (const id of toFetch) inFlightRef.current.delete(id);\n });\n\n return () => {\n cancelled = true;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [visibleFp, cache, maxMidpointIdsPerRequest]);\n\n const { prices, venueByOutcomeId } = useMemo(() => {\n const map = new Map<string, number>();\n const venueMap = new Map<string, string>();\n for (const market of visibleMarkets) {\n const entry = cache.get(market.id);\n if (!entry) continue;\n const ownVenue = entry.venue ?? market.venue;\n\n for (const outcome of market.venueMarketOutcomes) {\n // Start with this outcome's own midpoint (if any).\n let best: number | null = entry.ownOutcomes.get(outcome.id) ?? null;\n let bestVenue: string | null = best != null ? ownVenue : null;\n\n // Walk MVMO refs to compare per-outcome cross-venue midpoints.\n for (const ref of outcome.matchedVenueMarketOutcomes ?? []) {\n const sib = entry.matched.find((m) => m.venueMarketId === ref.venueMarketId);\n if (!sib) continue;\n const sibMidpoint = sib.outcomes.get(ref.venueMarketOutcomeId);\n if (sibMidpoint == null) continue;\n if (best == null || sibMidpoint < best) {\n best = sibMidpoint;\n bestVenue = sib.venue ?? bestVenue;\n }\n }\n\n if (best != null) {\n map.set(outcome.id, best);\n if (bestVenue) venueMap.set(outcome.id, bestVenue);\n }\n }\n }\n return { prices: map, venueByOutcomeId: venueMap };\n }, [cache, visibleMarkets]);\n\n return { prices, venueByOutcomeId };\n}\n","import { useCallback, useEffect, useRef, useState } from \"react\";\n\nexport interface UseVisibleIdsOptions {\n /** IntersectionObserver root margin. Expand to pre-fetch just off-screen. */\n rootMargin?: string;\n /** IntersectionObserver threshold. Default 0 (fires on any overlap). */\n threshold?: number | number[];\n}\n\nexport interface UseVisibleIdsResult {\n /** Ids whose observed elements currently intersect the viewport. */\n visibleIds: Set<string>;\n /**\n * Returns a React callback ref for the element keyed by `id`. Attach it to\n * the card's DOM root; detaching (null) removes the id from observation.\n */\n register: (id: string) => (el: Element | null) => void;\n}\n\n/**\n * Track which ids are currently visible via IntersectionObserver. Useful for\n * gating expensive per-item work (e.g. polling) to on-screen items only.\n *\n * Callers pass a stable `id` per registered element; `visibleIds` updates as\n * elements enter and leave the viewport.\n */\nexport function useVisibleIds(options: UseVisibleIdsOptions = {}): UseVisibleIdsResult {\n const { rootMargin = \"0px\", threshold = 0 } = options;\n const [visibleIds, setVisibleIds] = useState<Set<string>>(() => new Set());\n\n const observerRef = useRef<IntersectionObserver | null>(null);\n const elementsRef = useRef<Map<string, Element>>(new Map());\n const elementIdRef = useRef<WeakMap<Element, string>>(new WeakMap());\n // Cache the callback ref per id so consumers pass a *stable* ref to React.\n // Without this, `register(id)` returns a new function each call and React\n // treats every render as a ref change — detach/attach on every render keeps\n // firing the observer, which re-triggers setVisibleIds, re-renders, loops.\n const callbackRefsRef = useRef<Map<string, (el: Element | null) => void>>(new Map());\n\n useEffect(() => {\n if (typeof IntersectionObserver === \"undefined\") return;\n\n const observer = new IntersectionObserver(\n (entries) => {\n setVisibleIds((prev) => {\n let changed = false;\n const next = new Set(prev);\n for (const entry of entries) {\n const id = elementIdRef.current.get(entry.target);\n if (!id) continue;\n if (entry.isIntersecting) {\n if (!next.has(id)) {\n next.add(id);\n changed = true;\n }\n } else if (next.has(id)) {\n next.delete(id);\n changed = true;\n }\n }\n return changed ? next : prev;\n });\n },\n { rootMargin, threshold },\n );\n\n observerRef.current = observer;\n for (const el of elementsRef.current.values()) observer.observe(el);\n\n return () => {\n observer.disconnect();\n observerRef.current = null;\n };\n }, [rootMargin, threshold]);\n\n const register = useCallback((id: string) => {\n const existing = callbackRefsRef.current.get(id);\n if (existing) return existing;\n\n const callback = (el: Element | null) => {\n const prev = elementsRef.current.get(id);\n if (prev === el) return;\n\n if (prev) {\n observerRef.current?.unobserve(prev);\n elementIdRef.current.delete(prev);\n elementsRef.current.delete(id);\n setVisibleIds((curr) => {\n if (!curr.has(id)) return curr;\n const next = new Set(curr);\n next.delete(id);\n return next;\n });\n }\n\n if (el) {\n elementsRef.current.set(id, el);\n elementIdRef.current.set(el, id);\n observerRef.current?.observe(el);\n } else {\n callbackRefsRef.current.delete(id);\n }\n };\n\n callbackRefsRef.current.set(id, callback);\n return callback;\n }, []);\n\n return { visibleIds, register };\n}\n","import { useCallback, useEffect, useState } from \"react\";\nimport { useAggAuthContext } from \"./core/provider\";\nimport { useResolvedExecutionMode } from \"./use-resolved-execution-mode\";\n\nconst STORAGE_KEY = \"agg_paper_onboarding_seen\";\n\nconst isBrowser = (): boolean => typeof window !== \"undefined\" && \"localStorage\" in window;\n\n/**\n * Per-user key. Two users on one browser (shared laptop, a tester switching\n * wallets) must each get the intro once — a single global flag would silently\n * swallow it for everyone after the first.\n */\nconst seenKey = (userId: string): string => `${STORAGE_KEY}:${userId}`;\n\nconst hasSeen = (userId: string): boolean => {\n if (!isBrowser()) return false;\n try {\n return window.localStorage.getItem(seenKey(userId)) === \"1\";\n } catch {\n // Private mode / storage disabled. Treat as \"already seen\" rather than\n // \"never seen\": re-showing the intro on every page load is far worse than\n // not showing it at all.\n return true;\n }\n};\n\nconst markSeen = (userId: string): void => {\n if (!isBrowser()) return;\n try {\n window.localStorage.setItem(seenKey(userId), \"1\");\n } catch {\n // Nothing to do — worst case the user sees it again next session.\n }\n};\n\nexport interface UsePaperOnboardingResult {\n /** Whether the intro should be on screen right now. */\n isOpen: boolean;\n /** Dismiss and never show again for this user. Idempotent. */\n dismiss: () => void;\n}\n\n/**\n * Decides whether to show the paper-trading intro.\n *\n * Shown once per user, and only in a paper app. All four conditions must hold:\n *\n * 1. the app resolved to paper mode (never in a live app),\n * 2. mode resolution has finished (otherwise a live app flashes the intro\n * before `/app/config` answers),\n * 3. the user is signed in and we know who they are (the flag is per-user),\n * 4. that user has not dismissed it before.\n */\nexport function usePaperOnboarding(): UsePaperOnboardingResult {\n const { isPaperMode, isResolving } = useResolvedExecutionMode();\n const { isAuthenticated, user } = useAggAuthContext();\n const userId = user?.id;\n\n const [dismissed, setDismissed] = useState(false);\n // Read storage in an effect, not during render: localStorage is unavailable\n // during SSR, and reading it inline would desync server and client HTML.\n const [seen, setSeen] = useState<boolean | null>(null);\n\n useEffect(() => {\n if (!userId) {\n setSeen(null);\n return;\n }\n setSeen(hasSeen(userId));\n }, [userId]);\n\n // A different user signing in on the same browser gets their own showing.\n useEffect(() => {\n setDismissed(false);\n }, [userId]);\n\n const dismiss = useCallback(() => {\n setDismissed(true);\n if (userId) markSeen(userId);\n }, [userId]);\n\n const isOpen =\n isPaperMode &&\n !isResolving &&\n isAuthenticated &&\n Boolean(userId) &&\n seen === false &&\n !dismissed;\n\n return { isOpen, dismiss };\n}\n","import { useQuery } from \"@tanstack/react-query\";\nimport type { VenueMarket } from \"@agg-build/sdk\";\nimport { useAggClient } from \"./core/provider\";\n\nexport interface UseSettlementDetailsDataOptions {\n eventId: string;\n /** Omit when only the event's details (description, settlementDiff) are needed. */\n market?: Pick<VenueMarket, \"id\" | \"venue\" | \"externalIdentifier\" | \"venueEventId\">;\n enabled: boolean;\n needsEvent: boolean;\n needsMarket: boolean;\n}\n/** Demand-load full settlement text for only the visible selected market and its permitted siblings. */\nexport function useSettlementDetailsData(options: UseSettlementDetailsDataOptions) {\n const client = useAggClient();\n const { eventId, market, enabled, needsEvent, needsMarket } = options;\n const eventQuery = useQuery({\n queryKey: [\"settlement-details\", \"event\", client.appId, eventId],\n queryFn: ({ signal }) => client.getVenueEventById(eventId, { signal }),\n enabled: enabled && needsEvent,\n staleTime: 5 * 60_000,\n gcTime: 10 * 60_000,\n retry: false,\n });\n const marketQuery = useQuery({\n queryKey: [\"settlement-details\", \"market\", client.appId, market?.id],\n queryFn: async ({ signal }) => {\n if (!market) throw new Error(\"Selected market details unavailable\");\n // Use the selected market's native identity and own event when available.\n // Explicit full projection restores text even when that event id is absent;\n // the displayed event may belong to a different cluster member.\n const response = await client.getVenueMarkets(\n {\n venue: market.venue,\n venueEventId: market.venueEventId ?? undefined,\n externalIdentifier: [market.externalIdentifier],\n limit: 1,\n projection: \"full\",\n },\n { signal },\n );\n const selected = response.data.find((candidate) => candidate.id === market.id);\n if (!selected) throw new Error(\"Selected market details unavailable\");\n return { selected, markets: response.data };\n },\n enabled: enabled && needsMarket && market != null,\n staleTime: 5 * 60_000,\n gcTime: 10 * 60_000,\n retry: false,\n });\n return { eventQuery, marketQuery };\n}\n","import { useEffect, useRef, useState } from \"react\";\nimport { useMutation, useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport type { HostedVenueWithdrawal, HostedVenueWithdrawalRequest } from \"@agg-build/sdk\";\nimport { useAggAuthContext, useAggClient } from \"./core/provider\";\nimport { useResolvedExecutionMode } from \"./use-resolved-execution-mode\";\nimport { hostedVenueAccountQueryKeys } from \"./use-hosted-venue-account\";\nimport { invalidateBalanceQueries } from \"./execution/balance-invalidation\";\n\ntype Journal = { request: HostedVenueWithdrawalRequest; withdrawalId?: string };\ntype Environment = \"production\" | \"sandbox\";\nconst validRequest = (value: unknown): value is Journal => {\n const row = value as Journal | null;\n return (\n !!row &&\n row.request?.mode === \"live\" &&\n /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(\n row.request.requestId,\n ) &&\n /^[1-9][0-9]{0,31}$/.test(row.request.amountRaw) &&\n /^[1-9A-HJ-NP-Za-km-z]{32,44}$/.test(row.request.destinationAddress) &&\n (row.withdrawalId === undefined || /^[a-zA-Z0-9_-]{1,256}$/.test(row.withdrawalId))\n );\n};\n\n/** Explicit hosted transfers, bound to the current user and persisted before dispatch.\n * Reloads may read status; they never automatically submit or retry a withdrawal.\n */\nexport function useHostedVenueTransfers(accountId: string, environment: Environment) {\n const client = useAggClient();\n const { user, isAuthenticated } = useAggAuthContext();\n const { executionMode, isResolving } = useResolvedExecutionMode();\n const queryClient = useQueryClient();\n const userId = user?.id ?? null;\n const permitted = isAuthenticated && !!userId && !isResolving && executionMode === \"live\";\n const scope = JSON.stringify([userId, accountId, environment]);\n const storageKey = \"agg:betdex-withdrawal:\" + scope;\n const [entry, setEntry] = useState<{\n scope: string;\n ready: boolean;\n journal: Journal | null;\n invalid: boolean;\n }>({\n scope: \"\",\n ready: false,\n journal: null,\n invalid: false,\n });\n const session = useRef({ client, scope, permitted });\n session.current = { client, scope, permitted };\n const mounted = useRef(true);\n const dispatching = useRef(false);\n const intent = useRef<{ scope: string; journal: Journal } | null>(null);\n const current = entry.scope === scope ? entry : null;\n const journal = current?.journal ?? null;\n const assertSession = () => {\n if (\n !mounted.current ||\n !permitted ||\n !session.current.permitted ||\n session.current.client !== client ||\n session.current.scope !== scope\n )\n throw new Error(\"Hosted transfers are unavailable for this session\");\n };\n const save = (next: Journal) => {\n localStorage.setItem(storageKey, JSON.stringify(next));\n if (mounted.current && session.current.scope === scope) {\n intent.current = { scope, journal: next };\n setEntry({ scope, ready: true, journal: next, invalid: false });\n }\n };\n const assertResult = (result: { accountId: string; environment: string }) => {\n if (result.accountId !== accountId || result.environment !== environment)\n throw new Error(\"Hosted transfer identity mismatch\");\n };\n const invalidate = () => {\n void queryClient.invalidateQueries({\n queryKey: hostedVenueAccountQueryKeys.account(\"betdex\", userId, \"live\"),\n });\n invalidateBalanceQueries(queryClient);\n };\n const deposit = useMutation({\n mutationFn: async () => {\n assertSession();\n const result = await client.getHostedVenueDepositAddress(\"betdex\", { mode: \"live\" });\n assertResult(result);\n assertSession();\n return { scope, result };\n },\n retry: false,\n });\n const withdrawal = useMutation({\n mutationFn: async (request: Journal) => {\n assertSession();\n if (dispatching.current) throw new Error(\"Withdrawal request is already pending\");\n dispatching.current = true;\n try {\n // Saving must succeed before the first network request.\n save(request);\n const result = request.withdrawalId\n ? await client.getHostedVenueWithdrawal(\"betdex\", request.withdrawalId, { mode: \"live\" })\n : await client.withdrawHostedVenue(\"betdex\", request.request);\n assertResult(result);\n save({ ...request, withdrawalId: result.id });\n assertSession();\n invalidate();\n return { scope, result };\n } finally {\n dispatching.current = false;\n }\n },\n retry: false,\n });\n const status = useQuery({\n queryKey: [\"agg\", \"hosted-venue-withdrawal\", scope, journal?.withdrawalId],\n queryFn: async () => {\n assertSession();\n if (!journal?.withdrawalId) throw new Error(\"Withdrawal identity is unavailable\");\n const result = await client.getHostedVenueWithdrawal(\"betdex\", journal.withdrawalId, {\n mode: \"live\",\n });\n assertResult(result);\n assertSession();\n if (result.status === \"confirmed\" || result.status === \"failed\") invalidate();\n return result;\n },\n enabled: permitted && !!journal?.withdrawalId,\n retry: false,\n refetchInterval: (query) => (query.state.data?.status === \"processing\" ? 2000 : false),\n refetchIntervalInBackground: false,\n });\n useEffect(() => {\n mounted.current = true;\n return () => {\n mounted.current = false;\n };\n }, []);\n const resetDeposit = deposit.reset;\n const resetWithdrawal = withdrawal.reset;\n useEffect(() => {\n resetDeposit();\n resetWithdrawal();\n if (!permitted) return;\n try {\n const text = localStorage.getItem(storageKey);\n const value: unknown = text ? JSON.parse(text) : null;\n if (value !== null && !validRequest(value)) throw new Error(\"Invalid saved withdrawal\");\n intent.current = value ? { scope, journal: value as Journal } : null;\n setEntry({ scope, ready: true, journal: value as Journal | null, invalid: false });\n } catch {\n setEntry({ scope, ready: false, journal: null, invalid: true });\n }\n }, [storageKey, scope, permitted, resetDeposit, resetWithdrawal]);\n\n const result: HostedVenueWithdrawal | undefined =\n status.data ?? (withdrawal.data?.scope === scope ? withdrawal.data.result : undefined);\n const terminal = result?.status === \"confirmed\" || result?.status === \"failed\";\n return {\n isAvailable: permitted,\n ready: !!current?.ready,\n storageError: !!current?.invalid,\n deposit: { ...deposit, data: deposit.data?.scope === scope ? deposit.data.result : undefined },\n withdrawal: { ...withdrawal, data: result, isError: withdrawal.isError || status.isError },\n request: journal?.request,\n submit: async (amountRaw: string, destinationAddress: string) => {\n assertSession();\n if (!current?.ready || current.invalid || journal || intent.current?.scope === scope)\n throw new Error(\"Resolve the existing withdrawal first\");\n const request = {\n mode: \"live\" as const,\n requestId: crypto.randomUUID(),\n amountRaw,\n destinationAddress,\n };\n if (!validRequest({ request })) throw new Error(\"Invalid withdrawal request\");\n // Set the durable intent synchronously, before React renders the mutation state.\n save({ request });\n return withdrawal.mutateAsync({ request });\n },\n check: async () => {\n assertSession();\n if (!journal || !current?.ready) throw new Error(\"No saved withdrawal\");\n return withdrawal.mutateAsync(journal);\n },\n clear: () => {\n assertSession();\n if (!terminal || dispatching.current || intent.current?.journal.withdrawalId !== result?.id)\n throw new Error(\"Withdrawal is not terminal\");\n localStorage.removeItem(storageKey);\n intent.current = null;\n setEntry({ scope, ready: true, journal: null, invalid: false });\n withdrawal.reset();\n },\n };\n}\n"],"mappings":"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"}