@agg-build/hooks 4.26.1 → 4.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/deposit.d.mts +142 -138
- package/dist/deposit.d.mts.map +1 -0
- package/dist/deposit.d.ts +142 -138
- package/dist/deposit.d.ts.map +1 -0
- package/dist/deposit.js +751 -2414
- package/dist/deposit.mjs +744 -727
- package/dist/deposit.mjs.map +1 -0
- package/dist/index-CbNR3EIA.d.mts +341 -0
- package/dist/index-CbNR3EIA.d.mts.map +1 -0
- package/dist/index-CsP1jRMD.d.ts +341 -0
- package/dist/index-CsP1jRMD.d.ts.map +1 -0
- package/dist/index-D0fXU85a.d.mts +743 -0
- package/dist/index-D0fXU85a.d.mts.map +1 -0
- package/dist/index-D0fXU85a.d.ts +743 -0
- package/dist/index-D0fXU85a.d.ts.map +1 -0
- package/dist/index.d.mts +6458 -7515
- package/dist/index.d.mts.map +1 -0
- package/dist/index.d.ts +6458 -7515
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7451 -11417
- package/dist/index.mjs +7154 -5221
- package/dist/index.mjs.map +1 -0
- package/dist/use-ramp-session-7RAG9tvY.js +30 -0
- package/dist/use-ramp-session-BFWHCtuc.mjs +21 -0
- package/dist/use-ramp-session-BFWHCtuc.mjs.map +1 -0
- package/dist/use-sync-balances-BkcqInJh.mjs +1779 -0
- package/dist/use-sync-balances-BkcqInJh.mjs.map +1 -0
- package/dist/{use-sync-balances-CeD8qZWP.d.ts → use-sync-balances-CVEg__2V.d.mts} +7 -8
- package/dist/use-sync-balances-CVEg__2V.d.mts.map +1 -0
- package/dist/{use-sync-balances-CeD8qZWP.d.mts → use-sync-balances-CVEg__2V.d.ts} +7 -8
- package/dist/use-sync-balances-CVEg__2V.d.ts.map +1 -0
- package/dist/use-sync-balances-HryB8Q7F.js +1974 -0
- package/dist/withdraw--f5kYKJA.mjs +1474 -0
- package/dist/withdraw--f5kYKJA.mjs.map +1 -0
- package/dist/withdraw-BXWZYmJa.js +1591 -0
- package/dist/withdraw.d.mts +3 -351
- package/dist/withdraw.d.ts +3 -351
- package/dist/withdraw.js +10 -2229
- package/dist/withdraw.mjs +3 -20
- package/package.json +7 -6
- package/dist/chunk-JFJNW2PD.mjs +0 -5649
- package/dist/chunk-LNIAMJTZ.mjs +0 -505
- package/dist/chunk-OZQ3K47U.mjs +0 -31
- package/dist/use-deposit-addresses-B9ICS-3U.d.mts +0 -236
- package/dist/use-deposit-addresses-B9ICS-3U.d.ts +0 -236
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"withdraw--f5kYKJA.mjs","names":["CandleBuilder","MAX_BUILDERS","builders","Map","getOrCreateBuilder","marketId","existing","get","delete","set","evict","builder","getBuilder","resetAllBuilders","values","reset","size","oldest","keys","next","value","dispose","getCandleStoreDiagnostics","retainedCandles","reduce","total","const","count","interval","getClosed","length","getForming","maxBuilders","OrderbookState","WsTrade","MAX_TRADES","OrderbookUpdateSource","MarketLiveState","marketId","orderbook","orderbookSnapshotVersion","orderbookError","trades","isConnected","integrity","createMarketLiveState","overrides","Partial","withLiveConnectionState","data","withLiveOrderbook","source","current","withLiveOrderbookError","withLiveIntegrity","withLiveTrade","trade","outcomeId","slice","WsCandleInterval","marketDataKeys","all","const","live","marketId","livePrefix","orderbook","selectionKey","depth","orderbookPrefix","orderbookQuote","side","size","chart","interval","rangeKey","countBack","chartPrefix","useMemo","useSyncExternalStore","useQueryClient","QueryClient","CandleTail","createMarketLiveState","MarketLiveState","marketDataKeys","LiveSnapshot","connectionGeneration","orderbookGeneration","candles","receivedAtMs","LIVE_RETENTION","maxInactiveSnapshots","maxInactiveLevels","inactiveTtlMs","maxEntries","const","levelEntries","state","book","orderbook","bids","length","asks","Object","values","venueOrderbooks","reduce","n","venue","hasSnapshot","trades","MarketLiveStore","connectionState","states","Map","listeners","Set","touched","timer","ReturnType","setTimeout","needsPrune","constructor","seed","id","ensure","get","has","Date","now","drop","undefined","isConnected","set","prune","peek","getMany","ids","result","map","update","updater","previous","next","bookChanged","seq","checksum","timestamp","orderbookSnapshotVersion","listener","connected","keys","subscribe","add","delete","size","getDiagnostics","inactive","filter","entries","activeEntries","cachedBooks","cachedLevelEntries","inactiveSnapshots","inactiveLevelEntries","limits","protectedIds","clearTimeout","sort","a","b","count","levels","nextExpiry","Infinity","Math","min","Number","isFinite","max","stores","WeakMap","getMarketLiveStore","client","store","getQueryData","live","useLiveStates","Array","data","key","JSON","stringify","selector","selectedIds","parse","every","entry","index","mergeCandleTails","fromEntries","interval","oldClosed","closed","incoming","candle","openTime","slice","forming","MarketResolutionInput","outcomeId","status","outcomes","Array","label","winner","externalIdentifier","isRecord","value","Record","NESTED_COLLECTION_FIELDS","const","marketContainsOutcomeId","market","venueMarketOutcomes","isArray","some","outcome","id","cachedDataContainsOutcomeId","data","entry","field","normalizeLabel","trim","toLowerCase","findResolvedOutcome","resolvedOutcomes","length","matchedByExternalId","find","resolved","applyWinnersToOutcomes","resolution","changed","next","map","nextWinner","applyResolutionToMarket","nextOutcomes","statusChanged","applyResolutionToCachedData","updated","QueryClient","MarketChartData","marketDataKeys","DEFAULT_HISTORY_RETENTION","maxInactiveQueries","maxInactivePoints","const","HistoryRetentionLimits","Owner","refs","clock","touched","Map","evicted","queued","pruning","limits","unsubscribe","prune","owners","WeakMap","isHistory","key","points","data","chart","Partial","venues","Object","values","reduce","total","venue","candles","length","liveCandle","getChartHistoryRetentionStats","client","queries","getQueryCache","findAll","queryKey","chartPrefix","active","filter","query","getObserversCount","inactive","owner","get","activeQueries","inactiveQueries","activePoints","sum","state","inactivePoints","inFlightQueries","fetchStatus","trackedQueries","size","evictedQueries","installChartHistoryRetention","Date","now","set","current","sort","a","b","queryHash","dataUpdatedAt","count","totalPoints","delete","removeQueries","exact","schedule","queueMicrotask","subscribe","event","type","Math","max","released","createContext","useCallback","useContext","useEffect","useMemo","useRef","useState","ReactNode","useQueryClient","AggWebSocket","AggWebSocketCallbacks","DiagnosticEvent","WsBalanceUpdate","WsMarketResolved","WsOrderEvent","WsOrderSubmitted","WsRedeemEvent","WsWithdrawalLifecycleEvent","createMarketLiveState","withLiveIntegrity","withLiveOrderbook","withLiveOrderbookError","withLiveTrade","getMarketLiveStore","mergeCandleTails","getOrCreateBuilder","resetAllBuilders","getCandleStoreDiagnostics","applyResolutionToCachedData","cachedDataContainsOutcomeId","installChartHistoryRetention","getChartHistoryRetentionStats","marketDataKeys","invalidateBalanceQueries","invalidatePositionQueries","invalidateUserActivityQueries","shouldInvalidateBalancesForOrderEvent","useAggClient","useAggUiConfig","AggWebSocketContext","AggWebSocketConnectionContext","WsUserEventListeners","addOrderSubmittedListener","cb","msg","addBalanceUpdateListener","addOrderEventListener","addRedeemEventListener","addWithdrawalLifecycleListener","AggWsUserEventContext","snapshotUnavailableOutcomeIdPattern","resolveSnapshotUnavailableOutcomeId","errorMessage","matchedOutcomeId","exec","replace","useAggWebSocket","useAggWebSocketConnectionState","useWsUserEventListeners","useOnOrderSubmitted","callback","listeners","callbackRef","current","hasCallback","handler","useOnBalanceUpdate","useOnOrderEvent","useOnRedeemEvent","useOnWithdrawalLifecycle","WsProviderProps","children","AggWebSocketProvider","React","JSX","Element","client","enableWebsocketsLogs","queryClient","liveStore","ws","setWs","isConnected","setIsConnected","isClientAuthenticated","setIsClientAuthenticated","isAuthenticated","wsRef","resyncDeadlineByMarketRef","Map","lastBalanceInvalidationAtRef","onAuthStateChange","authenticated","orderSubmittedListenersRef","Set","balanceUpdateListenersRef","orderEventListenersRef","redeemEventListenersRef","withdrawalLifecycleListenersRef","userEventListeners","add","delete","syncLiveQuery","marketId","updater","previous","ReturnType","update","invalidateBalanceCaches","now","Date","invalidatePositionCaches","invalidateActivityCaches","invalidateResolutionCaches","resolution","outcomeId","orderbook","orderbookSnapshotVersion","orderbookError","integrity","affectedQueries","getQueryCache","findAll","predicate","query","state","data","setQueryData","queryKey","invalidateQueries","refetchType","publishLocalCandles","id","builder","candles","Object","fromEntries","const","map","interval","forming","getForming","closed","getClosed","slice","CandleTail","callbacks","onMarketView","view","book","snapshot","receivedAtMs","trades","replaceTail","onSnapshot","processesCandles","midpoint","addMidpoint","timestamp","onDelta","onTrade","trade","addTrade","price","size","onHeartbeat","forEach","deadline","resnapshot","set","onDiagnostics","event","type","onOrderSubmitted","listener","onBalanceUpdate","onOrderEvent","currentUserId","user","onRedeemEvent","onWithdrawalLifecycle","onMarketResolved","onError","message","onConnectionStateChange","connected","chartPrefix","callbacksRef","setCallbacks","instance","resyncDeadlineByMarket","createWebSocket","enableLogs","console","warn","setHostDiagnostics","live","getDiagnostics","history","destroy","clear","useMutation","useQueryClient","WithdrawManagedParams","WithdrawManagedResponse","useAggClient","invalidateUserMoneyState","UseWithdrawManagedOptions","onSuccess","data","onError","error","Error","useWithdrawManaged","options","client","queryClient","mutationFn","params","withdrawManaged","useQuery","useAggClient","executionKeys","UseManagedBalancesOptions","enabled","mode","custody","useManagedBalances","options","client","params","query","queryKey","balances","queryFn","getManagedBalances","Object","keys","length","undefined","staleTime","refetchInterval","refetchIntervalInBackground","gcTime","retry","data","useCallback","useEffect","useMemo","useState","WithdrawTokenSymbol","useAggBalanceState","useAggWebSocket","useDepositAddresses","useManagedBalances","useSyncBalances","useWithdrawManaged","WithdrawSelectOption","value","label","disabled","DestinationAddressKind","WithdrawSummary","amountReceived","network","toWallet","fees","EVM_ADDRESS_REGEX","SOLANA_ADDRESS_REGEX","SOLANA_CHAIN_ID","WITHDRAWAL_SUPPORTED_CHAIN_IDS","Set","isValidDestinationAddress","address","chainId","test","detectDestinationAddressKind","trimmed","trim","UseWithdrawFlowResult","open","onOpenChange","withdrawFlow","balance","balanceDisplay","amount","destinationWallet","tokenOptions","networkOptions","selectedToken","selectedNetwork","purchaseSummary","withdrawalId","isMax","onWithdrawDestinationChange","onWithdrawAmountChange","onWithdrawTokenChange","token","onWithdrawNetworkChange","onMaxClick","onSelectWithdrawProvider","providerId","Promise","onDoneWithdraw","UseWithdrawFlowOptions","DEFAULT_WITHDRAW_SUMMARY","formatRawTokenAmount","rawAmount","decimals","raw","BigInt","divisor","repeat","whole","remainder","toString","padStart","replace","formatRawTokenAmountForDisplay","fractionDigits","wholePart","fractionalPart","split","normalizedFraction","padEnd","slice","parseTokenAmountToRaw","normalizedAmount","length","normalizedWhole","shortenAddress","useWithdrawFlow","options","totalBalance","balances","enabled","supportedChains","withdrawMutation","syncBalances","ws","mutate","undefined","onError","withdrawDestination","setWithdrawDestination","withdrawAmount","setWithdrawAmount","withdrawToken","setWithdrawToken","withdrawNetwork","setWithdrawNetwork","withdrawSummary","setWithdrawSummary","setWithdrawalId","setIsMax","detectedAddressKind","filter","chain","has","map","String","isSolana","name","firstEnabledNetwork","find","option","isCurrentNetworkSelectable","some","resolvedWithdrawNetwork","selectedChainId","Number","supportedTokensForNetwork","tokens","withdrawableSymbols","symbol","cash","cashEntry","tokenSymbol","resolvedWithdrawToken","selectedCashEntry","selectedTokenDecimals","exactBalance","totalRaw","resetFlowState","handleWithdrawOpenChange","isOpen","handleWithdrawProvider","destinationChainId","trimmedDestination","amountRaw","Error","isFinite","expected","scaleBy","n","exp","balanceInDestFrame","native","connect","resolve","reject","destinationAddress","max","onSuccess","data","v","_providerId","useMemo","WithdrawFeeEstimate","estimatedFees","networkReserve","youReceive","UseWithdrawEstimateParams","amount","selectedToken","selectedNetwork","useWithdrawEstimate","numAmount","Number","isNaN","network","toLowerCase","feeVal","reserveVal","youReceiveVal","Math","max","toFixed","useCallback","useEffect","useMemo","useRef","useState","useQueryClient","WithdrawalLeg","WithdrawManagedResponse","WithdrawManagedSourceItem","WsWithdrawalLifecycleEvent","WsWithdrawalLifecycleLeg","WsWithdrawalLifecycleStatus","useAggClient","useAggWebSocketConnectionState","useOnWithdrawalLifecycle","invalidateUserMoneyState","WithdrawalLifecycleState","pending","status","requestedAmountRaw","completedAmountRaw","feeRaw","terminal","lastLeg","legs","errorMessage","timestamp","INITIAL_STATE","restLegToWsLeg","leg","sourceChainId","destChainId","type","amountRaw","txHash","bridgeOperationId","mergeLegs","prev","snapshot","delta","idx","findIndex","l","next","slice","restToLifecycleState","response","requested","expected","map","UseWithdrawalLifecycleResult","state","reset","useWithdrawalLifecycle","withdrawalId","client","wsConnected","queryClient","setState","stateRef","current","balanceRefetchedForRef","cancelled","getWithdrawalStatus","wsAlreadyWon","handler","msg","syncManagedBalances","catch","useQuery","WithdrawPreviewParams","WithdrawPreviewResponse","useAggClient","UseWithdrawPreviewParams","amountRaw","tokenSymbol","destinationChainId","destinationAddress","max","useWithdrawPreview","client","enabled","BigInt","queryKey","staleTime","queryFn","withdrawPreview"],"sources":["../src/candle-store.ts","../src/market-data/live-cache.ts","../src/market-data/query-keys.ts","../src/market-data/live-store.ts","../src/market-data/market-resolution-cache.ts","../src/market-data/history-retention.ts","../src/core/providers/ws-provider.tsx","../src/execution/use-withdraw-managed.ts","../src/execution/use-managed-balances.ts","../src/withdraw/use-withdraw-flow.ts","../src/withdraw/use-withdraw-estimate.ts","../src/withdraw/use-withdrawal-lifecycle.ts","../src/withdraw/use-withdraw-preview.ts"],"sourcesContent":["import { CandleBuilder } from \"@agg-build/sdk\";\n\nconst MAX_BUILDERS = 60;\nconst builders = new Map<string, CandleBuilder>();\n\n/**\n * LRU-bounded store for per-market CandleBuilders.\n * Fed from WS provider (onDelta/onSnapshot/onTrade).\n * Read from useLiveCandles and SDK-only partners.\n */\nexport function getOrCreateBuilder(marketId: string): CandleBuilder {\n const existing = builders.get(marketId);\n if (existing) {\n // Touch: move to end (most recently used)\n builders.delete(marketId);\n builders.set(marketId, existing);\n return existing;\n }\n\n evict();\n const builder = new CandleBuilder();\n builders.set(marketId, builder);\n return builder;\n}\n\nexport function getBuilder(marketId: string): CandleBuilder | undefined {\n return builders.get(marketId);\n}\n\nexport function resetAllBuilders(): void {\n for (const builder of builders.values()) {\n builder.reset();\n }\n}\n\nfunction evict(): void {\n if (builders.size < MAX_BUILDERS) return;\n const oldest = builders.keys().next().value;\n if (oldest) {\n builders.get(oldest)?.dispose();\n builders.delete(oldest);\n }\n}\n\n/** On-demand counts only; no candle arrays escape through diagnostics. */\nexport function getCandleStoreDiagnostics() {\n return {\n builders: builders.size,\n retainedCandles: [...builders.values()].reduce(\n (total, builder) =>\n total +\n ([\"1m\", \"5m\", \"1h\", \"1d\"] as const).reduce(\n (count, interval) =>\n count + builder.getClosed(interval).length + (builder.getForming(interval) ? 1 : 0),\n 0,\n ),\n 0,\n ),\n maxBuilders: MAX_BUILDERS,\n };\n}\n","import type { OrderbookState, WsTrade } from \"@agg-build/sdk\";\n\nconst MAX_TRADES = 50;\n\nexport type OrderbookUpdateSource = \"snapshot\" | \"delta\";\n\nexport interface MarketLiveState {\n marketId: string;\n orderbook: OrderbookState | null;\n orderbookSnapshotVersion: number;\n orderbookError: string | null;\n trades: WsTrade[];\n isConnected: boolean;\n integrity: \"ok\" | \"resyncing\";\n}\n\nexport const createMarketLiveState = (\n marketId: string,\n overrides?: Partial<MarketLiveState>,\n): MarketLiveState => ({\n marketId,\n orderbook: null,\n orderbookSnapshotVersion: 0,\n orderbookError: null,\n trades: [],\n isConnected: false,\n integrity: \"ok\",\n ...overrides,\n});\n\nexport const withLiveConnectionState = (\n data: MarketLiveState | null | undefined,\n isConnected: boolean,\n): MarketLiveState | null | undefined => {\n if (!data) return data;\n if (data.isConnected === isConnected) return data;\n\n return {\n ...data,\n isConnected,\n };\n};\n\nexport const withLiveOrderbook = (\n data: MarketLiveState | null | undefined,\n orderbook: OrderbookState,\n source: OrderbookUpdateSource,\n): MarketLiveState => {\n const current = data ?? createMarketLiveState(orderbook.marketId);\n\n return {\n ...current,\n orderbook,\n orderbookSnapshotVersion:\n source === \"snapshot\"\n ? current.orderbookSnapshotVersion + 1\n : current.orderbookSnapshotVersion,\n orderbookError: null,\n integrity: \"ok\",\n };\n};\n\nexport const withLiveOrderbookError = (\n data: MarketLiveState | null | undefined,\n marketId: string,\n orderbookError: string,\n): MarketLiveState => {\n const current = data ?? createMarketLiveState(marketId);\n\n if (current.orderbookError === orderbookError && current.marketId === marketId) {\n return current;\n }\n\n return {\n ...current,\n marketId,\n orderbookError,\n };\n};\n\nexport const withLiveIntegrity = (\n data: MarketLiveState | null | undefined,\n integrity: \"ok\" | \"resyncing\",\n): MarketLiveState | null | undefined => {\n if (!data) return data;\n if (data.integrity === integrity) return data;\n\n return {\n ...data,\n integrity,\n };\n};\n\nexport const withLiveTrade = (\n data: MarketLiveState | null | undefined,\n trade: WsTrade,\n): MarketLiveState => {\n const current = data ?? createMarketLiveState(trade.outcomeId);\n const trades = [trade, ...current.trades].slice(0, MAX_TRADES);\n\n return {\n ...current,\n trades,\n };\n};\n","import type { WsCandleInterval } from \"@agg-build/sdk\";\n\nexport const marketDataKeys = {\n all: () => [\"market-data\"] as const,\n live: (marketId: string) => [\"market-data\", \"live\", marketId] as const,\n livePrefix: () => [\"market-data\", \"live\"] as const,\n orderbook: (marketId: string, selectionKey?: string | null, depth?: number) =>\n [\"market-data\", \"orderbook\", marketId, selectionKey ?? null, depth ?? null] as const,\n orderbookPrefix: (marketId?: string) =>\n marketId == null\n ? ([\"market-data\", \"orderbook\"] as const)\n : ([\"market-data\", \"orderbook\", marketId] as const),\n orderbookQuote: (marketId: string, side: \"buy\" | \"sell\", size: number) =>\n [\"market-data\", \"orderbook-quote\", marketId, side, size] as const,\n /**\n * Stable per `{marketId, interval, rangeKey}`. Deliberately excludes the\n * concrete `startTs`/`endTs` of the rolling window — those advance every\n * candle bucket, and including them would mint a fresh key on every\n * rollover, defeating React Query's cache on tab/page revisits. The\n * current window is passed to `queryFn` via closure instead, and\n * `refetchInterval` advances the data under the stable key.\n */\n chart: (\n marketId: string,\n interval: WsCandleInterval,\n rangeKey: string,\n countBack?: number | null,\n ) => [\"market-data\", \"chart\", marketId, interval, rangeKey, countBack ?? null] as const,\n chartPrefix: (marketId?: string, interval?: WsCandleInterval) => {\n if (!marketId) return [\"market-data\", \"chart\"] as const;\n if (!interval) return [\"market-data\", \"chart\", marketId] as const;\n return [\"market-data\", \"chart\", marketId, interval] as const;\n },\n};\n","import { useMemo, useSyncExternalStore } from \"react\";\nimport { useQueryClient, type QueryClient } from \"@tanstack/react-query\";\nimport type { CandleTail } from \"@agg-build/sdk\";\nimport { createMarketLiveState, type MarketLiveState } from \"./live-cache\";\nimport { marketDataKeys } from \"./query-keys\";\n\nexport interface LiveSnapshot extends MarketLiveState {\n /** Local socket generation; sequences are only comparable inside one generation. */\n connectionGeneration?: number;\n orderbookGeneration?: number;\n candles?: CandleTail;\n receivedAtMs?: number;\n}\nexport const LIVE_RETENTION = {\n maxInactiveSnapshots: 32,\n maxInactiveLevels: 16_384,\n inactiveTtlMs: 5000,\n maxEntries: 300,\n} as const;\nconst levelEntries = (state: LiveSnapshot): number => {\n const book = state.orderbook;\n return book\n ? (book.bids?.length ?? 0) +\n (book.asks?.length ?? 0) +\n Object.values(book.venueOrderbooks ?? {}).reduce(\n (n, venue) => n + venue.bids.length + venue.asks.length,\n 0,\n )\n : 0;\n};\nconst hasSnapshot = (state: LiveSnapshot): boolean =>\n !!state.orderbook || !!state.candles || state.trades.length > 0;\n\n/** Stable per-outcome snapshots; inactive depth is bounded separately from active subscribers. */\nexport class MarketLiveStore {\n private connectionState = false;\n private connectionGeneration = 0;\n private states = new Map<string, LiveSnapshot>();\n private listeners = new Map<string, Set<() => void>>();\n private touched = new Map<string, number>();\n private timer?: ReturnType<typeof setTimeout>;\n private needsPrune = false;\n constructor(private readonly seed?: (id: string) => MarketLiveState | undefined) {}\n private ensure(id: string): LiveSnapshot {\n let state = this.states.get(id);\n if (\n state &&\n !this.listeners.has(id) &&\n Date.now() - (this.touched.get(id) ?? 0) >= LIVE_RETENTION.inactiveTtlMs\n ) {\n this.drop(id);\n state = undefined;\n }\n if (!state) {\n const seed = this.seed?.(id);\n state = {\n ...createMarketLiveState(id, { isConnected: this.connectionState, ...seed }),\n connectionGeneration: this.connectionGeneration,\n orderbookGeneration: seed?.orderbook ? -1 : this.connectionGeneration,\n };\n this.states.set(id, state);\n this.touched.set(id, Date.now());\n this.needsPrune = true;\n }\n return state;\n }\n get(id: string): LiveSnapshot {\n const state = this.ensure(id);\n this.touched.set(id, Date.now());\n if (this.needsPrune) this.prune(new Set([id]));\n return state;\n }\n /** Read retained data without creating a state, keeping it alive, or observing updates. */\n peek(id: string): LiveSnapshot | undefined {\n if (\n !this.listeners.has(id) &&\n Date.now() - (this.touched.get(id) ?? 0) >= LIVE_RETENTION.inactiveTtlMs\n )\n return undefined;\n return this.states.get(id);\n }\n /** Protect a render's whole selection before useSyncExternalStore subscribes. */\n getMany(ids: string[]): LiveSnapshot[] {\n const result = ids.map((id) => {\n const state = this.ensure(id);\n this.touched.set(id, Date.now());\n return state;\n });\n if (this.needsPrune) this.prune(new Set(ids));\n return result;\n }\n update(id: string, updater: (previous: LiveSnapshot) => LiveSnapshot | null | undefined): void {\n const previous = this.ensure(id);\n const next = updater(previous);\n if (!next || next === previous) return;\n const bookChanged =\n next.orderbook &&\n (!previous.orderbook ||\n next.orderbook.seq !== previous.orderbook.seq ||\n next.orderbook.checksum !== previous.orderbook.checksum ||\n next.orderbook.timestamp !== previous.orderbook.timestamp ||\n next.orderbookSnapshotVersion !== previous.orderbookSnapshotVersion);\n this.states.set(\n id,\n bookChanged ? { ...next, orderbookGeneration: this.connectionGeneration } : next,\n );\n if (bookChanged || next.candles !== previous.candles || next.trades !== previous.trades)\n this.touched.set(id, Date.now());\n for (const listener of this.listeners.get(id) ?? []) listener();\n if (!this.listeners.has(id) || this.needsPrune) this.prune(new Set([id]));\n }\n connected(connected: boolean): void {\n if (connected && !this.connectionState) this.connectionGeneration++;\n this.connectionState = connected;\n for (const id of [...this.states.keys()])\n this.update(id, (state) =>\n state.isConnected === connected && state.connectionGeneration === this.connectionGeneration\n ? state\n : {\n ...state,\n isConnected: connected,\n connectionGeneration: this.connectionGeneration,\n ...(connected ? {} : { candles: undefined }),\n },\n );\n }\n subscribe(ids: string[], listener: () => void): () => void {\n for (const id of ids) {\n const set = this.listeners.get(id) ?? new Set();\n set.add(listener);\n this.listeners.set(id, set);\n this.touched.set(id, Date.now());\n }\n return () => {\n for (const id of ids) {\n const set = this.listeners.get(id);\n set?.delete(listener);\n if (!set?.size) {\n this.listeners.delete(id);\n this.touched.set(id, Date.now());\n }\n }\n this.prune();\n };\n }\n getDiagnostics() {\n const inactive = [...this.states].filter(([id]) => !this.listeners.has(id));\n return {\n entries: this.states.size,\n activeEntries: this.listeners.size,\n cachedBooks: [...this.states.values()].filter((state) => state.orderbook).length,\n cachedLevelEntries: [...this.states.values()].reduce(\n (n, state) => n + levelEntries(state),\n 0,\n ),\n inactiveSnapshots: inactive.filter(([, state]) => hasSnapshot(state)).length,\n inactiveLevelEntries: inactive.reduce((n, [, state]) => n + levelEntries(state), 0),\n limits: LIVE_RETENTION,\n };\n }\n private drop(id: string): void {\n this.states.delete(id);\n this.touched.delete(id);\n }\n private prune(protectedIds = new Set<string>()): void {\n this.needsPrune = false;\n if (this.timer) clearTimeout(this.timer);\n this.timer = undefined;\n const now = Date.now();\n const inactive = [...this.states]\n .filter(([id]) => !this.listeners.has(id) && !protectedIds.has(id))\n .sort(([a], [b]) => (this.touched.get(a) ?? 0) - (this.touched.get(b) ?? 0));\n let count = inactive.filter(([, state]) => hasSnapshot(state)).length;\n let levels = inactive.reduce((n, [, state]) => n + levelEntries(state), 0);\n for (const [id, state] of inactive) {\n if (\n now - (this.touched.get(id) ?? 0) >= LIVE_RETENTION.inactiveTtlMs ||\n this.states.size > LIVE_RETENTION.maxEntries ||\n count > LIVE_RETENTION.maxInactiveSnapshots ||\n levels > LIVE_RETENTION.maxInactiveLevels\n ) {\n if (hasSnapshot(state)) count--;\n levels -= levelEntries(state);\n this.drop(id);\n }\n }\n let nextExpiry = Infinity;\n for (const id of this.states.keys())\n if (!this.listeners.has(id))\n nextExpiry = Math.min(\n nextExpiry,\n (this.touched.get(id) ?? now) + LIVE_RETENTION.inactiveTtlMs,\n );\n if (Number.isFinite(nextExpiry))\n this.timer = setTimeout(\n () => {\n this.timer = undefined;\n this.prune();\n },\n Math.max(1, nextExpiry - now),\n );\n }\n}\nconst stores = new WeakMap<QueryClient, MarketLiveStore>();\nexport function getMarketLiveStore(client: QueryClient): MarketLiveStore {\n let store = stores.get(client);\n if (!store) {\n store = new MarketLiveStore((id) => client.getQueryData?.(marketDataKeys.live(id)));\n stores.set(client, store);\n }\n return store;\n}\nexport function useLiveStates(ids: string[]): Array<{ data: LiveSnapshot }> {\n const client = useQueryClient();\n const store = getMarketLiveStore(client);\n const key = JSON.stringify(ids);\n const selector = useMemo(() => {\n const selectedIds = JSON.parse(key) as string[];\n let previous: Array<{ data: LiveSnapshot }> = [];\n return {\n subscribe: (listener: () => void) => store.subscribe(selectedIds, listener),\n get: () => {\n const next = store.getMany(selectedIds).map((data) => ({ data }));\n if (\n next.length === previous.length &&\n next.every((entry, index) => entry.data === previous[index]?.data)\n )\n return previous;\n previous = next;\n return next;\n },\n };\n }, [key, store]);\n return useSyncExternalStore(selector.subscribe, selector.get, selector.get);\n}\n\n/** Keep acknowledged closed tails until REST history catches up; empty batches never erase them. */\nexport function mergeCandleTails(previous: CandleTail | undefined, next: CandleTail): CandleTail {\n return Object.fromEntries(\n ([\"1m\", \"5m\", \"1h\", \"1d\"] as const).map((interval) => {\n const oldClosed = previous?.[interval].closed ?? [];\n const incoming = next[interval].closed;\n const closed = incoming.length\n ? [\n ...new Map(\n [...oldClosed, ...incoming].map((candle) => [candle.openTime, candle]),\n ).values(),\n ]\n .sort((a, b) => a.openTime - b.openTime)\n .slice(-500)\n : oldClosed;\n return [interval, { forming: next[interval].forming, closed }];\n }),\n ) as CandleTail;\n}\n","/**\n * Pure helpers for applying a `market_resolved` WebSocket event to the various\n * React Query caches that embed venue-market data (event detail, event lists,\n * search results, venue-event/venue-markets, infinite-query pages …).\n *\n * Query data is untyped at this layer — any cache surface can hold markets in a\n * different shape — so these walk the known container fields defensively and\n * preserve referential equality for every untouched branch (so an unrelated\n * market in the same event list never re-renders on someone else's\n * resolution).\n */\n\n/** Minimal shape of a `WsMarketResolved` payload these helpers consume. */\nexport interface MarketResolutionInput {\n /** Internal venue-market-outcome id (matches `outcome.id`) that resolved. */\n outcomeId: string;\n /** Terminal market status the venue reported. */\n status: \"resolved\" | \"closed\";\n /** Per-outcome winner data, keyed by external id or label to local outcomes. */\n outcomes: Array<{\n label?: string | null;\n winner?: boolean;\n externalIdentifier?: string | null;\n }>;\n}\n\nconst isRecord = (value: unknown): value is Record<string, unknown> => {\n return typeof value === \"object\" && value !== null;\n};\n\nconst NESTED_COLLECTION_FIELDS = [\"pages\", \"data\", \"markets\", \"events\", \"venueMarkets\"] as const;\n\nconst marketContainsOutcomeId = (market: unknown, outcomeId: string): boolean => {\n if (!isRecord(market)) return false;\n\n const outcomes = market.venueMarketOutcomes;\n if (!Array.isArray(outcomes)) return false;\n\n return outcomes.some((outcome) => isRecord(outcome) && outcome.id === outcomeId);\n};\n\n/**\n * Deep-search arbitrary query data for a venue market that holds `outcomeId`.\n * Used both to decide which cached queries to optimistically patch and as the\n * `invalidateQueries` predicate.\n */\nexport const cachedDataContainsOutcomeId = (data: unknown, outcomeId: string): boolean => {\n if (Array.isArray(data)) {\n return data.some((entry) => cachedDataContainsOutcomeId(entry, outcomeId));\n }\n\n if (!isRecord(data)) return false;\n if (marketContainsOutcomeId(data, outcomeId)) return true;\n\n return NESTED_COLLECTION_FIELDS.some((field) => {\n const value = data[field];\n return (\n Array.isArray(value) && value.some((entry) => cachedDataContainsOutcomeId(entry, outcomeId))\n );\n });\n};\n\nconst normalizeLabel = (label: unknown): string => {\n return typeof label === \"string\" ? label.trim().toLowerCase() : \"\";\n};\n\n/**\n * Match a local outcome to the resolution payload by external identifier first\n * (authoritative on-chain token id) then by label — the WS event carries\n * `externalIdentifier`/`label`, never the internal `id` per outcome.\n */\nconst findResolvedOutcome = (\n resolvedOutcomes: MarketResolutionInput[\"outcomes\"],\n outcome: Record<string, unknown>,\n): MarketResolutionInput[\"outcomes\"][number] | null => {\n const externalIdentifier = outcome.externalIdentifier;\n if (typeof externalIdentifier === \"string\" && externalIdentifier.length > 0) {\n const matchedByExternalId = resolvedOutcomes.find(\n (resolved) => resolved.externalIdentifier === externalIdentifier,\n );\n if (matchedByExternalId) return matchedByExternalId;\n }\n\n const label = normalizeLabel(outcome.label);\n if (label) {\n return resolvedOutcomes.find((resolved) => normalizeLabel(resolved.label) === label) ?? null;\n }\n\n return null;\n};\n\nconst applyWinnersToOutcomes = (\n outcomes: unknown[],\n resolution: MarketResolutionInput,\n): unknown[] => {\n let changed = false;\n\n const next = outcomes.map((outcome) => {\n if (!isRecord(outcome)) return outcome;\n\n const resolved = findResolvedOutcome(resolution.outcomes, outcome);\n if (!resolved) return outcome;\n\n const nextWinner = resolved.winner === true;\n if (outcome.winner === nextWinner) return outcome;\n\n changed = true;\n return { ...outcome, winner: nextWinner };\n });\n\n return changed ? next : outcomes;\n};\n\nconst applyResolutionToMarket = (\n market: Record<string, unknown>,\n resolution: MarketResolutionInput,\n): Record<string, unknown> => {\n const outcomes = market.venueMarketOutcomes;\n if (!Array.isArray(outcomes)) return market;\n\n // Only the market that actually holds the resolved outcome flips — sibling\n // markets in the same event resolve via their own events.\n if (!outcomes.some((outcome) => isRecord(outcome) && outcome.id === resolution.outcomeId)) {\n return market;\n }\n\n const nextOutcomes = applyWinnersToOutcomes(outcomes, resolution);\n const statusChanged = market.status !== resolution.status;\n\n if (!statusChanged && nextOutcomes === outcomes) return market;\n\n return { ...market, status: resolution.status, venueMarketOutcomes: nextOutcomes };\n};\n\n/**\n * Return a structurally-shared copy of `data` with the resolved market marked\n * `status: resolved|closed` and its outcomes' `winner` flags stamped from the\n * WS payload. Untouched branches keep their original reference (no spurious\n * re-renders). Returns the original `data` when nothing matched.\n */\nexport const applyResolutionToCachedData = (\n data: unknown,\n resolution: MarketResolutionInput,\n): unknown => {\n if (Array.isArray(data)) {\n let changed = false;\n const next = data.map((entry) => {\n const updated = applyResolutionToCachedData(entry, resolution);\n if (updated !== entry) changed = true;\n return updated;\n });\n return changed ? next : data;\n }\n\n if (!isRecord(data)) return data;\n\n if (Array.isArray(data.venueMarketOutcomes)) {\n return applyResolutionToMarket(data, resolution);\n }\n\n let changed = false;\n const next: Record<string, unknown> = { ...data };\n\n for (const field of NESTED_COLLECTION_FIELDS) {\n const value = data[field];\n if (!Array.isArray(value)) continue;\n\n const updated = applyResolutionToCachedData(value, resolution);\n if (updated !== value) {\n next[field] = updated;\n changed = true;\n }\n }\n\n return changed ? next : data;\n};\n","import type { QueryClient } from \"@tanstack/react-query\";\nimport type { MarketChartData } from \"./chart-cache\";\nimport { marketDataKeys } from \"./query-keys\";\n\nexport const DEFAULT_HISTORY_RETENTION = {\n maxInactiveQueries: 16,\n maxInactivePoints: 20_000,\n} as const;\nexport interface HistoryRetentionLimits {\n maxInactiveQueries: number;\n maxInactivePoints: number;\n}\ntype Owner = {\n refs: number;\n clock: number;\n touched: Map<string, number>;\n evicted: number;\n queued: boolean;\n pruning: boolean;\n limits: HistoryRetentionLimits;\n unsubscribe: () => void;\n prune: () => void;\n};\nconst owners = new WeakMap<QueryClient, Owner>();\nconst isHistory = (key: readonly unknown[]) => key[0] === \"market-data\" && key[1] === \"chart\";\nconst points = (data: unknown): number => {\n const chart = data as Partial<MarketChartData> | undefined;\n return chart?.venues\n ? Object.values(chart.venues).reduce(\n (total, venue) => total + venue.candles.length + (venue.liveCandle ? 1 : 0),\n 0,\n )\n : 0;\n};\n\n/** Read-only diagnostics for chart policy only; ordinary REST and user caches are excluded. */\nexport function getChartHistoryRetentionStats(client: QueryClient) {\n const queries = client.getQueryCache().findAll({ queryKey: marketDataKeys.chartPrefix() });\n const active = queries.filter((query) => query.getObserversCount() > 0);\n const inactive = queries.filter((query) => query.getObserversCount() === 0);\n const owner = owners.get(client);\n return {\n activeQueries: active.length,\n inactiveQueries: inactive.length,\n activePoints: active.reduce((sum, query) => sum + points(query.state.data), 0),\n inactivePoints: inactive.reduce((sum, query) => sum + points(query.state.data), 0),\n inFlightQueries: queries.filter((query) => query.state.fetchStatus === \"fetching\").length,\n trackedQueries: owner?.touched.size ?? 0,\n evictedQueries: owner?.evicted ?? 0,\n limits: owner?.limits ?? DEFAULT_HISTORY_RETENTION,\n };\n}\n\n/** One reusable policy owner per QueryClient. Called by the hooks provider, never the demo app. */\nexport function installChartHistoryRetention(\n client: QueryClient,\n limits: HistoryRetentionLimits = DEFAULT_HISTORY_RETENTION,\n): () => void {\n let owner = owners.get(client);\n if (!owner) {\n owner = {\n refs: 0,\n clock: Date.now(),\n touched: new Map(),\n evicted: 0,\n queued: false,\n pruning: false,\n limits,\n unsubscribe: () => {},\n prune: () => {},\n };\n owners.set(client, owner);\n const current = owner;\n const prune = () => {\n if (current.pruning) return;\n current.pruning = true;\n try {\n const inactive = client\n .getQueryCache()\n .findAll({ queryKey: marketDataKeys.chartPrefix() })\n .filter((query) => query.getObserversCount() === 0)\n .sort(\n (a, b) =>\n (current.touched.get(a.queryHash) ?? a.state.dataUpdatedAt) -\n (current.touched.get(b.queryHash) ?? b.state.dataUpdatedAt),\n );\n let count = inactive.length;\n let totalPoints = inactive.reduce((sum, query) => sum + points(query.state.data), 0);\n for (const query of inactive) {\n if (\n count <= current.limits.maxInactiveQueries &&\n totalPoints <= current.limits.maxInactivePoints\n )\n break;\n // Recheck ownership: removal destroys/cancels the query and its actual abortable fetch.\n if (query.getObserversCount() > 0) continue;\n count--;\n totalPoints -= points(query.state.data);\n current.evicted++;\n current.touched.delete(query.queryHash);\n client.removeQueries({ queryKey: query.queryKey, exact: true });\n }\n } finally {\n current.pruning = false;\n }\n };\n current.prune = prune;\n const schedule = () => {\n if (current.queued) return;\n current.queued = true;\n queueMicrotask(() => {\n current.queued = false;\n prune();\n });\n };\n current.unsubscribe = client.getQueryCache().subscribe((event) => {\n if (!isHistory(event.query.queryKey)) return;\n if (event.type === \"removed\") current.touched.delete(event.query.queryHash);\n else if (\n event.type === \"observerAdded\" ||\n event.type === \"updated\" ||\n event.type === \"added\"\n ) {\n current.clock = Math.max(current.clock + 1, Date.now());\n current.touched.set(event.query.queryHash, current.clock);\n }\n if (!current.pruning) schedule();\n });\n schedule();\n }\n owner.refs++;\n const current = owner;\n let released = false;\n return () => {\n if (released) return;\n released = true;\n if (--current.refs > 0) return;\n // Child query observers may unsubscribe later in the same React cleanup turn.\n queueMicrotask(() => {\n if (current.refs > 0) return;\n current.prune();\n current.unsubscribe();\n owners.delete(client);\n });\n };\n}\n","import {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport type { ReactNode } from \"react\";\nimport { useQueryClient } from \"@tanstack/react-query\";\nimport type {\n AggWebSocket,\n AggWebSocketCallbacks,\n DiagnosticEvent,\n WsBalanceUpdate,\n WsMarketResolved,\n WsOrderEvent,\n WsOrderSubmitted,\n WsRedeemEvent,\n WsWithdrawalLifecycleEvent,\n} from \"@agg-build/sdk\";\nimport {\n createMarketLiveState,\n withLiveIntegrity,\n withLiveOrderbook,\n withLiveOrderbookError,\n withLiveTrade,\n} from \"../../market-data/live-cache\";\nimport { getMarketLiveStore, mergeCandleTails } from \"../../market-data/live-store\";\nimport {\n getOrCreateBuilder,\n resetAllBuilders,\n getCandleStoreDiagnostics,\n} from \"../../candle-store\";\nimport {\n applyResolutionToCachedData,\n cachedDataContainsOutcomeId,\n} from \"../../market-data/market-resolution-cache\";\nimport {\n installChartHistoryRetention,\n getChartHistoryRetentionStats,\n} from \"../../market-data/history-retention\";\nimport { marketDataKeys } from \"../../market-data/query-keys\";\nimport {\n invalidateBalanceQueries,\n invalidatePositionQueries,\n invalidateUserActivityQueries,\n shouldInvalidateBalancesForOrderEvent,\n} from \"../../execution/balance-invalidation\";\nimport { useAggClient, useAggUiConfig } from \"./hooks\";\n\nconst AggWebSocketContext = createContext<AggWebSocket | null>(null);\nconst AggWebSocketConnectionContext = createContext(false);\n\ntype WsUserEventListeners = {\n addOrderSubmittedListener: (cb: (msg: WsOrderSubmitted) => void) => () => void;\n addBalanceUpdateListener: (cb: (msg: WsBalanceUpdate) => void) => () => void;\n addOrderEventListener: (cb: (msg: WsOrderEvent) => void) => () => void;\n addRedeemEventListener: (cb: (msg: WsRedeemEvent) => void) => () => void;\n addWithdrawalLifecycleListener: (cb: (msg: WsWithdrawalLifecycleEvent) => void) => () => void;\n};\n\nconst AggWsUserEventContext = createContext<WsUserEventListeners | null>(null);\n\nconst snapshotUnavailableOutcomeIdPattern = /snapshot unavailable for\\s+([^\\s]+)/i;\nconst resolveSnapshotUnavailableOutcomeId = (errorMessage: string): string | null => {\n const matchedOutcomeId = snapshotUnavailableOutcomeIdPattern.exec(errorMessage)?.[1];\n if (!matchedOutcomeId) return null;\n\n return matchedOutcomeId.replace(/[.,;:!?]+$/, \"\");\n};\n\nexport function useAggWebSocket(): AggWebSocket | null {\n return useContext(AggWebSocketContext);\n}\n\nexport function useAggWebSocketConnectionState(): boolean {\n return useContext(AggWebSocketConnectionContext);\n}\n\nexport function useWsUserEventListeners(): WsUserEventListeners | null {\n return useContext(AggWsUserEventContext);\n}\n\nexport function useOnOrderSubmitted(callback: ((msg: WsOrderSubmitted) => void) | null): void {\n const listeners = useContext(AggWsUserEventContext);\n const callbackRef = useRef(callback);\n callbackRef.current = callback;\n const hasCallback = callback !== null;\n\n useEffect(() => {\n if (!listeners || !callbackRef.current) return;\n\n const handler = (msg: WsOrderSubmitted): void => {\n callbackRef.current?.(msg);\n };\n\n return listeners.addOrderSubmittedListener(handler);\n }, [listeners, hasCallback]);\n}\n\nexport function useOnBalanceUpdate(callback: ((msg: WsBalanceUpdate) => void) | null): void {\n const listeners = useContext(AggWsUserEventContext);\n const callbackRef = useRef(callback);\n callbackRef.current = callback;\n const hasCallback = callback !== null;\n\n useEffect(() => {\n if (!listeners || !callbackRef.current) return;\n\n const handler = (msg: WsBalanceUpdate): void => {\n callbackRef.current?.(msg);\n };\n\n return listeners.addBalanceUpdateListener(handler);\n }, [listeners, hasCallback]);\n}\n\nexport function useOnOrderEvent(callback: ((msg: WsOrderEvent) => void) | null): void {\n const listeners = useContext(AggWsUserEventContext);\n const callbackRef = useRef(callback);\n callbackRef.current = callback;\n const hasCallback = callback !== null;\n\n useEffect(() => {\n if (!listeners || !callbackRef.current) return;\n\n const handler = (msg: WsOrderEvent): void => {\n callbackRef.current?.(msg);\n };\n\n return listeners.addOrderEventListener(handler);\n }, [listeners, hasCallback]);\n}\n\nexport function useOnRedeemEvent(callback: ((msg: WsRedeemEvent) => void) | null): void {\n const listeners = useContext(AggWsUserEventContext);\n const callbackRef = useRef(callback);\n callbackRef.current = callback;\n const hasCallback = callback !== null;\n\n useEffect(() => {\n if (!listeners || !callbackRef.current) return;\n\n const handler = (msg: WsRedeemEvent): void => {\n callbackRef.current?.(msg);\n };\n\n return listeners.addRedeemEventListener(handler);\n }, [listeners, hasCallback]);\n}\n\nexport function useOnWithdrawalLifecycle(\n callback: ((msg: WsWithdrawalLifecycleEvent) => void) | null,\n): void {\n const listeners = useContext(AggWsUserEventContext);\n const callbackRef = useRef(callback);\n callbackRef.current = callback;\n const hasCallback = callback !== null;\n\n useEffect(() => {\n if (!listeners || !callbackRef.current) return;\n\n const handler = (msg: WsWithdrawalLifecycleEvent): void => {\n callbackRef.current?.(msg);\n };\n\n return listeners.addWithdrawalLifecycleListener(handler);\n }, [listeners, hasCallback]);\n}\n\ninterface WsProviderProps {\n children: ReactNode;\n}\n\nexport function AggWebSocketProvider({ children }: WsProviderProps): React.JSX.Element {\n const client = useAggClient();\n const { enableWebsocketsLogs } = useAggUiConfig();\n const queryClient = useQueryClient();\n const liveStore = getMarketLiveStore(queryClient);\n useEffect(() => installChartHistoryRetention(queryClient), [queryClient]);\n const [ws, setWs] = useState<AggWebSocket | null>(null);\n const [isConnected, setIsConnected] = useState(false);\n const [isClientAuthenticated, setIsClientAuthenticated] = useState(client.isAuthenticated);\n const wsRef = useRef<AggWebSocket | null>(null);\n const resyncDeadlineByMarketRef = useRef(new Map<string, number>());\n const lastBalanceInvalidationAtRef = useRef(0);\n\n useEffect(() => {\n setIsClientAuthenticated(client.isAuthenticated);\n return client.onAuthStateChange((authenticated) => {\n setIsClientAuthenticated(authenticated);\n });\n }, [client]);\n\n const orderSubmittedListenersRef = useRef(new Set<(msg: WsOrderSubmitted) => void>());\n const balanceUpdateListenersRef = useRef(new Set<(msg: WsBalanceUpdate) => void>());\n const orderEventListenersRef = useRef(new Set<(msg: WsOrderEvent) => void>());\n const redeemEventListenersRef = useRef(new Set<(msg: WsRedeemEvent) => void>());\n const withdrawalLifecycleListenersRef = useRef(\n new Set<(msg: WsWithdrawalLifecycleEvent) => void>(),\n );\n\n const userEventListeners = useMemo(\n (): WsUserEventListeners => ({\n addOrderSubmittedListener: (cb) => {\n orderSubmittedListenersRef.current.add(cb);\n return () => {\n orderSubmittedListenersRef.current.delete(cb);\n };\n },\n addBalanceUpdateListener: (cb) => {\n balanceUpdateListenersRef.current.add(cb);\n return () => {\n balanceUpdateListenersRef.current.delete(cb);\n };\n },\n addOrderEventListener: (cb) => {\n orderEventListenersRef.current.add(cb);\n return () => {\n orderEventListenersRef.current.delete(cb);\n };\n },\n addRedeemEventListener: (cb) => {\n redeemEventListenersRef.current.add(cb);\n return () => {\n redeemEventListenersRef.current.delete(cb);\n };\n },\n addWithdrawalLifecycleListener: (cb) => {\n withdrawalLifecycleListenersRef.current.add(cb);\n return () => {\n withdrawalLifecycleListenersRef.current.delete(cb);\n };\n },\n }),\n [],\n );\n\n const syncLiveQuery = useCallback(\n (\n marketId: string,\n updater: (previous: ReturnType<typeof createMarketLiveState> | undefined) => unknown,\n ): void => {\n liveStore.update(marketId, (previous) => updater(previous) as typeof previous);\n },\n [liveStore],\n );\n\n const invalidateBalanceCaches = useCallback((): void => {\n const now = Date.now();\n if (now - lastBalanceInvalidationAtRef.current < 750) return;\n\n lastBalanceInvalidationAtRef.current = now;\n invalidateBalanceQueries(queryClient);\n }, [queryClient]);\n\n const invalidatePositionCaches = useCallback((): void => {\n invalidatePositionQueries(queryClient);\n }, [queryClient]);\n\n // Activity feed gets stale whenever a deposit/withdrawal status flips. The\n // mutation success paths already invalidate it, but the canonical signal\n // for a deposit confirming (or a deferred withdrawal completing while the\n // tab was hidden) is the WS `balance_update` event — refetch the activity\n // family there too so the row's pending → completed transition shows up\n // without a manual refresh.\n const invalidateActivityCaches = useCallback((): void => {\n invalidateUserActivityQueries(queryClient);\n }, [queryClient]);\n\n const invalidateResolutionCaches = useCallback(\n (resolution: WsMarketResolved): void => {\n const { outcomeId } = resolution;\n\n syncLiveQuery(outcomeId, (previous) => {\n if (!previous) return previous;\n\n return {\n ...previous,\n orderbook: null,\n orderbookSnapshotVersion: previous.orderbookSnapshotVersion + 1,\n orderbookError: null,\n integrity: \"ok\",\n };\n });\n\n // Optimistically flip every cached market that holds this outcome to its\n // resolved/closed status and stamp the winner flags from the WS payload,\n // so trading is disabled and the resolved UI (winning outcome, \"Resolved:\n // Yes\") shows immediately — before the REST refetch below lands. The\n // server-truth refetch then reconciles authoritative winner/payout data.\n const affectedQueries = queryClient.getQueryCache().findAll({\n predicate: (query) => cachedDataContainsOutcomeId(query.state.data, outcomeId),\n });\n for (const query of affectedQueries) {\n queryClient.setQueryData(query.queryKey, (previous: unknown) =>\n applyResolutionToCachedData(previous, resolution),\n );\n }\n\n queryClient.invalidateQueries({\n queryKey: [\"midpoints\"],\n refetchType: \"all\",\n });\n queryClient.invalidateQueries({\n queryKey: [\"venue-market-midpoints\"],\n refetchType: \"all\",\n });\n queryClient.invalidateQueries({\n queryKey: [\"venue-event\"],\n refetchType: \"all\",\n });\n queryClient.invalidateQueries({\n queryKey: [\"venue-markets\"],\n refetchType: \"all\",\n });\n queryClient.invalidateQueries({\n queryKey: [\"events\"],\n refetchType: \"all\",\n });\n queryClient.invalidateQueries({\n queryKey: [\"event-list\"],\n refetchType: \"all\",\n });\n queryClient.invalidateQueries({\n queryKey: [\"search\"],\n refetchType: \"all\",\n });\n queryClient.invalidateQueries({\n predicate: (query) => cachedDataContainsOutcomeId(query.state.data, outcomeId),\n refetchType: \"all\",\n });\n },\n [queryClient, syncLiveQuery],\n );\n\n const publishLocalCandles = useCallback(\n (id: string): void => {\n const builder = getOrCreateBuilder(id);\n const candles = Object.fromEntries(\n ([\"1m\", \"5m\", \"1h\", \"1d\"] as const).map((interval) => [\n interval,\n {\n forming: builder.getForming(interval) ? { ...builder.getForming(interval)! } : null,\n closed: builder.getClosed(interval).slice(-2),\n },\n ]),\n ) as import(\"@agg-build/sdk\").CandleTail;\n liveStore.update(id, (previous) => ({ ...previous, candles }));\n },\n [liveStore],\n );\n\n const callbacks = useMemo(\n (): AggWebSocketCallbacks => ({\n onMarketView: (view) => {\n if (view.book && view.integrity === \"ok\")\n resyncDeadlineByMarketRef.current.delete(view.outcomeId);\n liveStore.update(view.outcomeId, (previous) => ({\n ...(view.book\n ? withLiveOrderbook(previous, view.book, view.snapshot ? \"snapshot\" : \"delta\")\n : previous),\n integrity: view.integrity,\n candles: mergeCandleTails(previous.candles, view.candles),\n receivedAtMs: view.receivedAtMs,\n trades: [...view.trades, ...previous.trades].slice(0, 50),\n }));\n getOrCreateBuilder(view.outcomeId).replaceTail(view.candles);\n },\n onSnapshot: (marketId, book) => {\n if ((wsRef.current as { processesCandles?: boolean } | null)?.processesCandles) return;\n resyncDeadlineByMarketRef.current.delete(marketId);\n syncLiveQuery(marketId, (previous) => withLiveOrderbook(previous, book, \"snapshot\"));\n if (\n !(wsRef.current as { processesCandles?: boolean } | null)?.processesCandles &&\n book.midpoint != null\n ) {\n getOrCreateBuilder(marketId).addMidpoint(book.midpoint, book.timestamp);\n publishLocalCandles(marketId);\n }\n },\n onDelta: (marketId, book) => {\n if ((wsRef.current as { processesCandles?: boolean } | null)?.processesCandles) return;\n resyncDeadlineByMarketRef.current.delete(marketId);\n syncLiveQuery(marketId, (previous) => withLiveOrderbook(previous, book, \"delta\"));\n if (\n !(wsRef.current as { processesCandles?: boolean } | null)?.processesCandles &&\n book.midpoint != null\n ) {\n getOrCreateBuilder(marketId).addMidpoint(book.midpoint, book.timestamp);\n publishLocalCandles(marketId);\n }\n },\n onTrade: (trade) => {\n if ((wsRef.current as { processesCandles?: boolean } | null)?.processesCandles) return;\n syncLiveQuery(trade.outcomeId, (previous) => withLiveTrade(previous, trade));\n if (!(wsRef.current as { processesCandles?: boolean } | null)?.processesCandles) {\n getOrCreateBuilder(trade.outcomeId).addTrade(trade.price, trade.size, trade.timestamp);\n publishLocalCandles(trade.outcomeId);\n }\n },\n onHeartbeat: () => {\n const now = Date.now();\n\n resyncDeadlineByMarketRef.current.forEach((deadline, marketId) => {\n if (deadline > now) return;\n\n wsRef.current?.resnapshot(marketId);\n resyncDeadlineByMarketRef.current.set(marketId, now + 35_000);\n });\n },\n onDiagnostics: (event: DiagnosticEvent) => {\n if (event.type !== \"seq_gap\" && event.type !== \"checksum_mismatch\") return;\n\n const id = event.outcomeId ?? event.marketId;\n resyncDeadlineByMarketRef.current.set(id, Date.now() + 35_000);\n\n syncLiveQuery(id, (previous) => withLiveIntegrity(previous, \"resyncing\"));\n },\n onOrderSubmitted: (msg) => {\n for (const listener of orderSubmittedListenersRef.current) {\n listener(msg);\n }\n },\n onBalanceUpdate: (msg) => {\n if (isClientAuthenticated) {\n invalidateBalanceCaches();\n invalidateActivityCaches();\n }\n for (const listener of balanceUpdateListenersRef.current) {\n listener(msg);\n }\n },\n onOrderEvent: (msg) => {\n if (isClientAuthenticated) {\n const currentUserId = client.user?.id ?? null;\n if (shouldInvalidateBalancesForOrderEvent(msg, currentUserId)) {\n invalidateBalanceCaches();\n // Filled/partial_fill events change outcome-token holdings as well\n // as wallet balances — refresh positions so share counts in the\n // sell tab and portfolio reflect the on-chain state.\n invalidatePositionCaches();\n }\n }\n for (const listener of orderEventListenersRef.current) {\n listener(msg);\n }\n },\n onRedeemEvent: (msg) => {\n for (const listener of redeemEventListenersRef.current) {\n listener(msg);\n }\n },\n onWithdrawalLifecycle: (msg) => {\n // Lifecycle events change managed-balance state on terminal completion\n // (and on intermediate sweeps, indirectly), so refresh balances on\n // every event — the listeners themselves only render UI deltas.\n if (isClientAuthenticated) {\n invalidateBalanceCaches();\n }\n for (const listener of withdrawalLifecycleListenersRef.current) {\n listener(msg);\n }\n },\n onMarketResolved: (msg) => {\n invalidateResolutionCaches(msg);\n\n // A resolution turns the user's open position into a winning/losing\n // closed position with (possibly) claimable winnings. Refresh the\n // money-state caches so the portfolio, balances, activity feed, and the\n // claimable-count badge reflect it — and so `useResolvedMarketClaim`\n // can surface the Claim Winnings CTA. `invalidatePositionCaches`\n // invalidates the whole `[\"execution\", \"positions\"]` family, which\n // covers the claimable-count query too. Gated on auth: unauthenticated\n // clients have no money state to refresh.\n if (isClientAuthenticated) {\n invalidateBalanceCaches();\n invalidatePositionCaches();\n invalidateActivityCaches();\n }\n },\n onError: (msg) => {\n const outcomeId = resolveSnapshotUnavailableOutcomeId(msg.message);\n if (!outcomeId) return;\n\n syncLiveQuery(outcomeId, (previous) =>\n withLiveOrderbookError(previous, outcomeId, msg.message),\n );\n },\n onConnectionStateChange: (connected) => {\n setIsConnected(connected);\n\n if (connected) {\n // Re-fetch REST chart data to fill gaps from disconnect\n queryClient.invalidateQueries({\n queryKey: marketDataKeys.chartPrefix(),\n refetchType: \"active\",\n });\n } else {\n // Clear CandleBuilder state on disconnect — REST re-fetch will fill the gap\n resetAllBuilders();\n }\n\n liveStore.connected(connected);\n },\n }),\n [\n client,\n invalidateActivityCaches,\n invalidateBalanceCaches,\n invalidatePositionCaches,\n invalidateResolutionCaches,\n isClientAuthenticated,\n queryClient,\n syncLiveQuery,\n liveStore,\n publishLocalCandles,\n ],\n );\n\n const callbacksRef = useRef(callbacks);\n callbacksRef.current = callbacks;\n useEffect(() => {\n wsRef.current?.setCallbacks(callbacks);\n }, [callbacks]);\n\n useEffect(() => {\n let instance: AggWebSocket | null = null;\n const resyncDeadlineByMarket = resyncDeadlineByMarketRef.current;\n\n try {\n instance = client.createWebSocket(callbacksRef.current, { enableLogs: enableWebsocketsLogs });\n } catch {\n console.warn(\n \"[AggUI] WebSocket connection could not be established. Ensure wsUrl is configured in createAggClient(). Real-time features (live prices, order updates) are disabled.\",\n );\n setWs(null);\n wsRef.current = null;\n setIsConnected(false);\n return;\n }\n\n instance.setHostDiagnostics?.(() => ({\n live: liveStore.getDiagnostics(),\n history: getChartHistoryRetentionStats(queryClient),\n candles: getCandleStoreDiagnostics(),\n }));\n setWs(instance);\n wsRef.current = instance;\n\n return () => {\n instance?.destroy();\n if (wsRef.current === instance) {\n wsRef.current = null;\n }\n resyncDeadlineByMarket.clear();\n setWs(null);\n setIsConnected(false);\n };\n }, [client, enableWebsocketsLogs, isClientAuthenticated, liveStore, queryClient]);\n\n return (\n <AggWebSocketConnectionContext.Provider value={isConnected}>\n <AggWsUserEventContext.Provider value={userEventListeners}>\n <AggWebSocketContext.Provider value={ws}>{children}</AggWebSocketContext.Provider>\n </AggWsUserEventContext.Provider>\n </AggWebSocketConnectionContext.Provider>\n );\n}\n","import { useMutation, useQueryClient } from \"@tanstack/react-query\";\nimport type { WithdrawManagedParams, WithdrawManagedResponse } from \"@agg-build/sdk\";\nimport { useAggClient } from \"../core/provider\";\nimport { invalidateUserMoneyState } from \"./balance-invalidation\";\n\nexport interface UseWithdrawManagedOptions {\n onSuccess?: (data: WithdrawManagedResponse) => void;\n onError?: (error: Error) => void;\n}\n\n/**\n * Mutation hook for withdrawing funds from managed wallets. On submission\n * success the backend has already debited the managed-side balance and\n * recorded the activity row, so we invalidate the full money-state cache\n * surface (balances, positions, activity). Terminal lifecycle invalidation\n * is handled separately by `useWithdrawalLifecycle`.\n */\nexport function useWithdrawManaged(options?: UseWithdrawManagedOptions) {\n const client = useAggClient();\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: (params: WithdrawManagedParams) => client.withdrawManaged(params),\n onSuccess: (data) => {\n invalidateUserMoneyState(queryClient);\n options?.onSuccess?.(data);\n },\n onError: options?.onError,\n });\n}\n","import { useQuery } from \"@tanstack/react-query\";\nimport { useAggClient } from \"../core/provider\";\nimport { executionKeys } from \"./query-keys\";\n\nexport interface UseManagedBalancesOptions {\n enabled?: boolean;\n mode?: \"live\" | \"paper\";\n /**\n * `\"self\"` fetches the balances of the wallets linked to this account rather\n * than the managed wallet. Its own query key, so both can be held at once.\n */\n custody?: \"managed\" | \"self\";\n}\n\n/**\n * Query hook for fetching unified managed wallet balances across all chains.\n */\nexport function useManagedBalances(options?: UseManagedBalancesOptions) {\n const client = useAggClient();\n const { enabled = true, mode, custody } = options ?? {};\n const params = { ...(mode ? { mode } : {}), ...(custody ? { custody } : {}) };\n\n const query = useQuery({\n queryKey: executionKeys.balances(mode, custody),\n queryFn: () => client.getManagedBalances(Object.keys(params).length ? params : undefined),\n enabled,\n staleTime: 10_000,\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: mode === \"paper\" ? false : 5_000,\n refetchIntervalInBackground: false,\n gcTime: 5 * 60_000,\n retry: 1,\n });\n\n return {\n ...query,\n balances: query.data,\n };\n}\n","import { useCallback, useEffect, useMemo, useState } from \"react\";\nimport type { WithdrawTokenSymbol } from \"@agg-build/sdk\";\nimport { useAggBalanceState } from \"../core/provider\";\nimport { useAggWebSocket } from \"../core/providers/ws-provider\";\nimport {\n useDepositAddresses,\n useManagedBalances,\n useSyncBalances,\n useWithdrawManaged,\n} from \"../execution\";\n\ntype WithdrawSelectOption = { value: string; label: string; disabled?: boolean };\n\n/** The chain family a recipient address structurally belongs to, or null if it isn't (yet) a valid address. */\ntype DestinationAddressKind = \"solana\" | \"evm\";\n\ntype WithdrawSummary = {\n /**\n * The amount the user submitted for withdrawal — NOT a confirmed payout\n * figure. A preflight quote can still fail or settle partially later, so\n * labeling this \"received\" was misleading.\n */\n amountReceived: string;\n network: string;\n toWallet: string;\n fees: string;\n};\n\nconst EVM_ADDRESS_REGEX = /^0x[a-fA-F0-9]{40}$/;\n// Bitcoin alphabet base58, 32–44 chars — covers normal Solana mainnet\n// wallet output. The full base58 set is `1-9A-HJ-NP-Za-km-z` (no `0OIl`).\nconst SOLANA_ADDRESS_REGEX = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;\n\n/** Solana mainnet chain id (mirrors `CHAIN_IDS.SOLANA` in `@app/balance`). */\nconst SOLANA_CHAIN_ID = 792703809;\n\n/**\n * Chain IDs the withdrawal pipeline can settle on. Mirrors\n * `WITHDRAWAL_SUPPORTED_CHAIN_IDS` in `@app/balance` (api). Solana is\n * supported as a destination — the API resolves the SPL USDC mint and\n * Relay's cross-chain quotes accept base58 recipients (no on-chain\n * forwarder for Solana, so the lifecycle path skips that step). Keep this\n * set in lock-step with the api-side constant.\n */\nconst WITHDRAWAL_SUPPORTED_CHAIN_IDS = new Set<number>([\n 1, // Ethereum\n 137, // Polygon\n 42161, // Arbitrum\n 8453, // Base\n 56, // BNB\n SOLANA_CHAIN_ID,\n 1337, // Hyperliquid\n]);\n\nconst isValidDestinationAddress = (address: string, chainId: number): boolean => {\n if (chainId === SOLANA_CHAIN_ID) return SOLANA_ADDRESS_REGEX.test(address);\n return EVM_ADDRESS_REGEX.test(address);\n};\n\n/**\n * Classify a recipient address by chain family so the network picker can\n * auto-select the matching chain and disable the others. EVM addresses are\n * unambiguous (`0x…` — `0` isn't in the base58 alphabet, so they can never\n * match the Solana regex), so we test EVM first. Returns null until the input\n * is a structurally complete address of either family — partial/garbage input\n * leaves every network enabled.\n */\nconst detectDestinationAddressKind = (address: string): DestinationAddressKind | null => {\n const trimmed = address.trim();\n if (!trimmed) return null;\n if (EVM_ADDRESS_REGEX.test(trimmed)) return \"evm\";\n if (SOLANA_ADDRESS_REGEX.test(trimmed)) return \"solana\";\n return null;\n};\n\nexport interface UseWithdrawFlowResult {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n withdrawFlow: {\n balance: number;\n balanceDisplay: string;\n amount: string;\n destinationWallet: string;\n tokenOptions: WithdrawSelectOption[];\n networkOptions: WithdrawSelectOption[];\n selectedToken: string;\n selectedNetwork: string;\n purchaseSummary: WithdrawSummary;\n /**\n * The id returned by `POST /execution/withdraw-managed` once the user\n * has submitted the flow — used by the success step to subscribe to\n * `withdrawal_lifecycle` WS events. `null` until submission succeeds\n * and reset to `null` when the modal closes.\n */\n withdrawalId: string | null;\n /**\n * True when the user clicked Max — the backend should apply its own cap\n * rather than rejecting an over-balance request. Reset to false when the\n * user manually edits the amount field afterward.\n */\n isMax: boolean;\n };\n onWithdrawDestinationChange: (address: string) => void;\n onWithdrawAmountChange: (amount: string) => void;\n onWithdrawTokenChange: (token: string) => void;\n onWithdrawNetworkChange: (network: string) => void;\n onMaxClick: () => void;\n onSelectWithdrawProvider: (providerId: string) => Promise<void>;\n onDoneWithdraw: () => void;\n}\n\nexport interface UseWithdrawFlowOptions {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n}\n\nconst DEFAULT_WITHDRAW_SUMMARY: WithdrawSummary = {\n amountReceived: \"\",\n network: \"\",\n toWallet: \"\",\n fees: \"—\",\n};\n\nconst formatRawTokenAmount = (rawAmount: string, decimals: number): string => {\n if (!rawAmount) return \"0\";\n const raw = BigInt(rawAmount);\n const divisor = BigInt(`1${\"0\".repeat(decimals)}`);\n const whole = raw / divisor;\n const remainder = raw % divisor;\n if (remainder === BigInt(0)) return whole.toString();\n return `${whole.toString()}.${remainder.toString().padStart(decimals, \"0\").replace(/0+$/, \"\")}`;\n};\n\nconst formatRawTokenAmountForDisplay = (\n rawAmount: string,\n decimals: number,\n fractionDigits = 2,\n): string => {\n const [wholePart, fractionalPart = \"\"] = formatRawTokenAmount(rawAmount, decimals).split(\".\");\n const normalizedFraction = fractionalPart.padEnd(fractionDigits, \"0\").slice(0, fractionDigits);\n return `${wholePart}.${normalizedFraction}`;\n};\n\nconst parseTokenAmountToRaw = (amount: string, decimals: number): string | null => {\n const normalizedAmount = amount.trim();\n if (!normalizedAmount || !/^\\d*(?:\\.\\d*)?$/.test(normalizedAmount)) {\n return null;\n }\n\n const [wholePart = \"0\", fractionalPart = \"\"] = normalizedAmount.split(\".\");\n if (fractionalPart.length > decimals) return null;\n\n const normalizedWhole = wholePart === \"\" ? \"0\" : wholePart;\n const normalizedFraction = fractionalPart.padEnd(decimals, \"0\");\n\n try {\n return `${BigInt(normalizedWhole)}${normalizedFraction}`.replace(/^0+(?=\\d)/, \"\");\n } catch {\n return null;\n }\n};\n\nconst shortenAddress = (address: string): string =>\n address.length > 12 ? `${address.slice(0, 6)}...${address.slice(-4)}` : address;\n\nexport function useWithdrawFlow(options: UseWithdrawFlowOptions): UseWithdrawFlowResult {\n const { open, onOpenChange } = options;\n const { totalBalance } = useAggBalanceState();\n const { balances } = useManagedBalances({ enabled: open });\n const { supportedChains } = useDepositAddresses({ enabled: open });\n const withdrawMutation = useWithdrawManaged();\n const syncBalances = useSyncBalances();\n const ws = useAggWebSocket();\n\n // Force a fresh on-chain balance sync the moment the modal opens. The\n // server caches balances for 5–10s and the per-user sync endpoint has a\n // 60s throttle; without this nudge users opening the modal shortly\n // after a deposit/trade saw a stale figure (the \"$12 actual vs $5\n // shown\" symptom). Fire-and-forget — `useSyncBalances` already\n // invalidates query caches on success, and a throttled response is\n // fine because `useManagedBalances` will refetch again when its own\n // 10s React Query stale window expires.\n //\n // We use a ref + open-edge effect rather than depending on the mutation\n // identity so flipping `open` true→false→true within the same modal\n // session always re-syncs.\n useEffect(() => {\n if (!open) return;\n syncBalances.mutate(undefined, {\n onError: () => {\n /* throttled or transient — managed-balances poll will catch up */\n },\n });\n // eslint-disable-next-line react-hooks/exhaustive-deps -- only fire on open-edge transitions\n }, [open]);\n\n const [withdrawDestination, setWithdrawDestination] = useState(\"\");\n const [withdrawAmount, setWithdrawAmount] = useState(\"\");\n const [withdrawToken, setWithdrawToken] = useState(\"USDC\");\n const [withdrawNetwork, setWithdrawNetwork] = useState(\"\");\n const [withdrawSummary, setWithdrawSummary] = useState<WithdrawSummary>(DEFAULT_WITHDRAW_SUMMARY);\n const [withdrawalId, setWithdrawalId] = useState<string | null>(null);\n const [isMax, setIsMax] = useState(false);\n\n // The chain family of the recipient address the user typed/pasted. Drives\n // which network options are disabled and which chain we auto-select.\n const detectedAddressKind = useMemo(\n () => detectDestinationAddressKind(withdrawDestination),\n [withdrawDestination],\n );\n\n const networkOptions = useMemo(\n () =>\n (supportedChains ?? [])\n .filter((chain: { chainId: number }) => WITHDRAWAL_SUPPORTED_CHAIN_IDS.has(chain.chainId))\n .map((chain) => {\n const value = String(chain.chainId);\n const isSolana = chain.chainId === SOLANA_CHAIN_ID;\n // A Solana recipient can only settle on Solana (and vice-versa). When\n // the address tells us the family, disable every option that can't\n // receive it so the user can't pick a mismatched chain.\n const disabled =\n detectedAddressKind === \"solana\"\n ? !isSolana\n : detectedAddressKind === \"evm\"\n ? isSolana\n : false;\n return { value, label: chain.name, disabled };\n }),\n [supportedChains, detectedAddressKind],\n );\n\n const firstEnabledNetwork =\n networkOptions.find((option) => !option.disabled)?.value ?? networkOptions[0]?.value ?? \"\";\n const isCurrentNetworkSelectable = networkOptions.some(\n (option) => option.value === withdrawNetwork && !option.disabled,\n );\n // Always resolve to a selectable network so the preview/submit never run\n // against a chain the pasted address can't settle on, even before the\n // reconciliation effect below flushes the state update.\n const resolvedWithdrawNetwork = isCurrentNetworkSelectable\n ? withdrawNetwork\n : firstEnabledNetwork;\n\n useEffect(() => {\n if (!networkOptions.length) return;\n if (!isCurrentNetworkSelectable && firstEnabledNetwork) {\n setWithdrawNetwork(firstEnabledNetwork);\n }\n }, [networkOptions, isCurrentNetworkSelectable, firstEnabledNetwork]);\n\n const tokenOptions = useMemo(() => {\n const selectedChainId = Number(resolvedWithdrawNetwork);\n const supportedTokensForNetwork =\n supportedChains?.find((chain) => chain.chainId === selectedChainId)?.tokens ?? [];\n const withdrawableSymbols = new Set(supportedTokensForNetwork.map((token) => token.symbol));\n\n return (balances?.cash ?? [])\n .filter((cashEntry) => withdrawableSymbols.has(cashEntry.tokenSymbol))\n .map((cashEntry) => ({\n value: cashEntry.tokenSymbol,\n label: cashEntry.tokenSymbol,\n }));\n }, [balances, resolvedWithdrawNetwork, supportedChains]);\n\n const resolvedWithdrawToken = tokenOptions.some((option) => option.value === withdrawToken)\n ? withdrawToken\n : tokenOptions[0]?.value || \"\";\n\n useEffect(() => {\n if (!tokenOptions.length) return;\n if (!tokenOptions.some((option) => option.value === withdrawToken)) {\n setWithdrawToken(tokenOptions[0]!.value);\n }\n }, [tokenOptions, withdrawToken]);\n\n const selectedCashEntry = useMemo(\n () => balances?.cash.find((cashEntry) => cashEntry.tokenSymbol === resolvedWithdrawToken),\n [balances, resolvedWithdrawToken],\n );\n\n const selectedTokenDecimals = useMemo(() => {\n const selectedChainId = Number(resolvedWithdrawNetwork);\n return (\n supportedChains\n ?.find((chain) => chain.chainId === selectedChainId)\n ?.tokens.find((token) => token.symbol === resolvedWithdrawToken)?.decimals ??\n selectedCashEntry?.decimals ??\n 6\n );\n }, [\n resolvedWithdrawNetwork,\n resolvedWithdrawToken,\n selectedCashEntry?.decimals,\n supportedChains,\n ]);\n\n const exactBalance = useMemo(() => {\n if (!selectedCashEntry) return \"0\";\n return formatRawTokenAmount(selectedCashEntry.totalRaw, selectedCashEntry.decimals);\n }, [selectedCashEntry]);\n\n const balanceDisplay = useMemo(() => {\n if (!selectedCashEntry) return `0.00 ${resolvedWithdrawToken || withdrawToken}`;\n return `${formatRawTokenAmountForDisplay(\n selectedCashEntry.totalRaw,\n selectedCashEntry.decimals,\n )} ${resolvedWithdrawToken}`;\n }, [resolvedWithdrawToken, selectedCashEntry, withdrawToken]);\n\n const resetFlowState = useCallback(() => {\n setWithdrawDestination(\"\");\n setWithdrawAmount(\"\");\n setWithdrawToken(\"USDC\");\n setWithdrawNetwork(\"\");\n setWithdrawSummary(DEFAULT_WITHDRAW_SUMMARY);\n setWithdrawalId(null);\n setIsMax(false);\n }, []);\n\n const handleWithdrawOpenChange = useCallback(\n (isOpen: boolean) => {\n if (!isOpen) resetFlowState();\n onOpenChange(isOpen);\n },\n [onOpenChange, resetFlowState],\n );\n\n // Defensive reset when the parent toggles `open` to false directly\n // (instead of routing through `handleWithdrawOpenChange`). Without this,\n // a stale `withdrawalId` from a completed withdrawal lingered across\n // modal opens, and the next open would land on the success step with\n // \"Withdrawal submitted\" copy until the page was hard-refreshed.\n useEffect(() => {\n if (!open) resetFlowState();\n }, [open, resetFlowState]);\n\n const handleWithdrawProvider = useCallback(async (): Promise<void> => {\n const destinationChainId = Number(resolvedWithdrawNetwork);\n const trimmedDestination = withdrawDestination.trim();\n const amountRaw = parseTokenAmountToRaw(withdrawAmount, selectedTokenDecimals);\n\n if (!amountRaw || BigInt(amountRaw) <= BigInt(0)) {\n throw new Error(\"Enter a withdrawal amount greater than zero.\");\n }\n if (!Number.isFinite(destinationChainId) || destinationChainId <= 0) {\n throw new Error(\"Select a destination network.\");\n }\n if (!isValidDestinationAddress(trimmedDestination, destinationChainId)) {\n const expected =\n destinationChainId === SOLANA_CHAIN_ID\n ? \"a Solana wallet address (base58, 32–44 chars)\"\n : \"an EVM destination address (0x… 40 hex chars)\";\n throw new Error(`Enter ${expected}.`);\n }\n if (selectedCashEntry) {\n // Compare in the destination's decimal frame so cross-chain decimal\n // mismatches (BNB 18-dec vs EVM 6-dec) don't false-positive on either\n // side. `formatRawTokenAmount` is expressed in `selectedTokenDecimals`\n // which equals the destination chain's USDC decimals.\n // tsconfig targets pre-ES2020, so we avoid bigint literals (`10n`)\n // and exponentiation; build the decimal scale via repeated string\n // concatenation instead.\n const scaleBy = (n: bigint, exp: number): bigint => {\n if (exp <= 0) return n;\n return n * BigInt(`1${\"0\".repeat(exp)}`);\n };\n const balanceInDestFrame = ((): bigint => {\n const native = BigInt(selectedCashEntry.totalRaw);\n if (selectedCashEntry.decimals === selectedTokenDecimals) return native;\n if (selectedCashEntry.decimals > selectedTokenDecimals) {\n return native / scaleBy(BigInt(1), selectedCashEntry.decimals - selectedTokenDecimals);\n }\n return scaleBy(native, selectedTokenDecimals - selectedCashEntry.decimals);\n })();\n if (!isMax && BigInt(amountRaw) > balanceInDestFrame) {\n throw new Error(\"Withdrawal amount exceeds your available balance.\");\n }\n }\n\n // Open the WS *before* we kick the withdrawal off. The SDK only auto-\n // connects on the first orderbook/trade subscribe, so user-keyed events\n // (`withdrawal_lifecycle`, `balance_update`, …) flow on the\n // authenticated channel without per-id subs and never arrive unless we\n // explicitly call `connect()`. Doing it here — gated on the user\n // confirming a withdrawal — keeps the socket dormant for users who\n // never actually withdraw, and guarantees the lifecycle listener that\n // attaches once `setWithdrawalId(...)` lands has a live channel to\n // hear on. `connect()` is idempotent; if the socket is already open\n // (e.g. a market view is mounted) this is a no-op.\n ws?.connect();\n\n // The lifecycle response is informational here — the success-step UI shows\n // the user-submitted amount. We do not synthesize a \"received\" figure from\n // sources because the lifecycle remains authoritative and source amounts\n // are in source-native decimals; summing them across decimal frames was\n // the source of prior under/over-counts.\n // `resolvedWithdrawToken` is sourced from `tokenOptions`, whose values come\n // from `/execution/deposit-addresses` (server-curated) intersected with the\n // user's actual `balances.cash` symbols. The API rejects unsupported\n // symbols, so any string that survives that intersection is one of the\n // supported variants. The cast keeps the SDK's strict union contract\n // while avoiding a runtime guard that would only re-prove server state.\n await new Promise<void>((resolve, reject) => {\n withdrawMutation.mutate(\n {\n amountRaw,\n tokenSymbol: resolvedWithdrawToken as WithdrawTokenSymbol,\n destinationAddress: trimmedDestination,\n destinationChainId,\n ...(isMax ? { max: true } : {}),\n },\n {\n onSuccess: (data) => {\n // Capture the withdrawalId so the success step can subscribe to\n // `withdrawal_lifecycle` WS events and render real progress\n // (replacing the static \"submitted\" message).\n setWithdrawalId(data.withdrawalId);\n resolve();\n },\n onError: reject,\n },\n );\n });\n\n setWithdrawSummary({\n amountReceived: `${formatRawTokenAmountForDisplay(amountRaw, selectedTokenDecimals)} ${resolvedWithdrawToken}`,\n network:\n supportedChains?.find((chain) => chain.chainId === destinationChainId)?.name ??\n resolvedWithdrawNetwork,\n toWallet: shortenAddress(trimmedDestination),\n fees: \"—\",\n });\n }, [\n isMax,\n resolvedWithdrawNetwork,\n resolvedWithdrawToken,\n selectedCashEntry,\n selectedTokenDecimals,\n supportedChains,\n withdrawAmount,\n withdrawDestination,\n withdrawMutation,\n ws,\n ]);\n\n return {\n open,\n onOpenChange: handleWithdrawOpenChange,\n withdrawFlow: {\n balance: totalBalance,\n balanceDisplay,\n amount: withdrawAmount,\n destinationWallet: withdrawDestination,\n tokenOptions,\n networkOptions,\n selectedToken: resolvedWithdrawToken,\n selectedNetwork: resolvedWithdrawNetwork,\n purchaseSummary: withdrawSummary,\n withdrawalId,\n isMax,\n },\n onWithdrawDestinationChange: setWithdrawDestination,\n onWithdrawAmountChange: useCallback((v: string) => {\n setIsMax(false);\n setWithdrawAmount(v);\n }, []),\n onWithdrawTokenChange: setWithdrawToken,\n onWithdrawNetworkChange: setWithdrawNetwork,\n onMaxClick: useCallback(() => {\n setIsMax(true);\n setWithdrawAmount(exactBalance === \"0\" ? \"0\" : exactBalance);\n }, [exactBalance]),\n onSelectWithdrawProvider: useCallback(\n async (_providerId: string) => handleWithdrawProvider(),\n [handleWithdrawProvider],\n ),\n onDoneWithdraw: useCallback(() => handleWithdrawOpenChange(false), [handleWithdrawOpenChange]),\n };\n}\n","import { useMemo } from \"react\";\n\nexport interface WithdrawFeeEstimate {\n estimatedFees: string;\n networkReserve: string;\n youReceive: string;\n}\n\nexport interface UseWithdrawEstimateParams {\n amount: string;\n selectedToken: string;\n selectedNetwork: string;\n}\n\n/**\n * Natively estimates withdrawal fees, network reserves, and the expected net\n * amount to be received based on the selected token, destination network,\n * and transfer amount.\n */\nexport function useWithdrawEstimate({\n amount,\n selectedToken,\n selectedNetwork,\n}: UseWithdrawEstimateParams): WithdrawFeeEstimate | null {\n return useMemo(() => {\n const numAmount = Number(amount);\n if (!amount || isNaN(numAmount) || numAmount <= 0 || !selectedToken || !selectedNetwork) {\n return null;\n }\n\n const network = selectedNetwork.toLowerCase();\n\n // Default fee values\n let feeVal = 0.1;\n let reserveVal = 0.2;\n\n if (network === \"1\" || network === \"mainnet\" || network === \"ethereum\") {\n feeVal = 1.22;\n reserveVal = 0.3;\n } else if (network === \"137\" || network === \"polygon\") {\n feeVal = 0.05;\n reserveVal = 0.15;\n } else if (network === \"42161\" || network === \"arbitrum\") {\n feeVal = 0.05;\n reserveVal = 0.15;\n } else if (network === \"8453\" || network === \"base\") {\n feeVal = 0.05;\n reserveVal = 0.15;\n } else if (network === \"56\" || network === \"bnb\" || network === \"bsc\") {\n feeVal = 0.1;\n reserveVal = 0.2;\n } else if (network === \"792703809\" || network === \"solana\") {\n feeVal = 0.01;\n reserveVal = 0.04;\n } else if (network === \"1337\" || network === \"hyperliquid\") {\n feeVal = 0.02;\n reserveVal = 0.08;\n }\n\n const youReceiveVal = Math.max(0, numAmount - feeVal);\n\n return {\n estimatedFees: `~$${feeVal.toFixed(2)}`,\n networkReserve: `~$${reserveVal.toFixed(2)}`,\n youReceive: `~${youReceiveVal.toFixed(2)} ${selectedToken}`,\n };\n }, [amount, selectedToken, selectedNetwork]);\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { useQueryClient } from \"@tanstack/react-query\";\nimport type {\n WithdrawalLeg,\n WithdrawManagedResponse,\n WithdrawManagedSourceItem,\n WsWithdrawalLifecycleEvent,\n WsWithdrawalLifecycleLeg,\n WsWithdrawalLifecycleStatus,\n} from \"@agg-build/sdk\";\nimport { useAggClient } from \"../core/providers/hooks\";\nimport {\n useAggWebSocketConnectionState,\n useOnWithdrawalLifecycle,\n} from \"../core/providers/ws-provider\";\nimport { invalidateUserMoneyState } from \"../execution/balance-invalidation\";\n\n/**\n * Latest lifecycle snapshot for a single withdrawal, materialized from the\n * most recent `WsWithdrawalLifecycleEvent` whose `withdrawalId` matches.\n *\n * The wire format is intentionally additive (legs may arrive partial), so\n * `legs` reflects the latest snapshot the server emitted — earlier per-leg\n * deltas are not re-merged on the client. Consumers should treat `legs` as\n * \"last known truth\" rather than a derived rollup.\n */\nexport interface WithdrawalLifecycleState {\n /** True until the first lifecycle event for this withdrawal arrives. */\n pending: boolean;\n /** Top-level status, or `null` until the first event arrives. */\n status: WsWithdrawalLifecycleStatus | null;\n /** Requested withdrawal amount in destination-token native decimals. */\n requestedAmountRaw: string | null;\n /** Terminal settled amount in destination-token native decimals. */\n completedAmountRaw: string | null;\n /** Realized platform fee in destination-token native decimals. Only present on terminal events; null until then. */\n feeRaw: string | null;\n /** Whether `status` is a terminal state (`completed` / `partial` / `failed`). */\n terminal: boolean;\n /** Last leg delta (the leg whose flip triggered the most recent event). */\n lastLeg: WsWithdrawalLifecycleLeg | null;\n /** All legs at the moment of the most recent event (server snapshot). */\n legs: WsWithdrawalLifecycleLeg[];\n /** Failure reason for terminal `failed` / `partial`. */\n errorMessage: string | null;\n /** Server timestamp (ms) of the most recent event. */\n timestamp: number | null;\n}\n\nconst INITIAL_STATE: WithdrawalLifecycleState = {\n pending: true,\n status: null,\n requestedAmountRaw: null,\n completedAmountRaw: null,\n feeRaw: null,\n terminal: false,\n lastLeg: null,\n legs: [],\n errorMessage: null,\n timestamp: null,\n};\n\n/**\n * Convert a leg row from the REST status response into the WS lifecycle leg\n * shape so a single state mapping handles both. The REST leg includes the\n * type/status fields the WS event omits in the legs[] array — they line up\n * cleanly because the WS leg type is a superset.\n */\nconst restLegToWsLeg = (leg: WithdrawalLeg): WsWithdrawalLifecycleLeg => ({\n sourceChainId: leg.sourceChainId,\n destChainId: leg.destChainId,\n type: leg.type,\n // The wire-level WS leg status enum and the REST leg status enum are the\n // same union (planned/submitted/confirmed/failed). Keep the cast narrow to\n // avoid pulling the SDK enum apart for a one-line bridge.\n status: leg.status as WsWithdrawalLifecycleLeg[\"status\"],\n amountRaw: leg.amountRaw,\n txHash: leg.txHash,\n bridgeOperationId: leg.bridgeOperationId,\n});\n\n/**\n * Merge the new event's leg-state into the existing `legs[]`.\n *\n * - If the event carries a full `legs[]` snapshot (pending / terminal\n * rollup), it replaces — the server's snapshot is authoritative.\n * - If it carries only a `leg` delta, find the matching row by\n * (sourceChainId, destChainId, type) and replace it; if no row matches\n * (the delta arrived before any snapshot listed the leg), append it.\n * This preserves the timeline UI between snapshots — without this,\n * intermediate `submitted`/`confirmed` deltas would wipe `legs[]` to\n * `[]` and the per-leg checklist would collapse mid-flow.\n * - If neither is present, leave the existing `legs[]` untouched.\n */\nconst mergeLegs = (\n prev: WsWithdrawalLifecycleLeg[],\n snapshot: WsWithdrawalLifecycleLeg[] | undefined,\n delta: WsWithdrawalLifecycleLeg | undefined,\n): WsWithdrawalLifecycleLeg[] => {\n if (snapshot) return snapshot;\n if (!delta) return prev;\n const idx = prev.findIndex(\n (l) =>\n l.sourceChainId === delta.sourceChainId &&\n l.destChainId === delta.destChainId &&\n l.type === delta.type,\n );\n if (idx === -1) return [...prev, delta];\n const next = prev.slice();\n next[idx] = delta;\n return next;\n};\n\nconst restToLifecycleState = (response: WithdrawManagedResponse): WithdrawalLifecycleState => {\n // The REST shape uses sources[] for richer per-source detail; legs[] is the\n // ordered transfer/bridge plan that mirrors the WS event payload.\n // Surface legs verbatim — they're already keyed by source ordering server-side.\n void (null as unknown as WithdrawManagedSourceItem); // type-only retention\n return {\n pending: false,\n status: response.status,\n requestedAmountRaw: response.requested.amountRaw,\n completedAmountRaw: response.completedAmountRaw ?? null,\n feeRaw: response.expected.feeRaw ?? null,\n terminal:\n response.status === \"completed\" ||\n response.status === \"partial\" ||\n response.status === \"failed\",\n lastLeg: null,\n legs: response.legs.map(restLegToWsLeg),\n errorMessage: response.errorMessage ?? null,\n // No server timestamp on the REST response — we use 0 as \"older than any\n // WS timestamp\" so a subsequent WS event always wins. Callers that read\n // `timestamp` should treat 0/null interchangeably as \"unset\".\n timestamp: 0,\n };\n};\n\nexport interface UseWithdrawalLifecycleResult {\n /** Latest lifecycle snapshot for the watched `withdrawalId`. */\n state: WithdrawalLifecycleState;\n /** Reset to the initial pre-event state — call when the modal is closed or a new flow starts. */\n reset: () => void;\n}\n\n/**\n * Subscribes to `withdrawal_lifecycle` WS events for a single `withdrawalId`\n * and exposes the latest snapshot. Returns a stable `pending` initial state\n * until the first matching event arrives.\n *\n * Pass `null` for `withdrawalId` to disable the subscription (e.g. before\n * the user has submitted a withdrawal). Switching the `withdrawalId` resets\n * the state so a stale snapshot from a prior withdrawal can never bleed\n * across.\n *\n * **Backfill behavior**: on mount with a non-null `withdrawalId`, and again\n * whenever the WS connection re-opens, the hook calls\n * `GET /execution/withdrawals/:id` to recover any lifecycle events that fired\n * before the listener was attached or while the socket was disconnected. WS\n * events always win over REST snapshots (REST stamps as `timestamp: 0`), so a\n * race between the two never regresses to a stale state.\n */\nexport function useWithdrawalLifecycle(withdrawalId: string | null): UseWithdrawalLifecycleResult {\n const client = useAggClient();\n const wsConnected = useAggWebSocketConnectionState();\n const queryClient = useQueryClient();\n const [state, setState] = useState<WithdrawalLifecycleState>(INITIAL_STATE);\n const stateRef = useRef(state);\n stateRef.current = state;\n // Track ids we've already invalidated for to avoid double-firing the\n // refetch on every re-render after terminal — terminal state stays\n // sticky for the rest of the modal session.\n const balanceRefetchedForRef = useRef<string | null>(null);\n\n // Reset whenever the watched id changes — the initial pre-event state is\n // what callers expect to see, not the previous withdrawal's terminal state.\n useEffect(() => {\n setState(INITIAL_STATE);\n }, [withdrawalId]);\n\n // REST backfill: fetch the persisted state on mount and on every WS\n // reconnect. Only apply the snapshot if the in-memory state has no\n // server-side information (no WS event has landed) — WS always wins.\n useEffect(() => {\n if (!withdrawalId) return;\n let cancelled = false;\n (async () => {\n try {\n const response = await client.getWithdrawalStatus(withdrawalId);\n if (cancelled) return;\n // If the watched id changed during the fetch, ignore the result.\n if (response.withdrawalId !== withdrawalId) return;\n // If a WS event has already populated state for this id, prefer it.\n // We detect \"WS already won\" by a non-null `timestamp > 0` (REST\n // backfill stamps timestamp=0 so a later WS event with any real ms\n // timestamp dominates).\n const current = stateRef.current;\n const wsAlreadyWon = current.timestamp != null && current.timestamp > 0;\n if (wsAlreadyWon) return;\n setState(restToLifecycleState(response));\n } catch {\n // Backfill is best-effort: a 404/network error here is non-fatal,\n // the WS channel will populate state when the next event arrives.\n }\n })();\n return () => {\n cancelled = true;\n };\n // Depend on wsConnected so a reconnect re-fetches. The first-mount fetch\n // happens on the initial render where wsConnected is `false`, then again\n // on the eventual `true` transition.\n }, [client, withdrawalId, wsConnected]);\n\n // Pass `null` when disabled so the provider hook can short-circuit.\n const handler = useMemo(() => {\n if (!withdrawalId) return null;\n return (msg: WsWithdrawalLifecycleEvent) => {\n if (msg.withdrawalId !== withdrawalId) return;\n setState((prev) => ({\n pending: false,\n status: msg.status,\n requestedAmountRaw: msg.requestedAmountRaw ?? prev.requestedAmountRaw,\n completedAmountRaw: msg.completedAmountRaw ?? prev.completedAmountRaw,\n feeRaw: msg.feeRaw ?? null,\n terminal: msg.terminal,\n lastLeg: msg.leg ?? null,\n // `legs[]` is the cumulative server-known truth. Snapshots\n // (`pending` / terminal rollup) carry a full `legs[]` and replace\n // it. Intermediate per-leg deltas carry only `leg` (no `legs[]`)\n // — merge the delta into the existing array by\n // (sourceChainId, destChainId, type) so the timeline UI doesn't\n // collapse to empty between snapshots.\n legs: mergeLegs(prev.legs, msg.legs, msg.leg),\n errorMessage: msg.errorMessage ?? null,\n timestamp: msg.timestamp,\n }));\n };\n }, [withdrawalId]);\n\n useOnWithdrawalLifecycle(handler);\n\n // Refresh every money-state cache surface as soon as the withdrawal\n // reaches a terminal state. Funds have left (completed/partial) or were\n // never debited (failed) — either way the cached balance, positions, and\n // activity feed are stale and should update without the user having to\n // reopen the app. Fires once per withdrawal id; the modal's reset on\n // close clears the ref via id change so a subsequent withdrawal in the\n // same session re-fires.\n useEffect(() => {\n if (!withdrawalId) return;\n if (!state.terminal) return;\n if (balanceRefetchedForRef.current === withdrawalId) return;\n balanceRefetchedForRef.current = withdrawalId;\n invalidateUserMoneyState(queryClient);\n // Best-effort on-chain sync to bypass the server's 60s sync throttle\n // when funds have just landed. The mutation is fire-and-forget — if\n // it fails (throttle, network) the React Query invalidate above still\n // refetches from the server cache, which Alchemy's webhooks will\n // backfill within a few seconds anyway.\n client.syncManagedBalances().catch(() => {\n /* throttled or transient — invalidate above is enough */\n });\n }, [client, queryClient, state.terminal, withdrawalId]);\n\n const reset = useCallback(() => setState(INITIAL_STATE), []);\n\n return { state, reset };\n}\n","import { useQuery } from \"@tanstack/react-query\";\nimport type { WithdrawPreviewParams, WithdrawPreviewResponse } from \"@agg-build/sdk\";\nimport { useAggClient } from \"../core/providers/hooks\";\n\nexport interface UseWithdrawPreviewParams {\n amountRaw: string | null;\n tokenSymbol: string | null;\n destinationChainId: number | null;\n destinationAddress: string | null;\n /**\n * When `true`, the backend caps the withdrawal to the maximum deliverable amount.\n * Included in the query key so max vs non-max are distinct cache entries.\n */\n max?: boolean;\n}\n\n/**\n * Live withdrawal preview backed by the API (`POST /execution/withdraw/preview`).\n * Disabled until amount/token/chain/address are present and amount is non-zero.\n * The backend caches identical previews for 15s; FE debounce keeps Relay calls\n * bounded. Returns the real fee + receive amount, replacing the hardcoded\n * `useWithdrawEstimate`.\n */\nexport function useWithdrawPreview({\n amountRaw,\n tokenSymbol,\n destinationChainId,\n destinationAddress,\n max,\n}: UseWithdrawPreviewParams) {\n const client = useAggClient();\n const enabled =\n !!amountRaw &&\n BigInt(amountRaw || \"0\") > BigInt(0) &&\n !!tokenSymbol &&\n !!destinationChainId &&\n !!destinationAddress;\n\n return useQuery<WithdrawPreviewResponse>({\n queryKey: [\n \"withdraw-preview\",\n tokenSymbol,\n amountRaw,\n destinationChainId,\n destinationAddress,\n max ?? false,\n ],\n enabled,\n staleTime: 15_000,\n queryFn: () =>\n client.withdrawPreview({\n amountRaw: amountRaw as string,\n tokenSymbol: tokenSymbol as WithdrawPreviewParams[\"tokenSymbol\"],\n destinationChainId: destinationChainId as number,\n destinationAddress: destinationAddress as string,\n ...(max ? { max: true } : {}),\n }),\n });\n}\n"],"mappings":"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"}
|