@liberfi.io/ui-perpetuals 0.2.21 → 0.2.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/version.ts","../src/client/hyperliquid/WebSocketManager.ts","../src/client/hyperliquid/HyperliquidPerpetualsClient.ts","../src/client/liberfi/transport.ts","../src/client/liberfi/LiberFiPerpetualsClient.ts","../src/client/liberfi/LiberFiPerpDepositClient.ts","../src/client/liberfi/deposit-types.ts","../src/client/liberfi/deposit-state-machine.ts","../src/context/PerpetualsContext.ts","../src/providers/PerpetualsProvider.tsx","../src/hooks/usePerpetualsClient.ts","../src/hooks/useCoinsQuery.ts","../src/hooks/useMarketQuery.ts","../src/hooks/useMarketsQuery.ts","../src/hooks/useKlinesQuery.ts","../src/hooks/useOrderBookQuery.ts","../src/hooks/useRecentTradesQuery.ts","../src/hooks/usePositionsQuery.ts","../src/hooks/useOrdersQuery.ts","../src/hooks/useTradesQuery.ts","../src/hooks/useActiveAssetLeverageQuery.ts","../src/hooks/useAssetMetaQuery.ts","../src/hooks/useCreateOrderMutation.ts","../src/hooks/useCancelOrderMutation.ts","../src/hooks/useMarketDataSubscription.ts","../src/hooks/useCandlesSubscription.ts","../src/hooks/useUserDataSubscription.ts","../src/hooks/useAccountStateQuery.ts","../src/hooks/useAccountStateSubscription.ts","../src/hooks/usePerpDepositClient.ts","../src/hooks/usePerpDepositQuote.ts","../src/hooks/usePerpDepositExecute.ts","../src/hooks/usePerpDepositStatus.ts","../src/hooks/hyperliquid-setup/setup-state-machine.ts","../src/hooks/hyperliquid-setup/useHyperliquidSetup.ts","../src/components/coin-info/coin-info-notfound.ui.tsx","../src/internal/skeleton.tsx","../src/components/coin-info/coin-info-skeletons.ui.tsx","../src/components/coin-info/coin-info.script.tsx","../src/components/coin-info/coin-info.ui.tsx","../src/components/coin-info/coin-info.widget.tsx","../src/components/search-coins/search-coins.script.tsx","../src/components/search-coins/search-coins.ui.tsx","../src/components/search-coins/search-coins.widget.tsx","../src/components/orderbook/orderbook.script.tsx","../src/components/orderbook/orderbook.ui.tsx","../src/components/orderbook/orderbook.widget.tsx","../src/components/trades/trades.script.tsx","../src/components/trades/trades.ui.tsx","../src/components/trades/trades.widget.tsx","../src/components/place-order/tp-sl-math.ts","../src/components/place-order/place-order-form.script.tsx","../src/components/place-order/place-order-form.ui.tsx","../src/components/place-order/place-order-form.widget.tsx","../src/components/positions/positions.script.tsx","../src/components/positions/positions.ui.tsx","../src/components/positions/positions.widget.tsx","../src/components/open-orders/open-orders.script.tsx","../src/components/open-orders/open-orders.ui.tsx","../src/components/open-orders/open-orders.widget.tsx","../src/components/trade-history/trade-history.script.tsx","../src/components/trade-history/trade-history.ui.tsx","../src/components/trade-history/trade-history.widget.tsx","../src/components/perp-deposit/format.ts","../src/components/perp-deposit/deposit-confirm.ui.tsx","../src/components/perp-deposit/deposit-form.ui.tsx","../src/components/perp-deposit/deposit-status.ui.tsx","../src/components/perp-deposit/deposit-flow.widget.tsx","../src/components/hyperliquid-init/hyperliquid-init.ui.tsx","../src/components/hyperliquid-init/hyperliquid-init.widget.tsx"],"names":["version_default","aggregationKey","type","param","aggregation","m","WebSocketManager","wsEndpoint","resolve","reject","settled","settle","callback","ws","event","error","delay","message","subscription","data","channel","subscriptionId","transformedData","expectedCoin","payloadCoin","symbol","ctx","mid","mark","prev","change24h","trade","bids","asks","level","fill","sub","interval","unsubscription","HYPERLIQUID_ENDPOINTS","ASSET_META_TTL_MS","HyperliquidPerpetualsClient","config","endpoint","body","url","controller","timeoutId","response","HyperliquidApiError","meta","asset","markets","symbols","assetCtxs","allMarkets","index","currentPrice","prevPrice","symbolSet","limitOrOptions","coin","options","intervalMs","limit","startTime","endTime","bars","candle","maxLevel","_params","params","clearinghouse","openOrdersRaw","metaAndCtxs","result","parseClearinghouseState","markByCoin","buildMarkPriceMap","enrichPositions","sum","p","lev","universe","now","fetchPromise","map","orders","parseOpenOrder","filteredOrders","o","trades","isLong","t","userAddress","subscriptionType","raw","parseWebData2","symbolFilter","positions","assetPos","pos","quantity","entryPrice","unrealizedPnl","positionValue","filteredPositions","withdrawableRaw","availableBalance","order","origSz","remainingSz","filledSz","isBuySide","rawOrderType","baseOrderType","isTrigger","triggerType","triggerPx","triggerCondition","parseSpotBalances","balances","b","positionsResult","openOrders","spotBalances","enrichedPositions","totalUnrealizedPnl","ctxs","px","pickPositionTpSl","position","closingSide","closingSideBool","tpOrder","slOrder","orderTypeStr","isTp","isSl","marks","next","tp","sl","markPrice","dir","pnl","statusCode","responseBody","LiberFiApiError","DEFAULT_TIMEOUT_MS","LiberFiHttpTransport","path","query","key","value","qs","method","opts","timeoutMs","text","safeText","err","DEFAULT_WS_ENDPOINT","LiberFiPerpetualsClient","fills","prepared","signature","LiberFiPerpDepositClient","req","intentId","TERMINAL_DEPOSIT_STATUSES","initialDepositState","reduceDepositState","state","mapStatusToPhase","status","isTerminal","isPolling","currentStatus","currentBreakdown","isTerminalLifecycle","PerpetualsContext","createContext","PerpetualsProvider","client","depositClient","children","useMemo","jsx","usePerpetualsClient","context","useContext","coinsQueryKey","fetchCoins","useCoinsQuery","useQuery","DEFAULT_REFETCH_INTERVAL_MS","marketQueryKey","fetchMarket","useMarketQuery","marketsQueryKey","fetchMarkets","useMarketsQuery","klinesQueryKey","fetchKlines","useKlinesQuery","orderBookQueryKey","agg","aggKey","fetchOrderBook","useOrderBookQuery","recentTradesQueryKey","fetchRecentTrades","useRecentTradesQuery","positionsQueryKey","fetchPositions","usePositionsQuery","enabled","queryParams","ordersQueryKey","fetchOrders","useOrdersQuery","tradesQueryKey","fetchTrades","useTradesQuery","activeAssetLeverageQueryKey","fetchActiveAssetLeverage","useActiveAssetLeverageQuery","assetMetaQueryKey","fetchAssetMeta","useAssetMetaQuery","createOrder","useCreateOrderMutation","useMutation","cancelOrder","useCancelOrderMutation","useMarketDataSubscription","throttleMs","setData","useState","isConnected","setIsConnected","setError","pendingDataRef","useRef","flushTimerRef","throttleMsRef","handleData","useCallback","newData","useEffect","isSubscribed","useCandlesSubscription","useUserDataSubscription","accountStateQueryKey","useAccountStateQuery","rest","useAccountStateSubscription","queryClient","useQueryClient","isMounted","handlePush","ordersResult","unsubError","usePerpDepositClient","usePerpDepositClientMaybe","perpDepositQuoteQueryKey","fetchPerpDepositQuote","usePerpDepositQuote","isQuoteReady","usePerpDepositExecute","signAndBroadcast","dispatch","useReducer","reset","execute","input","quote","solanaTxHash","info","toErrorInfo","submitReq","out","fallbackCode","parsed","parseJsonSafe","perpDepositStatusQueryKey","fetchPerpDepositStatus","usePerpDepositStatus","pollIntervalMs","initialSetupState","classifyStep","step","current","sameAddress","reduceSetupState","action","rec","i","mergedAccount","mergeAccountState","s","nextRunnableStep","a","base","patch","useHyperliquidSetup","adapter","steps","autoLoad","onComplete","onError","adapterRef","stepsRef","onCompleteRef","onErrorRef","reload","accountState","records","e","toError","runStep","record","invokeAdapter","runNext","idx","completedRef","CoinInfoNotFoundUI","KEYFRAME_NAME","SHIMMER_KEYFRAMES_CSS","ShimmerStyle","shimmer","shimmerDelay","CoinInfoSkeletonsUI","jsxs","Fragment","cellStyle","StatColumn","labelWidth","valueWidth","width","height","useCoinInfo","marketData","setMarketData","fundingCountdown","setFundingCountdown","initialData","isPending","realtimeData","normalized","normalizeRealtimeTickerPayload","previous","buildMarketData","calculateCountdown","oneHour","remainder","timeUntilNext","payload","matched","item","toNumberOr","fallback","formatCountdown","seconds","hours","minutes","secs","formatNumber","num","decimals","formatPrice","price","CoinInfoUI","indexPrice","volume24h","openInterest","fundingRate","safeChange24h","safeFundingRate","isPositiveChange","changePercent","CoinInfoWidget","isLoading","useSearchCoinsScript","onSelectCoin","searchQuery","setSearchQuery","coins","setCoins","coinSymbols","isLoadingSymbols","marketsData","isLoadingMarkets","filteredCoins","SearchCoinsUI","onSearchChange","SearchIcon","fundingPercent","isPositiveFunding","tokenName","target","SearchCoinsWidget","className","handleSelectCoin","aggregationFromStep","k","candidates","eps","best","c","aggregateByPrecision","levels","precision","side","aggregated","round","roundedPrice","existing","calculateTotalsAndPercentages","total","withTotals","usdAmount","maxTotal","useOrderBookScript","initialPrecision","orderBook","setOrderBook","setPrecision","priceMagnitude","bestBid","bestAsk","ref","referencePrice","aggregatedBids","aggregatedAsks","sortedBids","sortedAsks","spread","spreadPercentage","ORDERBOOK_SCROLL_STYLE","CONTAINER_STYLE","HEADER_STYLE","HEADER_CELL_STYLE","ROW_STYLE","ASK_BAR_STYLE_BASE","BID_BAR_STYLE_BASE","ASK_PRICE_STYLE","BID_PRICE_STYLE","ROW_CELL_STYLE","ROW_PRICE_CELL_STYLE","SPREAD_BAR_STYLE","SPREAD_BAR_INNER_STYLE","SPREAD_LABEL_STYLE","SPREAD_VALUE_STYLE","SPREAD_BUTTON_STYLE","SPREAD_DROPDOWN_STYLE","SPREAD_OPTION_STYLE","SPREAD_OPTION_SELECTED_STYLE","formatQuantity","qty","formatPrecision","OBRow","memo","percentage","onPriceClick","isAsk","barStyle","handleClick","SpreadBar","precisionOptions","onPrecisionChange","open","setOpen","wrapperRef","handler","chevronStyle","v","opt","selected","OrderBookUI","asksScrollRef","bidsScrollRef","asksStuckRef","bidsStuckRef","renderedAsks","el","handleAsksScroll","distanceFromBottom","handleBidsScroll","ask","bid","DEFAULT_ORDER_BOOK_PRECISION_OPTIONS","SKEL_CONTAINER_STYLE","SKEL_HEADER_STYLE","SKEL_HEADER_CELL_STYLE","SKEL_ROW_STYLE","SKEL_SPREAD_BAR_STYLE","SkelRow","OrderBookSkeleton","askRows","_","bidRows","OrderBookEmpty","OrderBookWidget","defaultPrecision","BATCH_FLUSH_MS","useTradesScript","setTrades","realtimeTrade","isValidTrade","pendingRef","limitRef","incoming","normalizeRealtimeTrades","batch","deduped","ROW_HEIGHT","HEADER_HEIGHT","PRICE_COL_MAX_W","AGE_COL_MAX_W","HEADER_PRICE_CELL","HEADER_SIZE_CELL","HEADER_AGE_CELL","ROW_INNER_STYLE","ROW_PRICE_CELL","ROW_SIZE_CELL","ROW_AGE_CELL","BUY_BAR_STYLE_BASE","SELL_BAR_STYLE_BASE","formatUsd","usd","formatAge","ageMs","barWidth","TradeRow","style","onTradeClick","birthday","useTickAge","isBuy","TradesUI","listContainerRef","useResizeObserver","rowProps","List","SKEL_HEADER_PRICE_CELL","SKEL_HEADER_SIZE_CELL","SKEL_HEADER_AGE_CELL","TradeSkelRow","TradesSkeleton","rows","TradesEmpty","TradesWidget","signFor","kind","deriveTpSlPercent","entry","leverage","deriveTpSlPrice","percent","sign","priceΔ","roundTpSlPrice","magnitude","factor","roundTpSlPercent","FALLBACK_LEVERAGE","usePlaceOrderFormScript","maxLeverageProp","onSuccess","onUpdateLeverage","onPlaceOrder","setSide","orderType","setOrderType","form","useForm","assetMeta","szDecimals","resolvedMaxLeverage","createOrderViaClient","isClientPending","placeOrderViaHostMutation","request","isSubmitting","watchedValues","amount","notional","estimatedFee","estimatedTotal","liquidationPrice","l","offset","positionsData","accountValue","availableMargin","currentPosition","account","hasOpenOrdersForSymbol","activeAssetLeverage","currentLeverage","isLeverageReady","lastSyncedSymbolRef","handleSubmit","finalPrice","takeProfitPrice","stopLossPrice","size","BRAND_PRIMARY","SIDE_LONG_COLOR","SIDE_SHORT_COLOR","BRAND_DANGER","withAlpha","hex","alpha","HYPERLIQUID_ICON_CDN","MIN_NOTIONAL_USDC","sanitiseAmountInput","cleaned","parts","inlineTextSkeleton","formatLiqPrice","LEVERAGE_MIN","buildLeverageMarks","max","ceiling","niceRound","ticks","pct","LeverageModal","isOpen","initialLeverage","maxLeverage","coinName","hasOpenPosition","hasOpenOrders","onConfirm","onUpdate","onClose","draft","setDraft","pending","setPending","handleConfirm","guardedConfirm","useAuthCallback","StyledModal","ModalContent","XCloseIcon","Slider","Spinner","BuyAmountInput","methods","formValue","numericValue","inputText","setInputText","inputRef","isFocused","parsedPrev","valuesAgree","handleChange","handleKeyDownCapture","formatTpSlNumber","TpSlInput","field","placeholder","refPrice","isPriceField","partnerField","partnerValue","rounded","PlaceOrderFormUI","onSideChange","onOrderTypeChange","onSubmit","onAddFunds","showLeverageModal","setShowLeverageModal","showTpSl","setShowTpSl","rawAmount","hasAmount","tokenSymbol","positionPercent","handlePositionSlider","tokenQuantity","minMarginUsdc","submitState","handleSubmitButtonClick","formatTokenQuantity","n","StyledTooltip","tab","RHForm","RHNumberInput","isSubmit","buttonType","activeBg","activeColor","isPlacing","PlaceOrderFormWidget","resolvedOnUpdateLeverage","getSortValue","comparePositions","aVal","bVal","usePositionsScript","onCloseSuccess","onCloseError","sortKey","setSortKey","sortDir","setSortDir","onSort","currentKey","d","isClosing","sortedPositions","handleClosePosition","closeSide","formatUsdPrice","abs","dp","formatUsd2","formatSignedUsd2","formatPercentAbs","COL_STYLE","TABLE_MIN_WIDTH","HEADER_ROW_STYLE","BODY_ROW_STYLE","ALIGN_TO_JUSTIFY","HeaderCell","activeSortKey","align","arrow","interactive","justify","inner","cn","PositionsUI","onClosePosition","useTranslation","header","PositionRow","striped","directionLabel","directionColor","pnlColor","PositionsSkeleton","PositionsEmpty","PositionsWidget","useOpenOrdersScript","onCancelSuccess","onCancelError","setOrders","ordersData","realtimeOrder","isCanceling","prevOrders","existingIndex","newOrders","handleCancelOrder","formatTime","timestamp","date","OpenOrdersUI","onCancelOrder","Button","OpenOrdersSkeleton","OpenOrdersEmpty","OpenOrdersWidget","getTimeRangeInMs","range","today","useTradeHistoryScript","initialTimeRange","pageSize","timeRange","setTimeRange","currentPage","setCurrentPage","allTrades","setAllTrades","tradesData","totalPages","startIndex","endIndex","page","formatDateTime","month","day","TIME_RANGE_OPTIONS","TradeHistoryUI","onTimeRangeChange","onNextPage","onPreviousPage","onGoToPage","option","pageNum","TradeHistorySkeleton","TradeHistoryEmpty","TradeHistoryWidget","goToNextPage","goToPreviousPage","goToPage","LAMPORTS_PER_SOL","HL_USDC_DECIMALS","HL_USDC_DIVISOR","lamportsToSol","divToFixed","hlUsdcRawToUsdc","microUsdcToUsdc","solToLamports","whole","frac","fracPadded","combined","numerator","denominator","negative","scale","scaledRemainder","secondsUntil","expiresAtMs","nowMs","shortAddress","addr","head","tail","DepositConfirmUI","isExecuting","isExpired","onCancel","onExpire","secondsLeft","setSecondsLeft","id","remaining","Modal","ModalHeader","ModalBody","BreakdownSummary","ModalFooter","breakdown","Row","label","highlight","muted","DepositFormUI","onAmountChange","recipient","onRecipientChange","balanceSol","disabled","amountError","recipientError","onMax","Input","ACCENT","DepositStatusUI","phase","solanaExplorerUrl","hyperliquidExplorerUrl","onRetry","errorMessage","variant","phaseToVariant","showRetry","PhaseIcon","variantTextClass","TxLink","href","hash","ExternalLinkIcon","AccentSpinner","CheckCircle","AlertCircle","XCircle","props","DepositFlowWidget","userSolanaAddress","userId","source","campaign","defaultRecipient","onMaxClick","validateRecipient","buildSolanaExplorerUrl","buildHyperliquidExplorerUrl","onSettled","setAmount","setRecipient","grossLamports","quoteReq","quoteQ","statusQ","handleContinue","handleExpire","handleRetry","showConfirm","showStatus","continueDisabled","Card","CardBody","HyperliquidInitUI","onContinue","onRetryStep","onReload","onDismiss","isLoadError","CardHeader","LoadingRow","SetupStepRow","CardFooter","isCurrent","title","stepTitle","description","bps","statusLabel","StepIcon","statusBadgeClass","_id","compute","HyperliquidInitWidget","handleReload"],"mappings":"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","file":"index.js","sourcesContent":["declare global {\n interface Window {\n __LIBERFI_VERSION__?: {\n [key: string]: string;\n };\n }\n}\nif (typeof window !== \"undefined\") {\n window.__LIBERFI_VERSION__ = window.__LIBERFI_VERSION__ || {};\n window.__LIBERFI_VERSION__[\"@liberfi.io/ui-perpetuals\"] = \"0.2.21\";\n}\n\nexport default \"0.2.21\";\n","import type { Kline, MarketData } from \"../../types\";\n\n/**\n * WebSocket subscription callback function type\n */\ntype SubscriptionCallback = (data: any) => void;\n\n/**\n * Hyperliquid `l2Book` aggregation parameters.\n *\n * Sending these on the `subscribe` payload causes Hyperliquid to pre-aggregate\n * raw price levels into discrete buckets server-side, so a single 20-level\n * snapshot covers a much wider price range than at native tick resolution.\n *\n * - `nSigFigs`: number of significant figures (2..5) to round prices to.\n * `undefined` (or `null`) means full native precision.\n * - `mantissa`: only valid when `nSigFigs === 5`. Allowed values: 1, 2, 5.\n * At BTC ~$80k with `nSigFigs=5`, mantissa controls the smallest digit:\n * 1 → step $1, 2 → step $2, 5 → step $5.\n *\n * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint\n */\nexport interface OrderBookAggregation {\n nSigFigs?: 2 | 3 | 4 | 5;\n mantissa?: 1 | 2 | 5;\n}\n\n/**\n * WebSocket subscription metadata\n */\ninterface Subscription {\n type: string;\n param: string;\n callback: SubscriptionCallback;\n aggregation?: OrderBookAggregation;\n}\n\n/**\n * Build a stable map key for a (type, param, aggregation) triple. Different\n * aggregations of the same coin are separate subscriptions because Hyperliquid\n * pushes a different stream for each — they must not share storage.\n */\nfunction aggregationKey(\n type: string,\n param: string,\n aggregation?: OrderBookAggregation,\n): string {\n if (\n type !== \"orderBook\" ||\n !aggregation ||\n aggregation.nSigFigs === undefined\n ) {\n return `${type}:${param}`;\n }\n const m =\n aggregation.nSigFigs === 5 &&\n aggregation.mantissa &&\n aggregation.mantissa !== 1\n ? `:m${aggregation.mantissa}`\n : \"\";\n return `${type}:${param}:n${aggregation.nSigFigs}${m}`;\n}\n\n/**\n * WebSocket Manager for Hyperliquid\n *\n * Handles WebSocket connection lifecycle, including:\n * - Connection management (connect/disconnect)\n * - Automatic reconnection with exponential backoff\n * - Heartbeat to keep connection alive\n * - Subscription management (subscribe/unsubscribe)\n * - Message queue for offline messages\n */\nexport class WebSocketManager {\n private ws: WebSocket | null = null;\n private wsEndpoint: string;\n private subscriptions: Map<string, Subscription> = new Map();\n private reconnectAttempts: number = 0;\n private maxReconnectAttempts: number = 10;\n private reconnectDelay: number = 1000; // Initial reconnect delay: 1 second\n private heartbeatInterval: number | null = null;\n private messageQueue: any[] = []; // Message queue before connection established\n private isConnected: boolean = false;\n private pingInterval: number = 30000; // 30 second heartbeat\n private reconnectTimeout: number | null = null;\n private isReconnecting: boolean = false;\n private connectPromise: Promise<void> | null = null;\n private manuallyDisconnected: boolean = false;\n\n /**\n * Create a new WebSocketManager\n * @param wsEndpoint WebSocket endpoint URL\n */\n constructor(wsEndpoint: string) {\n this.wsEndpoint = wsEndpoint;\n }\n\n /**\n * Connect to WebSocket server\n * @returns Promise that resolves when connection is established\n */\n async connect(): Promise<void> {\n if (this.isConnected && this.ws?.readyState === WebSocket.OPEN) {\n return;\n }\n\n if (this.connectPromise) {\n return this.connectPromise;\n }\n\n this.manuallyDisconnected = false;\n\n this.connectPromise = new Promise((resolve, reject) => {\n let settled = false;\n\n const settle = (callback: () => void) => {\n if (settled) return;\n settled = true;\n this.connectPromise = null;\n callback();\n };\n\n try {\n const ws = new WebSocket(this.wsEndpoint);\n this.ws = ws;\n\n ws.onopen = () => {\n if (this.ws !== ws) return;\n console.log(\"[WebSocket] Connected to Hyperliquid\");\n this.isConnected = true;\n this.reconnectAttempts = 0;\n this.isReconnecting = false;\n this.startHeartbeat();\n this.flushMessageQueue();\n settle(resolve);\n };\n\n ws.onmessage = (event: MessageEvent) => {\n if (this.ws !== ws) return;\n this.handleMessage(event.data);\n };\n\n ws.onerror = (error: Event) => {\n if (this.ws !== ws) return;\n console.error(\"[WebSocket] Error:\", error);\n this.isConnected = false;\n settle(() => reject(new Error(\"WebSocket connection failed\")));\n };\n\n ws.onclose = (event: CloseEvent) => {\n if (this.ws !== ws) return;\n console.log(\n `[WebSocket] Closed: ${event.code} - ${event.reason || \"No reason provided\"}`,\n );\n this.isConnected = false;\n this.stopHeartbeat();\n this.connectPromise = null;\n\n // Only attempt reconnect if not manually disconnected (code 1000 = normal closure)\n if (!settled) {\n settle(() =>\n reject(\n new Error(\n `WebSocket closed before connection was established: ${event.code}`,\n ),\n ),\n );\n }\n\n if (!this.manuallyDisconnected && event.code !== 1000) {\n this.attemptReconnect();\n }\n };\n } catch (error) {\n settle(() => reject(error));\n }\n });\n\n return this.connectPromise;\n }\n\n /**\n * Disconnect from WebSocket server\n */\n disconnect(): void {\n this.manuallyDisconnected = true;\n this.stopHeartbeat();\n this.subscriptions.clear();\n\n // Clear reconnect timeout\n if (this.reconnectTimeout !== null) {\n clearTimeout(this.reconnectTimeout);\n this.reconnectTimeout = null;\n }\n\n if (this.ws) {\n this.ws.close(1000, \"Normal closure\");\n this.ws = null;\n }\n\n this.isConnected = false;\n this.isReconnecting = false;\n this.reconnectAttempts = 0;\n }\n\n /**\n * Attempt to reconnect with exponential backoff\n */\n private attemptReconnect(): void {\n if (this.isReconnecting) {\n return; // Already attempting to reconnect\n }\n\n if (this.reconnectAttempts >= this.maxReconnectAttempts) {\n console.error(\"[WebSocket] Max reconnection attempts reached\");\n return;\n }\n\n this.isReconnecting = true;\n this.reconnectAttempts++;\n\n // Exponential backoff: min(1000 * 2^attempts, 30000)\n const delay = Math.min(\n this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1),\n 30000, // Max 30 seconds\n );\n\n console.log(\n `[WebSocket] Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts}/${this.maxReconnectAttempts})`,\n );\n\n this.reconnectTimeout = window.setTimeout(() => {\n this.connect()\n .then(() => {\n // Resubscribe to all previous subscriptions\n this.resubscribeAll();\n })\n .catch((error) => {\n console.error(\"[WebSocket] Reconnection failed:\", error);\n this.isReconnecting = false;\n // attemptReconnect will be called again by onclose event\n });\n }, delay);\n }\n\n /**\n * Start heartbeat interval to keep connection alive\n */\n private startHeartbeat(): void {\n this.heartbeatInterval = window.setInterval(() => {\n if (\n this.isConnected &&\n this.ws &&\n this.ws.readyState === WebSocket.OPEN\n ) {\n // Send a ping message to keep connection alive\n // Hyperliquid WebSocket accepts JSON messages\n this.send({ method: \"ping\" });\n }\n }, this.pingInterval);\n }\n\n /**\n * Stop heartbeat interval\n */\n private stopHeartbeat(): void {\n if (this.heartbeatInterval !== null) {\n clearInterval(this.heartbeatInterval);\n this.heartbeatInterval = null;\n }\n }\n\n /**\n * Send message to WebSocket server\n * @param message Message object to send\n */\n private send(message: any): void {\n if (this.isConnected && this.ws && this.ws.readyState === WebSocket.OPEN) {\n this.ws.send(JSON.stringify(message));\n } else {\n // Connection not established, add to queue\n this.messageQueue.push(message);\n }\n }\n\n /**\n * Flush message queue after connection established\n */\n private flushMessageQueue(): void {\n while (this.messageQueue.length > 0) {\n const message = this.messageQueue.shift();\n if (message) {\n this.send(message);\n }\n }\n }\n\n /**\n * Resubscribe to all subscriptions after reconnection\n */\n private resubscribeAll(): void {\n this.subscriptions.forEach((subscription) => {\n this.sendSubscription(\n subscription.type,\n subscription.param,\n subscription.aggregation,\n );\n });\n }\n\n /**\n * Handle incoming WebSocket message\n * @param data Raw message data\n */\n private handleMessage(data: string): void {\n try {\n const message = JSON.parse(data);\n\n // Handle different message types\n if (message.channel) {\n this.handleChannelMessage(message);\n } else if (message.method === \"pong\") {\n // Heartbeat response\n // No action needed\n }\n } catch (error) {\n console.error(\"[WebSocket] Failed to parse message:\", error, data);\n }\n }\n\n /**\n * Handle channel-specific messages\n * @param message Parsed message object\n */\n private handleChannelMessage(message: any): void {\n const channel = message.channel;\n\n // Find matching subscriptions and trigger callbacks\n this.subscriptions.forEach((subscription, subscriptionId) => {\n if (\n this.isChannelMatch(\n channel,\n subscription.type,\n subscription.param,\n message,\n )\n ) {\n try {\n const transformedData = this.transformData(\n subscription.type,\n message.data,\n subscription.param,\n );\n subscription.callback(transformedData);\n } catch (error) {\n console.error(\n `[WebSocket] Error in subscription callback (${subscriptionId}):`,\n error,\n );\n }\n }\n });\n }\n\n /**\n * Check if channel matches subscription\n *\n * For per-coin channels (ticker via `activeAssetCtx`, trades, orderBook,\n * candle), we additionally match the coin in the payload against the\n * subscription parameter so a single multiplexed connection can feed many\n * subscriptions without cross-talk.\n *\n * @param channel Channel name from message\n * @param type Subscription type\n * @param param Subscription parameter (e.g. \"BTC-USDC\", \"BTC-USDC:1m\")\n * @param message Full parsed message (used to read payload coin)\n * @returns True if channel matches subscription\n */\n private isChannelMatch(\n channel: string,\n type: string,\n param: string,\n message: any,\n ): boolean {\n if (type === \"ticker\") {\n if (channel !== \"activeAssetCtx\") return false;\n const expectedCoin = param.split(\"-\")[0];\n const payloadCoin = message?.data?.coin;\n return typeof payloadCoin === \"string\" && payloadCoin === expectedCoin;\n } else if (type === \"trades\") {\n if (channel !== \"trades\") return false;\n const expectedCoin = param.split(\"-\")[0];\n // `trades` payload is an array; check the first element's coin if any.\n const payloadCoin = Array.isArray(message?.data)\n ? message.data[0]?.coin\n : undefined;\n return typeof payloadCoin !== \"string\" || payloadCoin === expectedCoin;\n } else if (type === \"orderBook\") {\n if (channel !== \"l2Book\") return false;\n const expectedCoin = param.split(\"-\")[0];\n const payloadCoin = message?.data?.coin;\n return typeof payloadCoin === \"string\" && payloadCoin === expectedCoin;\n } else if (type === \"candle\") {\n return channel === \"candle\";\n } else if (type === \"userFills\") {\n return channel === \"userFills\";\n } else if (type === \"userEvents\") {\n return channel === \"userEvents\";\n } else if (type === \"accountState\") {\n // `webData2` is Hyperliquid's unified per-user push channel: each\n // payload carries the full clearinghouseState + spotState + open\n // orders snapshot. Match purely on channel — the upstream filters\n // by `user`, so cross-talk is impossible.\n return channel === \"webData2\";\n }\n\n return false;\n }\n\n /**\n * Transform raw data to standard format\n * @param type Subscription type\n * @param data Raw data from WebSocket\n * @param param Subscription parameter (e.g., symbol, interval)\n * @returns Transformed data\n */\n private transformData(type: string, data: any, param: string): any {\n if (type === \"ticker\") {\n return this.transformTickerData(data, param);\n } else if (type === \"trades\") {\n return this.transformTradesData(data, param);\n } else if (type === \"orderBook\") {\n return this.transformOrderBookData(data, param);\n } else if (type === \"candle\") {\n return this.transformCandleData(data, param);\n } else if (type === \"userFills\") {\n return this.transformUserFillsData(data);\n } else if (type === \"userEvents\") {\n return this.transformUserEventsData(data);\n }\n\n return data;\n }\n\n /**\n * Transform ticker data (Hyperliquid `activeAssetCtx` channel).\n *\n * Each push delivers the full per-coin market context — mark/mid price,\n * `prevDayPx` (so we can compute 24h change client-side), notional volume,\n * funding, open interest, oracle price, etc. We map this into the\n * standard {@link MarketData} shape so consumers (`useCoinInfo`, ticker\n * widgets, etc.) get a real-time, complete snapshot in one shot — no\n * second REST call required to fill in 24h change.\n *\n * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/websocket\n */\n private transformTickerData(data: any, param: string): MarketData {\n const coin: string = data?.coin ?? param.split(\"-\")[0];\n const symbol = `${coin}-USDC`;\n const ctx = data?.ctx ?? {};\n\n const mid = parseFloat(ctx.midPx ?? ctx.markPx ?? \"0\");\n const mark = parseFloat(ctx.markPx ?? ctx.midPx ?? \"0\");\n const prev = ctx.prevDayPx ? parseFloat(ctx.prevDayPx) : mid;\n const change24h = prev > 0 ? ((mid - prev) / prev) * 100 : 0;\n\n return {\n symbol,\n price: mid,\n change24h,\n volume24h: parseFloat(ctx.dayNtlVlm ?? \"0\"),\n fundingRate: parseFloat(ctx.funding ?? \"0\"),\n openInterest: parseFloat(ctx.openInterest ?? \"0\"),\n markPrice: mark,\n indexPrice: parseFloat(ctx.oraclePx ?? ctx.midPx ?? \"0\"),\n };\n }\n\n /**\n * Transform trades data\n */\n private transformTradesData(data: any, symbol: string): any {\n if (!Array.isArray(data)) {\n return [];\n }\n\n return data.map((trade: any) => ({\n symbol,\n side: trade.side === \"B\" ? \"buy\" : \"sell\",\n price: parseFloat(trade.px),\n quantity: parseFloat(trade.sz),\n timestamp: trade.time,\n tradeId: trade.tid,\n }));\n }\n\n /**\n * Transform order book data\n */\n private transformOrderBookData(data: any, symbol: string): any {\n const [bids, asks] = data.levels || [[], []];\n\n return {\n symbol,\n bids: bids.map((level: any) => ({\n price: parseFloat(level.px),\n quantity: parseFloat(level.sz),\n count: level.n,\n })),\n asks: asks.map((level: any) => ({\n price: parseFloat(level.px),\n quantity: parseFloat(level.sz),\n count: level.n,\n })),\n timestamp: data.time || Date.now(),\n };\n }\n\n /**\n * Transform candle data\n */\n private transformCandleData(data: any, param: string): Kline {\n const [symbol] = param.split(\":\");\n\n return {\n symbol,\n open: parseFloat(data.o),\n high: parseFloat(data.h),\n low: parseFloat(data.l),\n close: parseFloat(data.c),\n volume: parseFloat(data.v),\n timestamp: data.t,\n closeTimestamp: data.T,\n };\n }\n\n /**\n * Transform user fills data\n */\n private transformUserFillsData(data: any): any {\n if (!Array.isArray(data)) {\n return [];\n }\n\n return data.map((fill: any) => ({\n tradeId: fill.tid?.toString(),\n orderId: fill.oid?.toString(),\n symbol: `${fill.coin}-USDC`,\n side: fill.dir?.includes(\"Long\") ? \"long\" : \"short\",\n price: parseFloat(fill.px),\n quantity: parseFloat(fill.sz),\n fee: parseFloat(fill.fee || \"0\"),\n feeCurrency: fill.feeToken || \"USDC\",\n isMaker: fill.side === \"M\",\n timestamp: fill.time,\n }));\n }\n\n /**\n * Transform user events data (orders and positions)\n */\n private transformUserEventsData(data: any): any {\n // User events can contain both order updates and position updates\n // Return the data as-is for now, let the callback handle it\n return data;\n }\n\n /**\n * Send subscription message to Hyperliquid WebSocket\n * @param type Subscription type\n * @param param Subscription parameter\n * @param aggregation Optional orderBook aggregation params (nSigFigs/mantissa)\n */\n private sendSubscription(\n type: string,\n param: string,\n aggregation?: OrderBookAggregation,\n ): void {\n let subscription: any;\n\n if (type === \"ticker\") {\n // Subscribe to per-coin `activeAssetCtx` so each push carries a full\n // market snapshot (mark/mid price, prevDayPx for 24h change, volume,\n // funding, open interest). This avoids the limitations of `allMids`,\n // which only streams price.\n const coin = param.split(\"-\")[0]; // \"BTC-USDC\" -> \"BTC\"\n subscription = {\n method: \"subscribe\",\n subscription: {\n type: \"activeAssetCtx\",\n coin,\n },\n };\n } else if (type === \"trades\") {\n // Subscribe to trades for specific coin\n const coin = param.split(\"-\")[0]; // \"BTC-USDC\" -> \"BTC\"\n subscription = {\n method: \"subscribe\",\n subscription: {\n type: \"trades\",\n coin,\n },\n };\n } else if (type === \"orderBook\") {\n // Subscribe to order book for specific coin. nSigFigs/mantissa let\n // Hyperliquid pre-aggregate the 20-level snapshot to a coarser grid,\n // dramatically widening the price range covered by a single payload.\n const coin = param.split(\"-\")[0];\n const sub: Record<string, unknown> = {\n type: \"l2Book\",\n coin,\n };\n if (aggregation?.nSigFigs !== undefined) {\n sub.nSigFigs = aggregation.nSigFigs;\n if (\n aggregation.nSigFigs === 5 &&\n aggregation.mantissa !== undefined &&\n aggregation.mantissa !== 1\n ) {\n sub.mantissa = aggregation.mantissa;\n }\n }\n subscription = {\n method: \"subscribe\",\n subscription: sub,\n };\n } else if (type === \"candle\") {\n // Subscribe to candles\n const [symbol, interval] = param.split(\":\");\n const coin = symbol.split(\"-\")[0];\n subscription = {\n method: \"subscribe\",\n subscription: {\n type: \"candle\",\n coin,\n interval,\n },\n };\n } else if (type === \"userFills\") {\n // Subscribe to user fills\n const userAddress = param;\n subscription = {\n method: \"subscribe\",\n subscription: {\n type: \"userFills\",\n user: userAddress,\n },\n };\n } else if (type === \"userEvents\") {\n // Subscribe to user events (orders + positions)\n const userAddress = param;\n subscription = {\n method: \"subscribe\",\n subscription: {\n type: \"userEvents\",\n user: userAddress,\n },\n };\n } else if (type === \"accountState\") {\n // `webData2` ships every clearinghouseState / spotState / openOrders\n // snapshot for the user on a single subscription, so a single\n // socket can drive the entire account-state surface (positions,\n // available margin, spot balances, open orders) without per-field\n // REST polling.\n const userAddress = param;\n subscription = {\n method: \"subscribe\",\n subscription: {\n type: \"webData2\",\n user: userAddress,\n },\n };\n }\n\n if (subscription) {\n this.send(subscription);\n }\n }\n\n /**\n * Send unsubscription message to Hyperliquid WebSocket\n * @param type Subscription type\n * @param param Subscription parameter\n * @param aggregation Aggregation params used at subscribe time. Hyperliquid\n * matches subscriptions by full payload, so unsubscribe must echo the\n * same nSigFigs/mantissa.\n */\n private sendUnsubscription(\n type: string,\n param: string,\n aggregation?: OrderBookAggregation,\n ): void {\n let unsubscription: any;\n\n if (type === \"ticker\") {\n const coin = param.split(\"-\")[0];\n unsubscription = {\n method: \"unsubscribe\",\n subscription: {\n type: \"activeAssetCtx\",\n coin,\n },\n };\n } else if (type === \"trades\") {\n const coin = param.split(\"-\")[0];\n unsubscription = {\n method: \"unsubscribe\",\n subscription: {\n type: \"trades\",\n coin,\n },\n };\n } else if (type === \"orderBook\") {\n const coin = param.split(\"-\")[0];\n const sub: Record<string, unknown> = {\n type: \"l2Book\",\n coin,\n };\n if (aggregation?.nSigFigs !== undefined) {\n sub.nSigFigs = aggregation.nSigFigs;\n if (\n aggregation.nSigFigs === 5 &&\n aggregation.mantissa !== undefined &&\n aggregation.mantissa !== 1\n ) {\n sub.mantissa = aggregation.mantissa;\n }\n }\n unsubscription = {\n method: \"unsubscribe\",\n subscription: sub,\n };\n } else if (type === \"candle\") {\n const [symbol, interval] = param.split(\":\");\n const coin = symbol.split(\"-\")[0];\n unsubscription = {\n method: \"unsubscribe\",\n subscription: {\n type: \"candle\",\n coin,\n interval,\n },\n };\n } else if (type === \"userFills\") {\n const userAddress = param;\n unsubscription = {\n method: \"unsubscribe\",\n subscription: {\n type: \"userFills\",\n user: userAddress,\n },\n };\n } else if (type === \"userEvents\") {\n const userAddress = param;\n unsubscription = {\n method: \"unsubscribe\",\n subscription: {\n type: \"userEvents\",\n user: userAddress,\n },\n };\n } else if (type === \"accountState\") {\n const userAddress = param;\n unsubscription = {\n method: \"unsubscribe\",\n subscription: {\n type: \"webData2\",\n user: userAddress,\n },\n };\n }\n\n if (unsubscription) {\n this.send(unsubscription);\n }\n }\n\n /**\n * Subscribe to a data stream\n * @param type Subscription type\n * @param param Subscription parameter (symbol, user address, etc.)\n * @param callback Callback function to receive data\n * @param aggregation Optional `l2Book` aggregation params (only meaningful\n * when `type === \"orderBook\"`). The same params are echoed back in the\n * unsubscribe payload.\n * @returns Subscription ID (for unsubscribing). Aggregation is encoded in\n * the id so multiple aggregations of the same coin can coexist.\n */\n subscribe(\n type: string,\n param: string,\n callback: SubscriptionCallback,\n aggregation?: OrderBookAggregation,\n ): string {\n const subscriptionId = aggregationKey(type, param, aggregation);\n\n // Store subscription\n this.subscriptions.set(subscriptionId, {\n type,\n param,\n callback,\n aggregation,\n });\n\n // Send subscription message\n this.sendSubscription(type, param, aggregation);\n\n return subscriptionId;\n }\n\n /**\n * Unsubscribe from a data stream\n * @param subscriptionId Subscription ID returned from subscribe()\n */\n unsubscribe(subscriptionId: string): void {\n const subscription = this.subscriptions.get(subscriptionId);\n\n if (subscription) {\n // Send unsubscription message\n this.sendUnsubscription(\n subscription.type,\n subscription.param,\n subscription.aggregation,\n );\n\n // Remove subscription\n this.subscriptions.delete(subscriptionId);\n }\n }\n\n /**\n * Check if WebSocket is connected\n * @returns True if connected\n */\n isConnectedNow(): boolean {\n return this.isConnected;\n }\n}\n","import type {\n AccountState,\n IPerpetualsClient,\n MarketData,\n Kline,\n KlineInterval,\n KlineQueryOptions,\n Order,\n OrderBook,\n OrderType,\n Position,\n SpotBalance,\n Trade,\n PlaceOrderParams,\n PlaceOrderResult,\n CancelOrderParams,\n CancelOrderResult,\n GetPositionsParams,\n GetPositionsResult,\n GetOpenOrdersParams,\n GetOpenOrdersResult,\n GetTradesParams,\n GetTradesResult,\n ActiveAssetLeverage,\n GetActiveAssetLeverageParams,\n AssetMeta,\n GetAssetMetaParams,\n} from \"../../types\";\nimport {\n WebSocketManager,\n type OrderBookAggregation,\n} from \"./WebSocketManager\";\n\nexport type { OrderBookAggregation };\n\n/**\n * Hyperliquid 环境类型\n */\nexport type HyperliquidEnvironment = \"testnet\" | \"mainnet\";\n\n/**\n * Hyperliquid 客户端配置\n */\nexport interface HyperliquidClientConfig {\n /**\n * 环境配置\n * @default \"testnet\"\n */\n environment?: HyperliquidEnvironment;\n\n /**\n * 自定义 API 端点(可选)\n * 如果不提供,将根据 environment 自动选择\n */\n apiEndpoint?: string;\n\n /**\n * 自定义 WebSocket 端点(可选)\n * 如果不提供,将根据 environment 自动选择\n */\n wsEndpoint?: string;\n\n /**\n * 请求超时时间(毫秒)\n * @default 30000\n */\n timeout?: number;\n}\n\n/**\n * Hyperliquid API 端点配置\n */\nconst HYPERLIQUID_ENDPOINTS = {\n testnet: {\n api: \"https://api.hyperliquid-testnet.xyz\",\n ws: \"wss://api.hyperliquid-testnet.xyz/ws\",\n },\n mainnet: {\n api: \"https://api.hyperliquid.xyz\",\n ws: \"wss://api.hyperliquid.xyz/ws\",\n },\n} as const;\n\n/**\n * Cache lifetime for the asset universe (`meta` info endpoint).\n * 60 seconds is well below the cadence at which Hyperliquid actually\n * adjusts the universe (typically only on listing additions /\n * delistings, which happen weekly at most), but small enough that\n * stale caches from a previous session don't survive across page\n * loads in long-running tabs.\n */\nconst ASSET_META_TTL_MS = 60 * 1000;\n\n/**\n * HyperliquidPerpetualsClient 类\n *\n * 实现 IPerpetualsClient 接口,提供 Hyperliquid 永续合约交易功能\n */\nexport class HyperliquidPerpetualsClient implements IPerpetualsClient {\n private readonly apiEndpoint: string;\n private readonly _wsEndpoint: string;\n private readonly timeout: number;\n private readonly environment: HyperliquidEnvironment;\n private wsManager: WebSocketManager | null = null;\n /**\n * Reference count of active WebSocket consumers. The connection is\n * established on the first `connectWebSocket()` call and torn down\n * only when the last consumer disconnects — see the matching comment\n * on {@link LiberFiPerpetualsClient}.\n */\n private wsRefCount: number = 0;\n\n /**\n * Process-local memoisation of the venue's asset universe (the\n * `meta` info endpoint). Hyperliquid's universe rarely changes (new\n * listings, leverage cap adjustments) so the SDK caches the parsed\n * map for {@link ASSET_META_TTL_MS} per client instance to spare\n * downstream consumers a network round-trip on every render.\n *\n * The TanStack Query layer adds another tier of caching above this\n * (per `staleTime`), but caching here too keeps the contract correct\n * for non-React callers that talk to the client directly.\n */\n private assetMetaCache: {\n fetchedAt: number;\n map: Map<string, AssetMeta>;\n } | null = null;\n /**\n * In-flight `getAssetMeta` request, deduped so concurrent callers\n * collapse onto a single network request when the cache misses.\n */\n private assetMetaPending: Promise<Map<string, AssetMeta>> | null = null;\n\n /**\n * 构造 Hyperliquid 客户端\n *\n * @param config 客户端配置,不传则使用默认配置(testnet)\n */\n constructor(config: HyperliquidClientConfig = {}) {\n // 1. 确定环境\n this.environment = config.environment || \"testnet\";\n\n // 2. 确定 API 端点\n this.apiEndpoint =\n config.apiEndpoint || HYPERLIQUID_ENDPOINTS[this.environment].api;\n\n // 3. 确定 WebSocket 端点\n this._wsEndpoint =\n config.wsEndpoint || HYPERLIQUID_ENDPOINTS[this.environment].ws;\n\n // 4. 设置超时时间\n this.timeout = config.timeout || 30000;\n }\n\n /**\n * 内部 HTTP 请求方法\n *\n * @param endpoint API 端点路径\n * @param body 请求体\n * @returns 响应数据\n * @throws {HyperliquidApiError} API 请求失败\n */\n private async request<T = any>(endpoint: string, body: any): Promise<T> {\n const url = `${this.apiEndpoint}${endpoint}`;\n\n try {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n const response = await fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n throw new HyperliquidApiError(\n `HTTP ${response.status}: ${response.statusText}`,\n response.status,\n await response.text(),\n );\n }\n\n const data = await response.json();\n return data;\n } catch (error: any) {\n if (error.name === \"AbortError\") {\n throw new HyperliquidApiError(\n `Request timeout after ${this.timeout}ms`,\n 408,\n \"\",\n );\n }\n\n if (error instanceof HyperliquidApiError) {\n throw error;\n }\n\n throw new HyperliquidApiError(`Network error: ${error.message}`, 0, \"\");\n }\n }\n\n /**\n * 辅助方法:将符号格式转换为 Hyperliquid 币种名称\n * @param symbol 统一格式符号(例如 \"BTC-USDC\")\n * @returns Hyperliquid 币种名称(例如 \"BTC\")\n */\n private symbolToCoin(symbol: string): string {\n return symbol.split(\"-\")[0];\n }\n\n /**\n * 辅助方法:将 KlineInterval 转换为毫秒数\n * @param interval K线时间间隔\n * @returns 毫秒数\n */\n private parseInterval(interval: KlineInterval): number {\n const intervalMap: Record<KlineInterval, number> = {\n \"1m\": 60 * 1000,\n \"5m\": 5 * 60 * 1000,\n \"15m\": 15 * 60 * 1000,\n \"30m\": 30 * 60 * 1000,\n \"1h\": 60 * 60 * 1000,\n \"4h\": 4 * 60 * 60 * 1000,\n \"1d\": 24 * 60 * 60 * 1000,\n \"1w\": 7 * 24 * 60 * 60 * 1000,\n };\n return intervalMap[interval];\n }\n\n // ===================================\n // 市场数据查询接口(6个方法)\n // ===================================\n\n /**\n * 获取所有支持的币种列表\n * @returns 币种符号数组\n * @throws {HyperliquidApiError} API 请求失败\n */\n async getSupportedCoins(): Promise<string[]> {\n const [meta] = await this.request<[{ universe: Array<{ name: string }> }]>(\n \"/info\",\n { type: \"metaAndAssetCtxs\" },\n );\n\n // 转换:coin.name -> \"BTC-USDC\"\n return meta.universe.map((asset) => `${asset.name}-USDC`);\n }\n\n /**\n * 获取指定币种的市场数据\n * @param symbol 币种符号\n * @returns 市场数据,币种不存在时返回 null\n * @throws {HyperliquidApiError} API 请求失败\n */\n async getMarket(symbol: string): Promise<MarketData | null> {\n const markets = await this.getMarkets([symbol]);\n return markets.length > 0 ? markets[0] : null;\n }\n\n /**\n * 获取多个或所有币种的市场数据\n * @param symbols 币种符号数组(可选)\n * @returns 市场数据数组\n * @throws {HyperliquidApiError} API 请求失败\n */\n async getMarkets(symbols?: string[]): Promise<MarketData[]> {\n const [meta, assetCtxs] = await this.request<\n [\n { universe: Array<{ name: string }> },\n Array<{\n funding?: string;\n openInterest?: string;\n prevDayPx?: string;\n dayNtlVlm?: string;\n oraclePx?: string;\n markPx?: string;\n midPx?: string;\n }>,\n ]\n >(\"/info\", { type: \"metaAndAssetCtxs\" });\n\n // 合并 meta 和 assetCtxs 数据\n const allMarkets = meta.universe.map((asset, index) => {\n const ctx = assetCtxs[index];\n const symbol = `${asset.name}-USDC`;\n\n // 使用 midPx 作为当前价格,fallback 到 markPx\n const currentPrice = parseFloat(ctx.midPx || ctx.markPx || \"0\");\n const prevPrice = ctx.prevDayPx\n ? parseFloat(ctx.prevDayPx)\n : currentPrice;\n const change24h =\n prevPrice > 0 ? ((currentPrice - prevPrice) / prevPrice) * 100 : 0;\n\n return {\n symbol,\n price: currentPrice,\n change24h,\n volume24h: parseFloat(ctx.dayNtlVlm || \"0\"),\n fundingRate: parseFloat(ctx.funding || \"0\"),\n openInterest: parseFloat(ctx.openInterest || \"0\"),\n markPrice: parseFloat(ctx.markPx || \"0\"),\n indexPrice: parseFloat(ctx.oraclePx || ctx.midPx || \"0\"),\n } as MarketData;\n });\n\n // 如果指定了 symbols,进行过滤\n if (symbols && symbols.length > 0) {\n const symbolSet = new Set(symbols);\n return allMarkets.filter((m) => symbolSet.has(m.symbol));\n }\n\n return allMarkets;\n }\n\n /**\n * Fetch kline / candlestick data.\n *\n * Supports both shapes documented on\n * {@link IPerpetualsClient.getKlines}:\n *\n * - `getKlines(symbol, interval, limit)` — last `limit` candles ending now.\n * - `getKlines(symbol, interval, { from, to, limit? })` — explicit window\n * for backward history pagination (TradingView pan).\n *\n * Maps to Hyperliquid's `candleSnapshot` which natively accepts\n * `startTime` / `endTime` (ms epochs).\n *\n * @throws {HyperliquidApiError}\n */\n async getKlines(\n symbol: string,\n interval: KlineInterval,\n limitOrOptions: number | KlineQueryOptions = 100,\n ): Promise<Kline[]> {\n const coin = this.symbolToCoin(symbol);\n const options: KlineQueryOptions =\n typeof limitOrOptions === \"number\"\n ? { limit: limitOrOptions }\n : limitOrOptions;\n\n const intervalMs = this.parseInterval(interval);\n const limit = options.limit;\n\n // Resolve the [startTime, endTime] window:\n // - Range mode: caller provides from/to → use them directly.\n // - Legacy mode: derive a [now - limit*interval, now] window.\n // - Mixed: range with limit → honor the explicit window, slice to limit.\n let startTime: number;\n let endTime: number;\n if (options.from !== undefined && options.to !== undefined) {\n startTime = options.from;\n endTime = options.to;\n } else if (options.to !== undefined && limit) {\n endTime = options.to;\n startTime = endTime - intervalMs * limit;\n } else if (options.from !== undefined && limit) {\n startTime = options.from;\n endTime = startTime + intervalMs * limit;\n } else {\n endTime = Date.now();\n startTime = endTime - intervalMs * (limit ?? 100);\n }\n\n const data = await this.request<\n Array<{\n t: number;\n T: number;\n s: string;\n i: string;\n o: string;\n c: string;\n h: string;\n l: string;\n v: string;\n n: number;\n }>\n >(\"/info\", {\n type: \"candleSnapshot\",\n req: { coin, interval, startTime, endTime },\n });\n\n let bars: Kline[] = data.map((candle) => ({\n symbol,\n open: parseFloat(candle.o),\n high: parseFloat(candle.h),\n low: parseFloat(candle.l),\n close: parseFloat(candle.c),\n volume: parseFloat(candle.v),\n timestamp: candle.t,\n closeTimestamp: candle.T,\n }));\n\n // When the caller asked for a hard cap (limit), keep the most recent N.\n if (limit && bars.length > limit) {\n bars = bars.slice(bars.length - limit);\n }\n return bars;\n }\n\n /**\n * Get the order book.\n *\n * @param symbol Trading pair symbol (e.g. `BTC-USDC`)\n * @param maxLevel Max number of levels to keep per side (post-slice)\n * @param options Optional Hyperliquid `l2Book` aggregation params. When\n * provided, Hyperliquid pre-aggregates raw levels into discrete buckets\n * server-side, so a single 20-level snapshot covers a much wider price\n * range than at native tick resolution. See {@link OrderBookAggregation}.\n * @returns Order book data\n * @throws {HyperliquidApiError} API 请求失败\n */\n async getOrderBook(\n symbol: string,\n maxLevel: number = 10,\n options?: OrderBookAggregation,\n ): Promise<OrderBook> {\n const coin = this.symbolToCoin(symbol);\n\n const body: Record<string, unknown> = { type: \"l2Book\", coin };\n if (options?.nSigFigs !== undefined) {\n body.nSigFigs = options.nSigFigs;\n if (\n options.nSigFigs === 5 &&\n options.mantissa !== undefined &&\n options.mantissa !== 1\n ) {\n body.mantissa = options.mantissa;\n }\n }\n\n const data = await this.request<{\n coin: string;\n time: number;\n levels: [\n Array<{ px: string; sz: string; n: number }>,\n Array<{ px: string; sz: string; n: number }>,\n ];\n }>(\"/info\", body);\n\n const [bids, asks] = data.levels;\n\n return {\n symbol,\n bids: bids.slice(0, maxLevel).map((level) => ({\n price: parseFloat(level.px),\n quantity: parseFloat(level.sz),\n count: level.n,\n })),\n asks: asks.slice(0, maxLevel).map((level) => ({\n price: parseFloat(level.px),\n quantity: parseFloat(level.sz),\n count: level.n,\n })),\n timestamp: data.time,\n };\n }\n\n /**\n * 获取最近成交记录\n * @param symbol 交易对符号\n * @param limit 最大成交记录数\n * @returns 成交记录数组\n * @throws {HyperliquidApiError} API 请求失败\n */\n async getRecentTrades(symbol: string, limit: number = 50): Promise<Trade[]> {\n const coin = this.symbolToCoin(symbol);\n\n const data = await this.request<\n Array<{\n coin: string;\n side: string;\n px: string;\n sz: string;\n time: number;\n tid: number;\n }>\n >(\"/info\", { type: \"recentTrades\", coin });\n\n return data.slice(0, limit).map((trade) => ({\n symbol,\n side: trade.side === \"B\" ? \"buy\" : \"sell\",\n price: parseFloat(trade.px),\n quantity: parseFloat(trade.sz),\n timestamp: trade.time,\n tradeId: trade.tid,\n }));\n }\n\n // ===================================\n // 交易操作接口(2个方法)\n // ===================================\n\n /**\n * 下单(买入或卖出合约)\n *\n * ⚠️ 注意:此方法需要配置钱包私钥进行 EIP-712 签名认证\n *\n * @param params 下单参数\n * @returns 下单结果\n * @throws {HyperliquidApiError} API 请求失败、余额不足、参数错误等\n * @throws {Error} 未配置认证信息\n *\n * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint\n */\n async placeOrder(_params: PlaceOrderParams): Promise<PlaceOrderResult> {\n throw new Error(\n \"placeOrder() requires wallet private key configuration for EIP-712 signature. \" +\n \"Please configure authentication before calling this method. \" +\n \"See: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint\",\n );\n }\n\n /**\n * 取消订单\n *\n * ⚠️ 注意:此方法需要配置钱包私钥进行 EIP-712 签名认证\n *\n * @param params 取消订单参数\n * @returns 取消订单结果\n * @throws {HyperliquidApiError} API 请求失败、订单不存在等\n * @throws {Error} 未配置认证信息\n *\n * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint\n */\n async cancelOrder(_params: CancelOrderParams): Promise<CancelOrderResult> {\n throw new Error(\n \"cancelOrder() requires wallet private key configuration for EIP-712 signature. \" +\n \"Please configure authentication before calling this method. \" +\n \"See: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint\",\n );\n }\n\n // ===================================\n // 账户查询接口(3个方法)\n // ===================================\n\n /**\n * 获取用户持仓信息\n *\n * ⚠️ Hyperliquid 要求:必须提供 userAddress 参数\n *\n * @param params 查询参数\n * @returns 持仓结果\n * @throws {HyperliquidApiError} API 请求失败\n * @throws {Error} 缺少必需参数\n */\n async getPositions(\n params: GetPositionsParams = {},\n ): Promise<GetPositionsResult> {\n if (!params.userAddress) {\n throw new Error(\n \"Hyperliquid requires userAddress parameter. \" +\n \"Example: { userAddress: '0x...' }\",\n );\n }\n\n // Fan three info reads out in parallel — clearinghouseState gives us\n // the positions skeleton, frontendOpenOrders supplies the TP/SL\n // trigger prices we enrich each position with, and metaAndAssetCtxs\n // delivers the live mark price (which clearinghouseState alone does\n // not provide). We use `Promise.all` instead of three sequential\n // awaits so the slowest leg dominates the latency, not their sum.\n const [clearinghouse, openOrdersRaw, metaAndCtxs] = await Promise.all([\n this.request<HyperliquidClearinghouseState>(\"/info\", {\n type: \"clearinghouseState\",\n user: params.userAddress,\n }),\n this.request<HyperliquidOpenOrder[]>(\"/info\", {\n type: \"frontendOpenOrders\",\n user: params.userAddress,\n }),\n this.request<\n [\n { universe: Array<{ name: string }> },\n Array<{ markPx?: string; midPx?: string }>,\n ]\n >(\"/info\", { type: \"metaAndAssetCtxs\" }),\n ]);\n\n const result = parseClearinghouseState(clearinghouse, params.symbol);\n const markByCoin = buildMarkPriceMap(metaAndCtxs);\n result.positions = enrichPositions(\n result.positions,\n openOrdersRaw,\n markByCoin,\n );\n // Recompute aggregate PnL since per-position PnL may have been\n // recomputed against a fresher mark price.\n result.totalUnrealizedPnl = result.positions.reduce(\n (sum, p) => sum + p.unrealizedPnl,\n 0,\n );\n return result;\n }\n\n /**\n * Read the user's per-asset leverage configuration via the\n * `activeAssetData` info endpoint. This works whether or not an open\n * position exists for the asset, so the UI can render the latest\n * configured leverage on a fresh page load.\n *\n * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint/perpetuals#retrieve-users-active-asset-data\n */\n async getActiveAssetLeverage(\n params: GetActiveAssetLeverageParams,\n ): Promise<ActiveAssetLeverage | null> {\n const coin = this.symbolToCoin(params.symbol);\n try {\n const data = await this.request<{\n leverage:\n | { type: \"isolated\"; value: number; rawUsd: string }\n | { type: \"cross\"; value: number };\n }>(\"/info\", {\n type: \"activeAssetData\",\n coin,\n user: params.userAddress,\n });\n\n const lev = data?.leverage;\n if (!lev || typeof lev.value !== \"number\") return null;\n return { value: lev.value, type: lev.type };\n } catch (error) {\n // The endpoint returns an error for unknown coins / users; treat\n // it as \"no data\" so the form falls back to its own default\n // instead of surfacing a transient network blip to the user.\n if (\n error instanceof HyperliquidApiError &&\n (error.statusCode === 422 || error.statusCode === 400)\n ) {\n return null;\n }\n throw error;\n }\n }\n\n /**\n * Fetch the venue's static metadata for `params.symbol` (currently\n * `szDecimals` and `maxLeverage`). Backed by Hyperliquid's `meta`\n * info endpoint, with an in-memory cache keyed on this client\n * instance and TTL'd at {@link ASSET_META_TTL_MS}.\n *\n * Returns `null` when the symbol isn't part of the universe so\n * downstream consumers can branch on absence without try/catching\n * lookups for unsupported coins.\n *\n * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint/perpetuals#retrieve-perpetuals-metadata\n */\n async getAssetMeta(params: GetAssetMetaParams): Promise<AssetMeta | null> {\n const universe = await this.fetchAssetUniverse();\n const coin = this.symbolToCoin(params.symbol);\n return universe.get(coin) ?? null;\n }\n\n /**\n * Internal: ensure {@link assetMetaCache} is populated and fresh,\n * then return the resolved coin → {@link AssetMeta} map. Concurrent\n * cache misses share a single in-flight request via\n * {@link assetMetaPending}.\n */\n private async fetchAssetUniverse(): Promise<Map<string, AssetMeta>> {\n const now = Date.now();\n if (\n this.assetMetaCache &&\n now - this.assetMetaCache.fetchedAt < ASSET_META_TTL_MS\n ) {\n return this.assetMetaCache.map;\n }\n if (this.assetMetaPending) {\n return this.assetMetaPending;\n }\n\n const fetchPromise = (async () => {\n const data = await this.request<{\n universe: Array<{\n name: string;\n szDecimals: number;\n maxLeverage?: number;\n }>;\n }>(\"/info\", { type: \"meta\" });\n\n const map = new Map<string, AssetMeta>();\n for (const asset of data.universe) {\n if (!asset || typeof asset.name !== \"string\") continue;\n if (typeof asset.szDecimals !== \"number\") continue;\n map.set(asset.name, {\n szDecimals: asset.szDecimals,\n maxLeverage: asset.maxLeverage,\n });\n }\n this.assetMetaCache = { fetchedAt: Date.now(), map };\n return map;\n })();\n\n this.assetMetaPending = fetchPromise;\n try {\n return await fetchPromise;\n } finally {\n // Clear regardless of outcome so a transient failure doesn't\n // pin every future caller to a rejected promise.\n this.assetMetaPending = null;\n }\n }\n\n /**\n * 获取用户挂单信息\n *\n * ⚠️ Hyperliquid 要求:必须提供 userAddress 参数\n *\n * @param params 查询参数\n * @returns 挂单结果\n * @throws {HyperliquidApiError} API 请求失败\n * @throws {Error} 缺少必需参数\n */\n async getOpenOrders(\n params: GetOpenOrdersParams = {},\n ): Promise<GetOpenOrdersResult> {\n if (!params.userAddress) {\n throw new Error(\n \"Hyperliquid requires userAddress parameter. \" +\n \"Example: { userAddress: '0x...' }\",\n );\n }\n\n const data = await this.request<HyperliquidOpenOrder[]>(\"/info\", {\n type: \"openOrders\",\n user: params.userAddress,\n });\n\n const orders = data.map(parseOpenOrder);\n const filteredOrders = params.symbol\n ? orders.filter((o) => o.symbol === params.symbol)\n : orders;\n\n return {\n orders: filteredOrders,\n totalCount: filteredOrders.length,\n raw: data,\n };\n }\n\n /**\n * 获取用户交易历史\n *\n * ⚠️ Hyperliquid 要求:必须提供 userAddress 参数\n *\n * @param params 查询参数\n * @returns 交易历史结果\n * @throws {HyperliquidApiError} API 请求失败\n * @throws {Error} 缺少必需参数\n */\n async getTrades(params: GetTradesParams = {}): Promise<GetTradesResult> {\n if (!params.userAddress) {\n throw new Error(\n \"Hyperliquid requires userAddress parameter. \" +\n \"Example: { userAddress: '0x...' }\",\n );\n }\n\n const data = await this.request<\n Array<{\n coin: string;\n side: string;\n px: string;\n sz: string;\n time: number;\n dir: string;\n oid: number;\n tid: number;\n fee?: string;\n feeToken?: string;\n }>\n >(\"/info\", { type: \"userFills\", user: params.userAddress });\n\n // 转换交易数据\n let trades = data.map((fill) => {\n const symbol = `${fill.coin}-USDC`;\n const isLong = fill.dir.includes(\"Long\");\n\n return {\n tradeId: fill.tid.toString(),\n orderId: fill.oid.toString(),\n symbol,\n side: isLong ? (\"long\" as const) : (\"short\" as const),\n price: parseFloat(fill.px),\n quantity: parseFloat(fill.sz),\n fee: parseFloat(fill.fee || \"0\"),\n feeCurrency: fill.feeToken || \"USDC\",\n isMaker: fill.side === \"M\", // \"M\" = Maker, \"T\" = Taker\n timestamp: fill.time,\n };\n });\n\n // 过滤指定币种\n if (params.symbol) {\n trades = trades.filter((t) => t.symbol === params.symbol);\n }\n\n // 过滤时间范围\n if (params.startTime) {\n trades = trades.filter((t) => t.timestamp >= params.startTime!);\n }\n if (params.endTime) {\n trades = trades.filter((t) => t.timestamp <= params.endTime!);\n }\n\n // 限制返回数量\n if (params.limit) {\n trades = trades.slice(0, params.limit);\n }\n\n return {\n trades,\n totalCount: trades.length,\n raw: data,\n };\n }\n\n // ===================================\n // WebSocket 连接管理(2个方法)\n // ===================================\n\n /**\n * Connect to WebSocket server\n *\n * Establishes WebSocket connection for real-time data streaming.\n * Connection will auto-reconnect on disconnect.\n *\n * @throws {Error} Connection failed\n */\n async connectWebSocket(): Promise<void> {\n this.wsRefCount += 1;\n if (!this.wsManager) {\n this.wsManager = new WebSocketManager(this._wsEndpoint);\n }\n\n if (this.wsManager.isConnectedNow()) {\n return;\n }\n\n await this.wsManager.connect();\n }\n\n /**\n * Disconnect from WebSocket server\n *\n * Decrements the consumer ref count. The underlying socket is closed\n * only when the last consumer disconnects, so concurrent widgets\n * (order book, trades, ticker) can mount/unmount independently\n * without stealing each other's stream.\n */\n disconnectWebSocket(): void {\n this.wsRefCount = Math.max(0, this.wsRefCount - 1);\n if (this.wsRefCount === 0 && this.wsManager) {\n this.wsManager.disconnect();\n this.wsManager = null;\n }\n }\n\n // ===================================\n // WebSocket 订阅(4个方法)\n // ===================================\n\n /**\n * Subscribe to market data (price, trades, order book)\n *\n * @param type Subscription type: 'ticker' | 'trades' | 'orderBook'\n * @param symbol Trading pair symbol (e.g., \"BTC-USDC\")\n * @param callback Data callback function\n * @param options Optional subscription options. For `orderBook`, provide\n * `aggregation` (Hyperliquid `nSigFigs` / `mantissa`) so the server\n * pre-aggregates levels into discrete price buckets — required to render\n * wide-range books at coarse aggregation steps (e.g. $1000 buckets).\n * @returns Subscription ID (for unsubscribing)\n */\n subscribeMarketData(\n type: \"ticker\" | \"trades\" | \"orderBook\",\n symbol: string,\n callback: (data: any) => void,\n options?: { aggregation?: OrderBookAggregation },\n ): string {\n if (!this.wsManager) {\n throw new Error(\n \"WebSocket not connected. Call connectWebSocket() first.\",\n );\n }\n\n return this.wsManager.subscribe(\n type,\n symbol,\n callback,\n options?.aggregation,\n );\n }\n\n /**\n * Subscribe to kline (candlestick) data\n *\n * @param symbol Trading pair symbol (e.g., \"BTC-USDC\")\n * @param interval Time interval (e.g., \"1m\", \"1h\", \"1d\")\n * @param callback Data callback function\n * @returns Subscription ID (for unsubscribing)\n */\n subscribeCandles(\n symbol: string,\n interval: KlineInterval,\n callback: (candle: Kline) => void,\n ): string {\n if (!this.wsManager) {\n throw new Error(\n \"WebSocket not connected. Call connectWebSocket() first.\",\n );\n }\n\n // Combine symbol and interval as parameter\n const param = `${symbol}:${interval}`;\n return this.wsManager.subscribe(\"candle\", param, callback);\n }\n\n /**\n * Subscribe to user data (orders, positions, fills)\n *\n * @param type Subscription type: 'orders' | 'positions' | 'fills'\n * @param userAddress User wallet address\n * @param callback Data callback function\n * @returns Subscription ID (for unsubscribing)\n */\n subscribeUserData(\n type: \"orders\" | \"positions\" | \"fills\",\n userAddress: string,\n callback: (data: any) => void,\n ): string {\n if (!this.wsManager) {\n throw new Error(\n \"WebSocket not connected. Call connectWebSocket() first.\",\n );\n }\n\n // Use userEvents for orders and positions, userFills for fills\n const subscriptionType = type === \"fills\" ? \"userFills\" : \"userEvents\";\n\n return this.wsManager.subscribe(subscriptionType, userAddress, callback);\n }\n\n /**\n * Subscribe to the user's full account state via Hyperliquid's\n * `webData2` channel. Each push carries a complete snapshot of:\n *\n * - `clearinghouseState` — perp positions, margin summaries, and the\n * `withdrawable` figure used as \"Available Margin\".\n * - `spotState` — spot wallet balances (USDC, USOL, etc.).\n * - `openOrders` — the user's resting limit orders.\n *\n * Replaces three separate REST polls (`clearinghouseState`,\n * `spotClearinghouseState`, `openOrders`) with a single push channel.\n * Hooks like `useAccountStateSubscription` use this to seed React\n * Query caches in real time so consumers see fills / margin moves\n * the moment Hyperliquid pushes them.\n *\n * @param userAddress Wallet address whose state to track.\n * @param callback Receives the canonical {@link AccountState} on\n * every push (raw payload available on `state.raw`).\n * @returns Subscription ID for {@link unsubscribe}.\n *\n * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/websocket/subscriptions#webdata2\n */\n subscribeAccountState(\n userAddress: string,\n callback: (state: AccountState) => void,\n ): string {\n if (!this.wsManager) {\n throw new Error(\n \"WebSocket not connected. Call connectWebSocket() first.\",\n );\n }\n\n // Funnel raw `webData2` payloads through the same parser as the\n // REST `clearinghouseState` / `openOrders` paths so positions /\n // available margin / open orders look identical regardless of\n // transport. Single source of truth for the venue → SDK shape\n // conversion.\n return this.wsManager.subscribe(\n \"accountState\",\n userAddress,\n (raw: HyperliquidWebData2Payload) => {\n callback(parseWebData2(raw));\n },\n );\n }\n\n /**\n * Unsubscribe from a data stream\n *\n * @param subscriptionId Subscription ID returned from subscribe methods\n */\n unsubscribe(subscriptionId: string): void {\n if (this.wsManager) {\n this.wsManager.unsubscribe(subscriptionId);\n }\n }\n}\n\n// ===================================\n// Hyperliquid wire-format helpers\n// ===================================\n\n/**\n * Raw shape of Hyperliquid's `clearinghouseState` (REST + the inner\n * payload of `webData2`). Captured here so REST and WS code paths share\n * a single type definition — drift between the two would silently break\n * the cache write-through that powers `useAccountStateSubscription`.\n */\ninterface HyperliquidClearinghouseState {\n assetPositions: Array<{\n position: {\n coin: string;\n szi: string;\n leverage: { type: string; value: number };\n entryPx: string;\n positionValue: string;\n unrealizedPnl: string;\n returnOnEquity: string;\n liquidationPx: string | null;\n marginUsed: string;\n };\n }>;\n marginSummary: {\n accountValue: string;\n totalMarginUsed: string;\n totalNtlPos: string;\n totalRawUsd: string;\n };\n crossMarginSummary: {\n accountValue: string;\n totalMarginUsed: string;\n totalNtlPos: string;\n totalRawUsd: string;\n };\n /**\n * \"Available to spend on a new isolated trade or to withdraw\" —\n * Hyperliquid's canonical figure that already accounts for cross\n * margin reservations and the venue's protocol-level safety buffer\n * (typically the maintenance + initial margin overlap).\n *\n * For a wallet with no open positions this equals\n * `crossMarginSummary.accountValue`, but as soon as the account\n * mixes isolated and cross positions it diverges. Axiom's order\n * panel uses this exact field as \"Available Margin\", so we mirror\n * it for parity.\n */\n withdrawable: string;\n}\n\n/**\n * Hyperliquid open order shape. `frontendOpenOrders` returns a richer\n * payload than the basic `openOrders` endpoint — including\n * `triggerPx` / `triggerCondition` / `isTrigger` / `reduceOnly`, which\n * we need to compute per-position TP/SL.\n *\n * Fields are typed loose where the venue's wire format is loose\n * (`side` is the string \"A\" / \"B\" on `frontendOpenOrders`, but a\n * boolean on `webData2`'s `openOrders` — the parser handles both).\n */\ninterface HyperliquidOpenOrder {\n coin: string;\n /**\n * Side encoding varies by endpoint:\n * - `frontendOpenOrders` REST → string `\"A\"` (Ask/Sell) | `\"B\"` (Buy)\n * - `webData2` push → boolean `true` (Buy) | `false` (Sell)\n * - basic `openOrders` REST → boolean (same as webData2)\n * We accept both and normalise in {@link parseOpenOrder}.\n */\n side: boolean | \"A\" | \"B\";\n limitPx: string;\n sz: string;\n origSz: string;\n oid: number;\n cloid?: string | null;\n timestamp: number;\n /**\n * Human-readable order type from the venue, e.g.\n * `\"Limit\"`, `\"Stop Market\"`, `\"Take Profit Market\"`,\n * `\"Stop Limit\"`, `\"Take Profit Limit\"`, `\"Market\"`.\n * `frontendOpenOrders` returns this as a string; the basic\n * `openOrders` endpoint returns a structured object — both are\n * tolerated here via the `unknown` widening.\n */\n orderType?: string | { limit?: unknown; trigger?: unknown };\n /** True when the order is a trigger order (stop / take-profit / etc). */\n isTrigger?: boolean;\n /** Trigger price as a stringified decimal (only meaningful when isTrigger). */\n triggerPx?: string;\n /** Human-readable trigger condition, e.g. \"Price above 81470\" or \"N/A\". */\n triggerCondition?: string;\n reduceOnly?: boolean;\n /** Position TP/SL (HL `positionTpsl` grouping) flag. */\n isPositionTpsl?: boolean;\n tif?: string | null;\n children?: unknown[];\n}\n\ninterface HyperliquidSpotBalance {\n coin: string;\n total: string;\n hold: string;\n entryNtl?: string;\n}\n\ninterface HyperliquidWebData2Payload {\n clearinghouseState?: HyperliquidClearinghouseState;\n spotState?: { balances?: HyperliquidSpotBalance[] };\n /**\n * `webData2` exposes the user's resting orders under `openOrders`,\n * but historically the basic `openOrders` info endpoint and the\n * richer `frontendOpenOrders` shape are both possible payloads.\n * Some venue snapshots have surfaced trigger fields here too — keep\n * the parser tolerant.\n */\n openOrders?: HyperliquidOpenOrder[];\n /**\n * Asset universe (perp contracts) used to map a position's `coin`\n * back to the matching index in `assetCtxs`. Mirrors the response\n * of the `meta` info endpoint.\n */\n meta?: { universe: Array<{ name: string }> };\n /**\n * Per-asset live context: includes `markPx`, `oraclePx`, funding,\n * `dayNtlVlm`. Indexed parallel to `meta.universe`.\n */\n assetCtxs?: Array<{\n markPx?: string;\n midPx?: string;\n oraclePx?: string;\n funding?: string;\n openInterest?: string;\n dayNtlVlm?: string;\n }>;\n serverTime?: number;\n}\n\n/**\n * Translate a `clearinghouseState` payload to the SDK's\n * {@link GetPositionsResult} shape. Used by both the REST `getPositions`\n * call and the WS `webData2` push, keeping the venue→SDK mapping in one\n * place — drift between the two would let the cache write-through ship\n * subtly different objects than the polling path.\n */\nfunction parseClearinghouseState(\n data: HyperliquidClearinghouseState,\n symbolFilter?: string,\n): GetPositionsResult {\n const positions = data.assetPositions\n .map((assetPos) => {\n const pos = assetPos.position;\n const symbol = `${pos.coin}-USDC`;\n const quantity = parseFloat(pos.szi);\n\n if (quantity === 0) {\n return null;\n }\n\n const entryPrice = parseFloat(pos.entryPx);\n const unrealizedPnl = parseFloat(pos.unrealizedPnl);\n const positionValue = parseFloat(pos.positionValue);\n\n const position: Position = {\n symbol,\n side: quantity > 0 ? \"long\" : \"short\",\n quantity: Math.abs(quantity),\n // Strip the sign so consumers can render the absolute size\n // alongside a Long/Short prefix (e.g. \"Long 0.00045 BTC\")\n // without manually parsing the venue string.\n quantityRaw: pos.szi.startsWith(\"-\") ? pos.szi.slice(1) : pos.szi,\n entryPrice,\n markPrice: entryPrice, // Hyperliquid 不直接提供,可从 assetCtxs 获取\n unrealizedPnl,\n unrealizedPnlPercent: parseFloat(pos.returnOnEquity) * 100,\n leverage: pos.leverage.value,\n liquidationPrice: pos.liquidationPx\n ? parseFloat(pos.liquidationPx)\n : undefined,\n margin: parseFloat(pos.marginUsed),\n notionalValue: Math.abs(positionValue),\n };\n return position;\n })\n .filter((p): p is Position => p !== null);\n\n const filteredPositions = symbolFilter\n ? positions.filter((p) => p.symbol === symbolFilter)\n : positions;\n\n // Prefer the venue's `withdrawable` field as the source of truth for\n // \"available margin\": it already accounts for the maintenance buffer\n // that `accountValue - totalMarginUsed` overstates whenever isolated\n // and cross positions coexist. Older payloads (or future schema\n // shifts) may omit it, so we fall back to the legacy formula.\n const withdrawableRaw = data.withdrawable;\n const availableBalance =\n typeof withdrawableRaw === \"string\" && withdrawableRaw.length > 0\n ? parseFloat(withdrawableRaw)\n : parseFloat(data.marginSummary.accountValue) -\n parseFloat(data.marginSummary.totalMarginUsed);\n\n return {\n positions: filteredPositions,\n totalEquity: parseFloat(data.marginSummary.accountValue),\n availableBalance,\n totalUnrealizedPnl: filteredPositions.reduce(\n (sum, p) => sum + p.unrealizedPnl,\n 0,\n ),\n raw: data,\n };\n}\n\n/**\n * Translate Hyperliquid's open-order wire format to the SDK's\n * {@link Order} shape. Handles both `frontendOpenOrders` (string side\n * `\"A\"/\"B\"`, raw `orderType` strings, trigger fields) and the simpler\n * `webData2.openOrders` push (boolean side, no trigger metadata).\n */\nfunction parseOpenOrder(order: HyperliquidOpenOrder): Order {\n const symbol = `${order.coin}-USDC`;\n const origSz = parseFloat(order.origSz);\n const remainingSz = parseFloat(order.sz);\n const filledSz = origSz - remainingSz;\n\n // Normalise side: `\"A\"` / `false` → sell/short close; `\"B\"` / `true`\n // → buy/long. The SDK's `Order.side` represents the order's\n // direction (not the position direction), so we map directly.\n const isBuySide = order.side === true || order.side === \"B\";\n\n // Normalise orderType to a \"Limit\" / \"Market\" baseline. The richer\n // trigger info goes into the dedicated trigger fields below — leaving\n // `orderType` as a strict `\"limit\" | \"market\"` keeps the existing\n // OpenOrders UI working without a breaking refactor.\n const rawOrderType =\n typeof order.orderType === \"string\" ? order.orderType : \"Limit\";\n const isMarket = /^market$/i.test(rawOrderType);\n const baseOrderType: OrderType = isMarket ? \"market\" : \"limit\";\n\n // Trigger discriminator: HL uses the human-readable strings\n // \"Take Profit Market\" / \"Take Profit Limit\" / \"Stop Market\" /\n // \"Stop Limit\" — all four collapse to the binary tp/sl axis the\n // positions table cares about.\n const isTrigger = order.isTrigger === true;\n let triggerType: \"tp\" | \"sl\" | undefined;\n if (isTrigger) {\n if (/take\\s*profit/i.test(rawOrderType)) triggerType = \"tp\";\n else if (/stop/i.test(rawOrderType)) triggerType = \"sl\";\n }\n const triggerPx =\n typeof order.triggerPx === \"string\" && order.triggerPx.length > 0\n ? parseFloat(order.triggerPx)\n : undefined;\n const triggerCondition =\n typeof order.triggerCondition === \"string\" &&\n order.triggerCondition !== \"N/A\"\n ? order.triggerCondition\n : undefined;\n\n return {\n orderId: order.oid.toString(),\n clientOrderId: order.cloid ?? undefined,\n symbol,\n side: isBuySide ? \"long\" : \"short\",\n orderType: baseOrderType,\n price: parseFloat(order.limitPx),\n quantity: origSz,\n filledQuantity: filledSz,\n remainingQuantity: remainingSz,\n status: filledSz > 0 && remainingSz > 0 ? \"partially_filled\" : \"pending\",\n timestamp: order.timestamp,\n updateTimestamp: order.timestamp,\n reduceOnly: order.reduceOnly === true,\n isTrigger: isTrigger || undefined,\n triggerPx,\n triggerType,\n triggerCondition,\n };\n}\n\nfunction parseSpotBalances(\n balances: HyperliquidSpotBalance[] | undefined,\n): SpotBalance[] {\n if (!balances) return [];\n return balances.map((b) => ({\n coin: b.coin,\n total: parseFloat(b.total),\n // Preserve the venue's exact decimal precision for display —\n // round-tripping through `Number` can flip \"0.00000005\" into\n // scientific notation and drop trailing zeros that the UI cares\n // about.\n totalRaw: b.total,\n hold: parseFloat(b.hold),\n entryNotional: b.entryNtl ? parseFloat(b.entryNtl) : undefined,\n }));\n}\n\n/**\n * Translate Hyperliquid's `webData2` push to the SDK's\n * {@link AccountState} shape. Reuses {@link parseClearinghouseState} so\n * positions / available margin look identical to the REST path, then\n * enriches each position with:\n * - active TP/SL trigger prices (from `openOrders`)\n * - live mark price + recomputed PnL (from `meta` + `assetCtxs`)\n *\n * Both enrichments are no-ops when the inputs are missing — older\n * webData2 snapshots without `assetCtxs` simply leave `markPrice`\n * pointed at the entry-price placeholder, so the function stays\n * forward-compatible with venue payload churn.\n */\nfunction parseWebData2(raw: HyperliquidWebData2Payload): AccountState {\n const clearinghouse = raw.clearinghouseState;\n const positionsResult = clearinghouse\n ? parseClearinghouseState(clearinghouse)\n : {\n positions: [],\n totalEquity: 0,\n availableBalance: 0,\n totalUnrealizedPnl: 0,\n };\n\n const openOrdersRaw = raw.openOrders ?? [];\n const openOrders = openOrdersRaw.map(parseOpenOrder);\n const spotBalances = parseSpotBalances(raw.spotState?.balances);\n\n // Enrich positions: TP/SL from open trigger orders + live mark price\n // from assetCtxs. Done after the main parse so the enrichment logic\n // stays decoupled from the clearinghouse->Position transform and can\n // be unit-tested in isolation.\n const markByCoin =\n raw.meta && raw.assetCtxs\n ? buildMarkPriceMap([raw.meta, raw.assetCtxs])\n : null;\n\n const enrichedPositions = enrichPositions(\n positionsResult.positions,\n openOrdersRaw,\n markByCoin,\n );\n\n // Aggregate PnL has to be recomputed because per-position PnL may\n // have shifted when we re-marked it against the live `markPx`.\n const totalUnrealizedPnl = enrichedPositions.reduce(\n (sum, p) => sum + p.unrealizedPnl,\n 0,\n );\n\n return {\n positions: enrichedPositions,\n openOrders,\n spotBalances,\n totalEquity: positionsResult.totalEquity ?? 0,\n availableBalance: positionsResult.availableBalance ?? 0,\n totalUnrealizedPnl,\n serverTime: raw.serverTime,\n raw,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Enrichment helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Build a `coin → markPrice` lookup from Hyperliquid's\n * `metaAndAssetCtxs` tuple. Falls back to `midPx` / `oraclePx` when\n * `markPx` is absent — the exact field hierarchy mirrors the existing\n * {@link HyperliquidPerpetualsClient.getMarkets} behaviour so all\n * consumers see the same \"current price\" definition.\n */\nfunction buildMarkPriceMap(\n metaAndCtxs: [\n { universe: Array<{ name: string }> },\n Array<{ markPx?: string; midPx?: string; oraclePx?: string }>,\n ],\n): Map<string, number> {\n const [meta, ctxs] = metaAndCtxs;\n const map = new Map<string, number>();\n meta.universe.forEach((asset, index) => {\n const ctx = ctxs[index];\n if (!ctx) return;\n const raw = ctx.markPx ?? ctx.midPx ?? ctx.oraclePx;\n if (typeof raw !== \"string\" || raw.length === 0) return;\n const px = parseFloat(raw);\n if (Number.isFinite(px) && px > 0) {\n map.set(asset.name, px);\n }\n });\n return map;\n}\n\n/**\n * Pick the take-profit and stop-loss trigger prices that would\n * actually close `position`. Filtering rules:\n *\n * 1. `coin` matches the position's coin.\n * 2. `reduceOnly === true` — non-reduce-only triggers can flip the\n * position direction, not close it, so they don't belong in the\n * \"TP/SL of this position\" answer.\n * 3. `isTrigger === true` (defensive — every reduceOnly TP/SL we\n * care about is also a trigger order).\n * 4. **Closing-side match**: a Long position is closed by a SELL\n * (HL `side: \"A\"` / `false`); a Short by a BUY (`\"B\"` / `true`).\n * Orphan triggers from a previously-closed opposite position\n * stay in `frontendOpenOrders` until cancelled — they would\n * never trigger against the current position, so we exclude\n * them. This is the **semantically correct** match (vs Axiom's\n * naïve \"max triggerPx across both sides\", which can surface\n * orphans).\n *\n * Among matching triggers, pick the most recent one per type\n * (`Take Profit Market` → TP, `Stop Market` → SL) by timestamp /\n * `oid`. When multiple TPs/SLs exist (laddered exits), this picks the\n * most-recently placed one — keeping the contract simple. A future\n * improvement could expose the full list for richer rendering.\n */\nfunction pickPositionTpSl(\n position: Position,\n openOrders: HyperliquidOpenOrder[],\n): { tp?: number; sl?: number } {\n const coin = position.symbol.split(\"-\")[0];\n const closingSide: \"A\" | \"B\" = position.side === \"long\" ? \"A\" : \"B\";\n const closingSideBool = closingSide === \"B\";\n\n let tpOrder: HyperliquidOpenOrder | undefined;\n let slOrder: HyperliquidOpenOrder | undefined;\n\n for (const order of openOrders) {\n if (order.coin !== coin) continue;\n if (order.reduceOnly !== true) continue;\n if (order.isTrigger !== true) continue;\n\n const sideMatches =\n order.side === closingSide || order.side === closingSideBool;\n if (!sideMatches) continue;\n\n const orderTypeStr =\n typeof order.orderType === \"string\" ? order.orderType : \"\";\n const isTp = /take\\s*profit/i.test(orderTypeStr);\n const isSl = /stop/i.test(orderTypeStr);\n\n if (isTp) {\n if (!tpOrder || order.timestamp > tpOrder.timestamp) {\n tpOrder = order;\n }\n } else if (isSl) {\n if (!slOrder || order.timestamp > slOrder.timestamp) {\n slOrder = order;\n }\n }\n }\n\n return {\n tp: tpOrder?.triggerPx ? parseFloat(tpOrder.triggerPx) : undefined,\n sl: slOrder?.triggerPx ? parseFloat(slOrder.triggerPx) : undefined,\n };\n}\n\n/**\n * Apply both enrichments — TP/SL (from `openOrders`) and live mark\n * price + recomputed PnL (from `marks`) — to a list of positions.\n * Returns a new array; never mutates the input.\n *\n * Pure function so it stays trivially testable and reusable across\n * both the REST `getPositions` path and the WS `webData2` push.\n */\nfunction enrichPositions(\n positions: Position[],\n openOrders: HyperliquidOpenOrder[],\n marks: Map<string, number> | null,\n): Position[] {\n return positions.map((position) => {\n const next: Position = { ...position };\n\n // 1. TP / SL — closing-side reduceOnly trigger orders.\n const { tp, sl } = pickPositionTpSl(position, openOrders);\n next.takeProfitPrice = tp;\n next.stopLossPrice = sl;\n\n // 2. Live mark price + PnL recompute.\n //\n // The venue's `clearinghouseState` snapshot ships an\n // `unrealizedPnl` already, but it's marked at whatever instant the\n // snapshot was taken — between user-action pushes the figure goes\n // stale fast. When we have a fresher mark from `assetCtxs` we\n // re-mark client-side using the same formula HL uses internally\n // (`(mark - entry) * |qty|` for long, mirrored for short) and\n // derive ROE as `pnl / margin`. Cross-margin positions use\n // `marginUsed` for that ratio too, which approximates HL's\n // displayed ROE within rounding (HL's exact cross ROE depends on\n // venue-internal collateral allocation that isn't surfaced).\n const coin = position.symbol.split(\"-\")[0];\n const markPrice = marks?.get(coin);\n if (markPrice && Number.isFinite(markPrice) && markPrice > 0) {\n next.markPrice = markPrice;\n const dir = position.side === \"long\" ? 1 : -1;\n const pnl = (markPrice - position.entryPrice) * position.quantity * dir;\n next.unrealizedPnl = pnl;\n next.notionalValue = markPrice * position.quantity;\n if (position.margin > 0) {\n next.unrealizedPnlPercent = (pnl / position.margin) * 100;\n }\n }\n\n return next;\n });\n}\n\n/**\n * Hyperliquid API 错误类\n */\nexport class HyperliquidApiError extends Error {\n constructor(\n message: string,\n public readonly statusCode: number,\n public readonly responseBody: string,\n ) {\n super(message);\n this.name = \"HyperliquidApiError\";\n }\n}\n","/**\n * Shared REST transport for every LiberFi perpetuals-server client.\n *\n * Pulled out of `LiberFiPerpetualsClient` so the deposit client (and any\n * future feature client) can reuse the same fetch-with-timeout, error\n * mapping, and header merging logic without copy-paste.\n *\n * Design choices:\n *\n * - The class is intentionally minimal: build URL → fire fetch →\n * decode JSON → throw a typed error on non-2xx. No retries, no\n * circuit breaker, no caching. That layering belongs to the caller\n * (e.g. TanStack Query handles retries/cache).\n *\n * - Custom query parameters are passed per-request, not per-instance,\n * except for `defaultQuery` which the perpetuals client uses for the\n * `?provider=` selector.\n *\n * - Headers merge in three layers (call > instance > built-in). This\n * lets a caller add a one-off `Authorization` for a single request\n * without leaking it into the rest of the session.\n */\n\n/**\n * Thrown when perpetuals-server returns a non-2xx HTTP status, when the\n * request times out, or when the network call fails outright.\n *\n * `statusCode` is the HTTP status (or `0` for network errors / `408`\n * for client-side timeouts). `responseBody` is the verbatim response\n * text — useful for surfacing backend error codes to the user.\n */\nexport class LiberFiApiError extends Error {\n constructor(\n message: string,\n public readonly statusCode: number,\n public readonly responseBody: string,\n ) {\n super(message);\n this.name = \"LiberFiApiError\";\n }\n}\n\n/** Configuration for {@link LiberFiHttpTransport}. */\nexport interface LiberFiHttpTransportConfig {\n /**\n * REST base URL, with NO trailing slash. The transport strips trailing\n * slashes on construction so callers can pass either form.\n */\n baseUrl: string;\n\n /** Per-request timeout in milliseconds. Defaults to 30 000 ms. */\n timeout?: number;\n\n /**\n * Headers merged into every request. Per-request headers (passed to\n * `request()`) win on key collision, then instance headers, then the\n * built-in `Accept` / `Content-Type`.\n */\n headers?: Record<string, string>;\n\n /**\n * Default query parameters appended to every request URL. Useful for\n * cross-cutting selectors like `?provider=hyperliquid`. Per-request\n * params override on key collision.\n */\n defaultQuery?: Record<string, string | undefined>;\n\n /**\n * Custom `fetch` implementation. Defaults to the global `fetch`.\n * Useful in tests (drop in a jest mock) or in environments where a\n * pre-configured fetch (e.g. with circuit breaker / proxy) is supplied\n * by the host application.\n */\n fetchImpl?: typeof fetch;\n}\n\n/** HTTP method shape — keep narrow; deposit and trading both use these. */\nexport type LiberFiHttpMethod = \"GET\" | \"POST\";\n\n/** Per-request options accepted by {@link LiberFiHttpTransport.request}. */\nexport interface RequestOptions {\n /** Path relative to `baseUrl` (must start with `/`). */\n path: string;\n /** Optional query string parameters. Undefined / empty values are skipped. */\n query?: Record<string, string | undefined>;\n /** JSON body for POST/PUT/etc. */\n body?: unknown;\n /** One-off headers — overrides the instance defaults. */\n headers?: Record<string, string>;\n /**\n * Override the per-instance timeout for this single request.\n * Use for fast-path reads or long-running submits.\n */\n timeoutMs?: number;\n}\n\nconst DEFAULT_TIMEOUT_MS = 30_000;\n\n/**\n * Stateless HTTP transport shared by every LiberFi perpetuals-server\n * client. Construct one per client (or one shared instance — the class\n * is safe for concurrent use).\n */\nexport class LiberFiHttpTransport {\n private readonly baseUrl: string;\n private readonly timeout: number;\n private readonly headers?: Record<string, string>;\n private readonly defaultQuery?: Record<string, string | undefined>;\n private readonly fetchImpl: typeof fetch;\n\n constructor(config: LiberFiHttpTransportConfig) {\n if (!config.baseUrl) {\n throw new Error(\n \"LiberFiHttpTransport: `baseUrl` is required (e.g. https://api.liberfi.io/perpetuals).\",\n );\n }\n this.baseUrl = config.baseUrl.replace(/\\/+$/, \"\");\n this.timeout = config.timeout ?? DEFAULT_TIMEOUT_MS;\n this.headers = config.headers;\n this.defaultQuery = config.defaultQuery;\n // Bind so `fetch` can be `globalThis.fetch` (which requires `this`\n // to be the realm's globalThis, not the transport instance).\n this.fetchImpl = config.fetchImpl ?? globalThis.fetch.bind(globalThis);\n }\n\n /** Read-only accessor used by the perpetuals client for WebSocket fallback. */\n getBaseUrl(): string {\n return this.baseUrl;\n }\n\n /** Build a fully-qualified URL with merged query string. */\n buildUrl(path: string, query?: Record<string, string | undefined>): string {\n const params = new URLSearchParams();\n if (this.defaultQuery) {\n for (const [key, value] of Object.entries(this.defaultQuery)) {\n if (value === undefined || value === \"\") continue;\n params.set(key, value);\n }\n }\n if (query) {\n for (const [key, value] of Object.entries(query)) {\n if (value === undefined || value === \"\") continue;\n params.set(key, value);\n }\n }\n const qs = params.toString();\n return `${this.baseUrl}${path}${qs ? `?${qs}` : \"\"}`;\n }\n\n /**\n * Issue an HTTP request and decode the JSON response. Returns\n * `undefined` (cast to T) for `204 No Content`. Throws\n * {@link LiberFiApiError} on every non-2xx, timeout, or network error.\n */\n async request<T>(\n method: LiberFiHttpMethod,\n opts: RequestOptions,\n ): Promise<T> {\n const url = this.buildUrl(opts.path, opts.query);\n const controller = new AbortController();\n const timeoutMs = opts.timeoutMs ?? this.timeout;\n const timeoutId = setTimeout(() => controller.abort(), timeoutMs);\n\n try {\n const response = await this.fetchImpl(url, {\n method,\n headers: {\n Accept: \"application/json\",\n ...(method === \"POST\" ? { \"Content-Type\": \"application/json\" } : {}),\n ...this.headers,\n ...opts.headers,\n },\n body: method === \"POST\" ? JSON.stringify(opts.body ?? {}) : undefined,\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const text = await safeText(response);\n throw new LiberFiApiError(\n `HTTP ${response.status} ${response.statusText} from ${method} ${url}`,\n response.status,\n text,\n );\n }\n\n if (response.status === 204) return undefined as T;\n return (await response.json()) as T;\n } catch (err: unknown) {\n if (err instanceof LiberFiApiError) throw err;\n if (err instanceof Error && err.name === \"AbortError\") {\n throw new LiberFiApiError(\n `Request timeout after ${timeoutMs}ms: ${method} ${url}`,\n 408,\n \"\",\n );\n }\n const message = err instanceof Error ? err.message : String(err);\n throw new LiberFiApiError(\n `Network error: ${method} ${url}: ${message}`,\n 0,\n \"\",\n );\n } finally {\n clearTimeout(timeoutId);\n }\n }\n}\n\nasync function safeText(response: Response): Promise<string> {\n try {\n return await response.text();\n } catch {\n return \"\";\n }\n}\n","import type {\n IPerpetualsClient,\n MarketData,\n Kline,\n KlineInterval,\n KlineQueryOptions,\n OrderBook,\n Trade,\n PlaceOrderParams,\n PlaceOrderResult,\n CancelOrderParams,\n CancelOrderResult,\n GetPositionsParams,\n GetPositionsResult,\n GetOpenOrdersParams,\n GetOpenOrdersResult,\n GetTradesParams,\n GetTradesResult,\n Position,\n Order,\n TradeHistory,\n ActiveAssetLeverage,\n GetActiveAssetLeverageParams,\n AssetMeta,\n GetAssetMetaParams,\n} from \"../../types\";\nimport { WebSocketManager } from \"../hyperliquid/WebSocketManager\";\nimport { LiberFiHttpTransport, LiberFiApiError } from \"./transport\";\n\n// Re-export the error so existing consumers continue to import it from\n// the perpetuals-client module.\nexport { LiberFiApiError };\n\n// ===== Public configuration ===================================================\n\n/**\n * `signTypedData` is invoked once per place / cancel during the\n * `prepare → submit` flow. The hosting app injects this so the user's wallet\n * (privy / wagmi / etc.) controls the keys — perpetuals-server never sees them.\n *\n * The `typedData` argument is the EIP-712 envelope returned verbatim by the\n * server. The function must return the resulting compact signature as a\n * `0x`-prefixed hex string.\n */\nexport type SignTypedDataFn = (\n typedData: Record<string, unknown>,\n) => Promise<`0x${string}`>;\n\n/** Configuration for {@link LiberFiPerpetualsClient}. */\nexport interface LiberFiPerpetualsClientConfig {\n /**\n * REST base URL, with NO trailing slash. Examples:\n * - Local dev: `http://localhost:8080`\n * - Staging: `https://api.liberfi.io/staging/perpetuals`\n * - Production: `https://api.liberfi.io/perpetuals`\n *\n * The client appends `/v1/...` paths to this value. Required UNLESS a\n * pre-built {@link LiberFiHttpTransport} is supplied via `transport`,\n * in which case the transport's baseUrl is used.\n */\n baseUrl?: string;\n\n /**\n * Optional WebSocket endpoint. Real-time data is NOT proxied by\n * perpetuals-server today — the WS subscription methods connect directly to\n * the upstream exchange. Defaults to Hyperliquid mainnet.\n */\n wsEndpoint?: string;\n\n /**\n * EIP-712 signer injected by the hosting app. REQUIRED for `placeOrder` /\n * `cancelOrder`; read-only methods work without it.\n */\n signTypedData?: SignTypedDataFn;\n\n /**\n * Per-request timeout in milliseconds. Defaults to 30 000 ms.\n * Ignored when `transport` is provided (the transport carries its own).\n */\n timeout?: number;\n\n /**\n * Optional provider override sent as `?provider=...`. Defaults to the server\n * configuration (currently `hyperliquid`). Only set this when the gateway\n * has multiple providers configured and you want a non-default one.\n */\n provider?: string;\n\n /**\n * Optional extra request headers (auth tokens, tracing, etc.) merged into\n * every fetch. Ignored when `transport` is provided.\n */\n headers?: Record<string, string>;\n\n /**\n * Inject a pre-built transport instead of letting the client construct\n * one from `baseUrl` / `timeout` / `headers`. Required when sharing a\n * single transport with the deposit client to halve the per-call\n * configuration footprint in `PerpetualsProvider`.\n */\n transport?: LiberFiHttpTransport;\n}\n\nconst DEFAULT_WS_ENDPOINT = \"wss://api.hyperliquid.xyz/ws\";\n\n// ===== Server-side wire types (mirror perpetuals-server/internal/domain) =======\n//\n// These intentionally use snake-free camelCase exactly matching the Go\n// `json:\"…\"` tags. They are kept private so consumers depend only on the\n// stable IPerpetualsClient surface above.\n\ninterface CoinDTO {\n symbol: string;\n name: string;\n tickSize?: number;\n stepSize?: number;\n minOrderSize?: number;\n maxLeverage?: number;\n}\n\ntype MarketDTO = MarketData;\ntype OrderBookDTO = OrderBook;\ntype TradeDTO = Trade;\ntype KlineDTO = Kline;\n\ninterface AccountDTO {\n totalEquity: number;\n availableBalance: number;\n totalUnrealizedPnl: number;\n usedMargin?: number;\n accountLeverage?: number;\n}\n\ninterface PositionsResultDTO {\n positions: Position[];\n account?: AccountDTO;\n}\n\ntype OrderDTO = Order;\n\ninterface UserFillDTO {\n tradeId: string;\n orderId: string;\n symbol: string;\n side: \"long\" | \"short\";\n price: number;\n quantity: number;\n fee: number;\n feeCurrency: string;\n isMaker: boolean;\n timestamp: number;\n}\n\ninterface PreparedActionDTO {\n typedData: Record<string, unknown>;\n action: Record<string, unknown>;\n nonce: number;\n vaultAddress?: string;\n}\n\ntype PlaceOrderResultDTO = PlaceOrderResult;\ntype CancelOrderResultDTO = CancelOrderResult;\n\n// ===== Implementation ============================================================\n\n/**\n * REST + injected-signer implementation of {@link IPerpetualsClient} that talks\n * to a deployed `perpetuals-server` instead of Hyperliquid directly.\n *\n * - Read-only methods are plain `fetch GET`s.\n * - `placeOrder` / `cancelOrder` follow the two-phase flow:\n * 1. POST `…/prepare` → server builds upstream action + EIP-712 typed data.\n * 2. Host wallet signs `typedData` via the injected `signTypedData`.\n * 3. POST `…/submit` with the original `action`, the user signature, and\n * the server-issued `nonce`. The server forwards to upstream and\n * normalises the response.\n * - WebSocket subscriptions are NOT proxied through perpetuals-server today.\n * They reuse the existing {@link WebSocketManager} pointed at the upstream\n * exchange (`wsEndpoint`, default Hyperliquid mainnet).\n */\nexport class LiberFiPerpetualsClient implements IPerpetualsClient {\n private readonly transport: LiberFiHttpTransport;\n private readonly wsEndpoint: string;\n private readonly signTypedData?: SignTypedDataFn;\n private wsManager: WebSocketManager | null = null;\n /**\n * Reference count of active WebSocket consumers (one per React hook\n * instance). The underlying connection is opened lazily on the first\n * connect() call and torn down only when the last consumer leaves —\n * this prevents one widget's unmount from killing the live stream\n * other widgets (order book, trades, ticker) still depend on.\n */\n private wsRefCount = 0;\n\n constructor(config: LiberFiPerpetualsClientConfig) {\n // Two construction modes: legacy (baseUrl / timeout / headers) or\n // transport-injected. The deposit client constructor mirrors the\n // same pattern so both share a consistent shape.\n if (config.transport) {\n this.transport = config.transport;\n } else {\n if (!config.baseUrl) {\n throw new Error(\n \"LiberFiPerpetualsClient: either `baseUrl` or a pre-built `transport` is required.\",\n );\n }\n this.transport = new LiberFiHttpTransport({\n baseUrl: config.baseUrl,\n timeout: config.timeout,\n headers: config.headers,\n defaultQuery: config.provider\n ? { provider: config.provider }\n : undefined,\n });\n }\n this.wsEndpoint = config.wsEndpoint ?? DEFAULT_WS_ENDPOINT;\n this.signTypedData = config.signTypedData;\n }\n\n // ── IPerpetualsClient: market data ────────────────────────────────────────\n\n async getSupportedCoins(): Promise<string[]> {\n const coins = await this.transport.request<CoinDTO[]>(\"GET\", {\n path: \"/v1/coins\",\n });\n return coins.map((coin) => coin.symbol);\n }\n\n async getMarket(symbol: string): Promise<MarketData | null> {\n try {\n return await this.transport.request<MarketDTO>(\"GET\", {\n path: `/v1/markets/${encodeURIComponent(symbol)}`,\n });\n } catch (err) {\n if (err instanceof LiberFiApiError && err.statusCode === 404) return null;\n throw err;\n }\n }\n\n async getMarkets(symbols?: string[]): Promise<MarketData[]> {\n return this.transport.request<MarketDTO[]>(\"GET\", {\n path: \"/v1/markets\",\n query:\n symbols && symbols.length > 0\n ? { symbols: symbols.join(\",\") }\n : undefined,\n });\n }\n\n async getKlines(\n symbol: string,\n interval: KlineInterval,\n limitOrOptions: number | KlineQueryOptions = 100,\n ): Promise<Kline[]> {\n const options: KlineQueryOptions =\n typeof limitOrOptions === \"number\"\n ? { limit: limitOrOptions }\n : limitOrOptions;\n\n const query: Record<string, string> = { interval };\n if (options.limit !== undefined) {\n query.limit = String(options.limit);\n }\n // Forward time-range parameters as `start` / `end` (ms epochs) — matches\n // the openapi-server `KlineParams` contract. Required for TradingView\n // backward history pagination.\n if (options.from !== undefined) {\n query.start = String(options.from);\n }\n if (options.to !== undefined) {\n query.end = String(options.to);\n }\n\n return this.transport.request<KlineDTO[]>(\"GET\", {\n path: `/v1/markets/${encodeURIComponent(symbol)}/klines`,\n query,\n });\n }\n\n async getOrderBook(\n symbol: string,\n maxLevel: number = 10,\n options?: { nSigFigs?: number; mantissa?: number },\n ): Promise<OrderBook> {\n const query: Record<string, string> = { maxLevel: String(maxLevel) };\n if (options?.nSigFigs !== undefined) {\n query.nSigFigs = String(options.nSigFigs);\n if (\n options.nSigFigs === 5 &&\n options.mantissa &&\n options.mantissa !== 1\n ) {\n query.mantissa = String(options.mantissa);\n }\n }\n return this.transport.request<OrderBookDTO>(\"GET\", {\n path: `/v1/markets/${encodeURIComponent(symbol)}/orderbook`,\n query,\n });\n }\n\n async getRecentTrades(symbol: string, limit: number = 50): Promise<Trade[]> {\n return this.transport.request<TradeDTO[]>(\"GET\", {\n path: `/v1/markets/${encodeURIComponent(symbol)}/trades`,\n query: { limit: String(limit) },\n });\n }\n\n // ── IPerpetualsClient: account ────────────────────────────────────────────\n\n async getPositions(\n params: GetPositionsParams = {},\n ): Promise<GetPositionsResult> {\n if (!params.userAddress) {\n throw new Error(\n \"LiberFiPerpetualsClient.getPositions requires `userAddress`.\",\n );\n }\n const result = await this.transport.request<PositionsResultDTO>(\"GET\", {\n path: `/v1/users/${encodeURIComponent(params.userAddress)}/positions`,\n query: { symbol: params.symbol },\n });\n\n return {\n positions: result.positions,\n totalEquity: result.account?.totalEquity,\n availableBalance: result.account?.availableBalance,\n totalUnrealizedPnl: result.account?.totalUnrealizedPnl,\n raw: result,\n };\n }\n\n async getOpenOrders(\n params: GetOpenOrdersParams = {},\n ): Promise<GetOpenOrdersResult> {\n if (!params.userAddress) {\n throw new Error(\n \"LiberFiPerpetualsClient.getOpenOrders requires `userAddress`.\",\n );\n }\n const orders = await this.transport.request<OrderDTO[]>(\"GET\", {\n path: `/v1/users/${encodeURIComponent(params.userAddress)}/orders`,\n query: { symbol: params.symbol },\n });\n return { orders, totalCount: orders.length, raw: orders };\n }\n\n async getTrades(params: GetTradesParams = {}): Promise<GetTradesResult> {\n if (!params.userAddress) {\n throw new Error(\n \"LiberFiPerpetualsClient.getTrades requires `userAddress`.\",\n );\n }\n const fills = await this.transport.request<UserFillDTO[]>(\"GET\", {\n path: `/v1/users/${encodeURIComponent(params.userAddress)}/fills`,\n query: {\n symbol: params.symbol,\n limit: params.limit !== undefined ? String(params.limit) : undefined,\n startTime:\n params.startTime !== undefined ? String(params.startTime) : undefined,\n endTime:\n params.endTime !== undefined ? String(params.endTime) : undefined,\n },\n });\n const trades: TradeHistory[] = fills.map((fill) => ({\n tradeId: fill.tradeId,\n orderId: fill.orderId,\n symbol: fill.symbol,\n side: fill.side,\n price: fill.price,\n quantity: fill.quantity,\n fee: fill.fee,\n feeCurrency: fill.feeCurrency,\n isMaker: fill.isMaker,\n timestamp: fill.timestamp,\n }));\n return { trades, totalCount: trades.length, raw: fills };\n }\n\n /**\n * The LiberFi backend does not yet expose an `activeAssetData`\n * equivalent. Returning `null` lets the form fall back to its own\n * default leverage without raising — the perpetuals-server can grow\n * this endpoint later and we'll plug it in here.\n */\n async getActiveAssetLeverage(\n _params: GetActiveAssetLeverageParams,\n ): Promise<ActiveAssetLeverage | null> {\n return null;\n }\n\n /**\n * The LiberFi backend doesn't currently surface per-asset\n * `szDecimals` / `maxLeverage` over a dedicated endpoint. We could\n * derive `szDecimals` from {@link getSupportedCoins}'s `stepSize`\n * once perpetuals-server starts populating it (`szDecimals =\n * -log10(stepSize)`), but until then the form falls back to its\n * adaptive heuristic when this returns `null`.\n *\n * TODO(perpetuals-server): expose `GET /v1/markets/:symbol/meta`\n * (or extend the existing `/v1/coins` payload with `szDecimals` +\n * `maxLeverage`) so this can resolve without a side trip to the\n * upstream venue.\n */\n async getAssetMeta(_params: GetAssetMetaParams): Promise<AssetMeta | null> {\n return null;\n }\n\n // ── IPerpetualsClient: trading (two-phase signing) ────────────────────────\n\n async placeOrder(params: PlaceOrderParams): Promise<PlaceOrderResult> {\n if (!this.signTypedData) {\n throw new Error(\n \"LiberFiPerpetualsClient.placeOrder requires `signTypedData` to be configured.\",\n );\n }\n if (!params.userAddress) {\n throw new Error(\n \"LiberFiPerpetualsClient.placeOrder requires `userAddress` (the signing wallet).\",\n );\n }\n\n const prepared = await this.transport.request<PreparedActionDTO>(\"POST\", {\n path: \"/v1/orders/prepare\",\n body: {\n userAddress: params.userAddress,\n symbol: params.symbol,\n side: params.side,\n orderType: params.orderType,\n amount: params.amount,\n price: params.price,\n leverage: params.leverage,\n reduceOnly: params.reduceOnly,\n takeProfitPrice: params.takeProfitPrice,\n stopLossPrice: params.stopLossPrice,\n clientOrderId: params.clientOrderId,\n },\n });\n\n const signature = await this.signTypedData(prepared.typedData);\n\n return this.transport.request<PlaceOrderResultDTO>(\"POST\", {\n path: \"/v1/orders/submit\",\n body: {\n action: prepared.action,\n signature,\n nonce: prepared.nonce,\n vaultAddress: prepared.vaultAddress,\n },\n });\n }\n\n async cancelOrder(params: CancelOrderParams): Promise<CancelOrderResult> {\n if (!this.signTypedData) {\n throw new Error(\n \"LiberFiPerpetualsClient.cancelOrder requires `signTypedData` to be configured.\",\n );\n }\n if (!params.userAddress) {\n throw new Error(\n \"LiberFiPerpetualsClient.cancelOrder requires `userAddress` (the signing wallet).\",\n );\n }\n\n const prepared = await this.transport.request<PreparedActionDTO>(\"POST\", {\n path: \"/v1/orders/cancel/prepare\",\n body: {\n userAddress: params.userAddress,\n symbol: params.symbol,\n orderId: params.orderId,\n clientOrderId: params.clientOrderId,\n },\n });\n\n const signature = await this.signTypedData(prepared.typedData);\n\n return this.transport.request<CancelOrderResultDTO>(\"POST\", {\n path: \"/v1/orders/cancel/submit\",\n body: {\n action: prepared.action,\n signature,\n nonce: prepared.nonce,\n vaultAddress: prepared.vaultAddress,\n },\n });\n }\n\n // ── IPerpetualsClient: WebSocket (direct upstream, NOT proxied) ───────────\n\n async connectWebSocket(): Promise<void> {\n this.wsRefCount += 1;\n if (!this.wsManager) {\n this.wsManager = new WebSocketManager(this.wsEndpoint);\n }\n if (this.wsManager.isConnectedNow()) return;\n await this.wsManager.connect();\n }\n\n disconnectWebSocket(): void {\n this.wsRefCount = Math.max(0, this.wsRefCount - 1);\n if (this.wsRefCount === 0 && this.wsManager) {\n this.wsManager.disconnect();\n this.wsManager = null;\n }\n }\n\n subscribeMarketData(\n type: \"ticker\" | \"trades\" | \"orderBook\",\n symbol: string,\n callback: (data: unknown) => void,\n options?: {\n aggregation?: { nSigFigs?: 2 | 3 | 4 | 5; mantissa?: 1 | 2 | 5 };\n },\n ): string {\n // The shared {@link WebSocketManager} speaks Hyperliquid's protocol, so\n // when the aggregation hint is provided we forward it as nSigFigs/mantissa\n // regardless of which client we're behind.\n return this.requireWS().subscribe(\n type,\n symbol,\n callback,\n options?.aggregation,\n );\n }\n\n subscribeCandles(\n symbol: string,\n interval: KlineInterval,\n callback: (candle: Kline) => void,\n ): string {\n return this.requireWS().subscribe(\n \"candle\",\n `${symbol}:${interval}`,\n callback,\n );\n }\n\n subscribeUserData(\n type: \"orders\" | \"positions\" | \"fills\",\n userAddress: string,\n callback: (data: unknown) => void,\n ): string {\n const channel = type === \"fills\" ? \"userFills\" : \"userEvents\";\n return this.requireWS().subscribe(channel, userAddress, callback);\n }\n\n unsubscribe(subscriptionId: string): void {\n if (this.wsManager) {\n this.wsManager.unsubscribe(subscriptionId);\n }\n }\n\n private requireWS(): WebSocketManager {\n if (!this.wsManager) {\n throw new Error(\n \"WebSocket not connected. Call connectWebSocket() first.\",\n );\n }\n return this.wsManager;\n }\n}\n","/**\n * REST client for the Solana → Hyperliquid deposit endpoints exposed by\n * the perpetuals-server (`/v1/deposits/*`).\n *\n * Engineering principles:\n * - Single responsibility: this file knows about /v1/deposits and\n * nothing else. Quote orchestration, fee adapters, status\n * reconciliation, etc. live server-side.\n * - Modularity: the HTTP transport is injected (or built from a\n * baseUrl) so integration tests can drop in a fetch mock; production\n * code shares the same transport instance with `LiberFiPerpetualsClient`.\n * - First principles: three methods (quote / submit / status), no\n * hidden state, no caching. Polling is the caller's concern (the\n * hooks do it via TanStack Query).\n */\nimport type {\n DepositQuoteRequest,\n DepositQuoteResponse,\n DepositStatusResponse,\n DepositSubmitRequest,\n DepositSubmitResponse,\n} from \"./deposit-types\";\nimport {\n LiberFiHttpTransport,\n type LiberFiHttpTransportConfig,\n} from \"./transport\";\n\n/**\n * Options for constructing a `LiberFiPerpDepositClient`.\n *\n * Either provide a pre-built `transport` (preferred — share one with\n * `LiberFiPerpetualsClient` so connection limits, headers and timeouts\n * stay consistent) or pass the raw config and let the client build one.\n */\nexport type LiberFiPerpDepositClientConfig =\n | { transport: LiberFiHttpTransport }\n | LiberFiHttpTransportConfig;\n\n/** Public surface of the deposit client; matches the three handler endpoints. */\nexport interface IPerpDepositClient {\n /** POST /v1/deposits/quote */\n quote(req: DepositQuoteRequest): Promise<DepositQuoteResponse>;\n /** POST /v1/deposits/submit */\n submit(req: DepositSubmitRequest): Promise<DepositSubmitResponse>;\n /** GET /v1/deposits/{id} */\n status(intentId: string): Promise<DepositStatusResponse>;\n /** POST /v1/deposits/{id}/refresh — bypasses any future cache TTL. */\n refresh(intentId: string): Promise<DepositStatusResponse>;\n}\n\n/** Concrete implementation backed by `LiberFiHttpTransport`. */\nexport class LiberFiPerpDepositClient implements IPerpDepositClient {\n private readonly transport: LiberFiHttpTransport;\n\n constructor(config: LiberFiPerpDepositClientConfig) {\n this.transport =\n \"transport\" in config\n ? config.transport\n : new LiberFiHttpTransport(config);\n }\n\n /** Returns the base URL of the underlying transport (mostly for logs/diagnostics). */\n getBaseUrl(): string {\n return this.transport.getBaseUrl();\n }\n\n async quote(req: DepositQuoteRequest): Promise<DepositQuoteResponse> {\n return this.transport.request<DepositQuoteResponse>(\"POST\", {\n path: \"/v1/deposits/quote\",\n body: req,\n });\n }\n\n async submit(req: DepositSubmitRequest): Promise<DepositSubmitResponse> {\n return this.transport.request<DepositSubmitResponse>(\"POST\", {\n path: \"/v1/deposits/submit\",\n body: req,\n });\n }\n\n async status(intentId: string): Promise<DepositStatusResponse> {\n if (!intentId) throw new Error(\"intentId is required\");\n return this.transport.request<DepositStatusResponse>(\"GET\", {\n path: `/v1/deposits/${encodeURIComponent(intentId)}`,\n });\n }\n\n async refresh(intentId: string): Promise<DepositStatusResponse> {\n if (!intentId) throw new Error(\"intentId is required\");\n return this.transport.request<DepositStatusResponse>(\"POST\", {\n path: `/v1/deposits/${encodeURIComponent(intentId)}/refresh`,\n });\n }\n}\n","/**\n * Wire / domain types for the Solana → Hyperliquid USDC deposit flow.\n *\n * These deliberately mirror the perpetuals-server DTOs (see\n * `internal/handler/deposit_handler.go`) so the SDK <-> backend contract\n * stays in sync. When the backend adds a new field, add it here too —\n * the compiler will then point at every place that needs to handle it.\n *\n * All amounts denominated in *smallest unit* (lamports for SOL, USDC's\n * 6-decimal microUSDC for the destination side) are typed as `string` so\n * we never accidentally lose precision on large values.\n */\n\n/** Where the deposit was initiated from. Drives fee attribution server-side. */\nexport type DepositSource = \"dex\" | \"prediction\" | \"launchpad\" | \"channel\";\n\n/** Lifecycle states a deposit can be in. */\nexport type DepositStatus =\n | \"broadcasted\" // user signed + broadcast on Solana, server has not seen Relay yet\n | \"relay_waiting\" // Relay observed the deposit but hasn't started forwarding\n | \"relay_pending\" // Relay is forwarding the deposit cross-chain\n | \"settled\" // funds delivered to Hyperliquid\n | \"refunded\" // Relay refunded — funds returned to user wallet\n | \"failed\" // terminal failure\n | \"stuck\"; // observed > stuckAfter without Relay seeing it; ops review\n\n/** True for status values that never transition further. */\nexport const TERMINAL_DEPOSIT_STATUSES: ReadonlySet<DepositStatus> =\n new Set<DepositStatus>([\"settled\", \"refunded\", \"failed\"]);\n\n/** A single state transition in the status history. */\nexport interface DepositStatusTransition {\n from: DepositStatus | \"\";\n to: DepositStatus;\n at: string; // ISO 8601 timestamp\n source: \"handler\" | \"status_pull\" | \"reconciliation\" | string;\n reason?: string;\n}\n\n/** Surfaced when the upstream produced an unrecoverable error. */\nexport interface DepositErrorInfo {\n code: string;\n message: string;\n recoverable: boolean;\n}\n\n/** Exact-decimal breakdown returned by the quote endpoint. */\nexport interface DepositBreakdown {\n /** Total lamports the user is paying in (gross). */\n grossLamports: string;\n /** Platform fee transferred to the LiberFi treasury (lamports). */\n platformFeeLamports: string;\n /** Net amount Relay bridges (= gross − platformFee), in lamports. */\n relayDepositLamports: string;\n /** SOL pubkey the platform fee is sent to. May be empty when fee = 0. */\n treasuryAddress: string;\n /** Expected destination output, in microUSDC (6-decimal). May be empty. */\n expectedOutputUSDC?: string;\n /** Origin chain id (Solana mainnet on Relay = 792703809). */\n originChainId: number;\n /** Destination chain id (Hyperliquid). */\n destinationChainId: number;\n /** Origin currency. SOL is encoded as the SystemProgram pseudo-pubkey. */\n originCurrency: string;\n /** Destination currency contract. */\n destinationCurrency: string;\n /** Relay-issued depository address — the program/wallet receiving SOL. */\n depository?: string;\n /** Relay request id; populated once Relay returns a quote. */\n relayRequestId?: string;\n}\n\n/** Body of POST /v1/deposits/quote. */\nexport interface DepositQuoteRequest {\n userSolanaAddress: string;\n hyperliquidRecipient: string;\n /** Smallest-unit amount the user is paying in. */\n grossLamports: string;\n /** Fee attribution source. Defaults to `dex` server-side when empty. */\n source: DepositSource;\n}\n\n/** Response of POST /v1/deposits/quote. */\nexport interface DepositQuoteResponse {\n /** Base64 SOL transaction the user signs in their wallet. */\n serializedTxBase64: string;\n /** Transaction size on the wire (used by client-side guards). */\n sizeBytes: number;\n /** True for v0 transactions (legacy = false). */\n isVersioned: boolean;\n breakdown: DepositBreakdown;\n /** ISO 8601 timestamp the quote was issued at. */\n issuedAt: string;\n /** ISO 8601 timestamp the quote expires at. */\n expiresAt: string;\n}\n\n/** Body of POST /v1/deposits/submit. */\nexport interface DepositSubmitRequest {\n userSolanaAddress: string;\n hyperliquidRecipient: string;\n /** The signed transaction's hash, returned by the wallet on broadcast. */\n solanaTxHash: string;\n breakdown: DepositBreakdown;\n /** Stable user identifier (LiberFi user id, NOT the wallet address). */\n userId: string;\n source: DepositSource;\n /** Optional marketing campaign / referral code passed through to attribution. */\n campaign?: string;\n /** Mirror back the issuedAt from /quote so the server can guard freshness. */\n quoteIssuedAt: string;\n}\n\n/** Response of POST /v1/deposits/submit. */\nexport interface DepositSubmitResponse {\n intentId: string;\n /** True the first time a unique solanaTxHash is seen; idempotent retries return false. */\n created: boolean;\n}\n\n/** Response of GET /v1/deposits/{id}. */\nexport interface DepositStatusResponse {\n intentId: string;\n status: DepositStatus;\n userSolanaAddress: string;\n hyperliquidRecipient: string;\n solanaTxHash: string;\n relayRequestId?: string;\n hyperliquidTxHash?: string;\n breakdown: DepositBreakdown;\n statusHistory: DepositStatusTransition[];\n lastError?: DepositErrorInfo;\n userId: string;\n source: DepositSource;\n campaign?: string;\n createdAt: string;\n updatedAt: string;\n}\n","/**\n * Pure state machine for the deposit UI.\n *\n * The backend owns the *authoritative* lifecycle (broadcasted → relay_*\n * → settled / refunded / failed / stuck). The frontend has a few extra\n * states *before* we can call /submit (idle, quoting, ready_to_sign,\n * signing, broadcasting). We model both halves here as a single FSM so\n * presentational components can switch on a single tag.\n *\n * Engineering principles applied:\n * - First principles: a state is a *type*, transitions are pure\n * functions over (state, event) → state. No timers, no fetch, no\n * setState — those live in hooks.\n * - Single responsibility: this file knows nothing about HTTP, React,\n * or wallets. It is unit-testable in isolation.\n * - Extensibility: add a new event by extending DepositEvent + a case\n * in `reduceDepositState`. The compiler enforces exhaustiveness.\n */\nimport {\n type DepositBreakdown,\n type DepositErrorInfo,\n type DepositQuoteResponse,\n type DepositStatus,\n type DepositStatusResponse,\n TERMINAL_DEPOSIT_STATUSES,\n} from \"./deposit-types\";\n\n/** UI-only state tags. Server-driven tags are a subset of DepositStatus. */\nexport type DepositPhase =\n | \"idle\" // user hasn't requested a quote yet\n | \"quoting\" // /quote in flight\n | \"ready_to_sign\" // quote received, awaiting wallet signature\n | \"signing\" // wallet is signing\n | \"broadcasting\" // signed tx submitted to RPC, waiting for hash\n | \"submitted\" // /submit called, intentId returned\n | \"tracking\" // polling /status with a non-terminal lifecycle status\n | \"succeeded\" // terminal: settled\n | \"refunded\" // terminal: refunded\n | \"failed\" // terminal: failed | stuck (or any local error)\n | \"expired\"; // quote expired before user signed\n\n/** Discriminated union representing the entire deposit flow at any moment. */\nexport type DepositState =\n | { phase: \"idle\" }\n | { phase: \"quoting\" }\n | {\n phase: \"ready_to_sign\";\n quote: DepositQuoteResponse;\n /** Epoch ms — caller pre-computes for stable comparisons. */\n expiresAtMs: number;\n }\n | { phase: \"signing\"; quote: DepositQuoteResponse }\n | { phase: \"broadcasting\"; quote: DepositQuoteResponse }\n | {\n phase: \"submitted\";\n quote: DepositQuoteResponse;\n intentId: string;\n solanaTxHash: string;\n }\n | {\n phase: \"tracking\";\n intentId: string;\n status: DepositStatusResponse;\n }\n | {\n phase: \"succeeded\";\n intentId: string;\n status: DepositStatusResponse;\n }\n | {\n phase: \"refunded\";\n intentId: string;\n status: DepositStatusResponse;\n }\n | {\n phase: \"failed\";\n error: DepositErrorInfo;\n /** Populated when the failure happened post-submit. */\n intentId?: string;\n status?: DepositStatusResponse;\n }\n | { phase: \"expired\"; quote: DepositQuoteResponse };\n\n/** Events the FSM can react to. Driven by hooks/components. */\nexport type DepositEvent =\n | { type: \"RESET\" }\n | { type: \"QUOTE_REQUEST\" }\n | { type: \"QUOTE_RECEIVED\"; quote: DepositQuoteResponse }\n | { type: \"QUOTE_FAILED\"; error: DepositErrorInfo }\n | { type: \"QUOTE_EXPIRED\" }\n | { type: \"SIGN_START\" }\n | { type: \"SIGN_FAILED\"; error: DepositErrorInfo }\n | { type: \"BROADCAST_START\" }\n | { type: \"BROADCAST_FAILED\"; error: DepositErrorInfo }\n | {\n type: \"SUBMIT_OK\";\n intentId: string;\n solanaTxHash: string;\n }\n | { type: \"SUBMIT_FAILED\"; error: DepositErrorInfo }\n | { type: \"STATUS_UPDATE\"; status: DepositStatusResponse };\n\nexport const initialDepositState: DepositState = { phase: \"idle\" };\n\n/**\n * Transition function. Pure, total — every (state, event) pair is\n * handled. Unknown transitions are no-ops (return current state); we\n * don't throw because hooks may fan out events optimistically (e.g. a\n * stale STATUS_UPDATE arriving after RESET).\n */\nexport function reduceDepositState(\n state: DepositState,\n event: DepositEvent,\n): DepositState {\n switch (event.type) {\n case \"RESET\":\n return initialDepositState;\n\n case \"QUOTE_REQUEST\":\n // Allowed from idle, ready_to_sign (re-quote), expired, failed (retry).\n if (\n state.phase === \"idle\" ||\n state.phase === \"ready_to_sign\" ||\n state.phase === \"expired\" ||\n state.phase === \"failed\"\n ) {\n return { phase: \"quoting\" };\n }\n return state;\n\n case \"QUOTE_RECEIVED\":\n if (state.phase === \"quoting\") {\n return {\n phase: \"ready_to_sign\",\n quote: event.quote,\n expiresAtMs: Date.parse(event.quote.expiresAt),\n };\n }\n return state;\n\n case \"QUOTE_FAILED\":\n if (state.phase === \"quoting\") {\n return { phase: \"failed\", error: event.error };\n }\n return state;\n\n case \"QUOTE_EXPIRED\":\n if (state.phase === \"ready_to_sign\") {\n return { phase: \"expired\", quote: state.quote };\n }\n return state;\n\n case \"SIGN_START\":\n if (state.phase === \"ready_to_sign\") {\n return { phase: \"signing\", quote: state.quote };\n }\n return state;\n\n case \"SIGN_FAILED\":\n if (state.phase === \"signing\") {\n // Keep the quote so the UI can offer a retry without re-quoting.\n return { phase: \"failed\", error: event.error };\n }\n return state;\n\n case \"BROADCAST_START\":\n if (state.phase === \"signing\") {\n return { phase: \"broadcasting\", quote: state.quote };\n }\n return state;\n\n case \"BROADCAST_FAILED\":\n if (state.phase === \"broadcasting\" || state.phase === \"signing\") {\n return { phase: \"failed\", error: event.error };\n }\n return state;\n\n case \"SUBMIT_OK\":\n if (state.phase === \"broadcasting\") {\n return {\n phase: \"submitted\",\n quote: state.quote,\n intentId: event.intentId,\n solanaTxHash: event.solanaTxHash,\n };\n }\n return state;\n\n case \"SUBMIT_FAILED\":\n if (state.phase === \"broadcasting\") {\n return { phase: \"failed\", error: event.error };\n }\n return state;\n\n case \"STATUS_UPDATE\": {\n // /status is polled after submit. Map the backend status to the UI phase.\n if (state.phase !== \"submitted\" && state.phase !== \"tracking\") {\n return state;\n }\n const intentId =\n state.phase === \"submitted\" ? state.intentId : state.intentId;\n const next = mapStatusToPhase(event.status, intentId);\n return next;\n }\n }\n}\n\nfunction mapStatusToPhase(\n status: DepositStatusResponse,\n intentId: string,\n): DepositState {\n switch (status.status) {\n case \"settled\":\n return { phase: \"succeeded\", intentId, status };\n case \"refunded\":\n return { phase: \"refunded\", intentId, status };\n case \"failed\":\n case \"stuck\":\n return {\n phase: \"failed\",\n error: status.lastError ?? {\n code: status.status === \"stuck\" ? \"STUCK\" : \"FAILED\",\n message:\n status.status === \"stuck\"\n ? \"Deposit hasn't been observed by Relay yet — please contact support if this persists.\"\n : \"Deposit failed. Funds will be refunded to your wallet shortly.\",\n recoverable: false,\n },\n intentId,\n status,\n };\n case \"broadcasted\":\n case \"relay_waiting\":\n case \"relay_pending\":\n default:\n return { phase: \"tracking\", intentId, status };\n }\n}\n\n// =====================================================================\n// Selectors — the same data, but in a shape components can render.\n// Defining them here keeps the UI free of `if (state.phase === \"...\" )`\n// branching.\n// =====================================================================\n\n/** True when the FSM has reached a terminal phase. */\nexport function isTerminal(state: DepositState): boolean {\n return (\n state.phase === \"succeeded\" ||\n state.phase === \"refunded\" ||\n state.phase === \"failed\"\n );\n}\n\n/** True when the UI should keep polling /status. */\nexport function isPolling(state: DepositState): boolean {\n return state.phase === \"submitted\" || state.phase === \"tracking\";\n}\n\n/** Returns the current backend lifecycle status, if any. */\nexport function currentStatus(state: DepositState): DepositStatus | undefined {\n if (\n state.phase === \"tracking\" ||\n state.phase === \"succeeded\" ||\n state.phase === \"refunded\"\n ) {\n return state.status.status;\n }\n if (state.phase === \"failed\" && state.status) {\n return state.status.status;\n }\n return undefined;\n}\n\n/** Returns the breakdown the UI should display, if any. */\nexport function currentBreakdown(\n state: DepositState,\n): DepositBreakdown | undefined {\n if (\n state.phase === \"ready_to_sign\" ||\n state.phase === \"signing\" ||\n state.phase === \"broadcasting\" ||\n state.phase === \"submitted\" ||\n state.phase === \"expired\"\n ) {\n return state.quote.breakdown;\n }\n if (\n state.phase === \"tracking\" ||\n state.phase === \"succeeded\" ||\n state.phase === \"refunded\"\n ) {\n return state.status.breakdown;\n }\n if (state.phase === \"failed\" && state.status) {\n return state.status.breakdown;\n }\n return undefined;\n}\n\n/**\n * Returns true when the phase is terminal *and* corresponds to one of\n * the known DepositStatus terminal values. Useful for analytics fan-out\n * (only emit the funnel-end event once per intent).\n */\nexport function isTerminalLifecycle(\n status: DepositStatus | undefined,\n): boolean {\n return status !== undefined && TERMINAL_DEPOSIT_STATUSES.has(status);\n}\n","import { createContext } from \"react\";\nimport type { IPerpDepositClient } from \"../client/liberfi/LiberFiPerpDepositClient\";\nimport type { IPerpetualsClient } from \"../types\";\n\n/**\n * Perpetuals context value type\n *\n * Provides access to the perpetuals trading client and (optionally) the\n * deposit client. The deposit client is optional because not every\n * surface that consumes this provider also needs the deposit flow — a\n * portfolio view that only renders positions can omit it without\n * pulling the deposit dependency along.\n */\nexport interface PerpetualsContextValue {\n /**\n * Perpetuals client instance for trading operations.\n */\n client: IPerpetualsClient;\n\n /**\n * Deposit client instance for the Solana → Hyperliquid funding flow.\n *\n * Optional: surfaces that don't render the deposit UI can omit it.\n * Hooks that need it (e.g. `usePerpDepositQuote`) will throw a clear\n * error pointing at the missing prop.\n */\n depositClient?: IPerpDepositClient;\n}\n\n/**\n * Perpetuals Context\n *\n * React context for accessing perpetuals trading + deposit functionality\n * throughout the app.\n */\nexport const PerpetualsContext = createContext<PerpetualsContextValue>(\n {} as PerpetualsContextValue,\n);\n","import { PropsWithChildren, useMemo } from \"react\";\nimport {\n PerpetualsContext,\n PerpetualsContextValue,\n} from \"../context/PerpetualsContext\";\n\n/**\n * Perpetuals provider props type.\n *\n * `client` is required; `depositClient` is optional and only needed by\n * surfaces that render the cross-chain deposit flow.\n */\nexport type PerpetualsProviderProps = PropsWithChildren<PerpetualsContextValue>;\n\n/**\n * Perpetuals Provider Component.\n *\n * Wraps the perpetuals trading client and (optionally) the deposit\n * client into a single context value. The value is memoised on the\n * client identities so re-renders of the consumer app do not break\n * referential equality for downstream `useContext` consumers.\n *\n * @param props Provider props containing client(s) and children\n * @returns Provider component wrapping children\n */\nexport function PerpetualsProvider({\n client,\n depositClient,\n children,\n}: PerpetualsProviderProps) {\n const value = useMemo<PerpetualsContextValue>(\n () => ({ client, depositClient }),\n [client, depositClient],\n );\n return (\n <PerpetualsContext.Provider value={value}>\n {children}\n </PerpetualsContext.Provider>\n );\n}\n","import { useContext } from \"react\";\nimport {\n PerpetualsContext,\n PerpetualsContextValue,\n} from \"../context/PerpetualsContext\";\n\n/**\n * Hook to access perpetuals client from context\n *\n * Must be used within a PerpetualsProvider component\n *\n * @returns Perpetuals context value containing the client instance\n * @throws Error if used outside of PerpetualsProvider\n */\nexport function usePerpetualsClient(): PerpetualsContextValue {\n const context = useContext(PerpetualsContext);\n\n if (!context || !context.client) {\n throw new Error(\n \"usePerpetualsClient must be used within a PerpetualsProvider\",\n );\n }\n\n return context;\n}\n","import { useQuery, UseQueryOptions } from \"@tanstack/react-query\";\nimport type { IPerpetualsClient } from \"../types\";\nimport { usePerpetualsClient } from \"./usePerpetualsClient\";\n\nexport function coinsQueryKey(): string[] {\n return [\"perps\", \"coins\"];\n}\n\nexport async function fetchCoins(client: IPerpetualsClient): Promise<string[]> {\n return await client.getSupportedCoins();\n}\n\nexport function useCoinsQuery(\n options: Omit<\n UseQueryOptions<string[], Error, string[], string[]>,\n \"queryKey\" | \"queryFn\"\n > = {},\n) {\n const { client } = usePerpetualsClient();\n return useQuery({\n queryKey: coinsQueryKey(),\n queryFn: async () => fetchCoins(client),\n staleTime: 5 * 60 * 1000,\n ...options,\n });\n}\n","import { useQuery, UseQueryOptions } from \"@tanstack/react-query\";\nimport type { IPerpetualsClient, MarketData } from \"../types\";\nimport { usePerpetualsClient } from \"./usePerpetualsClient\";\n\nexport interface UseMarketQueryParams {\n symbol: string;\n}\n\n/**\n * Default polling cadence for `metaAndAssetCtxs`. Mirrors Axiom's\n * perps page — they refresh meta + asset contexts (mark price, funding\n * rate, open interest, 24h volume) once a minute. Funding rate and\n * volume don't have a WebSocket channel, so without this the place\n * order form's Est. Liq. Price + the coin info header's funding /\n * 24h-vol can drift visibly between mounts.\n */\nconst DEFAULT_REFETCH_INTERVAL_MS = 60_000;\n\nexport function marketQueryKey(params: UseMarketQueryParams): string[] {\n return [\"perps\", \"market\", params.symbol];\n}\n\nexport async function fetchMarket(\n client: IPerpetualsClient,\n { symbol }: UseMarketQueryParams,\n): Promise<MarketData | null> {\n return await client.getMarket(symbol);\n}\n\nexport function useMarketQuery(\n params: UseMarketQueryParams,\n options: Omit<\n UseQueryOptions<MarketData | null, Error, MarketData | null, string[]>,\n \"queryKey\" | \"queryFn\"\n > = {},\n) {\n const { client } = usePerpetualsClient();\n return useQuery({\n queryKey: marketQueryKey(params),\n queryFn: async () => fetchMarket(client, params),\n // Treat the response as fresh for half the polling cadence so a\n // remount during the same window doesn't trigger an extra request.\n staleTime: DEFAULT_REFETCH_INTERVAL_MS / 2,\n refetchInterval: DEFAULT_REFETCH_INTERVAL_MS,\n ...options,\n });\n}\n","import { useQuery, UseQueryOptions } from \"@tanstack/react-query\";\nimport type { IPerpetualsClient, MarketData } from \"../types\";\nimport { usePerpetualsClient } from \"./usePerpetualsClient\";\n\nexport interface UseMarketsQueryParams {\n symbols?: string[];\n}\n\n/**\n * Default polling cadence for `metaAndAssetCtxs`. Mirrors the cadence\n * we observed on Axiom's perps page — they refresh meta + asset\n * contexts (mark price, funding rate, open interest, 24h volume) once\n * a minute. The data is comparatively cheap to refetch and changes on\n * roughly the same timescale, so a slower interval would let funding /\n * OI drift visibly between updates.\n */\nconst DEFAULT_REFETCH_INTERVAL_MS = 60_000;\n\nexport function marketsQueryKey(params: UseMarketsQueryParams = {}): string[] {\n return [\"perps\", \"markets\", JSON.stringify((params.symbols ?? []).sort())];\n}\n\nexport async function fetchMarkets(\n client: IPerpetualsClient,\n { symbols }: UseMarketsQueryParams = {},\n): Promise<MarketData[]> {\n return await client.getMarkets(symbols);\n}\n\nexport function useMarketsQuery(\n params: UseMarketsQueryParams = {},\n options: Omit<\n UseQueryOptions<MarketData[], Error, MarketData[], string[]>,\n \"queryKey\" | \"queryFn\"\n > = {},\n) {\n const { client } = usePerpetualsClient();\n return useQuery({\n queryKey: marketsQueryKey(params),\n queryFn: async () => fetchMarkets(client, params),\n // Treat the response as fresh for half the polling cadence so a\n // remount during the same window doesn't kick off an extra request.\n staleTime: DEFAULT_REFETCH_INTERVAL_MS / 2,\n refetchInterval: DEFAULT_REFETCH_INTERVAL_MS,\n ...options,\n });\n}\n","import { useQuery, UseQueryOptions } from \"@tanstack/react-query\";\nimport type { IPerpetualsClient, Kline, KlineInterval } from \"../types\";\nimport { usePerpetualsClient } from \"./usePerpetualsClient\";\n\nexport interface UseKlinesQueryParams {\n symbol: string;\n interval: KlineInterval;\n limit?: number;\n}\n\nexport function klinesQueryKey(params: UseKlinesQueryParams): string[] {\n return [\n \"perps\",\n \"klines\",\n params.symbol,\n params.interval,\n String(params.limit ?? 100),\n ];\n}\n\nexport async function fetchKlines(\n client: IPerpetualsClient,\n { symbol, interval, limit }: UseKlinesQueryParams,\n): Promise<Kline[]> {\n return await client.getKlines(symbol, interval, limit);\n}\n\nexport function useKlinesQuery(\n params: UseKlinesQueryParams,\n options: Omit<\n UseQueryOptions<Kline[], Error, Kline[], string[]>,\n \"queryKey\" | \"queryFn\"\n > = {},\n) {\n const { client } = usePerpetualsClient();\n return useQuery({\n queryKey: klinesQueryKey(params),\n queryFn: async () => fetchKlines(client, params),\n staleTime: 30 * 1000,\n ...options,\n });\n}\n","import { useQuery, UseQueryOptions } from \"@tanstack/react-query\";\nimport type {\n IPerpetualsClient,\n OrderBook,\n OrderBookAggregationOptions,\n} from \"../types\";\nimport { usePerpetualsClient } from \"./usePerpetualsClient\";\n\nexport interface UseOrderBookQueryParams {\n symbol: string;\n maxLevel?: number;\n /**\n * Optional venue aggregation params (e.g. Hyperliquid `nSigFigs` /\n * `mantissa`). When set, the request key includes these so different\n * aggregations cache independently.\n */\n aggregation?: OrderBookAggregationOptions;\n}\n\nexport function orderBookQueryKey(params: UseOrderBookQueryParams): string[] {\n const agg = params.aggregation;\n const aggKey =\n agg?.nSigFigs !== undefined\n ? `n${agg.nSigFigs}${\n agg.nSigFigs === 5 && agg.mantissa && agg.mantissa !== 1\n ? `m${agg.mantissa}`\n : \"\"\n }`\n : \"raw\";\n return [\n \"perps\",\n \"orderBook\",\n params.symbol,\n String(params.maxLevel ?? 20),\n aggKey,\n ];\n}\n\nexport async function fetchOrderBook(\n client: IPerpetualsClient,\n { symbol, maxLevel, aggregation }: UseOrderBookQueryParams,\n): Promise<OrderBook> {\n return await client.getOrderBook(symbol, maxLevel, aggregation);\n}\n\nexport function useOrderBookQuery(\n params: UseOrderBookQueryParams,\n options: Omit<\n UseQueryOptions<OrderBook, Error, OrderBook, string[]>,\n \"queryKey\" | \"queryFn\"\n > = {},\n) {\n const { client } = usePerpetualsClient();\n return useQuery({\n queryKey: orderBookQueryKey(params),\n queryFn: async () => fetchOrderBook(client, params),\n staleTime: 5 * 1000,\n ...options,\n });\n}\n","import { useQuery, UseQueryOptions } from \"@tanstack/react-query\";\nimport type { IPerpetualsClient, Trade } from \"../types\";\nimport { usePerpetualsClient } from \"./usePerpetualsClient\";\n\nexport interface UseRecentTradesQueryParams {\n symbol: string;\n limit?: number;\n}\n\nexport function recentTradesQueryKey(\n params: UseRecentTradesQueryParams,\n): string[] {\n return [\"perps\", \"recentTrades\", params.symbol, String(params.limit ?? 50)];\n}\n\nexport async function fetchRecentTrades(\n client: IPerpetualsClient,\n { symbol, limit }: UseRecentTradesQueryParams,\n): Promise<Trade[]> {\n return await client.getRecentTrades(symbol, limit);\n}\n\nexport function useRecentTradesQuery(\n params: UseRecentTradesQueryParams,\n options: Omit<\n UseQueryOptions<Trade[], Error, Trade[], string[]>,\n \"queryKey\" | \"queryFn\"\n > = {},\n) {\n const { client } = usePerpetualsClient();\n return useQuery({\n queryKey: recentTradesQueryKey(params),\n queryFn: async () => fetchRecentTrades(client, params),\n staleTime: 5 * 1000,\n ...options,\n });\n}\n","import { useQuery, UseQueryOptions } from \"@tanstack/react-query\";\nimport type {\n IPerpetualsClient,\n GetPositionsResult,\n GetPositionsParams,\n} from \"../types\";\nimport { usePerpetualsClient } from \"./usePerpetualsClient\";\n\nexport interface UsePositionsQueryParams extends GetPositionsParams {\n enabled?: boolean;\n}\n\nexport function positionsQueryKey(\n params: Omit<UsePositionsQueryParams, \"enabled\">,\n): string[] {\n return [\"perps\", \"positions\", params.userAddress ?? \"\", params.symbol ?? \"\"];\n}\n\nexport async function fetchPositions(\n client: IPerpetualsClient,\n params: GetPositionsParams,\n): Promise<GetPositionsResult> {\n return await client.getPositions(params);\n}\n\nexport function usePositionsQuery(\n params: UsePositionsQueryParams,\n options: Omit<\n UseQueryOptions<GetPositionsResult, Error, GetPositionsResult, string[]>,\n \"queryKey\" | \"queryFn\"\n > = {},\n) {\n const { client } = usePerpetualsClient();\n const { enabled = true, ...queryParams } = params;\n\n return useQuery({\n queryKey: positionsQueryKey(queryParams),\n queryFn: async () => fetchPositions(client, queryParams),\n enabled: enabled && !!queryParams.userAddress,\n staleTime: 10 * 1000,\n ...options,\n });\n}\n","import { useQuery, UseQueryOptions } from \"@tanstack/react-query\";\nimport type {\n IPerpetualsClient,\n GetOpenOrdersResult,\n GetOpenOrdersParams,\n} from \"../types\";\nimport { usePerpetualsClient } from \"./usePerpetualsClient\";\n\nexport interface UseOrdersQueryParams extends GetOpenOrdersParams {\n enabled?: boolean;\n}\n\nexport function ordersQueryKey(\n params: Omit<UseOrdersQueryParams, \"enabled\">,\n): string[] {\n return [\"perps\", \"orders\", params.userAddress ?? \"\", params.symbol ?? \"\"];\n}\n\nexport async function fetchOrders(\n client: IPerpetualsClient,\n params: GetOpenOrdersParams,\n): Promise<GetOpenOrdersResult> {\n return await client.getOpenOrders(params);\n}\n\nexport function useOrdersQuery(\n params: UseOrdersQueryParams,\n options: Omit<\n UseQueryOptions<GetOpenOrdersResult, Error, GetOpenOrdersResult, string[]>,\n \"queryKey\" | \"queryFn\"\n > = {},\n) {\n const { client } = usePerpetualsClient();\n const { enabled = true, ...queryParams } = params;\n\n return useQuery({\n queryKey: ordersQueryKey(queryParams),\n queryFn: async () => fetchOrders(client, queryParams),\n enabled: enabled && !!queryParams.userAddress,\n staleTime: 5 * 1000,\n ...options,\n });\n}\n","import { useQuery, UseQueryOptions } from \"@tanstack/react-query\";\nimport type {\n IPerpetualsClient,\n GetTradesResult,\n GetTradesParams,\n} from \"../types\";\nimport { usePerpetualsClient } from \"./usePerpetualsClient\";\n\nexport interface UseTradesQueryParams extends GetTradesParams {\n enabled?: boolean;\n}\n\nexport function tradesQueryKey(\n params: Omit<UseTradesQueryParams, \"enabled\">,\n): string[] {\n return [\n \"perps\",\n \"trades\",\n params.userAddress ?? \"\",\n params.symbol ?? \"\",\n String(params.limit ?? 50),\n String(params.startTime ?? \"\"),\n String(params.endTime ?? \"\"),\n ];\n}\n\nexport async function fetchTrades(\n client: IPerpetualsClient,\n params: GetTradesParams,\n): Promise<GetTradesResult> {\n return await client.getTrades(params);\n}\n\nexport function useTradesQuery(\n params: UseTradesQueryParams,\n options: Omit<\n UseQueryOptions<GetTradesResult, Error, GetTradesResult, string[]>,\n \"queryKey\" | \"queryFn\"\n > = {},\n) {\n const { client } = usePerpetualsClient();\n const { enabled = true, ...queryParams } = params;\n\n return useQuery({\n queryKey: tradesQueryKey(queryParams),\n queryFn: async () => fetchTrades(client, queryParams),\n enabled: enabled && !!queryParams.userAddress,\n staleTime: 30 * 1000,\n ...options,\n });\n}\n","import { useQuery, UseQueryOptions } from \"@tanstack/react-query\";\nimport type {\n ActiveAssetLeverage,\n GetActiveAssetLeverageParams,\n IPerpetualsClient,\n} from \"../types\";\nimport { usePerpetualsClient } from \"./usePerpetualsClient\";\n\nexport interface UseActiveAssetLeverageQueryParams {\n /** User wallet address. Query stays disabled until this is set. */\n userAddress?: string;\n /** Trading pair symbol (e.g. \"BTC-USDC\"). */\n symbol: string;\n /** Optional override; useful for tests. */\n enabled?: boolean;\n}\n\n/**\n * React Query key for the user's per-asset leverage configuration.\n *\n * Accepts an undefined `userAddress` (e.g. before the wallet connects)\n * because consumers often want a stable key shape to feed\n * `invalidateQueries` after the address resolves. The fallback empty\n * string just makes the key deterministic; the query itself stays\n * disabled until both fields are populated.\n */\nexport function activeAssetLeverageQueryKey(params: {\n userAddress?: GetActiveAssetLeverageParams[\"userAddress\"];\n symbol?: GetActiveAssetLeverageParams[\"symbol\"];\n}): string[] {\n return [\n \"perps\",\n \"activeAssetLeverage\",\n params.userAddress ?? \"\",\n params.symbol ?? \"\",\n ];\n}\n\nexport async function fetchActiveAssetLeverage(\n client: IPerpetualsClient,\n params: GetActiveAssetLeverageParams,\n): Promise<ActiveAssetLeverage | null> {\n return await client.getActiveAssetLeverage(params);\n}\n\n/**\n * Read the user's configured leverage for `symbol` from the venue,\n * independent of whether an open position exists. Backed by Hyperliquid's\n * `activeAssetData` info endpoint when the active provider is\n * Hyperliquid; the LiberFi adapter currently returns `null` (the form\n * will fall back to its default).\n *\n * The returned data updates every 30s while the form is mounted, and\n * the consumer is expected to invalidate the query after a successful\n * `updateLeverage` so the UI reflects the new value immediately.\n */\nexport function useActiveAssetLeverageQuery(\n params: UseActiveAssetLeverageQueryParams,\n options: Omit<\n UseQueryOptions<\n ActiveAssetLeverage | null,\n Error,\n ActiveAssetLeverage | null,\n string[]\n >,\n \"queryKey\" | \"queryFn\"\n > = {},\n) {\n const { client } = usePerpetualsClient();\n const { enabled = true, userAddress, symbol } = params;\n\n return useQuery({\n queryKey: activeAssetLeverageQueryKey({ userAddress, symbol }),\n queryFn: async () => {\n // The `enabled` guard below ensures `userAddress` is defined by\n // the time React Query runs the fetcher, but TypeScript can't\n // narrow that on its own — surface it as a runtime invariant.\n if (!userAddress) {\n throw new Error(\"useActiveAssetLeverageQuery: userAddress is required\");\n }\n return fetchActiveAssetLeverage(client, { userAddress, symbol });\n },\n enabled: enabled && !!userAddress && !!symbol,\n staleTime: 30 * 1000,\n ...options,\n });\n}\n","import { useQuery, UseQueryOptions } from \"@tanstack/react-query\";\nimport type {\n AssetMeta,\n GetAssetMetaParams,\n IPerpetualsClient,\n} from \"../types\";\nimport { usePerpetualsClient } from \"./usePerpetualsClient\";\n\nexport interface UseAssetMetaQueryParams {\n /** Trading pair symbol (e.g. \"BTC-USDC\"). */\n symbol?: string;\n /** Optional override; useful for tests. */\n enabled?: boolean;\n}\n\n/**\n * React Query key for the per-asset metadata query.\n *\n * Tolerates an undefined `symbol` so consumers can build a stable key\n * shape before the symbol resolves; the query itself stays disabled\n * until both `enabled` and `symbol` are truthy.\n */\nexport function assetMetaQueryKey(params: {\n symbol?: GetAssetMetaParams[\"symbol\"];\n}): string[] {\n return [\"perps\", \"assetMeta\", params.symbol ?? \"\"];\n}\n\nexport async function fetchAssetMeta(\n client: IPerpetualsClient,\n params: GetAssetMetaParams,\n): Promise<AssetMeta | null> {\n return await client.getAssetMeta(params);\n}\n\n/**\n * Read the venue's static metadata (`szDecimals`, `maxLeverage`) for\n * `symbol`. Backed by Hyperliquid's `meta` info endpoint when the\n * active provider is Hyperliquid; the LiberFi adapter currently\n * returns `null` (the form falls back to an adaptive precision rule).\n *\n * The data is process-stable for minutes at a time (Hyperliquid only\n * updates the universe on listing additions / leverage cap changes),\n * so we set a generous `staleTime` of 60 seconds. Consumers don't\n * need to invalidate this on user actions — the data is keyed on\n * symbol alone.\n */\nexport function useAssetMetaQuery(\n params: UseAssetMetaQueryParams,\n options: Omit<\n UseQueryOptions<AssetMeta | null, Error, AssetMeta | null, string[]>,\n \"queryKey\" | \"queryFn\"\n > = {},\n) {\n const { client } = usePerpetualsClient();\n const { enabled = true, symbol } = params;\n\n return useQuery({\n queryKey: assetMetaQueryKey({ symbol }),\n queryFn: async () => {\n // The `enabled` guard below ensures `symbol` is defined by the\n // time React Query runs the fetcher, but TypeScript can't\n // narrow that on its own — surface it as a runtime invariant.\n if (!symbol) {\n throw new Error(\"useAssetMetaQuery: symbol is required\");\n }\n return fetchAssetMeta(client, { symbol });\n },\n enabled: enabled && !!symbol,\n staleTime: 60 * 1000,\n ...options,\n });\n}\n","import { useMutation, UseMutationOptions } from \"@tanstack/react-query\";\nimport type {\n IPerpetualsClient,\n PlaceOrderParams,\n PlaceOrderResult,\n} from \"../types\";\nimport { usePerpetualsClient } from \"./usePerpetualsClient\";\n\nexport type UseCreateOrderMutationParams = PlaceOrderParams;\n\nexport async function createOrder(\n client: IPerpetualsClient,\n params: UseCreateOrderMutationParams,\n): Promise<PlaceOrderResult> {\n return await client.placeOrder(params);\n}\n\nexport function useCreateOrderMutation(\n options: Omit<\n UseMutationOptions<PlaceOrderResult, Error, UseCreateOrderMutationParams>,\n \"mutationFn\"\n > = {},\n) {\n const { client } = usePerpetualsClient();\n return useMutation({\n mutationFn: async (params: UseCreateOrderMutationParams) =>\n createOrder(client, params),\n ...options,\n });\n}\n","import { useMutation, UseMutationOptions } from \"@tanstack/react-query\";\nimport type {\n IPerpetualsClient,\n CancelOrderParams,\n CancelOrderResult,\n} from \"../types\";\nimport { usePerpetualsClient } from \"./usePerpetualsClient\";\n\nexport type UseCancelOrderMutationParams = CancelOrderParams;\n\nexport async function cancelOrder(\n client: IPerpetualsClient,\n params: UseCancelOrderMutationParams,\n): Promise<CancelOrderResult> {\n return await client.cancelOrder(params);\n}\n\nexport function useCancelOrderMutation(\n options: Omit<\n UseMutationOptions<CancelOrderResult, Error, UseCancelOrderMutationParams>,\n \"mutationFn\"\n > = {},\n) {\n const { client } = usePerpetualsClient();\n return useMutation({\n mutationFn: async (params: UseCancelOrderMutationParams) =>\n cancelOrder(client, params),\n ...options,\n });\n}\n","import { useEffect, useState, useCallback, useRef } from \"react\";\nimport type {\n MarketData,\n Trade,\n OrderBook,\n OrderBookAggregationOptions,\n} from \"../types\";\nimport { usePerpetualsClient } from \"./usePerpetualsClient\";\n\nexport type MarketDataType = \"ticker\" | \"trades\" | \"orderBook\";\n\nexport interface UseMarketDataSubscriptionParams {\n type: MarketDataType;\n symbol: string;\n enabled?: boolean;\n /**\n * Optional venue aggregation hint (only meaningful when\n * `type === \"orderBook\"`). Changing it tears down and re-creates the\n * subscription so the upstream stream is re-keyed with the new\n * `nSigFigs` / `mantissa`.\n */\n aggregation?: OrderBookAggregationOptions;\n /**\n * If set, coalesce upstream pushes into a single React `setData` call no\n * more than once every `throttleMs` milliseconds. The latest payload\n * always wins; intermediate pushes are dropped. Use this for high-rate\n * streams (e.g. orderBook on active markets) where the human eye can't\n * tell the difference between 30 Hz and 10 Hz but React reconciliation\n * cost scales linearly.\n *\n * Leave undefined to forward every push immediately (default).\n */\n throttleMs?: number;\n}\n\nexport interface UseMarketDataSubscriptionResult<T> {\n data: T | null;\n isConnected: boolean;\n error: Error | null;\n}\n\nexport function useMarketDataSubscription<\n T = MarketDataType extends \"ticker\"\n ? MarketData\n : MarketDataType extends \"trades\"\n ? Trade\n : OrderBook,\n>(params: UseMarketDataSubscriptionParams): UseMarketDataSubscriptionResult<T> {\n const { type, symbol, enabled = true, aggregation, throttleMs } = params;\n const { client } = usePerpetualsClient();\n const [data, setData] = useState<T | null>(null);\n const [isConnected, setIsConnected] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n // Throttling state. We keep the most-recent payload in a ref and flush it\n // through `setData` on a trailing-edge timer. Refs (not state) so updating\n // them never triggers a render.\n const pendingDataRef = useRef<T | null>(null);\n const flushTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const throttleMsRef = useRef<number | undefined>(throttleMs);\n // Keep the ref in sync without re-creating `handleData` every render —\n // changing the throttle interval shouldn't tear down the WS subscription.\n throttleMsRef.current = throttleMs;\n\n const handleData = useCallback((newData: T) => {\n const interval = throttleMsRef.current;\n if (!interval || interval <= 0) {\n setData(newData);\n return;\n }\n // Always remember the latest payload; the trailing flush will pick it up.\n pendingDataRef.current = newData;\n if (flushTimerRef.current === null) {\n flushTimerRef.current = setTimeout(() => {\n flushTimerRef.current = null;\n if (pendingDataRef.current !== null) {\n const next = pendingDataRef.current;\n pendingDataRef.current = null;\n setData(next);\n }\n }, interval);\n }\n }, []);\n\n // Stable string key derived from aggregation. Effect re-runs only when this\n // changes (not on every parent render that produces a fresh object).\n const aggregationKey =\n aggregation?.nSigFigs !== undefined\n ? `n${aggregation.nSigFigs}${\n aggregation.nSigFigs === 5 &&\n aggregation.mantissa &&\n aggregation.mantissa !== 1\n ? `m${aggregation.mantissa}`\n : \"\"\n }`\n : \"\";\n\n useEffect(() => {\n if (!enabled) {\n return;\n }\n\n let subscriptionId: string | null = null;\n let isSubscribed = true;\n\n const connect = async () => {\n try {\n await client.connectWebSocket();\n\n if (!isSubscribed) return;\n\n setIsConnected(true);\n setError(null);\n\n subscriptionId = client.subscribeMarketData(\n type,\n symbol,\n handleData,\n type === \"orderBook\" && aggregation ? { aggregation } : undefined,\n );\n } catch (err) {\n if (isSubscribed) {\n setError(err instanceof Error ? err : new Error(\"Connection failed\"));\n setIsConnected(false);\n }\n }\n };\n\n connect();\n\n return () => {\n isSubscribed = false;\n if (subscriptionId) {\n try {\n client.unsubscribe(subscriptionId);\n } catch (err) {\n console.error(\"Failed to unsubscribe:\", err);\n }\n }\n client.disconnectWebSocket();\n // Drop any pending throttled payload so it can't land after the\n // subscription is torn down.\n if (flushTimerRef.current !== null) {\n clearTimeout(flushTimerRef.current);\n flushTimerRef.current = null;\n }\n pendingDataRef.current = null;\n setIsConnected(false);\n setData(null);\n };\n // aggregationKey is intentionally part of deps so re-subscribing on\n // precision change tears down the old stream and starts a new one with\n // the new nSigFigs/mantissa.\n }, [client, type, symbol, enabled, handleData, aggregationKey]);\n\n return { data, isConnected, error };\n}\n","import { useEffect, useState, useCallback } from \"react\";\nimport type { Kline, KlineInterval } from \"../types\";\nimport { usePerpetualsClient } from \"./usePerpetualsClient\";\n\nexport interface UseCandlesSubscriptionParams {\n symbol: string;\n interval: KlineInterval;\n enabled?: boolean;\n}\n\nexport interface UseCandlesSubscriptionResult {\n data: Kline | null;\n isConnected: boolean;\n error: Error | null;\n}\n\nexport function useCandlesSubscription(\n params: UseCandlesSubscriptionParams,\n): UseCandlesSubscriptionResult {\n const { symbol, interval, enabled = true } = params;\n const { client } = usePerpetualsClient();\n const [data, setData] = useState<Kline | null>(null);\n const [isConnected, setIsConnected] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const handleData = useCallback((newData: Kline) => {\n setData(newData);\n }, []);\n\n useEffect(() => {\n if (!enabled) {\n return;\n }\n\n let subscriptionId: string | null = null;\n let isSubscribed = true;\n\n const connect = async () => {\n try {\n await client.connectWebSocket();\n\n if (!isSubscribed) return;\n\n setIsConnected(true);\n setError(null);\n\n subscriptionId = client.subscribeCandles(symbol, interval, handleData);\n } catch (err) {\n if (isSubscribed) {\n setError(err instanceof Error ? err : new Error(\"Connection failed\"));\n setIsConnected(false);\n }\n }\n };\n\n connect();\n\n return () => {\n isSubscribed = false;\n if (subscriptionId) {\n try {\n client.unsubscribe(subscriptionId);\n } catch (err) {\n console.error(\"Failed to unsubscribe:\", err);\n }\n }\n client.disconnectWebSocket();\n setIsConnected(false);\n setData(null);\n };\n }, [client, symbol, interval, enabled, handleData]);\n\n return { data, isConnected, error };\n}\n","import { useEffect, useState, useCallback } from \"react\";\nimport type { Order, Position, TradeHistory } from \"../types\";\nimport { usePerpetualsClient } from \"./usePerpetualsClient\";\n\nexport type UserDataType = \"orders\" | \"positions\" | \"fills\";\n\nexport interface UseUserDataSubscriptionParams {\n type: UserDataType;\n userAddress: string;\n enabled?: boolean;\n}\n\nexport interface UseUserDataSubscriptionResult<T> {\n data: T | null;\n isConnected: boolean;\n error: Error | null;\n}\n\nexport function useUserDataSubscription<\n T = UserDataType extends \"orders\"\n ? Order\n : UserDataType extends \"positions\"\n ? Position\n : TradeHistory,\n>(params: UseUserDataSubscriptionParams): UseUserDataSubscriptionResult<T> {\n const { type, userAddress, enabled = true } = params;\n const { client } = usePerpetualsClient();\n const [data, setData] = useState<T | null>(null);\n const [isConnected, setIsConnected] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const handleData = useCallback((newData: T) => {\n setData(newData);\n }, []);\n\n useEffect(() => {\n if (!enabled || !userAddress) {\n return;\n }\n\n let subscriptionId: string | null = null;\n let isSubscribed = true;\n\n const connect = async () => {\n try {\n await client.connectWebSocket();\n\n if (!isSubscribed) return;\n\n setIsConnected(true);\n setError(null);\n\n subscriptionId = client.subscribeUserData(\n type,\n userAddress,\n handleData,\n );\n } catch (err) {\n if (isSubscribed) {\n setError(err instanceof Error ? err : new Error(\"Connection failed\"));\n setIsConnected(false);\n }\n }\n };\n\n connect();\n\n return () => {\n isSubscribed = false;\n if (subscriptionId) {\n try {\n client.unsubscribe(subscriptionId);\n } catch (err) {\n console.error(\"Failed to unsubscribe:\", err);\n }\n }\n client.disconnectWebSocket();\n setIsConnected(false);\n setData(null);\n };\n }, [client, type, userAddress, enabled, handleData]);\n\n return { data, isConnected, error };\n}\n","import { useQuery, UseQueryOptions } from \"@tanstack/react-query\";\nimport type { AccountState } from \"../types\";\n\nexport interface UseAccountStateQueryParams {\n /** User wallet address. The query is disabled when missing. */\n userAddress?: string;\n enabled?: boolean;\n}\n\n/**\n * Stable React Query key for the user's full account state. Shared\n * between {@link useAccountStateQuery} (read) and\n * `useAccountStateSubscription` (write) so a webData2 push and a\n * consumer reader land on the same cache slot.\n */\nexport function accountStateQueryKey(\n params: Pick<UseAccountStateQueryParams, \"userAddress\">,\n): string[] {\n return [\"perps\", \"accountState\", params.userAddress ?? \"\"];\n}\n\n/**\n * Read the user's full account state (positions, open orders, spot\n * balances, available margin) from the React Query cache.\n *\n * This hook does NOT itself fetch data over HTTP — the cache is fed\n * exclusively by `useAccountStateSubscription`, which subscribes to\n * Hyperliquid's `webData2` push channel and writes every snapshot\n * into the same cache slot. Mount the subscription somewhere high in\n * the tree (e.g. an app-shell layout) and this hook becomes a cheap\n * subscriber that re-renders whenever a fresh push lands.\n *\n * Returning `null` means no push has been received yet — wait for the\n * subscription to flush its initial snapshot rather than firing a\n * REST fallback, since `webData2` always primes the stream on\n * connect.\n *\n * @example\n * function WalletButton() {\n * const { address } = useWallet();\n * const { data: account } = useAccountStateQuery({ userAddress: address });\n * return <span>{account?.availableBalance.toFixed(2)} USDC</span>;\n * }\n */\nexport function useAccountStateQuery(\n params: UseAccountStateQueryParams,\n options: Omit<\n UseQueryOptions<AccountState | null, Error, AccountState | null, string[]>,\n \"queryKey\" | \"queryFn\"\n > = {},\n) {\n const { enabled = true, ...rest } = params;\n\n return useQuery({\n queryKey: accountStateQueryKey(rest),\n // No-op queryFn: the WebSocket subscription owns this cache. If a\n // consumer mounts the read hook before the writer, we surface\n // `null` until the first push — that's a tighter contract than\n // racing a REST fallback against the WS handshake.\n queryFn: () => null as AccountState | null,\n enabled: enabled && !!rest.userAddress,\n // The subscription pushes every server tick, so any data already\n // in the cache is by definition fresh. Disable automatic\n // background refetches.\n staleTime: Infinity,\n refetchOnWindowFocus: false,\n refetchOnReconnect: false,\n ...options,\n });\n}\n","\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { useQueryClient } from \"@tanstack/react-query\";\nimport type {\n AccountState,\n GetOpenOrdersResult,\n GetPositionsResult,\n} from \"../types\";\nimport { accountStateQueryKey } from \"./useAccountStateQuery\";\nimport { ordersQueryKey } from \"./useOrdersQuery\";\nimport { usePerpetualsClient } from \"./usePerpetualsClient\";\nimport { positionsQueryKey } from \"./usePositionsQuery\";\n\nexport interface UseAccountStateSubscriptionParams {\n /**\n * Wallet address whose state should be tracked. When undefined or\n * empty the subscription is disabled, so it's safe to mount this\n * hook before authentication completes.\n */\n userAddress?: string;\n /** Disable the subscription entirely (e.g. for SSR / paused tabs). */\n enabled?: boolean;\n}\n\nexport interface UseAccountStateSubscriptionResult {\n /** Latest account state pushed by the venue. */\n data: AccountState | null;\n /** WebSocket connection status (true after the first successful connect). */\n isConnected: boolean;\n /** Last connection / subscription error, or null on success. */\n error: Error | null;\n}\n\n/**\n * Subscribe to the venue's unified user-state push channel\n * (Hyperliquid's `webData2`) and fan the snapshots out across the\n * SDK's React Query caches.\n *\n * Why this hook exists:\n *\n * The naive way to keep `usePositionsQuery`, `useOrdersQuery`, and a\n * spot-balance reader live is to crank their `refetchInterval` down to\n * a few seconds, hammering Hyperliquid's `clearinghouseState` /\n * `spotClearinghouseState` / `openOrders` endpoints. That trades\n * bandwidth for latency and still misses fills between polls. Axiom\n * uses a single `webData2` subscription instead, and so should we.\n *\n * On every push this hook writes the parsed snapshot to:\n * - {@link accountStateQueryKey} — the canonical cache slot read by\n * {@link useAccountStateQuery} (consumed by wallet buttons,\n * deposit modals, etc.).\n * - {@link positionsQueryKey} — keeps `usePositionsQuery` in sync so\n * the place-order form's Available Margin / Current Position\n * reflects the venue without a second REST round-trip.\n * - {@link ordersQueryKey} — keeps `useOrdersQuery` in sync for the\n * open-orders table.\n *\n * Mount this hook **once** at the top of the perpetuals shell (a\n * shared layout, an app-wide provider, …). Children read through\n * existing hooks; nothing else needs to know that the data arrives\n * via WebSocket.\n *\n * Falls back gracefully when the venue does not support a unified\n * channel: if `client.subscribeAccountState` is missing the hook is a\n * no-op, and the existing REST polling continues to drive the caches.\n */\nexport function useAccountStateSubscription(\n params: UseAccountStateSubscriptionParams,\n): UseAccountStateSubscriptionResult {\n const { userAddress, enabled = true } = params;\n const { client } = usePerpetualsClient();\n const queryClient = useQueryClient();\n const [data, setData] = useState<AccountState | null>(null);\n const [isConnected, setIsConnected] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n useEffect(() => {\n if (!enabled || !userAddress) {\n return;\n }\n\n // Optional contract: not every venue exposes a unified user\n // channel. If the adapter doesn't implement it, leave the existing\n // REST-driven caches alone instead of crashing on `undefined()`.\n if (typeof client.subscribeAccountState !== \"function\") {\n return;\n }\n\n let subscriptionId: string | null = null;\n let isMounted = true;\n\n const handlePush = (state: AccountState) => {\n if (!isMounted) return;\n setData(state);\n\n // Mirror the snapshot across the per-cache slots that existing\n // consumers (Place Order form, positions table, open orders\n // widget) already read from. `setQueryData` also bumps\n // `dataUpdatedAt`, which marks the cache fresh and prevents the\n // accompanying REST queries from re-firing on focus / mount\n // while the subscription is alive.\n queryClient.setQueryData(accountStateQueryKey({ userAddress }), state);\n\n const positionsResult: GetPositionsResult = {\n positions: state.positions,\n totalEquity: state.totalEquity,\n availableBalance: state.availableBalance,\n totalUnrealizedPnl: state.totalUnrealizedPnl,\n raw: state.raw,\n };\n queryClient.setQueryData(\n positionsQueryKey({ userAddress }),\n positionsResult,\n );\n\n const ordersResult: GetOpenOrdersResult = {\n orders: state.openOrders,\n totalCount: state.openOrders.length,\n raw: state.raw,\n };\n queryClient.setQueryData(ordersQueryKey({ userAddress }), ordersResult);\n };\n\n const connect = async () => {\n try {\n await client.connectWebSocket();\n if (!isMounted) return;\n setIsConnected(true);\n setError(null);\n subscriptionId = client.subscribeAccountState!(userAddress, handlePush);\n } catch (err) {\n if (!isMounted) return;\n setIsConnected(false);\n setError(\n err instanceof Error ? err : new Error(\"WebSocket connect failed\"),\n );\n }\n };\n\n void connect();\n\n return () => {\n isMounted = false;\n if (subscriptionId) {\n try {\n client.unsubscribe(subscriptionId);\n } catch (unsubError) {\n console.error(\n \"[useAccountStateSubscription] unsubscribe failed:\",\n unsubError,\n );\n }\n }\n client.disconnectWebSocket();\n setIsConnected(false);\n };\n }, [client, queryClient, userAddress, enabled]);\n\n return { data, isConnected, error };\n}\n","import { useContext } from \"react\";\nimport type { IPerpDepositClient } from \"../client/liberfi/LiberFiPerpDepositClient\";\nimport { PerpetualsContext } from \"../context/PerpetualsContext\";\n\n/**\n * Hook to access the deposit client from `PerpetualsProvider`.\n *\n * Throws if the provider is missing OR if the host app forgot to pass\n * `depositClient`. The thrown message tells the consumer exactly what\n * to fix — preferring an explicit error to a silent runtime crash deep\n * inside a useQuery hook.\n *\n * @returns The deposit client instance.\n */\nexport function usePerpDepositClient(): IPerpDepositClient {\n const ctx = useContext(PerpetualsContext);\n if (!ctx || !ctx.client) {\n throw new Error(\n \"usePerpDepositClient must be used within a <PerpetualsProvider>.\",\n );\n }\n if (!ctx.depositClient) {\n throw new Error(\n \"usePerpDepositClient: <PerpetualsProvider> was rendered without a `depositClient` prop. \" +\n \"Pass a `LiberFiPerpDepositClient` instance to enable the deposit flow.\",\n );\n }\n return ctx.depositClient;\n}\n\n/**\n * Safe variant — returns `undefined` instead of throwing when\n * `depositClient` is not configured. Use this in hooks that should\n * degrade gracefully (e.g. query hooks that gate on `enabled`) rather\n * than crash when the deposit flow is not wired up.\n */\nexport function usePerpDepositClientMaybe(): IPerpDepositClient | undefined {\n const ctx = useContext(PerpetualsContext);\n return ctx?.depositClient;\n}\n","import { useQuery, UseQueryOptions } from \"@tanstack/react-query\";\nimport type { IPerpDepositClient } from \"../client/liberfi/LiberFiPerpDepositClient\";\nimport type {\n DepositQuoteRequest,\n DepositQuoteResponse,\n} from \"../client/liberfi/deposit-types\";\nimport { usePerpDepositClientMaybe } from \"./usePerpDepositClient\";\n\n/**\n * Stable query key shape for the deposit quote.\n *\n * The amount is part of the key so re-quoting on amount change does not\n * leak across users; the user/recipient pair is included so two users\n * sharing the same browser session don't see each other's quotes in the\n * cache.\n */\nexport function perpDepositQuoteQueryKey(\n req?: DepositQuoteRequest | null,\n): readonly unknown[] {\n return [\"perps\", \"deposit\", \"quote\", req] as const;\n}\n\n/** Pure fetcher — useful for SSR or for invoking outside React. */\nexport async function fetchPerpDepositQuote(\n client: IPerpDepositClient,\n req: DepositQuoteRequest,\n): Promise<DepositQuoteResponse> {\n return client.quote(req);\n}\n\nexport interface UsePerpDepositQuoteOptions extends Omit<\n UseQueryOptions<\n DepositQuoteResponse,\n Error,\n DepositQuoteResponse,\n ReturnType<typeof perpDepositQuoteQueryKey>\n >,\n \"queryKey\" | \"queryFn\" | \"enabled\"\n> {\n /**\n * Override automatic gating. By default the query runs when `req` is\n * fully populated. Pass `enabled: false` to defer firing while the\n * user is still typing the amount.\n */\n enabled?: boolean;\n}\n\n/**\n * Re-quotes on every parameter change, with TanStack Query handling\n * dedupe / refetch / cancellation. Caller is responsible for surfacing\n * `data.expiresAt` to the UI; the FSM will move to `expired` if the\n * user lingers past the deadline.\n *\n * Engineering note: the hook deliberately does NOT auto-refresh on a\n * timer. Re-quoting silently behind the user would erase the “Confirm”\n * button mid-action; the form should re-call `refetch()` on its own\n * cadence (e.g. when `expiresAt` is < 5 s from now).\n */\nexport function usePerpDepositQuote(\n req: DepositQuoteRequest | null | undefined,\n options: UsePerpDepositQuoteOptions = {},\n) {\n const client = usePerpDepositClientMaybe();\n const enabled =\n (options.enabled ?? Boolean(isQuoteReady(req))) && Boolean(client);\n return useQuery({\n queryKey: perpDepositQuoteQueryKey(req ?? null),\n queryFn: async () =>\n fetchPerpDepositQuote(client!, req as DepositQuoteRequest),\n enabled,\n staleTime: 0, // quotes are short-lived; never reuse silently\n gcTime: 30_000,\n refetchOnWindowFocus: false,\n ...options,\n });\n}\n\nfunction isQuoteReady(\n req: DepositQuoteRequest | null | undefined,\n): req is DepositQuoteRequest {\n return Boolean(\n req &&\n req.userSolanaAddress &&\n req.hyperliquidRecipient &&\n req.grossLamports &&\n req.source,\n );\n}\n","import { useCallback, useReducer } from \"react\";\nimport {\n type DepositEvent,\n type DepositState,\n initialDepositState,\n reduceDepositState,\n} from \"../client/liberfi/deposit-state-machine\";\nimport type {\n DepositErrorInfo,\n DepositQuoteResponse,\n DepositSource,\n DepositSubmitRequest,\n} from \"../client/liberfi/deposit-types\";\nimport { LiberFiApiError } from \"../client/liberfi/transport\";\nimport { usePerpDepositClientMaybe } from \"./usePerpDepositClient\";\n\n/**\n * Adapter the host app must provide. Lives on the consumer side so the\n * SDK never has to know how a particular wallet (Phantom / Backpack /\n * Privy / Solflare / …) signs and broadcasts a Solana transaction.\n *\n * Contract:\n * - Decode the `serializedTxBase64` produced by /quote.\n * - Have the user sign it (this is when the wallet UI shows up).\n * - Broadcast it. Return the resulting tx hash.\n * - Throw on user rejection or RPC failure.\n *\n * The SDK keeps things narrow: signature, broadcast, and \"did the wallet\n * succeed\" are the only outputs we care about. Everything else (RPC\n * endpoint, commitment, simulation pre-checks) is an implementation\n * detail the host already owns.\n */\nexport type SignAndBroadcastSolanaTx = (\n serializedTxBase64: string,\n ctx: { isVersioned: boolean; sizeBytes: number },\n) => Promise<string>;\n\n/** Inputs every deposit attempt needs. */\nexport interface ExecuteDepositInput {\n /** The quote previously returned by `/v1/deposits/quote`. */\n quote: DepositQuoteResponse;\n /** User-facing identifiers; must match what was sent to /quote. */\n userSolanaAddress: string;\n hyperliquidRecipient: string;\n /** LiberFi user id (NOT the wallet). Stable for fee attribution. */\n userId: string;\n source: DepositSource;\n /** Optional marketing / referral code. */\n campaign?: string;\n}\n\n/** Hook return shape — exposes the full FSM and a single trigger. */\nexport interface UsePerpDepositExecuteResult {\n state: DepositState;\n /**\n * Kick off the sign → broadcast → submit chain. Returns the eventual\n * `intentId` on success, throws on failure (the FSM will already be\n * in the `failed` phase with a descriptive `error`).\n */\n execute: (input: ExecuteDepositInput) => Promise<string>;\n /** Force back to `idle`. Use when the user dismisses the modal. */\n reset: () => void;\n /** Manually push an event into the FSM (advanced). */\n dispatch: (event: DepositEvent) => void;\n}\n\n/**\n * Orchestrates the full deposit flow:\n *\n * 1. SIGN_START → wallet signs (host adapter)\n * 2. BROADCAST_START → wallet broadcasts (host adapter)\n * 3. SUBMIT_OK → POST /v1/deposits/submit (this hook)\n * 4. STATUS_UPDATE ← `usePerpDepositStatus` polls and forwards\n *\n * Each stage emits a typed event into the same reducer used by the\n * presentational components. The hook itself never renders anything —\n * components consume `state.phase` and react accordingly.\n */\nexport function usePerpDepositExecute(\n signAndBroadcast: SignAndBroadcastSolanaTx,\n): UsePerpDepositExecuteResult {\n const client = usePerpDepositClientMaybe();\n const [state, dispatch] = useReducer(reduceDepositState, initialDepositState);\n\n const reset = useCallback(() => {\n dispatch({ type: \"RESET\" });\n }, []);\n\n const execute = useCallback<UsePerpDepositExecuteResult[\"execute\"]>(\n async (input) => {\n const { quote } = input;\n dispatch({ type: \"SIGN_START\" });\n let solanaTxHash: string;\n try {\n solanaTxHash = await signAndBroadcast(quote.serializedTxBase64, {\n isVersioned: quote.isVersioned,\n sizeBytes: quote.sizeBytes,\n });\n if (!solanaTxHash) {\n throw new Error(\"wallet returned an empty tx hash\");\n }\n } catch (err) {\n const info = toErrorInfo(err, \"WALLET_SIGN_OR_BROADCAST_FAILED\");\n // Distinguish sign vs broadcast: the FSM treats them the same\n // (both transition into `failed`) but we keep the original\n // event name for analytics correlation.\n dispatch({ type: \"SIGN_FAILED\", error: info });\n throw err;\n }\n\n // Optimistic broadcast → submit handshake. The FSM expects the\n // broadcast event before SUBMIT_OK so the phase stays consistent\n // across retries; the wallet adapter has already broadcasted by\n // the time we reach this line, so we fire both events back-to-back.\n dispatch({ type: \"BROADCAST_START\" });\n\n const submitReq: DepositSubmitRequest = {\n userSolanaAddress: input.userSolanaAddress,\n hyperliquidRecipient: input.hyperliquidRecipient,\n solanaTxHash,\n breakdown: quote.breakdown,\n userId: input.userId,\n source: input.source,\n campaign: input.campaign,\n quoteIssuedAt: quote.issuedAt,\n };\n\n if (!client) {\n dispatch({\n type: \"SUBMIT_FAILED\",\n error: {\n code: \"DEPOSIT_CLIENT_NOT_CONFIGURED\",\n message: \"Deposit client is not configured.\",\n recoverable: false,\n },\n });\n throw new Error(\"Deposit client is not configured.\");\n }\n try {\n const out = await client.submit(submitReq);\n dispatch({\n type: \"SUBMIT_OK\",\n intentId: out.intentId,\n solanaTxHash,\n });\n return out.intentId;\n } catch (err) {\n const info = toErrorInfo(err, \"DEPOSIT_SUBMIT_FAILED\");\n dispatch({ type: \"SUBMIT_FAILED\", error: info });\n throw err;\n }\n },\n [client, signAndBroadcast],\n );\n\n return { state, execute, reset, dispatch };\n}\n\nfunction toErrorInfo(err: unknown, fallbackCode: string): DepositErrorInfo {\n if (err instanceof LiberFiApiError) {\n // Try to extract the backend's typed { code, message } from the body.\n const parsed = parseJsonSafe(err.responseBody) as\n | { code?: string; message?: string }\n | undefined;\n return {\n code: parsed?.code ?? fallbackCode,\n message: parsed?.message ?? err.message,\n recoverable: err.statusCode >= 500 || err.statusCode === 408,\n };\n }\n if (err instanceof Error) {\n return { code: fallbackCode, message: err.message, recoverable: true };\n }\n return { code: fallbackCode, message: String(err), recoverable: true };\n}\n\nfunction parseJsonSafe(text: string): unknown {\n if (!text) return undefined;\n try {\n return JSON.parse(text);\n } catch {\n return undefined;\n }\n}\n","import { useQuery, UseQueryOptions } from \"@tanstack/react-query\";\nimport type { IPerpDepositClient } from \"../client/liberfi/LiberFiPerpDepositClient\";\nimport {\n TERMINAL_DEPOSIT_STATUSES,\n type DepositStatusResponse,\n} from \"../client/liberfi/deposit-types\";\nimport { usePerpDepositClientMaybe } from \"./usePerpDepositClient\";\n\nexport function perpDepositStatusQueryKey(\n intentId?: string,\n): readonly unknown[] {\n return [\"perps\", \"deposit\", \"status\", intentId ?? null] as const;\n}\n\nexport async function fetchPerpDepositStatus(\n client: IPerpDepositClient,\n intentId: string,\n): Promise<DepositStatusResponse> {\n return client.status(intentId);\n}\n\nexport interface UsePerpDepositStatusOptions extends Omit<\n UseQueryOptions<\n DepositStatusResponse,\n Error,\n DepositStatusResponse,\n ReturnType<typeof perpDepositStatusQueryKey>\n >,\n \"queryKey\" | \"queryFn\" | \"refetchInterval\" | \"enabled\"\n> {\n enabled?: boolean;\n /**\n * Polling interval in milliseconds while the deposit is non-terminal.\n * Defaults to 3 000 ms — matches the backend's reconciliation cadence\n * with a small safety margin.\n */\n pollIntervalMs?: number;\n}\n\n/**\n * Polls /v1/deposits/{id} until the deposit reaches a terminal status,\n * then stops the timer automatically. The component is responsible for\n * forwarding `data` into the deposit FSM via STATUS_UPDATE events.\n *\n * Engineering principle (single responsibility): this hook owns the\n * \"when to ask the server\" question; the FSM owns the \"what does the\n * answer mean\" question. They communicate through plain typed values.\n */\nexport function usePerpDepositStatus(\n intentId: string | undefined | null,\n options: UsePerpDepositStatusOptions = {},\n) {\n const client = usePerpDepositClientMaybe();\n const enabled = (options.enabled ?? Boolean(intentId)) && Boolean(client);\n // `client!` is safe here because `enabled` is false when `client` is undefined,\n // so the queryFn will never execute without a valid client.\n const pollIntervalMs = options.pollIntervalMs ?? 3_000;\n return useQuery({\n queryKey: perpDepositStatusQueryKey(intentId ?? undefined),\n queryFn: async () => fetchPerpDepositStatus(client!, intentId as string),\n enabled,\n refetchInterval: (query) => {\n const data = query.state.data;\n if (!data) return pollIntervalMs;\n return TERMINAL_DEPOSIT_STATUSES.has(data.status)\n ? false\n : pollIntervalMs;\n },\n refetchOnWindowFocus: false,\n staleTime: 0,\n ...options,\n });\n}\n","/**\n * Pure state machine for the Hyperliquid initialisation flow.\n *\n * Driven by `useReducer` — kept as a separate module so the transition\n * logic is unit-testable without React. The states cover the full\n * lifecycle:\n *\n * idle\n * → loading (caller pressed \"init\", reading current state)\n * → ready (we know which steps remain)\n * → executing (one step is in flight)\n * → done | error\n *\n * `error` is recoverable — `RETRY_STEP` returns the FSM to `executing`.\n * `RESET` always rewinds to `idle` so the caller can re-check status.\n */\nimport type {\n ApproveBuilderFeeParams,\n HyperliquidAccountState,\n SetReferrerParams,\n UpdateLeverageParams,\n} from \"../../client/hyperliquid/HyperliquidSetupAdapter\";\n\n/** Identifier for each setup step — drives the UI checklist. */\nexport type SetupStepId =\n | \"approveBuilderFee\"\n | \"setReferrer\"\n | \"updateLeverage\";\n\n/**\n * A single step in the setup checklist. `params` carry exactly the\n * information the adapter needs to perform the action — the FSM never\n * inspects them; it only routes them to the adapter.\n */\nexport type SetupStep =\n | { id: \"approveBuilderFee\"; params: ApproveBuilderFeeParams }\n | { id: \"setReferrer\"; params: SetReferrerParams }\n | { id: \"updateLeverage\"; params: UpdateLeverageParams };\n\n/** Per-step status tracked across the checklist. */\nexport type StepStatus =\n | \"pending\" // not yet attempted in this session\n | \"skipped\" // already done on-chain — no action needed\n | \"running\"\n | \"done\"\n | \"error\";\n\nexport interface StepRecord {\n step: SetupStep;\n status: StepStatus;\n /** Last error message captured for the step. */\n error?: string;\n /** Optional tx hash returned by the adapter. */\n txHash?: string;\n}\n\nexport type SetupPhase =\n | \"idle\"\n | \"loading\" // refreshing account state\n | \"ready\" // checklist computed, awaiting user action\n | \"executing\"\n | \"done\"\n | \"error\";\n\nexport interface SetupState {\n phase: SetupPhase;\n /** Snapshot of the on-chain state captured during `loading`. */\n accountState?: HyperliquidAccountState;\n /** All steps requested by the caller, in order. */\n steps: StepRecord[];\n /** Index of the step currently executing (only valid in `executing`). */\n currentIndex?: number;\n /** Top-level error — typically from `getAccountState`. */\n error?: string;\n}\n\nexport type SetupAction =\n | { type: \"START_LOADING\" }\n | {\n type: \"LOAD_SUCCESS\";\n accountState: HyperliquidAccountState;\n steps: StepRecord[];\n }\n | { type: \"LOAD_ERROR\"; error: string }\n | { type: \"RUN_STEP\"; index: number }\n | {\n type: \"STEP_SUCCESS\";\n index: number;\n txHash?: string;\n accountState?: HyperliquidAccountState;\n }\n | { type: \"STEP_ERROR\"; index: number; error: string }\n | { type: \"RESET\" };\n\nexport const initialSetupState: SetupState = {\n phase: \"idle\",\n steps: [],\n};\n\n/**\n * Determine the initial status of a step given the current on-chain\n * state. `done` (sometimes called `skipped` to the user) means the\n * action has already happened and we can elide it.\n *\n * Encapsulated as a pure function so the same logic is exercised by\n * both the loader (when `LOAD_SUCCESS` constructs the checklist) and\n * the adapter result handler (when an action reports a partial state\n * update).\n */\nexport function classifyStep(\n step: SetupStep,\n state: HyperliquidAccountState,\n): StepStatus {\n switch (step.id) {\n case \"approveBuilderFee\": {\n const current = state.builderApproval;\n if (\n current &&\n sameAddress(current.builder, step.params.builder) &&\n current.maxFeeRate >= step.params.maxFeeRate\n ) {\n return \"skipped\";\n }\n return \"pending\";\n }\n case \"setReferrer\": {\n // Referrer is a one-shot — any non-null value means done. We do\n // not try to \"fix\" a different referrer because Hyperliquid\n // rejects rebinding.\n return state.referrer ? \"skipped\" : \"pending\";\n }\n case \"updateLeverage\": {\n const current = state.leverage[step.params.asset];\n if (current === step.params.leverage) {\n return \"skipped\";\n }\n return \"pending\";\n }\n }\n}\n\nexport function reduceSetupState(\n state: SetupState,\n action: SetupAction,\n): SetupState {\n switch (action.type) {\n case \"START_LOADING\":\n return {\n phase: \"loading\",\n steps: state.steps,\n accountState: state.accountState,\n };\n case \"LOAD_SUCCESS\": {\n const allDone = action.steps.every(\n (s) => s.status === \"skipped\" || s.status === \"done\",\n );\n return {\n phase: allDone ? \"done\" : \"ready\",\n accountState: action.accountState,\n steps: action.steps,\n };\n }\n case \"LOAD_ERROR\":\n return {\n phase: \"error\",\n steps: state.steps,\n error: action.error,\n };\n case \"RUN_STEP\": {\n const next = state.steps.map((rec, i) =>\n i === action.index\n ? { ...rec, status: \"running\" as StepStatus, error: undefined }\n : rec,\n );\n return {\n phase: \"executing\",\n steps: next,\n accountState: state.accountState,\n currentIndex: action.index,\n };\n }\n case \"STEP_SUCCESS\": {\n const next = state.steps.map((rec, i) =>\n i === action.index\n ? {\n ...rec,\n status: \"done\" as StepStatus,\n txHash: action.txHash,\n error: undefined,\n }\n : rec,\n );\n const mergedAccount: HyperliquidAccountState | undefined =\n action.accountState && state.accountState\n ? mergeAccountState(state.accountState, action.accountState)\n : ((action.accountState as HyperliquidAccountState | undefined) ??\n state.accountState);\n const allDone = next.every(\n (s) => s.status === \"skipped\" || s.status === \"done\",\n );\n return {\n phase: allDone ? \"done\" : \"ready\",\n steps: next,\n accountState: mergedAccount,\n currentIndex: undefined,\n };\n }\n case \"STEP_ERROR\": {\n const next = state.steps.map((rec, i) =>\n i === action.index\n ? { ...rec, status: \"error\" as StepStatus, error: action.error }\n : rec,\n );\n return {\n phase: \"ready\",\n steps: next,\n accountState: state.accountState,\n currentIndex: undefined,\n };\n }\n case \"RESET\":\n return initialSetupState;\n }\n}\n\n/**\n * Find the next step that still needs to run. Returns `null` when the\n * checklist is complete — the caller should treat the FSM as `done`.\n */\nexport function nextRunnableStep(state: SetupState): number | null {\n for (let i = 0; i < state.steps.length; i++) {\n const status = state.steps[i].status;\n if (status === \"pending\" || status === \"error\") return i;\n }\n return null;\n}\n\nfunction sameAddress(a: string, b: string): boolean {\n return a.toLowerCase() === b.toLowerCase();\n}\n\nfunction mergeAccountState(\n base: HyperliquidAccountState,\n patch: Partial<HyperliquidAccountState>,\n): HyperliquidAccountState {\n return {\n builderApproval:\n patch.builderApproval !== undefined\n ? patch.builderApproval\n : base.builderApproval,\n referrer: patch.referrer !== undefined ? patch.referrer : base.referrer,\n leverage: { ...base.leverage, ...(patch.leverage ?? {}) },\n };\n}\n","import { useCallback, useEffect, useReducer, useRef } from \"react\";\nimport type {\n HyperliquidAccountState,\n IHyperliquidSetupAdapter,\n HyperliquidSetupActionResult,\n} from \"../../client/hyperliquid/HyperliquidSetupAdapter\";\nimport {\n classifyStep,\n initialSetupState,\n nextRunnableStep,\n reduceSetupState,\n type SetupState,\n type SetupStep,\n type StepRecord,\n} from \"./setup-state-machine\";\n\n/**\n * Configuration for the Hyperliquid setup orchestrator.\n *\n * The hook is intentionally adapter-agnostic — it does not import any\n * Hyperliquid signing code. The consumer wires in an adapter (typically\n * built around their wallet integration) plus the list of steps they\n * want to run.\n */\nexport interface UseHyperliquidSetupOptions {\n /** Adapter that knows how to read state and submit signed actions. */\n adapter: IHyperliquidSetupAdapter;\n /** EVM address of the user (required to read account state). */\n userAddress: string | undefined;\n /**\n * The steps the consumer wants the user to complete. Order is\n * preserved in the UI, and the orchestrator advances strictly in\n * sequence so failures don't strand the user mid-checklist.\n */\n steps: SetupStep[];\n /**\n * If true, the hook performs an initial state read on mount /\n * adapter change. Defaults to `true`.\n */\n autoLoad?: boolean;\n /** Optional callback invoked once every step is `done` or `skipped`. */\n onComplete?: (state: SetupState) => void;\n /** Optional callback for diagnostic logging. */\n onError?: (err: Error, context: { stepId?: SetupStep[\"id\"] }) => void;\n}\n\nexport interface UseHyperliquidSetupResult {\n state: SetupState;\n /** Re-fetch the on-chain state. Idempotent — safe to call repeatedly. */\n reload: () => Promise<void>;\n /** Run the next pending / error step. No-op when the checklist is done. */\n runNext: () => Promise<void>;\n /** Run a specific step by index — used by per-row \"Retry\" buttons. */\n runStep: (index: number) => Promise<void>;\n /** Reset the FSM to `idle` (e.g. when the user closes the wizard). */\n reset: () => void;\n}\n\n/**\n * Orchestrates the Hyperliquid first-run setup checklist.\n *\n * Responsibilities:\n * - Read the user's account state via the adapter.\n * - Classify each requested step against that state, marking ones\n * already done as `skipped`.\n * - Advance through the remaining steps, calling the appropriate\n * adapter method and merging the returned partial state back.\n * - Surface errors per-step so the UI can show a precise retry CTA.\n *\n * Out of scope:\n * - Signing — adapter does it.\n * - Persistence — Hyperliquid is the source of truth; we re-read on\n * reload instead of caching across sessions.\n */\nexport function useHyperliquidSetup(\n opts: UseHyperliquidSetupOptions,\n): UseHyperliquidSetupResult {\n const {\n adapter,\n userAddress,\n steps,\n autoLoad = true,\n onComplete,\n onError,\n } = opts;\n const [state, dispatch] = useReducer(reduceSetupState, initialSetupState);\n\n // Refs for stable closures inside async work.\n const adapterRef = useRef(adapter);\n const stepsRef = useRef(steps);\n const onCompleteRef = useRef(onComplete);\n const onErrorRef = useRef(onError);\n adapterRef.current = adapter;\n stepsRef.current = steps;\n onCompleteRef.current = onComplete;\n onErrorRef.current = onError;\n\n const reload = useCallback(async () => {\n if (!userAddress) return;\n dispatch({ type: \"START_LOADING\" });\n try {\n const accountState =\n await adapterRef.current.getAccountState(userAddress);\n const records: StepRecord[] = stepsRef.current.map((step) => ({\n step,\n status: classifyStep(step, accountState),\n }));\n dispatch({ type: \"LOAD_SUCCESS\", accountState, steps: records });\n } catch (e) {\n const err = toError(e);\n dispatch({ type: \"LOAD_ERROR\", error: err.message });\n onErrorRef.current?.(err, {});\n }\n }, [userAddress]);\n\n // Auto-load on first mount or when the user / adapter changes.\n useEffect(() => {\n if (autoLoad && userAddress) {\n void reload();\n }\n }, [autoLoad, userAddress, reload]);\n\n const runStep = useCallback(\n async (index: number) => {\n const record = state.steps[index];\n if (!record) return;\n dispatch({ type: \"RUN_STEP\", index });\n try {\n const result = await invokeAdapter(adapterRef.current, record.step);\n dispatch({\n type: \"STEP_SUCCESS\",\n index,\n txHash: result.txHash,\n accountState: result.state as HyperliquidAccountState | undefined,\n });\n } catch (e) {\n const err = toError(e);\n dispatch({ type: \"STEP_ERROR\", index, error: err.message });\n onErrorRef.current?.(err, { stepId: record.step.id });\n }\n },\n [state.steps],\n );\n\n const runNext = useCallback(async () => {\n const idx = nextRunnableStep(state);\n if (idx == null) return;\n await runStep(idx);\n }, [state, runStep]);\n\n const reset = useCallback(() => dispatch({ type: \"RESET\" }), []);\n\n // Fire `onComplete` exactly once when we transition into `done`.\n const completedRef = useRef(false);\n useEffect(() => {\n if (state.phase === \"done\" && !completedRef.current) {\n completedRef.current = true;\n onCompleteRef.current?.(state);\n } else if (state.phase !== \"done\") {\n completedRef.current = false;\n }\n }, [state]);\n\n return { state, reload, runNext, runStep, reset };\n}\n\nfunction invokeAdapter(\n adapter: IHyperliquidSetupAdapter,\n step: SetupStep,\n): Promise<HyperliquidSetupActionResult> {\n switch (step.id) {\n case \"approveBuilderFee\":\n return adapter.approveBuilderFee(step.params);\n case \"setReferrer\":\n return adapter.setReferrer(step.params);\n case \"updateLeverage\":\n return adapter.updateLeverage(step.params);\n }\n}\n\nfunction toError(e: unknown): Error {\n if (e instanceof Error) return e;\n return new Error(typeof e === \"string\" ? e : \"Unknown error\");\n}\n","export function CoinInfoNotFoundUI() {\n return (\n <div className=\"flex items-center justify-center px-4 py-3 bg-neutral-900 border-b border-neutral-800\">\n <span className=\"text-neutral-400 text-sm\">\n Market data not available\n </span>\n </div>\n );\n}\n","import type { CSSProperties } from \"react\";\n\n/**\n * Shared shimmer primitives for skeleton placeholders inside\n * `@liberfi.io/ui-perpetuals`.\n *\n * The visual language matches `@liberfi.io/ui-predict`'s skeletons\n * (events.skeleton, event-detail-skeleton): a subtle white-tint gradient\n * pulsing horizontally over a dark background, no HeroUI gray boxes.\n *\n * Why a shared util:\n * - DRY — the coin-info, orderbook and trades skeletons all need the same\n * keyframes + base style; previously each duplicated its own.\n * - Single source of truth — bumping the gradient colors or the timing\n * updates every loading state in lock-step.\n * - Single keyframe injection — `<ShimmerStyle />` mounts the\n * `@keyframes liberfi-perp-shimmer` rule once. Multiple instances are\n * harmless: the browser deduplicates same-name same-body keyframe\n * declarations across `<style>` tags.\n *\n * Long-term we may promote this to `@liberfi.io/ui` so other packages\n * (`ui-predict`, `ui-tokens`, ...) can share the same primitives.\n */\n\nconst KEYFRAME_NAME = \"liberfi-perp-shimmer\";\n\nconst SHIMMER_KEYFRAMES_CSS = `\n@keyframes ${KEYFRAME_NAME}{0%{background-position:200% 0}100%{background-position:-200% 0}}\n`;\n\n/**\n * Mount once anywhere inside a skeleton tree to inject the shimmer\n * keyframes. The returned `<style>` is tiny (~80 bytes) and React will\n * dedupe repeated mounts via reconciliation.\n */\nexport function ShimmerStyle() {\n return <style>{SHIMMER_KEYFRAMES_CSS}</style>;\n}\n\n/**\n * Base shimmer style. Spread into a `<div style={...}>` to render a\n * pulsing placeholder rectangle. Set `width` / `height` /\n * `borderRadius` via the consumer's own style override.\n *\n * Composition:\n * - `backgroundColor` provides a visible base layer (~16% white). The\n * perpetuals module's skeletons sit directly on the form's\n * near-black background with no surrounding card to lift them, so a\n * pure-gradient fill (which is what the predict cards rely on)\n * ends up nearly invisible. The base color guarantees the block is\n * readable as \"loading\" regardless of the host's background.\n * - `backgroundImage` carries the highlight sweep. We split it from\n * `backgroundColor` instead of using the `background` shorthand so\n * the color isn't cleared every render.\n *\n * Tweaking these values updates every skeleton in this module\n * (coin-info, orderbook, trades, place-order leverage badge, …) in\n * lock-step.\n */\nexport const shimmer: CSSProperties = {\n backgroundColor: \"rgba(255, 255, 255, 0.16)\",\n backgroundImage:\n \"linear-gradient(90deg, rgba(255,255,255,0) 25%, rgba(255,255,255,0.18) 50%, rgba(255,255,255,0) 75%)\",\n backgroundSize: \"200% 100%\",\n animation: `${KEYFRAME_NAME} 1.8s ease-in-out infinite`,\n borderRadius: 6,\n};\n\n/**\n * Stagger the shimmer animation across cells by giving each one its own\n * `animationDelay`. Produces a wave effect from left-to-right (or top-\n * to-bottom) instead of a simultaneous global pulse, which reads as\n * \"individual cells loading\" rather than \"the whole region is dead\".\n *\n * @param delay milliseconds to offset the animation start.\n */\nexport function shimmerDelay(delay: number): CSSProperties {\n return { ...shimmer, animationDelay: `${delay}ms` };\n}\n","import type { CSSProperties } from \"react\";\nimport { ShimmerStyle, shimmerDelay } from \"../../internal/skeleton\";\n\n/**\n * Skeleton placeholder for {@link CoinInfoUI}.\n *\n * Mirrors the live widget's flex layout so the loading shell occupies\n * exactly the same footprint (no jump on data arrival):\n * `[price + 24h%] [Oracle] [24h Volume] [Open Interest] [Funding / Countdown]`\n *\n * The container is intentionally transparent — coin-info renders inside the\n * perpetuals chart column whose host page provides the background (e.g.\n * `#000000` on the perpetuals page). A separate gray wash here would\n * clash with that.\n *\n * Shimmer styling is shared with the other perpetuals skeletons via\n * {@link ShimmerStyle} / {@link shimmerDelay}; see `../../internal/skeleton`.\n */\nexport function CoinInfoSkeletonsUI() {\n return (\n <>\n <ShimmerStyle />\n <div\n className=\"flex items-center px-4\"\n style={{ minHeight: 64, maxHeight: 64, gap: 24 }}\n >\n {/* Price + 24h change — matches `items-baseline` group in CoinInfoUI. */}\n <div className=\"flex items-baseline\" style={{ gap: 8 }}>\n <div style={cellStyle(0, 84, 23)} />\n <div style={cellStyle(60, 52, 16)} />\n </div>\n\n {/* Stat columns: Oracle Price | 24h Volume | Open Interest | Funding. */}\n <div className=\"flex items-center\" style={{ gap: 24 }}>\n <StatColumn labelWidth={72} valueWidth={64} delay={120} />\n <StatColumn labelWidth={72} valueWidth={48} delay={180} />\n <StatColumn labelWidth={84} valueWidth={56} delay={240} />\n\n {/* Funding / Countdown — wider label and a 2-value row. */}\n <div className=\"flex flex-col\" style={{ gap: 4 }}>\n <div style={cellStyle(300, 132, 16)} />\n <div className=\"flex items-center\" style={{ gap: 8 }}>\n <div style={cellStyle(330, 64, 17)} />\n <div style={cellStyle(360, 64, 17)} />\n </div>\n </div>\n </div>\n </div>\n </>\n );\n}\n\nfunction StatColumn({\n labelWidth,\n valueWidth,\n delay,\n}: {\n labelWidth: number;\n valueWidth: number;\n delay: number;\n}) {\n return (\n <div className=\"flex flex-col\" style={{ gap: 4 }}>\n <div style={cellStyle(delay, labelWidth, 16)} />\n <div style={cellStyle(delay + 30, valueWidth, 17)} />\n </div>\n );\n}\n\nfunction cellStyle(\n delay: number,\n width: number,\n height: number,\n): CSSProperties {\n return { ...shimmerDelay(delay), width, height };\n}\n","import { useEffect, useState } from \"react\";\nimport { useMarketDataSubscription } from \"../../hooks/useMarketDataSubscription\";\nimport { useMarketQuery } from \"../../hooks/useMarketQuery\";\nimport type { MarketData } from \"../../types\";\n\nexport type UseCoinInfoReturnType = {\n marketData?: MarketData;\n isLoading: boolean;\n fundingCountdown: number;\n};\n\nexport function useCoinInfo(symbol: string): UseCoinInfoReturnType {\n const [marketData, setMarketData] = useState<MarketData | undefined>();\n const [fundingCountdown, setFundingCountdown] = useState<number>(0);\n\n const { data: initialData, isPending } = useMarketQuery({ symbol });\n\n const { data: realtimeData, isConnected } =\n useMarketDataSubscription<MarketData>({\n type: \"ticker\",\n symbol,\n enabled: !!initialData,\n });\n\n useEffect(() => {\n if (!initialData) return;\n setMarketData(initialData);\n }, [initialData]);\n\n useEffect(() => {\n if (!realtimeData) return;\n\n const normalized = normalizeRealtimeTickerPayload(realtimeData, symbol);\n if (!normalized) return;\n\n setMarketData((previous) =>\n buildMarketData(previous ?? initialData ?? undefined, normalized, symbol),\n );\n }, [realtimeData, initialData, symbol]);\n\n useEffect(() => {\n // Hyperliquid funding settles **hourly** at the top of every UTC hour\n // (HH:00:00). The countdown below renders the time remaining until\n // the next settlement boundary.\n //\n // The previous implementation used an 8-hour interval, which mirrors\n // perp venues like Binance / Bybit but does not apply to Hyperliquid:\n // Axiom's reference UI shows `00:38:11` for the same market when our\n // 8-hour countdown showed `05:39:49`, off by ~8x. We intentionally\n // hard-code the cadence here because Hyperliquid is currently the\n // only backend; if/when other venues are wired in, this should\n // become a venue-specific config (e.g. `client.fundingIntervalMs`).\n const calculateCountdown = () => {\n const now = Date.now();\n const oneHour = 60 * 60 * 1000;\n const remainder = now % oneHour;\n const timeUntilNext = oneHour - remainder;\n return Math.floor(timeUntilNext / 1000);\n };\n\n setFundingCountdown(calculateCountdown());\n\n const interval = setInterval(() => {\n setFundingCountdown(calculateCountdown());\n }, 1000);\n\n return () => clearInterval(interval);\n }, []);\n\n return {\n marketData,\n isLoading: isPending,\n fundingCountdown,\n };\n}\n\nfunction normalizeRealtimeTickerPayload(\n payload: unknown,\n symbol: string,\n): Partial<MarketData> | null {\n if (Array.isArray(payload)) {\n const matched = payload.find((item) => {\n if (!item || typeof item !== \"object\") return false;\n return (item as { symbol?: string }).symbol === symbol;\n });\n return matched && typeof matched === \"object\"\n ? (matched as Partial<MarketData>)\n : null;\n }\n\n if (payload && typeof payload === \"object\") {\n return payload as Partial<MarketData>;\n }\n\n return null;\n}\n\nfunction toNumberOr(value: unknown, fallback: number): number {\n if (typeof value === \"number\" && Number.isFinite(value)) {\n return value;\n }\n return fallback;\n}\n\nfunction buildMarketData(\n base: MarketData | undefined,\n patch: Partial<MarketData>,\n symbol: string,\n): MarketData {\n return {\n symbol: patch.symbol ?? base?.symbol ?? symbol,\n price: toNumberOr(patch.price, base?.price ?? 0),\n change24h: toNumberOr(patch.change24h, base?.change24h ?? 0),\n volume24h: toNumberOr(patch.volume24h, base?.volume24h ?? 0),\n fundingRate: toNumberOr(patch.fundingRate, base?.fundingRate ?? 0),\n openInterest: toNumberOr(patch.openInterest, base?.openInterest ?? 0),\n markPrice: toNumberOr(patch.markPrice, base?.markPrice ?? 0),\n indexPrice:\n typeof patch.indexPrice === \"number\" && Number.isFinite(patch.indexPrice)\n ? patch.indexPrice\n : base?.indexPrice,\n high24h:\n typeof patch.high24h === \"number\" && Number.isFinite(patch.high24h)\n ? patch.high24h\n : base?.high24h,\n low24h:\n typeof patch.low24h === \"number\" && Number.isFinite(patch.low24h)\n ? patch.low24h\n : base?.low24h,\n };\n}\n","import { cn } from \"@liberfi.io/ui\";\nimport type { MarketData } from \"../../types\";\n\nexport type CoinInfoUIProps = {\n marketData: MarketData;\n fundingCountdown: number;\n};\n\nfunction formatCountdown(seconds: number): string {\n const hours = Math.floor(seconds / 3600);\n const minutes = Math.floor((seconds % 3600) / 60);\n const secs = seconds % 60;\n return `${String(hours).padStart(2, \"0\")}:${String(minutes).padStart(2, \"0\")}:${String(secs).padStart(2, \"0\")}`;\n}\n\nfunction formatNumber(num: number | undefined, decimals: number = 2): string {\n if (typeof num !== \"number\" || !Number.isFinite(num)) {\n return \"-\";\n }\n if (num >= 1e9) {\n return `$${(num / 1e9).toFixed(decimals)}B`;\n }\n if (num >= 1e6) {\n return `$${(num / 1e6).toFixed(decimals)}M`;\n }\n if (num >= 1e3) {\n return `$${(num / 1e3).toFixed(decimals)}K`;\n }\n return `$${num.toFixed(decimals)}`;\n}\n\nfunction formatPrice(price: number | undefined): string {\n if (typeof price !== \"number\" || !Number.isFinite(price)) {\n return \"-\";\n }\n if (price >= 1000) {\n return price.toLocaleString(\"en-US\", {\n minimumFractionDigits: 0,\n maximumFractionDigits: 0,\n });\n }\n if (price >= 1) {\n return price.toLocaleString(\"en-US\", {\n minimumFractionDigits: 2,\n maximumFractionDigits: 4,\n });\n }\n return price.toFixed(6);\n}\n\nexport function CoinInfoUI({ marketData, fundingCountdown }: CoinInfoUIProps) {\n const {\n symbol,\n price,\n change24h,\n indexPrice,\n volume24h,\n openInterest,\n fundingRate,\n } = marketData;\n\n const safeChange24h =\n typeof change24h === \"number\" && Number.isFinite(change24h) ? change24h : 0;\n const safeFundingRate =\n typeof fundingRate === \"number\" && Number.isFinite(fundingRate)\n ? fundingRate\n : 0;\n const isPositiveChange = safeChange24h >= 0;\n const changePercent = safeChange24h.toFixed(2);\n\n return (\n <div\n className=\"flex items-center px-4\"\n style={{ minHeight: 64, maxHeight: 64, gap: 24 }}\n >\n <div className=\"flex items-baseline\" style={{ gap: 8 }}>\n <span\n style={{\n fontSize: 18,\n fontWeight: 500,\n lineHeight: \"23px\",\n letterSpacing: \"-0.36px\",\n color: \"#ffffff\",\n }}\n >\n {formatPrice(price)}\n </span>\n <span\n style={{\n fontSize: 12,\n fontWeight: 400,\n lineHeight: \"16px\",\n color: isPositiveChange ? \"#C7FF2E\" : \"#F76816\",\n }}\n >\n {isPositiveChange ? \"+\" : \"\"}\n {changePercent}%\n </span>\n </div>\n\n <div className=\"flex items-center\" style={{ gap: 24 }}>\n <div className=\"flex flex-col\">\n <span\n style={{\n fontSize: 12,\n color: \"#b5b5b5\",\n lineHeight: \"16px\",\n letterSpacing: \"-0.12px\",\n }}\n >\n Oracle Price\n </span>\n <span\n style={{\n fontSize: 13,\n fontWeight: 400,\n lineHeight: \"17px\",\n color: \"#ffffff\",\n }}\n >\n {indexPrice ? formatPrice(indexPrice) : \"-\"}\n </span>\n </div>\n\n <div className=\"flex flex-col\">\n <span\n style={{\n fontSize: 12,\n color: \"#b5b5b5\",\n lineHeight: \"16px\",\n letterSpacing: \"-0.12px\",\n }}\n >\n 24h Volume\n </span>\n <span\n style={{\n fontSize: 13,\n fontWeight: 400,\n lineHeight: \"17px\",\n color: \"#ffffff\",\n }}\n >\n {formatNumber(volume24h, 0)}\n </span>\n </div>\n\n <div className=\"flex flex-col\">\n <span\n style={{\n fontSize: 12,\n color: \"#b5b5b5\",\n lineHeight: \"16px\",\n letterSpacing: \"-0.12px\",\n }}\n >\n Open Interest\n </span>\n <span\n style={{\n fontSize: 13,\n fontWeight: 400,\n lineHeight: \"17px\",\n color: \"#ffffff\",\n }}\n >\n {formatNumber(openInterest * (marketData.markPrice || price))}\n </span>\n </div>\n\n <div className=\"flex flex-col\">\n <span\n style={{\n fontSize: 12,\n color: \"#b5b5b5\",\n lineHeight: \"16px\",\n letterSpacing: \"-0.12px\",\n }}\n >\n Funding / Countdown\n </span>\n <div className=\"flex items-center\" style={{ gap: 8 }}>\n <span\n style={{\n fontSize: 13,\n lineHeight: \"17px\",\n color: safeFundingRate >= 0 ? \"#C7FF2E\" : \"#F76816\",\n }}\n >\n {(safeFundingRate * 100).toFixed(5)}%\n </span>\n <span\n style={{\n fontSize: 13,\n lineHeight: \"17px\",\n color: \"#ffffff\",\n }}\n >\n {formatCountdown(fundingCountdown)}\n </span>\n </div>\n </div>\n </div>\n </div>\n );\n}\n","import { CoinInfoNotFoundUI } from \"./coin-info-notfound.ui\";\nimport { CoinInfoSkeletonsUI } from \"./coin-info-skeletons.ui\";\nimport { useCoinInfo } from \"./coin-info.script\";\nimport { CoinInfoUI } from \"./coin-info.ui\";\n\nexport type CoinInfoWidgetProps = {\n symbol: string;\n};\n\nexport function CoinInfoWidget({ symbol }: CoinInfoWidgetProps) {\n const { marketData, isLoading, fundingCountdown } = useCoinInfo(symbol);\n\n if (isLoading) {\n return <CoinInfoSkeletonsUI />;\n }\n\n if (!marketData) {\n return <CoinInfoNotFoundUI />;\n }\n\n return (\n <CoinInfoUI marketData={marketData} fundingCountdown={fundingCountdown} />\n );\n}\n","import { useEffect, useMemo, useState } from \"react\";\nimport { useCoinsQuery } from \"../../hooks/useCoinsQuery\";\nimport { useMarketsQuery } from \"../../hooks/useMarketsQuery\";\nimport type { MarketData } from \"../../types\";\n\nexport type UseSearchCoinsScriptParams = {\n onSelectCoin?: (symbol: string) => void;\n};\n\nexport type UseSearchCoinsScriptResult = {\n coins: MarketData[];\n isLoading: boolean;\n searchQuery: string;\n setSearchQuery: (query: string) => void;\n filteredCoins: MarketData[];\n handleSelectCoin: (symbol: string) => void;\n};\n\nexport function useSearchCoinsScript({\n onSelectCoin,\n}: UseSearchCoinsScriptParams = {}): UseSearchCoinsScriptResult {\n const [searchQuery, setSearchQuery] = useState<string>(\"\");\n const [coins, setCoins] = useState<MarketData[]>([]);\n\n const { data: coinSymbols, isPending: isLoadingSymbols } = useCoinsQuery();\n\n const { data: marketsData, isPending: isLoadingMarkets } = useMarketsQuery(\n { symbols: coinSymbols },\n { enabled: !!coinSymbols && coinSymbols.length > 0 },\n );\n\n useEffect(() => {\n if (marketsData) {\n setCoins(marketsData);\n }\n }, [marketsData]);\n\n const filteredCoins = useMemo(() => {\n if (!searchQuery.trim()) {\n return coins;\n }\n\n const query = searchQuery.toLowerCase().trim();\n return coins.filter((coin) => coin.symbol.toLowerCase().includes(query));\n }, [coins, searchQuery]);\n\n const handleSelectCoin = (symbol: string) => {\n onSelectCoin?.(symbol);\n };\n\n return {\n coins,\n isLoading: isLoadingSymbols || isLoadingMarkets,\n searchQuery,\n setSearchQuery,\n filteredCoins,\n handleSelectCoin,\n };\n}\n","import { SearchIcon } from \"@liberfi.io/ui\";\nimport type { MarketData } from \"../../types\";\n\nexport type SearchCoinsUIProps = {\n coins: MarketData[];\n searchQuery: string;\n onSearchChange: (query: string) => void;\n onSelectCoin: (symbol: string) => void;\n isLoading?: boolean;\n};\n\nfunction formatNumber(num: number, decimals: number = 2): string {\n if (num >= 1e9) {\n return `$${(num / 1e9).toFixed(decimals)}B`;\n }\n if (num >= 1e6) {\n return `$${(num / 1e6).toFixed(decimals)}M`;\n }\n if (num >= 1e3) {\n return `$${(num / 1e3).toFixed(decimals)}K`;\n }\n return `$${num.toFixed(decimals)}`;\n}\n\nfunction formatPrice(price: number): string {\n if (price >= 1000) {\n return price.toFixed(2);\n }\n if (price >= 1) {\n return price.toFixed(4);\n }\n return price.toFixed(6);\n}\n\nexport function SearchCoinsUI({\n coins,\n searchQuery,\n onSearchChange,\n onSelectCoin,\n isLoading,\n}: SearchCoinsUIProps) {\n return (\n <div\n className=\"flex flex-col\"\n style={{ backgroundColor: \"#1A1A1A\", flex: \"1 1 0\", minHeight: 0 }}\n >\n <div style={{ padding: \"16px 16px 12px\" }}>\n <div\n className=\"flex items-center\"\n style={{\n height: 32,\n border: \"1px solid #2a2a2a\",\n borderRadius: 4,\n padding: \"0 6px 0 12px\",\n gap: 8,\n }}\n >\n <SearchIcon\n className=\"flex-shrink-0\"\n style={{ width: 14, height: 14, color: \"#6b6b6b\" }}\n />\n <input\n type=\"text\"\n placeholder=\"Search coins...\"\n value={searchQuery}\n onChange={(e) => onSearchChange(e.target.value)}\n className=\"flex-1 bg-transparent outline-none\"\n style={{ fontSize: 12, color: \"#ffffff\", border: \"none\" }}\n />\n </div>\n </div>\n\n <div className=\"flex-1 overflow-auto\">\n {/* Header */}\n <div\n className=\"flex items-center\"\n style={{\n height: 28,\n padding: \"0 16px\",\n borderBottom: \"1px solid rgba(42,42,42,0.5)\",\n position: \"sticky\",\n top: 0,\n backgroundColor: \"#1A1A1A\",\n zIndex: 1,\n }}\n >\n <span style={{ flex: \"0 0 140px\", fontSize: 12, color: \"#6b6b6b\" }}>\n Token\n </span>\n <span\n style={{\n flex: \"0 0 100px\",\n fontSize: 12,\n color: \"#6b6b6b\",\n textAlign: \"right\",\n }}\n >\n Last Price\n </span>\n <span\n style={{\n flex: \"0 0 120px\",\n fontSize: 12,\n color: \"#6b6b6b\",\n textAlign: \"right\",\n }}\n >\n 24h Change\n </span>\n <span\n style={{\n flex: \"0 0 100px\",\n fontSize: 12,\n color: \"#6b6b6b\",\n textAlign: \"right\",\n }}\n >\n 8h Funding\n </span>\n <span\n style={{\n flex: \"0 0 100px\",\n fontSize: 12,\n color: \"#6b6b6b\",\n textAlign: \"right\",\n }}\n >\n 24h Volume\n </span>\n <span\n style={{\n flex: \"1\",\n fontSize: 12,\n color: \"#6b6b6b\",\n textAlign: \"right\",\n }}\n >\n Open Interest\n </span>\n </div>\n\n {/* Rows */}\n {isLoading ? (\n <div\n className=\"flex items-center justify-center\"\n style={{ height: 100 }}\n >\n <span style={{ fontSize: 12, color: \"#6b6b6b\" }}>Loading...</span>\n </div>\n ) : coins.length === 0 ? (\n <div\n className=\"flex items-center justify-center\"\n style={{ height: 100 }}\n >\n <span style={{ fontSize: 12, color: \"#6b6b6b\" }}>\n {searchQuery ? \"No coins found\" : \"No coins available\"}\n </span>\n </div>\n ) : (\n coins.map((coin) => {\n const isPositiveChange = coin.change24h >= 0;\n const changePercent = coin.change24h.toFixed(2);\n const fundingPercent = (coin.fundingRate * 100).toFixed(4);\n const isPositiveFunding = coin.fundingRate >= 0;\n const tokenName = coin.symbol.split(\"-\")[0];\n\n return (\n <div\n key={coin.symbol}\n className=\"flex items-center cursor-pointer transition-colors\"\n style={{\n height: 36,\n padding: \"0 16px\",\n borderBottom: \"1px solid rgba(42,42,42,0.5)\",\n }}\n onClick={() => onSelectCoin(coin.symbol)}\n onMouseEnter={(e) => {\n (e.currentTarget as HTMLDivElement).style.backgroundColor =\n \"rgba(255,255,255,0.03)\";\n }}\n onMouseLeave={(e) => {\n (e.currentTarget as HTMLDivElement).style.backgroundColor =\n \"transparent\";\n }}\n >\n <div\n className=\"flex items-center\"\n style={{ flex: \"0 0 140px\", gap: 8 }}\n >\n <img\n src={`https://app.hyperliquid.xyz/coins/${tokenName}.svg`}\n alt={tokenName}\n className=\"rounded-full\"\n style={{ width: 20, height: 20 }}\n onError={(e) => {\n const target = e.target as HTMLImageElement;\n target.style.display = \"none\";\n }}\n />\n <span\n style={{ fontSize: 12, fontWeight: 500, color: \"#ffffff\" }}\n >\n {tokenName}\n </span>\n </div>\n <span\n style={{\n flex: \"0 0 100px\",\n fontSize: 12,\n color: \"#ffffff\",\n textAlign: \"right\",\n }}\n >\n {formatPrice(coin.price)}\n </span>\n <span\n style={{\n flex: \"0 0 120px\",\n fontSize: 12,\n fontWeight: 500,\n color: isPositiveChange ? \"#C7FF2E\" : \"#F76816\",\n textAlign: \"right\",\n }}\n >\n {isPositiveChange ? \"+\" : \"\"}\n {changePercent}%\n </span>\n <span\n style={{\n flex: \"0 0 100px\",\n fontSize: 12,\n color: isPositiveFunding ? \"#C7FF2E\" : \"#F76816\",\n textAlign: \"right\",\n }}\n >\n {fundingPercent}%\n </span>\n <span\n style={{\n flex: \"0 0 100px\",\n fontSize: 12,\n color: \"#b5b5b5\",\n textAlign: \"right\",\n }}\n >\n {formatNumber(coin.volume24h)}\n </span>\n <span\n style={{\n flex: \"1\",\n fontSize: 12,\n color: \"#b5b5b5\",\n textAlign: \"right\",\n }}\n >\n {formatNumber(coin.openInterest * coin.price)}\n </span>\n </div>\n );\n })\n )}\n </div>\n </div>\n );\n}\n","import { useSearchCoinsScript } from \"./search-coins.script\";\nimport { SearchCoinsUI } from \"./search-coins.ui\";\n\nexport type SearchCoinsWidgetProps = {\n onSelectCoin?: (symbol: string) => void;\n className?: string;\n};\n\nexport function SearchCoinsWidget({\n onSelectCoin,\n className,\n}: SearchCoinsWidgetProps) {\n const {\n filteredCoins,\n isLoading,\n searchQuery,\n setSearchQuery,\n handleSelectCoin,\n } = useSearchCoinsScript({ onSelectCoin });\n\n return (\n <div\n className={className}\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n flex: \"1 1 0\",\n minHeight: 0,\n overflow: \"hidden\",\n }}\n >\n <SearchCoinsUI\n coins={filteredCoins}\n searchQuery={searchQuery}\n onSearchChange={setSearchQuery}\n onSelectCoin={handleSelectCoin}\n isLoading={isLoading}\n />\n </div>\n );\n}\n","import { useEffect, useMemo, useState } from \"react\";\nimport { useMarketDataSubscription } from \"../../hooks/useMarketDataSubscription\";\nimport { useOrderBookQuery } from \"../../hooks/useOrderBookQuery\";\nimport type {\n OrderBook,\n OrderBookAggregationOptions,\n OrderBookLevel,\n} from \"../../types\";\n\nexport type PriceLevel = OrderBookLevel & {\n total: number;\n percentage: number;\n};\n\nexport type UseOrderBookScriptParams = {\n symbol: string;\n maxLevel?: number;\n /**\n * Initial price-bucket size. Defaults to `1` which matches major perpetual\n * pairs like BTC-USDC. Callers can change it dynamically via the returned\n * `setPrecision`.\n */\n precision?: number;\n};\n\n/**\n * Map a desired bucket step (in quote currency, e.g. USD) to the closest\n * Hyperliquid `l2Book` aggregation params at the given reference price.\n *\n * Hyperliquid only emits 20 levels per side per snapshot. To make those 20\n * levels span a wide enough range (e.g. ±$20k for a $1000 step), we ask the\n * server to pre-aggregate via `nSigFigs` / `mantissa`. This function picks the\n * coarsest server step that is still ≤ the user's chosen step, so any\n * remaining mismatch is corrected by client-side `aggregateByPrecision`\n * (which is idempotent when the steps already match).\n *\n * Examples (BTC, price ≈ $80,740):\n * step $1 → { nSigFigs: 5 } (Hyperliquid step $1)\n * step $2 → { nSigFigs: 5, mantissa: 2 } (Hyperliquid step $2)\n * step $5 → { nSigFigs: 5, mantissa: 5 } (Hyperliquid step $5)\n * step $10 → { nSigFigs: 4 } (Hyperliquid step $10)\n * step $100 → { nSigFigs: 3 } (Hyperliquid step $100)\n * step $1000 → { nSigFigs: 2 } (Hyperliquid step $1000)\n *\n * Examples (ETH, price ≈ $4,000):\n * step $1 → { nSigFigs: 4 } (Hyperliquid step $1)\n * step $2 → { nSigFigs: 4 } + client agg (server $1, client → $2)\n * step $10 → { nSigFigs: 3 } (Hyperliquid step $10)\n *\n * @param price Reference price (mid / mark) used to compute the magnitude.\n * @param step Desired bucket size in the same quote currency as `price`.\n * @returns Aggregation hint, or empty object when inputs are invalid.\n */\nexport function aggregationFromStep(\n price: number,\n step: number,\n): OrderBookAggregationOptions {\n if (\n !Number.isFinite(price) ||\n !Number.isFinite(step) ||\n price <= 0 ||\n step <= 0\n ) {\n return {};\n }\n\n // 10^k is the place value of `price`'s most-significant digit.\n // E.g. price=80740 → log10≈4.907 → k=4 (price sits in the 10^4 = \"tens of\n // thousands\" decade).\n const k = Math.floor(Math.log10(price));\n\n // Step produced by Hyperliquid for nSigFigs=n at this price magnitude:\n // server step = mantissa * 10^(k - n + 1) (mantissa defaults to 1)\n // We enumerate the supported (n, mantissa) tuples and pick the one whose\n // server step is the largest value ≤ user step.\n const candidates: Array<{\n nSigFigs: 2 | 3 | 4 | 5;\n mantissa?: 1 | 2 | 5;\n step: number;\n }> = [\n { nSigFigs: 2, step: Math.pow(10, k - 1) },\n { nSigFigs: 3, step: Math.pow(10, k - 2) },\n { nSigFigs: 4, step: Math.pow(10, k - 3) },\n { nSigFigs: 5, mantissa: 5, step: 5 * Math.pow(10, k - 4) },\n { nSigFigs: 5, mantissa: 2, step: 2 * Math.pow(10, k - 4) },\n { nSigFigs: 5, step: Math.pow(10, k - 4) },\n ];\n\n // Tolerance to absorb floating-point error from log10 / pow.\n const eps = 1e-9;\n\n let best: (typeof candidates)[number] | null = null;\n for (const c of candidates) {\n if (c.step <= step + eps && (!best || c.step > best.step)) {\n best = c;\n }\n }\n\n // If even nSigFigs=5 (the finest server bucket) is still coarser than the\n // user's requested step, fall back to it — we cannot ask Hyperliquid for a\n // finer grid, but the client will still aggregate further if needed.\n if (!best) {\n return { nSigFigs: 5 };\n }\n\n if (best.mantissa && best.mantissa !== 1) {\n return { nSigFigs: best.nSigFigs, mantissa: best.mantissa };\n }\n return { nSigFigs: best.nSigFigs };\n}\n\nexport type UseOrderBookScriptResult = {\n bids: PriceLevel[];\n asks: PriceLevel[];\n /** Raw `bestAsk - bestBid` after aggregation. */\n spread: number;\n /** `spread / bestBid * 100`. */\n spreadPercentage: number;\n isLoading: boolean;\n precision: number;\n setPrecision: (precision: number) => void;\n};\n\n/**\n * Aggregate raw order-book levels into discrete price buckets of size\n * `precision`.\n *\n * To keep the spread visually consistent with the chosen aggregation step we\n * round in opposite directions for the two sides:\n *\n * - ask (sell) levels round UP (`ceil`) → bucket >= raw price\n * - bid (buy) levels round DOWN (`floor`) → bucket <= raw price\n *\n * This is the standard convention used by Hyperliquid / dYdX / Axiom and\n * guarantees `bestAsk - bestBid >= step`, i.e. the visible spread never\n * collapses into a single bucket where the two sides would overlap.\n */\nfunction aggregateByPrecision(\n levels: OrderBookLevel[],\n precision: number,\n side: \"ask\" | \"bid\",\n): OrderBookLevel[] {\n if (precision <= 0) return levels;\n\n const aggregated = new Map<number, OrderBookLevel>();\n const round = side === \"ask\" ? Math.ceil : Math.floor;\n\n levels.forEach((level) => {\n const roundedPrice = round(level.price / precision) * precision;\n\n const existing = aggregated.get(roundedPrice);\n if (existing) {\n existing.quantity += level.quantity;\n if (level.count) {\n existing.count = (existing.count || 0) + level.count;\n }\n } else {\n aggregated.set(roundedPrice, {\n price: roundedPrice,\n quantity: level.quantity,\n count: level.count,\n });\n }\n });\n\n return Array.from(aggregated.values());\n}\n\nfunction calculateTotalsAndPercentages(levels: OrderBookLevel[]): PriceLevel[] {\n let total = 0;\n const withTotals = levels.map((level) => {\n const usdAmount = level.quantity * level.price;\n total += usdAmount;\n return {\n ...level,\n quantity: usdAmount,\n total,\n percentage: 0,\n };\n });\n\n const maxTotal = total;\n return withTotals.map((level) => ({\n ...level,\n percentage: maxTotal > 0 ? (level.total / maxTotal) * 100 : 0,\n }));\n}\n\nexport function useOrderBookScript({\n symbol,\n maxLevel = 20,\n precision: initialPrecision = 1,\n}: UseOrderBookScriptParams): UseOrderBookScriptResult {\n const [orderBook, setOrderBook] = useState<OrderBook | null>(null);\n const [precision, setPrecision] = useState<number>(initialPrecision);\n\n // Keep precision in sync if the caller changes the controlled prop.\n useEffect(() => {\n setPrecision(initialPrecision);\n }, [initialPrecision]);\n\n // First REST call seeds the book without venue aggregation. Its only role\n // here is to give us a reference price so we can compute the right\n // (nSigFigs, mantissa) for the live subscription.\n const { data: initialData, isPending } = useOrderBookQuery({\n symbol,\n maxLevel,\n });\n\n // Reference price ≈ mid of best bid / best ask. Falls back to whichever\n // side is available. Locked to the price *magnitude* (decade) so it stays\n // stable across price ticks — re-subscribing on every $1 move would be\n // catastrophic.\n const priceMagnitude = useMemo(() => {\n const bestBid = orderBook?.bids[0]?.price ?? initialData?.bids[0]?.price;\n const bestAsk = orderBook?.asks[0]?.price ?? initialData?.asks[0]?.price;\n const ref =\n bestBid && bestAsk ? (bestBid + bestAsk) / 2 : (bestAsk ?? bestBid ?? 0);\n return ref > 0 ? Math.floor(Math.log10(ref)) : null;\n }, [orderBook, initialData]);\n\n // Aggregation hint sent to the WS subscription. Only depends on the chosen\n // step + price magnitude, so it's stable and re-subscribes only on real\n // changes.\n const aggregation = useMemo<OrderBookAggregationOptions | undefined>(() => {\n if (priceMagnitude === null) return undefined;\n const referencePrice = Math.pow(10, priceMagnitude);\n return aggregationFromStep(referencePrice, precision);\n }, [precision, priceMagnitude]);\n\n // Throttle pushes to ~10 Hz. Hyperliquid emits l2Book updates faster than\n // that on active markets, but the human eye can't tell the difference and\n // React reconciliation of 40 rows per push at 30 Hz wastes CPU. The\n // trailing-edge throttle in {@link useMarketDataSubscription} keeps the\n // latest snapshot, so users still see the freshest data on each tick —\n // just less often.\n const { data: realtimeData } = useMarketDataSubscription<OrderBook>({\n type: \"orderBook\",\n symbol,\n enabled: !!initialData,\n aggregation,\n throttleMs: 100,\n });\n\n useEffect(() => {\n if (realtimeData) {\n setOrderBook(realtimeData);\n } else if (initialData) {\n setOrderBook(initialData);\n }\n }, [realtimeData, initialData]);\n\n const processedData = useMemo(() => {\n if (!orderBook) {\n return {\n bids: [],\n asks: [],\n spread: 0,\n spreadPercentage: 0,\n };\n }\n\n const aggregatedBids = aggregateByPrecision(\n orderBook.bids,\n precision,\n \"bid\",\n );\n const aggregatedAsks = aggregateByPrecision(\n orderBook.asks,\n precision,\n \"ask\",\n );\n\n const sortedBids = aggregatedBids\n .sort((a, b) => b.price - a.price)\n .slice(0, maxLevel);\n\n const sortedAsks = aggregatedAsks\n .sort((a, b) => a.price - b.price)\n .slice(0, maxLevel);\n\n const bids = calculateTotalsAndPercentages(sortedBids);\n const asks = calculateTotalsAndPercentages(sortedAsks);\n\n const bestBid = bids[0]?.price || 0;\n const bestAsk = asks[0]?.price || 0;\n const spread = bestAsk - bestBid;\n const spreadPercentage = bestBid > 0 ? (spread / bestBid) * 100 : 0;\n\n return {\n bids,\n asks,\n spread,\n spreadPercentage,\n };\n }, [orderBook, precision, maxLevel]);\n\n return {\n ...processedData,\n isLoading: isPending,\n precision,\n setPrecision,\n };\n}\n","import type { CSSProperties } from \"react\";\nimport { memo, useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport type { PriceLevel } from \"./orderbook.script\";\n\n// ---------------------------------------------------------------------------\n// Static styles hoisted to module scope so they are NOT reallocated on every\n// render. The order book re-renders at the WebSocket push rate (~10–30 Hz),\n// so allocating fresh style objects per render is wasted GC pressure and\n// breaks shallow-equality optimisations like React.memo.\n// ---------------------------------------------------------------------------\n\n/**\n * Thin, subtle scrollbar for the asks/bids panes. Firefox uses the\n * standard properties; Chromium/Safari fall back to their default scrollbar\n * which is already unobtrusive on a dark background. We avoid `::-webkit-`\n * pseudo selectors here so the file stays a pure inline-style component\n * (no global CSS leakage into consumer apps).\n */\nconst ORDERBOOK_SCROLL_STYLE: CSSProperties = {\n scrollbarWidth: \"thin\",\n scrollbarColor: \"rgba(63,63,70,0.6) transparent\",\n};\n\nconst CONTAINER_STYLE: CSSProperties = {\n backgroundColor: \"#000000\",\n fontSize: 11,\n};\n\nconst HEADER_STYLE: CSSProperties = {\n height: 28,\n minHeight: 28,\n padding: \"0 16px\",\n gap: 16,\n color: \"#6b6b6b\",\n fontSize: 11,\n};\n\nconst HEADER_CELL_STYLE: CSSProperties = { flex: \"1 1 0%\" };\n\nconst ROW_STYLE: CSSProperties = {\n height: 22,\n minHeight: 22,\n maxHeight: 22,\n padding: \"0 16px\",\n gap: 16,\n fontSize: 11,\n};\n\n// Per-side row decoration (background gradient + price color) is constant.\n// Pre-compute both branches so the render path just picks one by reference.\nconst ASK_BAR_STYLE_BASE: CSSProperties = {\n height: 20,\n background: \"linear-gradient(to right, rgba(247,104,22,0), #F76816)\",\n opacity: 0.15,\n};\nconst BID_BAR_STYLE_BASE: CSSProperties = {\n height: 20,\n background: \"linear-gradient(to right, rgba(199,255,46,0), #C7FF2E)\",\n opacity: 0.15,\n};\nconst ASK_PRICE_STYLE: CSSProperties = { color: \"#F76816\", fontWeight: 400 };\nconst BID_PRICE_STYLE: CSSProperties = { color: \"#C7FF2E\", fontWeight: 400 };\nconst ROW_CELL_STYLE: CSSProperties = { flex: \"1 1 0%\", color: \"#ffffff\" };\nconst ROW_PRICE_CELL_STYLE: CSSProperties = { flex: \"1 1 0%\" };\n\nconst SPREAD_BAR_STYLE: CSSProperties = {\n height: 24,\n minHeight: 24,\n padding: \"0 16px\",\n backgroundColor: \"rgba(26,26,26,0.5)\",\n};\nconst SPREAD_BAR_INNER_STYLE: CSSProperties = {\n gap: 12,\n fontSize: 12,\n color: \"#ffffff\",\n};\nconst SPREAD_LABEL_STYLE: CSSProperties = { color: \"#ffffff\" };\nconst SPREAD_VALUE_STYLE: CSSProperties = {\n color: \"#ffffff\",\n fontWeight: 500,\n};\nconst SPREAD_BUTTON_STYLE: CSSProperties = {\n color: \"#ffffff\",\n fontWeight: 400,\n background: \"none\",\n border: \"none\",\n padding: 0,\n gap: 4,\n};\nconst SPREAD_DROPDOWN_STYLE: CSSProperties = {\n top: \"calc(100% + 4px)\",\n minWidth: 64,\n backgroundColor: \"#0a0a0a\",\n border: \"1px solid rgba(63,63,70,0.6)\",\n borderRadius: 6,\n padding: 4,\n boxShadow: \"0 4px 16px rgba(0,0,0,0.5)\",\n};\n\nconst SPREAD_OPTION_STYLE: CSSProperties = {\n padding: \"4px 10px\",\n fontSize: 12,\n color: \"#ffffff\",\n background: \"transparent\",\n border: \"none\",\n borderRadius: 4,\n textAlign: \"left\",\n};\nconst SPREAD_OPTION_SELECTED_STYLE: CSSProperties = {\n ...SPREAD_OPTION_STYLE,\n color: \"#C7FF2E\",\n};\n\nexport type OrderBookUIProps = {\n bids: PriceLevel[];\n asks: PriceLevel[];\n /** `(bestAsk - bestBid) / bestBid * 100`, rendered next to the precision dropdown. */\n spreadPercentage: number;\n /** Currently selected aggregation step. */\n precision: number;\n /** Available steps shown in the dropdown. */\n precisionOptions: readonly number[];\n /** Notify parent when the user picks a new step. */\n onPrecisionChange: (precision: number) => void;\n onPriceClick?: (price: number) => void;\n};\n\nfunction formatPrice(price: number): string {\n if (price >= 1000) {\n return price.toLocaleString(\"en-US\", {\n minimumFractionDigits: 0,\n maximumFractionDigits: 0,\n });\n }\n if (price >= 1) {\n return price.toLocaleString(\"en-US\", {\n minimumFractionDigits: 2,\n maximumFractionDigits: 4,\n });\n }\n return price.toFixed(6);\n}\n\nfunction formatQuantity(qty: number): string {\n return Math.round(qty).toLocaleString(\"en-US\");\n}\n\n/** Format the precision step shown in the dropdown trigger and items. */\nfunction formatPrecision(value: number): string {\n if (value >= 1) {\n return value.toLocaleString(\"en-US\", {\n minimumFractionDigits: 0,\n maximumFractionDigits: 0,\n });\n }\n return value.toString();\n}\n\ntype OBRowProps = {\n price: number;\n quantity: number;\n total: number;\n percentage: number;\n side: \"ask\" | \"bid\";\n /**\n * Forwarded from `OrderBookUI`. Passing the raw callback (instead of a\n * `() => onPriceClick(price)` wrapper from the parent) lets the parent's\n * function reference stay stable across renders, which in turn lets\n * {@link React.memo} on this component skip re-renders for rows whose\n * price/quantity/total/percentage have not changed.\n */\n onPriceClick?: (price: number) => void;\n};\n\nconst OBRow = memo(\n function OBRow({\n price,\n quantity,\n total,\n percentage,\n side,\n onPriceClick,\n }: OBRowProps) {\n const isAsk = side === \"ask\";\n\n // Per-render allocation is unavoidable here because `width` depends on\n // the row's percentage. Keeping every other style static (see\n // ASK_BAR_STYLE_BASE / BID_BAR_STYLE_BASE) limits the cost to one tiny\n // object per visible row per push.\n const barStyle: CSSProperties = useMemo(\n () =>\n isAsk\n ? { ...ASK_BAR_STYLE_BASE, width: `${percentage}%` }\n : { ...BID_BAR_STYLE_BASE, width: `${percentage}%` },\n [isAsk, percentage],\n );\n\n const handleClick = useMemo(\n () => (onPriceClick ? () => onPriceClick(price) : undefined),\n [onPriceClick, price],\n );\n\n return (\n <div\n className=\"relative flex items-center cursor-pointer hover:bg-white/5 transition-colors\"\n style={ROW_STYLE}\n onClick={handleClick}\n >\n <div className=\"absolute left-0 top-0\" style={barStyle} />\n <div\n className=\"relative z-10 flex items-center\"\n style={ROW_PRICE_CELL_STYLE}\n >\n <span style={isAsk ? ASK_PRICE_STYLE : BID_PRICE_STYLE}>\n {formatPrice(price)}\n </span>\n </div>\n <div\n className=\"relative z-10 flex items-center justify-end\"\n style={ROW_CELL_STYLE}\n >\n {formatQuantity(quantity)}\n </div>\n <div\n className=\"relative z-10 flex items-center justify-end\"\n style={ROW_CELL_STYLE}\n >\n {formatQuantity(total)}\n </div>\n </div>\n );\n },\n // Custom equality: ignore object identity, compare the data fields React\n // actually renders. `onPriceClick` is treated as stable by reference (the\n // parent should `useCallback`/pass a stable handler).\n (prev, next) =>\n prev.price === next.price &&\n prev.quantity === next.quantity &&\n prev.total === next.total &&\n prev.percentage === next.percentage &&\n prev.side === next.side &&\n prev.onPriceClick === next.onPriceClick,\n);\n\n/**\n * Spread bar with precision step dropdown. Mirrors Axiom's design:\n *\n * Spread: [ 1 ▾ ] 0.001%\n *\n * Clicking the dropdown opens a vertical list of available steps. The actual\n * spread value is implicit (best ask - best bid is one step after\n * aggregation) so we only show the percentage on the right.\n */\nfunction SpreadBar({\n spreadPercentage,\n precision,\n precisionOptions,\n onPrecisionChange,\n}: {\n spreadPercentage: number;\n precision: number;\n precisionOptions: readonly number[];\n onPrecisionChange: (precision: number) => void;\n}) {\n const [open, setOpen] = useState(false);\n const wrapperRef = useRef<HTMLDivElement | null>(null);\n\n // Close on outside click.\n useEffect(() => {\n if (!open) return;\n const handler = (e: MouseEvent) => {\n if (!wrapperRef.current?.contains(e.target as Node)) {\n setOpen(false);\n }\n };\n document.addEventListener(\"mousedown\", handler);\n return () => document.removeEventListener(\"mousedown\", handler);\n }, [open]);\n\n // Chevron rotates on open. The transform is dynamic, the rest is static.\n const chevronStyle: CSSProperties = useMemo(\n () => ({\n color: \"#6b6b6b\",\n transform: open ? \"rotate(180deg)\" : \"rotate(0deg)\",\n transition: \"transform 0.15s\",\n }),\n [open],\n );\n\n return (\n <div className=\"flex items-center justify-center\" style={SPREAD_BAR_STYLE}>\n <div className=\"flex items-center\" style={SPREAD_BAR_INNER_STYLE}>\n <span style={SPREAD_LABEL_STYLE}>Spread:</span>\n <div ref={wrapperRef} className=\"relative\">\n <button\n type=\"button\"\n className=\"flex items-center cursor-pointer hover:text-white/80 transition-colors\"\n style={SPREAD_BUTTON_STYLE}\n onClick={() => setOpen((v) => !v)}\n aria-haspopup=\"listbox\"\n aria-expanded={open}\n >\n <span>{formatPrecision(precision)}</span>\n {/* Neutral grey chevron — kept independent of the precision\n value's text color so the affordance reads as \"decoration\",\n not as part of the active value. */}\n <svg\n width=\"8\"\n height=\"8\"\n viewBox=\"0 0 8 8\"\n fill=\"none\"\n style={chevronStyle}\n >\n <path\n d=\"M1 2.5L4 5.5L7 2.5\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n </button>\n {open && (\n <div\n role=\"listbox\"\n className=\"absolute left-1/2 -translate-x-1/2 z-20 flex flex-col\"\n style={SPREAD_DROPDOWN_STYLE}\n >\n {precisionOptions.map((opt) => {\n const selected = opt === precision;\n return (\n <button\n key={opt}\n type=\"button\"\n role=\"option\"\n aria-selected={selected}\n className=\"cursor-pointer transition-colors\"\n style={\n selected\n ? SPREAD_OPTION_SELECTED_STYLE\n : SPREAD_OPTION_STYLE\n }\n onMouseEnter={(e) => {\n e.currentTarget.style.backgroundColor =\n \"rgba(255,255,255,0.06)\";\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.backgroundColor = \"transparent\";\n }}\n onClick={() => {\n onPrecisionChange(opt);\n setOpen(false);\n }}\n >\n {formatPrecision(opt)}\n </button>\n );\n })}\n </div>\n )}\n </div>\n <span style={SPREAD_VALUE_STYLE}>{spreadPercentage.toFixed(3)}%</span>\n </div>\n </div>\n );\n}\n\n/**\n * Order book layout (top to bottom):\n *\n * ┌─ Header (Price / Amount / Total) ────┐ fixed height\n * ├─ Asks scroll region ─────────────────┤ flex-1, independent scroll\n * │ highest ask │\n * │ ... │\n * │ best ask ◄── default visible │\n * ├─ Spread bar with precision dropdown ─┤ fixed height\n * ├─ Bids scroll region ─────────────────┤ flex-1, independent scroll\n * │ best bid ◄── default visible │\n * │ ... │\n * │ lowest bid │\n * └──────────────────────────────────────┘\n *\n * Both scroll regions consume any leftover container height equally; if the\n * widget is short, each side scrolls on its own without dragging the other.\n *\n * Asks come in sorted ascending (best ask = lowest price = `asks[0]`). To\n * pin the best ask flush against the spread bar we render asks reversed\n * (highest first → best last in DOM order) inside a normal column scroll\n * container, then default-scroll to the bottom on mount. We re-stick the\n * scroll position to the bottom whenever the user is already near it, so\n * websocket updates don't bounce the view off the best ask.\n *\n * Bids are sorted descending (`bids[0]` = best) and rendered top-down,\n * so the best bid sits at `scrollTop = 0` flush against the spread bar\n * by default.\n */\nexport function OrderBookUI({\n bids,\n asks,\n spreadPercentage,\n precision,\n precisionOptions,\n onPrecisionChange,\n onPriceClick,\n}: OrderBookUIProps) {\n const asksScrollRef = useRef<HTMLDivElement | null>(null);\n const bidsScrollRef = useRef<HTMLDivElement | null>(null);\n // Track whether the user has scrolled away from the spread-bar edge of\n // each side. While they are still \"stuck\" near the spread, we keep that\n // edge in view across data updates; once they scroll away, we leave the\n // scroll position alone so they can browse deeper levels in peace.\n const asksStuckRef = useRef(true);\n const bidsStuckRef = useRef(true);\n\n // Render-order helper: highest ask first, best ask last (closest to\n // spread bar). Memoised so the array reference is stable when `asks` is\n // — otherwise the asks `useEffect` below would fire on every render,\n // not just on actual data updates.\n const renderedAsks = useMemo(() => [...asks].reverse(), [asks]);\n\n // Whenever asks update and the user is still pinned near the spread bar,\n // re-anchor the scroll position to the bottom (where the best ask lives).\n // Skip the assignment when scrollTop is already at the target to avoid\n // gratuitous layout work on every WebSocket push.\n useEffect(() => {\n const el = asksScrollRef.current;\n if (!el || !asksStuckRef.current) return;\n const target = el.scrollHeight;\n if (el.scrollTop !== target) {\n el.scrollTop = target;\n }\n }, [renderedAsks]);\n\n // Same idea for bids: keep the best bid (top) glued to the spread bar\n // until the user scrolls away.\n useEffect(() => {\n const el = bidsScrollRef.current;\n if (!el || !bidsStuckRef.current) return;\n if (el.scrollTop !== 0) {\n el.scrollTop = 0;\n }\n }, [bids]);\n\n const handleAsksScroll = useCallback(() => {\n const el = asksScrollRef.current;\n if (!el) return;\n // For asks the spread-bar edge is the *bottom* of the scroll region.\n // Allow a small tolerance (one row) so flicker from updates doesn't\n // un-stick the view.\n const distanceFromBottom = el.scrollHeight - el.scrollTop - el.clientHeight;\n asksStuckRef.current = distanceFromBottom <= 24;\n }, []);\n\n const handleBidsScroll = useCallback(() => {\n const el = bidsScrollRef.current;\n if (!el) return;\n // For bids the spread-bar edge is the *top* of the scroll region.\n bidsStuckRef.current = el.scrollTop <= 24;\n }, []);\n\n return (\n <div className=\"flex flex-col h-full min-h-0\" style={CONTAINER_STYLE}>\n {/* Header */}\n <div className=\"flex items-center flex-none\" style={HEADER_STYLE}>\n <div className=\"flex items-center\" style={HEADER_CELL_STYLE}>\n Price\n </div>\n <div\n className=\"flex items-center justify-end\"\n style={HEADER_CELL_STYLE}\n >\n Amount (USD)\n </div>\n <div\n className=\"flex items-center justify-end\"\n style={HEADER_CELL_STYLE}\n >\n Total (USD)\n </div>\n </div>\n\n {/* Asks — independent scroll. Reversed so best ask lives at the\n DOM bottom; we default-scroll to the bottom to surface it. */}\n <div\n ref={asksScrollRef}\n onScroll={handleAsksScroll}\n className=\"flex-1 min-h-0 overflow-y-auto\"\n style={ORDERBOOK_SCROLL_STYLE}\n >\n {renderedAsks.map((ask, index) => (\n <OBRow\n key={`ask-${ask.price}-${index}`}\n price={ask.price}\n quantity={ask.quantity}\n total={ask.total}\n percentage={ask.percentage}\n side=\"ask\"\n onPriceClick={onPriceClick}\n />\n ))}\n </div>\n\n {/* Spread bar */}\n <div className=\"flex-none\">\n <SpreadBar\n spreadPercentage={spreadPercentage}\n precision={precision}\n precisionOptions={precisionOptions}\n onPrecisionChange={onPrecisionChange}\n />\n </div>\n\n {/* Bids — independent scroll. Best bid is at the top so it sits\n flush against the spread bar at scrollTop=0. */}\n <div\n ref={bidsScrollRef}\n onScroll={handleBidsScroll}\n className=\"flex-1 min-h-0 overflow-y-auto\"\n style={ORDERBOOK_SCROLL_STYLE}\n >\n {bids.map((bid, index) => (\n <OBRow\n key={`bid-${bid.price}-${index}`}\n price={bid.price}\n quantity={bid.quantity}\n total={bid.total}\n percentage={bid.percentage}\n side=\"bid\"\n onPriceClick={onPriceClick}\n />\n ))}\n </div>\n </div>\n );\n}\n","import type { CSSProperties } from \"react\";\nimport { ShimmerStyle, shimmerDelay } from \"../../internal/skeleton\";\nimport { useOrderBookScript } from \"./orderbook.script\";\nimport { OrderBookUI } from \"./orderbook.ui\";\n\n/**\n * Default tick-aggregation steps offered to the user via the spread dropdown.\n *\n * Mirrors Axiom / Hyperliquid's perpetuals UI for major USD-quoted pairs\n * (BTC, ETH, SOL): users can collapse the book into 1, 2, 5, 10, 100, or\n * 1000-USD buckets to see liquidity at coarser granularities.\n */\nexport const DEFAULT_ORDER_BOOK_PRECISION_OPTIONS = [\n 1, 2, 5, 10, 100, 1000,\n] as const;\n\nexport type OrderBookWidgetProps = {\n symbol: string;\n /**\n * How many price levels to fetch + render per side. Defaults to `40` so\n * that asks and bids always have enough rows to overflow their containers\n * and show their independent scroll bars.\n */\n maxLevel?: number;\n /**\n * Steps shown in the \"Spread\" dropdown. Defaults to\n * `[1, 2, 5, 10, 100, 1000]` (Axiom's BTC perpetuals options).\n */\n precisionOptions?: readonly number[];\n /**\n * Initial selected step. Defaults to the first entry in `precisionOptions`.\n */\n defaultPrecision?: number;\n onPriceClick?: (price: number) => void;\n className?: string;\n};\n\n// ---------------------------------------------------------------------------\n// Skeleton — must match OrderBookUI's footprint (header + asks + spread bar\n// + bids) so the layout doesn't jump when data arrives. Header text renders\n// the real labels; the rows pulse with the shared shimmer language used by\n// coin-info, trades and the prediction module's skeletons.\n// ---------------------------------------------------------------------------\n\nconst SKEL_CONTAINER_STYLE: CSSProperties = {\n backgroundColor: \"#000000\",\n fontSize: 11,\n};\n\nconst SKEL_HEADER_STYLE: CSSProperties = {\n height: 28,\n minHeight: 28,\n padding: \"0 16px\",\n gap: 16,\n color: \"#6b6b6b\",\n fontSize: 11,\n};\n\nconst SKEL_HEADER_CELL_STYLE: CSSProperties = { flex: \"1 1 0%\" };\n\nconst SKEL_ROW_STYLE: CSSProperties = {\n height: 22,\n minHeight: 22,\n maxHeight: 22,\n padding: \"0 16px\",\n gap: 16,\n};\n\nconst SKEL_SPREAD_BAR_STYLE: CSSProperties = {\n height: 24,\n minHeight: 24,\n padding: \"0 16px\",\n backgroundColor: \"rgba(26,26,26,0.5)\",\n};\n\nfunction SkelRow({ delay }: { delay: number }) {\n return (\n <div className=\"flex items-center\" style={SKEL_ROW_STYLE}>\n <div style={SKEL_HEADER_CELL_STYLE}>\n <div style={{ ...shimmerDelay(delay), height: 11, width: 56 }} />\n </div>\n <div className=\"flex justify-end\" style={SKEL_HEADER_CELL_STYLE}>\n <div style={{ ...shimmerDelay(delay + 30), height: 11, width: 64 }} />\n </div>\n <div className=\"flex justify-end\" style={SKEL_HEADER_CELL_STYLE}>\n <div style={{ ...shimmerDelay(delay + 60), height: 11, width: 64 }} />\n </div>\n </div>\n );\n}\n\nfunction OrderBookSkeleton() {\n // 8 rows per side is a good visual budget — enough to fill the typical\n // viewport without overdrawing huge skeleton trees on tall screens.\n const askRows = Array.from({ length: 8 }, (_, i) => i);\n const bidRows = Array.from({ length: 8 }, (_, i) => i);\n return (\n <>\n <ShimmerStyle />\n <div\n className=\"flex flex-col h-full min-h-0\"\n style={SKEL_CONTAINER_STYLE}\n >\n {/* Real header — same text and metrics as OrderBookUI. */}\n <div className=\"flex items-center flex-none\" style={SKEL_HEADER_STYLE}>\n <div className=\"flex items-center\" style={SKEL_HEADER_CELL_STYLE}>\n Price\n </div>\n <div\n className=\"flex items-center justify-end\"\n style={SKEL_HEADER_CELL_STYLE}\n >\n Amount (USD)\n </div>\n <div\n className=\"flex items-center justify-end\"\n style={SKEL_HEADER_CELL_STYLE}\n >\n Total (USD)\n </div>\n </div>\n\n {/* Asks placeholder rows */}\n <div className=\"flex-1 min-h-0 overflow-hidden\">\n {askRows.map((i) => (\n <SkelRow key={`ask-${i}`} delay={i * 40} />\n ))}\n </div>\n\n {/* Spread bar placeholder — keep the bar's tinted background and\n a single shimmer cell where the precision dropdown lives. */}\n <div\n className=\"flex-none flex items-center justify-center\"\n style={SKEL_SPREAD_BAR_STYLE}\n >\n <div style={{ ...shimmerDelay(0), width: 96, height: 12 }} />\n </div>\n\n {/* Bids placeholder rows */}\n <div className=\"flex-1 min-h-0 overflow-hidden\">\n {bidRows.map((i) => (\n <SkelRow key={`bid-${i}`} delay={200 + i * 40} />\n ))}\n </div>\n </div>\n </>\n );\n}\n\nfunction OrderBookEmpty() {\n return (\n <div className=\"flex items-center justify-center h-full\">\n <span className=\"text-neutral-400 text-sm\">\n No order book data available\n </span>\n </div>\n );\n}\n\nexport function OrderBookWidget({\n symbol,\n maxLevel = 40,\n precisionOptions = DEFAULT_ORDER_BOOK_PRECISION_OPTIONS,\n defaultPrecision,\n onPriceClick,\n className,\n}: OrderBookWidgetProps) {\n const initialPrecision = defaultPrecision ?? precisionOptions[0] ?? 1;\n\n const { bids, asks, spreadPercentage, isLoading, precision, setPrecision } =\n useOrderBookScript({\n symbol,\n maxLevel,\n precision: initialPrecision,\n });\n\n if (isLoading) {\n return <OrderBookSkeleton />;\n }\n\n if (bids.length === 0 && asks.length === 0) {\n return <OrderBookEmpty />;\n }\n\n return (\n <div className={className}>\n <OrderBookUI\n bids={bids}\n asks={asks}\n spreadPercentage={spreadPercentage}\n precision={precision}\n precisionOptions={precisionOptions}\n onPrecisionChange={setPrecision}\n onPriceClick={onPriceClick}\n />\n </div>\n );\n}\n","import { useEffect, useRef, useState } from \"react\";\nimport { useMarketDataSubscription } from \"../../hooks/useMarketDataSubscription\";\nimport { useRecentTradesQuery } from \"../../hooks/useRecentTradesQuery\";\nimport type { Trade } from \"../../types\";\n\nexport type UseTradesScriptParams = {\n symbol: string;\n limit?: number;\n};\n\nexport type UseTradesScriptResult = {\n trades: Trade[];\n isLoading: boolean;\n};\n\n/**\n * Trailing-edge flush interval for incoming WebSocket trade pushes. Hyperliquid\n * can fire 5–30 fills per second on active markets like BTC perp. Calling\n * `setTrades` for every push triggers React reconciliation per push; coalescing\n * into one setState every `BATCH_FLUSH_MS` caps the reconcile rate at 5 Hz\n * without losing trades (we *append* — see {@link normalizeRealtimeTrades}).\n *\n * 200 ms is small enough that the latest trade is on screen \"instantly\" from\n * the user's perspective, and large enough to absorb the typical burst rate.\n */\nconst BATCH_FLUSH_MS = 200;\n\nexport function useTradesScript({\n symbol,\n limit = 50,\n}: UseTradesScriptParams): UseTradesScriptResult {\n const [trades, setTrades] = useState<Trade[]>([]);\n\n const { data: initialData, isPending } = useRecentTradesQuery({\n symbol,\n limit,\n });\n\n const { data: realtimeTrade } = useMarketDataSubscription<Trade | Trade[]>({\n type: \"trades\",\n symbol,\n enabled: !!initialData,\n });\n\n // Seed the in-memory trade list from the REST snapshot once it arrives.\n // After this point the websocket subscription owns updates.\n useEffect(() => {\n if (initialData) {\n setTrades(initialData.filter(isValidTrade));\n }\n }, [initialData]);\n\n // ---- Trailing-edge batch flush --------------------------------------\n // We accumulate incoming pushes in a ref and flush them through a single\n // `setTrades` no more than once every BATCH_FLUSH_MS. This is *append*\n // semantics (so we keep every fill), unlike `useMarketDataSubscription`'s\n // built-in `throttleMs` which is \"drop intermediate values\".\n const pendingRef = useRef<Trade[]>([]);\n const flushTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const limitRef = useRef(limit);\n limitRef.current = limit;\n\n useEffect(() => {\n if (!realtimeTrade) return;\n\n const incoming = normalizeRealtimeTrades(realtimeTrade);\n if (incoming.length === 0) return;\n pendingRef.current.push(...incoming);\n\n if (flushTimerRef.current !== null) return;\n\n flushTimerRef.current = setTimeout(() => {\n flushTimerRef.current = null;\n const batch = pendingRef.current;\n pendingRef.current = [];\n if (batch.length === 0) return;\n\n setTrades((prev) => {\n // Drop fills already present (Hyperliquid occasionally re-sends the\n // same trade across a reconnect). Match on (timestamp, price, qty)\n // tuple — `tradeId` is not always set.\n const deduped = batch.filter(\n (next) =>\n !prev.some(\n (existing) =>\n existing.timestamp === next.timestamp &&\n existing.price === next.price &&\n existing.quantity === next.quantity,\n ),\n );\n if (deduped.length === 0) return prev;\n\n // The batch arrives in chronological order from the WS feed; we\n // reverse it so the *latest* fill in the batch ends up at index 0\n // of the merged list (newest-first).\n return [...deduped.reverse(), ...prev].slice(0, limitRef.current);\n });\n }, BATCH_FLUSH_MS);\n }, [realtimeTrade]);\n\n // Reset on symbol change (or unmount). Drop any pending payload so it\n // can't land after the subscription is torn down.\n useEffect(() => {\n return () => {\n if (flushTimerRef.current !== null) {\n clearTimeout(flushTimerRef.current);\n flushTimerRef.current = null;\n }\n pendingRef.current = [];\n };\n }, [symbol]);\n\n return {\n trades,\n isLoading: isPending,\n };\n}\n\nfunction normalizeRealtimeTrades(payload: Trade | Trade[]): Trade[] {\n const list = Array.isArray(payload) ? payload : [payload];\n return list.filter(isValidTrade);\n}\n\nfunction isValidTrade(trade: Partial<Trade> | undefined): trade is Trade {\n if (!trade) return false;\n return (\n typeof trade.symbol === \"string\" &&\n (trade.side === \"buy\" || trade.side === \"sell\") &&\n typeof trade.price === \"number\" &&\n Number.isFinite(trade.price) &&\n typeof trade.quantity === \"number\" &&\n Number.isFinite(trade.quantity) &&\n typeof trade.timestamp === \"number\" &&\n Number.isFinite(trade.timestamp)\n );\n}\n","import type { CSSProperties, ReactElement } from \"react\";\nimport { useMemo, useRef } from \"react\";\nimport { List, type RowComponentProps } from \"react-window\";\nimport { useResizeObserver, useTickAge } from \"@liberfi.io/hooks\";\nimport type { Trade } from \"../../types\";\n\n// ---------------------------------------------------------------------------\n// Static styles hoisted to module scope so they are NOT reallocated on every\n// render. The trades list re-renders at the WS push rate and the age tick\n// rate, so allocating fresh style objects per render is wasted GC pressure\n// and breaks shallow-equality optimisations like React.memo.\n// ---------------------------------------------------------------------------\n\nconst ROW_HEIGHT = 22;\nconst HEADER_HEIGHT = 28;\nconst PRICE_COL_MAX_W = 100;\nconst AGE_COL_MAX_W = 120;\n\nconst CONTAINER_STYLE: CSSProperties = {\n backgroundColor: \"#000000\",\n fontSize: 11,\n};\n\nconst HEADER_STYLE: CSSProperties = {\n height: HEADER_HEIGHT,\n minHeight: HEADER_HEIGHT,\n padding: \"0 16px\",\n color: \"#6b6b6b\",\n fontSize: 11,\n};\n\nconst HEADER_PRICE_CELL: CSSProperties = {\n flex: \"1 1 0%\",\n maxWidth: PRICE_COL_MAX_W,\n};\nconst HEADER_SIZE_CELL: CSSProperties = { flex: \"1 1 0%\", marginLeft: 20 };\nconst HEADER_AGE_CELL: CSSProperties = {\n flex: \"1 1 0%\",\n maxWidth: AGE_COL_MAX_W,\n textAlign: \"right\",\n};\n\nconst ROW_INNER_STYLE: CSSProperties = {\n height: ROW_HEIGHT,\n minHeight: ROW_HEIGHT,\n maxHeight: ROW_HEIGHT,\n padding: \"0 16px\",\n};\n\nconst ROW_PRICE_CELL: CSSProperties = {\n flex: \"1 1 0%\",\n maxWidth: PRICE_COL_MAX_W,\n};\nconst ROW_SIZE_CELL: CSSProperties = {\n flex: \"1 1 0%\",\n marginLeft: 20,\n color: \"#FCFCFC\",\n};\nconst ROW_AGE_CELL: CSSProperties = {\n flex: \"1 1 0%\",\n maxWidth: AGE_COL_MAX_W,\n textAlign: \"right\",\n color: \"#777A8C\",\n};\n\n// Per-side row decoration. The colour comes from the project's semantic\n// theme tokens (declared in the consumer's `theme.css` as\n// `--color-bullish` / `--color-bearish`, which themselves resolve to\n// `hsl(var(--heroui-primary))` / `hsl(var(--heroui-secondary))`). Using\n// CSS variables instead of hard-coded hex keeps the bars in lock-step\n// with the active HeroUI theme — including future light-mode variants.\n//\n// Width is data-dependent (see `barWidth`), so we keep it out of the base.\nconst BUY_BAR_STYLE_BASE: CSSProperties = {\n position: \"absolute\",\n left: 0,\n top: 0,\n height: 20,\n background: \"linear-gradient(to right, transparent, var(--color-bullish))\",\n opacity: 0.15,\n pointerEvents: \"none\",\n};\nconst SELL_BAR_STYLE_BASE: CSSProperties = {\n position: \"absolute\",\n left: 0,\n top: 0,\n height: 20,\n background: \"linear-gradient(to right, transparent, var(--color-bearish))\",\n opacity: 0.15,\n pointerEvents: \"none\",\n};\n\n// ---------------------------------------------------------------------------\n// Formatting utilities\n// ---------------------------------------------------------------------------\n\n/**\n * Format the trade price. Mirrors `orderbook.ui.tsx`:\n * ≥ 1000 → integer with thousands separator (e.g. `80,646`)\n * ≥ 1 → 2–4 fraction digits (e.g. `84.62`)\n * < 1 → 6 fraction digits (e.g. `0.0457`)\n */\nfunction formatPrice(price: number): string {\n if (!Number.isFinite(price)) return \"-\";\n if (price >= 1000) {\n return price.toLocaleString(\"en-US\", {\n minimumFractionDigits: 0,\n maximumFractionDigits: 0,\n });\n }\n if (price >= 1) {\n return price.toLocaleString(\"en-US\", {\n minimumFractionDigits: 2,\n maximumFractionDigits: 4,\n });\n }\n return price.toFixed(6);\n}\n\n/**\n * Format the USD notional size. Always 2 fraction digits with a `$` prefix\n * and thousands separators, e.g. `$83.85`, `$8,365.65`. No K/M abbreviation\n * (Axiom uses full digits and so do we — easier to parse at a glance).\n */\nfunction formatUsd(usd: number): string {\n if (!Number.isFinite(usd)) return \"-\";\n return (\n \"$\" +\n usd.toLocaleString(\"en-US\", {\n minimumFractionDigits: 2,\n maximumFractionDigits: 2,\n })\n );\n}\n\n/**\n * Format the trade age. Receives milliseconds (the `useTickAge` return\n * value) to avoid a per-row second conversion. Steps:\n * < 60 s → `${n}s`\n * < 60 min → `${n}m`\n * < 24 h → `${n}h`\n * else → `${n}d`\n */\nfunction formatAge(ageMs: number): string {\n const seconds = Math.max(0, Math.floor(ageMs / 1000));\n if (seconds < 60) return `${seconds}s`;\n const minutes = Math.floor(seconds / 60);\n if (minutes < 60) return `${minutes}m`;\n const hours = Math.floor(minutes / 60);\n if (hours < 24) return `${hours}h`;\n return `${Math.floor(hours / 24)}d`;\n}\n\n/**\n * Map a USD notional value to a 0-100 percentage for the row's background\n * bar width. We reverse-engineered Axiom's relationship from observed DOM\n * samples (e.g. $12.09 → 11.24%, $83.85 → 23.85%, $8,365.65 → 53.84%) and\n * found a near-perfect fit:\n *\n * width(%) = 15 × log10(usd) − 5\n *\n * Logarithmic scale keeps small trades visible without letting whales\n * flatten everything to a sliver. Clamped to [0, 100].\n */\nfunction barWidth(usd: number): number {\n if (!Number.isFinite(usd) || usd <= 0) return 0;\n return Math.max(0, Math.min(100, 15 * Math.log10(usd) - 5));\n}\n\n// ---------------------------------------------------------------------------\n// Row component\n// ---------------------------------------------------------------------------\n\ntype TradeRowData = {\n trades: Trade[];\n onTradeClick?: (trade: Trade) => void;\n};\n\n/**\n * react-window v2 row component. Note: we deliberately do NOT wrap this in\n * `React.memo`. The age is driven by `useTickAge`'s internal `setAge`, which\n * only re-renders this single row — never the parent — so wrapping with\n * `memo` would not save any cascaded reconciliations. Parent re-renders\n * (caused by `trades` array changes from the 200ms batch flush) shift every\n * row's `trades[index]` reference anyway, defeating shallow equality.\n *\n * react-window itself already short-circuits off-screen rows by simply not\n * mounting them, so we get virtualization benefits without manual memo.\n */\nfunction TradeRow({\n index,\n style,\n trades,\n onTradeClick,\n}: RowComponentProps<TradeRowData>): ReactElement | null {\n const trade = trades[index];\n\n // Subscribe to the global 1 Hz timer for this row's age. `useTickAge` is a\n // thin wrapper over `useTick`, which itself uses a `GlobalTimer`\n // singleton — there is exactly one `setTimeout` for the entire app, all\n // rows share it via an internal Map. `setAge` fires only inside this row,\n // so age-tick reconciliation is bounded to *one* row per tick.\n const birthday = trade?.timestamp ?? Date.now();\n const ageMs = useTickAge(birthday);\n\n const usd = useMemo(() => {\n if (!trade) return 0;\n if (!Number.isFinite(trade.price) || !Number.isFinite(trade.quantity)) {\n return 0;\n }\n return trade.price * trade.quantity;\n }, [trade]);\n\n // Per-render allocation is unavoidable here because `width` depends on\n // `usd`. Keeping every other style static (see *_BAR_STYLE_BASE) limits\n // the cost to one tiny object per visible row per WS push.\n const barStyle: CSSProperties = useMemo(() => {\n const isBuy = trade?.side === \"buy\";\n const base = isBuy ? BUY_BAR_STYLE_BASE : SELL_BAR_STYLE_BASE;\n return { ...base, width: `${barWidth(usd)}%` };\n }, [trade, usd]);\n\n if (!trade) return null;\n\n const isBuy = trade.side === \"buy\";\n\n return (\n <div style={style}>\n <div\n className=\"relative flex items-center cursor-pointer hover:bg-white/5 transition-colors\"\n style={ROW_INNER_STYLE}\n onClick={onTradeClick ? () => onTradeClick(trade) : undefined}\n >\n <div style={barStyle} />\n <div className=\"relative z-10 flex items-center\" style={ROW_PRICE_CELL}>\n <span className={isBuy ? \"text-bullish\" : \"text-bearish\"}>\n {formatPrice(trade.price)}\n </span>\n </div>\n <div className=\"relative z-10 flex items-center\" style={ROW_SIZE_CELL}>\n {formatUsd(usd)}\n </div>\n <div\n className=\"relative z-10 flex items-center justify-end\"\n style={ROW_AGE_CELL}\n >\n {formatAge(ageMs)}\n </div>\n </div>\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// List component\n// ---------------------------------------------------------------------------\n\nexport type TradesUIProps = {\n trades: Trade[];\n onTradeClick?: (trade: Trade) => void;\n};\n\nexport function TradesUI({\n trades,\n onTradeClick,\n}: TradesUIProps): ReactElement {\n // Resize observation: react-window v2 needs an explicit `height` prop on\n // `<List>`. We measure the wrapping div with the shared `useResizeObserver`\n // hook (same pattern used in `ui-tokens` SearchResultListWidget).\n const listContainerRef = useRef<HTMLDivElement | null>(null);\n const { height = 0 } = useResizeObserver<HTMLDivElement>({\n ref: listContainerRef,\n });\n\n // `rowProps` is the parameter object react-window passes (alongside\n // `index` / `style`) into our `rowComponent`. Memoise so the reference\n // is stable when neither `trades` nor `onTradeClick` change — keeps\n // react-window's own bailouts effective.\n const rowProps = useMemo<TradeRowData>(\n () => ({ trades, onTradeClick }),\n [trades, onTradeClick],\n );\n\n return (\n <div className=\"flex flex-col h-full\" style={CONTAINER_STYLE}>\n <div className=\"flex items-center flex-none\" style={HEADER_STYLE}>\n <div style={HEADER_PRICE_CELL}>Price</div>\n <div style={HEADER_SIZE_CELL}>Size (USD)</div>\n <div style={HEADER_AGE_CELL}>Age</div>\n </div>\n <div ref={listContainerRef} className=\"flex-1 min-h-0\">\n {height > 0 && (\n <List\n style={{ height }}\n rowComponent={TradeRow}\n rowCount={trades.length}\n rowHeight={ROW_HEIGHT}\n rowProps={rowProps}\n overscanCount={4}\n />\n )}\n </div>\n </div>\n );\n}\n","import type { CSSProperties } from \"react\";\nimport { ShimmerStyle, shimmerDelay } from \"../../internal/skeleton\";\nimport type { Trade } from \"../../types\";\nimport { useTradesScript } from \"./trades.script\";\nimport { TradesUI } from \"./trades.ui\";\n\nexport type TradesWidgetProps = {\n symbol: string;\n limit?: number;\n onTradeClick?: (trade: Trade) => void;\n className?: string;\n};\n\n// ---------------------------------------------------------------------------\n// Skeleton — must match TradesUI's footprint (header + virtualised rows) so\n// the layout doesn't jump when data arrives. Header text renders the real\n// labels; row placeholders pulse with the shared shimmer language used by\n// coin-info, orderbook and the prediction module's skeletons.\n//\n// Column metrics here intentionally mirror the constants in `trades.ui.tsx`\n// (PRICE_COL_MAX_W=100, AGE_COL_MAX_W=120, marginLeft=20 between price and\n// size). Keeping them in sync visually anchors the placeholder columns to\n// where the real columns will land.\n// ---------------------------------------------------------------------------\n\nconst SKEL_CONTAINER_STYLE: CSSProperties = {\n backgroundColor: \"#000000\",\n fontSize: 11,\n};\n\nconst SKEL_HEADER_STYLE: CSSProperties = {\n height: 28,\n minHeight: 28,\n padding: \"0 16px\",\n color: \"#6b6b6b\",\n fontSize: 11,\n};\n\nconst SKEL_HEADER_PRICE_CELL: CSSProperties = {\n flex: \"1 1 0%\",\n maxWidth: 100,\n};\nconst SKEL_HEADER_SIZE_CELL: CSSProperties = {\n flex: \"1 1 0%\",\n marginLeft: 20,\n};\nconst SKEL_HEADER_AGE_CELL: CSSProperties = {\n flex: \"1 1 0%\",\n maxWidth: 120,\n textAlign: \"right\",\n};\n\nconst SKEL_ROW_STYLE: CSSProperties = {\n height: 22,\n minHeight: 22,\n maxHeight: 22,\n padding: \"0 16px\",\n};\n\nfunction TradeSkelRow({ delay }: { delay: number }) {\n return (\n <div className=\"flex items-center\" style={SKEL_ROW_STYLE}>\n <div style={SKEL_HEADER_PRICE_CELL}>\n <div style={{ ...shimmerDelay(delay), height: 11, width: 56 }} />\n </div>\n <div style={SKEL_HEADER_SIZE_CELL}>\n <div style={{ ...shimmerDelay(delay + 30), height: 11, width: 64 }} />\n </div>\n <div className=\"flex justify-end\" style={SKEL_HEADER_AGE_CELL}>\n <div style={{ ...shimmerDelay(delay + 60), height: 11, width: 28 }} />\n </div>\n </div>\n );\n}\n\nfunction TradesSkeleton() {\n // 12 placeholder rows — the live list typically renders ~20-30 visible\n // rows, but 12 is enough to fill the panel without paying for every\n // additional shimmer paint while data is in flight.\n const rows = Array.from({ length: 12 }, (_, i) => i);\n return (\n <>\n <ShimmerStyle />\n <div className=\"flex flex-col h-full\" style={SKEL_CONTAINER_STYLE}>\n {/* Real header — same text and metrics as TradesUI. */}\n <div className=\"flex items-center flex-none\" style={SKEL_HEADER_STYLE}>\n <div style={SKEL_HEADER_PRICE_CELL}>Price</div>\n <div style={SKEL_HEADER_SIZE_CELL}>Size (USD)</div>\n <div style={SKEL_HEADER_AGE_CELL}>Age</div>\n </div>\n <div className=\"flex-1 min-h-0 overflow-hidden\">\n {rows.map((i) => (\n <TradeSkelRow key={`trade-${i}`} delay={i * 35} />\n ))}\n </div>\n </div>\n </>\n );\n}\n\nfunction TradesEmpty() {\n return (\n <div className=\"flex items-center justify-center h-full\">\n <span className=\"text-neutral-400 text-sm\">No recent trades</span>\n </div>\n );\n}\n\nexport function TradesWidget({\n symbol,\n limit = 100,\n onTradeClick,\n className,\n}: TradesWidgetProps) {\n const { trades, isLoading } = useTradesScript({ symbol, limit });\n\n if (isLoading) {\n return <TradesSkeleton />;\n }\n\n if (trades.length === 0) {\n return <TradesEmpty />;\n }\n\n return (\n <div className={className}>\n <TradesUI trades={trades} onTradeClick={onTradeClick} />\n </div>\n );\n}\n","import type { OrderSide } from \"../../types\";\n\n/**\n * The two TP/SL \"rows\" in the place-order form. Each row owns a Price\n * input and a Percent input; this enum tags which row a math helper\n * is operating on so the ± direction can be looked up correctly.\n */\nexport type TpSlKind = \"tp\" | \"sl\";\n\n// ── TP/SL math reference ─────────────────────────────────────────\n//\n// Both axiom and Hyperliquid express TP/SL \"%\" as **leveraged ROI**\n// on the user's margin — NOT a raw price-change percent. The\n// reference price `entry` is the **live mark price** at the moment\n// the user types (axiom refetches it per input event), not a frozen\n// quote, so the same TP % typed twice can render slightly\n// different prices across keystrokes.\n//\n// ── Side × kind direction table ──────────────────────────────────\n// long + tp target above entry (price up = profit)\n// long + sl target below entry (price down = loss)\n// short + tp target below entry (price down = profit)\n// short + sl target above entry (price up = loss)\n//\n// Both rows emit a *positive* percent when the target sits on the\n// favourable side (TP → in-profit, SL → expected adverse move). A\n// target on the wrong side surfaces a *negative* percent so the\n// user sees they've inverted the direction; we deliberately do not\n// clamp because doing so would silently rewrite a typed value.\n//\n// ── Closed-form ──────────────────────────────────────────────────\n// priceΔ = roiPct / leverage / 100\n// sign = + when (side, kind) ∈ { (long, tp), (short, sl) }\n// − otherwise\n// target = entry × (1 + sign × priceΔ)\n//\n// Inverted (price → percent), the same `sign` multiplies the\n// (target − entry) magnitude before scaling by leverage × 100.\n//\n// ── Worked examples ──────────────────────────────────────────────\n// Each example walks margin → notional → size → derived field, and\n// then verifies the round-trip P&L lands on the typed % (or vice\n// versa). Numbers are rounded to two decimals for readability.\n//\n// Reading the steps:\n// \"50% ROI / 10x leverage = 5% price\" unwinds the leverage —\n// at 10x, every 1% of price = 10% of margin, so 50% ROI only\n// needs the price to move 5%.\n// \"5% / 100 = 0.05\" converts percent to a\n// plain decimal fraction so the multiplicative `(1 + priceΔ)`\n// below produces a price, not a string-mangled scalar.\n// The two divisions chain into the one-liner\n// `priceΔ = roiPct / leverage / 100`.\n//\n// 1. Long + TP — derive Price from %\n// Setup: margin $5 · leverage 10x · entry $89.46 (SOL)\n// notional = $5 × 10 = $50\n// size = $50 / $89.46 = 0.5589 SOL\n// Input: TP % = 50 (target +50% ROI on the $5 margin)\n// pricePct = roiPct / leverage = 50 / 10 = 5 (% of price)\n// priceΔ = pricePct / 100 = 5 / 100 = 0.05 (as decimal)\n// sign = +1 (long + tp)\n// TP Price = entry × (1 + sign × priceΔ)\n// = 89.46 × (1 + 0.05) = $93.93\n// Round-trip P&L:\n// P&L = 0.5589 SOL × ($93.93 − $89.46) = +$2.50\n// ROI = $2.50 / $5 = 50% ✓\n//\n// 2. Long + SL — derive Price from %\n// Setup: margin $100 · leverage 20x · entry $80,000 (BTC)\n// notional = $100 × 20 = $2,000\n// size = $2,000 / $80,000 = 0.025 BTC\n// Input: SL % = 60 (cap loss at 60% of margin)\n// pricePct = 60 / 20 = 3 (% of price — 60% ROI / 20x)\n// priceΔ = 3 / 100 = 0.03 (decimal — 3% adverse move)\n// sign = −1 (long + sl)\n// SL Price = 80,000 × (1 − 0.03) = $77,600\n// Round-trip P&L:\n// P&L = 0.025 BTC × ($77,600 − $80,000) = −$60\n// ROI = −$60 / $100 = −60% ✓\n//\n// 3. Short + TP — derive Percent from Price (inverse direction)\n// Setup: margin $5 · leverage 10x · entry $89.46 (SOL)\n// size = 0.5589 SOL (short)\n// Input: TP Price = $80 (cover when SOL drops to $80)\n// priceΔ = sign × (target − entry) / entry\n// = (−1 × (80 − 89.46)) / 89.46 = 0.1058 (decimal)\n// pricePct = priceΔ × 100 = 10.58 (% of price)\n// TP % = pricePct × leverage = 10.58 × 10 = 105.79 (ROI %)\n// Round-trip P&L:\n// P&L = 0.5589 SOL × ($89.46 − $80) = +$5.29\n// ROI = $5.29 / $5 = 105.79% ✓\n//\n// 4. Short + SL — derive Percent from Price (inverse direction)\n// Setup: margin $40 · leverage 5x · entry $2,300 (ETH)\n// notional = $200 size = 0.0870 ETH (short)\n// Input: SL Price = $2,415 (stop loss when ETH rallies)\n// priceΔ = (+1 × (2,415 − 2,300)) / 2,300 = 0.05 (decimal)\n// pricePct = 0.05 × 100 = 5 (% of price)\n// SL % = 5 × 5 = 25 (ROI %)\n// Round-trip P&L:\n// P&L = 0.0870 ETH × ($2,300 − $2,415) = −$10\n// ROI = −$10 / $40 = −25% ✓\n//\n// ── Empirical anchor ─────────────────────────────────────────────\n// The formula was sanity-checked end-to-end against axiom's live\n// UI on 2026-05-07 (Short SOL, 10x):\n// axiom: TP Price = 80 → TP % = 105.81\n// axiom: SL Price = 90 → SL % = 7.30\n// Our formula reproduces these values to within 0.05 — the residual\n// drift is pure mark-price movement between consecutive input\n// events (axiom recomputes against `entry` = live mark every\n// keystroke; our snapshots were taken seconds apart).\n// ─────────────────────────────────────────────────────────────────\n\n/**\n * Look up the ± sign that converts the *favourable-direction*\n * priceΔ to a signed offset of `entry`. Long+TP and Short+SL are\n * \"+\" (target sits above entry); long+SL and short+TP are \"−\".\n */\nfunction signFor(side: OrderSide, kind: TpSlKind): 1 | -1 {\n if (side === \"long\" && kind === \"tp\") return 1;\n if (side === \"short\" && kind === \"sl\") return 1;\n return -1;\n}\n\n/**\n * Convert a TP/SL **price** to its leveraged-ROI **percent**.\n * Returns `undefined` when the inputs are insufficient for a\n * meaningful conversion (zero / negative entry or leverage,\n * non-finite price). Callers should leave the partner field\n * untouched in that case so a transitional state (e.g. price\n * typed before the market loads) doesn't clobber existing input.\n */\nexport function deriveTpSlPercent(\n price: number,\n entry: number,\n leverage: number,\n side: OrderSide,\n kind: TpSlKind,\n): number | undefined {\n if (!Number.isFinite(price)) return undefined;\n if (!entry || entry <= 0) return undefined;\n if (!leverage || leverage <= 0) return undefined;\n const sign = signFor(side, kind);\n const priceΔ = (sign * (price - entry)) / entry;\n return priceΔ * leverage * 100;\n}\n\n/**\n * Convert a leveraged-ROI **percent** to a TP/SL **price**.\n * Returns `undefined` for the same insufficient-input cases as\n * {@link deriveTpSlPercent}.\n */\nexport function deriveTpSlPrice(\n percent: number,\n entry: number,\n leverage: number,\n side: OrderSide,\n kind: TpSlKind,\n): number | undefined {\n if (!Number.isFinite(percent)) return undefined;\n if (!entry || entry <= 0) return undefined;\n if (!leverage || leverage <= 0) return undefined;\n const sign = signFor(side, kind);\n const priceΔ = percent / leverage / 100;\n return entry * (1 + sign * priceΔ);\n}\n\n/**\n * Round a derived TP/SL price to a sensible number of decimals\n * based on the asset's price magnitude. Mirrors the rule used by\n * the Est. Liq. Price formatter so the two values look visually\n * consistent across coins (BTC 0–1 dp, ETH 1 dp, SOL 3 dp, sub-\n * dollar perps 5 dp).\n */\nexport function roundTpSlPrice(value: number): number {\n if (!Number.isFinite(value) || value <= 0) return value;\n const magnitude = Math.floor(Math.log10(value));\n const decimals = Math.max(0, 4 - magnitude);\n const factor = 10 ** decimals;\n return Math.round(value * factor) / factor;\n}\n\n/**\n * Round a derived TP/SL percent to two decimals — matches axiom's\n * displayed precision (`105.81`, `7.30`, etc.) and avoids long-\n * tail floats like `105.81234567` polluting the input.\n */\nexport function roundTpSlPercent(value: number): number {\n if (!Number.isFinite(value)) return value;\n return Math.round(value * 100) / 100;\n}\n","import { useState, useMemo, useCallback, useEffect, useRef } from \"react\";\nimport { useForm } from \"react-hook-form\";\nimport { useMutation } from \"@tanstack/react-query\";\nimport { useAccountStateQuery } from \"../../hooks/useAccountStateQuery\";\nimport { useActiveAssetLeverageQuery } from \"../../hooks/useActiveAssetLeverageQuery\";\nimport { useAssetMetaQuery } from \"../../hooks/useAssetMetaQuery\";\nimport { useCreateOrderMutation } from \"../../hooks/useCreateOrderMutation\";\nimport { useMarketQuery } from \"../../hooks/useMarketQuery\";\nimport { usePositionsQuery } from \"../../hooks/usePositionsQuery\";\nimport type {\n OrderSide,\n OrderType,\n PlaceOrderRequest,\n PlaceOrderResult,\n} from \"../../types\";\nimport { deriveTpSlPrice } from \"./tp-sl-math\";\n\n/**\n * Initial leverage shown before the venue's configured value loads.\n * Once the {@link useActiveAssetLeverageQuery} resolves (or a position\n * arrives), the form is updated to reflect the on-chain truth.\n */\nconst FALLBACK_LEVERAGE = 20;\n\nexport type PlaceOrderFormData = {\n price?: number;\n /**\n * USDC margin the user is committing to this trade. Optional so the\n * form can render an empty input on first mount (placeholder\n * `0.0 USDC`) instead of pre-filling `0`. The notional position size\n * a venue cares about is derived as `amount * leverage`; the token\n * quantity is `(amount * leverage) / currentPrice`.\n */\n amount?: number;\n leverage: number;\n takeProfitPrice?: number;\n takeProfitPercent?: number;\n stopLossPrice?: number;\n stopLossPercent?: number;\n};\n\nexport type UsePlaceOrderFormScriptParams = {\n symbol: string;\n userAddress?: string;\n maxLeverage?: number;\n onSuccess?: () => void;\n onError?: (error: Error) => void;\n /**\n * Optional callback fired when the user confirms a new leverage value\n * in the leverage modal. The host app is expected to sign + relay the\n * `updateLeverage` action to Hyperliquid (and surface a toast). The\n * widget tracks the returned promise to drive the modal's button\n * loading state — when the promise rejects, the modal stays open so\n * the user can retry.\n *\n * When omitted, the modal falls back to a local-only update: the\n * leverage slider commits to the form state without contacting the\n * exchange.\n */\n onUpdateLeverage?: (leverage: number) => Promise<void>;\n /**\n * Optional callback that takes over order submission. When provided,\n * the form bypasses the SDK's internal `client.placeOrder` mutation\n * and forwards the enriched {@link PlaceOrderRequest} (live mark\n * price + coin-unit size + per-asset `szDecimals`) so the host can\n * sign + relay the action against the venue directly.\n *\n * Mirrors the {@link onUpdateLeverage} pattern; when omitted, the\n * widget falls back to {@link useCreateOrderMutation} → the\n * configured `IPerpetualsClient.placeOrder` (used by the LiberFi\n * adapter, which holds the signing keys server-side).\n */\n onPlaceOrder?: (request: PlaceOrderRequest) => Promise<PlaceOrderResult>;\n};\n\nexport type UsePlaceOrderFormScriptResult = {\n form: ReturnType<typeof useForm<PlaceOrderFormData>>;\n side: OrderSide;\n orderType: OrderType;\n setSide: (side: OrderSide) => void;\n setOrderType: (type: OrderType) => void;\n handleSubmit: (data: PlaceOrderFormData) => Promise<void>;\n isSubmitting: boolean;\n currentPrice?: number;\n estimatedFee: number;\n estimatedTotal: number;\n liquidationPrice?: number;\n availableMargin: number;\n accountValue: number;\n /**\n * Position the user currently holds in the symbol shown by the form.\n * Shaped to match the Axiom layout — `Long 0.00045 BTC (1.19 USDC)` —\n * by exposing the venue-precision size, base symbol, and isolated\n * margin used. `undefined` when there is no position for the symbol.\n */\n currentPosition?: {\n side: OrderSide;\n /** Absolute quantity from the venue (preserves precision when available). */\n quantity: number;\n /** Raw absolute quantity string from the venue, e.g. `\"0.00045\"`. */\n quantityRaw?: string;\n /** Isolated margin used by this position, in USDC. */\n margin: number;\n /** Base asset symbol, e.g. `\"BTC\"` for `\"BTC-USDC\"`. */\n base: string;\n };\n maxLeverage: number;\n /**\n * Leverage currently configured on the venue for `symbol`, sourced\n * from the `activeAssetData` info endpoint. Defined whether or not\n * an open position exists; `undefined` only while the query is\n * loading or when the venue does not expose this data (e.g. the\n * LiberFi adapter today).\n */\n currentLeverage?: number;\n /**\n * `true` once the venue has returned a leverage value for `symbol`.\n * The UI uses this to render a skeleton in place of the form's\n * default until the real configuration arrives, avoiding a\n * `20 → real value` flash on refresh.\n */\n isLeverageReady: boolean;\n /**\n * `true` when the user has at least one resting order on the venue\n * for `symbol`. Surfaced to the leverage modal so it can warn\n * \"open order(s) will be affected by leverage change\" — Hyperliquid\n * recomputes margin on resting orders whenever the per-asset\n * leverage changes, so the user should know before confirming.\n *\n * Sourced from the same `webData2` snapshot that drives positions\n * and balances, so it stays in sync with the rest of the form\n * without an extra REST round-trip.\n */\n hasOpenOrdersForSymbol: boolean;\n /**\n * Number of decimal places the venue uses to express the size\n * (token quantity) for `symbol`. Sourced from the `meta` info\n * endpoint; `undefined` while the query is in flight or when the\n * venue does not expose it (e.g. the LiberFi adapter today). The UI\n * uses this to format the converted token quantity badge with\n * per-asset precision (BTC → 5, SOL → 2, DOGE → 0).\n */\n szDecimals?: number;\n /** Forwarded callback (see {@link UsePlaceOrderFormScriptParams.onUpdateLeverage}). */\n onUpdateLeverage?: (leverage: number) => Promise<void>;\n};\n\nexport function usePlaceOrderFormScript({\n symbol,\n userAddress,\n maxLeverage: maxLeverageProp = 150,\n onSuccess,\n onError,\n onUpdateLeverage,\n onPlaceOrder,\n}: UsePlaceOrderFormScriptParams): UsePlaceOrderFormScriptResult {\n const [side, setSide] = useState<OrderSide>(\"long\");\n const [orderType, setOrderType] = useState<OrderType>(\"market\");\n\n // Form state. Leverage is seeded with a sensible default and then\n // overridden by the venue's configured value (Hyperliquid\n // `activeAssetData`) as soon as it loads — see the sync effects\n // further down. The form does not own leverage state; the exchange\n // does.\n //\n // `amount` is intentionally undefined on first mount so the input\n // renders its placeholder (`0.0 USDC`) instead of pre-filling `0`.\n const form = useForm<PlaceOrderFormData>({\n defaultValues: {\n amount: undefined,\n leverage: FALLBACK_LEVERAGE,\n takeProfitPrice: undefined,\n takeProfitPercent: undefined,\n stopLossPrice: undefined,\n stopLossPercent: undefined,\n },\n });\n\n const { data: marketData } = useMarketQuery({ symbol });\n\n // Per-asset venue metadata: size precision (`szDecimals`, used by\n // the UI's converted-token-quantity badge) and the leverage cap\n // (`maxLeverage`, used by the leverage modal's slider AND by the\n // liquidation-price formula). Independent of the user (no\n // `userAddress` needed) and stable for minutes at a time — the\n // client memoises the universe and TanStack caches the resolved\n // value, so re-renders don't re-fetch. When the meta hasn't\n // loaded yet (or the venue doesn't expose it, e.g. the LiberFi\n // adapter), `maxLeverage` falls back to the consumer-provided\n // prop and `liquidationPrice` resolves to `undefined` (rendered\n // as `--` by the UI).\n const { data: assetMeta } = useAssetMetaQuery({ symbol });\n const szDecimals = assetMeta?.szDecimals;\n // Resolve the effective leverage ceiling. Priority: per-asset\n // value from `meta` (Hyperliquid varies it per coin — BTC 40x,\n // ETH 25x, niche perps 3x–10x) → consumer-provided prop fallback.\n // The fallback keeps the modal usable on the first paint before\n // `useAssetMetaQuery` resolves.\n const resolvedMaxLeverage = assetMeta?.maxLeverage ?? maxLeverageProp;\n\n // Two mutations run in parallel — only one fires per submit.\n //\n // - `createOrderViaClient` → SDK's `IPerpetualsClient.placeOrder`,\n // used by the LiberFi adapter (which holds the signing keys\n // server-side and exposes a single high-level API).\n // - `placeOrderViaHost` → fires the `onPlaceOrder` callback so the\n // host app can sign + relay the action itself (used by the\n // direct-Hyperliquid setup, where the wallet lives in the\n // browser).\n //\n // Both share the same success/error/reset wiring; `isSubmitting`\n // is the OR of their pending flags so the submit button's spinner\n // works regardless of which path is active.\n const { mutateAsync: createOrderViaClient, isPending: isClientPending } =\n useCreateOrderMutation({\n onSuccess: () => {\n form.reset();\n onSuccess?.();\n },\n onError: (error) => {\n onError?.(error);\n },\n });\n\n const placeOrderViaHostMutation = useMutation<\n PlaceOrderResult,\n Error,\n PlaceOrderRequest\n >({\n mutationFn: async (request) => {\n if (!onPlaceOrder) {\n throw new Error(\n \"onPlaceOrder is not configured; cannot submit via host path\",\n );\n }\n return await onPlaceOrder(request);\n },\n onSuccess: () => {\n form.reset();\n onSuccess?.();\n },\n onError: (error: Error) => {\n onError?.(error);\n },\n });\n\n const isSubmitting = isClientPending || placeOrderViaHostMutation.isPending;\n\n const watchedValues = form.watch();\n const { amount, leverage, price } = watchedValues;\n\n const currentPrice = useMemo(() => {\n if (orderType === \"limit\" && price) {\n return price;\n }\n return marketData?.price || 0;\n }, [orderType, price, marketData?.price]);\n\n // Notional size of the position in USDC: the user commits `amount`\n // USDC of margin, leveraged up to `amount * leverage`. Both fee and\n // total are computed off the notional, not the margin alone.\n const notional = useMemo(() => {\n if (!amount || amount <= 0 || !leverage) return 0;\n return amount * leverage;\n }, [amount, leverage]);\n\n const estimatedFee = useMemo(() => {\n if (!notional) return 0;\n const feeRate = 0.0005;\n return notional * feeRate;\n }, [notional]);\n\n const estimatedTotal = useMemo(() => {\n if (!notional) return 0;\n return notional + estimatedFee;\n }, [notional, estimatedFee]);\n\n // Estimated liquidation price for a fresh isolated position.\n //\n // ── Setup ─────────────────────────────────────────────────────\n // m margin (USDC the user commits)\n // lev leverage (e.g. 20)\n // p entry price\n // N = m × lev position notional in USDC\n // q = N / p position size in coin units\n // l = 1 / (2 × maxLeverage) per-asset maintenance margin rate;\n // Hyperliquid pins maintenance to half\n // of the initial margin rate cap (BTC\n // maxLev 40x → initial 2.5%, mmr 1.25%)\n //\n // ── Liquidation condition ─────────────────────────────────────\n // A position is liquidated when equity drops to the maintenance\n // requirement, where the requirement is computed off the\n // *current* notional (q × p_liq), not the entry notional:\n //\n // long : m + q × (p_liq - p) = q × p_liq × l\n // short : m − q × (p_liq - p) = q × p_liq × l\n //\n // Substituting q = m·lev/p, dividing by m, and letting\n // x = p_liq / p, both sides solve to:\n //\n // long : x = (1 − 1/lev) / (1 − l) ⇒ 1 − (1/lev − l)/(1 − l)\n // short : x = (1 + 1/lev) / (1 + l) ⇒ 1 + (1/lev − l)/(1 + l)\n //\n // ── Intuition ────────────────────────────────────────────────\n // • `1/lev` initial margin rate — price has to move this far\n // against you for equity to reach zero.\n // • `l` maintenance margin rate — but liquidation fires\n // *before* equity hits zero, leaving only a buffer\n // of `1/lev − l` to burn through.\n // • `/(1 ∓ l)` closed-form correction for the implicit equation:\n // the maintenance requirement scales with `p_liq`\n // itself (q × p_liq × l), so `l` ends up in the\n // denominator after solving.\n //\n // ── Why we gate on `maxLeverage` ─────────────────────────────\n // Without per-asset `l`, the only honest fallback is \"--\". A\n // hardcoded mmr (the previous 0.5%) is wrong for nearly every\n // coin — BTC's true `l` ≈ 1.25%, SOL's ≈ 2.5%, niche perps go up\n // to 16% — and produces estimates that drift several percent\n // from the venue's actual liquidation level. We'd rather show\n // `--` for a beat than mislead the user.\n const liquidationPrice = useMemo(() => {\n if (!amount || !currentPrice || !leverage || leverage === 1)\n return undefined;\n if (!assetMeta?.maxLeverage) return undefined;\n\n const l = 1 / (2 * assetMeta.maxLeverage);\n const offset = (1 / leverage - l) / (side === \"long\" ? 1 - l : 1 + l);\n return side === \"long\"\n ? currentPrice * (1 - offset)\n : currentPrice * (1 + offset);\n }, [amount, currentPrice, leverage, side, assetMeta?.maxLeverage]);\n\n // Real account / position data sourced from Hyperliquid `clearinghouseState`.\n // Falls back to 0 when the wallet isn't connected (the query stays disabled\n // until `userAddress` is set; see `usePositionsQuery`'s internal guard).\n const { data: positionsData } = usePositionsQuery({\n userAddress,\n symbol,\n });\n\n const accountValue = positionsData?.totalEquity ?? 0;\n const availableMargin = positionsData?.availableBalance ?? 0;\n const currentPosition = useMemo<\n UsePlaceOrderFormScriptResult[\"currentPosition\"]\n >(() => {\n const pos = positionsData?.positions?.[0];\n if (!pos) return undefined;\n // Symbols come from the venue as `BASE-USDC` (e.g. `BTC-USDC`).\n // Fall back to the full symbol if the format ever changes so the\n // UI never renders an empty string.\n const base = pos.symbol.includes(\"-\")\n ? pos.symbol.split(\"-\")[0]\n : pos.symbol;\n return {\n side: pos.side,\n quantity: pos.quantity,\n quantityRaw: pos.quantityRaw,\n margin: pos.margin,\n base,\n };\n }, [positionsData?.positions]);\n\n // Read open orders for `symbol` from the unified WS-driven account\n // snapshot, not a `useOrdersQuery({ userAddress, symbol })` call.\n // The `useAccountStateSubscription` hook writes to the\n // `[\"perps\", \"orders\", userAddress, \"\"]` slot (no symbol filter);\n // querying with a `symbol` would land in a different cache slot\n // and fall through to a REST fetch, defeating the WS migration.\n // Reading from `useAccountStateQuery` keeps us on the live channel\n // and we filter client-side — at most a handful of items.\n const { data: account } = useAccountStateQuery({\n userAddress,\n enabled: !!userAddress,\n });\n const hasOpenOrdersForSymbol = useMemo(() => {\n if (!account?.openOrders?.length) return false;\n return account.openOrders.some((o) => o.symbol === symbol);\n }, [account?.openOrders, symbol]);\n\n // Read the user's per-asset leverage from the venue's\n // `activeAssetData` endpoint. This is the canonical source — it\n // works whether or not an open position exists, so a page refresh\n // always shows the latest leverage the user pushed via\n // `updateLeverage`. The position object also carries leverage, but\n // only when a position is open; `activeAssetData` covers both cases\n // and is therefore the single source of truth.\n const { data: activeAssetLeverage } = useActiveAssetLeverageQuery({\n userAddress,\n symbol,\n });\n const currentLeverage = activeAssetLeverage?.value;\n\n // Single gate for the leverage display:\n // - When the wallet is connected, we wait for the venue's\n // configured leverage to arrive before showing a value. This\n // avoids a `20 → real value` flash on refresh — the UI renders\n // a skeleton in the meantime.\n // - When the wallet is NOT connected, there is no per-user\n // leverage to fetch and the query stays disabled. Rendering a\n // skeleton in that case is wrong (it would never resolve), so\n // we treat the form's default (`FALLBACK_LEVERAGE`, 20x) as\n // canonical and show it immediately.\n //\n // The first time the user signs in we re-evaluate, and the\n // skeleton appears only if the query is genuinely in flight.\n const isLeverageReady = !userAddress || currentLeverage !== undefined;\n\n // Sync the form's `leverage` field with the venue's configured value\n // whenever it arrives (or whenever the user switches symbol). Only\n // runs once per symbol to avoid clobbering manual adjustments the\n // user makes via the leverage modal between syncs.\n const lastSyncedSymbolRef = useRef<string | null>(null);\n useEffect(() => {\n if (lastSyncedSymbolRef.current === symbol) return;\n if (currentLeverage && currentLeverage > 0) {\n form.setValue(\"leverage\", currentLeverage);\n lastSyncedSymbolRef.current = symbol;\n }\n }, [symbol, currentLeverage, form]);\n\n // Reset the per-symbol sync guard whenever the user navigates to a\n // different symbol so the new symbol's leverage payload is allowed\n // to overwrite the form value.\n useEffect(() => {\n lastSyncedSymbolRef.current = null;\n }, [symbol]);\n\n // Hard ceiling on Buy Amount: the user can never spend more margin\n // than they have. If they paste / type a value larger than the\n // available margin we rewrite the field in place — the UI doesn't\n // need to do anything, the input is bound to this same form state.\n //\n // For \"below zero\" we deliberately do NOT snap to `0`. Snapping to\n // a hard `0` competes with two legitimate user actions:\n // - Clearing the input (select-all + delete) should leave it\n // empty so the placeholder (`0.0 USDC`) can render.\n // - Dragging the slider all the way to 0% should also clear the\n // field, not pin it to a literal \"0\".\n // Both flows go through the form as `undefined`. So we only react\n // to a *strictly negative* number that survived the keyboard guard\n // (e.g. a paste) and clear it the same way — by writing\n // `undefined`, which the RHNumberInput renders as empty.\n useEffect(() => {\n if (typeof amount !== \"number\" || Number.isNaN(amount)) return;\n if (amount < 0) {\n form.setValue(\"amount\", undefined, {\n shouldValidate: false,\n shouldDirty: false,\n });\n return;\n }\n if (availableMargin > 0 && amount > availableMargin) {\n form.setValue(\"amount\", availableMargin, {\n shouldValidate: false,\n shouldDirty: true,\n });\n }\n }, [amount, availableMargin, form]);\n\n const handleSubmit = useCallback(\n async (data: PlaceOrderFormData) => {\n if (!userAddress) {\n throw new Error(\"User address is required\");\n }\n if (!data.amount || data.amount <= 0) {\n throw new Error(\"Amount is required\");\n }\n\n const finalPrice = orderType === \"limit\" ? data.price : undefined;\n\n // Submit-time fallback. The UI keeps Price ↔ Percent in\n // lock-step on every keystroke, so under normal conditions\n // both fields land here populated. The fallback covers the\n // edge case where the partner couldn't be derived at typing\n // time (e.g. mark price hadn't loaded yet) — we recompute\n // here using the SAME leveraged-ROI formula the UI uses,\n // sourced from `tp-sl-math.ts`. Order matters: prefer the\n // user-typed price; only synthesise from percent when the\n // price field is blank. Submitting with neither field set\n // leaves the corresponding bracket order out of the request,\n // which is the right thing to do since the user explicitly\n // declined to set one.\n let takeProfitPrice = data.takeProfitPrice;\n let stopLossPrice = data.stopLossPrice;\n\n if (\n !takeProfitPrice &&\n data.takeProfitPercent &&\n data.takeProfitPercent > 0 &&\n currentPrice\n ) {\n takeProfitPrice = deriveTpSlPrice(\n data.takeProfitPercent,\n currentPrice,\n data.leverage,\n side,\n \"tp\",\n );\n }\n\n if (\n !stopLossPrice &&\n data.stopLossPercent &&\n data.stopLossPercent > 0 &&\n currentPrice\n ) {\n stopLossPrice = deriveTpSlPrice(\n data.stopLossPercent,\n currentPrice,\n data.leverage,\n side,\n \"sl\",\n );\n }\n\n if (onPlaceOrder) {\n // Host-signed path: gate on the data the host hook needs.\n // Both `currentPrice` and `szDecimals` are populated by the\n // SDK's own queries, so this only fails if the user submits\n // before the first market / meta refetch lands — in which\n // case retrying once those are ready is the right UX.\n if (!currentPrice || currentPrice <= 0) {\n throw new Error(\n \"Mark price is unavailable; please retry once the market loads\",\n );\n }\n if (szDecimals === undefined) {\n throw new Error(\n \"Asset metadata is loading; please retry in a moment\",\n );\n }\n\n // Coin-unit position size. Matches the converted-quantity\n // badge the user sees beside the amount input. Done here\n // (not in the host hook) so consumers can stay venue-only\n // and don't need to reach into the form's mark price.\n const size = (data.amount * data.leverage) / currentPrice;\n\n await placeOrderViaHostMutation.mutateAsync({\n symbol,\n side,\n orderType,\n amount: data.amount,\n price: finalPrice,\n leverage: data.leverage,\n takeProfitPrice,\n stopLossPrice,\n userAddress,\n size,\n refPrice: currentPrice,\n szDecimals,\n });\n return;\n }\n\n // Default path: SDK client owns submission (LiberFi adapter).\n await createOrderViaClient({\n symbol,\n side,\n orderType,\n amount: data.amount,\n price: finalPrice,\n leverage: data.leverage,\n takeProfitPrice,\n stopLossPrice,\n userAddress,\n });\n },\n [\n symbol,\n side,\n orderType,\n currentPrice,\n szDecimals,\n userAddress,\n onPlaceOrder,\n placeOrderViaHostMutation,\n createOrderViaClient,\n ],\n );\n\n return {\n form,\n side,\n orderType,\n setSide,\n setOrderType,\n handleSubmit,\n isSubmitting,\n currentPrice,\n estimatedFee,\n estimatedTotal,\n liquidationPrice,\n availableMargin,\n accountValue,\n currentPosition,\n maxLeverage: resolvedMaxLeverage,\n currentLeverage,\n isLeverageReady,\n hasOpenOrdersForSymbol,\n szDecimals,\n onUpdateLeverage,\n };\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport type { CSSProperties } from \"react\";\nimport type { UseFormReturn } from \"react-hook-form\";\nimport {\n ModalContent,\n RHForm,\n RHNumberInput,\n Slider,\n Spinner,\n StyledModal,\n StyledTooltip,\n XCloseIcon,\n} from \"@liberfi.io/ui\";\nimport { useAuthCallback } from \"@liberfi.io/wallet-connector\";\nimport { shimmer, ShimmerStyle } from \"../../internal/skeleton\";\nimport type { OrderSide, OrderType } from \"../../types\";\nimport type { PlaceOrderFormData } from \"./place-order-form.script\";\nimport {\n deriveTpSlPercent,\n deriveTpSlPrice,\n roundTpSlPercent,\n roundTpSlPrice,\n type TpSlKind,\n} from \"./tp-sl-math\";\n\n/** Brand primary green; mirrors the color used elsewhere in the form. */\nconst BRAND_PRIMARY = \"#C7FF2E\";\n/** Long side accent — used wherever Long/Short need symmetric styling. */\nconst SIDE_LONG_COLOR = BRAND_PRIMARY;\n/** Short side accent — Hyperliquid orange. */\nconst SIDE_SHORT_COLOR = \"#F76816\";\n/**\n * Warning / risk text color — same hue as the short-side accent so\n * the form's loss/risk vocabulary stays visually consistent.\n * Applied via inline `style` rather than `text-[#…]` because\n * Tailwind 4 only registers arbitrary-value classes it finds in\n * scanned source — and the consumer's `@source` glob points at the\n * tsup-compiled dist files where the class name may not survive\n * minification verbatim, leaving the hex unmatched and the text\n * falling back to the default zinc color. Inline style sidesteps\n * that entire scan path.\n */\nconst BRAND_DANGER = SIDE_SHORT_COLOR;\n\n/**\n * Append an 8-bit alpha to a `#RRGGBB` hex string.\n *\n * Used by the Available Margin capsule to layer translucent fills over\n * the brand primary without pulling in a CSS-vars + `color-mix` setup —\n * the form is already a single styled component island, so a tiny pure\n * helper keeps the capsule readable inline.\n *\n * @param hex `#RRGGBB` (case-insensitive). Returned as-is when the\n * caller passed something else; we don't try to parse\n * `rgb()`/`hsl()` values.\n * @param alpha 0–255 alpha byte (e.g. `0x1A` ≈ 10%, `0x33` ≈ 20%).\n */\nfunction withAlpha(hex: string, alpha: number): string {\n if (!/^#[0-9a-fA-F]{6}$/.test(hex)) return hex;\n const a = Math.max(0, Math.min(255, Math.round(alpha)));\n return `${hex}${a.toString(16).padStart(2, \"0\").toUpperCase()}`;\n}\n\n/**\n * Hyperliquid-hosted icon CDN. The path is `${tokenSymbol}.svg` for\n * every listed asset. The form falls back silently (icon hidden) when\n * a symbol isn't covered, matching the consumer's `CoinSelectorBar`\n * behaviour. We don't expose this as a prop yet because every\n * consumer of this widget points at Hyperliquid; if a different venue\n * ever ships, lift this to a `tokenIconUrl` prop.\n */\nconst HYPERLIQUID_ICON_CDN = \"https://app.hyperliquid.xyz/coins\";\n\n/**\n * Hyperliquid's documented minimum order size, expressed in USDC of\n * notional position value (margin × leverage). It's a venue-wide\n * constant, not per-asset, and isn't surfaced by any /info endpoint —\n * the platform documents it in its public SDK docs and we mirror the\n * constant here. Update this single line if Hyperliquid ever raises\n * the floor.\n *\n * The threshold the input is actually compared against is the\n * **margin** equivalent of this notional at the *current leverage*,\n * computed at validation time as `MIN_NOTIONAL_USDC / leverage`. That\n * derivation lives in the submit-state machine because `leverage`\n * changes whenever the user opens the leverage modal — a leverage-\n * agnostic margin floor would either let small orders through at low\n * leverage (venue rejects) or block legitimate orders at high\n * leverage (false negative).\n */\nconst MIN_NOTIONAL_USDC = 10;\n\n/**\n * Sanitise a user-typed string into the canonical \"valid partial\n * number\" form. Drops everything that isn't a digit or a dot, and\n * collapses any extra dots — so `1..2`, `1.2.3`, `abc1.2def` all\n * become `1.2`. Returns the cleaned string verbatim (callers decide\n * whether to commit it as a number or keep it as a transitional\n * `\"2.\"` text state).\n */\nfunction sanitiseAmountInput(raw: string): string {\n const cleaned = raw.replace(/[^\\d.]/g, \"\");\n const parts = cleaned.split(\".\");\n return parts.length > 1 ? `${parts[0]}.${parts.slice(1).join(\"\")}` : cleaned;\n}\n\n/**\n * Inline skeleton block used to placehold a few characters of text\n * (e.g. the leverage value `20x`). Composes the shared {@link shimmer}\n * style with the size + `inline-block` needed to slot inside the\n * leverage button's flex row. All visual tuning (base color, sweep\n * gradient, animation timing) lives in `internal/skeleton.tsx` so the\n * coin-info, orderbook, trades, and place-order placeholders share a\n * single source of truth.\n */\nconst inlineTextSkeleton: CSSProperties = {\n ...shimmer,\n display: \"inline-block\",\n width: 28,\n height: 14,\n borderRadius: 4,\n};\n\nexport type PlaceOrderFormUIProps = {\n methods: UseFormReturn<PlaceOrderFormData>;\n side: OrderSide;\n orderType: OrderType;\n onSideChange: (side: OrderSide) => void;\n onOrderTypeChange: (type: OrderType) => void;\n onSubmit: (data: PlaceOrderFormData) => Promise<void>;\n isSubmitting: boolean;\n symbol: string;\n currentPrice?: number;\n estimatedFee: number;\n estimatedTotal: number;\n liquidationPrice?: number;\n availableMargin: number;\n accountValue: number;\n /**\n * Position the user currently holds in the symbol shown by the form.\n * Shaped to match the Axiom layout — `Long 0.00045 BTC (1.19 USDC)`.\n * `undefined` when there is no open position for `symbol`, in which\n * case the row falls back to `--`.\n */\n currentPosition?: {\n side: \"long\" | \"short\";\n quantity: number;\n quantityRaw?: string;\n margin: number;\n base: string;\n };\n maxLeverage: number;\n /**\n * Whether the leverage value can be displayed. When `false` the\n * leverage button shows a skeleton instead of the form's default,\n * to avoid flashing `20x` before the venue's per-asset configuration\n * is loaded. Defaults to `true` for backwards compatibility.\n */\n isLeverageReady?: boolean;\n /**\n * Whether the user has at least one resting order on `symbol`.\n * Drives the leverage modal's \"Open order(s) will be affected\"\n * advisory — Hyperliquid recomputes resting-order margin when the\n * per-asset leverage changes, so the user should see this before\n * confirming. Purely informational; does NOT block the update.\n */\n hasOpenOrdersForSymbol?: boolean;\n /**\n * Number of decimal places the venue uses for the size of `symbol`\n * (e.g. BTC → 5, ETH → 4, SOL → 2, DOGE → 0). Sourced from\n * Hyperliquid's `meta` info endpoint via `useAssetMetaQuery`. The\n * UI uses this to format the converted token quantity badge with\n * per-asset precision. When omitted the form falls back to an\n * adaptive heuristic that keeps the badge readable across coins\n * with very different price magnitudes.\n */\n szDecimals?: number;\n /**\n * Optional callback fired when the user clicks the \"Add More Funds\"\n * button (typically wired by the host app to open a deposit dialog).\n * The button is hidden when this prop is omitted, so consumers that\n * don't support a deposit flow don't render a dead control.\n */\n onAddFunds?: () => void;\n /**\n * Optional callback fired when the user confirms a new leverage in\n * the leverage modal. The widget tracks the returned promise to\n * drive the modal's button loading state — when it rejects the\n * modal stays open so the caller can retry. When omitted, the\n * leverage value is committed to the form locally without contacting\n * the exchange.\n */\n onUpdateLeverage?: (leverage: number) => Promise<void>;\n};\n\nfunction formatNumber(num: number, decimals: number = 2): string {\n return num.toFixed(decimals);\n}\n\n/**\n * Format a USD price for the \"Est. Liq. Price\" line.\n *\n * Mirrors the venue convention used by Hyperliquid's hosted UI and\n * Axiom — a `$` prefix, thousand separators, and roughly five\n * significant figures, so the precision tracks the asset's\n * magnitude (BTC `$79,771` → 0 decimals, ETH `$2,267.5` → 1\n * decimal, SOL `$96.524` → 3 decimals).\n *\n * Decimals are derived from `floor(log10(value))` instead of an\n * `if/else` ladder so the rule is uniform across price ranges,\n * including sub-dollar perps where `value < 1` and we keep more\n * decimals to preserve significance.\n */\nfunction formatLiqPrice(value: number): string {\n if (!Number.isFinite(value) || value <= 0) return \"--\";\n const magnitude = Math.floor(Math.log10(value));\n const decimals = Math.max(0, 4 - magnitude);\n return `$${new Intl.NumberFormat(\"en-US\", {\n minimumFractionDigits: decimals,\n maximumFractionDigits: decimals,\n }).format(value)}`;\n}\n\n/**\n * Hyperliquid's `updateLeverage` schema rejects 0, so 1x is the\n * absolute floor. The upper bound is per-asset (BTC 40x, ETH 25x,\n * niche perps as low as 3x) and flows in via `maxLeverage`.\n */\nconst LEVERAGE_MIN = 1;\n\n/**\n * Build orientation tick marks for the leverage slider. The visible\n * range is `[LEVERAGE_MIN, max]`; we pin 1x and `max` as anchors and\n * fill in three quartile marks rounded to a \"nice\" integer (multiples\n * of 5 once we're above 10) so the labels stay legible across\n * different per-asset caps. The set is deduped and sorted, so\n * degenerate caps (e.g. max = 3) collapse cleanly to `[1, 2, 3]`.\n */\nfunction buildLeverageMarks(max: number): { value: number; label: string }[] {\n const ceiling = Math.max(LEVERAGE_MIN, Math.floor(max));\n const niceRound = (n: number): number => {\n const v = Math.round(n);\n if (v <= 10) return Math.max(LEVERAGE_MIN, v);\n return Math.round(v / 5) * 5;\n };\n const ticks = new Set<number>([LEVERAGE_MIN, ceiling]);\n for (const pct of [0.25, 0.5, 0.75]) {\n const t = niceRound(ceiling * pct);\n if (t > LEVERAGE_MIN && t < ceiling) ticks.add(t);\n }\n return Array.from(ticks)\n .sort((a, b) => a - b)\n .map((value) => ({ value, label: `${value}x` }));\n}\n\nfunction LeverageModal({\n isOpen,\n initialLeverage,\n maxLeverage,\n coinName,\n hasOpenPosition,\n hasOpenOrders,\n onConfirm,\n onUpdate,\n onClose,\n}: {\n isOpen: boolean;\n initialLeverage: number;\n /**\n * Per-asset leverage cap from the venue's universe metadata.\n * Drives the slider's `maxValue` and the rightmost tick mark so\n * the user can't pick a value the venue would reject.\n */\n maxLeverage: number;\n /**\n * Base asset name (e.g. `\"BTC\"`) used in the advisory copy. The\n * widget derives this from `currentPosition.base` or strips\n * `-USDC` from `symbol`, so the warning reads `... for BTC ...`\n * regardless of which path produced it.\n */\n coinName: string;\n /**\n * `true` when the user already holds a position on `symbol`.\n * Hyperliquid rejects `updateLeverage` while a position is open,\n * so the modal blocks the update path: the slider is disabled,\n * the CTA is greyed out, and an explanatory advisory is shown.\n */\n hasOpenPosition: boolean;\n /**\n * `true` when the user has at least one resting order on `symbol`.\n * Purely informational — the venue still accepts the update, but\n * resting-order margin will be recomputed under the new leverage,\n * so the modal surfaces a note before confirmation.\n */\n hasOpenOrders: boolean;\n /**\n * Called immediately on confirm with the new leverage value. The\n * modal uses this to commit the value to the form regardless of\n * whether `onUpdate` is provided.\n */\n onConfirm: (v: number) => void;\n /**\n * Optional async hook for relaying the change to the exchange (sign\n * + POST /exchange `updateLeverage`). When provided, the modal\n * tracks the returned promise to drive the button's loading state\n * and only closes on resolve. On reject the modal stays open so\n * the caller can retry. The caller is responsible for surfacing\n * success / error toasts; the SDK does not toast on its own.\n */\n onUpdate?: (v: number) => Promise<void>;\n onClose: () => void;\n}) {\n // The venue cap can legitimately be < `LEVERAGE_MIN` only if the\n // upstream meta is malformed; clamp defensively so the slider\n // bounds stay valid.\n const ceiling = Math.max(LEVERAGE_MIN, Math.floor(maxLeverage));\n // Modal-local state: only commit to the form when the user hits\n // \"Update Leverage\". Lets them cancel via X / backdrop without side\n // effects, matching the reference design's modal semantics.\n const [draft, setDraft] = useState(\n Math.max(LEVERAGE_MIN, Math.min(initialLeverage, ceiling)),\n );\n const [pending, setPending] = useState(false);\n\n // Re-seed the draft when the modal reopens with a new initial value\n // (e.g. the user changed symbol and the on-chain leverage refreshed)\n // OR when the per-asset ceiling drops below the previously-drafted\n // value (e.g. user switches from a 40x asset to a 5x one).\n useEffect(() => {\n if (isOpen) {\n setDraft(Math.max(LEVERAGE_MIN, Math.min(initialLeverage, ceiling)));\n setPending(false);\n }\n }, [isOpen, initialLeverage, ceiling]);\n\n const marks = useMemo(() => buildLeverageMarks(ceiling), [ceiling]);\n\n const handleConfirm = useCallback(async () => {\n if (pending) return;\n if (!onUpdate) {\n onConfirm(draft);\n onClose();\n return;\n }\n setPending(true);\n try {\n await onUpdate(draft);\n onConfirm(draft);\n onClose();\n } catch {\n // Caller already toasted; keep the modal open so the user can\n // pick a different value or retry.\n setPending(false);\n }\n }, [pending, onUpdate, draft, onConfirm, onClose]);\n\n // Auth-gate `handleConfirm` (not `onUpdate`). The wrap order matters:\n // wrapping `onUpdate` would let the unauth case land *inside* the\n // try block as a resolved-with-undefined promise, which the modal\n // would then misread as \"exchange accepted\" and incorrectly commit\n // the draft + close. Wrapping `handleConfirm` short-circuits the\n // entire click handler before `setPending` / the try block run, so\n // the modal stays in its pre-click state (no spinner, still open)\n // while `signIn()` fires in the background. After auth completes\n // the user clicks \"Update Leverage\" again and the full flow runs.\n const guardedConfirm = useAuthCallback(handleConfirm);\n\n return (\n <StyledModal\n isOpen={isOpen}\n onOpenChange={(next) => {\n // Block backdrop / Esc dismiss while the update is in flight so\n // the user doesn't accidentally drop the request mid-signature.\n if (pending) return;\n if (!next) onClose();\n }}\n size=\"md\"\n hideCloseButton\n backdrop=\"blur\"\n classNames={{\n base: \"!bg-[#18181b] !rounded-[14px] !border !border-[rgba(39,39,42,1)] !shadow-[0_25px_50px_-12px_rgba(0,0,0,0.5)] max-w-[420px]\",\n body: \"!p-0\",\n }}\n >\n <ModalContent>\n <div className=\"flex flex-col\">\n {/* Header — mirrors DepositHyperliquidUsdcModal layout */}\n <div className=\"flex items-center justify-between px-5 pt-5 pb-2\">\n <h3 className=\"text-base font-semibold text-white m-0\">\n Adjust Leverage\n </h3>\n <button\n type=\"button\"\n onClick={onClose}\n disabled={pending}\n aria-label=\"Close\"\n className=\"p-1 rounded-[10px] hover:bg-[rgba(39,39,42,0.5)] text-zinc-400 hover:text-white transition-colors cursor-pointer disabled:cursor-not-allowed disabled:opacity-50\"\n >\n <XCloseIcon width={16} height={16} />\n </button>\n </div>\n\n <div className=\"px-5 pb-5 pt-2 flex flex-col gap-4\">\n {/* Two independent advisories:\n - Position-blocking (red) — Hyperliquid rejects\n `updateLeverage` while a position is open. Replaces\n the default gray description so the user isn't told\n to \"manage exposure\" when they can't actually\n proceed. Gates the slider + CTA on it.\n - Open-orders advisory (red) — informational only;\n stacks below the gray description (or below the\n position warning) and the venue still accepts the\n update. Margin on resting orders is recomputed\n under the new leverage, hence the warning. */}\n <div className=\"flex flex-col gap-1\">\n {hasOpenPosition ? (\n <p\n className=\"text-[13px] leading-[18px] m-0\"\n style={{ color: BRAND_DANGER }}\n >\n You may not update leverage for {coinName} while a position is\n open.\n </p>\n ) : (\n <p className=\"text-[13px] text-zinc-400 leading-[18px] m-0\">\n Adjust your leverage to manage your exposure. Higher leverage\n increases both potential profits and risks.\n </p>\n )}\n {hasOpenOrders && (\n <p\n className=\"text-[13px] leading-[18px] m-0\"\n style={{ color: BRAND_DANGER }}\n >\n Open order(s) for {coinName} will be affected by leverage\n change.\n </p>\n )}\n </div>\n\n {/* Slider with tick marks */}\n <div\n className=\"perp-leverage-slider\"\n style={{ padding: \"8px 6px 4px\" }}\n >\n {/* HeroUI Slider colors are theme-driven; tsup-compiled template\n literals would be invisible to Tailwind's static scan, so we\n tint the track / filler / thumb via plain CSS overrides keyed\n on a wrapper className. */}\n <style>{`\n .perp-leverage-slider [data-slot=\"track\"] { background-color: rgba(255,255,255,0.08) !important; }\n .perp-leverage-slider [data-slot=\"filler\"] { background-color: ${BRAND_PRIMARY} !important; }\n .perp-leverage-slider [data-slot=\"thumb\"] { background-color: ${BRAND_PRIMARY} !important; }\n .perp-leverage-slider [data-slot=\"thumb\"]::after { background-color: ${BRAND_PRIMARY} !important; }\n .perp-leverage-slider [data-slot=\"mark\"] { color: #6b6b6b !important; }\n `}</style>\n <Slider\n value={[draft]}\n onChange={(value: number | number[]) =>\n setDraft(Array.isArray(value) ? value[0] : value)\n }\n isDisabled={pending || hasOpenPosition}\n minValue={LEVERAGE_MIN}\n maxValue={ceiling}\n step={1}\n marks={marks}\n aria-label=\"Leverage\"\n />\n </div>\n\n {/* Selected value */}\n <div className=\"text-sm text-white font-medium\">\n Leverage: {draft}x\n </div>\n\n {/* Confirm button — matches the deposit modal CTA shape.\n Uses `guardedConfirm` so signed-out users get an auth\n prompt instead of a no-op click. When a position is\n open the venue rejects the update, so the button is\n replaced with a permanently-disabled \"Unable to update\n leverage\" CTA — matching the reference UX. */}\n <button\n type=\"button\"\n onClick={() => void guardedConfirm()}\n disabled={pending || hasOpenPosition}\n className=\"cursor-pointer mt-1 w-full h-12 rounded-[12px] font-medium text-black bg-[#C7FF2E] hover:bg-[#b6ed1c] active:bg-[#a6d913] transition-colors flex items-center justify-center gap-2 disabled:bg-[#3f3f46] disabled:text-zinc-500 disabled:cursor-not-allowed\"\n >\n {pending && <Spinner size=\"sm\" color=\"current\" />}\n {hasOpenPosition\n ? \"Unable to update leverage\"\n : pending\n ? \"Updating Leverage...\"\n : \"Update Leverage\"}\n </button>\n </div>\n </div>\n </ModalContent>\n </StyledModal>\n );\n}\n\n/**\n * Live-syncing text input bound to the form's `amount` field.\n *\n * Two mutable values:\n * - `inputText` — the visible string. Holds transitional states\n * React can't represent as a number (`\"\"`, `\".\"`, `\"5.\"`).\n * - `field.value` (RHF) — the parsed number, or `undefined` for\n * \"no input\". This is what every other consumer of the form\n * (slider, clamp effect, submit handler) reads.\n *\n * Sync rules:\n * - User types → sanitise, store as `inputText`, push parsed\n * number to RHF (or `undefined` for empty).\n * - RHF changes externally (slider drag, clamp effect) AND the\n * input is NOT focused → re-derive `inputText` from the new\n * number. Skipping the sync while focused preserves transitional\n * text like `\"5.\"` while the user is mid-keystroke.\n *\n * Why a subcomponent: scoping `useState` here keeps the input's\n * local string state out of the parent's render tree, so cycles\n * triggered by `methods.watch` higher up don't re-evaluate this\n * input's effects.\n */\nfunction BuyAmountInput({\n methods,\n}: {\n methods: UseFormReturn<PlaceOrderFormData>;\n}) {\n const formValue = methods.watch(\"amount\");\n const numericValue =\n typeof formValue === \"number\" && Number.isFinite(formValue)\n ? formValue\n : undefined;\n\n // Seed the input text from whatever's already in the form (may\n // come from `defaultValues`, navigation back into the page, or a\n // prior session).\n const [inputText, setInputText] = useState<string>(() =>\n numericValue !== undefined ? String(numericValue) : \"\",\n );\n const inputRef = useRef<HTMLInputElement | null>(null);\n\n // Sync inputText from the form value when an external source\n // (slider drag, the script's clamp effect, programmatic reset, …)\n // updates it.\n //\n // Naive rule \"skip sync while focused\" is too coarse: it preserves\n // transitional text (`\"5.\"` mid-typing → form holds `5`) but also\n // suppresses *legitimate* overrides like the script's\n // `amount > availableMargin` clamp. After typing `999` the user\n // would see the visible input keep `999` even though the form has\n // already snapped to the cap — and that mismatch is exactly the\n // bug Axiom side-steps by aggressively overwriting the field on\n // every over-cap keystroke.\n //\n // The right rule is \"skip sync only when the visible text already\n // *agrees* numerically with the form value\". `\"5.\"` parses to `5`\n // and the form holds `5` — values agree, leave the dot in place.\n // `\"999\"` parses to `999` and the form holds `5.343352` — values\n // disagree, the form has won, mirror it back to the visible\n // input. While unfocused we always sync (the user isn't typing\n // anything we'd be in danger of clobbering).\n useEffect(() => {\n const isFocused =\n typeof document !== \"undefined\" &&\n document.activeElement === inputRef.current;\n setInputText((prev) => {\n const parsedPrev = parseFloat(prev);\n const valuesAgree =\n Number.isFinite(parsedPrev) && parsedPrev === numericValue;\n if (isFocused && valuesAgree) return prev;\n const next = numericValue !== undefined ? String(numericValue) : \"\";\n return prev === next ? prev : next;\n });\n }, [numericValue]);\n\n const handleChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const cleaned = sanitiseAmountInput(e.target.value);\n setInputText(cleaned);\n\n if (cleaned === \"\" || cleaned === \".\") {\n // Empty or just-a-dot — no committable number yet. Push\n // `undefined` to the form so the slider stays at 0% and any\n // submit-state machine that reads `amount` sees \"no value\".\n methods.setValue(\"amount\", undefined, {\n shouldValidate: false,\n shouldDirty: true,\n });\n return;\n }\n const parsed = Number(cleaned);\n if (!Number.isFinite(parsed)) return;\n methods.setValue(\"amount\", parsed, {\n shouldValidate: false,\n shouldDirty: true,\n });\n },\n [methods],\n );\n\n const handleKeyDownCapture = useCallback(\n (e: React.KeyboardEvent<HTMLInputElement>) => {\n // Block sign / scientific-notation keys at source. Pasted\n // signed/exponent strings are still neutralised by\n // `sanitiseAmountInput` in onChange.\n if (e.key === \"-\" || e.key === \"+\" || e.key === \"e\" || e.key === \"E\") {\n e.preventDefault();\n e.stopPropagation();\n }\n },\n [],\n );\n\n return (\n <input\n ref={inputRef}\n type=\"text\"\n inputMode=\"decimal\"\n pattern=\"[0-9.]*\"\n autoComplete=\"off\"\n autoCorrect=\"off\"\n spellCheck={false}\n name=\"amount\"\n placeholder=\"0.0 USDC\"\n aria-label=\"Buy amount\"\n className=\"flex-1 min-w-0 bg-transparent border-none outline-none w-full\"\n style={{\n color: \"#ffffff\",\n fontSize: 18,\n lineHeight: \"23px\",\n fontVariantNumeric: \"tabular-nums\",\n padding: 0,\n }}\n value={inputText}\n onChange={handleChange}\n onKeyDownCapture={handleKeyDownCapture}\n />\n );\n}\n\n/**\n * Pretty-print a numeric form value for the TP/SL input boxes.\n * Strips the `.000…` tail that `String(0)` / `String(1.0)` produce\n * by going through `Number.toString()`'s shortest-roundtrip\n * representation, which matches what axiom shows in its input\n * boxes (`105.81`, `7.30`, `89.866` rather than `105.81000`).\n */\nfunction formatTpSlNumber(value: number): string {\n if (!Number.isFinite(value)) return \"\";\n return String(value);\n}\n\n/**\n * One half of a TP/SL row — either the Price input or the Percent\n * input. Holds its own string state (so transitional text like\n * `\"5.\"` survives mid-typing the same way `BuyAmountInput` does)\n * and is keyed off the matching `react-hook-form` field.\n *\n * Bidirectional sync lives here, not in the script, because it's\n * an interaction concern: the partner field is recomputed only on\n * a *user-driven* keystroke. Pure form-state changes (slider\n * drags, programmatic resets, side / leverage changes) never\n * trigger derivation — they go through `setValue` which the\n * `useEffect` below mirrors back into the input text without\n * touching the partner field.\n *\n * Direction lookup uses the {@link TpSlKind} + side combo; see\n * `tp-sl-math.ts` for the closed-form derivation and the side ×\n * kind sign table.\n */\nfunction TpSlInput({\n methods,\n field,\n placeholder,\n refPrice,\n leverage,\n side,\n}: {\n methods: UseFormReturn<PlaceOrderFormData>;\n field:\n | \"takeProfitPrice\"\n | \"takeProfitPercent\"\n | \"stopLossPrice\"\n | \"stopLossPercent\";\n placeholder: string;\n refPrice?: number;\n leverage: number;\n side: OrderSide;\n}) {\n // Resolve the TP/SL row this input belongs to (\"tp\" or \"sl\") and\n // the partner field name from the field id alone — keeps the\n // call sites symmetrical (they pass only `field`).\n const kind: TpSlKind = field.startsWith(\"takeProfit\") ? \"tp\" : \"sl\";\n const isPriceField = field === \"takeProfitPrice\" || field === \"stopLossPrice\";\n const partnerField: typeof field = (() => {\n switch (field) {\n case \"takeProfitPrice\":\n return \"takeProfitPercent\";\n case \"takeProfitPercent\":\n return \"takeProfitPrice\";\n case \"stopLossPrice\":\n return \"stopLossPercent\";\n case \"stopLossPercent\":\n return \"stopLossPrice\";\n }\n })();\n\n const formValue = methods.watch(field);\n const numericValue =\n typeof formValue === \"number\" && Number.isFinite(formValue)\n ? formValue\n : undefined;\n\n const [inputText, setInputText] = useState<string>(() =>\n numericValue !== undefined ? formatTpSlNumber(numericValue) : \"\",\n );\n const inputRef = useRef<HTMLInputElement | null>(null);\n\n // Same focus-aware sync rule as `BuyAmountInput`: only suppress\n // the mirror when the visible text already *agrees* numerically\n // with the form value. Lets transitional text (`\"5.\"`) persist\n // without leaking stale text after side / leverage changes\n // re-derive the partner field.\n useEffect(() => {\n const isFocused =\n typeof document !== \"undefined\" &&\n document.activeElement === inputRef.current;\n setInputText((prev) => {\n const parsedPrev = parseFloat(prev);\n const valuesAgree =\n Number.isFinite(parsedPrev) && parsedPrev === numericValue;\n if (isFocused && valuesAgree) return prev;\n const next =\n numericValue !== undefined ? formatTpSlNumber(numericValue) : \"\";\n return prev === next ? prev : next;\n });\n }, [numericValue]);\n\n const handleChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const cleaned = sanitiseAmountInput(e.target.value);\n setInputText(cleaned);\n\n // Empty / dot-only → clear *both* fields in this row.\n // Mirrors axiom: emptying TP Price also empties TP %, so the\n // user starts fresh next time they open the row.\n if (cleaned === \"\" || cleaned === \".\") {\n methods.setValue(field, undefined, {\n shouldValidate: false,\n shouldDirty: true,\n });\n methods.setValue(partnerField, undefined, {\n shouldValidate: false,\n shouldDirty: false,\n });\n return;\n }\n\n const parsed = Number(cleaned);\n if (!Number.isFinite(parsed)) return;\n\n methods.setValue(field, parsed, {\n shouldValidate: false,\n shouldDirty: true,\n });\n\n // Derive partner field. When the live mark price hasn't\n // landed yet (first paint, or a cold WebSocket) we leave the\n // partner alone so we don't blow it away with an undefined\n // derivation — the script's submit-time fallback recomputes\n // from whichever field is filled.\n if (!refPrice || refPrice <= 0 || !leverage || leverage <= 0) return;\n\n const partnerValue = isPriceField\n ? deriveTpSlPercent(parsed, refPrice, leverage, side, kind)\n : deriveTpSlPrice(parsed, refPrice, leverage, side, kind);\n\n if (partnerValue === undefined || !Number.isFinite(partnerValue)) {\n return;\n }\n const rounded = isPriceField\n ? roundTpSlPercent(partnerValue)\n : roundTpSlPrice(partnerValue);\n methods.setValue(partnerField, rounded, {\n shouldValidate: false,\n shouldDirty: false,\n });\n },\n [\n methods,\n field,\n partnerField,\n isPriceField,\n refPrice,\n leverage,\n side,\n kind,\n ],\n );\n\n const handleKeyDownCapture = useCallback(\n (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === \"-\" || e.key === \"+\" || e.key === \"e\" || e.key === \"E\") {\n e.preventDefault();\n e.stopPropagation();\n }\n },\n [],\n );\n\n return (\n <input\n ref={inputRef}\n type=\"text\"\n inputMode=\"decimal\"\n pattern=\"[0-9.]*\"\n autoComplete=\"off\"\n autoCorrect=\"off\"\n spellCheck={false}\n name={field}\n placeholder={placeholder}\n aria-label={field}\n className=\"w-full bg-transparent outline-none\"\n style={{\n color: \"#ffffff\",\n fontSize: 12,\n height: 32,\n padding: \"0 8px\",\n border: \"1px solid #1c1c1c\",\n borderRadius: 4,\n fontVariantNumeric: \"tabular-nums\",\n }}\n value={inputText}\n onChange={handleChange}\n onKeyDownCapture={handleKeyDownCapture}\n />\n );\n}\n\nexport function PlaceOrderFormUI({\n methods,\n side,\n orderType,\n onSideChange,\n onOrderTypeChange,\n onSubmit,\n isSubmitting,\n symbol,\n currentPrice,\n estimatedFee,\n liquidationPrice,\n availableMargin,\n accountValue,\n currentPosition,\n // Per-asset leverage cap from Hyperliquid's universe metadata\n // (`assetMeta.maxLeverage`, resolved by the script). Drives the\n // modal's slider max so the user can't pick a value the venue\n // would reject. Falls back to the prop default until the meta\n // query resolves.\n maxLeverage,\n isLeverageReady = true,\n hasOpenOrdersForSymbol = false,\n szDecimals,\n onAddFunds,\n onUpdateLeverage,\n}: PlaceOrderFormUIProps) {\n const [showLeverageModal, setShowLeverageModal] = useState(false);\n const [showTpSl, setShowTpSl] = useState(false);\n const leverage = methods.watch(\"leverage\") || 20;\n // Watching as `number | undefined` so the input renders empty (and\n // its placeholder shows) until the user types or the slider sets a\n // value.\n //\n // Note: HeroUI's NumberInput surfaces an *empty* state as `NaN`, not\n // `undefined`. `typeof NaN === \"number\"` is true, which means a\n // naive `typeof === \"number\"` guard would let NaN through and then\n // every downstream calc (`amount / availableMargin`, the slider's\n // `value`) would propagate NaN. `<input type=range>` falls back to\n // its midpoint when handed NaN — that was the \"50% on first paint\"\n // bug. We require a finite number everywhere.\n const rawAmount = methods.watch(\"amount\");\n const amount =\n typeof rawAmount === \"number\" && Number.isFinite(rawAmount) ? rawAmount : 0;\n const hasAmount = amount > 0;\n const tokenSymbol = symbol.split(\"-\")[0];\n\n // Slider reflects how much of the user's available margin they're\n // committing — a pure ratio, decoupled from leverage and price. This\n // matches the spec (\"拖动进度条 = Available Margin 的百分比\") and\n // keeps the slider stable when the underlying token price moves.\n const positionPercent = useMemo(() => {\n if (!availableMargin || availableMargin <= 0) return 0;\n if (!hasAmount) return 0;\n const pct = (amount / availableMargin) * 100;\n if (!Number.isFinite(pct)) return 0;\n return Math.max(0, Math.min(100, pct));\n }, [hasAmount, amount, availableMargin]);\n\n const handlePositionSlider = useCallback(\n (value: number) => {\n if (availableMargin <= 0) return;\n const pct = Math.max(0, Math.min(100, value)) / 100;\n // Slider all the way to 0% clears the input (placeholder shows\n // again) instead of pinning it to a literal \"0\" — same\n // contract as the user manually emptying the field. Anything\n // above 0 lands at 4-decimal precision: keystroke entry is\n // free-form (whatever precision the user types survives), but\n // drag emits a sensible step so the field doesn't fill with\n // long-tail floats like `12.34567891234567`. Submission still\n // truncates to the venue's tick size at the API layer.\n if (pct === 0) {\n methods.setValue(\"amount\", undefined, {\n shouldValidate: false,\n shouldDirty: true,\n });\n return;\n }\n const next = Number((availableMargin * pct).toFixed(4));\n methods.setValue(\"amount\", next, {\n shouldValidate: false,\n shouldDirty: true,\n });\n },\n [availableMargin, methods],\n );\n\n // USDC margin → coin quantity conversion shown to the right of the\n // Buy Amount input.\n //\n // ── Formula ───────────────────────────────────────────────────\n // notional = amount × leverage // total position size in USDC\n // coins = notional / currentPrice // how many coins that buys\n //\n // Worked example (SOL @ $89.475, 10x leverage, $5 margin):\n // notional = 5 × 10 = $50\n // coins = 50 / 89.475 = 0.5589 SOL\n // display = 0.56 SOL // truncated to szDecimals = 2\n //\n // ── Inputs ────────────────────────────────────────────────────\n // • `amount` USDC the user committed (form field).\n // • `leverage` synced with `activeAssetData` from the venue\n // (NOT the leverage button's display value when\n // they diverge — the on-chain value wins).\n // • `currentPrice` mark/last from `useMarketQuery`. Re-renders\n // automatically when the ticker moves, so the\n // coin quantity stays live.\n //\n // ── Display only ─────────────────────────────────────────────\n // The SDK does not submit token quantity yet — order placement\n // is driven by `notional` once the venue order pipe is wired.\n // This number exists purely to give the user a visual sense of\n // how big a position the USDC amount opens.\n const tokenQuantity = useMemo(() => {\n if (!hasAmount || !currentPrice || currentPrice <= 0) return 0;\n return (amount * leverage) / currentPrice;\n }, [hasAmount, amount, leverage, currentPrice]);\n\n // Margin floor that satisfies Hyperliquid's $10-notional minimum at\n // the user's *current* leverage. We derive this on every render\n // because `leverage` is itself live (the user can open the leverage\n // modal mid-input). Clamping to 1x at the bottom guards against\n // transient zero/negative values during state transitions — the\n // modal already enforces `LEVERAGE_MIN = 1` so this is purely\n // defensive.\n const minMarginUsdc = useMemo(\n () => MIN_NOTIONAL_USDC / Math.max(1, leverage),\n [leverage],\n );\n\n // Submit button state machine. Mirrors the spec exactly:\n // 1. balance = 0 → \"Add More Funds\"\n // 2a. amount empty → \"Invalid Buy Amount\"\n // 2b. amount × leverage < $10 notional → \"Order size too small\"\n // 3. otherwise → \"Long HYPE-USD\" / \"Short HYPE-USD\"\n //\n // Cases 2a and 2b share the same `kind: \"invalid\"` styling (gray,\n // disabled) but the copy is split: an empty input is a \"type\n // something\" prompt, while a too-small amount is an \"actually you\n // typed something but the venue won't accept it\" hint. The user\n // takes the same action to fix either, but seeing the distinction\n // helps them learn the venue's $10-notional minimum the first time\n // they hit it.\n //\n // The \"Add More Funds\" branch also covers the *not-logged-in* case:\n // when there is no connected wallet the upstream queries gate on\n // `userAddress` and surface `availableMargin = 0`, so we land here\n // naturally. The consumer is expected to wrap `onAddFunds` with an\n // auth guard (e.g. `useAuthenticatedCallback`) so clicking the\n // button while signed-out triggers login first and then opens the\n // deposit dialog. Keeping auth out of the SDK preserves the\n // venue-agnostic boundary.\n //\n // We compute the state once so the JSX stays readable and the\n // button properties (text / onClick / disabled) stay in lockstep.\n const submitState = useMemo<{\n label: string;\n kind: \"deposit\" | \"invalid\" | \"submit\";\n disabled: boolean;\n }>(() => {\n if (availableMargin <= 0) {\n return {\n label: \"Add More Funds\",\n kind: \"deposit\",\n disabled: !onAddFunds,\n };\n }\n if (!hasAmount) {\n return {\n label: \"Invalid Buy Amount\",\n kind: \"invalid\",\n disabled: true,\n };\n }\n if (amount < minMarginUsdc) {\n return {\n label: \"Order size too small\",\n kind: \"invalid\",\n disabled: true,\n };\n }\n return {\n label: `${side === \"long\" ? \"Long\" : \"Short\"} ${tokenSymbol}-USD`,\n kind: \"submit\",\n disabled: isSubmitting,\n };\n }, [\n availableMargin,\n hasAmount,\n amount,\n minMarginUsdc,\n side,\n tokenSymbol,\n isSubmitting,\n onAddFunds,\n ]);\n\n const handleSubmitButtonClick = useCallback(() => {\n if (submitState.kind === \"deposit\") onAddFunds?.();\n // \"submit\" delegates to native form submission (type=\"submit\");\n // \"invalid\" is disabled and cannot fire.\n }, [submitState.kind, onAddFunds]);\n\n // Pretty-format a token quantity. Coins span 6+ orders of magnitude\n // (e.g. BTC ~ 0.0001 vs PEPE ~ 1_000_000), so when the venue tells\n // us the canonical size precision (Hyperliquid's `szDecimals`) we\n // honour it exactly — that's what axiom does and it gives us\n // 1:1 fidelity with the venue (BTC → 5 dp, ETH → 4, SOL → 2,\n // DOGE → 0). Without it we fall back to an adaptive heuristic that\n // keeps the badge legible regardless of magnitude.\n const formatTokenQuantity = (n: number): string => {\n if (!Number.isFinite(n) || n <= 0) {\n // `0` is the resting state. When the venue declares 0 size\n // decimals (e.g. DOGE) emit a bare `0`; otherwise emit `0`\n // with no fraction to keep the row compact. Either way the\n // value is the same so we don't need to branch on szDecimals.\n return \"0\";\n }\n if (typeof szDecimals === \"number\" && szDecimals >= 0) {\n return n.toFixed(szDecimals);\n }\n if (n >= 1000) return n.toFixed(2);\n if (n >= 1) return n.toFixed(4);\n return n.toFixed(6);\n };\n\n return (\n <div\n className=\"flex flex-col h-full\"\n style={{ backgroundColor: \"#000000\" }}\n >\n {/* Inject the shimmer keyframes once per form mount so the\n inline leverage skeleton (and any future inline skeletons in\n this form) inherit the same sweep animation as the prediction\n module's card skeletons. The `<style>` tag is tiny and React\n dedupes duplicate same-body keyframe declarations. */}\n <ShimmerStyle />\n <div\n className=\"perp-order-form flex-1 overflow-y-auto\"\n style={{\n padding: \"16px 16px\",\n display: \"flex\",\n flexDirection: \"column\",\n gap: 16,\n }}\n >\n {/* Long / Short — bordered tab toggle */}\n <div\n className=\"perp-side-tabs flex\"\n style={{\n border: \"1px solid rgba(39,39,42,0.8)\",\n borderRadius: 8,\n padding: 4,\n gap: 4,\n }}\n >\n <StyledTooltip\n content=\"Buy asset, profit when price goes up\"\n placement=\"top\"\n delay={200}\n closeDelay={0}\n >\n <button\n type=\"button\"\n data-active={side === \"long\"}\n className=\"perp-side-tab perp-side-tab--long flex-1 cursor-pointer transition-colors\"\n style={{\n height: 32,\n fontSize: 14,\n borderRadius: 4,\n backgroundColor:\n side === \"long\" ? BRAND_PRIMARY : \"transparent\",\n color: side === \"long\" ? \"#000000\" : \"#b5b5b5\",\n fontWeight: side === \"long\" ? 500 : 400,\n border: \"none\",\n }}\n onClick={() => onSideChange(\"long\")}\n >\n Long\n </button>\n </StyledTooltip>\n <StyledTooltip\n content=\"Sell asset, profit when price goes down\"\n placement=\"top\"\n delay={200}\n closeDelay={0}\n >\n <button\n type=\"button\"\n data-active={side === \"short\"}\n className=\"perp-side-tab perp-side-tab--short flex-1 cursor-pointer transition-colors\"\n style={{\n height: 32,\n fontSize: 14,\n borderRadius: 4,\n backgroundColor: side === \"short\" ? \"#F76816\" : \"transparent\",\n color: side === \"short\" ? \"#000000\" : \"#b5b5b5\",\n fontWeight: side === \"short\" ? 500 : 400,\n border: \"none\",\n }}\n onClick={() => onSideChange(\"short\")}\n >\n Short\n </button>\n </StyledTooltip>\n </div>\n\n {/* Market / Limit + Leverage button */}\n <div className=\"flex items-center\" style={{ gap: 8 }}>\n <div className=\"flex\">\n {[\n { key: \"market\" as const, label: \"Market\" },\n { key: \"limit\" as const, label: \"Limit\" },\n ].map((tab) => (\n <div\n key={tab.key}\n style={{\n height: 32,\n display: \"flex\",\n alignItems: \"center\",\n borderBottom:\n orderType === tab.key\n ? \"2px solid #ffffff\"\n : \"2px solid transparent\",\n padding: \"2px 0 0\",\n cursor: \"pointer\",\n }}\n >\n <button\n type=\"button\"\n className=\"cursor-pointer transition-colors\"\n style={{\n padding: \"0 8px\",\n fontSize: 12,\n fontWeight: 500,\n backgroundColor: \"transparent\",\n color: orderType === tab.key ? \"#ffffff\" : \"#b5b5b5\",\n border: \"none\",\n }}\n onClick={() => onOrderTypeChange(tab.key)}\n >\n {tab.label}\n </button>\n </div>\n ))}\n </div>\n <div className=\"flex-1\" />\n {/* Leverage button — pill control sized to match the\n Market/Limit toggle text (12px / 400) so the controls in\n this row feel visually equal-weight. The focus ring uses\n the brand primary so keyboard navigation lands on the\n same accent color used everywhere else in the app.\n\n While the venue's configured leverage is loading we render\n a skeleton in place of the number so users don't see a\n jarring `20x → 35x` flash on refresh. The skeleton width\n is sized to roughly match a typical 1–2 digit value to\n avoid layout shift when the real number lands. */}\n <button\n type=\"button\"\n className=\"cursor-pointer flex items-center gap-1.5 px-3 py-1.5 rounded-[10px] transition-colors text-zinc-500 hover:text-zinc-200 hover:bg-zinc-800/40 focus:outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#C7FF2E] disabled:cursor-progress\"\n style={{ fontSize: 12, fontWeight: 400 }}\n onClick={() => setShowLeverageModal(true)}\n disabled={!isLeverageReady}\n >\n <span>Leverage:</span>\n {isLeverageReady ? (\n <span>{leverage}x</span>\n ) : (\n <span aria-hidden=\"true\" style={inlineTextSkeleton} />\n )}\n </button>\n </div>\n\n <RHForm methods={methods} onSubmit={onSubmit}>\n <div className=\"space-y-3 w-full\">\n {/* Limit price input */}\n {orderType === \"limit\" && (\n <div\n className=\"perp-price-box\"\n style={{\n borderRadius: 4,\n padding: 8,\n backgroundColor: \"rgba(26,26,26,0.5)\",\n border: \"1px solid #1c1c1c\",\n height: 64,\n display: \"flex\",\n flexDirection: \"column\",\n justifyContent: \"center\",\n }}\n >\n <div className=\"flex justify-between items-center\">\n <span style={{ fontSize: 12, color: \"#6b6b6b\" }}>Price</span>\n <span style={{ fontSize: 12, color: \"#6b6b6b\" }}>USDC</span>\n </div>\n <RHNumberInput\n name=\"price\"\n placeholder=\"0.0 USDC\"\n className=\"w-full\"\n />\n </div>\n )}\n\n {/* Buy Amount — input on the left in USDC, badge on the\n right showing the asset icon, ticker, and the converted\n token quantity (margin × leverage / price). The badge\n gives the user a live read of \"what am I actually\n buying\" without needing a second field. */}\n <div\n className=\"perp-buy-amt\"\n style={{\n borderRadius: 4,\n padding: 8,\n backgroundColor: \"rgba(26,26,26,0.5)\",\n border: \"1px solid #1c1c1c\",\n height: 64,\n display: \"flex\",\n flexDirection: \"column\",\n justifyContent: \"center\",\n }}\n >\n <div className=\"flex justify-between items-center\">\n <span style={{ fontSize: 12, color: \"#6b6b6b\" }}>\n Buy Amount\n </span>\n {/* Top-right slot is reserved for the asset symbol —\n a stable label that names the unit on the right\n side of the box, independent of whether the user\n has entered an amount yet. The numeric conversion\n sits below on the icon row. */}\n <span\n style={{\n fontSize: 14,\n fontWeight: 500,\n color: \"#ffffff\",\n }}\n >\n {tokenSymbol}\n </span>\n </div>\n <div\n className=\"flex items-center\"\n style={{ gap: 8, minHeight: 24 }}\n >\n {/* Plain controlled text input. We deliberately\n avoid `RHNumberInput` (HeroUI → React Aria\n NumberField) here because it commits its parsed\n value to RHF only on **blur**. That breaks live\n bidirectional sync with the slider: typing `5`\n keeps the slider thumb pinned at 0% until the\n input loses focus.\n \n `BuyAmountInput` keeps its own string state for\n the visible text, propagates a parsed number to\n RHF on every keystroke, and re-syncs when the\n form value changes externally (slider drag, the\n script's clamp effect). End result mirrors\n axiom's UX exactly. */}\n <BuyAmountInput methods={methods} />\n {/* Bottom-right slot — asset icon + the converted\n token quantity. Unit (e.g. \"BTC\") is implied by\n the symbol label up top; we show the bare number\n here so the row stays compact. The icon hides\n itself on a 404 so a missing CDN entry doesn't\n leave a broken image. */}\n <div className=\"flex items-center shrink-0\" style={{ gap: 6 }}>\n <img\n src={`${HYPERLIQUID_ICON_CDN}/${tokenSymbol}.svg`}\n alt={tokenSymbol}\n width={18}\n height={18}\n className=\"rounded-full\"\n style={{ width: 18, height: 18 }}\n onError={(e) => {\n (e.target as HTMLImageElement).style.display = \"none\";\n }}\n />\n {/* Font sizing intentionally matches the BuyAmountInput\n on the left (18 / 23) so the input value and its\n converted-token equivalent read as a single, balanced\n pair across the row instead of looking like a primary\n input + secondary caption. */}\n <span\n style={{\n fontSize: 18,\n lineHeight: \"23px\",\n color: \"#b5b5b5\",\n fontVariantNumeric: \"tabular-nums\",\n }}\n >\n {formatTokenQuantity(tokenQuantity)}\n </span>\n </div>\n </div>\n </div>\n\n {/* Position size slider — pure margin-percentage drag. The\n input above is the source of truth; we just project\n `amount / availableMargin` onto a 0–100 range. The\n slider is disabled when the user has no margin to\n spend (the spec's \"Deposit\" branch handles that\n case).\n \n Track fill: the visual rule is \"everything left of the\n thumb is brand green, everything to the right is the\n inert track\". WebKit doesn't expose a native filled\n pseudo-element on `<input type=range>`, so we fake it\n via a two-stop gradient on the runnable-track — driven\n by a `--pct` CSS variable set inline below. Firefox\n uses the native `::-moz-range-progress` pseudo, which\n handles the fill for free. */}\n <div>\n <style>{`\n .perp-buy-amt input, .perp-price-box input { font-size: 18px !important; line-height: 23px !important; }\n .perp-order-form .group,\n .perp-order-form .group div { background: transparent !important; border: none !important; padding: 0 !important; border-radius: 0 !important; min-height: 0 !important; height: auto !important; }\n .perp-order-form .group input { color: #ffffff !important; }\n .perp-slider { -webkit-appearance: none; appearance: none; background: transparent; cursor: pointer; width: 100%; height: 16px; --pct: 0%; --fill: ${BRAND_PRIMARY}; --track: #1c1c1c; }\n .perp-slider::-webkit-slider-runnable-track {\n height: 4px; border-radius: 2px;\n background: linear-gradient(to right, var(--fill) 0, var(--fill) var(--pct), var(--track) var(--pct), var(--track) 100%);\n }\n .perp-slider::-webkit-slider-thumb { -webkit-appearance: none; width: 12px; height: 12px; border-radius: 50%; background: ${BRAND_PRIMARY}; margin-top: -4px; border: none; box-shadow: 0 0 0 2px rgba(0,0,0,0.6); }\n .perp-slider::-moz-range-track { height: 4px; border-radius: 2px; background: #1c1c1c; border: none; }\n .perp-slider::-moz-range-progress { height: 4px; border-radius: 2px; background: ${BRAND_PRIMARY}; }\n .perp-slider::-moz-range-thumb { width: 12px; height: 12px; border-radius: 50%; background: ${BRAND_PRIMARY}; border: none; box-shadow: 0 0 0 2px rgba(0,0,0,0.6); }\n .perp-slider:disabled { cursor: not-allowed; opacity: 0.5; }\n .perp-side-tab[data-active=\"false\"]:hover { background-color: rgba(255,255,255,0.12) !important; color: #ffffff !important; }\n `}</style>\n <input\n type=\"range\"\n value={Math.round(positionPercent)}\n onChange={(e) => handlePositionSlider(Number(e.target.value))}\n min={0}\n max={100}\n step={1}\n disabled={availableMargin <= 0}\n className=\"perp-slider\"\n style={\n {\n // CSS var consumed by ::-webkit-slider-runnable-track\n // gradient. Pseudo-elements inherit custom properties\n // from the host, so the inline value flows down.\n [\"--pct\" as never]: `${Math.round(positionPercent)}%`,\n } as CSSProperties\n }\n />\n <div\n className=\"flex justify-between\"\n style={{ fontSize: 10, color: \"#b5b5b5\", marginTop: 4 }}\n >\n <span>0%</span>\n <span>25%</span>\n <span>50%</span>\n <span>75%</span>\n <span>100%</span>\n </div>\n </div>\n\n {/* TP/SL + Est. Liq. Price.\n Sits visually one tier below the percentage slider — the\n slider closes a \"size your order\" group and this row\n opens an \"advanced options\" group, so the gap here is\n intentionally wider than the form's default `space-y-3`\n rhythm. */}\n <div\n className=\"flex items-center justify-between\"\n style={{ marginTop: 16 }}\n >\n <div className=\"flex items-center\" style={{ gap: 6 }}>\n <div\n onClick={() => setShowTpSl((v) => !v)}\n style={{\n width: 16,\n height: 16,\n borderRadius: 4,\n border: \"1px solid #2a2a2a\",\n backgroundColor: showTpSl ? \"#C7FF2E\" : \"transparent\",\n flexShrink: 0,\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n }}\n >\n {showTpSl && (\n <svg width=\"10\" height=\"8\" viewBox=\"0 0 10 8\" fill=\"none\">\n <path\n d=\"M1 4L3.5 6.5L9 1\"\n stroke=\"#000000\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n )}\n </div>\n <span\n style={{ fontSize: 12, fontWeight: 500, color: \"#b5b5b5\" }}\n >\n TP/SL\n </span>\n </div>\n <div style={{ fontSize: 12, color: \"#6b6b6b\" }}>\n <span>Est. Liq. Price: </span>\n <span style={{ color: \"#b5b5b5\" }}>\n {liquidationPrice ? formatLiqPrice(liquidationPrice) : \"--\"}\n </span>\n </div>\n </div>\n\n {/* TP / SL rows (visible when TP/SL checked).\n Each row pairs a Price input with a Percent input.\n The two are bidirectionally linked: typing in either\n immediately rewrites the other, using the live mark\n price (`currentPrice`) as the entry reference and\n the on-chain `leverage` to convert raw priceΔ into\n leveraged ROI. The two rows are otherwise\n independent — the user can fill just TP, just SL,\n both, or neither, exactly like axiom. */}\n {showTpSl && (\n <div className=\"flex\" style={{ gap: 8 }}>\n <div className=\"flex-1\">\n <span\n style={{\n fontSize: 12,\n color: \"#6b6b6b\",\n marginBottom: 2,\n display: \"block\",\n }}\n >\n TP Price\n </span>\n <TpSlInput\n methods={methods}\n field=\"takeProfitPrice\"\n placeholder=\"Enter TP price\"\n refPrice={currentPrice}\n leverage={leverage}\n side={side}\n />\n </div>\n <div style={{ width: 70 }}>\n <span\n style={{\n fontSize: 12,\n color: \"#6b6b6b\",\n marginBottom: 2,\n display: \"block\",\n }}\n >\n TP %\n </span>\n <TpSlInput\n methods={methods}\n field=\"takeProfitPercent\"\n placeholder=\"0.0\"\n refPrice={currentPrice}\n leverage={leverage}\n side={side}\n />\n </div>\n </div>\n )}\n\n {showTpSl && (\n <div className=\"flex\" style={{ gap: 8 }}>\n <div className=\"flex-1\">\n <span\n style={{\n fontSize: 12,\n color: \"#6b6b6b\",\n marginBottom: 2,\n display: \"block\",\n }}\n >\n SL Price\n </span>\n <TpSlInput\n methods={methods}\n field=\"stopLossPrice\"\n placeholder=\"Enter SL price\"\n refPrice={currentPrice}\n leverage={leverage}\n side={side}\n />\n </div>\n <div style={{ width: 70 }}>\n <span\n style={{\n fontSize: 12,\n color: \"#6b6b6b\",\n marginBottom: 2,\n display: \"block\",\n }}\n >\n SL %\n </span>\n <TpSlInput\n methods={methods}\n field=\"stopLossPercent\"\n placeholder=\"0.0\"\n refPrice={currentPrice}\n leverage={leverage}\n side={side}\n />\n </div>\n </div>\n )}\n\n {/* Smart submit button — collapses what used to be a\n separate \"Add More Funds\" CTA into a single, context-\n sensitive action:\n - balance = 0 → \"Add More Funds\" (calls onAddFunds;\n consumer is expected to gate it\n with an auth callback so the\n signed-out path triggers login\n before opening the deposit dialog)\n - amount < $0.50 → \"Order size too small\" (disabled)\n - amount ∈ [0.5, max] → \"Long HYPE-USD\" / \"Short HYPE-USD\"\n The colour also tracks the side accent so users get a\n Long-green / Short-orange CTA matching the side toggle\n up top. */}\n {(() => {\n const isSubmit = submitState.kind === \"submit\";\n const buttonType = isSubmit ? \"submit\" : \"button\";\n const isLong = side === \"long\";\n const activeBg = isSubmit\n ? isLong\n ? SIDE_LONG_COLOR\n : SIDE_SHORT_COLOR\n : submitState.kind === \"deposit\"\n ? BRAND_PRIMARY\n : \"rgba(63,63,70,0.6)\";\n const activeColor =\n submitState.kind === \"invalid\" ? \"#71717a\" : \"#000000\";\n // While the submit mutation is in-flight, swap the\n // label for a spinner + \"Placing order...\" so the user\n // gets immediate feedback that the click registered.\n // Mirrors the LeverageModal's pending state above.\n const isPlacing = isSubmit && isSubmitting;\n return (\n <button\n type={buttonType}\n disabled={submitState.disabled}\n onClick={isSubmit ? undefined : handleSubmitButtonClick}\n className=\"w-full transition-colors disabled:cursor-not-allowed flex items-center justify-center gap-2\"\n style={{\n // Extra breathing room above the CTA so it reads as\n // a separate \"commit\" group from the TP/SL row (or\n // its expanded inputs) immediately above. Without\n // this the submit button feels glued to the\n // optional fields and is easy to mis-click while\n // adjusting them.\n marginTop: 16,\n height: 40,\n fontSize: 14,\n fontWeight: 600,\n color: activeColor,\n backgroundColor: activeBg,\n borderRadius: 9999,\n border: \"none\",\n cursor: submitState.disabled ? \"not-allowed\" : \"pointer\",\n opacity: submitState.disabled ? 0.9 : 1,\n }}\n >\n {isPlacing && <Spinner size=\"sm\" color=\"current\" />}\n {isPlacing ? \"Placing order...\" : submitState.label}\n </button>\n );\n })()}\n\n {/* Account info — sits directly under the Add More Funds CTA so\n Available Margin / Perps Account Value / Current Position\n stay near the action that funds them, instead of being\n pushed to the bottom of the form column. */}\n <div\n style={{\n fontSize: 12,\n display: \"flex\",\n flexDirection: \"column\",\n gap: 6,\n paddingTop: 4,\n }}\n >\n <div className=\"flex justify-between items-center\">\n <span style={{ color: \"#6b6b6b\" }}>Available Margin</span>\n {/* Capsule button — mirrors Axiom's \"tap-to-fund\" entry\n point. We intentionally use our own brand primary\n (green) instead of Axiom's blue, so the deposit CTA\n inherits the same accent as the rest of the form\n (Long color, slider fill, leverage thumb). The\n button degrades to a non-interactive pill when\n `onAddFunds` isn't wired, so headless consumers see\n the same shape without a dead click target. */}\n <button\n type=\"button\"\n onClick={onAddFunds}\n disabled={!onAddFunds}\n style={{\n height: 24,\n padding: \"0 8px\",\n borderRadius: 4,\n border: \"none\",\n backgroundColor: withAlpha(BRAND_PRIMARY, 0x1a),\n color: BRAND_PRIMARY,\n fontSize: 12,\n fontWeight: 500,\n lineHeight: \"16px\",\n cursor: onAddFunds ? \"pointer\" : \"default\",\n transition: \"background-color 150ms ease-in-out\",\n }}\n onMouseEnter={(e) => {\n if (onAddFunds) {\n e.currentTarget.style.backgroundColor = withAlpha(\n BRAND_PRIMARY,\n 0x33,\n );\n }\n }}\n onMouseLeave={(e) => {\n if (onAddFunds) {\n e.currentTarget.style.backgroundColor = withAlpha(\n BRAND_PRIMARY,\n 0x1a,\n );\n }\n }}\n >\n {formatNumber(availableMargin)} USDC\n </button>\n </div>\n <div className=\"flex justify-between\">\n <span style={{ color: \"#6b6b6b\" }}>Perps Account Value</span>\n <span style={{ color: \"#b5b5b5\", fontSize: 12 }}>\n {formatNumber(accountValue)} USDC\n </span>\n </div>\n <div className=\"flex justify-between\">\n <span style={{ color: \"#6b6b6b\" }}>Current Position</span>\n <span style={{ color: \"#b5b5b5\", fontSize: 12 }}>\n {currentPosition\n ? // Mirror Axiom's layout: `Long 0.00045 BTC (1.19 USDC)`.\n // `quantityRaw` preserves the venue's exact precision\n // (BTC's 5-dp `0.00045` survives instead of collapsing\n // to `0.00` like a `toFixed(2)` would), with the\n // parsed number as a fallback for adapters that don't\n // surface the raw string.\n `${currentPosition.side === \"long\" ? \"Long\" : \"Short\"} ${\n currentPosition.quantityRaw ??\n String(currentPosition.quantity)\n } ${currentPosition.base} (${currentPosition.margin.toFixed(2)} USDC)`\n : \"--\"}\n </span>\n </div>\n </div>\n </div>\n </RHForm>\n </div>\n\n {/* Branding footer */}\n <div\n style={{\n padding: \"10px 16px\",\n fontSize: 12,\n display: \"flex\",\n flexDirection: \"column\",\n }}\n >\n <div className=\"flex items-center justify-end\" style={{ gap: 6 }}>\n <span style={{ fontSize: 11, color: \"#6b6b6b\" }}>powered by</span>\n <img\n src=\"https://axiom-assets.sfo3.cdn.digitaloceanspaces.com/images/hyperliquid-logo.svg\"\n alt=\"Hyperliquid\"\n className=\"h-3 opacity-60\"\n onError={(e) => {\n const target = e.target as HTMLImageElement;\n target.style.display = \"none\";\n }}\n />\n </div>\n </div>\n\n {/* Leverage modal — kept always-mounted so HeroUI's open/close\n animations run smoothly, gated by `isOpen`. The modal\n locks updates when a position is open (venue-enforced) and\n shows an advisory when resting orders exist (caller-side\n info; the venue still accepts the update). */}\n <LeverageModal\n isOpen={showLeverageModal}\n initialLeverage={leverage}\n maxLeverage={maxLeverage}\n coinName={\n currentPosition?.base ??\n (symbol.includes(\"-\") ? symbol.split(\"-\")[0] : symbol)\n }\n hasOpenPosition={!!currentPosition}\n hasOpenOrders={hasOpenOrdersForSymbol}\n onConfirm={(v) => methods.setValue(\"leverage\", v)}\n onUpdate={onUpdateLeverage}\n onClose={() => setShowLeverageModal(false)}\n />\n </div>\n );\n}\n","import type { PlaceOrderRequest, PlaceOrderResult } from \"../../types\";\nimport { usePlaceOrderFormScript } from \"./place-order-form.script\";\nimport { PlaceOrderFormUI } from \"./place-order-form.ui\";\n\nexport type PlaceOrderFormWidgetProps = {\n symbol: string;\n userAddress?: string;\n maxLeverage?: number;\n onSuccess?: () => void;\n onError?: (error: Error) => void;\n /**\n * Optional callback fired when the user clicks \"Add More Funds\".\n * The host app typically opens its deposit dialog here. When omitted,\n * the button is hidden so the form doesn't expose a non-functional\n * control.\n */\n onAddFunds?: () => void;\n /**\n * Optional callback fired when the user confirms a new leverage value\n * in the leverage modal. The host app should sign + relay the\n * `updateLeverage` action to Hyperliquid and surface a toast. While\n * the returned promise is pending the modal's button shows a spinner;\n * if it rejects, the modal stays open so the user can retry.\n */\n onUpdateLeverage?: (leverage: number) => Promise<void>;\n /**\n * Optional callback that takes over order submission. When provided,\n * the widget bypasses its internal `client.placeOrder` mutation and\n * forwards the enriched {@link PlaceOrderRequest} (live mark price +\n * coin-unit size + per-asset `szDecimals`) so the host can sign and\n * relay the action against the venue directly. While the returned\n * promise is pending, the submit button shows a spinner; on\n * rejection, `onError` fires.\n *\n * Mirrors the `onUpdateLeverage` pattern. When omitted, the SDK\n * falls back to `IPerpetualsClient.placeOrder` (used by the LiberFi\n * adapter, which holds the signing keys server-side).\n */\n onPlaceOrder?: (request: PlaceOrderRequest) => Promise<PlaceOrderResult>;\n className?: string;\n};\n\nexport function PlaceOrderFormWidget({\n symbol,\n userAddress,\n maxLeverage,\n onSuccess,\n onError,\n onAddFunds,\n onUpdateLeverage,\n onPlaceOrder,\n className,\n}: PlaceOrderFormWidgetProps) {\n const {\n form,\n side,\n orderType,\n setSide,\n setOrderType,\n handleSubmit,\n isSubmitting,\n currentPrice,\n estimatedFee,\n estimatedTotal,\n liquidationPrice,\n availableMargin,\n accountValue,\n currentPosition,\n maxLeverage: resolvedMaxLeverage,\n isLeverageReady,\n hasOpenOrdersForSymbol,\n szDecimals,\n onUpdateLeverage: resolvedOnUpdateLeverage,\n } = usePlaceOrderFormScript({\n symbol,\n userAddress,\n maxLeverage,\n onSuccess,\n onError,\n onUpdateLeverage,\n onPlaceOrder,\n });\n\n return (\n <div className={className}>\n <PlaceOrderFormUI\n methods={form}\n side={side}\n orderType={orderType}\n onSideChange={setSide}\n onOrderTypeChange={setOrderType}\n onSubmit={handleSubmit}\n isSubmitting={isSubmitting}\n symbol={symbol}\n currentPrice={currentPrice}\n estimatedFee={estimatedFee}\n estimatedTotal={estimatedTotal}\n liquidationPrice={liquidationPrice}\n availableMargin={availableMargin}\n accountValue={accountValue}\n currentPosition={currentPosition}\n maxLeverage={resolvedMaxLeverage}\n isLeverageReady={isLeverageReady}\n hasOpenOrdersForSymbol={hasOpenOrdersForSymbol}\n szDecimals={szDecimals}\n onAddFunds={onAddFunds}\n onUpdateLeverage={resolvedOnUpdateLeverage}\n />\n </div>\n );\n}\n","import { useCallback, useMemo, useState } from \"react\";\nimport { useCreateOrderMutation } from \"../../hooks/useCreateOrderMutation\";\nimport { usePositionsQuery } from \"../../hooks/usePositionsQuery\";\nimport type { Position } from \"../../types\";\nimport type { PositionSortKey, SortDirection } from \"./positions.ui\";\n\nexport type UsePositionsScriptParams = {\n userAddress?: string;\n symbol?: string;\n onCloseSuccess?: () => void;\n onCloseError?: (error: Error) => void;\n};\n\nexport type UsePositionsScriptResult = {\n /** Positions already sorted by the active `sortKey` / `sortDir`. */\n positions: Position[];\n isLoading: boolean;\n error: Error | null;\n /** Active sort column (`null` only when the consumer overrides it). */\n sortKey: PositionSortKey | null;\n sortDir: SortDirection;\n /** Toggle the sort column / direction. Mirrors Axiom's 2-state cycle:\n * first click on a new column → asc, subsequent clicks toggle asc ↔\n * desc. There is no \"no-sort\" state. */\n onSort: (key: PositionSortKey) => void;\n handleClosePosition: (position: Position) => Promise<void>;\n isClosing: boolean;\n};\n\n// ---------------------------------------------------------------------------\n// Sort helpers\n// ---------------------------------------------------------------------------\n\n/** Map a sort key to the comparable scalar for a given position. */\nfunction getSortValue(\n position: Position,\n key: PositionSortKey,\n): number | string | null {\n switch (key) {\n case \"asset\":\n return position.symbol.split(\"-\")[0];\n case \"position\":\n return Math.abs(position.quantity);\n case \"value\":\n return position.notionalValue;\n case \"entry\":\n return position.entryPrice;\n case \"mark\":\n return position.markPrice;\n case \"liq\":\n // Empty liquidation price (very low leverage / cross-margin\n // surplus) is sorted to the end regardless of direction. We\n // signal this with `null` and the comparator handles ranking.\n return position.liquidationPrice ?? null;\n case \"marginPnl\":\n // Sort by the **margin amount**, not by PNL%. The column shows\n // both `$margin` and `(signed_$pnl / abs_pct%)`, but the sort\n // axis is the margin — biggest committed capital at the top\n // when `desc`. PNL% is a derived signal that depends on entry\n // and current mark, which makes it noisy as a sort key.\n return position.margin;\n }\n}\n\n/**\n * Compare two positions for the given column. `null` values (e.g.\n * unset `liquidationPrice`) always rank last, regardless of direction —\n * the standard \"missing data goes to the bottom\" UX convention.\n */\nfunction comparePositions(\n a: Position,\n b: Position,\n key: PositionSortKey,\n dir: SortDirection,\n): number {\n const aVal = getSortValue(a, key);\n const bVal = getSortValue(b, key);\n\n // Null ranking — always last, ignoring direction.\n if (aVal === null && bVal === null) return 0;\n if (aVal === null) return 1;\n if (bVal === null) return -1;\n\n let result: number;\n if (typeof aVal === \"string\" && typeof bVal === \"string\") {\n result = aVal.localeCompare(bVal);\n } else {\n // Both numbers (TS narrows from the union via the string check).\n result = (aVal as number) - (bVal as number);\n }\n\n return dir === \"asc\" ? result : -result;\n}\n\n// ---------------------------------------------------------------------------\n// Hook\n// ---------------------------------------------------------------------------\n\n/**\n * Container hook for the positions table. Responsibilities:\n * - read positions via `usePositionsQuery` (which the consumer's\n * `useAccountStateSubscription` keeps live via webData2 cache\n * write-through, so we do **not** subscribe to `userEvents` here —\n * doing so would clobber the TP/SL + mark-price enrichment that\n * the client adds on the webData2 path).\n * - own sort state (default `marginPnl ↓` — biggest margin first).\n * - expose a `handleClosePosition` shim over `useCreateOrderMutation`.\n */\nexport function usePositionsScript({\n userAddress,\n symbol,\n onCloseSuccess,\n onCloseError,\n}: UsePositionsScriptParams): UsePositionsScriptResult {\n // Default sort: `Margin Used (PNL) ↓` — biggest committed margin\n // at the top.\n const [sortKey, setSortKey] = useState<PositionSortKey | null>(\"marginPnl\");\n const [sortDir, setSortDir] = useState<SortDirection>(\"desc\");\n\n const onSort = useCallback((key: PositionSortKey) => {\n setSortKey((currentKey) => {\n if (currentKey === key) {\n // Same column → flip direction.\n setSortDir((d) => (d === \"asc\" ? \"desc\" : \"asc\"));\n return currentKey;\n }\n // New column → start ascending.\n setSortDir(\"asc\");\n return key;\n });\n }, []);\n\n const {\n data: positionsData,\n isLoading,\n error,\n } = usePositionsQuery({ userAddress, symbol }, { enabled: !!userAddress });\n\n const { mutateAsync: createOrder, isPending: isClosing } =\n useCreateOrderMutation({\n onSuccess: () => {\n onCloseSuccess?.();\n },\n onError: (err) => {\n onCloseError?.(err);\n },\n });\n\n const positions = useMemo(\n () => positionsData?.positions ?? [],\n [positionsData],\n );\n\n // Memoise the sorted view so React.memo'd children downstream skip\n // re-renders when sort state and source data are unchanged. Sorts a\n // copy — never mutate the source array, otherwise sibling\n // subscribers (e.g. account summary) would observe reordering.\n const sortedPositions = useMemo(() => {\n if (!sortKey) return positions;\n return [...positions].sort((a, b) =>\n comparePositions(a, b, sortKey, sortDir),\n );\n }, [positions, sortKey, sortDir]);\n\n const handleClosePosition = useCallback(\n async (position: Position) => {\n if (!userAddress) {\n throw new Error(\"User address is required\");\n }\n\n const closeSide = position.side === \"long\" ? \"short\" : \"long\";\n\n await createOrder({\n symbol: position.symbol,\n side: closeSide,\n orderType: \"market\",\n amount: Math.abs(position.quantity),\n leverage: position.leverage,\n userAddress,\n });\n },\n [userAddress, createOrder],\n );\n\n return {\n positions: sortedPositions,\n isLoading,\n error,\n sortKey,\n sortDir,\n onSort,\n handleClosePosition,\n isClosing,\n };\n}\n","import type { CSSProperties, ReactNode } from \"react\";\nimport { useTranslation } from \"@liberfi.io/i18n\";\nimport { cn, StyledTooltip } from \"@liberfi.io/ui\";\nimport type { Position } from \"../../types\";\n\n// ---------------------------------------------------------------------------\n// Sort\n// ---------------------------------------------------------------------------\n\n/**\n * Stable identifier for a sortable column. Mirrors Axiom's set: 7 of the\n * 9 columns are sortable; `tpsl` and `close` are interaction-only.\n *\n * Kept as a discriminated string union (rather than an enum) so it\n * survives a tsup build to a stable runtime string — consumers that\n * persist the active sort key to local-storage / URL params are\n * insulated from enum-numbering churn.\n */\nexport type PositionSortKey =\n | \"asset\"\n | \"position\"\n | \"value\"\n | \"entry\"\n | \"mark\"\n | \"liq\"\n | \"marginPnl\";\n\nexport type SortDirection = \"asc\" | \"desc\";\n\n// ---------------------------------------------------------------------------\n// Formatting\n// ---------------------------------------------------------------------------\n\n/**\n * Adaptive USD price formatter — mirrors Axiom's per-magnitude rounding\n * so a $80,564 BTC mark and a $0.0007 memecoin mark both render at a\n * useful precision without over- or under-reporting.\n *\n * ≥ 1000 → 0 fraction digits + thousands separator (e.g. `$80,564`)\n * ≥ 1 → 2 fraction digits (e.g. `$291.45`)\n * ≥ 0.01 → 4 fraction digits (e.g. `$0.0123`)\n * < 0.01 → 6 fraction digits (e.g. `$0.000123`)\n */\nfunction formatUsdPrice(n: number | undefined): string {\n if (n === undefined || !Number.isFinite(n)) return \"--\";\n const abs = Math.abs(n);\n let dp: number;\n if (abs >= 1000) dp = 0;\n else if (abs >= 1) dp = 2;\n else if (abs >= 0.01) dp = 4;\n else dp = 6;\n return (\n \"$\" +\n n.toLocaleString(\"en-US\", {\n minimumFractionDigits: dp,\n maximumFractionDigits: dp,\n })\n );\n}\n\n/** Notional / margin amount — always 2 decimals + `$` prefix. */\nfunction formatUsd2(n: number): string {\n if (!Number.isFinite(n)) return \"--\";\n return (\n \"$\" +\n n.toLocaleString(\"en-US\", {\n minimumFractionDigits: 2,\n maximumFractionDigits: 2,\n })\n );\n}\n\n/**\n * Signed PnL dollar amount, e.g. `+$0.06` / `-$0.06`. Sign is always\n * shown so the value remains intelligible if the row text colour is\n * lost (high-contrast modes, screenshots, copy-paste).\n */\nfunction formatSignedUsd2(n: number): string {\n if (!Number.isFinite(n)) return \"--\";\n const sign = n >= 0 ? \"+\" : \"-\";\n return (\n sign +\n \"$\" +\n Math.abs(n).toLocaleString(\"en-US\", {\n minimumFractionDigits: 2,\n maximumFractionDigits: 2,\n })\n );\n}\n\n/**\n * Absolute PnL percentage, e.g. `15.03%`. Direction is conveyed by the\n * cell colour (`text-bullish` / `text-bearish`), which removes the\n * redundant `+`/`-` clutter — matches Axiom and HL/Binance/Bybit\n * conventions.\n */\nfunction formatPercentAbs(percent: number): string {\n if (!Number.isFinite(percent)) return \"--\";\n return Math.abs(percent).toFixed(2) + \"%\";\n}\n\n/**\n * Position size string. Prefer the venue-supplied raw quantity to\n * preserve the exact precision (e.g. Hyperliquid's `pos.szi` may carry\n * trailing zeros that `parseFloat → toFixed` would erase). Fall back to\n * the parsed number with sensible defaults when the raw is missing.\n */\nfunction formatQuantity(quantity: number, raw?: string): string {\n if (raw) return raw;\n if (!Number.isFinite(quantity)) return \"--\";\n // 5 decimals covers BTC szDecimals (5); larger-precision assets are\n // rare on perp venues and will arrive with a `raw` string anyway.\n return quantity.toFixed(5).replace(/\\.?0+$/, \"\");\n}\n\n// ---------------------------------------------------------------------------\n// Column layout\n// ---------------------------------------------------------------------------\n\n/**\n * Flex-grow ratios per column, applied as **inline `style`** rather than\n * Tailwind arbitrary-value classes (e.g. `flex-[0.8]`).\n *\n * Why inline:\n * - Layout-critical: without these ratios cells collapse to text-content\n * width and the whole table reads as one mashed-up line.\n * - SDK self-containment: arbitrary-value classes only emit CSS when the\n * consumer's Tailwind v4 `@source` globs cover the file emitting them.\n * Common dev setups — `USE_LOCAL_SDK=true` aliasing imports from\n * `react-sdk/packages/*` — sidestep the consumer's `node_modules`\n * `@source` and silently drop the classes. Inline `style` always works.\n *\n * Total = 8.3, matching Axiom 1:1 so a 1440px-wide panel reproduces the\n * reference's column widths exactly. Position gets 1.2 to fit\n * `Long 0.000 12345 BTC` on one line; Margin (PNL) gets 1.5 — widest\n * column, has to host margin amount + signed PnL + abs %.\n */\nconst COL_STYLE: Record<string, CSSProperties> = {\n asset: { flex: \"0.8 1 0%\" },\n position: { flex: \"1.2 1 0%\" },\n value: { flex: \"0.8 1 0%\" },\n entry: { flex: \"0.8 1 0%\" },\n mark: { flex: \"0.8 1 0%\" },\n liq: { flex: \"0.8 1 0%\" },\n marginPnl: { flex: \"1.5 1 0%\" },\n tpsl: { flex: \"0.8 1 0%\" },\n close: { flex: \"0.8 1 0%\" },\n};\n\n/** Min-width of the inner table body — same rationale as `COL_STYLE`. */\nconst TABLE_MIN_WIDTH: CSSProperties = { minWidth: 1000 };\n\n/**\n * Header row: 28px tall, fixed.\n *\n * Uses `min-height` + `max-height` rather than `height` because the\n * row participates in a `flex-1` flex-col cascade (flex-basis: 0%\n * overrides the `height` property and lets the row collapse to its\n * content's font-size). `min-height` / `max-height` win over flex\n * sizing and clamp the row to exactly 28px regardless of flex grow.\n * Mirrors Axiom's `max-h-[28px] min-h-[28px]` pair.\n */\nconst HEADER_ROW_STYLE: CSSProperties = { minHeight: 28, maxHeight: 28 };\n\n/**\n * Body row: 36px tall, fixed. Same rationale as {@link HEADER_ROW_STYLE}\n * — clamps via `min-height` / `max-height` so flex-grow can't compress it.\n */\nconst BODY_ROW_STYLE: CSSProperties = { minHeight: 36, maxHeight: 36 };\n\n// ---------------------------------------------------------------------------\n// Header\n// ---------------------------------------------------------------------------\n\ntype HeaderAlign = \"start\" | \"center\" | \"end\";\n\ntype HeaderCellProps = {\n /** Inline `style` carrying the column's flex ratio (one of `COL_STYLE`). */\n style: CSSProperties;\n /** Cell content — usually a `<span>` with the column title. */\n children: ReactNode;\n /** When set, the cell is sortable and clicking toggles the sort. */\n sortKey?: PositionSortKey;\n activeSortKey?: PositionSortKey | null;\n sortDir?: SortDirection;\n onSort?: (key: PositionSortKey) => void;\n /**\n * Horizontal alignment of the header label. Defaults to `\"start\"`.\n * `\"end\"` is used by `Close` (right-aligned action column).\n * `\"center\"` is used by `TP/SL` so the header sits visually above\n * the slash divider in the body's `1fr auto 1fr` grid.\n */\n align?: HeaderAlign;\n};\n\nconst ALIGN_TO_JUSTIFY: Record<HeaderAlign, string> = {\n start: \"justify-start\",\n center: \"justify-center\",\n end: \"justify-end\",\n};\n\n/**\n * One header cell. Sortable cells get `cursor-pointer` + a hover white\n * tint, an `↑`/`↓` glyph appended when active, and an accessible\n * `<button>` semantic so keyboard users can sort with Enter / Space.\n */\nfunction HeaderCell({\n style,\n children,\n sortKey,\n activeSortKey,\n sortDir,\n onSort,\n align = \"start\",\n}: HeaderCellProps) {\n const isActive = sortKey !== undefined && sortKey === activeSortKey;\n const arrow = isActive ? (sortDir === \"asc\" ? \" \\u2191\" : \" \\u2193\") : \"\";\n const interactive = sortKey !== undefined && onSort !== undefined;\n const justify = ALIGN_TO_JUSTIFY[align];\n\n const inner = (\n <span className=\"text-xs font-normal text-default-500\">\n {children}\n {arrow}\n </span>\n );\n\n if (!interactive) {\n return (\n <div style={style} className={cn(\"flex flex-row items-center\", justify)}>\n {inner}\n </div>\n );\n }\n\n return (\n <button\n type=\"button\"\n onClick={() => onSort?.(sortKey)}\n style={style}\n className={cn(\n \"flex flex-row items-center cursor-pointer hover:text-foreground\",\n justify,\n )}\n >\n {inner}\n </button>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\nexport type PositionsUIProps = {\n /** Already-sorted positions. The script layer owns sort state. */\n positions: Position[];\n /** Currently active sort column, or `null` when no sort applied. */\n sortKey: PositionSortKey | null;\n sortDir: SortDirection;\n onSort: (key: PositionSortKey) => void;\n onClosePosition: (position: Position) => void;\n isClosing: boolean;\n /** Optional className for the outer container. */\n className?: string;\n};\n\nexport function PositionsUI({\n positions,\n sortKey,\n sortDir,\n onSort,\n onClosePosition,\n isClosing,\n className,\n}: PositionsUIProps) {\n const { t } = useTranslation();\n\n // Header is always rendered (even when empty) so the column legend\n // is visible while waiting for the first position. Mirrors Axiom.\n const header = (\n <div\n style={HEADER_ROW_STYLE}\n className=\"flex flex-1 flex-row items-center justify-start border-default-200 px-4 sm:border-b\"\n >\n <HeaderCell\n style={COL_STYLE.asset}\n sortKey=\"asset\"\n activeSortKey={sortKey}\n sortDir={sortDir}\n onSort={onSort}\n >\n {t(\"perpetuals.positions.col.asset\")}\n </HeaderCell>\n <HeaderCell\n style={COL_STYLE.position}\n sortKey=\"position\"\n activeSortKey={sortKey}\n sortDir={sortDir}\n onSort={onSort}\n >\n {t(\"perpetuals.positions.col.position\")}\n </HeaderCell>\n <HeaderCell\n style={COL_STYLE.value}\n sortKey=\"value\"\n activeSortKey={sortKey}\n sortDir={sortDir}\n onSort={onSort}\n >\n {t(\"perpetuals.positions.col.positionValue\")}\n </HeaderCell>\n <HeaderCell\n style={COL_STYLE.entry}\n sortKey=\"entry\"\n activeSortKey={sortKey}\n sortDir={sortDir}\n onSort={onSort}\n >\n {t(\"perpetuals.positions.col.entryPrice\")}\n </HeaderCell>\n <HeaderCell\n style={COL_STYLE.mark}\n sortKey=\"mark\"\n activeSortKey={sortKey}\n sortDir={sortDir}\n onSort={onSort}\n >\n {t(\"perpetuals.positions.col.markPrice\")}\n </HeaderCell>\n <HeaderCell\n style={COL_STYLE.liq}\n sortKey=\"liq\"\n activeSortKey={sortKey}\n sortDir={sortDir}\n onSort={onSort}\n >\n <StyledTooltip\n content={t(\"perpetuals.positions.tooltip.liqPrice\")}\n placement=\"top\"\n delay={200}\n closeDelay={0}\n >\n <span className=\"border-b border-dashed border-default-500/40\">\n <span className=\"hidden sm:inline\">\n {t(\"perpetuals.positions.col.liqPrice\")}\n </span>\n <span className=\"inline sm:hidden\">\n {t(\"perpetuals.positions.col.liqPriceShort\")}\n </span>\n </span>\n </StyledTooltip>\n </HeaderCell>\n <HeaderCell\n style={COL_STYLE.marginPnl}\n sortKey=\"marginPnl\"\n activeSortKey={sortKey}\n sortDir={sortDir}\n onSort={onSort}\n >\n <StyledTooltip\n content={t(\"perpetuals.positions.tooltip.marginPnl\")}\n placement=\"top\"\n delay={200}\n closeDelay={0}\n >\n <span className=\"border-b border-dashed border-default-500/40\">\n {t(\"perpetuals.positions.col.marginPnl\")}\n </span>\n </StyledTooltip>\n </HeaderCell>\n <HeaderCell style={COL_STYLE.tpsl} align=\"center\">\n {t(\"perpetuals.positions.col.tpsl\")}\n </HeaderCell>\n <HeaderCell style={COL_STYLE.close} align=\"end\">\n {t(\"perpetuals.positions.col.close\")}\n </HeaderCell>\n </div>\n );\n\n // Empty state: keep the header for layout context, render a centred\n // \"no positions\" line below.\n if (positions.length === 0) {\n return (\n <div\n className={cn(\n \"flex w-full min-w-0 flex-col overflow-hidden bg-transparent\",\n className,\n )}\n >\n <div className=\"flex flex-1 flex-col overflow-x-auto\">\n <div\n style={{ ...TABLE_MIN_WIDTH, ...HEADER_ROW_STYLE }}\n className=\"flex flex-1 flex-col\"\n >\n {header}\n </div>\n <div\n style={TABLE_MIN_WIDTH}\n className=\"flex flex-1 flex-col items-center justify-center py-6 text-xs text-default-700\"\n >\n {t(\"perpetuals.positions.empty\")}\n </div>\n </div>\n </div>\n );\n }\n\n return (\n <div\n className={cn(\n \"flex w-full min-w-0 flex-col overflow-hidden bg-transparent\",\n className,\n )}\n >\n <div className=\"flex flex-1 flex-col overflow-x-auto\">\n <div\n style={{ ...TABLE_MIN_WIDTH, ...HEADER_ROW_STYLE }}\n className=\"flex flex-1 flex-col\"\n >\n {header}\n </div>\n <div\n style={TABLE_MIN_WIDTH}\n className=\"flex flex-1 flex-col overflow-y-auto\"\n >\n {positions.map((position, index) => (\n <PositionRow\n key={position.symbol}\n position={position}\n striped={index % 2 === 1}\n isClosing={isClosing}\n onClose={onClosePosition}\n />\n ))}\n </div>\n </div>\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Row\n// ---------------------------------------------------------------------------\n\ntype PositionRowProps = {\n position: Position;\n /** Zebra striping — every other row gets a faint background. */\n striped: boolean;\n isClosing: boolean;\n onClose: (position: Position) => void;\n};\n\nfunction PositionRow({\n position,\n striped,\n isClosing,\n onClose,\n}: PositionRowProps) {\n const { t } = useTranslation();\n const tokenSymbol = position.symbol.split(\"-\")[0];\n const isLong = position.side === \"long\";\n const directionLabel = isLong\n ? t(\"perpetuals.positions.long\")\n : t(\"perpetuals.positions.short\");\n const directionColor = isLong ? \"text-bullish\" : \"text-bearish\";\n\n const isProfitable = position.unrealizedPnl >= 0;\n const pnlColor = isProfitable ? \"text-bullish\" : \"text-bearish\";\n\n return (\n <div className={cn(striped ? \"bg-default-100/30\" : \"bg-transparent\")}>\n <div\n style={BODY_ROW_STYLE}\n className=\"flex flex-1 flex-row items-center justify-start px-4\"\n >\n {/* Asset — icon + symbol, hover underline. Click target left\n for a future \"deep-link to chart\" wiring (PR3). */}\n <div\n style={COL_STYLE.asset}\n className=\"flex flex-row items-center justify-start gap-1.5\"\n >\n <img\n alt={tokenSymbol}\n src={`https://app.hyperliquid.xyz/coins/${tokenSymbol}.svg`}\n className=\"rounded-full\"\n style={{ width: 16, height: 16 }}\n onError={(e) => {\n (e.currentTarget as HTMLImageElement).style.display = \"none\";\n }}\n />\n <span className=\"text-xs font-medium text-foreground\">\n {tokenSymbol}\n </span>\n </div>\n\n {/* Position — `Long/Short` (themed) + size + coin */}\n <div\n style={COL_STYLE.position}\n className=\"flex flex-row items-center justify-start gap-1\"\n >\n <span className={cn(\"text-xs font-medium\", directionColor)}>\n {directionLabel}\n </span>\n <span className=\"text-xs font-normal text-default-700\">\n {formatQuantity(position.quantity, position.quantityRaw)}{\" \"}\n {tokenSymbol}\n </span>\n </div>\n\n {/* Position Value */}\n <div\n style={COL_STYLE.value}\n className=\"flex flex-row items-center justify-start\"\n >\n <span className=\"text-xs font-normal text-default-700\">\n {formatUsd2(position.notionalValue)}\n </span>\n </div>\n\n {/* Entry Price */}\n <div\n style={COL_STYLE.entry}\n className=\"flex flex-row items-center justify-start\"\n >\n <span className=\"text-xs font-normal text-default-700\">\n {formatUsdPrice(position.entryPrice)}\n </span>\n </div>\n\n {/* Mark Price */}\n <div\n style={COL_STYLE.mark}\n className=\"flex flex-row items-center justify-start\"\n >\n <span className=\"text-xs font-normal text-default-700\">\n {formatUsdPrice(position.markPrice)}\n </span>\n </div>\n\n {/* Liquidation Price */}\n <div\n style={COL_STYLE.liq}\n className=\"flex flex-row items-center justify-start\"\n >\n <span className=\"text-xs font-normal text-default-700\">\n {formatUsdPrice(position.liquidationPrice)}\n </span>\n </div>\n\n {/* Margin Used (PNL) — single row: `$margin (signedPnl / abs%)`\n with the PnL block tinted bullish/bearish so colour alone\n tells direction; sign + percent stay intelligible without\n colour for accessibility. */}\n <div\n style={COL_STYLE.marginPnl}\n className=\"flex flex-row items-center justify-start gap-1\"\n >\n <span className=\"text-xs font-normal text-default-700\">\n {formatUsd2(position.margin)}\n </span>\n <span className={cn(\"text-xs font-medium\", pnlColor)}>\n ({formatSignedUsd2(position.unrealizedPnl)} /{\" \"}\n {formatPercentAbs(position.unrealizedPnlPercent)})\n </span>\n </div>\n\n {/* TP / SL — derived client-side from the user's reduceOnly\n trigger orders. Layout mirrors Axiom: a 3-cell inline grid\n with TP right-aligned, slash divider, SL left-aligned, so\n the slash always sits at the cell's centre even when one\n side is missing. Picks the closing-side trigger only\n (Long → SELL, Short → BUY) so orphan triggers from a\n previously-closed opposite-direction position never bleed\n into this row.\n `display: grid` + `gridTemplateColumns` is inline because\n arbitrary-value classes (`grid-cols-[1fr_auto_1fr]`) only\n emit CSS when Tailwind scans the source; in `USE_LOCAL_SDK`\n mode the consumer's `@source` globs miss this file. */}\n <div\n style={{\n ...COL_STYLE.tpsl,\n display: \"grid\",\n gridTemplateColumns: \"1fr auto 1fr\",\n alignItems: \"center\",\n }}\n >\n <span className=\"pr-1 text-right text-xs font-normal text-default-700\">\n {position.takeProfitPrice !== undefined\n ? formatUsdPrice(position.takeProfitPrice)\n : \"--\"}\n </span>\n <span className=\"text-xs font-normal text-default-500\">/</span>\n <span className=\"pl-1 text-left text-xs font-normal text-default-700\">\n {position.stopLossPrice !== undefined\n ? formatUsdPrice(position.stopLossPrice)\n : \"--\"}\n </span>\n </div>\n\n {/* Close — single `Market` action in `text-bearish` (theme\n secondary). The Axiom split into `Market` / `Limit` is a\n future expansion: limit-close needs a price input and a\n second mutation path. Tracking as a follow-up. */}\n <div\n style={COL_STYLE.close}\n className=\"flex flex-row items-center justify-end gap-2\"\n >\n <button\n type=\"button\"\n onClick={() => onClose(position)}\n disabled={isClosing}\n className={cn(\n \"text-xs font-medium text-bearish\",\n \"transition-opacity duration-150 ease-in-out\",\n \"hover:opacity-80 disabled:cursor-not-allowed disabled:opacity-50\",\n )}\n >\n {t(\"perpetuals.positions.close.market\")}\n </button>\n </div>\n </div>\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Skeleton / Empty\n// ---------------------------------------------------------------------------\n\n/** Loading skeleton for positions panel */\nexport function PositionsSkeleton() {\n return (\n <div className=\"w-full space-y-4 p-4\">\n <div className=\"h-4 bg-neutral-800 rounded w-full animate-pulse\" />\n <div className=\"h-4 bg-neutral-800 rounded w-full animate-pulse\" />\n <div className=\"h-4 bg-neutral-800 rounded w-full animate-pulse\" />\n </div>\n );\n}\n\n/**\n * Standalone empty-state component. The main `PositionsUI` renders its\n * own empty layout (header + centred message) so this export exists for\n * consumers that wire their own empty state outside the widget.\n */\nexport function PositionsEmpty() {\n return (\n <div className=\"flex h-24 items-center justify-center text-[14px] text-default-700\">\n No open positions\n </div>\n );\n}\n","import { usePositionsScript } from \"./positions.script\";\nimport { PositionsUI, PositionsSkeleton } from \"./positions.ui\";\n\nexport type PositionsWidgetProps = {\n userAddress?: string;\n symbol?: string;\n onCloseSuccess?: () => void;\n onCloseError?: (error: Error) => void;\n className?: string;\n};\n\n/**\n * Positions table widget. Owns no business logic — wires the\n * `usePositionsScript` data layer (sort + close-mutation) to the\n * presentational `PositionsUI`. The host page just provides the\n * connected wallet address and (optionally) a symbol filter; the\n * widget handles everything else (sort state, realtime updates,\n * close-position toasts in the consumer's mutation lifecycle).\n */\nexport function PositionsWidget({\n userAddress,\n symbol,\n onCloseSuccess,\n onCloseError,\n className,\n}: PositionsWidgetProps) {\n const {\n positions,\n isLoading,\n sortKey,\n sortDir,\n onSort,\n handleClosePosition,\n isClosing,\n } = usePositionsScript({\n userAddress,\n symbol,\n onCloseSuccess,\n onCloseError,\n });\n\n if (isLoading) {\n return (\n <div className={className}>\n <PositionsSkeleton />\n </div>\n );\n }\n\n return (\n <PositionsUI\n positions={positions}\n sortKey={sortKey}\n sortDir={sortDir}\n onSort={onSort}\n onClosePosition={handleClosePosition}\n isClosing={isClosing}\n className={className}\n />\n );\n}\n","import { useState, useEffect, useCallback } from \"react\";\nimport { useCancelOrderMutation } from \"../../hooks/useCancelOrderMutation\";\nimport { useOrdersQuery } from \"../../hooks/useOrdersQuery\";\nimport { useUserDataSubscription } from \"../../hooks/useUserDataSubscription\";\nimport type { Order } from \"../../types\";\n\nexport type UseOpenOrdersScriptParams = {\n userAddress?: string;\n symbol?: string;\n onCancelSuccess?: () => void;\n onCancelError?: (error: Error) => void;\n};\n\nexport type UseOpenOrdersScriptResult = {\n orders: Order[];\n isLoading: boolean;\n error: Error | null;\n handleCancelOrder: (order: Order) => Promise<void>;\n isCanceling: boolean;\n};\n\nexport function useOpenOrdersScript({\n userAddress,\n symbol,\n onCancelSuccess,\n onCancelError,\n}: UseOpenOrdersScriptParams): UseOpenOrdersScriptResult {\n const [orders, setOrders] = useState<Order[]>([]);\n\n // Fetch initial orders data\n const {\n data: ordersData,\n isLoading,\n error,\n } = useOrdersQuery({ userAddress, symbol }, { enabled: !!userAddress });\n\n // Subscribe to realtime order updates\n const { data: realtimeOrder } = useUserDataSubscription<Order>({\n type: \"orders\",\n userAddress: userAddress || \"\",\n enabled: !!userAddress,\n });\n\n // Cancel order mutation\n const { mutateAsync: cancelOrder, isPending: isCanceling } =\n useCancelOrderMutation({\n onSuccess: () => {\n onCancelSuccess?.();\n },\n onError: (error) => {\n onCancelError?.(error);\n },\n });\n\n // Initialize orders data\n useEffect(() => {\n if (ordersData?.orders) {\n setOrders(ordersData.orders);\n }\n }, [ordersData]);\n\n // Handle realtime order updates\n useEffect(() => {\n if (realtimeOrder) {\n setOrders((prevOrders) => {\n const existingIndex = prevOrders.findIndex(\n (o) => o.orderId === realtimeOrder.orderId,\n );\n\n // If order is cancelled, filled or rejected, remove from list\n if (\n realtimeOrder.status === \"cancelled\" ||\n realtimeOrder.status === \"filled\" ||\n realtimeOrder.status === \"rejected\"\n ) {\n if (existingIndex !== -1) {\n return prevOrders.filter((_, i) => i !== existingIndex);\n }\n return prevOrders;\n }\n\n // Update existing order\n if (existingIndex !== -1) {\n const newOrders = [...prevOrders];\n newOrders[existingIndex] = realtimeOrder;\n return newOrders;\n }\n\n // Add new order\n return [realtimeOrder, ...prevOrders];\n });\n }\n }, [realtimeOrder]);\n\n // Handle cancel order\n const handleCancelOrder = useCallback(\n async (order: Order) => {\n if (!userAddress) {\n throw new Error(\"User address is required\");\n }\n\n await cancelOrder({\n orderId: order.orderId,\n symbol: order.symbol,\n userAddress,\n });\n },\n [userAddress, cancelOrder],\n );\n\n return {\n orders,\n isLoading,\n error,\n handleCancelOrder,\n isCanceling,\n };\n}\n","import { Button, cn } from \"@liberfi.io/ui\";\nimport type { Order } from \"../../types\";\n\nexport type OpenOrdersUIProps = {\n orders: Order[];\n onCancelOrder: (order: Order) => void;\n isCanceling: boolean;\n};\n\nfunction formatNumber(num: number, decimals: number = 2): string {\n return num.toFixed(decimals);\n}\n\nfunction formatPrice(price: number): string {\n return formatNumber(price, 4);\n}\n\nfunction formatQuantity(quantity: number): string {\n return formatNumber(quantity, 4);\n}\n\nfunction formatTime(timestamp: number): string {\n const date = new Date(timestamp);\n const hours = String(date.getHours()).padStart(2, \"0\");\n const minutes = String(date.getMinutes()).padStart(2, \"0\");\n const seconds = String(date.getSeconds()).padStart(2, \"0\");\n return `${hours}:${minutes}:${seconds}`;\n}\n\nexport function OpenOrdersUI({\n orders,\n onCancelOrder,\n isCanceling,\n}: OpenOrdersUIProps) {\n if (orders.length === 0) {\n return (\n <div\n className=\"flex items-center justify-center h-24\"\n style={{ fontSize: 11, color: \"#b5b5b5\" }}\n >\n No open orders\n </div>\n );\n }\n\n return (\n <div className=\"w-full overflow-x-auto bg-transparent\">\n <table className=\"w-full\" style={{ fontSize: 11 }}>\n <thead>\n <tr style={{ borderBottom: \"1px solid #1c1c1c\" }}>\n <th\n className=\"text-left py-1.5 px-3 font-normal\"\n style={{ fontSize: 11, color: \"#b5b5b5\" }}\n >\n Asset\n </th>\n <th\n className=\"text-left py-1.5 px-3 font-normal\"\n style={{ fontSize: 11, color: \"#b5b5b5\" }}\n >\n Type\n </th>\n <th\n className=\"text-right py-1.5 px-3 font-normal\"\n style={{ fontSize: 11, color: \"#b5b5b5\" }}\n >\n Price\n </th>\n <th\n className=\"text-right py-1.5 px-3 font-normal\"\n style={{ fontSize: 11, color: \"#b5b5b5\" }}\n >\n Amount\n </th>\n <th\n className=\"text-right py-1.5 px-3 font-normal\"\n style={{ fontSize: 11, color: \"#b5b5b5\" }}\n >\n Filled\n </th>\n <th\n className=\"text-right py-1.5 px-3 font-normal\"\n style={{ fontSize: 11, color: \"#b5b5b5\" }}\n >\n Remaining\n </th>\n <th\n className=\"text-right py-1.5 px-3 font-normal\"\n style={{ fontSize: 11, color: \"#b5b5b5\" }}\n >\n Status\n </th>\n <th\n className=\"text-right py-1.5 px-3 font-normal\"\n style={{ fontSize: 11, color: \"#b5b5b5\" }}\n >\n Time\n </th>\n <th\n className=\"text-right py-1.5 px-3 font-normal\"\n style={{ fontSize: 11, color: \"#b5b5b5\" }}\n >\n Action\n </th>\n </tr>\n </thead>\n <tbody>\n {orders.map((order) => {\n return (\n <tr\n key={order.orderId}\n className=\"hover:bg-neutral-900/50\"\n style={{ borderBottom: \"1px solid #1c1c1c\" }}\n >\n {/* Asset */}\n <td className=\"py-1.5 px-3\">\n <div className=\"flex flex-col\">\n <span className=\"font-medium\" style={{ color: \"#ffffff\" }}>\n {order.symbol.split(\"-\")[0]}\n </span>\n <span\n className={cn(\n order.side === \"long\" ? \"text-bullish\" : \"text-bearish\",\n )}\n >\n {order.side.toUpperCase()}\n {order.leverage ? ` ${order.leverage}x` : \"\"}\n </span>\n </div>\n </td>\n\n {/* Type */}\n <td\n className=\"py-1.5 px-3 capitalize\"\n style={{ color: \"#ffffff\" }}\n >\n {order.orderType}\n </td>\n\n {/* Price */}\n <td\n className=\"py-1.5 px-3 text-right\"\n style={{ color: \"#ffffff\" }}\n >\n {order.orderType === \"market\" ? (\n <span style={{ color: \"#b5b5b5\" }}>Market</span>\n ) : (\n `$${formatPrice(order.price)}`\n )}\n </td>\n\n {/* Amount */}\n <td\n className=\"py-1.5 px-3 text-right\"\n style={{ color: \"#ffffff\" }}\n >\n {formatQuantity(order.quantity)}\n </td>\n\n {/* Filled */}\n <td\n className=\"py-1.5 px-3 text-right\"\n style={{ color: \"#ffffff\" }}\n >\n {formatQuantity(order.filledQuantity)}\n </td>\n\n {/* Remaining */}\n <td\n className=\"py-1.5 px-3 text-right\"\n style={{ color: \"#ffffff\" }}\n >\n {formatQuantity(order.remainingQuantity)}\n </td>\n\n {/* Status */}\n <td className=\"py-1.5 px-3 text-right\">\n <span\n className={cn(\n \"px-2 py-0.5 rounded\",\n \"text-[11px]\",\n order.status === \"pending\" &&\n \"bg-yellow-600/20 text-yellow-500\",\n order.status === \"partially_filled\" &&\n \"bg-blue-600/20 text-blue-500\",\n order.status === \"filled\" &&\n \"bg-green-600/20 text-green-500\",\n order.status === \"cancelled\" &&\n \"bg-neutral-600/20 text-neutral-400\",\n order.status === \"rejected\" &&\n \"bg-red-600/20 text-red-500\",\n )}\n >\n {order.status.replace(\"_\", \" \")}\n </span>\n </td>\n\n {/* Time */}\n <td\n className=\"py-1.5 px-3 text-right\"\n style={{ color: \"#b5b5b5\" }}\n >\n {formatTime(order.timestamp)}\n </td>\n\n {/* Action */}\n <td className=\"py-1.5 px-3 text-right\">\n {order.status === \"pending\" ||\n order.status === \"partially_filled\" ? (\n <Button\n size=\"sm\"\n onClick={() => onCancelOrder(order)}\n isLoading={isCanceling}\n className=\"bg-red-600 hover:bg-red-700 text-white text-xs px-3 py-1\"\n >\n Cancel\n </Button>\n ) : (\n <span className=\"text-[11px]\" style={{ color: \"#6b6d7a\" }}>\n -\n </span>\n )}\n </td>\n </tr>\n );\n })}\n </tbody>\n </table>\n </div>\n );\n}\n\n// Loading skeleton component\nexport function OpenOrdersSkeleton() {\n return (\n <div className=\"w-full space-y-4 p-4\">\n <div className=\"h-4 bg-neutral-800 rounded w-full animate-pulse\" />\n <div className=\"h-4 bg-neutral-800 rounded w-full animate-pulse\" />\n <div className=\"h-4 bg-neutral-800 rounded w-full animate-pulse\" />\n </div>\n );\n}\n\n// Empty state component\nexport function OpenOrdersEmpty() {\n return (\n <div\n className=\"flex items-center justify-center h-24\"\n style={{ fontSize: 11, color: \"#b5b5b5\" }}\n >\n No open orders\n </div>\n );\n}\n","import { useOpenOrdersScript } from \"./open-orders.script\";\nimport {\n OpenOrdersUI,\n OpenOrdersSkeleton,\n OpenOrdersEmpty,\n} from \"./open-orders.ui\";\n\nexport type OpenOrdersWidgetProps = {\n userAddress?: string;\n symbol?: string;\n onCancelSuccess?: () => void;\n onCancelError?: (error: Error) => void;\n className?: string;\n};\n\nexport function OpenOrdersWidget({\n userAddress,\n symbol,\n onCancelSuccess,\n onCancelError,\n className,\n}: OpenOrdersWidgetProps) {\n const { orders, isLoading, handleCancelOrder, isCanceling } =\n useOpenOrdersScript({\n userAddress,\n symbol,\n onCancelSuccess,\n onCancelError,\n });\n\n if (isLoading) {\n return (\n <div className={className}>\n <OpenOrdersSkeleton />\n </div>\n );\n }\n\n if (orders.length === 0) {\n return (\n <div className={className}>\n <OpenOrdersEmpty />\n </div>\n );\n }\n\n return (\n <div className={className}>\n <OpenOrdersUI\n orders={orders}\n onCancelOrder={handleCancelOrder}\n isCanceling={isCanceling}\n />\n </div>\n );\n}\n","import { useState, useEffect } from \"react\";\nimport { useTradesQuery } from \"../../hooks/useTradesQuery\";\nimport type { TradeHistory } from \"../../types\";\n\nexport type TimeRange = \"today\" | \"7d\" | \"30d\" | \"all\";\n\nexport type UseTradeHistoryScriptParams = {\n userAddress?: string;\n symbol?: string;\n initialTimeRange?: TimeRange;\n pageSize?: number;\n};\n\nexport type UseTradeHistoryScriptResult = {\n trades: TradeHistory[];\n isLoading: boolean;\n error: Error | null;\n timeRange: TimeRange;\n setTimeRange: (range: TimeRange) => void;\n currentPage: number;\n totalPages: number;\n goToNextPage: () => void;\n goToPreviousPage: () => void;\n goToPage: (page: number) => void;\n};\n\nfunction getTimeRangeInMs(range: TimeRange): {\n startTime?: number;\n endTime?: number;\n} {\n const now = Date.now();\n const endTime = now;\n\n switch (range) {\n case \"today\":\n const today = new Date();\n today.setHours(0, 0, 0, 0);\n return { startTime: today.getTime(), endTime };\n case \"7d\":\n return { startTime: now - 7 * 24 * 60 * 60 * 1000, endTime };\n case \"30d\":\n return { startTime: now - 30 * 24 * 60 * 60 * 1000, endTime };\n case \"all\":\n default:\n return {};\n }\n}\n\nexport function useTradeHistoryScript({\n userAddress,\n symbol,\n initialTimeRange = \"7d\",\n pageSize = 50,\n}: UseTradeHistoryScriptParams): UseTradeHistoryScriptResult {\n const [timeRange, setTimeRange] = useState<TimeRange>(initialTimeRange);\n const [currentPage, setCurrentPage] = useState(1);\n const [allTrades, setAllTrades] = useState<TradeHistory[]>([]);\n\n const { startTime, endTime } = getTimeRangeInMs(timeRange);\n\n // Fetch trades with time range filter\n const {\n data: tradesData,\n isLoading,\n error,\n } = useTradesQuery(\n {\n userAddress,\n symbol,\n startTime,\n endTime,\n limit: 1000, // Fetch more data for client-side pagination\n },\n { enabled: !!userAddress },\n );\n\n // Update all trades when data changes\n useEffect(() => {\n if (tradesData?.trades) {\n setAllTrades(tradesData.trades);\n setCurrentPage(1); // Reset to first page when data changes\n }\n }, [tradesData]);\n\n // Reset page when time range changes\n useEffect(() => {\n setCurrentPage(1);\n }, [timeRange]);\n\n // Calculate pagination\n const totalPages = Math.ceil(allTrades.length / pageSize);\n const startIndex = (currentPage - 1) * pageSize;\n const endIndex = startIndex + pageSize;\n const trades = allTrades.slice(startIndex, endIndex);\n\n const goToNextPage = () => {\n if (currentPage < totalPages) {\n setCurrentPage(currentPage + 1);\n }\n };\n\n const goToPreviousPage = () => {\n if (currentPage > 1) {\n setCurrentPage(currentPage - 1);\n }\n };\n\n const goToPage = (page: number) => {\n if (page >= 1 && page <= totalPages) {\n setCurrentPage(page);\n }\n };\n\n return {\n trades,\n isLoading,\n error,\n timeRange,\n setTimeRange,\n currentPage,\n totalPages,\n goToNextPage,\n goToPreviousPage,\n goToPage,\n };\n}\n","import { Button, cn } from \"@liberfi.io/ui\";\nimport type { TradeHistory } from \"../../types\";\nimport type { TimeRange } from \"./trade-history.script\";\n\nexport type TradeHistoryUIProps = {\n trades: TradeHistory[];\n timeRange: TimeRange;\n onTimeRangeChange: (range: TimeRange) => void;\n currentPage: number;\n totalPages: number;\n onNextPage: () => void;\n onPreviousPage: () => void;\n onGoToPage: (page: number) => void;\n};\n\nfunction formatNumber(num: number, decimals: number = 2): string {\n return num.toFixed(decimals);\n}\n\nfunction formatPrice(price: number): string {\n return formatNumber(price, 4);\n}\n\nfunction formatQuantity(quantity: number): string {\n return formatNumber(quantity, 4);\n}\n\nfunction formatDateTime(timestamp: number): string {\n const date = new Date(timestamp);\n const month = String(date.getMonth() + 1).padStart(2, \"0\");\n const day = String(date.getDate()).padStart(2, \"0\");\n const hours = String(date.getHours()).padStart(2, \"0\");\n const minutes = String(date.getMinutes()).padStart(2, \"0\");\n const seconds = String(date.getSeconds()).padStart(2, \"0\");\n return `${month}/${day} ${hours}:${minutes}:${seconds}`;\n}\n\nconst TIME_RANGE_OPTIONS: { label: string; value: TimeRange }[] = [\n { label: \"Today\", value: \"today\" },\n { label: \"7 Days\", value: \"7d\" },\n { label: \"30 Days\", value: \"30d\" },\n { label: \"All\", value: \"all\" },\n];\n\nexport function TradeHistoryUI({\n trades,\n timeRange,\n onTimeRangeChange,\n currentPage,\n totalPages,\n onNextPage,\n onPreviousPage,\n onGoToPage,\n}: TradeHistoryUIProps) {\n return (\n <div className=\"w-full flex flex-col gap-4\">\n {/* Time range filter */}\n <div className=\"flex gap-2\">\n {TIME_RANGE_OPTIONS.map((option) => {\n const selected = timeRange === option.value;\n return (\n <button\n key={option.value}\n type=\"button\"\n className={cn(\n \"rounded px-3 transition-colors\",\n !selected && \"hover:bg-[#1A1A1A]\",\n )}\n style={{\n height: 24,\n fontSize: 11,\n border: \"1px solid #1c1c1c\",\n backgroundColor: selected ? \"#1c1c1c\" : \"transparent\",\n color: selected ? \"#ffffff\" : \"#b5b5b5\",\n }}\n onClick={() => onTimeRangeChange(option.value)}\n >\n {option.label}\n </button>\n );\n })}\n </div>\n\n {/* Trade history table */}\n {trades.length === 0 ? (\n <div\n className=\"flex items-center justify-center h-24\"\n style={{ fontSize: 11, color: \"#b5b5b5\" }}\n >\n No trade history\n </div>\n ) : (\n <>\n <div className=\"w-full overflow-x-auto bg-transparent\">\n <table className=\"w-full\" style={{ fontSize: 11 }}>\n <thead>\n <tr style={{ borderBottom: \"1px solid #1c1c1c\" }}>\n <th\n className=\"text-left py-1.5 px-3 font-normal\"\n style={{ fontSize: 11, color: \"#b5b5b5\" }}\n >\n Asset\n </th>\n <th\n className=\"text-left py-1.5 px-3 font-normal\"\n style={{ fontSize: 11, color: \"#b5b5b5\" }}\n >\n Side\n </th>\n <th\n className=\"text-right py-1.5 px-3 font-normal\"\n style={{ fontSize: 11, color: \"#b5b5b5\" }}\n >\n Price\n </th>\n <th\n className=\"text-right py-1.5 px-3 font-normal\"\n style={{ fontSize: 11, color: \"#b5b5b5\" }}\n >\n Quantity\n </th>\n <th\n className=\"text-right py-1.5 px-3 font-normal\"\n style={{ fontSize: 11, color: \"#b5b5b5\" }}\n >\n Fee\n </th>\n <th\n className=\"text-center py-1.5 px-3 font-normal\"\n style={{ fontSize: 11, color: \"#b5b5b5\" }}\n >\n Maker/Taker\n </th>\n <th\n className=\"text-right py-1.5 px-3 font-normal\"\n style={{ fontSize: 11, color: \"#b5b5b5\" }}\n >\n Time\n </th>\n </tr>\n </thead>\n <tbody>\n {trades.map((trade) => (\n <tr\n key={trade.tradeId}\n className=\"hover:bg-neutral-900/50\"\n style={{ borderBottom: \"1px solid #1c1c1c\" }}\n >\n {/* Asset */}\n <td\n className=\"py-1.5 px-3 font-medium\"\n style={{ color: \"#ffffff\" }}\n >\n {trade.symbol.split(\"-\")[0]}\n </td>\n\n {/* Side */}\n <td className=\"py-1.5 px-3\">\n <span\n className={cn(\n \"px-2 py-0.5 rounded text-[11px]\",\n trade.side === \"long\"\n ? \"bg-bullish/20 text-bullish\"\n : \"bg-bearish/20 text-bearish\",\n )}\n >\n {trade.side.toUpperCase()}\n </span>\n </td>\n\n {/* Price */}\n <td\n className=\"py-1.5 px-3 text-right\"\n style={{ color: \"#ffffff\" }}\n >\n ${formatPrice(trade.price)}\n </td>\n\n {/* Quantity */}\n <td\n className=\"py-1.5 px-3 text-right\"\n style={{ color: \"#ffffff\" }}\n >\n {formatQuantity(trade.quantity)}\n </td>\n\n {/* Fee */}\n <td\n className=\"py-1.5 px-3 text-right\"\n style={{ color: \"#ffffff\" }}\n >\n {formatNumber(trade.fee, 4)} {trade.feeCurrency}\n </td>\n\n {/* Maker/Taker */}\n <td className=\"py-1.5 px-3 text-center\">\n <span\n className={cn(\n \"px-2 py-0.5 rounded text-[11px]\",\n trade.isMaker\n ? \"bg-blue-600/20 text-blue-500\"\n : \"bg-purple-600/20 text-purple-500\",\n )}\n >\n {trade.isMaker ? \"Maker\" : \"Taker\"}\n </span>\n </td>\n\n {/* Time */}\n <td\n className=\"py-1.5 px-3 text-right\"\n style={{ color: \"#b5b5b5\" }}\n >\n {formatDateTime(trade.timestamp)}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n\n {/* Pagination */}\n {totalPages > 1 && (\n <div className=\"flex items-center justify-between\">\n <div className=\"text-sm text-neutral-400\">\n Page {currentPage} of {totalPages}\n </div>\n <div className=\"flex gap-2\">\n <Button\n size=\"sm\"\n onClick={onPreviousPage}\n disabled={currentPage === 1}\n className=\"bg-neutral-800 hover:bg-neutral-700 text-white disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n Previous\n </Button>\n {/* Page numbers */}\n <div className=\"flex gap-1\">\n {Array.from({ length: Math.min(5, totalPages) }, (_, i) => {\n let pageNum: number;\n if (totalPages <= 5) {\n pageNum = i + 1;\n } else if (currentPage <= 3) {\n pageNum = i + 1;\n } else if (currentPage >= totalPages - 2) {\n pageNum = totalPages - 4 + i;\n } else {\n pageNum = currentPage - 2 + i;\n }\n\n return (\n <button\n key={pageNum}\n type=\"button\"\n className={cn(\n \"w-8 h-8 text-sm rounded transition-colors\",\n currentPage === pageNum\n ? \"bg-neutral-700 text-white\"\n : \"text-neutral-400 hover:bg-neutral-800 hover:text-white\",\n )}\n onClick={() => onGoToPage(pageNum)}\n >\n {pageNum}\n </button>\n );\n })}\n </div>\n <Button\n size=\"sm\"\n onClick={onNextPage}\n disabled={currentPage === totalPages}\n className=\"bg-neutral-800 hover:bg-neutral-700 text-white disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n Next\n </Button>\n </div>\n </div>\n )}\n </>\n )}\n </div>\n );\n}\n\n// Loading skeleton component\nexport function TradeHistorySkeleton() {\n return (\n <div className=\"w-full space-y-4 p-4\">\n <div className=\"h-4 bg-neutral-800 rounded w-full animate-pulse\" />\n <div className=\"h-4 bg-neutral-800 rounded w-full animate-pulse\" />\n <div className=\"h-4 bg-neutral-800 rounded w-full animate-pulse\" />\n </div>\n );\n}\n\n// Empty state component\nexport function TradeHistoryEmpty() {\n return (\n <div\n className=\"flex items-center justify-center h-24\"\n style={{ fontSize: 11, color: \"#b5b5b5\" }}\n >\n No trade history\n </div>\n );\n}\n","import { useTradeHistoryScript } from \"./trade-history.script\";\nimport type { TimeRange } from \"./trade-history.script\";\nimport {\n TradeHistoryUI,\n TradeHistorySkeleton,\n TradeHistoryEmpty,\n} from \"./trade-history.ui\";\n\nexport type TradeHistoryWidgetProps = {\n userAddress?: string;\n symbol?: string;\n initialTimeRange?: TimeRange;\n pageSize?: number;\n className?: string;\n};\n\nexport function TradeHistoryWidget({\n userAddress,\n symbol,\n initialTimeRange = \"7d\",\n pageSize = 50,\n className,\n}: TradeHistoryWidgetProps) {\n const {\n trades,\n isLoading,\n timeRange,\n setTimeRange,\n currentPage,\n totalPages,\n goToNextPage,\n goToPreviousPage,\n goToPage,\n } = useTradeHistoryScript({\n userAddress,\n symbol,\n initialTimeRange,\n pageSize,\n });\n\n if (isLoading) {\n return (\n <div className={className}>\n <TradeHistorySkeleton />\n </div>\n );\n }\n\n if (trades.length === 0) {\n return (\n <div className={className}>\n <TradeHistoryEmpty />\n </div>\n );\n }\n\n return (\n <div className={className}>\n <TradeHistoryUI\n trades={trades}\n timeRange={timeRange}\n onTimeRangeChange={setTimeRange}\n currentPage={currentPage}\n totalPages={totalPages}\n onNextPage={goToNextPage}\n onPreviousPage={goToPreviousPage}\n onGoToPage={goToPage}\n />\n </div>\n );\n}\n","/**\n * Tiny number-formatting helpers shared by the deposit UI.\n *\n * We use plain `bigint` arithmetic here — never `Number(...)` on a\n * lamport / microUSDC value — so we never silently lose precision on\n * deposits that exceed `Number.MAX_SAFE_INTEGER` lamports.\n */\n\nconst LAMPORTS_PER_SOL = 1_000_000_000n;\n\n/**\n * Hyperliquid credits perp USDC at 8-decimal granularity (NOT the 6\n * decimals used by ERC-20 USDC on Arbitrum). Relay's `currencyOut.amount`\n * for a Hyperliquid bridge quote is therefore expressed in HL perp units\n * — divide by 1e8 to get the human-readable USDC amount.\n */\nexport const HL_USDC_DECIMALS = 8;\nconst HL_USDC_DIVISOR = 10n ** BigInt(HL_USDC_DECIMALS);\n\n/**\n * Convert a lamport amount (string bigint) to a SOL-denominated string\n * with `precision` decimals and trailing zeros stripped.\n */\nexport function lamportsToSol(value: string, precision = 4): string {\n if (!value) return \"0\";\n let n: bigint;\n try {\n n = BigInt(value);\n } catch {\n return \"0\";\n }\n return divToFixed(n, LAMPORTS_PER_SOL, precision);\n}\n\n/**\n * Convert a raw Hyperliquid USDC amount (8 decimals) to a USDC display\n * string with `precision` decimals and trailing zeros stripped.\n *\n * This is the unit returned by the perpetuals-server `/deposits/quote`\n * endpoint in `breakdown.expectedOutputUSDC` — it mirrors Hyperliquid's\n * internal perp-account precision, NOT the 6-decimal USDC token on\n * Arbitrum.\n */\nexport function hlUsdcRawToUsdc(\n value: string | undefined,\n precision = 2,\n): string {\n if (!value) return \"0\";\n let n: bigint;\n try {\n n = BigInt(value);\n } catch {\n return \"0\";\n }\n return divToFixed(n, HL_USDC_DIVISOR, precision);\n}\n\n/**\n * @deprecated Use {@link hlUsdcRawToUsdc} instead. The previous name\n * implied a 6-decimal microUSDC unit, but the Hyperliquid bridge actually\n * returns amounts at 8-decimal precision. Kept as a thin alias to avoid\n * a hard break for downstream callers; remove after consumers migrate.\n */\nexport const microUsdcToUsdc = hlUsdcRawToUsdc;\n\n/** Convert a SOL-denominated decimal string to a lamport `string` (bigint). */\nexport function solToLamports(value: string): string {\n if (!value) return \"0\";\n const [whole, frac = \"\"] = value.replace(/[\\s,]/g, \"\").split(\".\");\n if (!/^\\d*$/.test(whole) || !/^\\d*$/.test(frac)) return \"0\";\n // Pad / truncate the fractional component to 9 digits to match SOL.\n const fracPadded = (frac + \"000000000\").slice(0, 9);\n const combined = `${whole || \"0\"}${fracPadded}`.replace(/^0+(?=\\d)/, \"\");\n return combined === \"\" ? \"0\" : combined;\n}\n\nfunction divToFixed(\n numerator: bigint,\n denominator: bigint,\n precision: number,\n): string {\n const negative = numerator < 0n;\n const abs = negative ? -numerator : numerator;\n let whole = abs / denominator;\n const remainder = abs % denominator;\n if (precision <= 0) {\n // Round to nearest integer when precision is 0.\n if (remainder * 2n >= denominator) whole += 1n;\n return `${negative ? \"-\" : \"\"}${whole.toString()}`;\n }\n const scale = 10n ** BigInt(precision);\n let scaledRemainder = (remainder * scale + denominator / 2n) / denominator;\n // Carry over to the whole part when half-rounding pushed the fractional\n // component to or above `scale` (e.g. 0.999999 with precision 2 -> 1.00).\n if (scaledRemainder >= scale) {\n whole += 1n;\n scaledRemainder = 0n;\n }\n let frac = scaledRemainder.toString().padStart(precision, \"0\");\n // Trim trailing zeros for nicer display.\n frac = frac.replace(/0+$/, \"\");\n if (!frac) return `${negative ? \"-\" : \"\"}${whole.toString()}`;\n return `${negative ? \"-\" : \"\"}${whole.toString()}.${frac}`;\n}\n\n/** Returns whole-second countdown until `expiresAtMs`. Negative -> 0. */\nexport function secondsUntil(\n expiresAtMs: number,\n nowMs: number = Date.now(),\n): number {\n return Math.max(0, Math.floor((expiresAtMs - nowMs) / 1000));\n}\n\n/** Truncate an address to `head…tail` for display. */\nexport function shortAddress(addr: string, head = 6, tail = 4): string {\n if (!addr) return \"\";\n if (addr.length <= head + tail + 1) return addr;\n return `${addr.slice(0, head)}…${addr.slice(-tail)}`;\n}\n","import { useEffect, useState } from \"react\";\nimport { useTranslation } from \"@liberfi.io/i18n\";\nimport {\n Button,\n Modal,\n ModalBody,\n ModalContent,\n ModalFooter,\n ModalHeader,\n Spinner,\n} from \"@liberfi.io/ui\";\nimport type {\n DepositBreakdown,\n DepositQuoteResponse,\n} from \"../../client/liberfi/deposit-types\";\nimport { lamportsToSol, hlUsdcRawToUsdc, secondsUntil } from \"./format\";\n\n/**\n * Pure presentational confirm modal for the deposit flow.\n *\n * Owns no fetching or signing — it just renders the breakdown and\n * fires `onConfirm` / `onCancel`. The expiry countdown ticks locally\n * via setInterval and re-renders once a second; when it hits 0 the\n * `onExpire` callback fires (the parent should refetch the quote).\n */\nexport interface DepositConfirmUIProps {\n isOpen: boolean;\n /** Quote currently being shown to the user. Required when `isOpen`. */\n quote: DepositQuoteResponse | undefined;\n /** True while `/submit` (or wallet sign) is in flight. Disables the CTA. */\n isExecuting?: boolean;\n /** True when the displayed quote has already expired. */\n isExpired?: boolean;\n onConfirm: () => void;\n onCancel: () => void;\n /** Fires when the local countdown reaches zero. */\n onExpire?: () => void;\n /** Optional inline error to surface inside the modal. */\n error?: string;\n}\n\nexport function DepositConfirmUI({\n isOpen,\n quote,\n isExecuting,\n isExpired,\n onConfirm,\n onCancel,\n onExpire,\n error,\n}: DepositConfirmUIProps) {\n const { t } = useTranslation();\n\n const expiresAtMs = quote ? Date.parse(quote.expiresAt) : 0;\n const [secondsLeft, setSecondsLeft] = useState(() =>\n expiresAtMs ? secondsUntil(expiresAtMs) : 0,\n );\n\n useEffect(() => {\n if (!isOpen || !expiresAtMs) return;\n setSecondsLeft(secondsUntil(expiresAtMs));\n const id = setInterval(() => {\n const remaining = secondsUntil(expiresAtMs);\n setSecondsLeft(remaining);\n if (remaining === 0) {\n onExpire?.();\n clearInterval(id);\n }\n }, 1000);\n return () => clearInterval(id);\n }, [isOpen, expiresAtMs, onExpire]);\n\n return (\n <Modal\n isOpen={isOpen}\n onOpenChange={(next) => !next && onCancel()}\n hideCloseButton\n backdrop=\"blur\"\n >\n <ModalContent className=\"bg-content2 rounded-lg\">\n <ModalHeader>{t(\"perpDeposit.confirm.title\")}</ModalHeader>\n <ModalBody>\n {!quote ? (\n <div className=\"flex h-32 items-center justify-center\">\n <Spinner />\n </div>\n ) : (\n <BreakdownSummary breakdown={quote.breakdown} />\n )}\n\n {quote && !isExpired && (\n <div className=\"text-default-500 mt-4 text-xs\">\n {t(\"perpDeposit.confirm.expiresIn\", { seconds: secondsLeft })}\n </div>\n )}\n {isExpired && (\n <div className=\"text-warning-500 mt-4 text-xs\">\n {t(\"perpDeposit.confirm.expired\")}\n </div>\n )}\n {error && <div className=\"text-danger mt-4 text-xs\">{error}</div>}\n </ModalBody>\n <ModalFooter className=\"flex justify-between gap-2\">\n <Button\n variant=\"flat\"\n color=\"default\"\n onPress={onCancel}\n isDisabled={isExecuting}\n >\n {t(\"perpDeposit.confirm.cancel\")}\n </Button>\n <Button\n color=\"primary\"\n onPress={onConfirm}\n isDisabled={!quote || isExecuting || isExpired}\n isLoading={isExecuting}\n >\n {t(\"perpDeposit.confirm.cta\")}\n </Button>\n </ModalFooter>\n </ModalContent>\n </Modal>\n );\n}\n\ninterface BreakdownSummaryProps {\n breakdown: DepositBreakdown;\n}\n\nfunction BreakdownSummary({ breakdown }: BreakdownSummaryProps) {\n const { t } = useTranslation();\n return (\n <dl className=\"flex flex-col gap-2 text-sm\">\n <Row\n label={t(\"perpDeposit.confirm.send\")}\n value={`${lamportsToSol(breakdown.grossLamports)} SOL`}\n />\n <Row\n label={t(\"perpDeposit.confirm.receive\")}\n value={`${hlUsdcRawToUsdc(breakdown.expectedOutputUSDC)} USDC`}\n highlight\n />\n <Row\n label={t(\"perpDeposit.confirm.platformFee\")}\n value={`${lamportsToSol(breakdown.platformFeeLamports, 6)} SOL`}\n muted\n />\n <Row\n label={t(\"perpDeposit.confirm.relayFee\")}\n value={`${lamportsToSol(breakdown.relayDepositLamports, 6)} SOL`}\n muted\n />\n </dl>\n );\n}\n\ninterface RowProps {\n label: string;\n value: string;\n highlight?: boolean;\n muted?: boolean;\n}\n\nfunction Row({ label, value, highlight, muted }: RowProps) {\n return (\n <div className=\"flex items-center justify-between\">\n <dt className=\"text-default-500\">{label}</dt>\n <dd\n className={\n highlight\n ? \"text-foreground text-base font-semibold\"\n : muted\n ? \"text-default-500 text-xs\"\n : \"text-foreground\"\n }\n >\n {value}\n </dd>\n </div>\n );\n}\n","import { useTranslation } from \"@liberfi.io/i18n\";\nimport { Button, Input, cn } from \"@liberfi.io/ui\";\n\n/**\n * Pure presentational form for collecting the deposit amount + the\n * Hyperliquid recipient address.\n *\n * No data fetching, no state — every input is controlled from above.\n * Lets the host app decide when to show the wallet's connected SOL\n * balance (or omit it entirely).\n */\nexport interface DepositFormUIProps {\n amount: string;\n onAmountChange: (value: string) => void;\n recipient: string;\n onRecipientChange: (value: string) => void;\n /** Optional: shown as the \"Balance: …\" hint above the amount input. */\n balanceSol?: string;\n /** Disables every interactive control (e.g. while quoting). */\n disabled?: boolean;\n /** Inline error to render under the amount input. */\n amountError?: string;\n /** Inline error to render under the recipient input. */\n recipientError?: string;\n /** Click handler for \"Max\" — only rendered when `balanceSol` is set. */\n onMax?: () => void;\n className?: string;\n}\n\nexport function DepositFormUI({\n amount,\n onAmountChange,\n recipient,\n onRecipientChange,\n balanceSol,\n disabled,\n amountError,\n recipientError,\n onMax,\n className,\n}: DepositFormUIProps) {\n const { t } = useTranslation();\n return (\n <div className={cn(\"flex flex-col gap-4\", className)}>\n <div>\n <div className=\"flex items-center justify-between mb-1.5\">\n <label\n htmlFor=\"perp-deposit-amount\"\n className=\"text-sm font-medium text-foreground\"\n >\n {t(\"perpDeposit.amount\")}\n </label>\n {balanceSol && (\n <span className=\"text-xs text-default-500\">\n {t(\"perpDeposit.amount.balance\", { balance: balanceSol })}\n </span>\n )}\n </div>\n <div className=\"relative\">\n <Input\n id=\"perp-deposit-amount\"\n type=\"text\"\n inputMode=\"decimal\"\n placeholder={t(\"perpDeposit.amount.placeholder\")}\n value={amount}\n onValueChange={onAmountChange}\n isDisabled={disabled}\n isInvalid={Boolean(amountError)}\n errorMessage={amountError}\n endContent={\n <div className=\"flex items-center gap-2\">\n <span className=\"text-default-500 text-sm\">\n {t(\"perpDeposit.amount.unit\")}\n </span>\n {balanceSol && onMax && (\n <Button\n size=\"sm\"\n variant=\"flat\"\n color=\"primary\"\n onPress={onMax}\n isDisabled={disabled}\n >\n {t(\"perpDeposit.amount.max\")}\n </Button>\n )}\n </div>\n }\n />\n </div>\n </div>\n\n <div>\n <label\n htmlFor=\"perp-deposit-recipient\"\n className=\"text-sm font-medium text-foreground mb-1.5 block\"\n >\n {t(\"perpDeposit.recipient\")}\n </label>\n <Input\n id=\"perp-deposit-recipient\"\n type=\"text\"\n placeholder={t(\"perpDeposit.recipient.placeholder\")}\n value={recipient}\n onValueChange={onRecipientChange}\n isDisabled={disabled}\n isInvalid={Boolean(recipientError)}\n errorMessage={recipientError}\n autoComplete=\"off\"\n spellCheck=\"false\"\n />\n </div>\n </div>\n );\n}\n","import { useTranslation } from \"@liberfi.io/i18n\";\nimport { ModalContent, StyledModal, XCloseIcon, cn } from \"@liberfi.io/ui\";\nimport type { DepositPhase } from \"../../client/liberfi/deposit-state-machine\";\nimport type { DepositStatusResponse } from \"../../client/liberfi/deposit-types\";\nimport { shortAddress } from \"./format\";\n\n/**\n * Polished progress / result panel for the SOL → Hyperliquid USDC\n * deposit flow.\n *\n * Visual design intentionally mirrors the swap-style deposit form\n * modal (dark surface, 14 px radius, accent-color spinner / icons,\n * pill-style transaction links) so the in-flight, success and failure\n * states all feel like the same product surface rather than a generic\n * HeroUI dialog.\n *\n * Renders one of four visual states based on the FSM phase:\n * - in-progress (broadcasting / submitted / tracking)\n * - succeeded\n * - refunded\n * - failed\n *\n * Explorer URLs are caller-provided so the SDK never has to know which\n * RPC / explorer the host wants (Solscan vs Solana Beach, etc.).\n */\nexport interface DepositStatusUIProps {\n isOpen: boolean;\n /** The current FSM phase — drives the visual treatment. */\n phase: DepositPhase;\n /** Backend status record (may be unavailable on first frame). */\n status?: DepositStatusResponse;\n /** Optional Solana explorer URL (caller decides the network). */\n solanaExplorerUrl?: string;\n /** Optional Hyperliquid explorer URL. */\n hyperliquidExplorerUrl?: string;\n /** \"Try again\" handler — only rendered when `phase === \"failed\"`. */\n onRetry?: () => void;\n onClose: () => void;\n /** Optional override for the human-readable message. */\n errorMessage?: string;\n}\n\ntype Variant = \"progress\" | \"success\" | \"warning\" | \"error\";\n\nconst ACCENT = \"#C7FF2E\";\n\nexport function DepositStatusUI({\n isOpen,\n phase,\n status,\n solanaExplorerUrl,\n hyperliquidExplorerUrl,\n onRetry,\n onClose,\n errorMessage,\n}: DepositStatusUIProps) {\n const { t } = useTranslation();\n\n const variant = phaseToVariant(phase);\n const message = ((): string => {\n if (phase === \"failed\") {\n if (errorMessage) return errorMessage;\n if (status?.lastError?.message) {\n return t(\"perpDeposit.status.failed\", {\n message: status.lastError.message,\n });\n }\n return t(\"perpDeposit.status.failed\", { message: \"\" });\n }\n if (phase === \"succeeded\") return t(\"perpDeposit.status.settled\");\n if (phase === \"refunded\") return t(\"perpDeposit.status.refunded\");\n if (status?.status === \"broadcasted\")\n return t(\"perpDeposit.status.broadcasted\");\n if (status?.status === \"relay_waiting\")\n return t(\"perpDeposit.status.relay_waiting\");\n if (status?.status === \"relay_pending\")\n return t(\"perpDeposit.status.relay_pending\");\n if (status?.status === \"stuck\") return t(\"perpDeposit.status.stuck\");\n return t(\"perpDeposit.status.broadcasted\");\n })();\n\n const showRetry = phase === \"failed\" && !!onRetry;\n\n return (\n <StyledModal\n isOpen={isOpen}\n onOpenChange={(next) => !next && onClose()}\n size=\"md\"\n hideCloseButton\n backdrop=\"blur\"\n classNames={{\n base: \"!bg-[#18181b] !rounded-[14px] !border !border-[rgba(39,39,42,1)] !shadow-[0_25px_50px_-12px_rgba(0,0,0,0.5)] max-w-[420px]\",\n body: \"!p-0\",\n }}\n >\n <ModalContent>\n <div className=\"flex flex-col\">\n {/* Header */}\n <div className=\"flex items-start justify-between px-5 pt-5 pb-2\">\n <div className=\"flex items-center gap-2.5\">\n <h3 className=\"text-base font-semibold text-white\">\n {t(\"perpDeposit.status.title\")}\n </h3>\n </div>\n <button\n type=\"button\"\n onClick={onClose}\n className=\"cursor-pointer p-1 rounded-[10px] hover:bg-[rgba(39,39,42,0.5)] text-zinc-400 hover:text-white transition-colors\"\n aria-label={t(\"perpDeposit.status.close\")}\n >\n <XCloseIcon width={16} height={16} />\n </button>\n </div>\n\n {/* Body */}\n <div className=\"px-5 pb-3 pt-2\">\n <div className=\"rounded-[12px] bg-[#0a0a0b] border border-[#27272a] px-4 py-6 flex flex-col items-center text-center gap-4\">\n <PhaseIcon variant={variant} />\n <p\n className={cn(\n \"text-sm leading-relaxed max-w-[320px]\",\n variantTextClass(variant),\n )}\n >\n {message}\n </p>\n </div>\n\n {/* Transaction links */}\n {(status?.solanaTxHash || status?.hyperliquidTxHash) && (\n <div className=\"mt-3 flex flex-col gap-2\">\n {status?.solanaTxHash && solanaExplorerUrl && (\n <TxLink\n href={solanaExplorerUrl}\n label={t(\"perpDeposit.status.viewSolanaTx\")}\n hash={status.solanaTxHash}\n />\n )}\n {status?.hyperliquidTxHash && hyperliquidExplorerUrl && (\n <TxLink\n href={hyperliquidExplorerUrl}\n label={t(\"perpDeposit.status.viewHyperliquidTx\")}\n hash={status.hyperliquidTxHash}\n />\n )}\n </div>\n )}\n </div>\n\n {/* Footer */}\n <div\n className={cn(\n \"px-5 pb-5 pt-2 flex gap-2\",\n showRetry ? \"justify-between\" : \"justify-end\",\n )}\n >\n {showRetry && (\n <button\n type=\"button\"\n onClick={onRetry}\n className=\"cursor-pointer flex-1 h-10 rounded-[10px] font-medium text-black bg-[#C7FF2E] hover:bg-[#b6ed1c] active:bg-[#a6d913] transition-colors flex items-center justify-center\"\n >\n {t(\"perpDeposit.status.tryAgain\")}\n </button>\n )}\n <button\n type=\"button\"\n onClick={onClose}\n className={cn(\n \"cursor-pointer h-10 rounded-[10px] font-medium transition-colors flex items-center justify-center\",\n showRetry\n ? \"flex-1 bg-[rgba(39,39,42,1)] hover:bg-[rgba(63,63,70,1)] text-white\"\n : \"px-6 bg-[rgba(39,39,42,1)] hover:bg-[rgba(63,63,70,1)] text-white\",\n )}\n >\n {t(\"perpDeposit.status.close\")}\n </button>\n </div>\n </div>\n </ModalContent>\n </StyledModal>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Sub-components\n// ---------------------------------------------------------------------------\n\nfunction TxLink({\n href,\n label,\n hash,\n}: {\n href: string;\n label: string;\n hash: string;\n}) {\n return (\n <a\n href={href}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"group flex items-center justify-between gap-2 px-3 py-2 rounded-[10px] bg-[#0a0a0b] border border-[#27272a] hover:border-[rgba(199,255,46,0.4)] transition-colors\"\n >\n <span className=\"text-xs text-zinc-400 group-hover:text-white transition-colors\">\n {label}\n </span>\n <span className=\"flex items-center gap-1.5 text-xs tabular-nums text-zinc-300 group-hover:text-[#C7FF2E] transition-colors\">\n {shortAddress(hash, 6, 4)}\n <ExternalLinkIcon />\n </span>\n </a>\n );\n}\n\nfunction PhaseIcon({ variant }: { variant: Variant }) {\n if (variant === \"progress\") {\n return (\n <div className=\"relative w-14 h-14 flex items-center justify-center\">\n <AccentSpinner />\n </div>\n );\n }\n if (variant === \"success\") {\n return (\n <div className=\"w-14 h-14 rounded-full flex items-center justify-center bg-[rgba(199,255,46,0.12)]\">\n <CheckCircle className=\"w-8 h-8\" style={{ color: ACCENT }} />\n </div>\n );\n }\n if (variant === \"warning\") {\n return (\n <div className=\"w-14 h-14 rounded-full flex items-center justify-center bg-[rgba(245,158,11,0.12)]\">\n <AlertCircle className=\"w-8 h-8 text-amber-400\" />\n </div>\n );\n }\n return (\n <div className=\"w-14 h-14 rounded-full flex items-center justify-center bg-[rgba(239,68,68,0.12)]\">\n <XCircle className=\"w-8 h-8 text-rose-400\" />\n </div>\n );\n}\n\n/**\n * Accent-coloured circular spinner matching the deposit form's theme.\n *\n * Implemented as an inline SVG with a CSS keyframe rotation rather than\n * pulling HeroUI's `Spinner` (which doesn't expose a clean way to set\n * the active arc colour to our brand `#C7FF2E`).\n */\nfunction AccentSpinner() {\n return (\n <>\n <svg\n className=\"lfi-perp-deposit-spinner\"\n viewBox=\"0 0 50 50\"\n width={48}\n height={48}\n aria-hidden=\"true\"\n >\n <circle\n cx=\"25\"\n cy=\"25\"\n r=\"20\"\n fill=\"none\"\n stroke=\"rgba(255,255,255,0.08)\"\n strokeWidth=\"4\"\n />\n <circle\n cx=\"25\"\n cy=\"25\"\n r=\"20\"\n fill=\"none\"\n stroke={ACCENT}\n strokeWidth=\"4\"\n strokeLinecap=\"round\"\n strokeDasharray=\"90 60\"\n />\n </svg>\n <style>{`\n .lfi-perp-deposit-spinner {\n animation: lfi-perp-deposit-spin 0.9s linear infinite;\n transform-origin: center;\n }\n @keyframes lfi-perp-deposit-spin {\n to { transform: rotate(360deg); }\n }\n `}</style>\n </>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction phaseToVariant(phase: DepositPhase): Variant {\n switch (phase) {\n case \"succeeded\":\n return \"success\";\n case \"refunded\":\n return \"warning\";\n case \"failed\":\n return \"error\";\n default:\n return \"progress\";\n }\n}\n\nfunction variantTextClass(variant: Variant): string {\n switch (variant) {\n case \"success\":\n return \"text-white\";\n case \"warning\":\n return \"text-amber-200\";\n case \"error\":\n return \"text-rose-300\";\n default:\n return \"text-zinc-200\";\n }\n}\n\n// Inline icons — kept tiny so we don't pull a heavy icon dep into the bundle.\nfunction CheckCircle(props: {\n className?: string;\n style?: React.CSSProperties;\n}) {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2.5}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n className={props.className}\n style={props.style}\n >\n <path d=\"M20 6L9 17l-5-5\" />\n </svg>\n );\n}\n\nfunction AlertCircle(props: { className?: string }) {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n className={props.className}\n >\n <path d=\"M12 2a10 10 0 100 20 10 10 0 000-20zm0 4c.6 0 1 .4 1 1v6c0 .6-.4 1-1 1s-1-.4-1-1V7c0-.6.4-1 1-1zm0 12c-.7 0-1.2-.5-1.2-1.2s.5-1.2 1.2-1.2 1.2.5 1.2 1.2-.5 1.2-1.2 1.2z\" />\n </svg>\n );\n}\n\nfunction XCircle(props: { className?: string }) {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2.5}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n className={props.className}\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"M15 9l-6 6M9 9l6 6\" />\n </svg>\n );\n}\n\nfunction ExternalLinkIcon() {\n return (\n <svg\n width=\"11\"\n height=\"11\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\" />\n <polyline points=\"15 3 21 3 21 9\" />\n <line x1=\"10\" y1=\"14\" x2=\"21\" y2=\"3\" />\n </svg>\n );\n}\n","import { useCallback, useEffect, useMemo, useState } from \"react\";\nimport { useTranslation } from \"@liberfi.io/i18n\";\nimport { Button, Card, CardBody } from \"@liberfi.io/ui\";\nimport type {\n DepositQuoteRequest,\n DepositSource,\n} from \"../../client/liberfi/deposit-types\";\nimport {\n type SignAndBroadcastSolanaTx,\n usePerpDepositExecute,\n} from \"../../hooks/usePerpDepositExecute\";\nimport { usePerpDepositQuote } from \"../../hooks/usePerpDepositQuote\";\nimport { usePerpDepositStatus } from \"../../hooks/usePerpDepositStatus\";\nimport { DepositConfirmUI } from \"./deposit-confirm.ui\";\nimport { DepositFormUI } from \"./deposit-form.ui\";\nimport { DepositStatusUI } from \"./deposit-status.ui\";\nimport { solToLamports } from \"./format\";\n\n/**\n * Highest-level deposit widget. Wires the three presentational\n * components (form / confirm / status) to the deposit hooks +\n * state machine.\n *\n * Engineering principles:\n * - Single responsibility: this file is the *only* place that knows\n * how the three components compose. Anything richer (e.g. embedded\n * FAQ panel, support links) belongs to the host application.\n * - Inversion of control: every side effect the host might want to\n * own (sign + broadcast, success / failure callbacks, explorer\n * URLs, balance fetch, address validation) is a prop. The widget\n * never imports a wallet adapter directly.\n */\nexport interface DepositFlowWidgetProps {\n /** Connected Solana wallet — used as `userSolanaAddress` in /quote. */\n userSolanaAddress: string;\n /** Stable LiberFi user id (for fee attribution). */\n userId: string;\n /** Where the deposit was initiated from. */\n source: DepositSource;\n /** Optional referral / campaign code propagated to the backend. */\n campaign?: string;\n\n /** Initial Hyperliquid recipient (e.g. derived from the user's EVM wallet). */\n defaultRecipient?: string;\n\n /**\n * Wallet adapter — sign and broadcast a Solana transaction. The host\n * app supplies its own wallet integration (Phantom, Privy, Backpack,\n * …) and returns the resulting tx hash. See `SignAndBroadcastSolanaTx`.\n */\n signAndBroadcast: SignAndBroadcastSolanaTx;\n\n /** Optional balance display (in SOL units, e.g. \"12.345\"). */\n balanceSol?: string;\n /** Click handler for \"Max\" — only rendered when `balanceSol` is set. */\n onMaxClick?: () => void;\n /** Validates the recipient string. Return undefined when valid. */\n validateRecipient?: (value: string) => string | undefined;\n\n /** Build a Solana explorer URL from a tx hash. */\n buildSolanaExplorerUrl?: (txHash: string) => string;\n /** Build a Hyperliquid explorer URL from a tx hash. */\n buildHyperliquidExplorerUrl?: (txHash: string) => string;\n\n /** Fired when a deposit reaches `settled`. */\n onSettled?: (intentId: string) => void;\n /** Fired when a deposit fails (after the wallet signed). */\n onError?: (intentId: string | undefined, message: string) => void;\n\n className?: string;\n}\n\nexport function DepositFlowWidget({\n userSolanaAddress,\n userId,\n source,\n campaign,\n defaultRecipient,\n signAndBroadcast,\n balanceSol,\n onMaxClick,\n validateRecipient,\n buildSolanaExplorerUrl,\n buildHyperliquidExplorerUrl,\n onSettled,\n onError,\n className,\n}: DepositFlowWidgetProps) {\n const { t } = useTranslation();\n\n const [amount, setAmount] = useState(\"\");\n const [recipient, setRecipient] = useState(defaultRecipient ?? \"\");\n\n // Local validation. Backend re-validates everything; these only\n // gate the \"Continue\" button and surface inline errors.\n const amountError = useMemo<string | undefined>(() => {\n if (!amount) return undefined;\n if (!/^\\d+(\\.\\d+)?$/.test(amount.trim())) {\n return t(\"perpDeposit.error.amountInvalid\");\n }\n if (Number(amount) <= 0) return t(\"perpDeposit.error.amountInvalid\");\n return undefined;\n }, [amount, t]);\n\n const recipientError = useMemo<string | undefined>(() => {\n if (!recipient) return undefined;\n return validateRecipient ? validateRecipient(recipient) : undefined;\n }, [recipient, validateRecipient]);\n\n const grossLamports = useMemo(\n () => (amountError ? \"\" : solToLamports(amount)),\n [amount, amountError],\n );\n\n const quoteReq = useMemo<DepositQuoteRequest | null>(() => {\n if (!grossLamports || grossLamports === \"0\") return null;\n if (recipientError) return null;\n if (!recipient) return null;\n return {\n userSolanaAddress,\n hyperliquidRecipient: recipient,\n grossLamports,\n source,\n };\n }, [grossLamports, recipient, recipientError, source, userSolanaAddress]);\n\n const quoteQ = usePerpDepositQuote(quoteReq, {\n enabled: Boolean(quoteReq),\n });\n\n const { state, execute, reset, dispatch } =\n usePerpDepositExecute(signAndBroadcast);\n const intentId =\n state.phase === \"submitted\" ||\n state.phase === \"tracking\" ||\n state.phase === \"succeeded\" ||\n state.phase === \"refunded\"\n ? state.intentId\n : state.phase === \"failed\"\n ? state.intentId\n : undefined;\n\n const statusQ = usePerpDepositStatus(intentId, {\n enabled:\n Boolean(intentId) &&\n state.phase !== \"succeeded\" &&\n state.phase !== \"refunded\" &&\n state.phase !== \"failed\",\n });\n\n // Forward backend status into the FSM so the UI advances.\n useEffect(() => {\n if (statusQ.data) {\n dispatch({ type: \"STATUS_UPDATE\", status: statusQ.data });\n }\n }, [statusQ.data, dispatch]);\n\n // Funnel-end side effects.\n useEffect(() => {\n if (state.phase === \"succeeded\") {\n onSettled?.(state.intentId);\n } else if (state.phase === \"failed\") {\n onError?.(state.intentId, state.error.message);\n }\n }, [state, onSettled, onError]);\n\n const handleContinue = useCallback(() => {\n if (!quoteQ.data) return;\n dispatch({ type: \"QUOTE_REQUEST\" });\n dispatch({ type: \"QUOTE_RECEIVED\", quote: quoteQ.data });\n }, [dispatch, quoteQ.data]);\n\n const handleConfirm = useCallback(async () => {\n if (state.phase !== \"ready_to_sign\") return;\n try {\n await execute({\n quote: state.quote,\n userSolanaAddress,\n hyperliquidRecipient: recipient,\n userId,\n source,\n campaign,\n });\n } catch {\n // Hook already advanced FSM into `failed`; nothing to do here.\n }\n }, [state, execute, userSolanaAddress, recipient, userId, source, campaign]);\n\n const handleExpire = useCallback(() => {\n dispatch({ type: \"QUOTE_EXPIRED\" });\n }, [dispatch]);\n\n const handleRetry = useCallback(async () => {\n dispatch({ type: \"RESET\" });\n await quoteQ.refetch();\n }, [dispatch, quoteQ]);\n\n const showConfirm =\n state.phase === \"ready_to_sign\" ||\n state.phase === \"signing\" ||\n state.phase === \"broadcasting\" ||\n state.phase === \"expired\";\n\n const showStatus =\n state.phase === \"submitted\" ||\n state.phase === \"tracking\" ||\n state.phase === \"succeeded\" ||\n state.phase === \"refunded\" ||\n (state.phase === \"failed\" && Boolean(state.intentId));\n\n const status =\n state.phase === \"tracking\" ||\n state.phase === \"succeeded\" ||\n state.phase === \"refunded\"\n ? state.status\n : state.phase === \"failed\"\n ? state.status\n : undefined;\n\n const continueDisabled =\n !quoteQ.data ||\n quoteQ.isFetching ||\n Boolean(amountError) ||\n Boolean(recipientError) ||\n !quoteReq;\n\n return (\n <Card className={className}>\n <CardBody className=\"flex flex-col gap-4 p-6\">\n <div>\n <h3 className=\"text-lg font-semibold\">{t(\"perpDeposit.title\")}</h3>\n <p className=\"text-default-500 text-sm\">\n {t(\"perpDeposit.description\")}\n </p>\n </div>\n\n <DepositFormUI\n amount={amount}\n onAmountChange={setAmount}\n recipient={recipient}\n onRecipientChange={setRecipient}\n balanceSol={balanceSol}\n onMax={onMaxClick}\n amountError={amountError}\n recipientError={recipientError}\n disabled={\n state.phase !== \"idle\" &&\n state.phase !== \"expired\" &&\n state.phase !== \"failed\"\n }\n />\n\n <Button\n color=\"primary\"\n isDisabled={continueDisabled}\n isLoading={quoteQ.isFetching}\n onPress={handleContinue}\n >\n {quoteQ.isFetching\n ? t(\"perpDeposit.gettingQuote\")\n : t(\"perpDeposit.confirmQuote\")}\n </Button>\n\n {quoteQ.error && (\n <div className=\"text-danger text-xs\">\n {t(\"perpDeposit.error.quoteFailed\")}\n </div>\n )}\n </CardBody>\n\n <DepositConfirmUI\n isOpen={showConfirm}\n quote={\n state.phase === \"ready_to_sign\" ||\n state.phase === \"signing\" ||\n state.phase === \"broadcasting\" ||\n state.phase === \"expired\"\n ? state.quote\n : undefined\n }\n isExecuting={\n state.phase === \"signing\" || state.phase === \"broadcasting\"\n }\n isExpired={state.phase === \"expired\"}\n onConfirm={handleConfirm}\n onCancel={reset}\n onExpire={handleExpire}\n />\n\n <DepositStatusUI\n isOpen={showStatus}\n phase={state.phase}\n status={status}\n solanaExplorerUrl={\n status?.solanaTxHash && buildSolanaExplorerUrl\n ? buildSolanaExplorerUrl(status.solanaTxHash)\n : undefined\n }\n hyperliquidExplorerUrl={\n status?.hyperliquidTxHash && buildHyperliquidExplorerUrl\n ? buildHyperliquidExplorerUrl(status.hyperliquidTxHash)\n : undefined\n }\n onRetry={state.phase === \"failed\" ? handleRetry : undefined}\n onClose={reset}\n errorMessage={\n state.phase === \"failed\" ? state.error.message : undefined\n }\n />\n </Card>\n );\n}\n","import { useTranslation } from \"@liberfi.io/i18n\";\nimport {\n Button,\n Card,\n CardBody,\n CardFooter,\n CardHeader,\n Spinner,\n cn,\n} from \"@liberfi.io/ui\";\nimport type {\n SetupState,\n SetupStep,\n StepRecord,\n StepStatus,\n} from \"../../hooks/hyperliquid-setup/setup-state-machine\";\n\n/**\n * Pure presentational card for the Hyperliquid first-run setup flow.\n *\n * The component is fully driven by the FSM state from\n * `useHyperliquidSetup` plus a couple of action callbacks, so consumers\n * can wire it into either a modal, a sidebar panel, or an inline card\n * without forking the markup.\n */\nexport interface HyperliquidInitUIProps {\n /** FSM snapshot rendered as the checklist. */\n state: SetupState;\n /** Trigger the next runnable step (sequential default). */\n onContinue: () => void;\n /** Retry a specific step (used by per-row error recovery). */\n onRetryStep?: (index: number) => void;\n /** Refresh the on-chain state — typically rendered when the load failed. */\n onReload?: () => void;\n /** Optional dismiss handler — show a \"Skip for now\" CTA when set. */\n onDismiss?: () => void;\n /** Optional className override for embedding inside other cards. */\n className?: string;\n}\n\nexport function HyperliquidInitUI({\n state,\n onContinue,\n onRetryStep,\n onReload,\n onDismiss,\n className,\n}: HyperliquidInitUIProps) {\n const { t } = useTranslation();\n const phase = state.phase;\n const isExecuting = phase === \"executing\";\n const isLoading = phase === \"loading\";\n const isLoadError = phase === \"error\" && state.steps.length === 0;\n\n return (\n <Card className={cn(\"w-full max-w-md\", className)}>\n <CardHeader className=\"flex flex-col items-start gap-1\">\n <h3 className=\"text-lg font-semibold\">\n {t(\"perpDeposit.setup.title\")}\n </h3>\n <p className=\"text-foreground-500 text-sm\">\n {t(\"perpDeposit.setup.description\")}\n </p>\n </CardHeader>\n <CardBody className=\"gap-3\">\n {isLoading && <LoadingRow />}\n {isLoadError && (\n <p className=\"text-danger text-sm\">\n {t(\"perpDeposit.setup.loadFailed\", { message: state.error ?? \"\" })}\n </p>\n )}\n {!isLoading &&\n !isLoadError &&\n state.steps.map((rec, idx) => (\n <SetupStepRow\n key={`${rec.step.id}-${idx}`}\n rec={rec}\n index={idx}\n isCurrent={state.currentIndex === idx}\n onRetry={onRetryStep}\n />\n ))}\n {phase === \"done\" && (\n <p className=\"text-success text-sm\">\n {t(\"perpDeposit.setup.alreadyActive\")}\n </p>\n )}\n </CardBody>\n <CardFooter className=\"flex justify-between gap-2\">\n {onDismiss && (\n <Button variant=\"light\" onPress={onDismiss} isDisabled={isExecuting}>\n {phase === \"done\"\n ? t(\"perpDeposit.setup.dismiss\")\n : t(\"perpDeposit.setup.skip\")}\n </Button>\n )}\n <div className=\"flex-1\" />\n {isLoadError && onReload && (\n <Button color=\"primary\" onPress={onReload}>\n {t(\"perpDeposit.setup.retry\")}\n </Button>\n )}\n {!isLoadError && phase !== \"done\" && (\n <Button\n color=\"primary\"\n onPress={onContinue}\n isLoading={isExecuting}\n isDisabled={isExecuting || isLoading}\n >\n {state.steps.some((s) => s.status === \"done\")\n ? t(\"perpDeposit.setup.continue\")\n : t(\"perpDeposit.setup.cta\")}\n </Button>\n )}\n </CardFooter>\n </Card>\n );\n}\n\ninterface SetupStepRowProps {\n rec: StepRecord;\n index: number;\n isCurrent: boolean;\n onRetry?: (index: number) => void;\n}\n\nfunction SetupStepRow({ rec, index, isCurrent, onRetry }: SetupStepRowProps) {\n const { t } = useTranslation();\n const title = stepTitle(rec.step.id, () => {\n switch (rec.step.id) {\n case \"approveBuilderFee\":\n return t(\"perpDeposit.setup.builderFee.label\");\n case \"setReferrer\":\n return t(\"perpDeposit.setup.referrer.label\");\n case \"updateLeverage\":\n return t(\"perpDeposit.setup.leverage.label\");\n }\n });\n const description = ((): string => {\n switch (rec.step.id) {\n case \"approveBuilderFee\": {\n const bps = (rec.step.params.maxFeeRate / 10).toFixed(1);\n return t(\"perpDeposit.setup.builderFee.description\", { bps });\n }\n case \"setReferrer\":\n return t(\"perpDeposit.setup.referrer.description\", {\n code: rec.step.params.code,\n });\n case \"updateLeverage\":\n return t(\"perpDeposit.setup.leverage.description\");\n }\n })();\n const statusLabel = ((): string => {\n switch (rec.status) {\n case \"pending\":\n return t(\"perpDeposit.setup.step.pending\");\n case \"skipped\":\n return t(\"perpDeposit.setup.step.skipped\");\n case \"running\":\n return t(\"perpDeposit.setup.step.running\");\n case \"done\":\n return t(\"perpDeposit.setup.step.done\");\n case \"error\":\n return t(\"perpDeposit.setup.step.error\");\n }\n })();\n return (\n <div\n className={cn(\n \"border-divider flex items-start justify-between gap-3 rounded-md border p-3\",\n rec.status === \"error\" && \"border-danger\",\n rec.status === \"done\" && \"border-success/40 bg-success/5\",\n rec.status === \"skipped\" && \"border-default bg-default-100/40\",\n )}\n >\n <div className=\"flex-1\">\n <div className=\"flex items-center gap-2 text-sm font-medium\">\n <StepIcon status={rec.status} isCurrent={isCurrent} />\n <span>{title}</span>\n </div>\n <p className=\"text-foreground-500 mt-1 text-xs\">{description}</p>\n {rec.status === \"error\" && rec.error && (\n <p className=\"text-danger mt-1 text-xs\">{rec.error}</p>\n )}\n </div>\n <div className=\"flex flex-col items-end gap-1 text-xs\">\n <span className={cn(statusBadgeClass(rec.status))}>{statusLabel}</span>\n {rec.status === \"error\" && onRetry && (\n <Button\n size=\"sm\"\n variant=\"flat\"\n color=\"danger\"\n onPress={() => onRetry(index)}\n >\n {t(\"perpDeposit.setup.retry\")}\n </Button>\n )}\n </div>\n </div>\n );\n}\n\nfunction LoadingRow() {\n const { t } = useTranslation();\n return (\n <div className=\"flex items-center gap-2 py-2 text-sm\">\n <Spinner size=\"sm\" />\n <span>{t(\"perpDeposit.setup.loading\")}</span>\n </div>\n );\n}\n\nfunction StepIcon({\n status,\n isCurrent,\n}: {\n status: StepStatus;\n isCurrent: boolean;\n}) {\n if (status === \"running\" || isCurrent) {\n return <Spinner size=\"sm\" />;\n }\n if (status === \"done\" || status === \"skipped\") {\n return (\n <span aria-hidden className=\"text-success\">\n ✓\n </span>\n );\n }\n if (status === \"error\") {\n return (\n <span aria-hidden className=\"text-danger\">\n !\n </span>\n );\n }\n return (\n <span\n aria-hidden\n className=\"border-foreground-400 inline-block h-3 w-3 rounded-full border\"\n />\n );\n}\n\nfunction statusBadgeClass(status: StepStatus): string {\n switch (status) {\n case \"done\":\n return \"text-success\";\n case \"skipped\":\n return \"text-foreground-500\";\n case \"running\":\n return \"text-primary\";\n case \"error\":\n return \"text-danger\";\n default:\n return \"text-foreground-500\";\n }\n}\n\n/**\n * Tiny indirection to keep `SetupStepRow` flat — invokes a closure\n * the caller wrote inline so we don't pass `t` across function\n * boundaries (which would defeat its strict-key inference).\n */\nfunction stepTitle(_id: SetupStep[\"id\"], compute: () => string): string {\n return compute();\n}\n","import { useCallback } from \"react\";\nimport {\n useHyperliquidSetup,\n type UseHyperliquidSetupOptions,\n type SetupState,\n} from \"../../hooks/hyperliquid-setup\";\nimport { HyperliquidInitUI } from \"./hyperliquid-init.ui\";\n\n/**\n * Highest-level Hyperliquid setup widget.\n *\n * Wraps `useHyperliquidSetup` with the presentational card so consumers\n * can drop in a single component:\n *\n * <HyperliquidInitWidget\n * adapter={mySetupAdapter}\n * userAddress={evmAddress}\n * steps={[ ... ]}\n * onComplete={() => navigate(\"/perp\")}\n * onDismiss={() => closeModal()}\n * />\n *\n * The widget is a thin coordinator — all logic lives in the hook and\n * all presentation lives in `HyperliquidInitUI`. This split keeps the\n * UI testable in isolation (Storybook just hands it a `state` prop).\n */\nexport interface HyperliquidInitWidgetProps extends Pick<\n UseHyperliquidSetupOptions,\n \"adapter\" | \"userAddress\" | \"steps\" | \"autoLoad\" | \"onError\"\n> {\n /** Invoked once every step is `done` or `skipped`. */\n onComplete?: (state: SetupState) => void;\n /**\n * Optional dismiss callback — when supplied the card renders a\n * \"Skip for now\" / \"Close\" CTA so the user can leave the wizard.\n */\n onDismiss?: () => void;\n /** Optional className passthrough to the rendered card. */\n className?: string;\n}\n\nexport function HyperliquidInitWidget({\n adapter,\n userAddress,\n steps,\n autoLoad,\n onComplete,\n onError,\n onDismiss,\n className,\n}: HyperliquidInitWidgetProps) {\n const { state, runNext, runStep, reload } = useHyperliquidSetup({\n adapter,\n userAddress,\n steps,\n autoLoad,\n onComplete,\n onError,\n });\n\n const handleContinue = useCallback(() => {\n void runNext();\n }, [runNext]);\n\n const handleRetry = useCallback(\n (index: number) => {\n void runStep(index);\n },\n [runStep],\n );\n\n const handleReload = useCallback(() => {\n void reload();\n }, [reload]);\n\n return (\n <HyperliquidInitUI\n state={state}\n onContinue={handleContinue}\n onRetryStep={handleRetry}\n onReload={handleReload}\n onDismiss={onDismiss}\n className={className}\n />\n );\n}\n"]}
1
+ {"version":3,"sources":["../src/version.ts","../src/client/hyperliquid/WebSocketManager.ts","../src/client/hyperliquid/HyperliquidPerpetualsClient.ts","../src/client/liberfi/transport.ts","../src/client/liberfi/LiberFiPerpetualsClient.ts","../src/client/liberfi/LiberFiPerpDepositClient.ts","../src/client/liberfi/deposit-types.ts","../src/client/liberfi/deposit-state-machine.ts","../src/context/PerpetualsContext.ts","../src/providers/PerpetualsProvider.tsx","../src/hooks/usePerpetualsClient.ts","../src/hooks/useCoinsQuery.ts","../src/hooks/useMarketQuery.ts","../src/hooks/useMarketsQuery.ts","../src/hooks/useKlinesQuery.ts","../src/hooks/useOrderBookQuery.ts","../src/hooks/useRecentTradesQuery.ts","../src/hooks/usePositionsQuery.ts","../src/hooks/useOrdersQuery.ts","../src/hooks/useTradesQuery.ts","../src/hooks/useActiveAssetLeverageQuery.ts","../src/hooks/useAssetMetaQuery.ts","../src/hooks/useCreateOrderMutation.ts","../src/hooks/useCancelOrderMutation.ts","../src/hooks/useMarketDataSubscription.ts","../src/hooks/useCandlesSubscription.ts","../src/hooks/useUserDataSubscription.ts","../src/hooks/useAccountStateQuery.ts","../src/hooks/useAccountStateSubscription.ts","../src/hooks/usePerpDepositClient.ts","../src/hooks/usePerpDepositQuote.ts","../src/hooks/usePerpDepositExecute.ts","../src/hooks/usePerpDepositStatus.ts","../src/hooks/hyperliquid-setup/setup-state-machine.ts","../src/hooks/hyperliquid-setup/useHyperliquidSetup.ts","../src/components/coin-info/coin-info-notfound.ui.tsx","../src/internal/skeleton.tsx","../src/components/coin-info/coin-info-skeletons.ui.tsx","../src/components/coin-info/coin-info.script.tsx","../src/components/coin-info/coin-info.ui.tsx","../src/components/coin-info/coin-info.widget.tsx","../src/components/search-coins/search-coins.script.tsx","../src/components/search-coins/search-coins.ui.tsx","../src/components/search-coins/search-coins.widget.tsx","../src/components/orderbook/orderbook.script.tsx","../src/components/orderbook/orderbook.ui.tsx","../src/components/orderbook/orderbook.widget.tsx","../src/components/trades/trades.script.tsx","../src/components/trades/trades.ui.tsx","../src/components/trades/trades.widget.tsx","../src/components/place-order/tp-sl-math.ts","../src/components/place-order/place-order-form.script.tsx","../src/components/place-order/place-order-form.ui.tsx","../src/components/place-order/place-order-form.widget.tsx","../src/components/positions/positions.script.tsx","../src/components/positions/positions.ui.tsx","../src/components/positions/positions.widget.tsx","../src/components/open-orders/open-orders.script.tsx","../src/components/open-orders/open-orders.ui.tsx","../src/components/open-orders/open-orders.widget.tsx","../src/components/trade-history/trade-history.script.tsx","../src/components/trade-history/trade-history.ui.tsx","../src/components/trade-history/trade-history.widget.tsx","../src/components/perp-deposit/format.ts","../src/components/perp-deposit/deposit-confirm.ui.tsx","../src/components/perp-deposit/deposit-form.ui.tsx","../src/components/perp-deposit/deposit-status.ui.tsx","../src/components/perp-deposit/deposit-flow.widget.tsx","../src/components/hyperliquid-init/hyperliquid-init.ui.tsx","../src/components/hyperliquid-init/hyperliquid-init.widget.tsx"],"names":["version_default","aggregationKey","type","param","aggregation","m","WebSocketManager","wsEndpoint","resolve","reject","settled","settle","callback","ws","event","error","delay","message","subscription","data","channel","subscriptionId","transformedData","expectedCoin","payloadCoin","symbol","ctx","mid","mark","prev","change24h","trade","bids","asks","level","fill","sub","interval","unsubscription","HYPERLIQUID_ENDPOINTS","ASSET_META_TTL_MS","HyperliquidPerpetualsClient","config","endpoint","body","url","controller","timeoutId","response","HyperliquidApiError","meta","asset","markets","symbols","assetCtxs","allMarkets","index","currentPrice","prevPrice","symbolSet","limitOrOptions","coin","options","intervalMs","limit","startTime","endTime","bars","candle","maxLevel","_params","params","clearinghouse","openOrdersRaw","metaAndCtxs","result","parseClearinghouseState","markByCoin","buildMarkPriceMap","enrichPositions","sum","p","lev","universe","now","fetchPromise","map","orders","parseOpenOrder","filteredOrders","o","trades","isLong","t","userAddress","subscriptionType","raw","parseWebData2","symbolFilter","positions","assetPos","pos","quantity","entryPrice","unrealizedPnl","positionValue","filteredPositions","withdrawableRaw","availableBalance","order","origSz","remainingSz","filledSz","isBuySide","rawOrderType","baseOrderType","isTrigger","triggerType","triggerPx","triggerCondition","parseSpotBalances","balances","b","positionsResult","openOrders","spotBalances","enrichedPositions","totalUnrealizedPnl","ctxs","px","pickPositionTpSl","position","closingSide","closingSideBool","tpOrder","slOrder","orderTypeStr","isTp","isSl","marks","next","tp","sl","markPrice","dir","pnl","statusCode","responseBody","LiberFiApiError","DEFAULT_TIMEOUT_MS","LiberFiHttpTransport","path","query","key","value","qs","method","opts","timeoutMs","text","safeText","err","DEFAULT_WS_ENDPOINT","LiberFiPerpetualsClient","fills","prepared","signature","LiberFiPerpDepositClient","req","intentId","TERMINAL_DEPOSIT_STATUSES","initialDepositState","reduceDepositState","state","mapStatusToPhase","status","isTerminal","isPolling","currentStatus","currentBreakdown","isTerminalLifecycle","PerpetualsContext","createContext","PerpetualsProvider","client","depositClient","children","useMemo","jsx","usePerpetualsClient","context","useContext","coinsQueryKey","fetchCoins","useCoinsQuery","useQuery","DEFAULT_REFETCH_INTERVAL_MS","marketQueryKey","fetchMarket","useMarketQuery","marketsQueryKey","fetchMarkets","useMarketsQuery","klinesQueryKey","fetchKlines","useKlinesQuery","orderBookQueryKey","agg","aggKey","fetchOrderBook","useOrderBookQuery","recentTradesQueryKey","fetchRecentTrades","useRecentTradesQuery","positionsQueryKey","fetchPositions","usePositionsQuery","enabled","queryParams","ordersQueryKey","fetchOrders","useOrdersQuery","tradesQueryKey","fetchTrades","useTradesQuery","activeAssetLeverageQueryKey","fetchActiveAssetLeverage","useActiveAssetLeverageQuery","assetMetaQueryKey","fetchAssetMeta","useAssetMetaQuery","createOrder","useCreateOrderMutation","useMutation","cancelOrder","useCancelOrderMutation","useMarketDataSubscription","throttleMs","setData","useState","isConnected","setIsConnected","setError","pendingDataRef","useRef","flushTimerRef","throttleMsRef","handleData","useCallback","newData","useEffect","isSubscribed","useCandlesSubscription","useUserDataSubscription","accountStateQueryKey","useAccountStateQuery","rest","useAccountStateSubscription","queryClient","useQueryClient","isMounted","handlePush","ordersResult","unsubError","usePerpDepositClient","usePerpDepositClientMaybe","perpDepositQuoteQueryKey","fetchPerpDepositQuote","usePerpDepositQuote","isQuoteReady","usePerpDepositExecute","signAndBroadcast","dispatch","useReducer","reset","execute","input","quote","solanaTxHash","info","toErrorInfo","submitReq","out","fallbackCode","parsed","parseJsonSafe","perpDepositStatusQueryKey","fetchPerpDepositStatus","usePerpDepositStatus","pollIntervalMs","initialSetupState","classifyStep","step","current","sameAddress","reduceSetupState","action","rec","i","mergedAccount","mergeAccountState","s","nextRunnableStep","a","base","patch","useHyperliquidSetup","adapter","steps","autoLoad","onComplete","onError","adapterRef","stepsRef","onCompleteRef","onErrorRef","reload","accountState","records","e","toError","runStep","record","invokeAdapter","runNext","idx","completedRef","CoinInfoNotFoundUI","KEYFRAME_NAME","SHIMMER_KEYFRAMES_CSS","ShimmerStyle","shimmer","shimmerDelay","CoinInfoSkeletonsUI","jsxs","Fragment","cellStyle","StatColumn","labelWidth","valueWidth","width","height","useCoinInfo","marketData","setMarketData","fundingCountdown","setFundingCountdown","initialData","isPending","realtimeData","normalized","normalizeRealtimeTickerPayload","previous","buildMarketData","calculateCountdown","oneHour","remainder","timeUntilNext","payload","matched","item","toNumberOr","fallback","formatCountdown","seconds","hours","minutes","secs","formatNumber","num","decimals","formatPrice","price","CoinInfoUI","indexPrice","volume24h","openInterest","fundingRate","safeChange24h","safeFundingRate","isPositiveChange","changePercent","CoinInfoWidget","isLoading","useSearchCoinsScript","onSelectCoin","searchQuery","setSearchQuery","coins","setCoins","coinSymbols","isLoadingSymbols","marketsData","isLoadingMarkets","filteredCoins","SearchCoinsUI","onSearchChange","SearchIcon","fundingPercent","isPositiveFunding","tokenName","target","SearchCoinsWidget","className","handleSelectCoin","aggregationFromStep","k","candidates","eps","best","c","aggregateByPrecision","levels","precision","side","aggregated","round","roundedPrice","existing","calculateTotalsAndPercentages","total","withTotals","usdAmount","maxTotal","useOrderBookScript","initialPrecision","orderBook","setOrderBook","setPrecision","priceMagnitude","bestBid","bestAsk","ref","referencePrice","aggregatedBids","aggregatedAsks","sortedBids","sortedAsks","spread","spreadPercentage","ORDERBOOK_SCROLL_STYLE","CONTAINER_STYLE","HEADER_STYLE","HEADER_CELL_STYLE","ROW_STYLE","ASK_BAR_STYLE_BASE","BID_BAR_STYLE_BASE","ASK_PRICE_STYLE","BID_PRICE_STYLE","ROW_CELL_STYLE","ROW_PRICE_CELL_STYLE","SPREAD_BAR_STYLE","SPREAD_BAR_INNER_STYLE","SPREAD_LABEL_STYLE","SPREAD_VALUE_STYLE","SPREAD_BUTTON_STYLE","SPREAD_DROPDOWN_STYLE","SPREAD_OPTION_STYLE","SPREAD_OPTION_SELECTED_STYLE","formatQuantity","qty","formatPrecision","OBRow","memo","percentage","onPriceClick","isAsk","barStyle","handleClick","SpreadBar","precisionOptions","onPrecisionChange","open","setOpen","wrapperRef","handler","chevronStyle","v","opt","selected","OrderBookUI","asksScrollRef","bidsScrollRef","asksStuckRef","bidsStuckRef","renderedAsks","el","handleAsksScroll","distanceFromBottom","handleBidsScroll","ask","bid","DEFAULT_ORDER_BOOK_PRECISION_OPTIONS","SKEL_CONTAINER_STYLE","SKEL_HEADER_STYLE","SKEL_HEADER_CELL_STYLE","SKEL_ROW_STYLE","SKEL_SPREAD_BAR_STYLE","SkelRow","OrderBookSkeleton","askRows","_","bidRows","OrderBookEmpty","OrderBookWidget","defaultPrecision","BATCH_FLUSH_MS","useTradesScript","setTrades","realtimeTrade","isValidTrade","pendingRef","limitRef","incoming","normalizeRealtimeTrades","batch","deduped","ROW_HEIGHT","HEADER_HEIGHT","PRICE_COL_MAX_W","AGE_COL_MAX_W","HEADER_PRICE_CELL","HEADER_SIZE_CELL","HEADER_AGE_CELL","ROW_INNER_STYLE","ROW_PRICE_CELL","ROW_SIZE_CELL","ROW_AGE_CELL","BUY_BAR_STYLE_BASE","SELL_BAR_STYLE_BASE","formatUsd","usd","formatAge","ageMs","barWidth","TradeRow","style","onTradeClick","birthday","useTickAge","isBuy","TradesUI","listContainerRef","useResizeObserver","rowProps","List","SKEL_HEADER_PRICE_CELL","SKEL_HEADER_SIZE_CELL","SKEL_HEADER_AGE_CELL","TradeSkelRow","TradesSkeleton","rows","TradesEmpty","TradesWidget","signFor","kind","deriveTpSlPercent","entry","leverage","deriveTpSlPrice","percent","sign","priceΔ","roundTpSlPrice","magnitude","factor","roundTpSlPercent","FALLBACK_LEVERAGE","usePlaceOrderFormScript","maxLeverageProp","onSuccess","onUpdateLeverage","onPlaceOrder","setSide","orderType","setOrderType","form","useForm","assetMeta","szDecimals","resolvedMaxLeverage","createOrderViaClient","isClientPending","placeOrderViaHostMutation","request","isSubmitting","watchedValues","amount","notional","estimatedFee","estimatedTotal","liquidationPrice","l","offset","positionsData","accountValue","availableMargin","currentPosition","account","hasOpenOrdersForSymbol","activeAssetLeverage","currentLeverage","isLeverageReady","lastSyncedSymbolRef","handleSubmit","finalPrice","takeProfitPrice","stopLossPrice","size","BRAND_PRIMARY","SIDE_LONG_COLOR","SIDE_SHORT_COLOR","BRAND_DANGER","withAlpha","hex","alpha","HYPERLIQUID_ICON_CDN","MIN_NOTIONAL_USDC","sanitiseAmountInput","cleaned","parts","inlineTextSkeleton","formatLiqPrice","LEVERAGE_MIN","buildLeverageMarks","max","ceiling","niceRound","ticks","pct","LeverageModal","isOpen","initialLeverage","maxLeverage","coinName","hasOpenPosition","hasOpenOrders","onConfirm","onUpdate","onClose","draft","setDraft","pending","setPending","handleConfirm","guardedConfirm","useAuthCallback","StyledModal","ModalContent","XCloseIcon","Slider","Spinner","BuyAmountInput","methods","formValue","numericValue","inputText","setInputText","inputRef","isFocused","parsedPrev","valuesAgree","handleChange","handleKeyDownCapture","formatTpSlNumber","TpSlInput","field","placeholder","refPrice","isPriceField","partnerField","partnerValue","rounded","PlaceOrderFormUI","onSideChange","onOrderTypeChange","onSubmit","onAddFunds","addFundsFallback","guardedAddFunds","guardedSubmit","showLeverageModal","setShowLeverageModal","showTpSl","setShowTpSl","rawAmount","hasAmount","tokenSymbol","positionPercent","handlePositionSlider","tokenQuantity","minMarginUsdc","submitState","handleSubmitButtonClick","formatTokenQuantity","n","StyledTooltip","tab","RHForm","RHNumberInput","isSubmit","buttonType","activeBg","activeColor","isPlacing","PlaceOrderFormWidget","resolvedOnUpdateLeverage","getSortValue","comparePositions","aVal","bVal","usePositionsScript","onCloseSuccess","onCloseError","sortKey","setSortKey","sortDir","setSortDir","onSort","currentKey","d","isClosing","sortedPositions","handleClosePosition","closeSide","formatUsdPrice","abs","dp","formatUsd2","formatSignedUsd2","formatPercentAbs","COL_STYLE","TABLE_MIN_WIDTH","HEADER_ROW_STYLE","BODY_ROW_STYLE","ALIGN_TO_JUSTIFY","HeaderCell","activeSortKey","align","arrow","interactive","justify","inner","cn","PositionsUI","onClosePosition","useTranslation","header","PositionRow","striped","directionLabel","directionColor","pnlColor","PositionsSkeleton","PositionsEmpty","PositionsWidget","useOpenOrdersScript","onCancelSuccess","onCancelError","setOrders","ordersData","realtimeOrder","isCanceling","prevOrders","existingIndex","newOrders","handleCancelOrder","formatTime","timestamp","date","OpenOrdersUI","onCancelOrder","Button","OpenOrdersSkeleton","OpenOrdersEmpty","OpenOrdersWidget","getTimeRangeInMs","range","today","useTradeHistoryScript","initialTimeRange","pageSize","timeRange","setTimeRange","currentPage","setCurrentPage","allTrades","setAllTrades","tradesData","totalPages","startIndex","endIndex","page","formatDateTime","month","day","TIME_RANGE_OPTIONS","TradeHistoryUI","onTimeRangeChange","onNextPage","onPreviousPage","onGoToPage","option","pageNum","TradeHistorySkeleton","TradeHistoryEmpty","TradeHistoryWidget","goToNextPage","goToPreviousPage","goToPage","LAMPORTS_PER_SOL","HL_USDC_DECIMALS","HL_USDC_DIVISOR","lamportsToSol","divToFixed","hlUsdcRawToUsdc","microUsdcToUsdc","solToLamports","whole","frac","fracPadded","combined","numerator","denominator","negative","scale","scaledRemainder","secondsUntil","expiresAtMs","nowMs","shortAddress","addr","head","tail","DepositConfirmUI","isExecuting","isExpired","onCancel","onExpire","secondsLeft","setSecondsLeft","id","remaining","Modal","ModalHeader","ModalBody","BreakdownSummary","ModalFooter","breakdown","Row","label","highlight","muted","DepositFormUI","onAmountChange","recipient","onRecipientChange","balanceSol","disabled","amountError","recipientError","onMax","Input","ACCENT","DepositStatusUI","phase","solanaExplorerUrl","hyperliquidExplorerUrl","onRetry","errorMessage","variant","phaseToVariant","showRetry","PhaseIcon","variantTextClass","TxLink","href","hash","ExternalLinkIcon","AccentSpinner","CheckCircle","AlertCircle","XCircle","props","DepositFlowWidget","userSolanaAddress","userId","source","campaign","defaultRecipient","onMaxClick","validateRecipient","buildSolanaExplorerUrl","buildHyperliquidExplorerUrl","onSettled","setAmount","setRecipient","grossLamports","quoteReq","quoteQ","statusQ","handleContinue","handleExpire","handleRetry","showConfirm","showStatus","continueDisabled","Card","CardBody","HyperliquidInitUI","onContinue","onRetryStep","onReload","onDismiss","isLoadError","CardHeader","LoadingRow","SetupStepRow","CardFooter","isCurrent","title","stepTitle","description","bps","statusLabel","StepIcon","statusBadgeClass","_id","compute","HyperliquidInitWidget","handleReload"],"mappings":"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","file":"index.js","sourcesContent":["declare global {\n interface Window {\n __LIBERFI_VERSION__?: {\n [key: string]: string;\n };\n }\n}\nif (typeof window !== \"undefined\") {\n window.__LIBERFI_VERSION__ = window.__LIBERFI_VERSION__ || {};\n window.__LIBERFI_VERSION__[\"@liberfi.io/ui-perpetuals\"] = \"0.2.22\";\n}\n\nexport default \"0.2.22\";\n","import type { Kline, MarketData } from \"../../types\";\n\n/**\n * WebSocket subscription callback function type\n */\ntype SubscriptionCallback = (data: any) => void;\n\n/**\n * Hyperliquid `l2Book` aggregation parameters.\n *\n * Sending these on the `subscribe` payload causes Hyperliquid to pre-aggregate\n * raw price levels into discrete buckets server-side, so a single 20-level\n * snapshot covers a much wider price range than at native tick resolution.\n *\n * - `nSigFigs`: number of significant figures (2..5) to round prices to.\n * `undefined` (or `null`) means full native precision.\n * - `mantissa`: only valid when `nSigFigs === 5`. Allowed values: 1, 2, 5.\n * At BTC ~$80k with `nSigFigs=5`, mantissa controls the smallest digit:\n * 1 → step $1, 2 → step $2, 5 → step $5.\n *\n * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint\n */\nexport interface OrderBookAggregation {\n nSigFigs?: 2 | 3 | 4 | 5;\n mantissa?: 1 | 2 | 5;\n}\n\n/**\n * WebSocket subscription metadata\n */\ninterface Subscription {\n type: string;\n param: string;\n callback: SubscriptionCallback;\n aggregation?: OrderBookAggregation;\n}\n\n/**\n * Build a stable map key for a (type, param, aggregation) triple. Different\n * aggregations of the same coin are separate subscriptions because Hyperliquid\n * pushes a different stream for each — they must not share storage.\n */\nfunction aggregationKey(\n type: string,\n param: string,\n aggregation?: OrderBookAggregation,\n): string {\n if (\n type !== \"orderBook\" ||\n !aggregation ||\n aggregation.nSigFigs === undefined\n ) {\n return `${type}:${param}`;\n }\n const m =\n aggregation.nSigFigs === 5 &&\n aggregation.mantissa &&\n aggregation.mantissa !== 1\n ? `:m${aggregation.mantissa}`\n : \"\";\n return `${type}:${param}:n${aggregation.nSigFigs}${m}`;\n}\n\n/**\n * WebSocket Manager for Hyperliquid\n *\n * Handles WebSocket connection lifecycle, including:\n * - Connection management (connect/disconnect)\n * - Automatic reconnection with exponential backoff\n * - Heartbeat to keep connection alive\n * - Subscription management (subscribe/unsubscribe)\n * - Message queue for offline messages\n */\nexport class WebSocketManager {\n private ws: WebSocket | null = null;\n private wsEndpoint: string;\n private subscriptions: Map<string, Subscription> = new Map();\n private reconnectAttempts: number = 0;\n private maxReconnectAttempts: number = 10;\n private reconnectDelay: number = 1000; // Initial reconnect delay: 1 second\n private heartbeatInterval: number | null = null;\n private messageQueue: any[] = []; // Message queue before connection established\n private isConnected: boolean = false;\n private pingInterval: number = 30000; // 30 second heartbeat\n private reconnectTimeout: number | null = null;\n private isReconnecting: boolean = false;\n private connectPromise: Promise<void> | null = null;\n private manuallyDisconnected: boolean = false;\n\n /**\n * Create a new WebSocketManager\n * @param wsEndpoint WebSocket endpoint URL\n */\n constructor(wsEndpoint: string) {\n this.wsEndpoint = wsEndpoint;\n }\n\n /**\n * Connect to WebSocket server\n * @returns Promise that resolves when connection is established\n */\n async connect(): Promise<void> {\n if (this.isConnected && this.ws?.readyState === WebSocket.OPEN) {\n return;\n }\n\n if (this.connectPromise) {\n return this.connectPromise;\n }\n\n this.manuallyDisconnected = false;\n\n this.connectPromise = new Promise((resolve, reject) => {\n let settled = false;\n\n const settle = (callback: () => void) => {\n if (settled) return;\n settled = true;\n this.connectPromise = null;\n callback();\n };\n\n try {\n const ws = new WebSocket(this.wsEndpoint);\n this.ws = ws;\n\n ws.onopen = () => {\n if (this.ws !== ws) return;\n console.log(\"[WebSocket] Connected to Hyperliquid\");\n this.isConnected = true;\n this.reconnectAttempts = 0;\n this.isReconnecting = false;\n this.startHeartbeat();\n this.flushMessageQueue();\n settle(resolve);\n };\n\n ws.onmessage = (event: MessageEvent) => {\n if (this.ws !== ws) return;\n this.handleMessage(event.data);\n };\n\n ws.onerror = (error: Event) => {\n if (this.ws !== ws) return;\n console.error(\"[WebSocket] Error:\", error);\n this.isConnected = false;\n settle(() => reject(new Error(\"WebSocket connection failed\")));\n };\n\n ws.onclose = (event: CloseEvent) => {\n if (this.ws !== ws) return;\n console.log(\n `[WebSocket] Closed: ${event.code} - ${event.reason || \"No reason provided\"}`,\n );\n this.isConnected = false;\n this.stopHeartbeat();\n this.connectPromise = null;\n\n // Only attempt reconnect if not manually disconnected (code 1000 = normal closure)\n if (!settled) {\n settle(() =>\n reject(\n new Error(\n `WebSocket closed before connection was established: ${event.code}`,\n ),\n ),\n );\n }\n\n if (!this.manuallyDisconnected && event.code !== 1000) {\n this.attemptReconnect();\n }\n };\n } catch (error) {\n settle(() => reject(error));\n }\n });\n\n return this.connectPromise;\n }\n\n /**\n * Disconnect from WebSocket server\n */\n disconnect(): void {\n this.manuallyDisconnected = true;\n this.stopHeartbeat();\n this.subscriptions.clear();\n\n // Clear reconnect timeout\n if (this.reconnectTimeout !== null) {\n clearTimeout(this.reconnectTimeout);\n this.reconnectTimeout = null;\n }\n\n if (this.ws) {\n this.ws.close(1000, \"Normal closure\");\n this.ws = null;\n }\n\n this.isConnected = false;\n this.isReconnecting = false;\n this.reconnectAttempts = 0;\n }\n\n /**\n * Attempt to reconnect with exponential backoff\n */\n private attemptReconnect(): void {\n if (this.isReconnecting) {\n return; // Already attempting to reconnect\n }\n\n if (this.reconnectAttempts >= this.maxReconnectAttempts) {\n console.error(\"[WebSocket] Max reconnection attempts reached\");\n return;\n }\n\n this.isReconnecting = true;\n this.reconnectAttempts++;\n\n // Exponential backoff: min(1000 * 2^attempts, 30000)\n const delay = Math.min(\n this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1),\n 30000, // Max 30 seconds\n );\n\n console.log(\n `[WebSocket] Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts}/${this.maxReconnectAttempts})`,\n );\n\n this.reconnectTimeout = window.setTimeout(() => {\n this.connect()\n .then(() => {\n // Resubscribe to all previous subscriptions\n this.resubscribeAll();\n })\n .catch((error) => {\n console.error(\"[WebSocket] Reconnection failed:\", error);\n this.isReconnecting = false;\n // attemptReconnect will be called again by onclose event\n });\n }, delay);\n }\n\n /**\n * Start heartbeat interval to keep connection alive\n */\n private startHeartbeat(): void {\n this.heartbeatInterval = window.setInterval(() => {\n if (\n this.isConnected &&\n this.ws &&\n this.ws.readyState === WebSocket.OPEN\n ) {\n // Send a ping message to keep connection alive\n // Hyperliquid WebSocket accepts JSON messages\n this.send({ method: \"ping\" });\n }\n }, this.pingInterval);\n }\n\n /**\n * Stop heartbeat interval\n */\n private stopHeartbeat(): void {\n if (this.heartbeatInterval !== null) {\n clearInterval(this.heartbeatInterval);\n this.heartbeatInterval = null;\n }\n }\n\n /**\n * Send message to WebSocket server\n * @param message Message object to send\n */\n private send(message: any): void {\n if (this.isConnected && this.ws && this.ws.readyState === WebSocket.OPEN) {\n this.ws.send(JSON.stringify(message));\n } else {\n // Connection not established, add to queue\n this.messageQueue.push(message);\n }\n }\n\n /**\n * Flush message queue after connection established\n */\n private flushMessageQueue(): void {\n while (this.messageQueue.length > 0) {\n const message = this.messageQueue.shift();\n if (message) {\n this.send(message);\n }\n }\n }\n\n /**\n * Resubscribe to all subscriptions after reconnection\n */\n private resubscribeAll(): void {\n this.subscriptions.forEach((subscription) => {\n this.sendSubscription(\n subscription.type,\n subscription.param,\n subscription.aggregation,\n );\n });\n }\n\n /**\n * Handle incoming WebSocket message\n * @param data Raw message data\n */\n private handleMessage(data: string): void {\n try {\n const message = JSON.parse(data);\n\n // Handle different message types\n if (message.channel) {\n this.handleChannelMessage(message);\n } else if (message.method === \"pong\") {\n // Heartbeat response\n // No action needed\n }\n } catch (error) {\n console.error(\"[WebSocket] Failed to parse message:\", error, data);\n }\n }\n\n /**\n * Handle channel-specific messages\n * @param message Parsed message object\n */\n private handleChannelMessage(message: any): void {\n const channel = message.channel;\n\n // Find matching subscriptions and trigger callbacks\n this.subscriptions.forEach((subscription, subscriptionId) => {\n if (\n this.isChannelMatch(\n channel,\n subscription.type,\n subscription.param,\n message,\n )\n ) {\n try {\n const transformedData = this.transformData(\n subscription.type,\n message.data,\n subscription.param,\n );\n subscription.callback(transformedData);\n } catch (error) {\n console.error(\n `[WebSocket] Error in subscription callback (${subscriptionId}):`,\n error,\n );\n }\n }\n });\n }\n\n /**\n * Check if channel matches subscription\n *\n * For per-coin channels (ticker via `activeAssetCtx`, trades, orderBook,\n * candle), we additionally match the coin in the payload against the\n * subscription parameter so a single multiplexed connection can feed many\n * subscriptions without cross-talk.\n *\n * @param channel Channel name from message\n * @param type Subscription type\n * @param param Subscription parameter (e.g. \"BTC-USDC\", \"BTC-USDC:1m\")\n * @param message Full parsed message (used to read payload coin)\n * @returns True if channel matches subscription\n */\n private isChannelMatch(\n channel: string,\n type: string,\n param: string,\n message: any,\n ): boolean {\n if (type === \"ticker\") {\n if (channel !== \"activeAssetCtx\") return false;\n const expectedCoin = param.split(\"-\")[0];\n const payloadCoin = message?.data?.coin;\n return typeof payloadCoin === \"string\" && payloadCoin === expectedCoin;\n } else if (type === \"trades\") {\n if (channel !== \"trades\") return false;\n const expectedCoin = param.split(\"-\")[0];\n // `trades` payload is an array; check the first element's coin if any.\n const payloadCoin = Array.isArray(message?.data)\n ? message.data[0]?.coin\n : undefined;\n return typeof payloadCoin !== \"string\" || payloadCoin === expectedCoin;\n } else if (type === \"orderBook\") {\n if (channel !== \"l2Book\") return false;\n const expectedCoin = param.split(\"-\")[0];\n const payloadCoin = message?.data?.coin;\n return typeof payloadCoin === \"string\" && payloadCoin === expectedCoin;\n } else if (type === \"candle\") {\n return channel === \"candle\";\n } else if (type === \"userFills\") {\n return channel === \"userFills\";\n } else if (type === \"userEvents\") {\n return channel === \"userEvents\";\n } else if (type === \"accountState\") {\n // `webData2` is Hyperliquid's unified per-user push channel: each\n // payload carries the full clearinghouseState + spotState + open\n // orders snapshot. Match purely on channel — the upstream filters\n // by `user`, so cross-talk is impossible.\n return channel === \"webData2\";\n }\n\n return false;\n }\n\n /**\n * Transform raw data to standard format\n * @param type Subscription type\n * @param data Raw data from WebSocket\n * @param param Subscription parameter (e.g., symbol, interval)\n * @returns Transformed data\n */\n private transformData(type: string, data: any, param: string): any {\n if (type === \"ticker\") {\n return this.transformTickerData(data, param);\n } else if (type === \"trades\") {\n return this.transformTradesData(data, param);\n } else if (type === \"orderBook\") {\n return this.transformOrderBookData(data, param);\n } else if (type === \"candle\") {\n return this.transformCandleData(data, param);\n } else if (type === \"userFills\") {\n return this.transformUserFillsData(data);\n } else if (type === \"userEvents\") {\n return this.transformUserEventsData(data);\n }\n\n return data;\n }\n\n /**\n * Transform ticker data (Hyperliquid `activeAssetCtx` channel).\n *\n * Each push delivers the full per-coin market context — mark/mid price,\n * `prevDayPx` (so we can compute 24h change client-side), notional volume,\n * funding, open interest, oracle price, etc. We map this into the\n * standard {@link MarketData} shape so consumers (`useCoinInfo`, ticker\n * widgets, etc.) get a real-time, complete snapshot in one shot — no\n * second REST call required to fill in 24h change.\n *\n * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/websocket\n */\n private transformTickerData(data: any, param: string): MarketData {\n const coin: string = data?.coin ?? param.split(\"-\")[0];\n const symbol = `${coin}-USDC`;\n const ctx = data?.ctx ?? {};\n\n const mid = parseFloat(ctx.midPx ?? ctx.markPx ?? \"0\");\n const mark = parseFloat(ctx.markPx ?? ctx.midPx ?? \"0\");\n const prev = ctx.prevDayPx ? parseFloat(ctx.prevDayPx) : mid;\n const change24h = prev > 0 ? ((mid - prev) / prev) * 100 : 0;\n\n return {\n symbol,\n price: mid,\n change24h,\n volume24h: parseFloat(ctx.dayNtlVlm ?? \"0\"),\n fundingRate: parseFloat(ctx.funding ?? \"0\"),\n openInterest: parseFloat(ctx.openInterest ?? \"0\"),\n markPrice: mark,\n indexPrice: parseFloat(ctx.oraclePx ?? ctx.midPx ?? \"0\"),\n };\n }\n\n /**\n * Transform trades data\n */\n private transformTradesData(data: any, symbol: string): any {\n if (!Array.isArray(data)) {\n return [];\n }\n\n return data.map((trade: any) => ({\n symbol,\n side: trade.side === \"B\" ? \"buy\" : \"sell\",\n price: parseFloat(trade.px),\n quantity: parseFloat(trade.sz),\n timestamp: trade.time,\n tradeId: trade.tid,\n }));\n }\n\n /**\n * Transform order book data\n */\n private transformOrderBookData(data: any, symbol: string): any {\n const [bids, asks] = data.levels || [[], []];\n\n return {\n symbol,\n bids: bids.map((level: any) => ({\n price: parseFloat(level.px),\n quantity: parseFloat(level.sz),\n count: level.n,\n })),\n asks: asks.map((level: any) => ({\n price: parseFloat(level.px),\n quantity: parseFloat(level.sz),\n count: level.n,\n })),\n timestamp: data.time || Date.now(),\n };\n }\n\n /**\n * Transform candle data\n */\n private transformCandleData(data: any, param: string): Kline {\n const [symbol] = param.split(\":\");\n\n return {\n symbol,\n open: parseFloat(data.o),\n high: parseFloat(data.h),\n low: parseFloat(data.l),\n close: parseFloat(data.c),\n volume: parseFloat(data.v),\n timestamp: data.t,\n closeTimestamp: data.T,\n };\n }\n\n /**\n * Transform user fills data\n */\n private transformUserFillsData(data: any): any {\n if (!Array.isArray(data)) {\n return [];\n }\n\n return data.map((fill: any) => ({\n tradeId: fill.tid?.toString(),\n orderId: fill.oid?.toString(),\n symbol: `${fill.coin}-USDC`,\n side: fill.dir?.includes(\"Long\") ? \"long\" : \"short\",\n price: parseFloat(fill.px),\n quantity: parseFloat(fill.sz),\n fee: parseFloat(fill.fee || \"0\"),\n feeCurrency: fill.feeToken || \"USDC\",\n isMaker: fill.side === \"M\",\n timestamp: fill.time,\n }));\n }\n\n /**\n * Transform user events data (orders and positions)\n */\n private transformUserEventsData(data: any): any {\n // User events can contain both order updates and position updates\n // Return the data as-is for now, let the callback handle it\n return data;\n }\n\n /**\n * Send subscription message to Hyperliquid WebSocket\n * @param type Subscription type\n * @param param Subscription parameter\n * @param aggregation Optional orderBook aggregation params (nSigFigs/mantissa)\n */\n private sendSubscription(\n type: string,\n param: string,\n aggregation?: OrderBookAggregation,\n ): void {\n let subscription: any;\n\n if (type === \"ticker\") {\n // Subscribe to per-coin `activeAssetCtx` so each push carries a full\n // market snapshot (mark/mid price, prevDayPx for 24h change, volume,\n // funding, open interest). This avoids the limitations of `allMids`,\n // which only streams price.\n const coin = param.split(\"-\")[0]; // \"BTC-USDC\" -> \"BTC\"\n subscription = {\n method: \"subscribe\",\n subscription: {\n type: \"activeAssetCtx\",\n coin,\n },\n };\n } else if (type === \"trades\") {\n // Subscribe to trades for specific coin\n const coin = param.split(\"-\")[0]; // \"BTC-USDC\" -> \"BTC\"\n subscription = {\n method: \"subscribe\",\n subscription: {\n type: \"trades\",\n coin,\n },\n };\n } else if (type === \"orderBook\") {\n // Subscribe to order book for specific coin. nSigFigs/mantissa let\n // Hyperliquid pre-aggregate the 20-level snapshot to a coarser grid,\n // dramatically widening the price range covered by a single payload.\n const coin = param.split(\"-\")[0];\n const sub: Record<string, unknown> = {\n type: \"l2Book\",\n coin,\n };\n if (aggregation?.nSigFigs !== undefined) {\n sub.nSigFigs = aggregation.nSigFigs;\n if (\n aggregation.nSigFigs === 5 &&\n aggregation.mantissa !== undefined &&\n aggregation.mantissa !== 1\n ) {\n sub.mantissa = aggregation.mantissa;\n }\n }\n subscription = {\n method: \"subscribe\",\n subscription: sub,\n };\n } else if (type === \"candle\") {\n // Subscribe to candles\n const [symbol, interval] = param.split(\":\");\n const coin = symbol.split(\"-\")[0];\n subscription = {\n method: \"subscribe\",\n subscription: {\n type: \"candle\",\n coin,\n interval,\n },\n };\n } else if (type === \"userFills\") {\n // Subscribe to user fills\n const userAddress = param;\n subscription = {\n method: \"subscribe\",\n subscription: {\n type: \"userFills\",\n user: userAddress,\n },\n };\n } else if (type === \"userEvents\") {\n // Subscribe to user events (orders + positions)\n const userAddress = param;\n subscription = {\n method: \"subscribe\",\n subscription: {\n type: \"userEvents\",\n user: userAddress,\n },\n };\n } else if (type === \"accountState\") {\n // `webData2` ships every clearinghouseState / spotState / openOrders\n // snapshot for the user on a single subscription, so a single\n // socket can drive the entire account-state surface (positions,\n // available margin, spot balances, open orders) without per-field\n // REST polling.\n const userAddress = param;\n subscription = {\n method: \"subscribe\",\n subscription: {\n type: \"webData2\",\n user: userAddress,\n },\n };\n }\n\n if (subscription) {\n this.send(subscription);\n }\n }\n\n /**\n * Send unsubscription message to Hyperliquid WebSocket\n * @param type Subscription type\n * @param param Subscription parameter\n * @param aggregation Aggregation params used at subscribe time. Hyperliquid\n * matches subscriptions by full payload, so unsubscribe must echo the\n * same nSigFigs/mantissa.\n */\n private sendUnsubscription(\n type: string,\n param: string,\n aggregation?: OrderBookAggregation,\n ): void {\n let unsubscription: any;\n\n if (type === \"ticker\") {\n const coin = param.split(\"-\")[0];\n unsubscription = {\n method: \"unsubscribe\",\n subscription: {\n type: \"activeAssetCtx\",\n coin,\n },\n };\n } else if (type === \"trades\") {\n const coin = param.split(\"-\")[0];\n unsubscription = {\n method: \"unsubscribe\",\n subscription: {\n type: \"trades\",\n coin,\n },\n };\n } else if (type === \"orderBook\") {\n const coin = param.split(\"-\")[0];\n const sub: Record<string, unknown> = {\n type: \"l2Book\",\n coin,\n };\n if (aggregation?.nSigFigs !== undefined) {\n sub.nSigFigs = aggregation.nSigFigs;\n if (\n aggregation.nSigFigs === 5 &&\n aggregation.mantissa !== undefined &&\n aggregation.mantissa !== 1\n ) {\n sub.mantissa = aggregation.mantissa;\n }\n }\n unsubscription = {\n method: \"unsubscribe\",\n subscription: sub,\n };\n } else if (type === \"candle\") {\n const [symbol, interval] = param.split(\":\");\n const coin = symbol.split(\"-\")[0];\n unsubscription = {\n method: \"unsubscribe\",\n subscription: {\n type: \"candle\",\n coin,\n interval,\n },\n };\n } else if (type === \"userFills\") {\n const userAddress = param;\n unsubscription = {\n method: \"unsubscribe\",\n subscription: {\n type: \"userFills\",\n user: userAddress,\n },\n };\n } else if (type === \"userEvents\") {\n const userAddress = param;\n unsubscription = {\n method: \"unsubscribe\",\n subscription: {\n type: \"userEvents\",\n user: userAddress,\n },\n };\n } else if (type === \"accountState\") {\n const userAddress = param;\n unsubscription = {\n method: \"unsubscribe\",\n subscription: {\n type: \"webData2\",\n user: userAddress,\n },\n };\n }\n\n if (unsubscription) {\n this.send(unsubscription);\n }\n }\n\n /**\n * Subscribe to a data stream\n * @param type Subscription type\n * @param param Subscription parameter (symbol, user address, etc.)\n * @param callback Callback function to receive data\n * @param aggregation Optional `l2Book` aggregation params (only meaningful\n * when `type === \"orderBook\"`). The same params are echoed back in the\n * unsubscribe payload.\n * @returns Subscription ID (for unsubscribing). Aggregation is encoded in\n * the id so multiple aggregations of the same coin can coexist.\n */\n subscribe(\n type: string,\n param: string,\n callback: SubscriptionCallback,\n aggregation?: OrderBookAggregation,\n ): string {\n const subscriptionId = aggregationKey(type, param, aggregation);\n\n // Store subscription\n this.subscriptions.set(subscriptionId, {\n type,\n param,\n callback,\n aggregation,\n });\n\n // Send subscription message\n this.sendSubscription(type, param, aggregation);\n\n return subscriptionId;\n }\n\n /**\n * Unsubscribe from a data stream\n * @param subscriptionId Subscription ID returned from subscribe()\n */\n unsubscribe(subscriptionId: string): void {\n const subscription = this.subscriptions.get(subscriptionId);\n\n if (subscription) {\n // Send unsubscription message\n this.sendUnsubscription(\n subscription.type,\n subscription.param,\n subscription.aggregation,\n );\n\n // Remove subscription\n this.subscriptions.delete(subscriptionId);\n }\n }\n\n /**\n * Check if WebSocket is connected\n * @returns True if connected\n */\n isConnectedNow(): boolean {\n return this.isConnected;\n }\n}\n","import type {\n AccountState,\n IPerpetualsClient,\n MarketData,\n Kline,\n KlineInterval,\n KlineQueryOptions,\n Order,\n OrderBook,\n OrderType,\n Position,\n SpotBalance,\n Trade,\n PlaceOrderParams,\n PlaceOrderResult,\n CancelOrderParams,\n CancelOrderResult,\n GetPositionsParams,\n GetPositionsResult,\n GetOpenOrdersParams,\n GetOpenOrdersResult,\n GetTradesParams,\n GetTradesResult,\n ActiveAssetLeverage,\n GetActiveAssetLeverageParams,\n AssetMeta,\n GetAssetMetaParams,\n} from \"../../types\";\nimport {\n WebSocketManager,\n type OrderBookAggregation,\n} from \"./WebSocketManager\";\n\nexport type { OrderBookAggregation };\n\n/**\n * Hyperliquid 环境类型\n */\nexport type HyperliquidEnvironment = \"testnet\" | \"mainnet\";\n\n/**\n * Hyperliquid 客户端配置\n */\nexport interface HyperliquidClientConfig {\n /**\n * 环境配置\n * @default \"testnet\"\n */\n environment?: HyperliquidEnvironment;\n\n /**\n * 自定义 API 端点(可选)\n * 如果不提供,将根据 environment 自动选择\n */\n apiEndpoint?: string;\n\n /**\n * 自定义 WebSocket 端点(可选)\n * 如果不提供,将根据 environment 自动选择\n */\n wsEndpoint?: string;\n\n /**\n * 请求超时时间(毫秒)\n * @default 30000\n */\n timeout?: number;\n}\n\n/**\n * Hyperliquid API 端点配置\n */\nconst HYPERLIQUID_ENDPOINTS = {\n testnet: {\n api: \"https://api.hyperliquid-testnet.xyz\",\n ws: \"wss://api.hyperliquid-testnet.xyz/ws\",\n },\n mainnet: {\n api: \"https://api.hyperliquid.xyz\",\n ws: \"wss://api.hyperliquid.xyz/ws\",\n },\n} as const;\n\n/**\n * Cache lifetime for the asset universe (`meta` info endpoint).\n * 60 seconds is well below the cadence at which Hyperliquid actually\n * adjusts the universe (typically only on listing additions /\n * delistings, which happen weekly at most), but small enough that\n * stale caches from a previous session don't survive across page\n * loads in long-running tabs.\n */\nconst ASSET_META_TTL_MS = 60 * 1000;\n\n/**\n * HyperliquidPerpetualsClient 类\n *\n * 实现 IPerpetualsClient 接口,提供 Hyperliquid 永续合约交易功能\n */\nexport class HyperliquidPerpetualsClient implements IPerpetualsClient {\n private readonly apiEndpoint: string;\n private readonly _wsEndpoint: string;\n private readonly timeout: number;\n private readonly environment: HyperliquidEnvironment;\n private wsManager: WebSocketManager | null = null;\n /**\n * Reference count of active WebSocket consumers. The connection is\n * established on the first `connectWebSocket()` call and torn down\n * only when the last consumer disconnects — see the matching comment\n * on {@link LiberFiPerpetualsClient}.\n */\n private wsRefCount: number = 0;\n\n /**\n * Process-local memoisation of the venue's asset universe (the\n * `meta` info endpoint). Hyperliquid's universe rarely changes (new\n * listings, leverage cap adjustments) so the SDK caches the parsed\n * map for {@link ASSET_META_TTL_MS} per client instance to spare\n * downstream consumers a network round-trip on every render.\n *\n * The TanStack Query layer adds another tier of caching above this\n * (per `staleTime`), but caching here too keeps the contract correct\n * for non-React callers that talk to the client directly.\n */\n private assetMetaCache: {\n fetchedAt: number;\n map: Map<string, AssetMeta>;\n } | null = null;\n /**\n * In-flight `getAssetMeta` request, deduped so concurrent callers\n * collapse onto a single network request when the cache misses.\n */\n private assetMetaPending: Promise<Map<string, AssetMeta>> | null = null;\n\n /**\n * 构造 Hyperliquid 客户端\n *\n * @param config 客户端配置,不传则使用默认配置(testnet)\n */\n constructor(config: HyperliquidClientConfig = {}) {\n // 1. 确定环境\n this.environment = config.environment || \"testnet\";\n\n // 2. 确定 API 端点\n this.apiEndpoint =\n config.apiEndpoint || HYPERLIQUID_ENDPOINTS[this.environment].api;\n\n // 3. 确定 WebSocket 端点\n this._wsEndpoint =\n config.wsEndpoint || HYPERLIQUID_ENDPOINTS[this.environment].ws;\n\n // 4. 设置超时时间\n this.timeout = config.timeout || 30000;\n }\n\n /**\n * 内部 HTTP 请求方法\n *\n * @param endpoint API 端点路径\n * @param body 请求体\n * @returns 响应数据\n * @throws {HyperliquidApiError} API 请求失败\n */\n private async request<T = any>(endpoint: string, body: any): Promise<T> {\n const url = `${this.apiEndpoint}${endpoint}`;\n\n try {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n const response = await fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n throw new HyperliquidApiError(\n `HTTP ${response.status}: ${response.statusText}`,\n response.status,\n await response.text(),\n );\n }\n\n const data = await response.json();\n return data;\n } catch (error: any) {\n if (error.name === \"AbortError\") {\n throw new HyperliquidApiError(\n `Request timeout after ${this.timeout}ms`,\n 408,\n \"\",\n );\n }\n\n if (error instanceof HyperliquidApiError) {\n throw error;\n }\n\n throw new HyperliquidApiError(`Network error: ${error.message}`, 0, \"\");\n }\n }\n\n /**\n * 辅助方法:将符号格式转换为 Hyperliquid 币种名称\n * @param symbol 统一格式符号(例如 \"BTC-USDC\")\n * @returns Hyperliquid 币种名称(例如 \"BTC\")\n */\n private symbolToCoin(symbol: string): string {\n return symbol.split(\"-\")[0];\n }\n\n /**\n * 辅助方法:将 KlineInterval 转换为毫秒数\n * @param interval K线时间间隔\n * @returns 毫秒数\n */\n private parseInterval(interval: KlineInterval): number {\n const intervalMap: Record<KlineInterval, number> = {\n \"1m\": 60 * 1000,\n \"5m\": 5 * 60 * 1000,\n \"15m\": 15 * 60 * 1000,\n \"30m\": 30 * 60 * 1000,\n \"1h\": 60 * 60 * 1000,\n \"4h\": 4 * 60 * 60 * 1000,\n \"1d\": 24 * 60 * 60 * 1000,\n \"1w\": 7 * 24 * 60 * 60 * 1000,\n };\n return intervalMap[interval];\n }\n\n // ===================================\n // 市场数据查询接口(6个方法)\n // ===================================\n\n /**\n * 获取所有支持的币种列表\n * @returns 币种符号数组\n * @throws {HyperliquidApiError} API 请求失败\n */\n async getSupportedCoins(): Promise<string[]> {\n const [meta] = await this.request<[{ universe: Array<{ name: string }> }]>(\n \"/info\",\n { type: \"metaAndAssetCtxs\" },\n );\n\n // 转换:coin.name -> \"BTC-USDC\"\n return meta.universe.map((asset) => `${asset.name}-USDC`);\n }\n\n /**\n * 获取指定币种的市场数据\n * @param symbol 币种符号\n * @returns 市场数据,币种不存在时返回 null\n * @throws {HyperliquidApiError} API 请求失败\n */\n async getMarket(symbol: string): Promise<MarketData | null> {\n const markets = await this.getMarkets([symbol]);\n return markets.length > 0 ? markets[0] : null;\n }\n\n /**\n * 获取多个或所有币种的市场数据\n * @param symbols 币种符号数组(可选)\n * @returns 市场数据数组\n * @throws {HyperliquidApiError} API 请求失败\n */\n async getMarkets(symbols?: string[]): Promise<MarketData[]> {\n const [meta, assetCtxs] = await this.request<\n [\n { universe: Array<{ name: string }> },\n Array<{\n funding?: string;\n openInterest?: string;\n prevDayPx?: string;\n dayNtlVlm?: string;\n oraclePx?: string;\n markPx?: string;\n midPx?: string;\n }>,\n ]\n >(\"/info\", { type: \"metaAndAssetCtxs\" });\n\n // 合并 meta 和 assetCtxs 数据\n const allMarkets = meta.universe.map((asset, index) => {\n const ctx = assetCtxs[index];\n const symbol = `${asset.name}-USDC`;\n\n // 使用 midPx 作为当前价格,fallback 到 markPx\n const currentPrice = parseFloat(ctx.midPx || ctx.markPx || \"0\");\n const prevPrice = ctx.prevDayPx\n ? parseFloat(ctx.prevDayPx)\n : currentPrice;\n const change24h =\n prevPrice > 0 ? ((currentPrice - prevPrice) / prevPrice) * 100 : 0;\n\n return {\n symbol,\n price: currentPrice,\n change24h,\n volume24h: parseFloat(ctx.dayNtlVlm || \"0\"),\n fundingRate: parseFloat(ctx.funding || \"0\"),\n openInterest: parseFloat(ctx.openInterest || \"0\"),\n markPrice: parseFloat(ctx.markPx || \"0\"),\n indexPrice: parseFloat(ctx.oraclePx || ctx.midPx || \"0\"),\n } as MarketData;\n });\n\n // 如果指定了 symbols,进行过滤\n if (symbols && symbols.length > 0) {\n const symbolSet = new Set(symbols);\n return allMarkets.filter((m) => symbolSet.has(m.symbol));\n }\n\n return allMarkets;\n }\n\n /**\n * Fetch kline / candlestick data.\n *\n * Supports both shapes documented on\n * {@link IPerpetualsClient.getKlines}:\n *\n * - `getKlines(symbol, interval, limit)` — last `limit` candles ending now.\n * - `getKlines(symbol, interval, { from, to, limit? })` — explicit window\n * for backward history pagination (TradingView pan).\n *\n * Maps to Hyperliquid's `candleSnapshot` which natively accepts\n * `startTime` / `endTime` (ms epochs).\n *\n * @throws {HyperliquidApiError}\n */\n async getKlines(\n symbol: string,\n interval: KlineInterval,\n limitOrOptions: number | KlineQueryOptions = 100,\n ): Promise<Kline[]> {\n const coin = this.symbolToCoin(symbol);\n const options: KlineQueryOptions =\n typeof limitOrOptions === \"number\"\n ? { limit: limitOrOptions }\n : limitOrOptions;\n\n const intervalMs = this.parseInterval(interval);\n const limit = options.limit;\n\n // Resolve the [startTime, endTime] window:\n // - Range mode: caller provides from/to → use them directly.\n // - Legacy mode: derive a [now - limit*interval, now] window.\n // - Mixed: range with limit → honor the explicit window, slice to limit.\n let startTime: number;\n let endTime: number;\n if (options.from !== undefined && options.to !== undefined) {\n startTime = options.from;\n endTime = options.to;\n } else if (options.to !== undefined && limit) {\n endTime = options.to;\n startTime = endTime - intervalMs * limit;\n } else if (options.from !== undefined && limit) {\n startTime = options.from;\n endTime = startTime + intervalMs * limit;\n } else {\n endTime = Date.now();\n startTime = endTime - intervalMs * (limit ?? 100);\n }\n\n const data = await this.request<\n Array<{\n t: number;\n T: number;\n s: string;\n i: string;\n o: string;\n c: string;\n h: string;\n l: string;\n v: string;\n n: number;\n }>\n >(\"/info\", {\n type: \"candleSnapshot\",\n req: { coin, interval, startTime, endTime },\n });\n\n let bars: Kline[] = data.map((candle) => ({\n symbol,\n open: parseFloat(candle.o),\n high: parseFloat(candle.h),\n low: parseFloat(candle.l),\n close: parseFloat(candle.c),\n volume: parseFloat(candle.v),\n timestamp: candle.t,\n closeTimestamp: candle.T,\n }));\n\n // When the caller asked for a hard cap (limit), keep the most recent N.\n if (limit && bars.length > limit) {\n bars = bars.slice(bars.length - limit);\n }\n return bars;\n }\n\n /**\n * Get the order book.\n *\n * @param symbol Trading pair symbol (e.g. `BTC-USDC`)\n * @param maxLevel Max number of levels to keep per side (post-slice)\n * @param options Optional Hyperliquid `l2Book` aggregation params. When\n * provided, Hyperliquid pre-aggregates raw levels into discrete buckets\n * server-side, so a single 20-level snapshot covers a much wider price\n * range than at native tick resolution. See {@link OrderBookAggregation}.\n * @returns Order book data\n * @throws {HyperliquidApiError} API 请求失败\n */\n async getOrderBook(\n symbol: string,\n maxLevel: number = 10,\n options?: OrderBookAggregation,\n ): Promise<OrderBook> {\n const coin = this.symbolToCoin(symbol);\n\n const body: Record<string, unknown> = { type: \"l2Book\", coin };\n if (options?.nSigFigs !== undefined) {\n body.nSigFigs = options.nSigFigs;\n if (\n options.nSigFigs === 5 &&\n options.mantissa !== undefined &&\n options.mantissa !== 1\n ) {\n body.mantissa = options.mantissa;\n }\n }\n\n const data = await this.request<{\n coin: string;\n time: number;\n levels: [\n Array<{ px: string; sz: string; n: number }>,\n Array<{ px: string; sz: string; n: number }>,\n ];\n }>(\"/info\", body);\n\n const [bids, asks] = data.levels;\n\n return {\n symbol,\n bids: bids.slice(0, maxLevel).map((level) => ({\n price: parseFloat(level.px),\n quantity: parseFloat(level.sz),\n count: level.n,\n })),\n asks: asks.slice(0, maxLevel).map((level) => ({\n price: parseFloat(level.px),\n quantity: parseFloat(level.sz),\n count: level.n,\n })),\n timestamp: data.time,\n };\n }\n\n /**\n * 获取最近成交记录\n * @param symbol 交易对符号\n * @param limit 最大成交记录数\n * @returns 成交记录数组\n * @throws {HyperliquidApiError} API 请求失败\n */\n async getRecentTrades(symbol: string, limit: number = 50): Promise<Trade[]> {\n const coin = this.symbolToCoin(symbol);\n\n const data = await this.request<\n Array<{\n coin: string;\n side: string;\n px: string;\n sz: string;\n time: number;\n tid: number;\n }>\n >(\"/info\", { type: \"recentTrades\", coin });\n\n return data.slice(0, limit).map((trade) => ({\n symbol,\n side: trade.side === \"B\" ? \"buy\" : \"sell\",\n price: parseFloat(trade.px),\n quantity: parseFloat(trade.sz),\n timestamp: trade.time,\n tradeId: trade.tid,\n }));\n }\n\n // ===================================\n // 交易操作接口(2个方法)\n // ===================================\n\n /**\n * 下单(买入或卖出合约)\n *\n * ⚠️ 注意:此方法需要配置钱包私钥进行 EIP-712 签名认证\n *\n * @param params 下单参数\n * @returns 下单结果\n * @throws {HyperliquidApiError} API 请求失败、余额不足、参数错误等\n * @throws {Error} 未配置认证信息\n *\n * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint\n */\n async placeOrder(_params: PlaceOrderParams): Promise<PlaceOrderResult> {\n throw new Error(\n \"placeOrder() requires wallet private key configuration for EIP-712 signature. \" +\n \"Please configure authentication before calling this method. \" +\n \"See: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint\",\n );\n }\n\n /**\n * 取消订单\n *\n * ⚠️ 注意:此方法需要配置钱包私钥进行 EIP-712 签名认证\n *\n * @param params 取消订单参数\n * @returns 取消订单结果\n * @throws {HyperliquidApiError} API 请求失败、订单不存在等\n * @throws {Error} 未配置认证信息\n *\n * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint\n */\n async cancelOrder(_params: CancelOrderParams): Promise<CancelOrderResult> {\n throw new Error(\n \"cancelOrder() requires wallet private key configuration for EIP-712 signature. \" +\n \"Please configure authentication before calling this method. \" +\n \"See: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint\",\n );\n }\n\n // ===================================\n // 账户查询接口(3个方法)\n // ===================================\n\n /**\n * 获取用户持仓信息\n *\n * ⚠️ Hyperliquid 要求:必须提供 userAddress 参数\n *\n * @param params 查询参数\n * @returns 持仓结果\n * @throws {HyperliquidApiError} API 请求失败\n * @throws {Error} 缺少必需参数\n */\n async getPositions(\n params: GetPositionsParams = {},\n ): Promise<GetPositionsResult> {\n if (!params.userAddress) {\n throw new Error(\n \"Hyperliquid requires userAddress parameter. \" +\n \"Example: { userAddress: '0x...' }\",\n );\n }\n\n // Fan three info reads out in parallel — clearinghouseState gives us\n // the positions skeleton, frontendOpenOrders supplies the TP/SL\n // trigger prices we enrich each position with, and metaAndAssetCtxs\n // delivers the live mark price (which clearinghouseState alone does\n // not provide). We use `Promise.all` instead of three sequential\n // awaits so the slowest leg dominates the latency, not their sum.\n const [clearinghouse, openOrdersRaw, metaAndCtxs] = await Promise.all([\n this.request<HyperliquidClearinghouseState>(\"/info\", {\n type: \"clearinghouseState\",\n user: params.userAddress,\n }),\n this.request<HyperliquidOpenOrder[]>(\"/info\", {\n type: \"frontendOpenOrders\",\n user: params.userAddress,\n }),\n this.request<\n [\n { universe: Array<{ name: string }> },\n Array<{ markPx?: string; midPx?: string }>,\n ]\n >(\"/info\", { type: \"metaAndAssetCtxs\" }),\n ]);\n\n const result = parseClearinghouseState(clearinghouse, params.symbol);\n const markByCoin = buildMarkPriceMap(metaAndCtxs);\n result.positions = enrichPositions(\n result.positions,\n openOrdersRaw,\n markByCoin,\n );\n // Recompute aggregate PnL since per-position PnL may have been\n // recomputed against a fresher mark price.\n result.totalUnrealizedPnl = result.positions.reduce(\n (sum, p) => sum + p.unrealizedPnl,\n 0,\n );\n return result;\n }\n\n /**\n * Read the user's per-asset leverage configuration via the\n * `activeAssetData` info endpoint. This works whether or not an open\n * position exists for the asset, so the UI can render the latest\n * configured leverage on a fresh page load.\n *\n * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint/perpetuals#retrieve-users-active-asset-data\n */\n async getActiveAssetLeverage(\n params: GetActiveAssetLeverageParams,\n ): Promise<ActiveAssetLeverage | null> {\n const coin = this.symbolToCoin(params.symbol);\n try {\n const data = await this.request<{\n leverage:\n | { type: \"isolated\"; value: number; rawUsd: string }\n | { type: \"cross\"; value: number };\n }>(\"/info\", {\n type: \"activeAssetData\",\n coin,\n user: params.userAddress,\n });\n\n const lev = data?.leverage;\n if (!lev || typeof lev.value !== \"number\") return null;\n return { value: lev.value, type: lev.type };\n } catch (error) {\n // The endpoint returns an error for unknown coins / users; treat\n // it as \"no data\" so the form falls back to its own default\n // instead of surfacing a transient network blip to the user.\n if (\n error instanceof HyperliquidApiError &&\n (error.statusCode === 422 || error.statusCode === 400)\n ) {\n return null;\n }\n throw error;\n }\n }\n\n /**\n * Fetch the venue's static metadata for `params.symbol` (currently\n * `szDecimals` and `maxLeverage`). Backed by Hyperliquid's `meta`\n * info endpoint, with an in-memory cache keyed on this client\n * instance and TTL'd at {@link ASSET_META_TTL_MS}.\n *\n * Returns `null` when the symbol isn't part of the universe so\n * downstream consumers can branch on absence without try/catching\n * lookups for unsupported coins.\n *\n * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint/perpetuals#retrieve-perpetuals-metadata\n */\n async getAssetMeta(params: GetAssetMetaParams): Promise<AssetMeta | null> {\n const universe = await this.fetchAssetUniverse();\n const coin = this.symbolToCoin(params.symbol);\n return universe.get(coin) ?? null;\n }\n\n /**\n * Internal: ensure {@link assetMetaCache} is populated and fresh,\n * then return the resolved coin → {@link AssetMeta} map. Concurrent\n * cache misses share a single in-flight request via\n * {@link assetMetaPending}.\n */\n private async fetchAssetUniverse(): Promise<Map<string, AssetMeta>> {\n const now = Date.now();\n if (\n this.assetMetaCache &&\n now - this.assetMetaCache.fetchedAt < ASSET_META_TTL_MS\n ) {\n return this.assetMetaCache.map;\n }\n if (this.assetMetaPending) {\n return this.assetMetaPending;\n }\n\n const fetchPromise = (async () => {\n const data = await this.request<{\n universe: Array<{\n name: string;\n szDecimals: number;\n maxLeverage?: number;\n }>;\n }>(\"/info\", { type: \"meta\" });\n\n const map = new Map<string, AssetMeta>();\n for (const asset of data.universe) {\n if (!asset || typeof asset.name !== \"string\") continue;\n if (typeof asset.szDecimals !== \"number\") continue;\n map.set(asset.name, {\n szDecimals: asset.szDecimals,\n maxLeverage: asset.maxLeverage,\n });\n }\n this.assetMetaCache = { fetchedAt: Date.now(), map };\n return map;\n })();\n\n this.assetMetaPending = fetchPromise;\n try {\n return await fetchPromise;\n } finally {\n // Clear regardless of outcome so a transient failure doesn't\n // pin every future caller to a rejected promise.\n this.assetMetaPending = null;\n }\n }\n\n /**\n * 获取用户挂单信息\n *\n * ⚠️ Hyperliquid 要求:必须提供 userAddress 参数\n *\n * @param params 查询参数\n * @returns 挂单结果\n * @throws {HyperliquidApiError} API 请求失败\n * @throws {Error} 缺少必需参数\n */\n async getOpenOrders(\n params: GetOpenOrdersParams = {},\n ): Promise<GetOpenOrdersResult> {\n if (!params.userAddress) {\n throw new Error(\n \"Hyperliquid requires userAddress parameter. \" +\n \"Example: { userAddress: '0x...' }\",\n );\n }\n\n const data = await this.request<HyperliquidOpenOrder[]>(\"/info\", {\n type: \"openOrders\",\n user: params.userAddress,\n });\n\n const orders = data.map(parseOpenOrder);\n const filteredOrders = params.symbol\n ? orders.filter((o) => o.symbol === params.symbol)\n : orders;\n\n return {\n orders: filteredOrders,\n totalCount: filteredOrders.length,\n raw: data,\n };\n }\n\n /**\n * 获取用户交易历史\n *\n * ⚠️ Hyperliquid 要求:必须提供 userAddress 参数\n *\n * @param params 查询参数\n * @returns 交易历史结果\n * @throws {HyperliquidApiError} API 请求失败\n * @throws {Error} 缺少必需参数\n */\n async getTrades(params: GetTradesParams = {}): Promise<GetTradesResult> {\n if (!params.userAddress) {\n throw new Error(\n \"Hyperliquid requires userAddress parameter. \" +\n \"Example: { userAddress: '0x...' }\",\n );\n }\n\n const data = await this.request<\n Array<{\n coin: string;\n side: string;\n px: string;\n sz: string;\n time: number;\n dir: string;\n oid: number;\n tid: number;\n fee?: string;\n feeToken?: string;\n }>\n >(\"/info\", { type: \"userFills\", user: params.userAddress });\n\n // 转换交易数据\n let trades = data.map((fill) => {\n const symbol = `${fill.coin}-USDC`;\n const isLong = fill.dir.includes(\"Long\");\n\n return {\n tradeId: fill.tid.toString(),\n orderId: fill.oid.toString(),\n symbol,\n side: isLong ? (\"long\" as const) : (\"short\" as const),\n price: parseFloat(fill.px),\n quantity: parseFloat(fill.sz),\n fee: parseFloat(fill.fee || \"0\"),\n feeCurrency: fill.feeToken || \"USDC\",\n isMaker: fill.side === \"M\", // \"M\" = Maker, \"T\" = Taker\n timestamp: fill.time,\n };\n });\n\n // 过滤指定币种\n if (params.symbol) {\n trades = trades.filter((t) => t.symbol === params.symbol);\n }\n\n // 过滤时间范围\n if (params.startTime) {\n trades = trades.filter((t) => t.timestamp >= params.startTime!);\n }\n if (params.endTime) {\n trades = trades.filter((t) => t.timestamp <= params.endTime!);\n }\n\n // 限制返回数量\n if (params.limit) {\n trades = trades.slice(0, params.limit);\n }\n\n return {\n trades,\n totalCount: trades.length,\n raw: data,\n };\n }\n\n // ===================================\n // WebSocket 连接管理(2个方法)\n // ===================================\n\n /**\n * Connect to WebSocket server\n *\n * Establishes WebSocket connection for real-time data streaming.\n * Connection will auto-reconnect on disconnect.\n *\n * @throws {Error} Connection failed\n */\n async connectWebSocket(): Promise<void> {\n this.wsRefCount += 1;\n if (!this.wsManager) {\n this.wsManager = new WebSocketManager(this._wsEndpoint);\n }\n\n if (this.wsManager.isConnectedNow()) {\n return;\n }\n\n await this.wsManager.connect();\n }\n\n /**\n * Disconnect from WebSocket server\n *\n * Decrements the consumer ref count. The underlying socket is closed\n * only when the last consumer disconnects, so concurrent widgets\n * (order book, trades, ticker) can mount/unmount independently\n * without stealing each other's stream.\n */\n disconnectWebSocket(): void {\n this.wsRefCount = Math.max(0, this.wsRefCount - 1);\n if (this.wsRefCount === 0 && this.wsManager) {\n this.wsManager.disconnect();\n this.wsManager = null;\n }\n }\n\n // ===================================\n // WebSocket 订阅(4个方法)\n // ===================================\n\n /**\n * Subscribe to market data (price, trades, order book)\n *\n * @param type Subscription type: 'ticker' | 'trades' | 'orderBook'\n * @param symbol Trading pair symbol (e.g., \"BTC-USDC\")\n * @param callback Data callback function\n * @param options Optional subscription options. For `orderBook`, provide\n * `aggregation` (Hyperliquid `nSigFigs` / `mantissa`) so the server\n * pre-aggregates levels into discrete price buckets — required to render\n * wide-range books at coarse aggregation steps (e.g. $1000 buckets).\n * @returns Subscription ID (for unsubscribing)\n */\n subscribeMarketData(\n type: \"ticker\" | \"trades\" | \"orderBook\",\n symbol: string,\n callback: (data: any) => void,\n options?: { aggregation?: OrderBookAggregation },\n ): string {\n if (!this.wsManager) {\n throw new Error(\n \"WebSocket not connected. Call connectWebSocket() first.\",\n );\n }\n\n return this.wsManager.subscribe(\n type,\n symbol,\n callback,\n options?.aggregation,\n );\n }\n\n /**\n * Subscribe to kline (candlestick) data\n *\n * @param symbol Trading pair symbol (e.g., \"BTC-USDC\")\n * @param interval Time interval (e.g., \"1m\", \"1h\", \"1d\")\n * @param callback Data callback function\n * @returns Subscription ID (for unsubscribing)\n */\n subscribeCandles(\n symbol: string,\n interval: KlineInterval,\n callback: (candle: Kline) => void,\n ): string {\n if (!this.wsManager) {\n throw new Error(\n \"WebSocket not connected. Call connectWebSocket() first.\",\n );\n }\n\n // Combine symbol and interval as parameter\n const param = `${symbol}:${interval}`;\n return this.wsManager.subscribe(\"candle\", param, callback);\n }\n\n /**\n * Subscribe to user data (orders, positions, fills)\n *\n * @param type Subscription type: 'orders' | 'positions' | 'fills'\n * @param userAddress User wallet address\n * @param callback Data callback function\n * @returns Subscription ID (for unsubscribing)\n */\n subscribeUserData(\n type: \"orders\" | \"positions\" | \"fills\",\n userAddress: string,\n callback: (data: any) => void,\n ): string {\n if (!this.wsManager) {\n throw new Error(\n \"WebSocket not connected. Call connectWebSocket() first.\",\n );\n }\n\n // Use userEvents for orders and positions, userFills for fills\n const subscriptionType = type === \"fills\" ? \"userFills\" : \"userEvents\";\n\n return this.wsManager.subscribe(subscriptionType, userAddress, callback);\n }\n\n /**\n * Subscribe to the user's full account state via Hyperliquid's\n * `webData2` channel. Each push carries a complete snapshot of:\n *\n * - `clearinghouseState` — perp positions, margin summaries, and the\n * `withdrawable` figure used as \"Available Margin\".\n * - `spotState` — spot wallet balances (USDC, USOL, etc.).\n * - `openOrders` — the user's resting limit orders.\n *\n * Replaces three separate REST polls (`clearinghouseState`,\n * `spotClearinghouseState`, `openOrders`) with a single push channel.\n * Hooks like `useAccountStateSubscription` use this to seed React\n * Query caches in real time so consumers see fills / margin moves\n * the moment Hyperliquid pushes them.\n *\n * @param userAddress Wallet address whose state to track.\n * @param callback Receives the canonical {@link AccountState} on\n * every push (raw payload available on `state.raw`).\n * @returns Subscription ID for {@link unsubscribe}.\n *\n * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/websocket/subscriptions#webdata2\n */\n subscribeAccountState(\n userAddress: string,\n callback: (state: AccountState) => void,\n ): string {\n if (!this.wsManager) {\n throw new Error(\n \"WebSocket not connected. Call connectWebSocket() first.\",\n );\n }\n\n // Funnel raw `webData2` payloads through the same parser as the\n // REST `clearinghouseState` / `openOrders` paths so positions /\n // available margin / open orders look identical regardless of\n // transport. Single source of truth for the venue → SDK shape\n // conversion.\n return this.wsManager.subscribe(\n \"accountState\",\n userAddress,\n (raw: HyperliquidWebData2Payload) => {\n callback(parseWebData2(raw));\n },\n );\n }\n\n /**\n * Unsubscribe from a data stream\n *\n * @param subscriptionId Subscription ID returned from subscribe methods\n */\n unsubscribe(subscriptionId: string): void {\n if (this.wsManager) {\n this.wsManager.unsubscribe(subscriptionId);\n }\n }\n}\n\n// ===================================\n// Hyperliquid wire-format helpers\n// ===================================\n\n/**\n * Raw shape of Hyperliquid's `clearinghouseState` (REST + the inner\n * payload of `webData2`). Captured here so REST and WS code paths share\n * a single type definition — drift between the two would silently break\n * the cache write-through that powers `useAccountStateSubscription`.\n */\ninterface HyperliquidClearinghouseState {\n assetPositions: Array<{\n position: {\n coin: string;\n szi: string;\n leverage: { type: string; value: number };\n entryPx: string;\n positionValue: string;\n unrealizedPnl: string;\n returnOnEquity: string;\n liquidationPx: string | null;\n marginUsed: string;\n };\n }>;\n marginSummary: {\n accountValue: string;\n totalMarginUsed: string;\n totalNtlPos: string;\n totalRawUsd: string;\n };\n crossMarginSummary: {\n accountValue: string;\n totalMarginUsed: string;\n totalNtlPos: string;\n totalRawUsd: string;\n };\n /**\n * \"Available to spend on a new isolated trade or to withdraw\" —\n * Hyperliquid's canonical figure that already accounts for cross\n * margin reservations and the venue's protocol-level safety buffer\n * (typically the maintenance + initial margin overlap).\n *\n * For a wallet with no open positions this equals\n * `crossMarginSummary.accountValue`, but as soon as the account\n * mixes isolated and cross positions it diverges. Axiom's order\n * panel uses this exact field as \"Available Margin\", so we mirror\n * it for parity.\n */\n withdrawable: string;\n}\n\n/**\n * Hyperliquid open order shape. `frontendOpenOrders` returns a richer\n * payload than the basic `openOrders` endpoint — including\n * `triggerPx` / `triggerCondition` / `isTrigger` / `reduceOnly`, which\n * we need to compute per-position TP/SL.\n *\n * Fields are typed loose where the venue's wire format is loose\n * (`side` is the string \"A\" / \"B\" on `frontendOpenOrders`, but a\n * boolean on `webData2`'s `openOrders` — the parser handles both).\n */\ninterface HyperliquidOpenOrder {\n coin: string;\n /**\n * Side encoding varies by endpoint:\n * - `frontendOpenOrders` REST → string `\"A\"` (Ask/Sell) | `\"B\"` (Buy)\n * - `webData2` push → boolean `true` (Buy) | `false` (Sell)\n * - basic `openOrders` REST → boolean (same as webData2)\n * We accept both and normalise in {@link parseOpenOrder}.\n */\n side: boolean | \"A\" | \"B\";\n limitPx: string;\n sz: string;\n origSz: string;\n oid: number;\n cloid?: string | null;\n timestamp: number;\n /**\n * Human-readable order type from the venue, e.g.\n * `\"Limit\"`, `\"Stop Market\"`, `\"Take Profit Market\"`,\n * `\"Stop Limit\"`, `\"Take Profit Limit\"`, `\"Market\"`.\n * `frontendOpenOrders` returns this as a string; the basic\n * `openOrders` endpoint returns a structured object — both are\n * tolerated here via the `unknown` widening.\n */\n orderType?: string | { limit?: unknown; trigger?: unknown };\n /** True when the order is a trigger order (stop / take-profit / etc). */\n isTrigger?: boolean;\n /** Trigger price as a stringified decimal (only meaningful when isTrigger). */\n triggerPx?: string;\n /** Human-readable trigger condition, e.g. \"Price above 81470\" or \"N/A\". */\n triggerCondition?: string;\n reduceOnly?: boolean;\n /** Position TP/SL (HL `positionTpsl` grouping) flag. */\n isPositionTpsl?: boolean;\n tif?: string | null;\n children?: unknown[];\n}\n\ninterface HyperliquidSpotBalance {\n coin: string;\n total: string;\n hold: string;\n entryNtl?: string;\n}\n\ninterface HyperliquidWebData2Payload {\n clearinghouseState?: HyperliquidClearinghouseState;\n spotState?: { balances?: HyperliquidSpotBalance[] };\n /**\n * `webData2` exposes the user's resting orders under `openOrders`,\n * but historically the basic `openOrders` info endpoint and the\n * richer `frontendOpenOrders` shape are both possible payloads.\n * Some venue snapshots have surfaced trigger fields here too — keep\n * the parser tolerant.\n */\n openOrders?: HyperliquidOpenOrder[];\n /**\n * Asset universe (perp contracts) used to map a position's `coin`\n * back to the matching index in `assetCtxs`. Mirrors the response\n * of the `meta` info endpoint.\n */\n meta?: { universe: Array<{ name: string }> };\n /**\n * Per-asset live context: includes `markPx`, `oraclePx`, funding,\n * `dayNtlVlm`. Indexed parallel to `meta.universe`.\n */\n assetCtxs?: Array<{\n markPx?: string;\n midPx?: string;\n oraclePx?: string;\n funding?: string;\n openInterest?: string;\n dayNtlVlm?: string;\n }>;\n serverTime?: number;\n}\n\n/**\n * Translate a `clearinghouseState` payload to the SDK's\n * {@link GetPositionsResult} shape. Used by both the REST `getPositions`\n * call and the WS `webData2` push, keeping the venue→SDK mapping in one\n * place — drift between the two would let the cache write-through ship\n * subtly different objects than the polling path.\n */\nfunction parseClearinghouseState(\n data: HyperliquidClearinghouseState,\n symbolFilter?: string,\n): GetPositionsResult {\n const positions = data.assetPositions\n .map((assetPos) => {\n const pos = assetPos.position;\n const symbol = `${pos.coin}-USDC`;\n const quantity = parseFloat(pos.szi);\n\n if (quantity === 0) {\n return null;\n }\n\n const entryPrice = parseFloat(pos.entryPx);\n const unrealizedPnl = parseFloat(pos.unrealizedPnl);\n const positionValue = parseFloat(pos.positionValue);\n\n const position: Position = {\n symbol,\n side: quantity > 0 ? \"long\" : \"short\",\n quantity: Math.abs(quantity),\n // Strip the sign so consumers can render the absolute size\n // alongside a Long/Short prefix (e.g. \"Long 0.00045 BTC\")\n // without manually parsing the venue string.\n quantityRaw: pos.szi.startsWith(\"-\") ? pos.szi.slice(1) : pos.szi,\n entryPrice,\n markPrice: entryPrice, // Hyperliquid 不直接提供,可从 assetCtxs 获取\n unrealizedPnl,\n unrealizedPnlPercent: parseFloat(pos.returnOnEquity) * 100,\n leverage: pos.leverage.value,\n liquidationPrice: pos.liquidationPx\n ? parseFloat(pos.liquidationPx)\n : undefined,\n margin: parseFloat(pos.marginUsed),\n notionalValue: Math.abs(positionValue),\n };\n return position;\n })\n .filter((p): p is Position => p !== null);\n\n const filteredPositions = symbolFilter\n ? positions.filter((p) => p.symbol === symbolFilter)\n : positions;\n\n // Prefer the venue's `withdrawable` field as the source of truth for\n // \"available margin\": it already accounts for the maintenance buffer\n // that `accountValue - totalMarginUsed` overstates whenever isolated\n // and cross positions coexist. Older payloads (or future schema\n // shifts) may omit it, so we fall back to the legacy formula.\n const withdrawableRaw = data.withdrawable;\n const availableBalance =\n typeof withdrawableRaw === \"string\" && withdrawableRaw.length > 0\n ? parseFloat(withdrawableRaw)\n : parseFloat(data.marginSummary.accountValue) -\n parseFloat(data.marginSummary.totalMarginUsed);\n\n return {\n positions: filteredPositions,\n totalEquity: parseFloat(data.marginSummary.accountValue),\n availableBalance,\n totalUnrealizedPnl: filteredPositions.reduce(\n (sum, p) => sum + p.unrealizedPnl,\n 0,\n ),\n raw: data,\n };\n}\n\n/**\n * Translate Hyperliquid's open-order wire format to the SDK's\n * {@link Order} shape. Handles both `frontendOpenOrders` (string side\n * `\"A\"/\"B\"`, raw `orderType` strings, trigger fields) and the simpler\n * `webData2.openOrders` push (boolean side, no trigger metadata).\n */\nfunction parseOpenOrder(order: HyperliquidOpenOrder): Order {\n const symbol = `${order.coin}-USDC`;\n const origSz = parseFloat(order.origSz);\n const remainingSz = parseFloat(order.sz);\n const filledSz = origSz - remainingSz;\n\n // Normalise side: `\"A\"` / `false` → sell/short close; `\"B\"` / `true`\n // → buy/long. The SDK's `Order.side` represents the order's\n // direction (not the position direction), so we map directly.\n const isBuySide = order.side === true || order.side === \"B\";\n\n // Normalise orderType to a \"Limit\" / \"Market\" baseline. The richer\n // trigger info goes into the dedicated trigger fields below — leaving\n // `orderType` as a strict `\"limit\" | \"market\"` keeps the existing\n // OpenOrders UI working without a breaking refactor.\n const rawOrderType =\n typeof order.orderType === \"string\" ? order.orderType : \"Limit\";\n const isMarket = /^market$/i.test(rawOrderType);\n const baseOrderType: OrderType = isMarket ? \"market\" : \"limit\";\n\n // Trigger discriminator: HL uses the human-readable strings\n // \"Take Profit Market\" / \"Take Profit Limit\" / \"Stop Market\" /\n // \"Stop Limit\" — all four collapse to the binary tp/sl axis the\n // positions table cares about.\n const isTrigger = order.isTrigger === true;\n let triggerType: \"tp\" | \"sl\" | undefined;\n if (isTrigger) {\n if (/take\\s*profit/i.test(rawOrderType)) triggerType = \"tp\";\n else if (/stop/i.test(rawOrderType)) triggerType = \"sl\";\n }\n const triggerPx =\n typeof order.triggerPx === \"string\" && order.triggerPx.length > 0\n ? parseFloat(order.triggerPx)\n : undefined;\n const triggerCondition =\n typeof order.triggerCondition === \"string\" &&\n order.triggerCondition !== \"N/A\"\n ? order.triggerCondition\n : undefined;\n\n return {\n orderId: order.oid.toString(),\n clientOrderId: order.cloid ?? undefined,\n symbol,\n side: isBuySide ? \"long\" : \"short\",\n orderType: baseOrderType,\n price: parseFloat(order.limitPx),\n quantity: origSz,\n filledQuantity: filledSz,\n remainingQuantity: remainingSz,\n status: filledSz > 0 && remainingSz > 0 ? \"partially_filled\" : \"pending\",\n timestamp: order.timestamp,\n updateTimestamp: order.timestamp,\n reduceOnly: order.reduceOnly === true,\n isTrigger: isTrigger || undefined,\n triggerPx,\n triggerType,\n triggerCondition,\n };\n}\n\nfunction parseSpotBalances(\n balances: HyperliquidSpotBalance[] | undefined,\n): SpotBalance[] {\n if (!balances) return [];\n return balances.map((b) => ({\n coin: b.coin,\n total: parseFloat(b.total),\n // Preserve the venue's exact decimal precision for display —\n // round-tripping through `Number` can flip \"0.00000005\" into\n // scientific notation and drop trailing zeros that the UI cares\n // about.\n totalRaw: b.total,\n hold: parseFloat(b.hold),\n entryNotional: b.entryNtl ? parseFloat(b.entryNtl) : undefined,\n }));\n}\n\n/**\n * Translate Hyperliquid's `webData2` push to the SDK's\n * {@link AccountState} shape. Reuses {@link parseClearinghouseState} so\n * positions / available margin look identical to the REST path, then\n * enriches each position with:\n * - active TP/SL trigger prices (from `openOrders`)\n * - live mark price + recomputed PnL (from `meta` + `assetCtxs`)\n *\n * Both enrichments are no-ops when the inputs are missing — older\n * webData2 snapshots without `assetCtxs` simply leave `markPrice`\n * pointed at the entry-price placeholder, so the function stays\n * forward-compatible with venue payload churn.\n */\nfunction parseWebData2(raw: HyperliquidWebData2Payload): AccountState {\n const clearinghouse = raw.clearinghouseState;\n const positionsResult = clearinghouse\n ? parseClearinghouseState(clearinghouse)\n : {\n positions: [],\n totalEquity: 0,\n availableBalance: 0,\n totalUnrealizedPnl: 0,\n };\n\n const openOrdersRaw = raw.openOrders ?? [];\n const openOrders = openOrdersRaw.map(parseOpenOrder);\n const spotBalances = parseSpotBalances(raw.spotState?.balances);\n\n // Enrich positions: TP/SL from open trigger orders + live mark price\n // from assetCtxs. Done after the main parse so the enrichment logic\n // stays decoupled from the clearinghouse->Position transform and can\n // be unit-tested in isolation.\n const markByCoin =\n raw.meta && raw.assetCtxs\n ? buildMarkPriceMap([raw.meta, raw.assetCtxs])\n : null;\n\n const enrichedPositions = enrichPositions(\n positionsResult.positions,\n openOrdersRaw,\n markByCoin,\n );\n\n // Aggregate PnL has to be recomputed because per-position PnL may\n // have shifted when we re-marked it against the live `markPx`.\n const totalUnrealizedPnl = enrichedPositions.reduce(\n (sum, p) => sum + p.unrealizedPnl,\n 0,\n );\n\n return {\n positions: enrichedPositions,\n openOrders,\n spotBalances,\n totalEquity: positionsResult.totalEquity ?? 0,\n availableBalance: positionsResult.availableBalance ?? 0,\n totalUnrealizedPnl,\n serverTime: raw.serverTime,\n raw,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Enrichment helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Build a `coin → markPrice` lookup from Hyperliquid's\n * `metaAndAssetCtxs` tuple. Falls back to `midPx` / `oraclePx` when\n * `markPx` is absent — the exact field hierarchy mirrors the existing\n * {@link HyperliquidPerpetualsClient.getMarkets} behaviour so all\n * consumers see the same \"current price\" definition.\n */\nfunction buildMarkPriceMap(\n metaAndCtxs: [\n { universe: Array<{ name: string }> },\n Array<{ markPx?: string; midPx?: string; oraclePx?: string }>,\n ],\n): Map<string, number> {\n const [meta, ctxs] = metaAndCtxs;\n const map = new Map<string, number>();\n meta.universe.forEach((asset, index) => {\n const ctx = ctxs[index];\n if (!ctx) return;\n const raw = ctx.markPx ?? ctx.midPx ?? ctx.oraclePx;\n if (typeof raw !== \"string\" || raw.length === 0) return;\n const px = parseFloat(raw);\n if (Number.isFinite(px) && px > 0) {\n map.set(asset.name, px);\n }\n });\n return map;\n}\n\n/**\n * Pick the take-profit and stop-loss trigger prices that would\n * actually close `position`. Filtering rules:\n *\n * 1. `coin` matches the position's coin.\n * 2. `reduceOnly === true` — non-reduce-only triggers can flip the\n * position direction, not close it, so they don't belong in the\n * \"TP/SL of this position\" answer.\n * 3. `isTrigger === true` (defensive — every reduceOnly TP/SL we\n * care about is also a trigger order).\n * 4. **Closing-side match**: a Long position is closed by a SELL\n * (HL `side: \"A\"` / `false`); a Short by a BUY (`\"B\"` / `true`).\n * Orphan triggers from a previously-closed opposite position\n * stay in `frontendOpenOrders` until cancelled — they would\n * never trigger against the current position, so we exclude\n * them. This is the **semantically correct** match (vs Axiom's\n * naïve \"max triggerPx across both sides\", which can surface\n * orphans).\n *\n * Among matching triggers, pick the most recent one per type\n * (`Take Profit Market` → TP, `Stop Market` → SL) by timestamp /\n * `oid`. When multiple TPs/SLs exist (laddered exits), this picks the\n * most-recently placed one — keeping the contract simple. A future\n * improvement could expose the full list for richer rendering.\n */\nfunction pickPositionTpSl(\n position: Position,\n openOrders: HyperliquidOpenOrder[],\n): { tp?: number; sl?: number } {\n const coin = position.symbol.split(\"-\")[0];\n const closingSide: \"A\" | \"B\" = position.side === \"long\" ? \"A\" : \"B\";\n const closingSideBool = closingSide === \"B\";\n\n let tpOrder: HyperliquidOpenOrder | undefined;\n let slOrder: HyperliquidOpenOrder | undefined;\n\n for (const order of openOrders) {\n if (order.coin !== coin) continue;\n if (order.reduceOnly !== true) continue;\n if (order.isTrigger !== true) continue;\n\n const sideMatches =\n order.side === closingSide || order.side === closingSideBool;\n if (!sideMatches) continue;\n\n const orderTypeStr =\n typeof order.orderType === \"string\" ? order.orderType : \"\";\n const isTp = /take\\s*profit/i.test(orderTypeStr);\n const isSl = /stop/i.test(orderTypeStr);\n\n if (isTp) {\n if (!tpOrder || order.timestamp > tpOrder.timestamp) {\n tpOrder = order;\n }\n } else if (isSl) {\n if (!slOrder || order.timestamp > slOrder.timestamp) {\n slOrder = order;\n }\n }\n }\n\n return {\n tp: tpOrder?.triggerPx ? parseFloat(tpOrder.triggerPx) : undefined,\n sl: slOrder?.triggerPx ? parseFloat(slOrder.triggerPx) : undefined,\n };\n}\n\n/**\n * Apply both enrichments — TP/SL (from `openOrders`) and live mark\n * price + recomputed PnL (from `marks`) — to a list of positions.\n * Returns a new array; never mutates the input.\n *\n * Pure function so it stays trivially testable and reusable across\n * both the REST `getPositions` path and the WS `webData2` push.\n */\nfunction enrichPositions(\n positions: Position[],\n openOrders: HyperliquidOpenOrder[],\n marks: Map<string, number> | null,\n): Position[] {\n return positions.map((position) => {\n const next: Position = { ...position };\n\n // 1. TP / SL — closing-side reduceOnly trigger orders.\n const { tp, sl } = pickPositionTpSl(position, openOrders);\n next.takeProfitPrice = tp;\n next.stopLossPrice = sl;\n\n // 2. Live mark price + PnL recompute.\n //\n // The venue's `clearinghouseState` snapshot ships an\n // `unrealizedPnl` already, but it's marked at whatever instant the\n // snapshot was taken — between user-action pushes the figure goes\n // stale fast. When we have a fresher mark from `assetCtxs` we\n // re-mark client-side using the same formula HL uses internally\n // (`(mark - entry) * |qty|` for long, mirrored for short) and\n // derive ROE as `pnl / margin`. Cross-margin positions use\n // `marginUsed` for that ratio too, which approximates HL's\n // displayed ROE within rounding (HL's exact cross ROE depends on\n // venue-internal collateral allocation that isn't surfaced).\n const coin = position.symbol.split(\"-\")[0];\n const markPrice = marks?.get(coin);\n if (markPrice && Number.isFinite(markPrice) && markPrice > 0) {\n next.markPrice = markPrice;\n const dir = position.side === \"long\" ? 1 : -1;\n const pnl = (markPrice - position.entryPrice) * position.quantity * dir;\n next.unrealizedPnl = pnl;\n next.notionalValue = markPrice * position.quantity;\n if (position.margin > 0) {\n next.unrealizedPnlPercent = (pnl / position.margin) * 100;\n }\n }\n\n return next;\n });\n}\n\n/**\n * Hyperliquid API 错误类\n */\nexport class HyperliquidApiError extends Error {\n constructor(\n message: string,\n public readonly statusCode: number,\n public readonly responseBody: string,\n ) {\n super(message);\n this.name = \"HyperliquidApiError\";\n }\n}\n","/**\n * Shared REST transport for every LiberFi perpetuals-server client.\n *\n * Pulled out of `LiberFiPerpetualsClient` so the deposit client (and any\n * future feature client) can reuse the same fetch-with-timeout, error\n * mapping, and header merging logic without copy-paste.\n *\n * Design choices:\n *\n * - The class is intentionally minimal: build URL → fire fetch →\n * decode JSON → throw a typed error on non-2xx. No retries, no\n * circuit breaker, no caching. That layering belongs to the caller\n * (e.g. TanStack Query handles retries/cache).\n *\n * - Custom query parameters are passed per-request, not per-instance,\n * except for `defaultQuery` which the perpetuals client uses for the\n * `?provider=` selector.\n *\n * - Headers merge in three layers (call > instance > built-in). This\n * lets a caller add a one-off `Authorization` for a single request\n * without leaking it into the rest of the session.\n */\n\n/**\n * Thrown when perpetuals-server returns a non-2xx HTTP status, when the\n * request times out, or when the network call fails outright.\n *\n * `statusCode` is the HTTP status (or `0` for network errors / `408`\n * for client-side timeouts). `responseBody` is the verbatim response\n * text — useful for surfacing backend error codes to the user.\n */\nexport class LiberFiApiError extends Error {\n constructor(\n message: string,\n public readonly statusCode: number,\n public readonly responseBody: string,\n ) {\n super(message);\n this.name = \"LiberFiApiError\";\n }\n}\n\n/** Configuration for {@link LiberFiHttpTransport}. */\nexport interface LiberFiHttpTransportConfig {\n /**\n * REST base URL, with NO trailing slash. The transport strips trailing\n * slashes on construction so callers can pass either form.\n */\n baseUrl: string;\n\n /** Per-request timeout in milliseconds. Defaults to 30 000 ms. */\n timeout?: number;\n\n /**\n * Headers merged into every request. Per-request headers (passed to\n * `request()`) win on key collision, then instance headers, then the\n * built-in `Accept` / `Content-Type`.\n */\n headers?: Record<string, string>;\n\n /**\n * Default query parameters appended to every request URL. Useful for\n * cross-cutting selectors like `?provider=hyperliquid`. Per-request\n * params override on key collision.\n */\n defaultQuery?: Record<string, string | undefined>;\n\n /**\n * Custom `fetch` implementation. Defaults to the global `fetch`.\n * Useful in tests (drop in a jest mock) or in environments where a\n * pre-configured fetch (e.g. with circuit breaker / proxy) is supplied\n * by the host application.\n */\n fetchImpl?: typeof fetch;\n}\n\n/** HTTP method shape — keep narrow; deposit and trading both use these. */\nexport type LiberFiHttpMethod = \"GET\" | \"POST\";\n\n/** Per-request options accepted by {@link LiberFiHttpTransport.request}. */\nexport interface RequestOptions {\n /** Path relative to `baseUrl` (must start with `/`). */\n path: string;\n /** Optional query string parameters. Undefined / empty values are skipped. */\n query?: Record<string, string | undefined>;\n /** JSON body for POST/PUT/etc. */\n body?: unknown;\n /** One-off headers — overrides the instance defaults. */\n headers?: Record<string, string>;\n /**\n * Override the per-instance timeout for this single request.\n * Use for fast-path reads or long-running submits.\n */\n timeoutMs?: number;\n}\n\nconst DEFAULT_TIMEOUT_MS = 30_000;\n\n/**\n * Stateless HTTP transport shared by every LiberFi perpetuals-server\n * client. Construct one per client (or one shared instance — the class\n * is safe for concurrent use).\n */\nexport class LiberFiHttpTransport {\n private readonly baseUrl: string;\n private readonly timeout: number;\n private readonly headers?: Record<string, string>;\n private readonly defaultQuery?: Record<string, string | undefined>;\n private readonly fetchImpl: typeof fetch;\n\n constructor(config: LiberFiHttpTransportConfig) {\n if (!config.baseUrl) {\n throw new Error(\n \"LiberFiHttpTransport: `baseUrl` is required (e.g. https://api.liberfi.io/perpetuals).\",\n );\n }\n this.baseUrl = config.baseUrl.replace(/\\/+$/, \"\");\n this.timeout = config.timeout ?? DEFAULT_TIMEOUT_MS;\n this.headers = config.headers;\n this.defaultQuery = config.defaultQuery;\n // Bind so `fetch` can be `globalThis.fetch` (which requires `this`\n // to be the realm's globalThis, not the transport instance).\n this.fetchImpl = config.fetchImpl ?? globalThis.fetch.bind(globalThis);\n }\n\n /** Read-only accessor used by the perpetuals client for WebSocket fallback. */\n getBaseUrl(): string {\n return this.baseUrl;\n }\n\n /** Build a fully-qualified URL with merged query string. */\n buildUrl(path: string, query?: Record<string, string | undefined>): string {\n const params = new URLSearchParams();\n if (this.defaultQuery) {\n for (const [key, value] of Object.entries(this.defaultQuery)) {\n if (value === undefined || value === \"\") continue;\n params.set(key, value);\n }\n }\n if (query) {\n for (const [key, value] of Object.entries(query)) {\n if (value === undefined || value === \"\") continue;\n params.set(key, value);\n }\n }\n const qs = params.toString();\n return `${this.baseUrl}${path}${qs ? `?${qs}` : \"\"}`;\n }\n\n /**\n * Issue an HTTP request and decode the JSON response. Returns\n * `undefined` (cast to T) for `204 No Content`. Throws\n * {@link LiberFiApiError} on every non-2xx, timeout, or network error.\n */\n async request<T>(\n method: LiberFiHttpMethod,\n opts: RequestOptions,\n ): Promise<T> {\n const url = this.buildUrl(opts.path, opts.query);\n const controller = new AbortController();\n const timeoutMs = opts.timeoutMs ?? this.timeout;\n const timeoutId = setTimeout(() => controller.abort(), timeoutMs);\n\n try {\n const response = await this.fetchImpl(url, {\n method,\n headers: {\n Accept: \"application/json\",\n ...(method === \"POST\" ? { \"Content-Type\": \"application/json\" } : {}),\n ...this.headers,\n ...opts.headers,\n },\n body: method === \"POST\" ? JSON.stringify(opts.body ?? {}) : undefined,\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const text = await safeText(response);\n throw new LiberFiApiError(\n `HTTP ${response.status} ${response.statusText} from ${method} ${url}`,\n response.status,\n text,\n );\n }\n\n if (response.status === 204) return undefined as T;\n return (await response.json()) as T;\n } catch (err: unknown) {\n if (err instanceof LiberFiApiError) throw err;\n if (err instanceof Error && err.name === \"AbortError\") {\n throw new LiberFiApiError(\n `Request timeout after ${timeoutMs}ms: ${method} ${url}`,\n 408,\n \"\",\n );\n }\n const message = err instanceof Error ? err.message : String(err);\n throw new LiberFiApiError(\n `Network error: ${method} ${url}: ${message}`,\n 0,\n \"\",\n );\n } finally {\n clearTimeout(timeoutId);\n }\n }\n}\n\nasync function safeText(response: Response): Promise<string> {\n try {\n return await response.text();\n } catch {\n return \"\";\n }\n}\n","import type {\n IPerpetualsClient,\n MarketData,\n Kline,\n KlineInterval,\n KlineQueryOptions,\n OrderBook,\n Trade,\n PlaceOrderParams,\n PlaceOrderResult,\n CancelOrderParams,\n CancelOrderResult,\n GetPositionsParams,\n GetPositionsResult,\n GetOpenOrdersParams,\n GetOpenOrdersResult,\n GetTradesParams,\n GetTradesResult,\n Position,\n Order,\n TradeHistory,\n ActiveAssetLeverage,\n GetActiveAssetLeverageParams,\n AssetMeta,\n GetAssetMetaParams,\n} from \"../../types\";\nimport { WebSocketManager } from \"../hyperliquid/WebSocketManager\";\nimport { LiberFiHttpTransport, LiberFiApiError } from \"./transport\";\n\n// Re-export the error so existing consumers continue to import it from\n// the perpetuals-client module.\nexport { LiberFiApiError };\n\n// ===== Public configuration ===================================================\n\n/**\n * `signTypedData` is invoked once per place / cancel during the\n * `prepare → submit` flow. The hosting app injects this so the user's wallet\n * (privy / wagmi / etc.) controls the keys — perpetuals-server never sees them.\n *\n * The `typedData` argument is the EIP-712 envelope returned verbatim by the\n * server. The function must return the resulting compact signature as a\n * `0x`-prefixed hex string.\n */\nexport type SignTypedDataFn = (\n typedData: Record<string, unknown>,\n) => Promise<`0x${string}`>;\n\n/** Configuration for {@link LiberFiPerpetualsClient}. */\nexport interface LiberFiPerpetualsClientConfig {\n /**\n * REST base URL, with NO trailing slash. Examples:\n * - Local dev: `http://localhost:8080`\n * - Staging: `https://api.liberfi.io/staging/perpetuals`\n * - Production: `https://api.liberfi.io/perpetuals`\n *\n * The client appends `/v1/...` paths to this value. Required UNLESS a\n * pre-built {@link LiberFiHttpTransport} is supplied via `transport`,\n * in which case the transport's baseUrl is used.\n */\n baseUrl?: string;\n\n /**\n * Optional WebSocket endpoint. Real-time data is NOT proxied by\n * perpetuals-server today — the WS subscription methods connect directly to\n * the upstream exchange. Defaults to Hyperliquid mainnet.\n */\n wsEndpoint?: string;\n\n /**\n * EIP-712 signer injected by the hosting app. REQUIRED for `placeOrder` /\n * `cancelOrder`; read-only methods work without it.\n */\n signTypedData?: SignTypedDataFn;\n\n /**\n * Per-request timeout in milliseconds. Defaults to 30 000 ms.\n * Ignored when `transport` is provided (the transport carries its own).\n */\n timeout?: number;\n\n /**\n * Optional provider override sent as `?provider=...`. Defaults to the server\n * configuration (currently `hyperliquid`). Only set this when the gateway\n * has multiple providers configured and you want a non-default one.\n */\n provider?: string;\n\n /**\n * Optional extra request headers (auth tokens, tracing, etc.) merged into\n * every fetch. Ignored when `transport` is provided.\n */\n headers?: Record<string, string>;\n\n /**\n * Inject a pre-built transport instead of letting the client construct\n * one from `baseUrl` / `timeout` / `headers`. Required when sharing a\n * single transport with the deposit client to halve the per-call\n * configuration footprint in `PerpetualsProvider`.\n */\n transport?: LiberFiHttpTransport;\n}\n\nconst DEFAULT_WS_ENDPOINT = \"wss://api.hyperliquid.xyz/ws\";\n\n// ===== Server-side wire types (mirror perpetuals-server/internal/domain) =======\n//\n// These intentionally use snake-free camelCase exactly matching the Go\n// `json:\"…\"` tags. They are kept private so consumers depend only on the\n// stable IPerpetualsClient surface above.\n\ninterface CoinDTO {\n symbol: string;\n name: string;\n tickSize?: number;\n stepSize?: number;\n minOrderSize?: number;\n maxLeverage?: number;\n}\n\ntype MarketDTO = MarketData;\ntype OrderBookDTO = OrderBook;\ntype TradeDTO = Trade;\ntype KlineDTO = Kline;\n\ninterface AccountDTO {\n totalEquity: number;\n availableBalance: number;\n totalUnrealizedPnl: number;\n usedMargin?: number;\n accountLeverage?: number;\n}\n\ninterface PositionsResultDTO {\n positions: Position[];\n account?: AccountDTO;\n}\n\ntype OrderDTO = Order;\n\ninterface UserFillDTO {\n tradeId: string;\n orderId: string;\n symbol: string;\n side: \"long\" | \"short\";\n price: number;\n quantity: number;\n fee: number;\n feeCurrency: string;\n isMaker: boolean;\n timestamp: number;\n}\n\ninterface PreparedActionDTO {\n typedData: Record<string, unknown>;\n action: Record<string, unknown>;\n nonce: number;\n vaultAddress?: string;\n}\n\ntype PlaceOrderResultDTO = PlaceOrderResult;\ntype CancelOrderResultDTO = CancelOrderResult;\n\n// ===== Implementation ============================================================\n\n/**\n * REST + injected-signer implementation of {@link IPerpetualsClient} that talks\n * to a deployed `perpetuals-server` instead of Hyperliquid directly.\n *\n * - Read-only methods are plain `fetch GET`s.\n * - `placeOrder` / `cancelOrder` follow the two-phase flow:\n * 1. POST `…/prepare` → server builds upstream action + EIP-712 typed data.\n * 2. Host wallet signs `typedData` via the injected `signTypedData`.\n * 3. POST `…/submit` with the original `action`, the user signature, and\n * the server-issued `nonce`. The server forwards to upstream and\n * normalises the response.\n * - WebSocket subscriptions are NOT proxied through perpetuals-server today.\n * They reuse the existing {@link WebSocketManager} pointed at the upstream\n * exchange (`wsEndpoint`, default Hyperliquid mainnet).\n */\nexport class LiberFiPerpetualsClient implements IPerpetualsClient {\n private readonly transport: LiberFiHttpTransport;\n private readonly wsEndpoint: string;\n private readonly signTypedData?: SignTypedDataFn;\n private wsManager: WebSocketManager | null = null;\n /**\n * Reference count of active WebSocket consumers (one per React hook\n * instance). The underlying connection is opened lazily on the first\n * connect() call and torn down only when the last consumer leaves —\n * this prevents one widget's unmount from killing the live stream\n * other widgets (order book, trades, ticker) still depend on.\n */\n private wsRefCount = 0;\n\n constructor(config: LiberFiPerpetualsClientConfig) {\n // Two construction modes: legacy (baseUrl / timeout / headers) or\n // transport-injected. The deposit client constructor mirrors the\n // same pattern so both share a consistent shape.\n if (config.transport) {\n this.transport = config.transport;\n } else {\n if (!config.baseUrl) {\n throw new Error(\n \"LiberFiPerpetualsClient: either `baseUrl` or a pre-built `transport` is required.\",\n );\n }\n this.transport = new LiberFiHttpTransport({\n baseUrl: config.baseUrl,\n timeout: config.timeout,\n headers: config.headers,\n defaultQuery: config.provider\n ? { provider: config.provider }\n : undefined,\n });\n }\n this.wsEndpoint = config.wsEndpoint ?? DEFAULT_WS_ENDPOINT;\n this.signTypedData = config.signTypedData;\n }\n\n // ── IPerpetualsClient: market data ────────────────────────────────────────\n\n async getSupportedCoins(): Promise<string[]> {\n const coins = await this.transport.request<CoinDTO[]>(\"GET\", {\n path: \"/v1/coins\",\n });\n return coins.map((coin) => coin.symbol);\n }\n\n async getMarket(symbol: string): Promise<MarketData | null> {\n try {\n return await this.transport.request<MarketDTO>(\"GET\", {\n path: `/v1/markets/${encodeURIComponent(symbol)}`,\n });\n } catch (err) {\n if (err instanceof LiberFiApiError && err.statusCode === 404) return null;\n throw err;\n }\n }\n\n async getMarkets(symbols?: string[]): Promise<MarketData[]> {\n return this.transport.request<MarketDTO[]>(\"GET\", {\n path: \"/v1/markets\",\n query:\n symbols && symbols.length > 0\n ? { symbols: symbols.join(\",\") }\n : undefined,\n });\n }\n\n async getKlines(\n symbol: string,\n interval: KlineInterval,\n limitOrOptions: number | KlineQueryOptions = 100,\n ): Promise<Kline[]> {\n const options: KlineQueryOptions =\n typeof limitOrOptions === \"number\"\n ? { limit: limitOrOptions }\n : limitOrOptions;\n\n const query: Record<string, string> = { interval };\n if (options.limit !== undefined) {\n query.limit = String(options.limit);\n }\n // Forward time-range parameters as `start` / `end` (ms epochs) — matches\n // the openapi-server `KlineParams` contract. Required for TradingView\n // backward history pagination.\n if (options.from !== undefined) {\n query.start = String(options.from);\n }\n if (options.to !== undefined) {\n query.end = String(options.to);\n }\n\n return this.transport.request<KlineDTO[]>(\"GET\", {\n path: `/v1/markets/${encodeURIComponent(symbol)}/klines`,\n query,\n });\n }\n\n async getOrderBook(\n symbol: string,\n maxLevel: number = 10,\n options?: { nSigFigs?: number; mantissa?: number },\n ): Promise<OrderBook> {\n const query: Record<string, string> = { maxLevel: String(maxLevel) };\n if (options?.nSigFigs !== undefined) {\n query.nSigFigs = String(options.nSigFigs);\n if (\n options.nSigFigs === 5 &&\n options.mantissa &&\n options.mantissa !== 1\n ) {\n query.mantissa = String(options.mantissa);\n }\n }\n return this.transport.request<OrderBookDTO>(\"GET\", {\n path: `/v1/markets/${encodeURIComponent(symbol)}/orderbook`,\n query,\n });\n }\n\n async getRecentTrades(symbol: string, limit: number = 50): Promise<Trade[]> {\n return this.transport.request<TradeDTO[]>(\"GET\", {\n path: `/v1/markets/${encodeURIComponent(symbol)}/trades`,\n query: { limit: String(limit) },\n });\n }\n\n // ── IPerpetualsClient: account ────────────────────────────────────────────\n\n async getPositions(\n params: GetPositionsParams = {},\n ): Promise<GetPositionsResult> {\n if (!params.userAddress) {\n throw new Error(\n \"LiberFiPerpetualsClient.getPositions requires `userAddress`.\",\n );\n }\n const result = await this.transport.request<PositionsResultDTO>(\"GET\", {\n path: `/v1/users/${encodeURIComponent(params.userAddress)}/positions`,\n query: { symbol: params.symbol },\n });\n\n return {\n positions: result.positions,\n totalEquity: result.account?.totalEquity,\n availableBalance: result.account?.availableBalance,\n totalUnrealizedPnl: result.account?.totalUnrealizedPnl,\n raw: result,\n };\n }\n\n async getOpenOrders(\n params: GetOpenOrdersParams = {},\n ): Promise<GetOpenOrdersResult> {\n if (!params.userAddress) {\n throw new Error(\n \"LiberFiPerpetualsClient.getOpenOrders requires `userAddress`.\",\n );\n }\n const orders = await this.transport.request<OrderDTO[]>(\"GET\", {\n path: `/v1/users/${encodeURIComponent(params.userAddress)}/orders`,\n query: { symbol: params.symbol },\n });\n return { orders, totalCount: orders.length, raw: orders };\n }\n\n async getTrades(params: GetTradesParams = {}): Promise<GetTradesResult> {\n if (!params.userAddress) {\n throw new Error(\n \"LiberFiPerpetualsClient.getTrades requires `userAddress`.\",\n );\n }\n const fills = await this.transport.request<UserFillDTO[]>(\"GET\", {\n path: `/v1/users/${encodeURIComponent(params.userAddress)}/fills`,\n query: {\n symbol: params.symbol,\n limit: params.limit !== undefined ? String(params.limit) : undefined,\n startTime:\n params.startTime !== undefined ? String(params.startTime) : undefined,\n endTime:\n params.endTime !== undefined ? String(params.endTime) : undefined,\n },\n });\n const trades: TradeHistory[] = fills.map((fill) => ({\n tradeId: fill.tradeId,\n orderId: fill.orderId,\n symbol: fill.symbol,\n side: fill.side,\n price: fill.price,\n quantity: fill.quantity,\n fee: fill.fee,\n feeCurrency: fill.feeCurrency,\n isMaker: fill.isMaker,\n timestamp: fill.timestamp,\n }));\n return { trades, totalCount: trades.length, raw: fills };\n }\n\n /**\n * The LiberFi backend does not yet expose an `activeAssetData`\n * equivalent. Returning `null` lets the form fall back to its own\n * default leverage without raising — the perpetuals-server can grow\n * this endpoint later and we'll plug it in here.\n */\n async getActiveAssetLeverage(\n _params: GetActiveAssetLeverageParams,\n ): Promise<ActiveAssetLeverage | null> {\n return null;\n }\n\n /**\n * The LiberFi backend doesn't currently surface per-asset\n * `szDecimals` / `maxLeverage` over a dedicated endpoint. We could\n * derive `szDecimals` from {@link getSupportedCoins}'s `stepSize`\n * once perpetuals-server starts populating it (`szDecimals =\n * -log10(stepSize)`), but until then the form falls back to its\n * adaptive heuristic when this returns `null`.\n *\n * TODO(perpetuals-server): expose `GET /v1/markets/:symbol/meta`\n * (or extend the existing `/v1/coins` payload with `szDecimals` +\n * `maxLeverage`) so this can resolve without a side trip to the\n * upstream venue.\n */\n async getAssetMeta(_params: GetAssetMetaParams): Promise<AssetMeta | null> {\n return null;\n }\n\n // ── IPerpetualsClient: trading (two-phase signing) ────────────────────────\n\n async placeOrder(params: PlaceOrderParams): Promise<PlaceOrderResult> {\n if (!this.signTypedData) {\n throw new Error(\n \"LiberFiPerpetualsClient.placeOrder requires `signTypedData` to be configured.\",\n );\n }\n if (!params.userAddress) {\n throw new Error(\n \"LiberFiPerpetualsClient.placeOrder requires `userAddress` (the signing wallet).\",\n );\n }\n\n const prepared = await this.transport.request<PreparedActionDTO>(\"POST\", {\n path: \"/v1/orders/prepare\",\n body: {\n userAddress: params.userAddress,\n symbol: params.symbol,\n side: params.side,\n orderType: params.orderType,\n amount: params.amount,\n price: params.price,\n leverage: params.leverage,\n reduceOnly: params.reduceOnly,\n takeProfitPrice: params.takeProfitPrice,\n stopLossPrice: params.stopLossPrice,\n clientOrderId: params.clientOrderId,\n },\n });\n\n const signature = await this.signTypedData(prepared.typedData);\n\n return this.transport.request<PlaceOrderResultDTO>(\"POST\", {\n path: \"/v1/orders/submit\",\n body: {\n action: prepared.action,\n signature,\n nonce: prepared.nonce,\n vaultAddress: prepared.vaultAddress,\n },\n });\n }\n\n async cancelOrder(params: CancelOrderParams): Promise<CancelOrderResult> {\n if (!this.signTypedData) {\n throw new Error(\n \"LiberFiPerpetualsClient.cancelOrder requires `signTypedData` to be configured.\",\n );\n }\n if (!params.userAddress) {\n throw new Error(\n \"LiberFiPerpetualsClient.cancelOrder requires `userAddress` (the signing wallet).\",\n );\n }\n\n const prepared = await this.transport.request<PreparedActionDTO>(\"POST\", {\n path: \"/v1/orders/cancel/prepare\",\n body: {\n userAddress: params.userAddress,\n symbol: params.symbol,\n orderId: params.orderId,\n clientOrderId: params.clientOrderId,\n },\n });\n\n const signature = await this.signTypedData(prepared.typedData);\n\n return this.transport.request<CancelOrderResultDTO>(\"POST\", {\n path: \"/v1/orders/cancel/submit\",\n body: {\n action: prepared.action,\n signature,\n nonce: prepared.nonce,\n vaultAddress: prepared.vaultAddress,\n },\n });\n }\n\n // ── IPerpetualsClient: WebSocket (direct upstream, NOT proxied) ───────────\n\n async connectWebSocket(): Promise<void> {\n this.wsRefCount += 1;\n if (!this.wsManager) {\n this.wsManager = new WebSocketManager(this.wsEndpoint);\n }\n if (this.wsManager.isConnectedNow()) return;\n await this.wsManager.connect();\n }\n\n disconnectWebSocket(): void {\n this.wsRefCount = Math.max(0, this.wsRefCount - 1);\n if (this.wsRefCount === 0 && this.wsManager) {\n this.wsManager.disconnect();\n this.wsManager = null;\n }\n }\n\n subscribeMarketData(\n type: \"ticker\" | \"trades\" | \"orderBook\",\n symbol: string,\n callback: (data: unknown) => void,\n options?: {\n aggregation?: { nSigFigs?: 2 | 3 | 4 | 5; mantissa?: 1 | 2 | 5 };\n },\n ): string {\n // The shared {@link WebSocketManager} speaks Hyperliquid's protocol, so\n // when the aggregation hint is provided we forward it as nSigFigs/mantissa\n // regardless of which client we're behind.\n return this.requireWS().subscribe(\n type,\n symbol,\n callback,\n options?.aggregation,\n );\n }\n\n subscribeCandles(\n symbol: string,\n interval: KlineInterval,\n callback: (candle: Kline) => void,\n ): string {\n return this.requireWS().subscribe(\n \"candle\",\n `${symbol}:${interval}`,\n callback,\n );\n }\n\n subscribeUserData(\n type: \"orders\" | \"positions\" | \"fills\",\n userAddress: string,\n callback: (data: unknown) => void,\n ): string {\n const channel = type === \"fills\" ? \"userFills\" : \"userEvents\";\n return this.requireWS().subscribe(channel, userAddress, callback);\n }\n\n unsubscribe(subscriptionId: string): void {\n if (this.wsManager) {\n this.wsManager.unsubscribe(subscriptionId);\n }\n }\n\n private requireWS(): WebSocketManager {\n if (!this.wsManager) {\n throw new Error(\n \"WebSocket not connected. Call connectWebSocket() first.\",\n );\n }\n return this.wsManager;\n }\n}\n","/**\n * REST client for the Solana → Hyperliquid deposit endpoints exposed by\n * the perpetuals-server (`/v1/deposits/*`).\n *\n * Engineering principles:\n * - Single responsibility: this file knows about /v1/deposits and\n * nothing else. Quote orchestration, fee adapters, status\n * reconciliation, etc. live server-side.\n * - Modularity: the HTTP transport is injected (or built from a\n * baseUrl) so integration tests can drop in a fetch mock; production\n * code shares the same transport instance with `LiberFiPerpetualsClient`.\n * - First principles: three methods (quote / submit / status), no\n * hidden state, no caching. Polling is the caller's concern (the\n * hooks do it via TanStack Query).\n */\nimport type {\n DepositQuoteRequest,\n DepositQuoteResponse,\n DepositStatusResponse,\n DepositSubmitRequest,\n DepositSubmitResponse,\n} from \"./deposit-types\";\nimport {\n LiberFiHttpTransport,\n type LiberFiHttpTransportConfig,\n} from \"./transport\";\n\n/**\n * Options for constructing a `LiberFiPerpDepositClient`.\n *\n * Either provide a pre-built `transport` (preferred — share one with\n * `LiberFiPerpetualsClient` so connection limits, headers and timeouts\n * stay consistent) or pass the raw config and let the client build one.\n */\nexport type LiberFiPerpDepositClientConfig =\n | { transport: LiberFiHttpTransport }\n | LiberFiHttpTransportConfig;\n\n/** Public surface of the deposit client; matches the three handler endpoints. */\nexport interface IPerpDepositClient {\n /** POST /v1/deposits/quote */\n quote(req: DepositQuoteRequest): Promise<DepositQuoteResponse>;\n /** POST /v1/deposits/submit */\n submit(req: DepositSubmitRequest): Promise<DepositSubmitResponse>;\n /** GET /v1/deposits/{id} */\n status(intentId: string): Promise<DepositStatusResponse>;\n /** POST /v1/deposits/{id}/refresh — bypasses any future cache TTL. */\n refresh(intentId: string): Promise<DepositStatusResponse>;\n}\n\n/** Concrete implementation backed by `LiberFiHttpTransport`. */\nexport class LiberFiPerpDepositClient implements IPerpDepositClient {\n private readonly transport: LiberFiHttpTransport;\n\n constructor(config: LiberFiPerpDepositClientConfig) {\n this.transport =\n \"transport\" in config\n ? config.transport\n : new LiberFiHttpTransport(config);\n }\n\n /** Returns the base URL of the underlying transport (mostly for logs/diagnostics). */\n getBaseUrl(): string {\n return this.transport.getBaseUrl();\n }\n\n async quote(req: DepositQuoteRequest): Promise<DepositQuoteResponse> {\n return this.transport.request<DepositQuoteResponse>(\"POST\", {\n path: \"/v1/deposits/quote\",\n body: req,\n });\n }\n\n async submit(req: DepositSubmitRequest): Promise<DepositSubmitResponse> {\n return this.transport.request<DepositSubmitResponse>(\"POST\", {\n path: \"/v1/deposits/submit\",\n body: req,\n });\n }\n\n async status(intentId: string): Promise<DepositStatusResponse> {\n if (!intentId) throw new Error(\"intentId is required\");\n return this.transport.request<DepositStatusResponse>(\"GET\", {\n path: `/v1/deposits/${encodeURIComponent(intentId)}`,\n });\n }\n\n async refresh(intentId: string): Promise<DepositStatusResponse> {\n if (!intentId) throw new Error(\"intentId is required\");\n return this.transport.request<DepositStatusResponse>(\"POST\", {\n path: `/v1/deposits/${encodeURIComponent(intentId)}/refresh`,\n });\n }\n}\n","/**\n * Wire / domain types for the Solana → Hyperliquid USDC deposit flow.\n *\n * These deliberately mirror the perpetuals-server DTOs (see\n * `internal/handler/deposit_handler.go`) so the SDK <-> backend contract\n * stays in sync. When the backend adds a new field, add it here too —\n * the compiler will then point at every place that needs to handle it.\n *\n * All amounts denominated in *smallest unit* (lamports for SOL, USDC's\n * 6-decimal microUSDC for the destination side) are typed as `string` so\n * we never accidentally lose precision on large values.\n */\n\n/** Where the deposit was initiated from. Drives fee attribution server-side. */\nexport type DepositSource = \"dex\" | \"prediction\" | \"launchpad\" | \"channel\";\n\n/** Lifecycle states a deposit can be in. */\nexport type DepositStatus =\n | \"broadcasted\" // user signed + broadcast on Solana, server has not seen Relay yet\n | \"relay_waiting\" // Relay observed the deposit but hasn't started forwarding\n | \"relay_pending\" // Relay is forwarding the deposit cross-chain\n | \"settled\" // funds delivered to Hyperliquid\n | \"refunded\" // Relay refunded — funds returned to user wallet\n | \"failed\" // terminal failure\n | \"stuck\"; // observed > stuckAfter without Relay seeing it; ops review\n\n/** True for status values that never transition further. */\nexport const TERMINAL_DEPOSIT_STATUSES: ReadonlySet<DepositStatus> =\n new Set<DepositStatus>([\"settled\", \"refunded\", \"failed\"]);\n\n/** A single state transition in the status history. */\nexport interface DepositStatusTransition {\n from: DepositStatus | \"\";\n to: DepositStatus;\n at: string; // ISO 8601 timestamp\n source: \"handler\" | \"status_pull\" | \"reconciliation\" | string;\n reason?: string;\n}\n\n/** Surfaced when the upstream produced an unrecoverable error. */\nexport interface DepositErrorInfo {\n code: string;\n message: string;\n recoverable: boolean;\n}\n\n/** Exact-decimal breakdown returned by the quote endpoint. */\nexport interface DepositBreakdown {\n /** Total lamports the user is paying in (gross). */\n grossLamports: string;\n /** Platform fee transferred to the LiberFi treasury (lamports). */\n platformFeeLamports: string;\n /** Net amount Relay bridges (= gross − platformFee), in lamports. */\n relayDepositLamports: string;\n /** SOL pubkey the platform fee is sent to. May be empty when fee = 0. */\n treasuryAddress: string;\n /** Expected destination output, in microUSDC (6-decimal). May be empty. */\n expectedOutputUSDC?: string;\n /** Origin chain id (Solana mainnet on Relay = 792703809). */\n originChainId: number;\n /** Destination chain id (Hyperliquid). */\n destinationChainId: number;\n /** Origin currency. SOL is encoded as the SystemProgram pseudo-pubkey. */\n originCurrency: string;\n /** Destination currency contract. */\n destinationCurrency: string;\n /** Relay-issued depository address — the program/wallet receiving SOL. */\n depository?: string;\n /** Relay request id; populated once Relay returns a quote. */\n relayRequestId?: string;\n}\n\n/** Body of POST /v1/deposits/quote. */\nexport interface DepositQuoteRequest {\n userSolanaAddress: string;\n hyperliquidRecipient: string;\n /** Smallest-unit amount the user is paying in. */\n grossLamports: string;\n /** Fee attribution source. Defaults to `dex` server-side when empty. */\n source: DepositSource;\n}\n\n/** Response of POST /v1/deposits/quote. */\nexport interface DepositQuoteResponse {\n /** Base64 SOL transaction the user signs in their wallet. */\n serializedTxBase64: string;\n /** Transaction size on the wire (used by client-side guards). */\n sizeBytes: number;\n /** True for v0 transactions (legacy = false). */\n isVersioned: boolean;\n breakdown: DepositBreakdown;\n /** ISO 8601 timestamp the quote was issued at. */\n issuedAt: string;\n /** ISO 8601 timestamp the quote expires at. */\n expiresAt: string;\n}\n\n/** Body of POST /v1/deposits/submit. */\nexport interface DepositSubmitRequest {\n userSolanaAddress: string;\n hyperliquidRecipient: string;\n /** The signed transaction's hash, returned by the wallet on broadcast. */\n solanaTxHash: string;\n breakdown: DepositBreakdown;\n /** Stable user identifier (LiberFi user id, NOT the wallet address). */\n userId: string;\n source: DepositSource;\n /** Optional marketing campaign / referral code passed through to attribution. */\n campaign?: string;\n /** Mirror back the issuedAt from /quote so the server can guard freshness. */\n quoteIssuedAt: string;\n}\n\n/** Response of POST /v1/deposits/submit. */\nexport interface DepositSubmitResponse {\n intentId: string;\n /** True the first time a unique solanaTxHash is seen; idempotent retries return false. */\n created: boolean;\n}\n\n/** Response of GET /v1/deposits/{id}. */\nexport interface DepositStatusResponse {\n intentId: string;\n status: DepositStatus;\n userSolanaAddress: string;\n hyperliquidRecipient: string;\n solanaTxHash: string;\n relayRequestId?: string;\n hyperliquidTxHash?: string;\n breakdown: DepositBreakdown;\n statusHistory: DepositStatusTransition[];\n lastError?: DepositErrorInfo;\n userId: string;\n source: DepositSource;\n campaign?: string;\n createdAt: string;\n updatedAt: string;\n}\n","/**\n * Pure state machine for the deposit UI.\n *\n * The backend owns the *authoritative* lifecycle (broadcasted → relay_*\n * → settled / refunded / failed / stuck). The frontend has a few extra\n * states *before* we can call /submit (idle, quoting, ready_to_sign,\n * signing, broadcasting). We model both halves here as a single FSM so\n * presentational components can switch on a single tag.\n *\n * Engineering principles applied:\n * - First principles: a state is a *type*, transitions are pure\n * functions over (state, event) → state. No timers, no fetch, no\n * setState — those live in hooks.\n * - Single responsibility: this file knows nothing about HTTP, React,\n * or wallets. It is unit-testable in isolation.\n * - Extensibility: add a new event by extending DepositEvent + a case\n * in `reduceDepositState`. The compiler enforces exhaustiveness.\n */\nimport {\n type DepositBreakdown,\n type DepositErrorInfo,\n type DepositQuoteResponse,\n type DepositStatus,\n type DepositStatusResponse,\n TERMINAL_DEPOSIT_STATUSES,\n} from \"./deposit-types\";\n\n/** UI-only state tags. Server-driven tags are a subset of DepositStatus. */\nexport type DepositPhase =\n | \"idle\" // user hasn't requested a quote yet\n | \"quoting\" // /quote in flight\n | \"ready_to_sign\" // quote received, awaiting wallet signature\n | \"signing\" // wallet is signing\n | \"broadcasting\" // signed tx submitted to RPC, waiting for hash\n | \"submitted\" // /submit called, intentId returned\n | \"tracking\" // polling /status with a non-terminal lifecycle status\n | \"succeeded\" // terminal: settled\n | \"refunded\" // terminal: refunded\n | \"failed\" // terminal: failed | stuck (or any local error)\n | \"expired\"; // quote expired before user signed\n\n/** Discriminated union representing the entire deposit flow at any moment. */\nexport type DepositState =\n | { phase: \"idle\" }\n | { phase: \"quoting\" }\n | {\n phase: \"ready_to_sign\";\n quote: DepositQuoteResponse;\n /** Epoch ms — caller pre-computes for stable comparisons. */\n expiresAtMs: number;\n }\n | { phase: \"signing\"; quote: DepositQuoteResponse }\n | { phase: \"broadcasting\"; quote: DepositQuoteResponse }\n | {\n phase: \"submitted\";\n quote: DepositQuoteResponse;\n intentId: string;\n solanaTxHash: string;\n }\n | {\n phase: \"tracking\";\n intentId: string;\n status: DepositStatusResponse;\n }\n | {\n phase: \"succeeded\";\n intentId: string;\n status: DepositStatusResponse;\n }\n | {\n phase: \"refunded\";\n intentId: string;\n status: DepositStatusResponse;\n }\n | {\n phase: \"failed\";\n error: DepositErrorInfo;\n /** Populated when the failure happened post-submit. */\n intentId?: string;\n status?: DepositStatusResponse;\n }\n | { phase: \"expired\"; quote: DepositQuoteResponse };\n\n/** Events the FSM can react to. Driven by hooks/components. */\nexport type DepositEvent =\n | { type: \"RESET\" }\n | { type: \"QUOTE_REQUEST\" }\n | { type: \"QUOTE_RECEIVED\"; quote: DepositQuoteResponse }\n | { type: \"QUOTE_FAILED\"; error: DepositErrorInfo }\n | { type: \"QUOTE_EXPIRED\" }\n | { type: \"SIGN_START\" }\n | { type: \"SIGN_FAILED\"; error: DepositErrorInfo }\n | { type: \"BROADCAST_START\" }\n | { type: \"BROADCAST_FAILED\"; error: DepositErrorInfo }\n | {\n type: \"SUBMIT_OK\";\n intentId: string;\n solanaTxHash: string;\n }\n | { type: \"SUBMIT_FAILED\"; error: DepositErrorInfo }\n | { type: \"STATUS_UPDATE\"; status: DepositStatusResponse };\n\nexport const initialDepositState: DepositState = { phase: \"idle\" };\n\n/**\n * Transition function. Pure, total — every (state, event) pair is\n * handled. Unknown transitions are no-ops (return current state); we\n * don't throw because hooks may fan out events optimistically (e.g. a\n * stale STATUS_UPDATE arriving after RESET).\n */\nexport function reduceDepositState(\n state: DepositState,\n event: DepositEvent,\n): DepositState {\n switch (event.type) {\n case \"RESET\":\n return initialDepositState;\n\n case \"QUOTE_REQUEST\":\n // Allowed from idle, ready_to_sign (re-quote), expired, failed (retry).\n if (\n state.phase === \"idle\" ||\n state.phase === \"ready_to_sign\" ||\n state.phase === \"expired\" ||\n state.phase === \"failed\"\n ) {\n return { phase: \"quoting\" };\n }\n return state;\n\n case \"QUOTE_RECEIVED\":\n if (state.phase === \"quoting\") {\n return {\n phase: \"ready_to_sign\",\n quote: event.quote,\n expiresAtMs: Date.parse(event.quote.expiresAt),\n };\n }\n return state;\n\n case \"QUOTE_FAILED\":\n if (state.phase === \"quoting\") {\n return { phase: \"failed\", error: event.error };\n }\n return state;\n\n case \"QUOTE_EXPIRED\":\n if (state.phase === \"ready_to_sign\") {\n return { phase: \"expired\", quote: state.quote };\n }\n return state;\n\n case \"SIGN_START\":\n if (state.phase === \"ready_to_sign\") {\n return { phase: \"signing\", quote: state.quote };\n }\n return state;\n\n case \"SIGN_FAILED\":\n if (state.phase === \"signing\") {\n // Keep the quote so the UI can offer a retry without re-quoting.\n return { phase: \"failed\", error: event.error };\n }\n return state;\n\n case \"BROADCAST_START\":\n if (state.phase === \"signing\") {\n return { phase: \"broadcasting\", quote: state.quote };\n }\n return state;\n\n case \"BROADCAST_FAILED\":\n if (state.phase === \"broadcasting\" || state.phase === \"signing\") {\n return { phase: \"failed\", error: event.error };\n }\n return state;\n\n case \"SUBMIT_OK\":\n if (state.phase === \"broadcasting\") {\n return {\n phase: \"submitted\",\n quote: state.quote,\n intentId: event.intentId,\n solanaTxHash: event.solanaTxHash,\n };\n }\n return state;\n\n case \"SUBMIT_FAILED\":\n if (state.phase === \"broadcasting\") {\n return { phase: \"failed\", error: event.error };\n }\n return state;\n\n case \"STATUS_UPDATE\": {\n // /status is polled after submit. Map the backend status to the UI phase.\n if (state.phase !== \"submitted\" && state.phase !== \"tracking\") {\n return state;\n }\n const intentId =\n state.phase === \"submitted\" ? state.intentId : state.intentId;\n const next = mapStatusToPhase(event.status, intentId);\n return next;\n }\n }\n}\n\nfunction mapStatusToPhase(\n status: DepositStatusResponse,\n intentId: string,\n): DepositState {\n switch (status.status) {\n case \"settled\":\n return { phase: \"succeeded\", intentId, status };\n case \"refunded\":\n return { phase: \"refunded\", intentId, status };\n case \"failed\":\n case \"stuck\":\n return {\n phase: \"failed\",\n error: status.lastError ?? {\n code: status.status === \"stuck\" ? \"STUCK\" : \"FAILED\",\n message:\n status.status === \"stuck\"\n ? \"Deposit hasn't been observed by Relay yet — please contact support if this persists.\"\n : \"Deposit failed. Funds will be refunded to your wallet shortly.\",\n recoverable: false,\n },\n intentId,\n status,\n };\n case \"broadcasted\":\n case \"relay_waiting\":\n case \"relay_pending\":\n default:\n return { phase: \"tracking\", intentId, status };\n }\n}\n\n// =====================================================================\n// Selectors — the same data, but in a shape components can render.\n// Defining them here keeps the UI free of `if (state.phase === \"...\" )`\n// branching.\n// =====================================================================\n\n/** True when the FSM has reached a terminal phase. */\nexport function isTerminal(state: DepositState): boolean {\n return (\n state.phase === \"succeeded\" ||\n state.phase === \"refunded\" ||\n state.phase === \"failed\"\n );\n}\n\n/** True when the UI should keep polling /status. */\nexport function isPolling(state: DepositState): boolean {\n return state.phase === \"submitted\" || state.phase === \"tracking\";\n}\n\n/** Returns the current backend lifecycle status, if any. */\nexport function currentStatus(state: DepositState): DepositStatus | undefined {\n if (\n state.phase === \"tracking\" ||\n state.phase === \"succeeded\" ||\n state.phase === \"refunded\"\n ) {\n return state.status.status;\n }\n if (state.phase === \"failed\" && state.status) {\n return state.status.status;\n }\n return undefined;\n}\n\n/** Returns the breakdown the UI should display, if any. */\nexport function currentBreakdown(\n state: DepositState,\n): DepositBreakdown | undefined {\n if (\n state.phase === \"ready_to_sign\" ||\n state.phase === \"signing\" ||\n state.phase === \"broadcasting\" ||\n state.phase === \"submitted\" ||\n state.phase === \"expired\"\n ) {\n return state.quote.breakdown;\n }\n if (\n state.phase === \"tracking\" ||\n state.phase === \"succeeded\" ||\n state.phase === \"refunded\"\n ) {\n return state.status.breakdown;\n }\n if (state.phase === \"failed\" && state.status) {\n return state.status.breakdown;\n }\n return undefined;\n}\n\n/**\n * Returns true when the phase is terminal *and* corresponds to one of\n * the known DepositStatus terminal values. Useful for analytics fan-out\n * (only emit the funnel-end event once per intent).\n */\nexport function isTerminalLifecycle(\n status: DepositStatus | undefined,\n): boolean {\n return status !== undefined && TERMINAL_DEPOSIT_STATUSES.has(status);\n}\n","import { createContext } from \"react\";\nimport type { IPerpDepositClient } from \"../client/liberfi/LiberFiPerpDepositClient\";\nimport type { IPerpetualsClient } from \"../types\";\n\n/**\n * Perpetuals context value type\n *\n * Provides access to the perpetuals trading client and (optionally) the\n * deposit client. The deposit client is optional because not every\n * surface that consumes this provider also needs the deposit flow — a\n * portfolio view that only renders positions can omit it without\n * pulling the deposit dependency along.\n */\nexport interface PerpetualsContextValue {\n /**\n * Perpetuals client instance for trading operations.\n */\n client: IPerpetualsClient;\n\n /**\n * Deposit client instance for the Solana → Hyperliquid funding flow.\n *\n * Optional: surfaces that don't render the deposit UI can omit it.\n * Hooks that need it (e.g. `usePerpDepositQuote`) will throw a clear\n * error pointing at the missing prop.\n */\n depositClient?: IPerpDepositClient;\n}\n\n/**\n * Perpetuals Context\n *\n * React context for accessing perpetuals trading + deposit functionality\n * throughout the app.\n */\nexport const PerpetualsContext = createContext<PerpetualsContextValue>(\n {} as PerpetualsContextValue,\n);\n","import { PropsWithChildren, useMemo } from \"react\";\nimport {\n PerpetualsContext,\n PerpetualsContextValue,\n} from \"../context/PerpetualsContext\";\n\n/**\n * Perpetuals provider props type.\n *\n * `client` is required; `depositClient` is optional and only needed by\n * surfaces that render the cross-chain deposit flow.\n */\nexport type PerpetualsProviderProps = PropsWithChildren<PerpetualsContextValue>;\n\n/**\n * Perpetuals Provider Component.\n *\n * Wraps the perpetuals trading client and (optionally) the deposit\n * client into a single context value. The value is memoised on the\n * client identities so re-renders of the consumer app do not break\n * referential equality for downstream `useContext` consumers.\n *\n * @param props Provider props containing client(s) and children\n * @returns Provider component wrapping children\n */\nexport function PerpetualsProvider({\n client,\n depositClient,\n children,\n}: PerpetualsProviderProps) {\n const value = useMemo<PerpetualsContextValue>(\n () => ({ client, depositClient }),\n [client, depositClient],\n );\n return (\n <PerpetualsContext.Provider value={value}>\n {children}\n </PerpetualsContext.Provider>\n );\n}\n","import { useContext } from \"react\";\nimport {\n PerpetualsContext,\n PerpetualsContextValue,\n} from \"../context/PerpetualsContext\";\n\n/**\n * Hook to access perpetuals client from context\n *\n * Must be used within a PerpetualsProvider component\n *\n * @returns Perpetuals context value containing the client instance\n * @throws Error if used outside of PerpetualsProvider\n */\nexport function usePerpetualsClient(): PerpetualsContextValue {\n const context = useContext(PerpetualsContext);\n\n if (!context || !context.client) {\n throw new Error(\n \"usePerpetualsClient must be used within a PerpetualsProvider\",\n );\n }\n\n return context;\n}\n","import { useQuery, UseQueryOptions } from \"@tanstack/react-query\";\nimport type { IPerpetualsClient } from \"../types\";\nimport { usePerpetualsClient } from \"./usePerpetualsClient\";\n\nexport function coinsQueryKey(): string[] {\n return [\"perps\", \"coins\"];\n}\n\nexport async function fetchCoins(client: IPerpetualsClient): Promise<string[]> {\n return await client.getSupportedCoins();\n}\n\nexport function useCoinsQuery(\n options: Omit<\n UseQueryOptions<string[], Error, string[], string[]>,\n \"queryKey\" | \"queryFn\"\n > = {},\n) {\n const { client } = usePerpetualsClient();\n return useQuery({\n queryKey: coinsQueryKey(),\n queryFn: async () => fetchCoins(client),\n staleTime: 5 * 60 * 1000,\n ...options,\n });\n}\n","import { useQuery, UseQueryOptions } from \"@tanstack/react-query\";\nimport type { IPerpetualsClient, MarketData } from \"../types\";\nimport { usePerpetualsClient } from \"./usePerpetualsClient\";\n\nexport interface UseMarketQueryParams {\n symbol: string;\n}\n\n/**\n * Default polling cadence for `metaAndAssetCtxs`. Mirrors Axiom's\n * perps page — they refresh meta + asset contexts (mark price, funding\n * rate, open interest, 24h volume) once a minute. Funding rate and\n * volume don't have a WebSocket channel, so without this the place\n * order form's Est. Liq. Price + the coin info header's funding /\n * 24h-vol can drift visibly between mounts.\n */\nconst DEFAULT_REFETCH_INTERVAL_MS = 60_000;\n\nexport function marketQueryKey(params: UseMarketQueryParams): string[] {\n return [\"perps\", \"market\", params.symbol];\n}\n\nexport async function fetchMarket(\n client: IPerpetualsClient,\n { symbol }: UseMarketQueryParams,\n): Promise<MarketData | null> {\n return await client.getMarket(symbol);\n}\n\nexport function useMarketQuery(\n params: UseMarketQueryParams,\n options: Omit<\n UseQueryOptions<MarketData | null, Error, MarketData | null, string[]>,\n \"queryKey\" | \"queryFn\"\n > = {},\n) {\n const { client } = usePerpetualsClient();\n return useQuery({\n queryKey: marketQueryKey(params),\n queryFn: async () => fetchMarket(client, params),\n // Treat the response as fresh for half the polling cadence so a\n // remount during the same window doesn't trigger an extra request.\n staleTime: DEFAULT_REFETCH_INTERVAL_MS / 2,\n refetchInterval: DEFAULT_REFETCH_INTERVAL_MS,\n ...options,\n });\n}\n","import { useQuery, UseQueryOptions } from \"@tanstack/react-query\";\nimport type { IPerpetualsClient, MarketData } from \"../types\";\nimport { usePerpetualsClient } from \"./usePerpetualsClient\";\n\nexport interface UseMarketsQueryParams {\n symbols?: string[];\n}\n\n/**\n * Default polling cadence for `metaAndAssetCtxs`. Mirrors the cadence\n * we observed on Axiom's perps page — they refresh meta + asset\n * contexts (mark price, funding rate, open interest, 24h volume) once\n * a minute. The data is comparatively cheap to refetch and changes on\n * roughly the same timescale, so a slower interval would let funding /\n * OI drift visibly between updates.\n */\nconst DEFAULT_REFETCH_INTERVAL_MS = 60_000;\n\nexport function marketsQueryKey(params: UseMarketsQueryParams = {}): string[] {\n return [\"perps\", \"markets\", JSON.stringify((params.symbols ?? []).sort())];\n}\n\nexport async function fetchMarkets(\n client: IPerpetualsClient,\n { symbols }: UseMarketsQueryParams = {},\n): Promise<MarketData[]> {\n return await client.getMarkets(symbols);\n}\n\nexport function useMarketsQuery(\n params: UseMarketsQueryParams = {},\n options: Omit<\n UseQueryOptions<MarketData[], Error, MarketData[], string[]>,\n \"queryKey\" | \"queryFn\"\n > = {},\n) {\n const { client } = usePerpetualsClient();\n return useQuery({\n queryKey: marketsQueryKey(params),\n queryFn: async () => fetchMarkets(client, params),\n // Treat the response as fresh for half the polling cadence so a\n // remount during the same window doesn't kick off an extra request.\n staleTime: DEFAULT_REFETCH_INTERVAL_MS / 2,\n refetchInterval: DEFAULT_REFETCH_INTERVAL_MS,\n ...options,\n });\n}\n","import { useQuery, UseQueryOptions } from \"@tanstack/react-query\";\nimport type { IPerpetualsClient, Kline, KlineInterval } from \"../types\";\nimport { usePerpetualsClient } from \"./usePerpetualsClient\";\n\nexport interface UseKlinesQueryParams {\n symbol: string;\n interval: KlineInterval;\n limit?: number;\n}\n\nexport function klinesQueryKey(params: UseKlinesQueryParams): string[] {\n return [\n \"perps\",\n \"klines\",\n params.symbol,\n params.interval,\n String(params.limit ?? 100),\n ];\n}\n\nexport async function fetchKlines(\n client: IPerpetualsClient,\n { symbol, interval, limit }: UseKlinesQueryParams,\n): Promise<Kline[]> {\n return await client.getKlines(symbol, interval, limit);\n}\n\nexport function useKlinesQuery(\n params: UseKlinesQueryParams,\n options: Omit<\n UseQueryOptions<Kline[], Error, Kline[], string[]>,\n \"queryKey\" | \"queryFn\"\n > = {},\n) {\n const { client } = usePerpetualsClient();\n return useQuery({\n queryKey: klinesQueryKey(params),\n queryFn: async () => fetchKlines(client, params),\n staleTime: 30 * 1000,\n ...options,\n });\n}\n","import { useQuery, UseQueryOptions } from \"@tanstack/react-query\";\nimport type {\n IPerpetualsClient,\n OrderBook,\n OrderBookAggregationOptions,\n} from \"../types\";\nimport { usePerpetualsClient } from \"./usePerpetualsClient\";\n\nexport interface UseOrderBookQueryParams {\n symbol: string;\n maxLevel?: number;\n /**\n * Optional venue aggregation params (e.g. Hyperliquid `nSigFigs` /\n * `mantissa`). When set, the request key includes these so different\n * aggregations cache independently.\n */\n aggregation?: OrderBookAggregationOptions;\n}\n\nexport function orderBookQueryKey(params: UseOrderBookQueryParams): string[] {\n const agg = params.aggregation;\n const aggKey =\n agg?.nSigFigs !== undefined\n ? `n${agg.nSigFigs}${\n agg.nSigFigs === 5 && agg.mantissa && agg.mantissa !== 1\n ? `m${agg.mantissa}`\n : \"\"\n }`\n : \"raw\";\n return [\n \"perps\",\n \"orderBook\",\n params.symbol,\n String(params.maxLevel ?? 20),\n aggKey,\n ];\n}\n\nexport async function fetchOrderBook(\n client: IPerpetualsClient,\n { symbol, maxLevel, aggregation }: UseOrderBookQueryParams,\n): Promise<OrderBook> {\n return await client.getOrderBook(symbol, maxLevel, aggregation);\n}\n\nexport function useOrderBookQuery(\n params: UseOrderBookQueryParams,\n options: Omit<\n UseQueryOptions<OrderBook, Error, OrderBook, string[]>,\n \"queryKey\" | \"queryFn\"\n > = {},\n) {\n const { client } = usePerpetualsClient();\n return useQuery({\n queryKey: orderBookQueryKey(params),\n queryFn: async () => fetchOrderBook(client, params),\n staleTime: 5 * 1000,\n ...options,\n });\n}\n","import { useQuery, UseQueryOptions } from \"@tanstack/react-query\";\nimport type { IPerpetualsClient, Trade } from \"../types\";\nimport { usePerpetualsClient } from \"./usePerpetualsClient\";\n\nexport interface UseRecentTradesQueryParams {\n symbol: string;\n limit?: number;\n}\n\nexport function recentTradesQueryKey(\n params: UseRecentTradesQueryParams,\n): string[] {\n return [\"perps\", \"recentTrades\", params.symbol, String(params.limit ?? 50)];\n}\n\nexport async function fetchRecentTrades(\n client: IPerpetualsClient,\n { symbol, limit }: UseRecentTradesQueryParams,\n): Promise<Trade[]> {\n return await client.getRecentTrades(symbol, limit);\n}\n\nexport function useRecentTradesQuery(\n params: UseRecentTradesQueryParams,\n options: Omit<\n UseQueryOptions<Trade[], Error, Trade[], string[]>,\n \"queryKey\" | \"queryFn\"\n > = {},\n) {\n const { client } = usePerpetualsClient();\n return useQuery({\n queryKey: recentTradesQueryKey(params),\n queryFn: async () => fetchRecentTrades(client, params),\n staleTime: 5 * 1000,\n ...options,\n });\n}\n","import { useQuery, UseQueryOptions } from \"@tanstack/react-query\";\nimport type {\n IPerpetualsClient,\n GetPositionsResult,\n GetPositionsParams,\n} from \"../types\";\nimport { usePerpetualsClient } from \"./usePerpetualsClient\";\n\nexport interface UsePositionsQueryParams extends GetPositionsParams {\n enabled?: boolean;\n}\n\nexport function positionsQueryKey(\n params: Omit<UsePositionsQueryParams, \"enabled\">,\n): string[] {\n return [\"perps\", \"positions\", params.userAddress ?? \"\", params.symbol ?? \"\"];\n}\n\nexport async function fetchPositions(\n client: IPerpetualsClient,\n params: GetPositionsParams,\n): Promise<GetPositionsResult> {\n return await client.getPositions(params);\n}\n\nexport function usePositionsQuery(\n params: UsePositionsQueryParams,\n options: Omit<\n UseQueryOptions<GetPositionsResult, Error, GetPositionsResult, string[]>,\n \"queryKey\" | \"queryFn\"\n > = {},\n) {\n const { client } = usePerpetualsClient();\n const { enabled = true, ...queryParams } = params;\n\n return useQuery({\n queryKey: positionsQueryKey(queryParams),\n queryFn: async () => fetchPositions(client, queryParams),\n enabled: enabled && !!queryParams.userAddress,\n staleTime: 10 * 1000,\n ...options,\n });\n}\n","import { useQuery, UseQueryOptions } from \"@tanstack/react-query\";\nimport type {\n IPerpetualsClient,\n GetOpenOrdersResult,\n GetOpenOrdersParams,\n} from \"../types\";\nimport { usePerpetualsClient } from \"./usePerpetualsClient\";\n\nexport interface UseOrdersQueryParams extends GetOpenOrdersParams {\n enabled?: boolean;\n}\n\nexport function ordersQueryKey(\n params: Omit<UseOrdersQueryParams, \"enabled\">,\n): string[] {\n return [\"perps\", \"orders\", params.userAddress ?? \"\", params.symbol ?? \"\"];\n}\n\nexport async function fetchOrders(\n client: IPerpetualsClient,\n params: GetOpenOrdersParams,\n): Promise<GetOpenOrdersResult> {\n return await client.getOpenOrders(params);\n}\n\nexport function useOrdersQuery(\n params: UseOrdersQueryParams,\n options: Omit<\n UseQueryOptions<GetOpenOrdersResult, Error, GetOpenOrdersResult, string[]>,\n \"queryKey\" | \"queryFn\"\n > = {},\n) {\n const { client } = usePerpetualsClient();\n const { enabled = true, ...queryParams } = params;\n\n return useQuery({\n queryKey: ordersQueryKey(queryParams),\n queryFn: async () => fetchOrders(client, queryParams),\n enabled: enabled && !!queryParams.userAddress,\n staleTime: 5 * 1000,\n ...options,\n });\n}\n","import { useQuery, UseQueryOptions } from \"@tanstack/react-query\";\nimport type {\n IPerpetualsClient,\n GetTradesResult,\n GetTradesParams,\n} from \"../types\";\nimport { usePerpetualsClient } from \"./usePerpetualsClient\";\n\nexport interface UseTradesQueryParams extends GetTradesParams {\n enabled?: boolean;\n}\n\nexport function tradesQueryKey(\n params: Omit<UseTradesQueryParams, \"enabled\">,\n): string[] {\n return [\n \"perps\",\n \"trades\",\n params.userAddress ?? \"\",\n params.symbol ?? \"\",\n String(params.limit ?? 50),\n String(params.startTime ?? \"\"),\n String(params.endTime ?? \"\"),\n ];\n}\n\nexport async function fetchTrades(\n client: IPerpetualsClient,\n params: GetTradesParams,\n): Promise<GetTradesResult> {\n return await client.getTrades(params);\n}\n\nexport function useTradesQuery(\n params: UseTradesQueryParams,\n options: Omit<\n UseQueryOptions<GetTradesResult, Error, GetTradesResult, string[]>,\n \"queryKey\" | \"queryFn\"\n > = {},\n) {\n const { client } = usePerpetualsClient();\n const { enabled = true, ...queryParams } = params;\n\n return useQuery({\n queryKey: tradesQueryKey(queryParams),\n queryFn: async () => fetchTrades(client, queryParams),\n enabled: enabled && !!queryParams.userAddress,\n staleTime: 30 * 1000,\n ...options,\n });\n}\n","import { useQuery, UseQueryOptions } from \"@tanstack/react-query\";\nimport type {\n ActiveAssetLeverage,\n GetActiveAssetLeverageParams,\n IPerpetualsClient,\n} from \"../types\";\nimport { usePerpetualsClient } from \"./usePerpetualsClient\";\n\nexport interface UseActiveAssetLeverageQueryParams {\n /** User wallet address. Query stays disabled until this is set. */\n userAddress?: string;\n /** Trading pair symbol (e.g. \"BTC-USDC\"). */\n symbol: string;\n /** Optional override; useful for tests. */\n enabled?: boolean;\n}\n\n/**\n * React Query key for the user's per-asset leverage configuration.\n *\n * Accepts an undefined `userAddress` (e.g. before the wallet connects)\n * because consumers often want a stable key shape to feed\n * `invalidateQueries` after the address resolves. The fallback empty\n * string just makes the key deterministic; the query itself stays\n * disabled until both fields are populated.\n */\nexport function activeAssetLeverageQueryKey(params: {\n userAddress?: GetActiveAssetLeverageParams[\"userAddress\"];\n symbol?: GetActiveAssetLeverageParams[\"symbol\"];\n}): string[] {\n return [\n \"perps\",\n \"activeAssetLeverage\",\n params.userAddress ?? \"\",\n params.symbol ?? \"\",\n ];\n}\n\nexport async function fetchActiveAssetLeverage(\n client: IPerpetualsClient,\n params: GetActiveAssetLeverageParams,\n): Promise<ActiveAssetLeverage | null> {\n return await client.getActiveAssetLeverage(params);\n}\n\n/**\n * Read the user's configured leverage for `symbol` from the venue,\n * independent of whether an open position exists. Backed by Hyperliquid's\n * `activeAssetData` info endpoint when the active provider is\n * Hyperliquid; the LiberFi adapter currently returns `null` (the form\n * will fall back to its default).\n *\n * The returned data updates every 30s while the form is mounted, and\n * the consumer is expected to invalidate the query after a successful\n * `updateLeverage` so the UI reflects the new value immediately.\n */\nexport function useActiveAssetLeverageQuery(\n params: UseActiveAssetLeverageQueryParams,\n options: Omit<\n UseQueryOptions<\n ActiveAssetLeverage | null,\n Error,\n ActiveAssetLeverage | null,\n string[]\n >,\n \"queryKey\" | \"queryFn\"\n > = {},\n) {\n const { client } = usePerpetualsClient();\n const { enabled = true, userAddress, symbol } = params;\n\n return useQuery({\n queryKey: activeAssetLeverageQueryKey({ userAddress, symbol }),\n queryFn: async () => {\n // The `enabled` guard below ensures `userAddress` is defined by\n // the time React Query runs the fetcher, but TypeScript can't\n // narrow that on its own — surface it as a runtime invariant.\n if (!userAddress) {\n throw new Error(\"useActiveAssetLeverageQuery: userAddress is required\");\n }\n return fetchActiveAssetLeverage(client, { userAddress, symbol });\n },\n enabled: enabled && !!userAddress && !!symbol,\n staleTime: 30 * 1000,\n ...options,\n });\n}\n","import { useQuery, UseQueryOptions } from \"@tanstack/react-query\";\nimport type {\n AssetMeta,\n GetAssetMetaParams,\n IPerpetualsClient,\n} from \"../types\";\nimport { usePerpetualsClient } from \"./usePerpetualsClient\";\n\nexport interface UseAssetMetaQueryParams {\n /** Trading pair symbol (e.g. \"BTC-USDC\"). */\n symbol?: string;\n /** Optional override; useful for tests. */\n enabled?: boolean;\n}\n\n/**\n * React Query key for the per-asset metadata query.\n *\n * Tolerates an undefined `symbol` so consumers can build a stable key\n * shape before the symbol resolves; the query itself stays disabled\n * until both `enabled` and `symbol` are truthy.\n */\nexport function assetMetaQueryKey(params: {\n symbol?: GetAssetMetaParams[\"symbol\"];\n}): string[] {\n return [\"perps\", \"assetMeta\", params.symbol ?? \"\"];\n}\n\nexport async function fetchAssetMeta(\n client: IPerpetualsClient,\n params: GetAssetMetaParams,\n): Promise<AssetMeta | null> {\n return await client.getAssetMeta(params);\n}\n\n/**\n * Read the venue's static metadata (`szDecimals`, `maxLeverage`) for\n * `symbol`. Backed by Hyperliquid's `meta` info endpoint when the\n * active provider is Hyperliquid; the LiberFi adapter currently\n * returns `null` (the form falls back to an adaptive precision rule).\n *\n * The data is process-stable for minutes at a time (Hyperliquid only\n * updates the universe on listing additions / leverage cap changes),\n * so we set a generous `staleTime` of 60 seconds. Consumers don't\n * need to invalidate this on user actions — the data is keyed on\n * symbol alone.\n */\nexport function useAssetMetaQuery(\n params: UseAssetMetaQueryParams,\n options: Omit<\n UseQueryOptions<AssetMeta | null, Error, AssetMeta | null, string[]>,\n \"queryKey\" | \"queryFn\"\n > = {},\n) {\n const { client } = usePerpetualsClient();\n const { enabled = true, symbol } = params;\n\n return useQuery({\n queryKey: assetMetaQueryKey({ symbol }),\n queryFn: async () => {\n // The `enabled` guard below ensures `symbol` is defined by the\n // time React Query runs the fetcher, but TypeScript can't\n // narrow that on its own — surface it as a runtime invariant.\n if (!symbol) {\n throw new Error(\"useAssetMetaQuery: symbol is required\");\n }\n return fetchAssetMeta(client, { symbol });\n },\n enabled: enabled && !!symbol,\n staleTime: 60 * 1000,\n ...options,\n });\n}\n","import { useMutation, UseMutationOptions } from \"@tanstack/react-query\";\nimport type {\n IPerpetualsClient,\n PlaceOrderParams,\n PlaceOrderResult,\n} from \"../types\";\nimport { usePerpetualsClient } from \"./usePerpetualsClient\";\n\nexport type UseCreateOrderMutationParams = PlaceOrderParams;\n\nexport async function createOrder(\n client: IPerpetualsClient,\n params: UseCreateOrderMutationParams,\n): Promise<PlaceOrderResult> {\n return await client.placeOrder(params);\n}\n\nexport function useCreateOrderMutation(\n options: Omit<\n UseMutationOptions<PlaceOrderResult, Error, UseCreateOrderMutationParams>,\n \"mutationFn\"\n > = {},\n) {\n const { client } = usePerpetualsClient();\n return useMutation({\n mutationFn: async (params: UseCreateOrderMutationParams) =>\n createOrder(client, params),\n ...options,\n });\n}\n","import { useMutation, UseMutationOptions } from \"@tanstack/react-query\";\nimport type {\n IPerpetualsClient,\n CancelOrderParams,\n CancelOrderResult,\n} from \"../types\";\nimport { usePerpetualsClient } from \"./usePerpetualsClient\";\n\nexport type UseCancelOrderMutationParams = CancelOrderParams;\n\nexport async function cancelOrder(\n client: IPerpetualsClient,\n params: UseCancelOrderMutationParams,\n): Promise<CancelOrderResult> {\n return await client.cancelOrder(params);\n}\n\nexport function useCancelOrderMutation(\n options: Omit<\n UseMutationOptions<CancelOrderResult, Error, UseCancelOrderMutationParams>,\n \"mutationFn\"\n > = {},\n) {\n const { client } = usePerpetualsClient();\n return useMutation({\n mutationFn: async (params: UseCancelOrderMutationParams) =>\n cancelOrder(client, params),\n ...options,\n });\n}\n","import { useEffect, useState, useCallback, useRef } from \"react\";\nimport type {\n MarketData,\n Trade,\n OrderBook,\n OrderBookAggregationOptions,\n} from \"../types\";\nimport { usePerpetualsClient } from \"./usePerpetualsClient\";\n\nexport type MarketDataType = \"ticker\" | \"trades\" | \"orderBook\";\n\nexport interface UseMarketDataSubscriptionParams {\n type: MarketDataType;\n symbol: string;\n enabled?: boolean;\n /**\n * Optional venue aggregation hint (only meaningful when\n * `type === \"orderBook\"`). Changing it tears down and re-creates the\n * subscription so the upstream stream is re-keyed with the new\n * `nSigFigs` / `mantissa`.\n */\n aggregation?: OrderBookAggregationOptions;\n /**\n * If set, coalesce upstream pushes into a single React `setData` call no\n * more than once every `throttleMs` milliseconds. The latest payload\n * always wins; intermediate pushes are dropped. Use this for high-rate\n * streams (e.g. orderBook on active markets) where the human eye can't\n * tell the difference between 30 Hz and 10 Hz but React reconciliation\n * cost scales linearly.\n *\n * Leave undefined to forward every push immediately (default).\n */\n throttleMs?: number;\n}\n\nexport interface UseMarketDataSubscriptionResult<T> {\n data: T | null;\n isConnected: boolean;\n error: Error | null;\n}\n\nexport function useMarketDataSubscription<\n T = MarketDataType extends \"ticker\"\n ? MarketData\n : MarketDataType extends \"trades\"\n ? Trade\n : OrderBook,\n>(params: UseMarketDataSubscriptionParams): UseMarketDataSubscriptionResult<T> {\n const { type, symbol, enabled = true, aggregation, throttleMs } = params;\n const { client } = usePerpetualsClient();\n const [data, setData] = useState<T | null>(null);\n const [isConnected, setIsConnected] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n // Throttling state. We keep the most-recent payload in a ref and flush it\n // through `setData` on a trailing-edge timer. Refs (not state) so updating\n // them never triggers a render.\n const pendingDataRef = useRef<T | null>(null);\n const flushTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const throttleMsRef = useRef<number | undefined>(throttleMs);\n // Keep the ref in sync without re-creating `handleData` every render —\n // changing the throttle interval shouldn't tear down the WS subscription.\n throttleMsRef.current = throttleMs;\n\n const handleData = useCallback((newData: T) => {\n const interval = throttleMsRef.current;\n if (!interval || interval <= 0) {\n setData(newData);\n return;\n }\n // Always remember the latest payload; the trailing flush will pick it up.\n pendingDataRef.current = newData;\n if (flushTimerRef.current === null) {\n flushTimerRef.current = setTimeout(() => {\n flushTimerRef.current = null;\n if (pendingDataRef.current !== null) {\n const next = pendingDataRef.current;\n pendingDataRef.current = null;\n setData(next);\n }\n }, interval);\n }\n }, []);\n\n // Stable string key derived from aggregation. Effect re-runs only when this\n // changes (not on every parent render that produces a fresh object).\n const aggregationKey =\n aggregation?.nSigFigs !== undefined\n ? `n${aggregation.nSigFigs}${\n aggregation.nSigFigs === 5 &&\n aggregation.mantissa &&\n aggregation.mantissa !== 1\n ? `m${aggregation.mantissa}`\n : \"\"\n }`\n : \"\";\n\n useEffect(() => {\n if (!enabled) {\n return;\n }\n\n let subscriptionId: string | null = null;\n let isSubscribed = true;\n\n const connect = async () => {\n try {\n await client.connectWebSocket();\n\n if (!isSubscribed) return;\n\n setIsConnected(true);\n setError(null);\n\n subscriptionId = client.subscribeMarketData(\n type,\n symbol,\n handleData,\n type === \"orderBook\" && aggregation ? { aggregation } : undefined,\n );\n } catch (err) {\n if (isSubscribed) {\n setError(err instanceof Error ? err : new Error(\"Connection failed\"));\n setIsConnected(false);\n }\n }\n };\n\n connect();\n\n return () => {\n isSubscribed = false;\n if (subscriptionId) {\n try {\n client.unsubscribe(subscriptionId);\n } catch (err) {\n console.error(\"Failed to unsubscribe:\", err);\n }\n }\n client.disconnectWebSocket();\n // Drop any pending throttled payload so it can't land after the\n // subscription is torn down.\n if (flushTimerRef.current !== null) {\n clearTimeout(flushTimerRef.current);\n flushTimerRef.current = null;\n }\n pendingDataRef.current = null;\n setIsConnected(false);\n setData(null);\n };\n // aggregationKey is intentionally part of deps so re-subscribing on\n // precision change tears down the old stream and starts a new one with\n // the new nSigFigs/mantissa.\n }, [client, type, symbol, enabled, handleData, aggregationKey]);\n\n return { data, isConnected, error };\n}\n","import { useEffect, useState, useCallback } from \"react\";\nimport type { Kline, KlineInterval } from \"../types\";\nimport { usePerpetualsClient } from \"./usePerpetualsClient\";\n\nexport interface UseCandlesSubscriptionParams {\n symbol: string;\n interval: KlineInterval;\n enabled?: boolean;\n}\n\nexport interface UseCandlesSubscriptionResult {\n data: Kline | null;\n isConnected: boolean;\n error: Error | null;\n}\n\nexport function useCandlesSubscription(\n params: UseCandlesSubscriptionParams,\n): UseCandlesSubscriptionResult {\n const { symbol, interval, enabled = true } = params;\n const { client } = usePerpetualsClient();\n const [data, setData] = useState<Kline | null>(null);\n const [isConnected, setIsConnected] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const handleData = useCallback((newData: Kline) => {\n setData(newData);\n }, []);\n\n useEffect(() => {\n if (!enabled) {\n return;\n }\n\n let subscriptionId: string | null = null;\n let isSubscribed = true;\n\n const connect = async () => {\n try {\n await client.connectWebSocket();\n\n if (!isSubscribed) return;\n\n setIsConnected(true);\n setError(null);\n\n subscriptionId = client.subscribeCandles(symbol, interval, handleData);\n } catch (err) {\n if (isSubscribed) {\n setError(err instanceof Error ? err : new Error(\"Connection failed\"));\n setIsConnected(false);\n }\n }\n };\n\n connect();\n\n return () => {\n isSubscribed = false;\n if (subscriptionId) {\n try {\n client.unsubscribe(subscriptionId);\n } catch (err) {\n console.error(\"Failed to unsubscribe:\", err);\n }\n }\n client.disconnectWebSocket();\n setIsConnected(false);\n setData(null);\n };\n }, [client, symbol, interval, enabled, handleData]);\n\n return { data, isConnected, error };\n}\n","import { useEffect, useState, useCallback } from \"react\";\nimport type { Order, Position, TradeHistory } from \"../types\";\nimport { usePerpetualsClient } from \"./usePerpetualsClient\";\n\nexport type UserDataType = \"orders\" | \"positions\" | \"fills\";\n\nexport interface UseUserDataSubscriptionParams {\n type: UserDataType;\n userAddress: string;\n enabled?: boolean;\n}\n\nexport interface UseUserDataSubscriptionResult<T> {\n data: T | null;\n isConnected: boolean;\n error: Error | null;\n}\n\nexport function useUserDataSubscription<\n T = UserDataType extends \"orders\"\n ? Order\n : UserDataType extends \"positions\"\n ? Position\n : TradeHistory,\n>(params: UseUserDataSubscriptionParams): UseUserDataSubscriptionResult<T> {\n const { type, userAddress, enabled = true } = params;\n const { client } = usePerpetualsClient();\n const [data, setData] = useState<T | null>(null);\n const [isConnected, setIsConnected] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n const handleData = useCallback((newData: T) => {\n setData(newData);\n }, []);\n\n useEffect(() => {\n if (!enabled || !userAddress) {\n return;\n }\n\n let subscriptionId: string | null = null;\n let isSubscribed = true;\n\n const connect = async () => {\n try {\n await client.connectWebSocket();\n\n if (!isSubscribed) return;\n\n setIsConnected(true);\n setError(null);\n\n subscriptionId = client.subscribeUserData(\n type,\n userAddress,\n handleData,\n );\n } catch (err) {\n if (isSubscribed) {\n setError(err instanceof Error ? err : new Error(\"Connection failed\"));\n setIsConnected(false);\n }\n }\n };\n\n connect();\n\n return () => {\n isSubscribed = false;\n if (subscriptionId) {\n try {\n client.unsubscribe(subscriptionId);\n } catch (err) {\n console.error(\"Failed to unsubscribe:\", err);\n }\n }\n client.disconnectWebSocket();\n setIsConnected(false);\n setData(null);\n };\n }, [client, type, userAddress, enabled, handleData]);\n\n return { data, isConnected, error };\n}\n","import { useQuery, UseQueryOptions } from \"@tanstack/react-query\";\nimport type { AccountState } from \"../types\";\n\nexport interface UseAccountStateQueryParams {\n /** User wallet address. The query is disabled when missing. */\n userAddress?: string;\n enabled?: boolean;\n}\n\n/**\n * Stable React Query key for the user's full account state. Shared\n * between {@link useAccountStateQuery} (read) and\n * `useAccountStateSubscription` (write) so a webData2 push and a\n * consumer reader land on the same cache slot.\n */\nexport function accountStateQueryKey(\n params: Pick<UseAccountStateQueryParams, \"userAddress\">,\n): string[] {\n return [\"perps\", \"accountState\", params.userAddress ?? \"\"];\n}\n\n/**\n * Read the user's full account state (positions, open orders, spot\n * balances, available margin) from the React Query cache.\n *\n * This hook does NOT itself fetch data over HTTP — the cache is fed\n * exclusively by `useAccountStateSubscription`, which subscribes to\n * Hyperliquid's `webData2` push channel and writes every snapshot\n * into the same cache slot. Mount the subscription somewhere high in\n * the tree (e.g. an app-shell layout) and this hook becomes a cheap\n * subscriber that re-renders whenever a fresh push lands.\n *\n * Returning `null` means no push has been received yet — wait for the\n * subscription to flush its initial snapshot rather than firing a\n * REST fallback, since `webData2` always primes the stream on\n * connect.\n *\n * @example\n * function WalletButton() {\n * const { address } = useWallet();\n * const { data: account } = useAccountStateQuery({ userAddress: address });\n * return <span>{account?.availableBalance.toFixed(2)} USDC</span>;\n * }\n */\nexport function useAccountStateQuery(\n params: UseAccountStateQueryParams,\n options: Omit<\n UseQueryOptions<AccountState | null, Error, AccountState | null, string[]>,\n \"queryKey\" | \"queryFn\"\n > = {},\n) {\n const { enabled = true, ...rest } = params;\n\n return useQuery({\n queryKey: accountStateQueryKey(rest),\n // No-op queryFn: the WebSocket subscription owns this cache. If a\n // consumer mounts the read hook before the writer, we surface\n // `null` until the first push — that's a tighter contract than\n // racing a REST fallback against the WS handshake.\n queryFn: () => null as AccountState | null,\n enabled: enabled && !!rest.userAddress,\n // The subscription pushes every server tick, so any data already\n // in the cache is by definition fresh. Disable automatic\n // background refetches.\n staleTime: Infinity,\n refetchOnWindowFocus: false,\n refetchOnReconnect: false,\n ...options,\n });\n}\n","\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { useQueryClient } from \"@tanstack/react-query\";\nimport type {\n AccountState,\n GetOpenOrdersResult,\n GetPositionsResult,\n} from \"../types\";\nimport { accountStateQueryKey } from \"./useAccountStateQuery\";\nimport { ordersQueryKey } from \"./useOrdersQuery\";\nimport { usePerpetualsClient } from \"./usePerpetualsClient\";\nimport { positionsQueryKey } from \"./usePositionsQuery\";\n\nexport interface UseAccountStateSubscriptionParams {\n /**\n * Wallet address whose state should be tracked. When undefined or\n * empty the subscription is disabled, so it's safe to mount this\n * hook before authentication completes.\n */\n userAddress?: string;\n /** Disable the subscription entirely (e.g. for SSR / paused tabs). */\n enabled?: boolean;\n}\n\nexport interface UseAccountStateSubscriptionResult {\n /** Latest account state pushed by the venue. */\n data: AccountState | null;\n /** WebSocket connection status (true after the first successful connect). */\n isConnected: boolean;\n /** Last connection / subscription error, or null on success. */\n error: Error | null;\n}\n\n/**\n * Subscribe to the venue's unified user-state push channel\n * (Hyperliquid's `webData2`) and fan the snapshots out across the\n * SDK's React Query caches.\n *\n * Why this hook exists:\n *\n * The naive way to keep `usePositionsQuery`, `useOrdersQuery`, and a\n * spot-balance reader live is to crank their `refetchInterval` down to\n * a few seconds, hammering Hyperliquid's `clearinghouseState` /\n * `spotClearinghouseState` / `openOrders` endpoints. That trades\n * bandwidth for latency and still misses fills between polls. Axiom\n * uses a single `webData2` subscription instead, and so should we.\n *\n * On every push this hook writes the parsed snapshot to:\n * - {@link accountStateQueryKey} — the canonical cache slot read by\n * {@link useAccountStateQuery} (consumed by wallet buttons,\n * deposit modals, etc.).\n * - {@link positionsQueryKey} — keeps `usePositionsQuery` in sync so\n * the place-order form's Available Margin / Current Position\n * reflects the venue without a second REST round-trip.\n * - {@link ordersQueryKey} — keeps `useOrdersQuery` in sync for the\n * open-orders table.\n *\n * Mount this hook **once** at the top of the perpetuals shell (a\n * shared layout, an app-wide provider, …). Children read through\n * existing hooks; nothing else needs to know that the data arrives\n * via WebSocket.\n *\n * Falls back gracefully when the venue does not support a unified\n * channel: if `client.subscribeAccountState` is missing the hook is a\n * no-op, and the existing REST polling continues to drive the caches.\n */\nexport function useAccountStateSubscription(\n params: UseAccountStateSubscriptionParams,\n): UseAccountStateSubscriptionResult {\n const { userAddress, enabled = true } = params;\n const { client } = usePerpetualsClient();\n const queryClient = useQueryClient();\n const [data, setData] = useState<AccountState | null>(null);\n const [isConnected, setIsConnected] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n\n useEffect(() => {\n if (!enabled || !userAddress) {\n return;\n }\n\n // Optional contract: not every venue exposes a unified user\n // channel. If the adapter doesn't implement it, leave the existing\n // REST-driven caches alone instead of crashing on `undefined()`.\n if (typeof client.subscribeAccountState !== \"function\") {\n return;\n }\n\n let subscriptionId: string | null = null;\n let isMounted = true;\n\n const handlePush = (state: AccountState) => {\n if (!isMounted) return;\n setData(state);\n\n // Mirror the snapshot across the per-cache slots that existing\n // consumers (Place Order form, positions table, open orders\n // widget) already read from. `setQueryData` also bumps\n // `dataUpdatedAt`, which marks the cache fresh and prevents the\n // accompanying REST queries from re-firing on focus / mount\n // while the subscription is alive.\n queryClient.setQueryData(accountStateQueryKey({ userAddress }), state);\n\n const positionsResult: GetPositionsResult = {\n positions: state.positions,\n totalEquity: state.totalEquity,\n availableBalance: state.availableBalance,\n totalUnrealizedPnl: state.totalUnrealizedPnl,\n raw: state.raw,\n };\n queryClient.setQueryData(\n positionsQueryKey({ userAddress }),\n positionsResult,\n );\n\n const ordersResult: GetOpenOrdersResult = {\n orders: state.openOrders,\n totalCount: state.openOrders.length,\n raw: state.raw,\n };\n queryClient.setQueryData(ordersQueryKey({ userAddress }), ordersResult);\n };\n\n const connect = async () => {\n try {\n await client.connectWebSocket();\n if (!isMounted) return;\n setIsConnected(true);\n setError(null);\n subscriptionId = client.subscribeAccountState!(userAddress, handlePush);\n } catch (err) {\n if (!isMounted) return;\n setIsConnected(false);\n setError(\n err instanceof Error ? err : new Error(\"WebSocket connect failed\"),\n );\n }\n };\n\n void connect();\n\n return () => {\n isMounted = false;\n if (subscriptionId) {\n try {\n client.unsubscribe(subscriptionId);\n } catch (unsubError) {\n console.error(\n \"[useAccountStateSubscription] unsubscribe failed:\",\n unsubError,\n );\n }\n }\n client.disconnectWebSocket();\n setIsConnected(false);\n };\n }, [client, queryClient, userAddress, enabled]);\n\n return { data, isConnected, error };\n}\n","import { useContext } from \"react\";\nimport type { IPerpDepositClient } from \"../client/liberfi/LiberFiPerpDepositClient\";\nimport { PerpetualsContext } from \"../context/PerpetualsContext\";\n\n/**\n * Hook to access the deposit client from `PerpetualsProvider`.\n *\n * Throws if the provider is missing OR if the host app forgot to pass\n * `depositClient`. The thrown message tells the consumer exactly what\n * to fix — preferring an explicit error to a silent runtime crash deep\n * inside a useQuery hook.\n *\n * @returns The deposit client instance.\n */\nexport function usePerpDepositClient(): IPerpDepositClient {\n const ctx = useContext(PerpetualsContext);\n if (!ctx || !ctx.client) {\n throw new Error(\n \"usePerpDepositClient must be used within a <PerpetualsProvider>.\",\n );\n }\n if (!ctx.depositClient) {\n throw new Error(\n \"usePerpDepositClient: <PerpetualsProvider> was rendered without a `depositClient` prop. \" +\n \"Pass a `LiberFiPerpDepositClient` instance to enable the deposit flow.\",\n );\n }\n return ctx.depositClient;\n}\n\n/**\n * Safe variant — returns `undefined` instead of throwing when\n * `depositClient` is not configured. Use this in hooks that should\n * degrade gracefully (e.g. query hooks that gate on `enabled`) rather\n * than crash when the deposit flow is not wired up.\n */\nexport function usePerpDepositClientMaybe(): IPerpDepositClient | undefined {\n const ctx = useContext(PerpetualsContext);\n return ctx?.depositClient;\n}\n","import { useQuery, UseQueryOptions } from \"@tanstack/react-query\";\nimport type { IPerpDepositClient } from \"../client/liberfi/LiberFiPerpDepositClient\";\nimport type {\n DepositQuoteRequest,\n DepositQuoteResponse,\n} from \"../client/liberfi/deposit-types\";\nimport { usePerpDepositClientMaybe } from \"./usePerpDepositClient\";\n\n/**\n * Stable query key shape for the deposit quote.\n *\n * The amount is part of the key so re-quoting on amount change does not\n * leak across users; the user/recipient pair is included so two users\n * sharing the same browser session don't see each other's quotes in the\n * cache.\n */\nexport function perpDepositQuoteQueryKey(\n req?: DepositQuoteRequest | null,\n): readonly unknown[] {\n return [\"perps\", \"deposit\", \"quote\", req] as const;\n}\n\n/** Pure fetcher — useful for SSR or for invoking outside React. */\nexport async function fetchPerpDepositQuote(\n client: IPerpDepositClient,\n req: DepositQuoteRequest,\n): Promise<DepositQuoteResponse> {\n return client.quote(req);\n}\n\nexport interface UsePerpDepositQuoteOptions extends Omit<\n UseQueryOptions<\n DepositQuoteResponse,\n Error,\n DepositQuoteResponse,\n ReturnType<typeof perpDepositQuoteQueryKey>\n >,\n \"queryKey\" | \"queryFn\" | \"enabled\"\n> {\n /**\n * Override automatic gating. By default the query runs when `req` is\n * fully populated. Pass `enabled: false` to defer firing while the\n * user is still typing the amount.\n */\n enabled?: boolean;\n}\n\n/**\n * Re-quotes on every parameter change, with TanStack Query handling\n * dedupe / refetch / cancellation. Caller is responsible for surfacing\n * `data.expiresAt` to the UI; the FSM will move to `expired` if the\n * user lingers past the deadline.\n *\n * Engineering note: the hook deliberately does NOT auto-refresh on a\n * timer. Re-quoting silently behind the user would erase the “Confirm”\n * button mid-action; the form should re-call `refetch()` on its own\n * cadence (e.g. when `expiresAt` is < 5 s from now).\n */\nexport function usePerpDepositQuote(\n req: DepositQuoteRequest | null | undefined,\n options: UsePerpDepositQuoteOptions = {},\n) {\n const client = usePerpDepositClientMaybe();\n const enabled =\n (options.enabled ?? Boolean(isQuoteReady(req))) && Boolean(client);\n return useQuery({\n queryKey: perpDepositQuoteQueryKey(req ?? null),\n queryFn: async () =>\n fetchPerpDepositQuote(client!, req as DepositQuoteRequest),\n enabled,\n staleTime: 0, // quotes are short-lived; never reuse silently\n gcTime: 30_000,\n refetchOnWindowFocus: false,\n ...options,\n });\n}\n\nfunction isQuoteReady(\n req: DepositQuoteRequest | null | undefined,\n): req is DepositQuoteRequest {\n return Boolean(\n req &&\n req.userSolanaAddress &&\n req.hyperliquidRecipient &&\n req.grossLamports &&\n req.source,\n );\n}\n","import { useCallback, useReducer } from \"react\";\nimport {\n type DepositEvent,\n type DepositState,\n initialDepositState,\n reduceDepositState,\n} from \"../client/liberfi/deposit-state-machine\";\nimport type {\n DepositErrorInfo,\n DepositQuoteResponse,\n DepositSource,\n DepositSubmitRequest,\n} from \"../client/liberfi/deposit-types\";\nimport { LiberFiApiError } from \"../client/liberfi/transport\";\nimport { usePerpDepositClientMaybe } from \"./usePerpDepositClient\";\n\n/**\n * Adapter the host app must provide. Lives on the consumer side so the\n * SDK never has to know how a particular wallet (Phantom / Backpack /\n * Privy / Solflare / …) signs and broadcasts a Solana transaction.\n *\n * Contract:\n * - Decode the `serializedTxBase64` produced by /quote.\n * - Have the user sign it (this is when the wallet UI shows up).\n * - Broadcast it. Return the resulting tx hash.\n * - Throw on user rejection or RPC failure.\n *\n * The SDK keeps things narrow: signature, broadcast, and \"did the wallet\n * succeed\" are the only outputs we care about. Everything else (RPC\n * endpoint, commitment, simulation pre-checks) is an implementation\n * detail the host already owns.\n */\nexport type SignAndBroadcastSolanaTx = (\n serializedTxBase64: string,\n ctx: { isVersioned: boolean; sizeBytes: number },\n) => Promise<string>;\n\n/** Inputs every deposit attempt needs. */\nexport interface ExecuteDepositInput {\n /** The quote previously returned by `/v1/deposits/quote`. */\n quote: DepositQuoteResponse;\n /** User-facing identifiers; must match what was sent to /quote. */\n userSolanaAddress: string;\n hyperliquidRecipient: string;\n /** LiberFi user id (NOT the wallet). Stable for fee attribution. */\n userId: string;\n source: DepositSource;\n /** Optional marketing / referral code. */\n campaign?: string;\n}\n\n/** Hook return shape — exposes the full FSM and a single trigger. */\nexport interface UsePerpDepositExecuteResult {\n state: DepositState;\n /**\n * Kick off the sign → broadcast → submit chain. Returns the eventual\n * `intentId` on success, throws on failure (the FSM will already be\n * in the `failed` phase with a descriptive `error`).\n */\n execute: (input: ExecuteDepositInput) => Promise<string>;\n /** Force back to `idle`. Use when the user dismisses the modal. */\n reset: () => void;\n /** Manually push an event into the FSM (advanced). */\n dispatch: (event: DepositEvent) => void;\n}\n\n/**\n * Orchestrates the full deposit flow:\n *\n * 1. SIGN_START → wallet signs (host adapter)\n * 2. BROADCAST_START → wallet broadcasts (host adapter)\n * 3. SUBMIT_OK → POST /v1/deposits/submit (this hook)\n * 4. STATUS_UPDATE ← `usePerpDepositStatus` polls and forwards\n *\n * Each stage emits a typed event into the same reducer used by the\n * presentational components. The hook itself never renders anything —\n * components consume `state.phase` and react accordingly.\n */\nexport function usePerpDepositExecute(\n signAndBroadcast: SignAndBroadcastSolanaTx,\n): UsePerpDepositExecuteResult {\n const client = usePerpDepositClientMaybe();\n const [state, dispatch] = useReducer(reduceDepositState, initialDepositState);\n\n const reset = useCallback(() => {\n dispatch({ type: \"RESET\" });\n }, []);\n\n const execute = useCallback<UsePerpDepositExecuteResult[\"execute\"]>(\n async (input) => {\n const { quote } = input;\n dispatch({ type: \"SIGN_START\" });\n let solanaTxHash: string;\n try {\n solanaTxHash = await signAndBroadcast(quote.serializedTxBase64, {\n isVersioned: quote.isVersioned,\n sizeBytes: quote.sizeBytes,\n });\n if (!solanaTxHash) {\n throw new Error(\"wallet returned an empty tx hash\");\n }\n } catch (err) {\n const info = toErrorInfo(err, \"WALLET_SIGN_OR_BROADCAST_FAILED\");\n // Distinguish sign vs broadcast: the FSM treats them the same\n // (both transition into `failed`) but we keep the original\n // event name for analytics correlation.\n dispatch({ type: \"SIGN_FAILED\", error: info });\n throw err;\n }\n\n // Optimistic broadcast → submit handshake. The FSM expects the\n // broadcast event before SUBMIT_OK so the phase stays consistent\n // across retries; the wallet adapter has already broadcasted by\n // the time we reach this line, so we fire both events back-to-back.\n dispatch({ type: \"BROADCAST_START\" });\n\n const submitReq: DepositSubmitRequest = {\n userSolanaAddress: input.userSolanaAddress,\n hyperliquidRecipient: input.hyperliquidRecipient,\n solanaTxHash,\n breakdown: quote.breakdown,\n userId: input.userId,\n source: input.source,\n campaign: input.campaign,\n quoteIssuedAt: quote.issuedAt,\n };\n\n if (!client) {\n dispatch({\n type: \"SUBMIT_FAILED\",\n error: {\n code: \"DEPOSIT_CLIENT_NOT_CONFIGURED\",\n message: \"Deposit client is not configured.\",\n recoverable: false,\n },\n });\n throw new Error(\"Deposit client is not configured.\");\n }\n try {\n const out = await client.submit(submitReq);\n dispatch({\n type: \"SUBMIT_OK\",\n intentId: out.intentId,\n solanaTxHash,\n });\n return out.intentId;\n } catch (err) {\n const info = toErrorInfo(err, \"DEPOSIT_SUBMIT_FAILED\");\n dispatch({ type: \"SUBMIT_FAILED\", error: info });\n throw err;\n }\n },\n [client, signAndBroadcast],\n );\n\n return { state, execute, reset, dispatch };\n}\n\nfunction toErrorInfo(err: unknown, fallbackCode: string): DepositErrorInfo {\n if (err instanceof LiberFiApiError) {\n // Try to extract the backend's typed { code, message } from the body.\n const parsed = parseJsonSafe(err.responseBody) as\n | { code?: string; message?: string }\n | undefined;\n return {\n code: parsed?.code ?? fallbackCode,\n message: parsed?.message ?? err.message,\n recoverable: err.statusCode >= 500 || err.statusCode === 408,\n };\n }\n if (err instanceof Error) {\n return { code: fallbackCode, message: err.message, recoverable: true };\n }\n return { code: fallbackCode, message: String(err), recoverable: true };\n}\n\nfunction parseJsonSafe(text: string): unknown {\n if (!text) return undefined;\n try {\n return JSON.parse(text);\n } catch {\n return undefined;\n }\n}\n","import { useQuery, UseQueryOptions } from \"@tanstack/react-query\";\nimport type { IPerpDepositClient } from \"../client/liberfi/LiberFiPerpDepositClient\";\nimport {\n TERMINAL_DEPOSIT_STATUSES,\n type DepositStatusResponse,\n} from \"../client/liberfi/deposit-types\";\nimport { usePerpDepositClientMaybe } from \"./usePerpDepositClient\";\n\nexport function perpDepositStatusQueryKey(\n intentId?: string,\n): readonly unknown[] {\n return [\"perps\", \"deposit\", \"status\", intentId ?? null] as const;\n}\n\nexport async function fetchPerpDepositStatus(\n client: IPerpDepositClient,\n intentId: string,\n): Promise<DepositStatusResponse> {\n return client.status(intentId);\n}\n\nexport interface UsePerpDepositStatusOptions extends Omit<\n UseQueryOptions<\n DepositStatusResponse,\n Error,\n DepositStatusResponse,\n ReturnType<typeof perpDepositStatusQueryKey>\n >,\n \"queryKey\" | \"queryFn\" | \"refetchInterval\" | \"enabled\"\n> {\n enabled?: boolean;\n /**\n * Polling interval in milliseconds while the deposit is non-terminal.\n * Defaults to 3 000 ms — matches the backend's reconciliation cadence\n * with a small safety margin.\n */\n pollIntervalMs?: number;\n}\n\n/**\n * Polls /v1/deposits/{id} until the deposit reaches a terminal status,\n * then stops the timer automatically. The component is responsible for\n * forwarding `data` into the deposit FSM via STATUS_UPDATE events.\n *\n * Engineering principle (single responsibility): this hook owns the\n * \"when to ask the server\" question; the FSM owns the \"what does the\n * answer mean\" question. They communicate through plain typed values.\n */\nexport function usePerpDepositStatus(\n intentId: string | undefined | null,\n options: UsePerpDepositStatusOptions = {},\n) {\n const client = usePerpDepositClientMaybe();\n const enabled = (options.enabled ?? Boolean(intentId)) && Boolean(client);\n // `client!` is safe here because `enabled` is false when `client` is undefined,\n // so the queryFn will never execute without a valid client.\n const pollIntervalMs = options.pollIntervalMs ?? 3_000;\n return useQuery({\n queryKey: perpDepositStatusQueryKey(intentId ?? undefined),\n queryFn: async () => fetchPerpDepositStatus(client!, intentId as string),\n enabled,\n refetchInterval: (query) => {\n const data = query.state.data;\n if (!data) return pollIntervalMs;\n return TERMINAL_DEPOSIT_STATUSES.has(data.status)\n ? false\n : pollIntervalMs;\n },\n refetchOnWindowFocus: false,\n staleTime: 0,\n ...options,\n });\n}\n","/**\n * Pure state machine for the Hyperliquid initialisation flow.\n *\n * Driven by `useReducer` — kept as a separate module so the transition\n * logic is unit-testable without React. The states cover the full\n * lifecycle:\n *\n * idle\n * → loading (caller pressed \"init\", reading current state)\n * → ready (we know which steps remain)\n * → executing (one step is in flight)\n * → done | error\n *\n * `error` is recoverable — `RETRY_STEP` returns the FSM to `executing`.\n * `RESET` always rewinds to `idle` so the caller can re-check status.\n */\nimport type {\n ApproveBuilderFeeParams,\n HyperliquidAccountState,\n SetReferrerParams,\n UpdateLeverageParams,\n} from \"../../client/hyperliquid/HyperliquidSetupAdapter\";\n\n/** Identifier for each setup step — drives the UI checklist. */\nexport type SetupStepId =\n | \"approveBuilderFee\"\n | \"setReferrer\"\n | \"updateLeverage\";\n\n/**\n * A single step in the setup checklist. `params` carry exactly the\n * information the adapter needs to perform the action — the FSM never\n * inspects them; it only routes them to the adapter.\n */\nexport type SetupStep =\n | { id: \"approveBuilderFee\"; params: ApproveBuilderFeeParams }\n | { id: \"setReferrer\"; params: SetReferrerParams }\n | { id: \"updateLeverage\"; params: UpdateLeverageParams };\n\n/** Per-step status tracked across the checklist. */\nexport type StepStatus =\n | \"pending\" // not yet attempted in this session\n | \"skipped\" // already done on-chain — no action needed\n | \"running\"\n | \"done\"\n | \"error\";\n\nexport interface StepRecord {\n step: SetupStep;\n status: StepStatus;\n /** Last error message captured for the step. */\n error?: string;\n /** Optional tx hash returned by the adapter. */\n txHash?: string;\n}\n\nexport type SetupPhase =\n | \"idle\"\n | \"loading\" // refreshing account state\n | \"ready\" // checklist computed, awaiting user action\n | \"executing\"\n | \"done\"\n | \"error\";\n\nexport interface SetupState {\n phase: SetupPhase;\n /** Snapshot of the on-chain state captured during `loading`. */\n accountState?: HyperliquidAccountState;\n /** All steps requested by the caller, in order. */\n steps: StepRecord[];\n /** Index of the step currently executing (only valid in `executing`). */\n currentIndex?: number;\n /** Top-level error — typically from `getAccountState`. */\n error?: string;\n}\n\nexport type SetupAction =\n | { type: \"START_LOADING\" }\n | {\n type: \"LOAD_SUCCESS\";\n accountState: HyperliquidAccountState;\n steps: StepRecord[];\n }\n | { type: \"LOAD_ERROR\"; error: string }\n | { type: \"RUN_STEP\"; index: number }\n | {\n type: \"STEP_SUCCESS\";\n index: number;\n txHash?: string;\n accountState?: HyperliquidAccountState;\n }\n | { type: \"STEP_ERROR\"; index: number; error: string }\n | { type: \"RESET\" };\n\nexport const initialSetupState: SetupState = {\n phase: \"idle\",\n steps: [],\n};\n\n/**\n * Determine the initial status of a step given the current on-chain\n * state. `done` (sometimes called `skipped` to the user) means the\n * action has already happened and we can elide it.\n *\n * Encapsulated as a pure function so the same logic is exercised by\n * both the loader (when `LOAD_SUCCESS` constructs the checklist) and\n * the adapter result handler (when an action reports a partial state\n * update).\n */\nexport function classifyStep(\n step: SetupStep,\n state: HyperliquidAccountState,\n): StepStatus {\n switch (step.id) {\n case \"approveBuilderFee\": {\n const current = state.builderApproval;\n if (\n current &&\n sameAddress(current.builder, step.params.builder) &&\n current.maxFeeRate >= step.params.maxFeeRate\n ) {\n return \"skipped\";\n }\n return \"pending\";\n }\n case \"setReferrer\": {\n // Referrer is a one-shot — any non-null value means done. We do\n // not try to \"fix\" a different referrer because Hyperliquid\n // rejects rebinding.\n return state.referrer ? \"skipped\" : \"pending\";\n }\n case \"updateLeverage\": {\n const current = state.leverage[step.params.asset];\n if (current === step.params.leverage) {\n return \"skipped\";\n }\n return \"pending\";\n }\n }\n}\n\nexport function reduceSetupState(\n state: SetupState,\n action: SetupAction,\n): SetupState {\n switch (action.type) {\n case \"START_LOADING\":\n return {\n phase: \"loading\",\n steps: state.steps,\n accountState: state.accountState,\n };\n case \"LOAD_SUCCESS\": {\n const allDone = action.steps.every(\n (s) => s.status === \"skipped\" || s.status === \"done\",\n );\n return {\n phase: allDone ? \"done\" : \"ready\",\n accountState: action.accountState,\n steps: action.steps,\n };\n }\n case \"LOAD_ERROR\":\n return {\n phase: \"error\",\n steps: state.steps,\n error: action.error,\n };\n case \"RUN_STEP\": {\n const next = state.steps.map((rec, i) =>\n i === action.index\n ? { ...rec, status: \"running\" as StepStatus, error: undefined }\n : rec,\n );\n return {\n phase: \"executing\",\n steps: next,\n accountState: state.accountState,\n currentIndex: action.index,\n };\n }\n case \"STEP_SUCCESS\": {\n const next = state.steps.map((rec, i) =>\n i === action.index\n ? {\n ...rec,\n status: \"done\" as StepStatus,\n txHash: action.txHash,\n error: undefined,\n }\n : rec,\n );\n const mergedAccount: HyperliquidAccountState | undefined =\n action.accountState && state.accountState\n ? mergeAccountState(state.accountState, action.accountState)\n : ((action.accountState as HyperliquidAccountState | undefined) ??\n state.accountState);\n const allDone = next.every(\n (s) => s.status === \"skipped\" || s.status === \"done\",\n );\n return {\n phase: allDone ? \"done\" : \"ready\",\n steps: next,\n accountState: mergedAccount,\n currentIndex: undefined,\n };\n }\n case \"STEP_ERROR\": {\n const next = state.steps.map((rec, i) =>\n i === action.index\n ? { ...rec, status: \"error\" as StepStatus, error: action.error }\n : rec,\n );\n return {\n phase: \"ready\",\n steps: next,\n accountState: state.accountState,\n currentIndex: undefined,\n };\n }\n case \"RESET\":\n return initialSetupState;\n }\n}\n\n/**\n * Find the next step that still needs to run. Returns `null` when the\n * checklist is complete — the caller should treat the FSM as `done`.\n */\nexport function nextRunnableStep(state: SetupState): number | null {\n for (let i = 0; i < state.steps.length; i++) {\n const status = state.steps[i].status;\n if (status === \"pending\" || status === \"error\") return i;\n }\n return null;\n}\n\nfunction sameAddress(a: string, b: string): boolean {\n return a.toLowerCase() === b.toLowerCase();\n}\n\nfunction mergeAccountState(\n base: HyperliquidAccountState,\n patch: Partial<HyperliquidAccountState>,\n): HyperliquidAccountState {\n return {\n builderApproval:\n patch.builderApproval !== undefined\n ? patch.builderApproval\n : base.builderApproval,\n referrer: patch.referrer !== undefined ? patch.referrer : base.referrer,\n leverage: { ...base.leverage, ...(patch.leverage ?? {}) },\n };\n}\n","import { useCallback, useEffect, useReducer, useRef } from \"react\";\nimport type {\n HyperliquidAccountState,\n IHyperliquidSetupAdapter,\n HyperliquidSetupActionResult,\n} from \"../../client/hyperliquid/HyperliquidSetupAdapter\";\nimport {\n classifyStep,\n initialSetupState,\n nextRunnableStep,\n reduceSetupState,\n type SetupState,\n type SetupStep,\n type StepRecord,\n} from \"./setup-state-machine\";\n\n/**\n * Configuration for the Hyperliquid setup orchestrator.\n *\n * The hook is intentionally adapter-agnostic — it does not import any\n * Hyperliquid signing code. The consumer wires in an adapter (typically\n * built around their wallet integration) plus the list of steps they\n * want to run.\n */\nexport interface UseHyperliquidSetupOptions {\n /** Adapter that knows how to read state and submit signed actions. */\n adapter: IHyperliquidSetupAdapter;\n /** EVM address of the user (required to read account state). */\n userAddress: string | undefined;\n /**\n * The steps the consumer wants the user to complete. Order is\n * preserved in the UI, and the orchestrator advances strictly in\n * sequence so failures don't strand the user mid-checklist.\n */\n steps: SetupStep[];\n /**\n * If true, the hook performs an initial state read on mount /\n * adapter change. Defaults to `true`.\n */\n autoLoad?: boolean;\n /** Optional callback invoked once every step is `done` or `skipped`. */\n onComplete?: (state: SetupState) => void;\n /** Optional callback for diagnostic logging. */\n onError?: (err: Error, context: { stepId?: SetupStep[\"id\"] }) => void;\n}\n\nexport interface UseHyperliquidSetupResult {\n state: SetupState;\n /** Re-fetch the on-chain state. Idempotent — safe to call repeatedly. */\n reload: () => Promise<void>;\n /** Run the next pending / error step. No-op when the checklist is done. */\n runNext: () => Promise<void>;\n /** Run a specific step by index — used by per-row \"Retry\" buttons. */\n runStep: (index: number) => Promise<void>;\n /** Reset the FSM to `idle` (e.g. when the user closes the wizard). */\n reset: () => void;\n}\n\n/**\n * Orchestrates the Hyperliquid first-run setup checklist.\n *\n * Responsibilities:\n * - Read the user's account state via the adapter.\n * - Classify each requested step against that state, marking ones\n * already done as `skipped`.\n * - Advance through the remaining steps, calling the appropriate\n * adapter method and merging the returned partial state back.\n * - Surface errors per-step so the UI can show a precise retry CTA.\n *\n * Out of scope:\n * - Signing — adapter does it.\n * - Persistence — Hyperliquid is the source of truth; we re-read on\n * reload instead of caching across sessions.\n */\nexport function useHyperliquidSetup(\n opts: UseHyperliquidSetupOptions,\n): UseHyperliquidSetupResult {\n const {\n adapter,\n userAddress,\n steps,\n autoLoad = true,\n onComplete,\n onError,\n } = opts;\n const [state, dispatch] = useReducer(reduceSetupState, initialSetupState);\n\n // Refs for stable closures inside async work.\n const adapterRef = useRef(adapter);\n const stepsRef = useRef(steps);\n const onCompleteRef = useRef(onComplete);\n const onErrorRef = useRef(onError);\n adapterRef.current = adapter;\n stepsRef.current = steps;\n onCompleteRef.current = onComplete;\n onErrorRef.current = onError;\n\n const reload = useCallback(async () => {\n if (!userAddress) return;\n dispatch({ type: \"START_LOADING\" });\n try {\n const accountState =\n await adapterRef.current.getAccountState(userAddress);\n const records: StepRecord[] = stepsRef.current.map((step) => ({\n step,\n status: classifyStep(step, accountState),\n }));\n dispatch({ type: \"LOAD_SUCCESS\", accountState, steps: records });\n } catch (e) {\n const err = toError(e);\n dispatch({ type: \"LOAD_ERROR\", error: err.message });\n onErrorRef.current?.(err, {});\n }\n }, [userAddress]);\n\n // Auto-load on first mount or when the user / adapter changes.\n useEffect(() => {\n if (autoLoad && userAddress) {\n void reload();\n }\n }, [autoLoad, userAddress, reload]);\n\n const runStep = useCallback(\n async (index: number) => {\n const record = state.steps[index];\n if (!record) return;\n dispatch({ type: \"RUN_STEP\", index });\n try {\n const result = await invokeAdapter(adapterRef.current, record.step);\n dispatch({\n type: \"STEP_SUCCESS\",\n index,\n txHash: result.txHash,\n accountState: result.state as HyperliquidAccountState | undefined,\n });\n } catch (e) {\n const err = toError(e);\n dispatch({ type: \"STEP_ERROR\", index, error: err.message });\n onErrorRef.current?.(err, { stepId: record.step.id });\n }\n },\n [state.steps],\n );\n\n const runNext = useCallback(async () => {\n const idx = nextRunnableStep(state);\n if (idx == null) return;\n await runStep(idx);\n }, [state, runStep]);\n\n const reset = useCallback(() => dispatch({ type: \"RESET\" }), []);\n\n // Fire `onComplete` exactly once when we transition into `done`.\n const completedRef = useRef(false);\n useEffect(() => {\n if (state.phase === \"done\" && !completedRef.current) {\n completedRef.current = true;\n onCompleteRef.current?.(state);\n } else if (state.phase !== \"done\") {\n completedRef.current = false;\n }\n }, [state]);\n\n return { state, reload, runNext, runStep, reset };\n}\n\nfunction invokeAdapter(\n adapter: IHyperliquidSetupAdapter,\n step: SetupStep,\n): Promise<HyperliquidSetupActionResult> {\n switch (step.id) {\n case \"approveBuilderFee\":\n return adapter.approveBuilderFee(step.params);\n case \"setReferrer\":\n return adapter.setReferrer(step.params);\n case \"updateLeverage\":\n return adapter.updateLeverage(step.params);\n }\n}\n\nfunction toError(e: unknown): Error {\n if (e instanceof Error) return e;\n return new Error(typeof e === \"string\" ? e : \"Unknown error\");\n}\n","export function CoinInfoNotFoundUI() {\n return (\n <div className=\"flex items-center justify-center px-4 py-3 bg-neutral-900 border-b border-neutral-800\">\n <span className=\"text-neutral-400 text-sm\">\n Market data not available\n </span>\n </div>\n );\n}\n","import type { CSSProperties } from \"react\";\n\n/**\n * Shared shimmer primitives for skeleton placeholders inside\n * `@liberfi.io/ui-perpetuals`.\n *\n * The visual language matches `@liberfi.io/ui-predict`'s skeletons\n * (events.skeleton, event-detail-skeleton): a subtle white-tint gradient\n * pulsing horizontally over a dark background, no HeroUI gray boxes.\n *\n * Why a shared util:\n * - DRY — the coin-info, orderbook and trades skeletons all need the same\n * keyframes + base style; previously each duplicated its own.\n * - Single source of truth — bumping the gradient colors or the timing\n * updates every loading state in lock-step.\n * - Single keyframe injection — `<ShimmerStyle />` mounts the\n * `@keyframes liberfi-perp-shimmer` rule once. Multiple instances are\n * harmless: the browser deduplicates same-name same-body keyframe\n * declarations across `<style>` tags.\n *\n * Long-term we may promote this to `@liberfi.io/ui` so other packages\n * (`ui-predict`, `ui-tokens`, ...) can share the same primitives.\n */\n\nconst KEYFRAME_NAME = \"liberfi-perp-shimmer\";\n\nconst SHIMMER_KEYFRAMES_CSS = `\n@keyframes ${KEYFRAME_NAME}{0%{background-position:200% 0}100%{background-position:-200% 0}}\n`;\n\n/**\n * Mount once anywhere inside a skeleton tree to inject the shimmer\n * keyframes. The returned `<style>` is tiny (~80 bytes) and React will\n * dedupe repeated mounts via reconciliation.\n */\nexport function ShimmerStyle() {\n return <style>{SHIMMER_KEYFRAMES_CSS}</style>;\n}\n\n/**\n * Base shimmer style. Spread into a `<div style={...}>` to render a\n * pulsing placeholder rectangle. Set `width` / `height` /\n * `borderRadius` via the consumer's own style override.\n *\n * Composition:\n * - `backgroundColor` provides a visible base layer (~16% white). The\n * perpetuals module's skeletons sit directly on the form's\n * near-black background with no surrounding card to lift them, so a\n * pure-gradient fill (which is what the predict cards rely on)\n * ends up nearly invisible. The base color guarantees the block is\n * readable as \"loading\" regardless of the host's background.\n * - `backgroundImage` carries the highlight sweep. We split it from\n * `backgroundColor` instead of using the `background` shorthand so\n * the color isn't cleared every render.\n *\n * Tweaking these values updates every skeleton in this module\n * (coin-info, orderbook, trades, place-order leverage badge, …) in\n * lock-step.\n */\nexport const shimmer: CSSProperties = {\n backgroundColor: \"rgba(255, 255, 255, 0.16)\",\n backgroundImage:\n \"linear-gradient(90deg, rgba(255,255,255,0) 25%, rgba(255,255,255,0.18) 50%, rgba(255,255,255,0) 75%)\",\n backgroundSize: \"200% 100%\",\n animation: `${KEYFRAME_NAME} 1.8s ease-in-out infinite`,\n borderRadius: 6,\n};\n\n/**\n * Stagger the shimmer animation across cells by giving each one its own\n * `animationDelay`. Produces a wave effect from left-to-right (or top-\n * to-bottom) instead of a simultaneous global pulse, which reads as\n * \"individual cells loading\" rather than \"the whole region is dead\".\n *\n * @param delay milliseconds to offset the animation start.\n */\nexport function shimmerDelay(delay: number): CSSProperties {\n return { ...shimmer, animationDelay: `${delay}ms` };\n}\n","import type { CSSProperties } from \"react\";\nimport { ShimmerStyle, shimmerDelay } from \"../../internal/skeleton\";\n\n/**\n * Skeleton placeholder for {@link CoinInfoUI}.\n *\n * Mirrors the live widget's flex layout so the loading shell occupies\n * exactly the same footprint (no jump on data arrival):\n * `[price + 24h%] [Oracle] [24h Volume] [Open Interest] [Funding / Countdown]`\n *\n * The container is intentionally transparent — coin-info renders inside the\n * perpetuals chart column whose host page provides the background (e.g.\n * `#000000` on the perpetuals page). A separate gray wash here would\n * clash with that.\n *\n * Shimmer styling is shared with the other perpetuals skeletons via\n * {@link ShimmerStyle} / {@link shimmerDelay}; see `../../internal/skeleton`.\n */\nexport function CoinInfoSkeletonsUI() {\n return (\n <>\n <ShimmerStyle />\n <div\n className=\"flex items-center px-4\"\n style={{ minHeight: 64, maxHeight: 64, gap: 24 }}\n >\n {/* Price + 24h change — matches `items-baseline` group in CoinInfoUI. */}\n <div className=\"flex items-baseline\" style={{ gap: 8 }}>\n <div style={cellStyle(0, 84, 23)} />\n <div style={cellStyle(60, 52, 16)} />\n </div>\n\n {/* Stat columns: Oracle Price | 24h Volume | Open Interest | Funding. */}\n <div className=\"flex items-center\" style={{ gap: 24 }}>\n <StatColumn labelWidth={72} valueWidth={64} delay={120} />\n <StatColumn labelWidth={72} valueWidth={48} delay={180} />\n <StatColumn labelWidth={84} valueWidth={56} delay={240} />\n\n {/* Funding / Countdown — wider label and a 2-value row. */}\n <div className=\"flex flex-col\" style={{ gap: 4 }}>\n <div style={cellStyle(300, 132, 16)} />\n <div className=\"flex items-center\" style={{ gap: 8 }}>\n <div style={cellStyle(330, 64, 17)} />\n <div style={cellStyle(360, 64, 17)} />\n </div>\n </div>\n </div>\n </div>\n </>\n );\n}\n\nfunction StatColumn({\n labelWidth,\n valueWidth,\n delay,\n}: {\n labelWidth: number;\n valueWidth: number;\n delay: number;\n}) {\n return (\n <div className=\"flex flex-col\" style={{ gap: 4 }}>\n <div style={cellStyle(delay, labelWidth, 16)} />\n <div style={cellStyle(delay + 30, valueWidth, 17)} />\n </div>\n );\n}\n\nfunction cellStyle(\n delay: number,\n width: number,\n height: number,\n): CSSProperties {\n return { ...shimmerDelay(delay), width, height };\n}\n","import { useEffect, useState } from \"react\";\nimport { useMarketDataSubscription } from \"../../hooks/useMarketDataSubscription\";\nimport { useMarketQuery } from \"../../hooks/useMarketQuery\";\nimport type { MarketData } from \"../../types\";\n\nexport type UseCoinInfoReturnType = {\n marketData?: MarketData;\n isLoading: boolean;\n fundingCountdown: number;\n};\n\nexport function useCoinInfo(symbol: string): UseCoinInfoReturnType {\n const [marketData, setMarketData] = useState<MarketData | undefined>();\n const [fundingCountdown, setFundingCountdown] = useState<number>(0);\n\n const { data: initialData, isPending } = useMarketQuery({ symbol });\n\n const { data: realtimeData, isConnected } =\n useMarketDataSubscription<MarketData>({\n type: \"ticker\",\n symbol,\n enabled: !!initialData,\n });\n\n useEffect(() => {\n if (!initialData) return;\n setMarketData(initialData);\n }, [initialData]);\n\n useEffect(() => {\n if (!realtimeData) return;\n\n const normalized = normalizeRealtimeTickerPayload(realtimeData, symbol);\n if (!normalized) return;\n\n setMarketData((previous) =>\n buildMarketData(previous ?? initialData ?? undefined, normalized, symbol),\n );\n }, [realtimeData, initialData, symbol]);\n\n useEffect(() => {\n // Hyperliquid funding settles **hourly** at the top of every UTC hour\n // (HH:00:00). The countdown below renders the time remaining until\n // the next settlement boundary.\n //\n // The previous implementation used an 8-hour interval, which mirrors\n // perp venues like Binance / Bybit but does not apply to Hyperliquid:\n // Axiom's reference UI shows `00:38:11` for the same market when our\n // 8-hour countdown showed `05:39:49`, off by ~8x. We intentionally\n // hard-code the cadence here because Hyperliquid is currently the\n // only backend; if/when other venues are wired in, this should\n // become a venue-specific config (e.g. `client.fundingIntervalMs`).\n const calculateCountdown = () => {\n const now = Date.now();\n const oneHour = 60 * 60 * 1000;\n const remainder = now % oneHour;\n const timeUntilNext = oneHour - remainder;\n return Math.floor(timeUntilNext / 1000);\n };\n\n setFundingCountdown(calculateCountdown());\n\n const interval = setInterval(() => {\n setFundingCountdown(calculateCountdown());\n }, 1000);\n\n return () => clearInterval(interval);\n }, []);\n\n return {\n marketData,\n isLoading: isPending,\n fundingCountdown,\n };\n}\n\nfunction normalizeRealtimeTickerPayload(\n payload: unknown,\n symbol: string,\n): Partial<MarketData> | null {\n if (Array.isArray(payload)) {\n const matched = payload.find((item) => {\n if (!item || typeof item !== \"object\") return false;\n return (item as { symbol?: string }).symbol === symbol;\n });\n return matched && typeof matched === \"object\"\n ? (matched as Partial<MarketData>)\n : null;\n }\n\n if (payload && typeof payload === \"object\") {\n return payload as Partial<MarketData>;\n }\n\n return null;\n}\n\nfunction toNumberOr(value: unknown, fallback: number): number {\n if (typeof value === \"number\" && Number.isFinite(value)) {\n return value;\n }\n return fallback;\n}\n\nfunction buildMarketData(\n base: MarketData | undefined,\n patch: Partial<MarketData>,\n symbol: string,\n): MarketData {\n return {\n symbol: patch.symbol ?? base?.symbol ?? symbol,\n price: toNumberOr(patch.price, base?.price ?? 0),\n change24h: toNumberOr(patch.change24h, base?.change24h ?? 0),\n volume24h: toNumberOr(patch.volume24h, base?.volume24h ?? 0),\n fundingRate: toNumberOr(patch.fundingRate, base?.fundingRate ?? 0),\n openInterest: toNumberOr(patch.openInterest, base?.openInterest ?? 0),\n markPrice: toNumberOr(patch.markPrice, base?.markPrice ?? 0),\n indexPrice:\n typeof patch.indexPrice === \"number\" && Number.isFinite(patch.indexPrice)\n ? patch.indexPrice\n : base?.indexPrice,\n high24h:\n typeof patch.high24h === \"number\" && Number.isFinite(patch.high24h)\n ? patch.high24h\n : base?.high24h,\n low24h:\n typeof patch.low24h === \"number\" && Number.isFinite(patch.low24h)\n ? patch.low24h\n : base?.low24h,\n };\n}\n","import { cn } from \"@liberfi.io/ui\";\nimport type { MarketData } from \"../../types\";\n\nexport type CoinInfoUIProps = {\n marketData: MarketData;\n fundingCountdown: number;\n};\n\nfunction formatCountdown(seconds: number): string {\n const hours = Math.floor(seconds / 3600);\n const minutes = Math.floor((seconds % 3600) / 60);\n const secs = seconds % 60;\n return `${String(hours).padStart(2, \"0\")}:${String(minutes).padStart(2, \"0\")}:${String(secs).padStart(2, \"0\")}`;\n}\n\nfunction formatNumber(num: number | undefined, decimals: number = 2): string {\n if (typeof num !== \"number\" || !Number.isFinite(num)) {\n return \"-\";\n }\n if (num >= 1e9) {\n return `$${(num / 1e9).toFixed(decimals)}B`;\n }\n if (num >= 1e6) {\n return `$${(num / 1e6).toFixed(decimals)}M`;\n }\n if (num >= 1e3) {\n return `$${(num / 1e3).toFixed(decimals)}K`;\n }\n return `$${num.toFixed(decimals)}`;\n}\n\nfunction formatPrice(price: number | undefined): string {\n if (typeof price !== \"number\" || !Number.isFinite(price)) {\n return \"-\";\n }\n if (price >= 1000) {\n return price.toLocaleString(\"en-US\", {\n minimumFractionDigits: 0,\n maximumFractionDigits: 0,\n });\n }\n if (price >= 1) {\n return price.toLocaleString(\"en-US\", {\n minimumFractionDigits: 2,\n maximumFractionDigits: 4,\n });\n }\n return price.toFixed(6);\n}\n\nexport function CoinInfoUI({ marketData, fundingCountdown }: CoinInfoUIProps) {\n const {\n symbol,\n price,\n change24h,\n indexPrice,\n volume24h,\n openInterest,\n fundingRate,\n } = marketData;\n\n const safeChange24h =\n typeof change24h === \"number\" && Number.isFinite(change24h) ? change24h : 0;\n const safeFundingRate =\n typeof fundingRate === \"number\" && Number.isFinite(fundingRate)\n ? fundingRate\n : 0;\n const isPositiveChange = safeChange24h >= 0;\n const changePercent = safeChange24h.toFixed(2);\n\n return (\n <div\n className=\"flex items-center px-4\"\n style={{ minHeight: 64, maxHeight: 64, gap: 24 }}\n >\n <div className=\"flex items-baseline\" style={{ gap: 8 }}>\n <span\n style={{\n fontSize: 18,\n fontWeight: 500,\n lineHeight: \"23px\",\n letterSpacing: \"-0.36px\",\n color: \"#ffffff\",\n }}\n >\n {formatPrice(price)}\n </span>\n <span\n style={{\n fontSize: 12,\n fontWeight: 400,\n lineHeight: \"16px\",\n color: isPositiveChange ? \"#C7FF2E\" : \"#F76816\",\n }}\n >\n {isPositiveChange ? \"+\" : \"\"}\n {changePercent}%\n </span>\n </div>\n\n <div className=\"flex items-center\" style={{ gap: 24 }}>\n <div className=\"flex flex-col\">\n <span\n style={{\n fontSize: 12,\n color: \"#b5b5b5\",\n lineHeight: \"16px\",\n letterSpacing: \"-0.12px\",\n }}\n >\n Oracle Price\n </span>\n <span\n style={{\n fontSize: 13,\n fontWeight: 400,\n lineHeight: \"17px\",\n color: \"#ffffff\",\n }}\n >\n {indexPrice ? formatPrice(indexPrice) : \"-\"}\n </span>\n </div>\n\n <div className=\"flex flex-col\">\n <span\n style={{\n fontSize: 12,\n color: \"#b5b5b5\",\n lineHeight: \"16px\",\n letterSpacing: \"-0.12px\",\n }}\n >\n 24h Volume\n </span>\n <span\n style={{\n fontSize: 13,\n fontWeight: 400,\n lineHeight: \"17px\",\n color: \"#ffffff\",\n }}\n >\n {formatNumber(volume24h, 0)}\n </span>\n </div>\n\n <div className=\"flex flex-col\">\n <span\n style={{\n fontSize: 12,\n color: \"#b5b5b5\",\n lineHeight: \"16px\",\n letterSpacing: \"-0.12px\",\n }}\n >\n Open Interest\n </span>\n <span\n style={{\n fontSize: 13,\n fontWeight: 400,\n lineHeight: \"17px\",\n color: \"#ffffff\",\n }}\n >\n {formatNumber(openInterest * (marketData.markPrice || price))}\n </span>\n </div>\n\n <div className=\"flex flex-col\">\n <span\n style={{\n fontSize: 12,\n color: \"#b5b5b5\",\n lineHeight: \"16px\",\n letterSpacing: \"-0.12px\",\n }}\n >\n Funding / Countdown\n </span>\n <div className=\"flex items-center\" style={{ gap: 8 }}>\n <span\n style={{\n fontSize: 13,\n lineHeight: \"17px\",\n color: safeFundingRate >= 0 ? \"#C7FF2E\" : \"#F76816\",\n }}\n >\n {(safeFundingRate * 100).toFixed(5)}%\n </span>\n <span\n style={{\n fontSize: 13,\n lineHeight: \"17px\",\n color: \"#ffffff\",\n }}\n >\n {formatCountdown(fundingCountdown)}\n </span>\n </div>\n </div>\n </div>\n </div>\n );\n}\n","import { CoinInfoNotFoundUI } from \"./coin-info-notfound.ui\";\nimport { CoinInfoSkeletonsUI } from \"./coin-info-skeletons.ui\";\nimport { useCoinInfo } from \"./coin-info.script\";\nimport { CoinInfoUI } from \"./coin-info.ui\";\n\nexport type CoinInfoWidgetProps = {\n symbol: string;\n};\n\nexport function CoinInfoWidget({ symbol }: CoinInfoWidgetProps) {\n const { marketData, isLoading, fundingCountdown } = useCoinInfo(symbol);\n\n if (isLoading) {\n return <CoinInfoSkeletonsUI />;\n }\n\n if (!marketData) {\n return <CoinInfoNotFoundUI />;\n }\n\n return (\n <CoinInfoUI marketData={marketData} fundingCountdown={fundingCountdown} />\n );\n}\n","import { useEffect, useMemo, useState } from \"react\";\nimport { useCoinsQuery } from \"../../hooks/useCoinsQuery\";\nimport { useMarketsQuery } from \"../../hooks/useMarketsQuery\";\nimport type { MarketData } from \"../../types\";\n\nexport type UseSearchCoinsScriptParams = {\n onSelectCoin?: (symbol: string) => void;\n};\n\nexport type UseSearchCoinsScriptResult = {\n coins: MarketData[];\n isLoading: boolean;\n searchQuery: string;\n setSearchQuery: (query: string) => void;\n filteredCoins: MarketData[];\n handleSelectCoin: (symbol: string) => void;\n};\n\nexport function useSearchCoinsScript({\n onSelectCoin,\n}: UseSearchCoinsScriptParams = {}): UseSearchCoinsScriptResult {\n const [searchQuery, setSearchQuery] = useState<string>(\"\");\n const [coins, setCoins] = useState<MarketData[]>([]);\n\n const { data: coinSymbols, isPending: isLoadingSymbols } = useCoinsQuery();\n\n const { data: marketsData, isPending: isLoadingMarkets } = useMarketsQuery(\n { symbols: coinSymbols },\n { enabled: !!coinSymbols && coinSymbols.length > 0 },\n );\n\n useEffect(() => {\n if (marketsData) {\n setCoins(marketsData);\n }\n }, [marketsData]);\n\n const filteredCoins = useMemo(() => {\n if (!searchQuery.trim()) {\n return coins;\n }\n\n const query = searchQuery.toLowerCase().trim();\n return coins.filter((coin) => coin.symbol.toLowerCase().includes(query));\n }, [coins, searchQuery]);\n\n const handleSelectCoin = (symbol: string) => {\n onSelectCoin?.(symbol);\n };\n\n return {\n coins,\n isLoading: isLoadingSymbols || isLoadingMarkets,\n searchQuery,\n setSearchQuery,\n filteredCoins,\n handleSelectCoin,\n };\n}\n","import { SearchIcon } from \"@liberfi.io/ui\";\nimport type { MarketData } from \"../../types\";\n\nexport type SearchCoinsUIProps = {\n coins: MarketData[];\n searchQuery: string;\n onSearchChange: (query: string) => void;\n onSelectCoin: (symbol: string) => void;\n isLoading?: boolean;\n};\n\nfunction formatNumber(num: number, decimals: number = 2): string {\n if (num >= 1e9) {\n return `$${(num / 1e9).toFixed(decimals)}B`;\n }\n if (num >= 1e6) {\n return `$${(num / 1e6).toFixed(decimals)}M`;\n }\n if (num >= 1e3) {\n return `$${(num / 1e3).toFixed(decimals)}K`;\n }\n return `$${num.toFixed(decimals)}`;\n}\n\nfunction formatPrice(price: number): string {\n if (price >= 1000) {\n return price.toFixed(2);\n }\n if (price >= 1) {\n return price.toFixed(4);\n }\n return price.toFixed(6);\n}\n\nexport function SearchCoinsUI({\n coins,\n searchQuery,\n onSearchChange,\n onSelectCoin,\n isLoading,\n}: SearchCoinsUIProps) {\n return (\n <div\n className=\"flex flex-col\"\n style={{ backgroundColor: \"#1A1A1A\", flex: \"1 1 0\", minHeight: 0 }}\n >\n <div style={{ padding: \"16px 16px 12px\" }}>\n <div\n className=\"flex items-center\"\n style={{\n height: 32,\n border: \"1px solid #2a2a2a\",\n borderRadius: 4,\n padding: \"0 6px 0 12px\",\n gap: 8,\n }}\n >\n <SearchIcon\n className=\"flex-shrink-0\"\n style={{ width: 14, height: 14, color: \"#6b6b6b\" }}\n />\n <input\n type=\"text\"\n placeholder=\"Search coins...\"\n value={searchQuery}\n onChange={(e) => onSearchChange(e.target.value)}\n className=\"flex-1 bg-transparent outline-none\"\n style={{ fontSize: 12, color: \"#ffffff\", border: \"none\" }}\n />\n </div>\n </div>\n\n <div className=\"flex-1 overflow-auto\">\n {/* Header */}\n <div\n className=\"flex items-center\"\n style={{\n height: 28,\n padding: \"0 16px\",\n borderBottom: \"1px solid rgba(42,42,42,0.5)\",\n position: \"sticky\",\n top: 0,\n backgroundColor: \"#1A1A1A\",\n zIndex: 1,\n }}\n >\n <span style={{ flex: \"0 0 140px\", fontSize: 12, color: \"#6b6b6b\" }}>\n Token\n </span>\n <span\n style={{\n flex: \"0 0 100px\",\n fontSize: 12,\n color: \"#6b6b6b\",\n textAlign: \"right\",\n }}\n >\n Last Price\n </span>\n <span\n style={{\n flex: \"0 0 120px\",\n fontSize: 12,\n color: \"#6b6b6b\",\n textAlign: \"right\",\n }}\n >\n 24h Change\n </span>\n <span\n style={{\n flex: \"0 0 100px\",\n fontSize: 12,\n color: \"#6b6b6b\",\n textAlign: \"right\",\n }}\n >\n 8h Funding\n </span>\n <span\n style={{\n flex: \"0 0 100px\",\n fontSize: 12,\n color: \"#6b6b6b\",\n textAlign: \"right\",\n }}\n >\n 24h Volume\n </span>\n <span\n style={{\n flex: \"1\",\n fontSize: 12,\n color: \"#6b6b6b\",\n textAlign: \"right\",\n }}\n >\n Open Interest\n </span>\n </div>\n\n {/* Rows */}\n {isLoading ? (\n <div\n className=\"flex items-center justify-center\"\n style={{ height: 100 }}\n >\n <span style={{ fontSize: 12, color: \"#6b6b6b\" }}>Loading...</span>\n </div>\n ) : coins.length === 0 ? (\n <div\n className=\"flex items-center justify-center\"\n style={{ height: 100 }}\n >\n <span style={{ fontSize: 12, color: \"#6b6b6b\" }}>\n {searchQuery ? \"No coins found\" : \"No coins available\"}\n </span>\n </div>\n ) : (\n coins.map((coin) => {\n const isPositiveChange = coin.change24h >= 0;\n const changePercent = coin.change24h.toFixed(2);\n const fundingPercent = (coin.fundingRate * 100).toFixed(4);\n const isPositiveFunding = coin.fundingRate >= 0;\n const tokenName = coin.symbol.split(\"-\")[0];\n\n return (\n <div\n key={coin.symbol}\n className=\"flex items-center cursor-pointer transition-colors\"\n style={{\n height: 36,\n padding: \"0 16px\",\n borderBottom: \"1px solid rgba(42,42,42,0.5)\",\n }}\n onClick={() => onSelectCoin(coin.symbol)}\n onMouseEnter={(e) => {\n (e.currentTarget as HTMLDivElement).style.backgroundColor =\n \"rgba(255,255,255,0.03)\";\n }}\n onMouseLeave={(e) => {\n (e.currentTarget as HTMLDivElement).style.backgroundColor =\n \"transparent\";\n }}\n >\n <div\n className=\"flex items-center\"\n style={{ flex: \"0 0 140px\", gap: 8 }}\n >\n <img\n src={`https://app.hyperliquid.xyz/coins/${tokenName}.svg`}\n alt={tokenName}\n className=\"rounded-full\"\n style={{ width: 20, height: 20 }}\n onError={(e) => {\n const target = e.target as HTMLImageElement;\n target.style.display = \"none\";\n }}\n />\n <span\n style={{ fontSize: 12, fontWeight: 500, color: \"#ffffff\" }}\n >\n {tokenName}\n </span>\n </div>\n <span\n style={{\n flex: \"0 0 100px\",\n fontSize: 12,\n color: \"#ffffff\",\n textAlign: \"right\",\n }}\n >\n {formatPrice(coin.price)}\n </span>\n <span\n style={{\n flex: \"0 0 120px\",\n fontSize: 12,\n fontWeight: 500,\n color: isPositiveChange ? \"#C7FF2E\" : \"#F76816\",\n textAlign: \"right\",\n }}\n >\n {isPositiveChange ? \"+\" : \"\"}\n {changePercent}%\n </span>\n <span\n style={{\n flex: \"0 0 100px\",\n fontSize: 12,\n color: isPositiveFunding ? \"#C7FF2E\" : \"#F76816\",\n textAlign: \"right\",\n }}\n >\n {fundingPercent}%\n </span>\n <span\n style={{\n flex: \"0 0 100px\",\n fontSize: 12,\n color: \"#b5b5b5\",\n textAlign: \"right\",\n }}\n >\n {formatNumber(coin.volume24h)}\n </span>\n <span\n style={{\n flex: \"1\",\n fontSize: 12,\n color: \"#b5b5b5\",\n textAlign: \"right\",\n }}\n >\n {formatNumber(coin.openInterest * coin.price)}\n </span>\n </div>\n );\n })\n )}\n </div>\n </div>\n );\n}\n","import { useSearchCoinsScript } from \"./search-coins.script\";\nimport { SearchCoinsUI } from \"./search-coins.ui\";\n\nexport type SearchCoinsWidgetProps = {\n onSelectCoin?: (symbol: string) => void;\n className?: string;\n};\n\nexport function SearchCoinsWidget({\n onSelectCoin,\n className,\n}: SearchCoinsWidgetProps) {\n const {\n filteredCoins,\n isLoading,\n searchQuery,\n setSearchQuery,\n handleSelectCoin,\n } = useSearchCoinsScript({ onSelectCoin });\n\n return (\n <div\n className={className}\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n flex: \"1 1 0\",\n minHeight: 0,\n overflow: \"hidden\",\n }}\n >\n <SearchCoinsUI\n coins={filteredCoins}\n searchQuery={searchQuery}\n onSearchChange={setSearchQuery}\n onSelectCoin={handleSelectCoin}\n isLoading={isLoading}\n />\n </div>\n );\n}\n","import { useEffect, useMemo, useState } from \"react\";\nimport { useMarketDataSubscription } from \"../../hooks/useMarketDataSubscription\";\nimport { useOrderBookQuery } from \"../../hooks/useOrderBookQuery\";\nimport type {\n OrderBook,\n OrderBookAggregationOptions,\n OrderBookLevel,\n} from \"../../types\";\n\nexport type PriceLevel = OrderBookLevel & {\n total: number;\n percentage: number;\n};\n\nexport type UseOrderBookScriptParams = {\n symbol: string;\n maxLevel?: number;\n /**\n * Initial price-bucket size. Defaults to `1` which matches major perpetual\n * pairs like BTC-USDC. Callers can change it dynamically via the returned\n * `setPrecision`.\n */\n precision?: number;\n};\n\n/**\n * Map a desired bucket step (in quote currency, e.g. USD) to the closest\n * Hyperliquid `l2Book` aggregation params at the given reference price.\n *\n * Hyperliquid only emits 20 levels per side per snapshot. To make those 20\n * levels span a wide enough range (e.g. ±$20k for a $1000 step), we ask the\n * server to pre-aggregate via `nSigFigs` / `mantissa`. This function picks the\n * coarsest server step that is still ≤ the user's chosen step, so any\n * remaining mismatch is corrected by client-side `aggregateByPrecision`\n * (which is idempotent when the steps already match).\n *\n * Examples (BTC, price ≈ $80,740):\n * step $1 → { nSigFigs: 5 } (Hyperliquid step $1)\n * step $2 → { nSigFigs: 5, mantissa: 2 } (Hyperliquid step $2)\n * step $5 → { nSigFigs: 5, mantissa: 5 } (Hyperliquid step $5)\n * step $10 → { nSigFigs: 4 } (Hyperliquid step $10)\n * step $100 → { nSigFigs: 3 } (Hyperliquid step $100)\n * step $1000 → { nSigFigs: 2 } (Hyperliquid step $1000)\n *\n * Examples (ETH, price ≈ $4,000):\n * step $1 → { nSigFigs: 4 } (Hyperliquid step $1)\n * step $2 → { nSigFigs: 4 } + client agg (server $1, client → $2)\n * step $10 → { nSigFigs: 3 } (Hyperliquid step $10)\n *\n * @param price Reference price (mid / mark) used to compute the magnitude.\n * @param step Desired bucket size in the same quote currency as `price`.\n * @returns Aggregation hint, or empty object when inputs are invalid.\n */\nexport function aggregationFromStep(\n price: number,\n step: number,\n): OrderBookAggregationOptions {\n if (\n !Number.isFinite(price) ||\n !Number.isFinite(step) ||\n price <= 0 ||\n step <= 0\n ) {\n return {};\n }\n\n // 10^k is the place value of `price`'s most-significant digit.\n // E.g. price=80740 → log10≈4.907 → k=4 (price sits in the 10^4 = \"tens of\n // thousands\" decade).\n const k = Math.floor(Math.log10(price));\n\n // Step produced by Hyperliquid for nSigFigs=n at this price magnitude:\n // server step = mantissa * 10^(k - n + 1) (mantissa defaults to 1)\n // We enumerate the supported (n, mantissa) tuples and pick the one whose\n // server step is the largest value ≤ user step.\n const candidates: Array<{\n nSigFigs: 2 | 3 | 4 | 5;\n mantissa?: 1 | 2 | 5;\n step: number;\n }> = [\n { nSigFigs: 2, step: Math.pow(10, k - 1) },\n { nSigFigs: 3, step: Math.pow(10, k - 2) },\n { nSigFigs: 4, step: Math.pow(10, k - 3) },\n { nSigFigs: 5, mantissa: 5, step: 5 * Math.pow(10, k - 4) },\n { nSigFigs: 5, mantissa: 2, step: 2 * Math.pow(10, k - 4) },\n { nSigFigs: 5, step: Math.pow(10, k - 4) },\n ];\n\n // Tolerance to absorb floating-point error from log10 / pow.\n const eps = 1e-9;\n\n let best: (typeof candidates)[number] | null = null;\n for (const c of candidates) {\n if (c.step <= step + eps && (!best || c.step > best.step)) {\n best = c;\n }\n }\n\n // If even nSigFigs=5 (the finest server bucket) is still coarser than the\n // user's requested step, fall back to it — we cannot ask Hyperliquid for a\n // finer grid, but the client will still aggregate further if needed.\n if (!best) {\n return { nSigFigs: 5 };\n }\n\n if (best.mantissa && best.mantissa !== 1) {\n return { nSigFigs: best.nSigFigs, mantissa: best.mantissa };\n }\n return { nSigFigs: best.nSigFigs };\n}\n\nexport type UseOrderBookScriptResult = {\n bids: PriceLevel[];\n asks: PriceLevel[];\n /** Raw `bestAsk - bestBid` after aggregation. */\n spread: number;\n /** `spread / bestBid * 100`. */\n spreadPercentage: number;\n isLoading: boolean;\n precision: number;\n setPrecision: (precision: number) => void;\n};\n\n/**\n * Aggregate raw order-book levels into discrete price buckets of size\n * `precision`.\n *\n * To keep the spread visually consistent with the chosen aggregation step we\n * round in opposite directions for the two sides:\n *\n * - ask (sell) levels round UP (`ceil`) → bucket >= raw price\n * - bid (buy) levels round DOWN (`floor`) → bucket <= raw price\n *\n * This is the standard convention used by Hyperliquid / dYdX / Axiom and\n * guarantees `bestAsk - bestBid >= step`, i.e. the visible spread never\n * collapses into a single bucket where the two sides would overlap.\n */\nfunction aggregateByPrecision(\n levels: OrderBookLevel[],\n precision: number,\n side: \"ask\" | \"bid\",\n): OrderBookLevel[] {\n if (precision <= 0) return levels;\n\n const aggregated = new Map<number, OrderBookLevel>();\n const round = side === \"ask\" ? Math.ceil : Math.floor;\n\n levels.forEach((level) => {\n const roundedPrice = round(level.price / precision) * precision;\n\n const existing = aggregated.get(roundedPrice);\n if (existing) {\n existing.quantity += level.quantity;\n if (level.count) {\n existing.count = (existing.count || 0) + level.count;\n }\n } else {\n aggregated.set(roundedPrice, {\n price: roundedPrice,\n quantity: level.quantity,\n count: level.count,\n });\n }\n });\n\n return Array.from(aggregated.values());\n}\n\nfunction calculateTotalsAndPercentages(levels: OrderBookLevel[]): PriceLevel[] {\n let total = 0;\n const withTotals = levels.map((level) => {\n const usdAmount = level.quantity * level.price;\n total += usdAmount;\n return {\n ...level,\n quantity: usdAmount,\n total,\n percentage: 0,\n };\n });\n\n const maxTotal = total;\n return withTotals.map((level) => ({\n ...level,\n percentage: maxTotal > 0 ? (level.total / maxTotal) * 100 : 0,\n }));\n}\n\nexport function useOrderBookScript({\n symbol,\n maxLevel = 20,\n precision: initialPrecision = 1,\n}: UseOrderBookScriptParams): UseOrderBookScriptResult {\n const [orderBook, setOrderBook] = useState<OrderBook | null>(null);\n const [precision, setPrecision] = useState<number>(initialPrecision);\n\n // Keep precision in sync if the caller changes the controlled prop.\n useEffect(() => {\n setPrecision(initialPrecision);\n }, [initialPrecision]);\n\n // First REST call seeds the book without venue aggregation. Its only role\n // here is to give us a reference price so we can compute the right\n // (nSigFigs, mantissa) for the live subscription.\n const { data: initialData, isPending } = useOrderBookQuery({\n symbol,\n maxLevel,\n });\n\n // Reference price ≈ mid of best bid / best ask. Falls back to whichever\n // side is available. Locked to the price *magnitude* (decade) so it stays\n // stable across price ticks — re-subscribing on every $1 move would be\n // catastrophic.\n const priceMagnitude = useMemo(() => {\n const bestBid = orderBook?.bids[0]?.price ?? initialData?.bids[0]?.price;\n const bestAsk = orderBook?.asks[0]?.price ?? initialData?.asks[0]?.price;\n const ref =\n bestBid && bestAsk ? (bestBid + bestAsk) / 2 : (bestAsk ?? bestBid ?? 0);\n return ref > 0 ? Math.floor(Math.log10(ref)) : null;\n }, [orderBook, initialData]);\n\n // Aggregation hint sent to the WS subscription. Only depends on the chosen\n // step + price magnitude, so it's stable and re-subscribes only on real\n // changes.\n const aggregation = useMemo<OrderBookAggregationOptions | undefined>(() => {\n if (priceMagnitude === null) return undefined;\n const referencePrice = Math.pow(10, priceMagnitude);\n return aggregationFromStep(referencePrice, precision);\n }, [precision, priceMagnitude]);\n\n // Throttle pushes to ~10 Hz. Hyperliquid emits l2Book updates faster than\n // that on active markets, but the human eye can't tell the difference and\n // React reconciliation of 40 rows per push at 30 Hz wastes CPU. The\n // trailing-edge throttle in {@link useMarketDataSubscription} keeps the\n // latest snapshot, so users still see the freshest data on each tick —\n // just less often.\n const { data: realtimeData } = useMarketDataSubscription<OrderBook>({\n type: \"orderBook\",\n symbol,\n enabled: !!initialData,\n aggregation,\n throttleMs: 100,\n });\n\n useEffect(() => {\n if (realtimeData) {\n setOrderBook(realtimeData);\n } else if (initialData) {\n setOrderBook(initialData);\n }\n }, [realtimeData, initialData]);\n\n const processedData = useMemo(() => {\n if (!orderBook) {\n return {\n bids: [],\n asks: [],\n spread: 0,\n spreadPercentage: 0,\n };\n }\n\n const aggregatedBids = aggregateByPrecision(\n orderBook.bids,\n precision,\n \"bid\",\n );\n const aggregatedAsks = aggregateByPrecision(\n orderBook.asks,\n precision,\n \"ask\",\n );\n\n const sortedBids = aggregatedBids\n .sort((a, b) => b.price - a.price)\n .slice(0, maxLevel);\n\n const sortedAsks = aggregatedAsks\n .sort((a, b) => a.price - b.price)\n .slice(0, maxLevel);\n\n const bids = calculateTotalsAndPercentages(sortedBids);\n const asks = calculateTotalsAndPercentages(sortedAsks);\n\n const bestBid = bids[0]?.price || 0;\n const bestAsk = asks[0]?.price || 0;\n const spread = bestAsk - bestBid;\n const spreadPercentage = bestBid > 0 ? (spread / bestBid) * 100 : 0;\n\n return {\n bids,\n asks,\n spread,\n spreadPercentage,\n };\n }, [orderBook, precision, maxLevel]);\n\n return {\n ...processedData,\n isLoading: isPending,\n precision,\n setPrecision,\n };\n}\n","import type { CSSProperties } from \"react\";\nimport { memo, useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport type { PriceLevel } from \"./orderbook.script\";\n\n// ---------------------------------------------------------------------------\n// Static styles hoisted to module scope so they are NOT reallocated on every\n// render. The order book re-renders at the WebSocket push rate (~10–30 Hz),\n// so allocating fresh style objects per render is wasted GC pressure and\n// breaks shallow-equality optimisations like React.memo.\n// ---------------------------------------------------------------------------\n\n/**\n * Thin, subtle scrollbar for the asks/bids panes. Firefox uses the\n * standard properties; Chromium/Safari fall back to their default scrollbar\n * which is already unobtrusive on a dark background. We avoid `::-webkit-`\n * pseudo selectors here so the file stays a pure inline-style component\n * (no global CSS leakage into consumer apps).\n */\nconst ORDERBOOK_SCROLL_STYLE: CSSProperties = {\n scrollbarWidth: \"thin\",\n scrollbarColor: \"rgba(63,63,70,0.6) transparent\",\n};\n\nconst CONTAINER_STYLE: CSSProperties = {\n backgroundColor: \"#000000\",\n fontSize: 11,\n};\n\nconst HEADER_STYLE: CSSProperties = {\n height: 28,\n minHeight: 28,\n padding: \"0 16px\",\n gap: 16,\n color: \"#6b6b6b\",\n fontSize: 11,\n};\n\nconst HEADER_CELL_STYLE: CSSProperties = { flex: \"1 1 0%\" };\n\nconst ROW_STYLE: CSSProperties = {\n height: 22,\n minHeight: 22,\n maxHeight: 22,\n padding: \"0 16px\",\n gap: 16,\n fontSize: 11,\n};\n\n// Per-side row decoration (background gradient + price color) is constant.\n// Pre-compute both branches so the render path just picks one by reference.\nconst ASK_BAR_STYLE_BASE: CSSProperties = {\n height: 20,\n background: \"linear-gradient(to right, rgba(247,104,22,0), #F76816)\",\n opacity: 0.15,\n};\nconst BID_BAR_STYLE_BASE: CSSProperties = {\n height: 20,\n background: \"linear-gradient(to right, rgba(199,255,46,0), #C7FF2E)\",\n opacity: 0.15,\n};\nconst ASK_PRICE_STYLE: CSSProperties = { color: \"#F76816\", fontWeight: 400 };\nconst BID_PRICE_STYLE: CSSProperties = { color: \"#C7FF2E\", fontWeight: 400 };\nconst ROW_CELL_STYLE: CSSProperties = { flex: \"1 1 0%\", color: \"#ffffff\" };\nconst ROW_PRICE_CELL_STYLE: CSSProperties = { flex: \"1 1 0%\" };\n\nconst SPREAD_BAR_STYLE: CSSProperties = {\n height: 24,\n minHeight: 24,\n padding: \"0 16px\",\n backgroundColor: \"rgba(26,26,26,0.5)\",\n};\nconst SPREAD_BAR_INNER_STYLE: CSSProperties = {\n gap: 12,\n fontSize: 12,\n color: \"#ffffff\",\n};\nconst SPREAD_LABEL_STYLE: CSSProperties = { color: \"#ffffff\" };\nconst SPREAD_VALUE_STYLE: CSSProperties = {\n color: \"#ffffff\",\n fontWeight: 500,\n};\nconst SPREAD_BUTTON_STYLE: CSSProperties = {\n color: \"#ffffff\",\n fontWeight: 400,\n background: \"none\",\n border: \"none\",\n padding: 0,\n gap: 4,\n};\nconst SPREAD_DROPDOWN_STYLE: CSSProperties = {\n top: \"calc(100% + 4px)\",\n minWidth: 64,\n backgroundColor: \"#0a0a0a\",\n border: \"1px solid rgba(63,63,70,0.6)\",\n borderRadius: 6,\n padding: 4,\n boxShadow: \"0 4px 16px rgba(0,0,0,0.5)\",\n};\n\nconst SPREAD_OPTION_STYLE: CSSProperties = {\n padding: \"4px 10px\",\n fontSize: 12,\n color: \"#ffffff\",\n background: \"transparent\",\n border: \"none\",\n borderRadius: 4,\n textAlign: \"left\",\n};\nconst SPREAD_OPTION_SELECTED_STYLE: CSSProperties = {\n ...SPREAD_OPTION_STYLE,\n color: \"#C7FF2E\",\n};\n\nexport type OrderBookUIProps = {\n bids: PriceLevel[];\n asks: PriceLevel[];\n /** `(bestAsk - bestBid) / bestBid * 100`, rendered next to the precision dropdown. */\n spreadPercentage: number;\n /** Currently selected aggregation step. */\n precision: number;\n /** Available steps shown in the dropdown. */\n precisionOptions: readonly number[];\n /** Notify parent when the user picks a new step. */\n onPrecisionChange: (precision: number) => void;\n onPriceClick?: (price: number) => void;\n};\n\nfunction formatPrice(price: number): string {\n if (price >= 1000) {\n return price.toLocaleString(\"en-US\", {\n minimumFractionDigits: 0,\n maximumFractionDigits: 0,\n });\n }\n if (price >= 1) {\n return price.toLocaleString(\"en-US\", {\n minimumFractionDigits: 2,\n maximumFractionDigits: 4,\n });\n }\n return price.toFixed(6);\n}\n\nfunction formatQuantity(qty: number): string {\n return Math.round(qty).toLocaleString(\"en-US\");\n}\n\n/** Format the precision step shown in the dropdown trigger and items. */\nfunction formatPrecision(value: number): string {\n if (value >= 1) {\n return value.toLocaleString(\"en-US\", {\n minimumFractionDigits: 0,\n maximumFractionDigits: 0,\n });\n }\n return value.toString();\n}\n\ntype OBRowProps = {\n price: number;\n quantity: number;\n total: number;\n percentage: number;\n side: \"ask\" | \"bid\";\n /**\n * Forwarded from `OrderBookUI`. Passing the raw callback (instead of a\n * `() => onPriceClick(price)` wrapper from the parent) lets the parent's\n * function reference stay stable across renders, which in turn lets\n * {@link React.memo} on this component skip re-renders for rows whose\n * price/quantity/total/percentage have not changed.\n */\n onPriceClick?: (price: number) => void;\n};\n\nconst OBRow = memo(\n function OBRow({\n price,\n quantity,\n total,\n percentage,\n side,\n onPriceClick,\n }: OBRowProps) {\n const isAsk = side === \"ask\";\n\n // Per-render allocation is unavoidable here because `width` depends on\n // the row's percentage. Keeping every other style static (see\n // ASK_BAR_STYLE_BASE / BID_BAR_STYLE_BASE) limits the cost to one tiny\n // object per visible row per push.\n const barStyle: CSSProperties = useMemo(\n () =>\n isAsk\n ? { ...ASK_BAR_STYLE_BASE, width: `${percentage}%` }\n : { ...BID_BAR_STYLE_BASE, width: `${percentage}%` },\n [isAsk, percentage],\n );\n\n const handleClick = useMemo(\n () => (onPriceClick ? () => onPriceClick(price) : undefined),\n [onPriceClick, price],\n );\n\n return (\n <div\n className=\"relative flex items-center cursor-pointer hover:bg-white/5 transition-colors\"\n style={ROW_STYLE}\n onClick={handleClick}\n >\n <div className=\"absolute left-0 top-0\" style={barStyle} />\n <div\n className=\"relative z-10 flex items-center\"\n style={ROW_PRICE_CELL_STYLE}\n >\n <span style={isAsk ? ASK_PRICE_STYLE : BID_PRICE_STYLE}>\n {formatPrice(price)}\n </span>\n </div>\n <div\n className=\"relative z-10 flex items-center justify-end\"\n style={ROW_CELL_STYLE}\n >\n {formatQuantity(quantity)}\n </div>\n <div\n className=\"relative z-10 flex items-center justify-end\"\n style={ROW_CELL_STYLE}\n >\n {formatQuantity(total)}\n </div>\n </div>\n );\n },\n // Custom equality: ignore object identity, compare the data fields React\n // actually renders. `onPriceClick` is treated as stable by reference (the\n // parent should `useCallback`/pass a stable handler).\n (prev, next) =>\n prev.price === next.price &&\n prev.quantity === next.quantity &&\n prev.total === next.total &&\n prev.percentage === next.percentage &&\n prev.side === next.side &&\n prev.onPriceClick === next.onPriceClick,\n);\n\n/**\n * Spread bar with precision step dropdown. Mirrors Axiom's design:\n *\n * Spread: [ 1 ▾ ] 0.001%\n *\n * Clicking the dropdown opens a vertical list of available steps. The actual\n * spread value is implicit (best ask - best bid is one step after\n * aggregation) so we only show the percentage on the right.\n */\nfunction SpreadBar({\n spreadPercentage,\n precision,\n precisionOptions,\n onPrecisionChange,\n}: {\n spreadPercentage: number;\n precision: number;\n precisionOptions: readonly number[];\n onPrecisionChange: (precision: number) => void;\n}) {\n const [open, setOpen] = useState(false);\n const wrapperRef = useRef<HTMLDivElement | null>(null);\n\n // Close on outside click.\n useEffect(() => {\n if (!open) return;\n const handler = (e: MouseEvent) => {\n if (!wrapperRef.current?.contains(e.target as Node)) {\n setOpen(false);\n }\n };\n document.addEventListener(\"mousedown\", handler);\n return () => document.removeEventListener(\"mousedown\", handler);\n }, [open]);\n\n // Chevron rotates on open. The transform is dynamic, the rest is static.\n const chevronStyle: CSSProperties = useMemo(\n () => ({\n color: \"#6b6b6b\",\n transform: open ? \"rotate(180deg)\" : \"rotate(0deg)\",\n transition: \"transform 0.15s\",\n }),\n [open],\n );\n\n return (\n <div className=\"flex items-center justify-center\" style={SPREAD_BAR_STYLE}>\n <div className=\"flex items-center\" style={SPREAD_BAR_INNER_STYLE}>\n <span style={SPREAD_LABEL_STYLE}>Spread:</span>\n <div ref={wrapperRef} className=\"relative\">\n <button\n type=\"button\"\n className=\"flex items-center cursor-pointer hover:text-white/80 transition-colors\"\n style={SPREAD_BUTTON_STYLE}\n onClick={() => setOpen((v) => !v)}\n aria-haspopup=\"listbox\"\n aria-expanded={open}\n >\n <span>{formatPrecision(precision)}</span>\n {/* Neutral grey chevron — kept independent of the precision\n value's text color so the affordance reads as \"decoration\",\n not as part of the active value. */}\n <svg\n width=\"8\"\n height=\"8\"\n viewBox=\"0 0 8 8\"\n fill=\"none\"\n style={chevronStyle}\n >\n <path\n d=\"M1 2.5L4 5.5L7 2.5\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n </button>\n {open && (\n <div\n role=\"listbox\"\n className=\"absolute left-1/2 -translate-x-1/2 z-20 flex flex-col\"\n style={SPREAD_DROPDOWN_STYLE}\n >\n {precisionOptions.map((opt) => {\n const selected = opt === precision;\n return (\n <button\n key={opt}\n type=\"button\"\n role=\"option\"\n aria-selected={selected}\n className=\"cursor-pointer transition-colors\"\n style={\n selected\n ? SPREAD_OPTION_SELECTED_STYLE\n : SPREAD_OPTION_STYLE\n }\n onMouseEnter={(e) => {\n e.currentTarget.style.backgroundColor =\n \"rgba(255,255,255,0.06)\";\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.backgroundColor = \"transparent\";\n }}\n onClick={() => {\n onPrecisionChange(opt);\n setOpen(false);\n }}\n >\n {formatPrecision(opt)}\n </button>\n );\n })}\n </div>\n )}\n </div>\n <span style={SPREAD_VALUE_STYLE}>{spreadPercentage.toFixed(3)}%</span>\n </div>\n </div>\n );\n}\n\n/**\n * Order book layout (top to bottom):\n *\n * ┌─ Header (Price / Amount / Total) ────┐ fixed height\n * ├─ Asks scroll region ─────────────────┤ flex-1, independent scroll\n * │ highest ask │\n * │ ... │\n * │ best ask ◄── default visible │\n * ├─ Spread bar with precision dropdown ─┤ fixed height\n * ├─ Bids scroll region ─────────────────┤ flex-1, independent scroll\n * │ best bid ◄── default visible │\n * │ ... │\n * │ lowest bid │\n * └──────────────────────────────────────┘\n *\n * Both scroll regions consume any leftover container height equally; if the\n * widget is short, each side scrolls on its own without dragging the other.\n *\n * Asks come in sorted ascending (best ask = lowest price = `asks[0]`). To\n * pin the best ask flush against the spread bar we render asks reversed\n * (highest first → best last in DOM order) inside a normal column scroll\n * container, then default-scroll to the bottom on mount. We re-stick the\n * scroll position to the bottom whenever the user is already near it, so\n * websocket updates don't bounce the view off the best ask.\n *\n * Bids are sorted descending (`bids[0]` = best) and rendered top-down,\n * so the best bid sits at `scrollTop = 0` flush against the spread bar\n * by default.\n */\nexport function OrderBookUI({\n bids,\n asks,\n spreadPercentage,\n precision,\n precisionOptions,\n onPrecisionChange,\n onPriceClick,\n}: OrderBookUIProps) {\n const asksScrollRef = useRef<HTMLDivElement | null>(null);\n const bidsScrollRef = useRef<HTMLDivElement | null>(null);\n // Track whether the user has scrolled away from the spread-bar edge of\n // each side. While they are still \"stuck\" near the spread, we keep that\n // edge in view across data updates; once they scroll away, we leave the\n // scroll position alone so they can browse deeper levels in peace.\n const asksStuckRef = useRef(true);\n const bidsStuckRef = useRef(true);\n\n // Render-order helper: highest ask first, best ask last (closest to\n // spread bar). Memoised so the array reference is stable when `asks` is\n // — otherwise the asks `useEffect` below would fire on every render,\n // not just on actual data updates.\n const renderedAsks = useMemo(() => [...asks].reverse(), [asks]);\n\n // Whenever asks update and the user is still pinned near the spread bar,\n // re-anchor the scroll position to the bottom (where the best ask lives).\n // Skip the assignment when scrollTop is already at the target to avoid\n // gratuitous layout work on every WebSocket push.\n useEffect(() => {\n const el = asksScrollRef.current;\n if (!el || !asksStuckRef.current) return;\n const target = el.scrollHeight;\n if (el.scrollTop !== target) {\n el.scrollTop = target;\n }\n }, [renderedAsks]);\n\n // Same idea for bids: keep the best bid (top) glued to the spread bar\n // until the user scrolls away.\n useEffect(() => {\n const el = bidsScrollRef.current;\n if (!el || !bidsStuckRef.current) return;\n if (el.scrollTop !== 0) {\n el.scrollTop = 0;\n }\n }, [bids]);\n\n const handleAsksScroll = useCallback(() => {\n const el = asksScrollRef.current;\n if (!el) return;\n // For asks the spread-bar edge is the *bottom* of the scroll region.\n // Allow a small tolerance (one row) so flicker from updates doesn't\n // un-stick the view.\n const distanceFromBottom = el.scrollHeight - el.scrollTop - el.clientHeight;\n asksStuckRef.current = distanceFromBottom <= 24;\n }, []);\n\n const handleBidsScroll = useCallback(() => {\n const el = bidsScrollRef.current;\n if (!el) return;\n // For bids the spread-bar edge is the *top* of the scroll region.\n bidsStuckRef.current = el.scrollTop <= 24;\n }, []);\n\n return (\n <div className=\"flex flex-col h-full min-h-0\" style={CONTAINER_STYLE}>\n {/* Header */}\n <div className=\"flex items-center flex-none\" style={HEADER_STYLE}>\n <div className=\"flex items-center\" style={HEADER_CELL_STYLE}>\n Price\n </div>\n <div\n className=\"flex items-center justify-end\"\n style={HEADER_CELL_STYLE}\n >\n Amount (USD)\n </div>\n <div\n className=\"flex items-center justify-end\"\n style={HEADER_CELL_STYLE}\n >\n Total (USD)\n </div>\n </div>\n\n {/* Asks — independent scroll. Reversed so best ask lives at the\n DOM bottom; we default-scroll to the bottom to surface it. */}\n <div\n ref={asksScrollRef}\n onScroll={handleAsksScroll}\n className=\"flex-1 min-h-0 overflow-y-auto\"\n style={ORDERBOOK_SCROLL_STYLE}\n >\n {renderedAsks.map((ask, index) => (\n <OBRow\n key={`ask-${ask.price}-${index}`}\n price={ask.price}\n quantity={ask.quantity}\n total={ask.total}\n percentage={ask.percentage}\n side=\"ask\"\n onPriceClick={onPriceClick}\n />\n ))}\n </div>\n\n {/* Spread bar */}\n <div className=\"flex-none\">\n <SpreadBar\n spreadPercentage={spreadPercentage}\n precision={precision}\n precisionOptions={precisionOptions}\n onPrecisionChange={onPrecisionChange}\n />\n </div>\n\n {/* Bids — independent scroll. Best bid is at the top so it sits\n flush against the spread bar at scrollTop=0. */}\n <div\n ref={bidsScrollRef}\n onScroll={handleBidsScroll}\n className=\"flex-1 min-h-0 overflow-y-auto\"\n style={ORDERBOOK_SCROLL_STYLE}\n >\n {bids.map((bid, index) => (\n <OBRow\n key={`bid-${bid.price}-${index}`}\n price={bid.price}\n quantity={bid.quantity}\n total={bid.total}\n percentage={bid.percentage}\n side=\"bid\"\n onPriceClick={onPriceClick}\n />\n ))}\n </div>\n </div>\n );\n}\n","import type { CSSProperties } from \"react\";\nimport { ShimmerStyle, shimmerDelay } from \"../../internal/skeleton\";\nimport { useOrderBookScript } from \"./orderbook.script\";\nimport { OrderBookUI } from \"./orderbook.ui\";\n\n/**\n * Default tick-aggregation steps offered to the user via the spread dropdown.\n *\n * Mirrors Axiom / Hyperliquid's perpetuals UI for major USD-quoted pairs\n * (BTC, ETH, SOL): users can collapse the book into 1, 2, 5, 10, 100, or\n * 1000-USD buckets to see liquidity at coarser granularities.\n */\nexport const DEFAULT_ORDER_BOOK_PRECISION_OPTIONS = [\n 1, 2, 5, 10, 100, 1000,\n] as const;\n\nexport type OrderBookWidgetProps = {\n symbol: string;\n /**\n * How many price levels to fetch + render per side. Defaults to `40` so\n * that asks and bids always have enough rows to overflow their containers\n * and show their independent scroll bars.\n */\n maxLevel?: number;\n /**\n * Steps shown in the \"Spread\" dropdown. Defaults to\n * `[1, 2, 5, 10, 100, 1000]` (Axiom's BTC perpetuals options).\n */\n precisionOptions?: readonly number[];\n /**\n * Initial selected step. Defaults to the first entry in `precisionOptions`.\n */\n defaultPrecision?: number;\n onPriceClick?: (price: number) => void;\n className?: string;\n};\n\n// ---------------------------------------------------------------------------\n// Skeleton — must match OrderBookUI's footprint (header + asks + spread bar\n// + bids) so the layout doesn't jump when data arrives. Header text renders\n// the real labels; the rows pulse with the shared shimmer language used by\n// coin-info, trades and the prediction module's skeletons.\n// ---------------------------------------------------------------------------\n\nconst SKEL_CONTAINER_STYLE: CSSProperties = {\n backgroundColor: \"#000000\",\n fontSize: 11,\n};\n\nconst SKEL_HEADER_STYLE: CSSProperties = {\n height: 28,\n minHeight: 28,\n padding: \"0 16px\",\n gap: 16,\n color: \"#6b6b6b\",\n fontSize: 11,\n};\n\nconst SKEL_HEADER_CELL_STYLE: CSSProperties = { flex: \"1 1 0%\" };\n\nconst SKEL_ROW_STYLE: CSSProperties = {\n height: 22,\n minHeight: 22,\n maxHeight: 22,\n padding: \"0 16px\",\n gap: 16,\n};\n\nconst SKEL_SPREAD_BAR_STYLE: CSSProperties = {\n height: 24,\n minHeight: 24,\n padding: \"0 16px\",\n backgroundColor: \"rgba(26,26,26,0.5)\",\n};\n\nfunction SkelRow({ delay }: { delay: number }) {\n return (\n <div className=\"flex items-center\" style={SKEL_ROW_STYLE}>\n <div style={SKEL_HEADER_CELL_STYLE}>\n <div style={{ ...shimmerDelay(delay), height: 11, width: 56 }} />\n </div>\n <div className=\"flex justify-end\" style={SKEL_HEADER_CELL_STYLE}>\n <div style={{ ...shimmerDelay(delay + 30), height: 11, width: 64 }} />\n </div>\n <div className=\"flex justify-end\" style={SKEL_HEADER_CELL_STYLE}>\n <div style={{ ...shimmerDelay(delay + 60), height: 11, width: 64 }} />\n </div>\n </div>\n );\n}\n\nfunction OrderBookSkeleton() {\n // 8 rows per side is a good visual budget — enough to fill the typical\n // viewport without overdrawing huge skeleton trees on tall screens.\n const askRows = Array.from({ length: 8 }, (_, i) => i);\n const bidRows = Array.from({ length: 8 }, (_, i) => i);\n return (\n <>\n <ShimmerStyle />\n <div\n className=\"flex flex-col h-full min-h-0\"\n style={SKEL_CONTAINER_STYLE}\n >\n {/* Real header — same text and metrics as OrderBookUI. */}\n <div className=\"flex items-center flex-none\" style={SKEL_HEADER_STYLE}>\n <div className=\"flex items-center\" style={SKEL_HEADER_CELL_STYLE}>\n Price\n </div>\n <div\n className=\"flex items-center justify-end\"\n style={SKEL_HEADER_CELL_STYLE}\n >\n Amount (USD)\n </div>\n <div\n className=\"flex items-center justify-end\"\n style={SKEL_HEADER_CELL_STYLE}\n >\n Total (USD)\n </div>\n </div>\n\n {/* Asks placeholder rows */}\n <div className=\"flex-1 min-h-0 overflow-hidden\">\n {askRows.map((i) => (\n <SkelRow key={`ask-${i}`} delay={i * 40} />\n ))}\n </div>\n\n {/* Spread bar placeholder — keep the bar's tinted background and\n a single shimmer cell where the precision dropdown lives. */}\n <div\n className=\"flex-none flex items-center justify-center\"\n style={SKEL_SPREAD_BAR_STYLE}\n >\n <div style={{ ...shimmerDelay(0), width: 96, height: 12 }} />\n </div>\n\n {/* Bids placeholder rows */}\n <div className=\"flex-1 min-h-0 overflow-hidden\">\n {bidRows.map((i) => (\n <SkelRow key={`bid-${i}`} delay={200 + i * 40} />\n ))}\n </div>\n </div>\n </>\n );\n}\n\nfunction OrderBookEmpty() {\n return (\n <div className=\"flex items-center justify-center h-full\">\n <span className=\"text-neutral-400 text-sm\">\n No order book data available\n </span>\n </div>\n );\n}\n\nexport function OrderBookWidget({\n symbol,\n maxLevel = 40,\n precisionOptions = DEFAULT_ORDER_BOOK_PRECISION_OPTIONS,\n defaultPrecision,\n onPriceClick,\n className,\n}: OrderBookWidgetProps) {\n const initialPrecision = defaultPrecision ?? precisionOptions[0] ?? 1;\n\n const { bids, asks, spreadPercentage, isLoading, precision, setPrecision } =\n useOrderBookScript({\n symbol,\n maxLevel,\n precision: initialPrecision,\n });\n\n if (isLoading) {\n return <OrderBookSkeleton />;\n }\n\n if (bids.length === 0 && asks.length === 0) {\n return <OrderBookEmpty />;\n }\n\n return (\n <div className={className}>\n <OrderBookUI\n bids={bids}\n asks={asks}\n spreadPercentage={spreadPercentage}\n precision={precision}\n precisionOptions={precisionOptions}\n onPrecisionChange={setPrecision}\n onPriceClick={onPriceClick}\n />\n </div>\n );\n}\n","import { useEffect, useRef, useState } from \"react\";\nimport { useMarketDataSubscription } from \"../../hooks/useMarketDataSubscription\";\nimport { useRecentTradesQuery } from \"../../hooks/useRecentTradesQuery\";\nimport type { Trade } from \"../../types\";\n\nexport type UseTradesScriptParams = {\n symbol: string;\n limit?: number;\n};\n\nexport type UseTradesScriptResult = {\n trades: Trade[];\n isLoading: boolean;\n};\n\n/**\n * Trailing-edge flush interval for incoming WebSocket trade pushes. Hyperliquid\n * can fire 5–30 fills per second on active markets like BTC perp. Calling\n * `setTrades` for every push triggers React reconciliation per push; coalescing\n * into one setState every `BATCH_FLUSH_MS` caps the reconcile rate at 5 Hz\n * without losing trades (we *append* — see {@link normalizeRealtimeTrades}).\n *\n * 200 ms is small enough that the latest trade is on screen \"instantly\" from\n * the user's perspective, and large enough to absorb the typical burst rate.\n */\nconst BATCH_FLUSH_MS = 200;\n\nexport function useTradesScript({\n symbol,\n limit = 50,\n}: UseTradesScriptParams): UseTradesScriptResult {\n const [trades, setTrades] = useState<Trade[]>([]);\n\n const { data: initialData, isPending } = useRecentTradesQuery({\n symbol,\n limit,\n });\n\n const { data: realtimeTrade } = useMarketDataSubscription<Trade | Trade[]>({\n type: \"trades\",\n symbol,\n enabled: !!initialData,\n });\n\n // Seed the in-memory trade list from the REST snapshot once it arrives.\n // After this point the websocket subscription owns updates.\n useEffect(() => {\n if (initialData) {\n setTrades(initialData.filter(isValidTrade));\n }\n }, [initialData]);\n\n // ---- Trailing-edge batch flush --------------------------------------\n // We accumulate incoming pushes in a ref and flush them through a single\n // `setTrades` no more than once every BATCH_FLUSH_MS. This is *append*\n // semantics (so we keep every fill), unlike `useMarketDataSubscription`'s\n // built-in `throttleMs` which is \"drop intermediate values\".\n const pendingRef = useRef<Trade[]>([]);\n const flushTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const limitRef = useRef(limit);\n limitRef.current = limit;\n\n useEffect(() => {\n if (!realtimeTrade) return;\n\n const incoming = normalizeRealtimeTrades(realtimeTrade);\n if (incoming.length === 0) return;\n pendingRef.current.push(...incoming);\n\n if (flushTimerRef.current !== null) return;\n\n flushTimerRef.current = setTimeout(() => {\n flushTimerRef.current = null;\n const batch = pendingRef.current;\n pendingRef.current = [];\n if (batch.length === 0) return;\n\n setTrades((prev) => {\n // Drop fills already present (Hyperliquid occasionally re-sends the\n // same trade across a reconnect). Match on (timestamp, price, qty)\n // tuple — `tradeId` is not always set.\n const deduped = batch.filter(\n (next) =>\n !prev.some(\n (existing) =>\n existing.timestamp === next.timestamp &&\n existing.price === next.price &&\n existing.quantity === next.quantity,\n ),\n );\n if (deduped.length === 0) return prev;\n\n // The batch arrives in chronological order from the WS feed; we\n // reverse it so the *latest* fill in the batch ends up at index 0\n // of the merged list (newest-first).\n return [...deduped.reverse(), ...prev].slice(0, limitRef.current);\n });\n }, BATCH_FLUSH_MS);\n }, [realtimeTrade]);\n\n // Reset on symbol change (or unmount). Drop any pending payload so it\n // can't land after the subscription is torn down.\n useEffect(() => {\n return () => {\n if (flushTimerRef.current !== null) {\n clearTimeout(flushTimerRef.current);\n flushTimerRef.current = null;\n }\n pendingRef.current = [];\n };\n }, [symbol]);\n\n return {\n trades,\n isLoading: isPending,\n };\n}\n\nfunction normalizeRealtimeTrades(payload: Trade | Trade[]): Trade[] {\n const list = Array.isArray(payload) ? payload : [payload];\n return list.filter(isValidTrade);\n}\n\nfunction isValidTrade(trade: Partial<Trade> | undefined): trade is Trade {\n if (!trade) return false;\n return (\n typeof trade.symbol === \"string\" &&\n (trade.side === \"buy\" || trade.side === \"sell\") &&\n typeof trade.price === \"number\" &&\n Number.isFinite(trade.price) &&\n typeof trade.quantity === \"number\" &&\n Number.isFinite(trade.quantity) &&\n typeof trade.timestamp === \"number\" &&\n Number.isFinite(trade.timestamp)\n );\n}\n","import type { CSSProperties, ReactElement } from \"react\";\nimport { useMemo, useRef } from \"react\";\nimport { List, type RowComponentProps } from \"react-window\";\nimport { useResizeObserver, useTickAge } from \"@liberfi.io/hooks\";\nimport type { Trade } from \"../../types\";\n\n// ---------------------------------------------------------------------------\n// Static styles hoisted to module scope so they are NOT reallocated on every\n// render. The trades list re-renders at the WS push rate and the age tick\n// rate, so allocating fresh style objects per render is wasted GC pressure\n// and breaks shallow-equality optimisations like React.memo.\n// ---------------------------------------------------------------------------\n\nconst ROW_HEIGHT = 22;\nconst HEADER_HEIGHT = 28;\nconst PRICE_COL_MAX_W = 100;\nconst AGE_COL_MAX_W = 120;\n\nconst CONTAINER_STYLE: CSSProperties = {\n backgroundColor: \"#000000\",\n fontSize: 11,\n};\n\nconst HEADER_STYLE: CSSProperties = {\n height: HEADER_HEIGHT,\n minHeight: HEADER_HEIGHT,\n padding: \"0 16px\",\n color: \"#6b6b6b\",\n fontSize: 11,\n};\n\nconst HEADER_PRICE_CELL: CSSProperties = {\n flex: \"1 1 0%\",\n maxWidth: PRICE_COL_MAX_W,\n};\nconst HEADER_SIZE_CELL: CSSProperties = { flex: \"1 1 0%\", marginLeft: 20 };\nconst HEADER_AGE_CELL: CSSProperties = {\n flex: \"1 1 0%\",\n maxWidth: AGE_COL_MAX_W,\n textAlign: \"right\",\n};\n\nconst ROW_INNER_STYLE: CSSProperties = {\n height: ROW_HEIGHT,\n minHeight: ROW_HEIGHT,\n maxHeight: ROW_HEIGHT,\n padding: \"0 16px\",\n};\n\nconst ROW_PRICE_CELL: CSSProperties = {\n flex: \"1 1 0%\",\n maxWidth: PRICE_COL_MAX_W,\n};\nconst ROW_SIZE_CELL: CSSProperties = {\n flex: \"1 1 0%\",\n marginLeft: 20,\n color: \"#FCFCFC\",\n};\nconst ROW_AGE_CELL: CSSProperties = {\n flex: \"1 1 0%\",\n maxWidth: AGE_COL_MAX_W,\n textAlign: \"right\",\n color: \"#777A8C\",\n};\n\n// Per-side row decoration. The colour comes from the project's semantic\n// theme tokens (declared in the consumer's `theme.css` as\n// `--color-bullish` / `--color-bearish`, which themselves resolve to\n// `hsl(var(--heroui-primary))` / `hsl(var(--heroui-secondary))`). Using\n// CSS variables instead of hard-coded hex keeps the bars in lock-step\n// with the active HeroUI theme — including future light-mode variants.\n//\n// Width is data-dependent (see `barWidth`), so we keep it out of the base.\nconst BUY_BAR_STYLE_BASE: CSSProperties = {\n position: \"absolute\",\n left: 0,\n top: 0,\n height: 20,\n background: \"linear-gradient(to right, transparent, var(--color-bullish))\",\n opacity: 0.15,\n pointerEvents: \"none\",\n};\nconst SELL_BAR_STYLE_BASE: CSSProperties = {\n position: \"absolute\",\n left: 0,\n top: 0,\n height: 20,\n background: \"linear-gradient(to right, transparent, var(--color-bearish))\",\n opacity: 0.15,\n pointerEvents: \"none\",\n};\n\n// ---------------------------------------------------------------------------\n// Formatting utilities\n// ---------------------------------------------------------------------------\n\n/**\n * Format the trade price. Mirrors `orderbook.ui.tsx`:\n * ≥ 1000 → integer with thousands separator (e.g. `80,646`)\n * ≥ 1 → 2–4 fraction digits (e.g. `84.62`)\n * < 1 → 6 fraction digits (e.g. `0.0457`)\n */\nfunction formatPrice(price: number): string {\n if (!Number.isFinite(price)) return \"-\";\n if (price >= 1000) {\n return price.toLocaleString(\"en-US\", {\n minimumFractionDigits: 0,\n maximumFractionDigits: 0,\n });\n }\n if (price >= 1) {\n return price.toLocaleString(\"en-US\", {\n minimumFractionDigits: 2,\n maximumFractionDigits: 4,\n });\n }\n return price.toFixed(6);\n}\n\n/**\n * Format the USD notional size. Always 2 fraction digits with a `$` prefix\n * and thousands separators, e.g. `$83.85`, `$8,365.65`. No K/M abbreviation\n * (Axiom uses full digits and so do we — easier to parse at a glance).\n */\nfunction formatUsd(usd: number): string {\n if (!Number.isFinite(usd)) return \"-\";\n return (\n \"$\" +\n usd.toLocaleString(\"en-US\", {\n minimumFractionDigits: 2,\n maximumFractionDigits: 2,\n })\n );\n}\n\n/**\n * Format the trade age. Receives milliseconds (the `useTickAge` return\n * value) to avoid a per-row second conversion. Steps:\n * < 60 s → `${n}s`\n * < 60 min → `${n}m`\n * < 24 h → `${n}h`\n * else → `${n}d`\n */\nfunction formatAge(ageMs: number): string {\n const seconds = Math.max(0, Math.floor(ageMs / 1000));\n if (seconds < 60) return `${seconds}s`;\n const minutes = Math.floor(seconds / 60);\n if (minutes < 60) return `${minutes}m`;\n const hours = Math.floor(minutes / 60);\n if (hours < 24) return `${hours}h`;\n return `${Math.floor(hours / 24)}d`;\n}\n\n/**\n * Map a USD notional value to a 0-100 percentage for the row's background\n * bar width. We reverse-engineered Axiom's relationship from observed DOM\n * samples (e.g. $12.09 → 11.24%, $83.85 → 23.85%, $8,365.65 → 53.84%) and\n * found a near-perfect fit:\n *\n * width(%) = 15 × log10(usd) − 5\n *\n * Logarithmic scale keeps small trades visible without letting whales\n * flatten everything to a sliver. Clamped to [0, 100].\n */\nfunction barWidth(usd: number): number {\n if (!Number.isFinite(usd) || usd <= 0) return 0;\n return Math.max(0, Math.min(100, 15 * Math.log10(usd) - 5));\n}\n\n// ---------------------------------------------------------------------------\n// Row component\n// ---------------------------------------------------------------------------\n\ntype TradeRowData = {\n trades: Trade[];\n onTradeClick?: (trade: Trade) => void;\n};\n\n/**\n * react-window v2 row component. Note: we deliberately do NOT wrap this in\n * `React.memo`. The age is driven by `useTickAge`'s internal `setAge`, which\n * only re-renders this single row — never the parent — so wrapping with\n * `memo` would not save any cascaded reconciliations. Parent re-renders\n * (caused by `trades` array changes from the 200ms batch flush) shift every\n * row's `trades[index]` reference anyway, defeating shallow equality.\n *\n * react-window itself already short-circuits off-screen rows by simply not\n * mounting them, so we get virtualization benefits without manual memo.\n */\nfunction TradeRow({\n index,\n style,\n trades,\n onTradeClick,\n}: RowComponentProps<TradeRowData>): ReactElement | null {\n const trade = trades[index];\n\n // Subscribe to the global 1 Hz timer for this row's age. `useTickAge` is a\n // thin wrapper over `useTick`, which itself uses a `GlobalTimer`\n // singleton — there is exactly one `setTimeout` for the entire app, all\n // rows share it via an internal Map. `setAge` fires only inside this row,\n // so age-tick reconciliation is bounded to *one* row per tick.\n const birthday = trade?.timestamp ?? Date.now();\n const ageMs = useTickAge(birthday);\n\n const usd = useMemo(() => {\n if (!trade) return 0;\n if (!Number.isFinite(trade.price) || !Number.isFinite(trade.quantity)) {\n return 0;\n }\n return trade.price * trade.quantity;\n }, [trade]);\n\n // Per-render allocation is unavoidable here because `width` depends on\n // `usd`. Keeping every other style static (see *_BAR_STYLE_BASE) limits\n // the cost to one tiny object per visible row per WS push.\n const barStyle: CSSProperties = useMemo(() => {\n const isBuy = trade?.side === \"buy\";\n const base = isBuy ? BUY_BAR_STYLE_BASE : SELL_BAR_STYLE_BASE;\n return { ...base, width: `${barWidth(usd)}%` };\n }, [trade, usd]);\n\n if (!trade) return null;\n\n const isBuy = trade.side === \"buy\";\n\n return (\n <div style={style}>\n <div\n className=\"relative flex items-center cursor-pointer hover:bg-white/5 transition-colors\"\n style={ROW_INNER_STYLE}\n onClick={onTradeClick ? () => onTradeClick(trade) : undefined}\n >\n <div style={barStyle} />\n <div className=\"relative z-10 flex items-center\" style={ROW_PRICE_CELL}>\n <span className={isBuy ? \"text-bullish\" : \"text-bearish\"}>\n {formatPrice(trade.price)}\n </span>\n </div>\n <div className=\"relative z-10 flex items-center\" style={ROW_SIZE_CELL}>\n {formatUsd(usd)}\n </div>\n <div\n className=\"relative z-10 flex items-center justify-end\"\n style={ROW_AGE_CELL}\n >\n {formatAge(ageMs)}\n </div>\n </div>\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// List component\n// ---------------------------------------------------------------------------\n\nexport type TradesUIProps = {\n trades: Trade[];\n onTradeClick?: (trade: Trade) => void;\n};\n\nexport function TradesUI({\n trades,\n onTradeClick,\n}: TradesUIProps): ReactElement {\n // Resize observation: react-window v2 needs an explicit `height` prop on\n // `<List>`. We measure the wrapping div with the shared `useResizeObserver`\n // hook (same pattern used in `ui-tokens` SearchResultListWidget).\n const listContainerRef = useRef<HTMLDivElement | null>(null);\n const { height = 0 } = useResizeObserver<HTMLDivElement>({\n ref: listContainerRef,\n });\n\n // `rowProps` is the parameter object react-window passes (alongside\n // `index` / `style`) into our `rowComponent`. Memoise so the reference\n // is stable when neither `trades` nor `onTradeClick` change — keeps\n // react-window's own bailouts effective.\n const rowProps = useMemo<TradeRowData>(\n () => ({ trades, onTradeClick }),\n [trades, onTradeClick],\n );\n\n return (\n <div className=\"flex flex-col h-full\" style={CONTAINER_STYLE}>\n <div className=\"flex items-center flex-none\" style={HEADER_STYLE}>\n <div style={HEADER_PRICE_CELL}>Price</div>\n <div style={HEADER_SIZE_CELL}>Size (USD)</div>\n <div style={HEADER_AGE_CELL}>Age</div>\n </div>\n <div ref={listContainerRef} className=\"flex-1 min-h-0\">\n {height > 0 && (\n <List\n style={{ height }}\n rowComponent={TradeRow}\n rowCount={trades.length}\n rowHeight={ROW_HEIGHT}\n rowProps={rowProps}\n overscanCount={4}\n />\n )}\n </div>\n </div>\n );\n}\n","import type { CSSProperties } from \"react\";\nimport { ShimmerStyle, shimmerDelay } from \"../../internal/skeleton\";\nimport type { Trade } from \"../../types\";\nimport { useTradesScript } from \"./trades.script\";\nimport { TradesUI } from \"./trades.ui\";\n\nexport type TradesWidgetProps = {\n symbol: string;\n limit?: number;\n onTradeClick?: (trade: Trade) => void;\n className?: string;\n};\n\n// ---------------------------------------------------------------------------\n// Skeleton — must match TradesUI's footprint (header + virtualised rows) so\n// the layout doesn't jump when data arrives. Header text renders the real\n// labels; row placeholders pulse with the shared shimmer language used by\n// coin-info, orderbook and the prediction module's skeletons.\n//\n// Column metrics here intentionally mirror the constants in `trades.ui.tsx`\n// (PRICE_COL_MAX_W=100, AGE_COL_MAX_W=120, marginLeft=20 between price and\n// size). Keeping them in sync visually anchors the placeholder columns to\n// where the real columns will land.\n// ---------------------------------------------------------------------------\n\nconst SKEL_CONTAINER_STYLE: CSSProperties = {\n backgroundColor: \"#000000\",\n fontSize: 11,\n};\n\nconst SKEL_HEADER_STYLE: CSSProperties = {\n height: 28,\n minHeight: 28,\n padding: \"0 16px\",\n color: \"#6b6b6b\",\n fontSize: 11,\n};\n\nconst SKEL_HEADER_PRICE_CELL: CSSProperties = {\n flex: \"1 1 0%\",\n maxWidth: 100,\n};\nconst SKEL_HEADER_SIZE_CELL: CSSProperties = {\n flex: \"1 1 0%\",\n marginLeft: 20,\n};\nconst SKEL_HEADER_AGE_CELL: CSSProperties = {\n flex: \"1 1 0%\",\n maxWidth: 120,\n textAlign: \"right\",\n};\n\nconst SKEL_ROW_STYLE: CSSProperties = {\n height: 22,\n minHeight: 22,\n maxHeight: 22,\n padding: \"0 16px\",\n};\n\nfunction TradeSkelRow({ delay }: { delay: number }) {\n return (\n <div className=\"flex items-center\" style={SKEL_ROW_STYLE}>\n <div style={SKEL_HEADER_PRICE_CELL}>\n <div style={{ ...shimmerDelay(delay), height: 11, width: 56 }} />\n </div>\n <div style={SKEL_HEADER_SIZE_CELL}>\n <div style={{ ...shimmerDelay(delay + 30), height: 11, width: 64 }} />\n </div>\n <div className=\"flex justify-end\" style={SKEL_HEADER_AGE_CELL}>\n <div style={{ ...shimmerDelay(delay + 60), height: 11, width: 28 }} />\n </div>\n </div>\n );\n}\n\nfunction TradesSkeleton() {\n // 12 placeholder rows — the live list typically renders ~20-30 visible\n // rows, but 12 is enough to fill the panel without paying for every\n // additional shimmer paint while data is in flight.\n const rows = Array.from({ length: 12 }, (_, i) => i);\n return (\n <>\n <ShimmerStyle />\n <div className=\"flex flex-col h-full\" style={SKEL_CONTAINER_STYLE}>\n {/* Real header — same text and metrics as TradesUI. */}\n <div className=\"flex items-center flex-none\" style={SKEL_HEADER_STYLE}>\n <div style={SKEL_HEADER_PRICE_CELL}>Price</div>\n <div style={SKEL_HEADER_SIZE_CELL}>Size (USD)</div>\n <div style={SKEL_HEADER_AGE_CELL}>Age</div>\n </div>\n <div className=\"flex-1 min-h-0 overflow-hidden\">\n {rows.map((i) => (\n <TradeSkelRow key={`trade-${i}`} delay={i * 35} />\n ))}\n </div>\n </div>\n </>\n );\n}\n\nfunction TradesEmpty() {\n return (\n <div className=\"flex items-center justify-center h-full\">\n <span className=\"text-neutral-400 text-sm\">No recent trades</span>\n </div>\n );\n}\n\nexport function TradesWidget({\n symbol,\n limit = 100,\n onTradeClick,\n className,\n}: TradesWidgetProps) {\n const { trades, isLoading } = useTradesScript({ symbol, limit });\n\n if (isLoading) {\n return <TradesSkeleton />;\n }\n\n if (trades.length === 0) {\n return <TradesEmpty />;\n }\n\n return (\n <div className={className}>\n <TradesUI trades={trades} onTradeClick={onTradeClick} />\n </div>\n );\n}\n","import type { OrderSide } from \"../../types\";\n\n/**\n * The two TP/SL \"rows\" in the place-order form. Each row owns a Price\n * input and a Percent input; this enum tags which row a math helper\n * is operating on so the ± direction can be looked up correctly.\n */\nexport type TpSlKind = \"tp\" | \"sl\";\n\n// ── TP/SL math reference ─────────────────────────────────────────\n//\n// Both axiom and Hyperliquid express TP/SL \"%\" as **leveraged ROI**\n// on the user's margin — NOT a raw price-change percent. The\n// reference price `entry` is the **live mark price** at the moment\n// the user types (axiom refetches it per input event), not a frozen\n// quote, so the same TP % typed twice can render slightly\n// different prices across keystrokes.\n//\n// ── Side × kind direction table ──────────────────────────────────\n// long + tp target above entry (price up = profit)\n// long + sl target below entry (price down = loss)\n// short + tp target below entry (price down = profit)\n// short + sl target above entry (price up = loss)\n//\n// Both rows emit a *positive* percent when the target sits on the\n// favourable side (TP → in-profit, SL → expected adverse move). A\n// target on the wrong side surfaces a *negative* percent so the\n// user sees they've inverted the direction; we deliberately do not\n// clamp because doing so would silently rewrite a typed value.\n//\n// ── Closed-form ──────────────────────────────────────────────────\n// priceΔ = roiPct / leverage / 100\n// sign = + when (side, kind) ∈ { (long, tp), (short, sl) }\n// − otherwise\n// target = entry × (1 + sign × priceΔ)\n//\n// Inverted (price → percent), the same `sign` multiplies the\n// (target − entry) magnitude before scaling by leverage × 100.\n//\n// ── Worked examples ──────────────────────────────────────────────\n// Each example walks margin → notional → size → derived field, and\n// then verifies the round-trip P&L lands on the typed % (or vice\n// versa). Numbers are rounded to two decimals for readability.\n//\n// Reading the steps:\n// \"50% ROI / 10x leverage = 5% price\" unwinds the leverage —\n// at 10x, every 1% of price = 10% of margin, so 50% ROI only\n// needs the price to move 5%.\n// \"5% / 100 = 0.05\" converts percent to a\n// plain decimal fraction so the multiplicative `(1 + priceΔ)`\n// below produces a price, not a string-mangled scalar.\n// The two divisions chain into the one-liner\n// `priceΔ = roiPct / leverage / 100`.\n//\n// 1. Long + TP — derive Price from %\n// Setup: margin $5 · leverage 10x · entry $89.46 (SOL)\n// notional = $5 × 10 = $50\n// size = $50 / $89.46 = 0.5589 SOL\n// Input: TP % = 50 (target +50% ROI on the $5 margin)\n// pricePct = roiPct / leverage = 50 / 10 = 5 (% of price)\n// priceΔ = pricePct / 100 = 5 / 100 = 0.05 (as decimal)\n// sign = +1 (long + tp)\n// TP Price = entry × (1 + sign × priceΔ)\n// = 89.46 × (1 + 0.05) = $93.93\n// Round-trip P&L:\n// P&L = 0.5589 SOL × ($93.93 − $89.46) = +$2.50\n// ROI = $2.50 / $5 = 50% ✓\n//\n// 2. Long + SL — derive Price from %\n// Setup: margin $100 · leverage 20x · entry $80,000 (BTC)\n// notional = $100 × 20 = $2,000\n// size = $2,000 / $80,000 = 0.025 BTC\n// Input: SL % = 60 (cap loss at 60% of margin)\n// pricePct = 60 / 20 = 3 (% of price — 60% ROI / 20x)\n// priceΔ = 3 / 100 = 0.03 (decimal — 3% adverse move)\n// sign = −1 (long + sl)\n// SL Price = 80,000 × (1 − 0.03) = $77,600\n// Round-trip P&L:\n// P&L = 0.025 BTC × ($77,600 − $80,000) = −$60\n// ROI = −$60 / $100 = −60% ✓\n//\n// 3. Short + TP — derive Percent from Price (inverse direction)\n// Setup: margin $5 · leverage 10x · entry $89.46 (SOL)\n// size = 0.5589 SOL (short)\n// Input: TP Price = $80 (cover when SOL drops to $80)\n// priceΔ = sign × (target − entry) / entry\n// = (−1 × (80 − 89.46)) / 89.46 = 0.1058 (decimal)\n// pricePct = priceΔ × 100 = 10.58 (% of price)\n// TP % = pricePct × leverage = 10.58 × 10 = 105.79 (ROI %)\n// Round-trip P&L:\n// P&L = 0.5589 SOL × ($89.46 − $80) = +$5.29\n// ROI = $5.29 / $5 = 105.79% ✓\n//\n// 4. Short + SL — derive Percent from Price (inverse direction)\n// Setup: margin $40 · leverage 5x · entry $2,300 (ETH)\n// notional = $200 size = 0.0870 ETH (short)\n// Input: SL Price = $2,415 (stop loss when ETH rallies)\n// priceΔ = (+1 × (2,415 − 2,300)) / 2,300 = 0.05 (decimal)\n// pricePct = 0.05 × 100 = 5 (% of price)\n// SL % = 5 × 5 = 25 (ROI %)\n// Round-trip P&L:\n// P&L = 0.0870 ETH × ($2,300 − $2,415) = −$10\n// ROI = −$10 / $40 = −25% ✓\n//\n// ── Empirical anchor ─────────────────────────────────────────────\n// The formula was sanity-checked end-to-end against axiom's live\n// UI on 2026-05-07 (Short SOL, 10x):\n// axiom: TP Price = 80 → TP % = 105.81\n// axiom: SL Price = 90 → SL % = 7.30\n// Our formula reproduces these values to within 0.05 — the residual\n// drift is pure mark-price movement between consecutive input\n// events (axiom recomputes against `entry` = live mark every\n// keystroke; our snapshots were taken seconds apart).\n// ─────────────────────────────────────────────────────────────────\n\n/**\n * Look up the ± sign that converts the *favourable-direction*\n * priceΔ to a signed offset of `entry`. Long+TP and Short+SL are\n * \"+\" (target sits above entry); long+SL and short+TP are \"−\".\n */\nfunction signFor(side: OrderSide, kind: TpSlKind): 1 | -1 {\n if (side === \"long\" && kind === \"tp\") return 1;\n if (side === \"short\" && kind === \"sl\") return 1;\n return -1;\n}\n\n/**\n * Convert a TP/SL **price** to its leveraged-ROI **percent**.\n * Returns `undefined` when the inputs are insufficient for a\n * meaningful conversion (zero / negative entry or leverage,\n * non-finite price). Callers should leave the partner field\n * untouched in that case so a transitional state (e.g. price\n * typed before the market loads) doesn't clobber existing input.\n */\nexport function deriveTpSlPercent(\n price: number,\n entry: number,\n leverage: number,\n side: OrderSide,\n kind: TpSlKind,\n): number | undefined {\n if (!Number.isFinite(price)) return undefined;\n if (!entry || entry <= 0) return undefined;\n if (!leverage || leverage <= 0) return undefined;\n const sign = signFor(side, kind);\n const priceΔ = (sign * (price - entry)) / entry;\n return priceΔ * leverage * 100;\n}\n\n/**\n * Convert a leveraged-ROI **percent** to a TP/SL **price**.\n * Returns `undefined` for the same insufficient-input cases as\n * {@link deriveTpSlPercent}.\n */\nexport function deriveTpSlPrice(\n percent: number,\n entry: number,\n leverage: number,\n side: OrderSide,\n kind: TpSlKind,\n): number | undefined {\n if (!Number.isFinite(percent)) return undefined;\n if (!entry || entry <= 0) return undefined;\n if (!leverage || leverage <= 0) return undefined;\n const sign = signFor(side, kind);\n const priceΔ = percent / leverage / 100;\n return entry * (1 + sign * priceΔ);\n}\n\n/**\n * Round a derived TP/SL price to a sensible number of decimals\n * based on the asset's price magnitude. Mirrors the rule used by\n * the Est. Liq. Price formatter so the two values look visually\n * consistent across coins (BTC 0–1 dp, ETH 1 dp, SOL 3 dp, sub-\n * dollar perps 5 dp).\n */\nexport function roundTpSlPrice(value: number): number {\n if (!Number.isFinite(value) || value <= 0) return value;\n const magnitude = Math.floor(Math.log10(value));\n const decimals = Math.max(0, 4 - magnitude);\n const factor = 10 ** decimals;\n return Math.round(value * factor) / factor;\n}\n\n/**\n * Round a derived TP/SL percent to two decimals — matches axiom's\n * displayed precision (`105.81`, `7.30`, etc.) and avoids long-\n * tail floats like `105.81234567` polluting the input.\n */\nexport function roundTpSlPercent(value: number): number {\n if (!Number.isFinite(value)) return value;\n return Math.round(value * 100) / 100;\n}\n","import { useState, useMemo, useCallback, useEffect, useRef } from \"react\";\nimport { useForm } from \"react-hook-form\";\nimport { useMutation } from \"@tanstack/react-query\";\nimport { useAccountStateQuery } from \"../../hooks/useAccountStateQuery\";\nimport { useActiveAssetLeverageQuery } from \"../../hooks/useActiveAssetLeverageQuery\";\nimport { useAssetMetaQuery } from \"../../hooks/useAssetMetaQuery\";\nimport { useCreateOrderMutation } from \"../../hooks/useCreateOrderMutation\";\nimport { useMarketQuery } from \"../../hooks/useMarketQuery\";\nimport { usePositionsQuery } from \"../../hooks/usePositionsQuery\";\nimport type {\n OrderSide,\n OrderType,\n PlaceOrderRequest,\n PlaceOrderResult,\n} from \"../../types\";\nimport { deriveTpSlPrice } from \"./tp-sl-math\";\n\n/**\n * Initial leverage shown before the venue's configured value loads.\n * Once the {@link useActiveAssetLeverageQuery} resolves (or a position\n * arrives), the form is updated to reflect the on-chain truth.\n */\nconst FALLBACK_LEVERAGE = 20;\n\nexport type PlaceOrderFormData = {\n price?: number;\n /**\n * USDC margin the user is committing to this trade. Optional so the\n * form can render an empty input on first mount (placeholder\n * `0.0 USDC`) instead of pre-filling `0`. The notional position size\n * a venue cares about is derived as `amount * leverage`; the token\n * quantity is `(amount * leverage) / currentPrice`.\n */\n amount?: number;\n leverage: number;\n takeProfitPrice?: number;\n takeProfitPercent?: number;\n stopLossPrice?: number;\n stopLossPercent?: number;\n};\n\nexport type UsePlaceOrderFormScriptParams = {\n symbol: string;\n userAddress?: string;\n maxLeverage?: number;\n onSuccess?: () => void;\n onError?: (error: Error) => void;\n /**\n * Optional callback fired when the user confirms a new leverage value\n * in the leverage modal. The host app is expected to sign + relay the\n * `updateLeverage` action to Hyperliquid (and surface a toast). The\n * widget tracks the returned promise to drive the modal's button\n * loading state — when the promise rejects, the modal stays open so\n * the user can retry.\n *\n * When omitted, the modal falls back to a local-only update: the\n * leverage slider commits to the form state without contacting the\n * exchange.\n */\n onUpdateLeverage?: (leverage: number) => Promise<void>;\n /**\n * Optional callback that takes over order submission. When provided,\n * the form bypasses the SDK's internal `client.placeOrder` mutation\n * and forwards the enriched {@link PlaceOrderRequest} (live mark\n * price + coin-unit size + per-asset `szDecimals`) so the host can\n * sign + relay the action against the venue directly.\n *\n * Mirrors the {@link onUpdateLeverage} pattern; when omitted, the\n * widget falls back to {@link useCreateOrderMutation} → the\n * configured `IPerpetualsClient.placeOrder` (used by the LiberFi\n * adapter, which holds the signing keys server-side).\n */\n onPlaceOrder?: (request: PlaceOrderRequest) => Promise<PlaceOrderResult>;\n};\n\nexport type UsePlaceOrderFormScriptResult = {\n form: ReturnType<typeof useForm<PlaceOrderFormData>>;\n side: OrderSide;\n orderType: OrderType;\n setSide: (side: OrderSide) => void;\n setOrderType: (type: OrderType) => void;\n handleSubmit: (data: PlaceOrderFormData) => Promise<void>;\n isSubmitting: boolean;\n currentPrice?: number;\n estimatedFee: number;\n estimatedTotal: number;\n liquidationPrice?: number;\n availableMargin: number;\n accountValue: number;\n /**\n * Position the user currently holds in the symbol shown by the form.\n * Shaped to match the Axiom layout — `Long 0.00045 BTC (1.19 USDC)` —\n * by exposing the venue-precision size, base symbol, and isolated\n * margin used. `undefined` when there is no position for the symbol.\n */\n currentPosition?: {\n side: OrderSide;\n /** Absolute quantity from the venue (preserves precision when available). */\n quantity: number;\n /** Raw absolute quantity string from the venue, e.g. `\"0.00045\"`. */\n quantityRaw?: string;\n /** Isolated margin used by this position, in USDC. */\n margin: number;\n /** Base asset symbol, e.g. `\"BTC\"` for `\"BTC-USDC\"`. */\n base: string;\n };\n maxLeverage: number;\n /**\n * Leverage currently configured on the venue for `symbol`, sourced\n * from the `activeAssetData` info endpoint. Defined whether or not\n * an open position exists; `undefined` only while the query is\n * loading or when the venue does not expose this data (e.g. the\n * LiberFi adapter today).\n */\n currentLeverage?: number;\n /**\n * `true` once the venue has returned a leverage value for `symbol`.\n * The UI uses this to render a skeleton in place of the form's\n * default until the real configuration arrives, avoiding a\n * `20 → real value` flash on refresh.\n */\n isLeverageReady: boolean;\n /**\n * `true` when the user has at least one resting order on the venue\n * for `symbol`. Surfaced to the leverage modal so it can warn\n * \"open order(s) will be affected by leverage change\" — Hyperliquid\n * recomputes margin on resting orders whenever the per-asset\n * leverage changes, so the user should know before confirming.\n *\n * Sourced from the same `webData2` snapshot that drives positions\n * and balances, so it stays in sync with the rest of the form\n * without an extra REST round-trip.\n */\n hasOpenOrdersForSymbol: boolean;\n /**\n * Number of decimal places the venue uses to express the size\n * (token quantity) for `symbol`. Sourced from the `meta` info\n * endpoint; `undefined` while the query is in flight or when the\n * venue does not expose it (e.g. the LiberFi adapter today). The UI\n * uses this to format the converted token quantity badge with\n * per-asset precision (BTC → 5, SOL → 2, DOGE → 0).\n */\n szDecimals?: number;\n /** Forwarded callback (see {@link UsePlaceOrderFormScriptParams.onUpdateLeverage}). */\n onUpdateLeverage?: (leverage: number) => Promise<void>;\n};\n\nexport function usePlaceOrderFormScript({\n symbol,\n userAddress,\n maxLeverage: maxLeverageProp = 150,\n onSuccess,\n onError,\n onUpdateLeverage,\n onPlaceOrder,\n}: UsePlaceOrderFormScriptParams): UsePlaceOrderFormScriptResult {\n const [side, setSide] = useState<OrderSide>(\"long\");\n const [orderType, setOrderType] = useState<OrderType>(\"market\");\n\n // Form state. Leverage is seeded with a sensible default and then\n // overridden by the venue's configured value (Hyperliquid\n // `activeAssetData`) as soon as it loads — see the sync effects\n // further down. The form does not own leverage state; the exchange\n // does.\n //\n // `amount` is intentionally undefined on first mount so the input\n // renders its placeholder (`0.0 USDC`) instead of pre-filling `0`.\n const form = useForm<PlaceOrderFormData>({\n defaultValues: {\n amount: undefined,\n leverage: FALLBACK_LEVERAGE,\n takeProfitPrice: undefined,\n takeProfitPercent: undefined,\n stopLossPrice: undefined,\n stopLossPercent: undefined,\n },\n });\n\n const { data: marketData } = useMarketQuery({ symbol });\n\n // Per-asset venue metadata: size precision (`szDecimals`, used by\n // the UI's converted-token-quantity badge) and the leverage cap\n // (`maxLeverage`, used by the leverage modal's slider AND by the\n // liquidation-price formula). Independent of the user (no\n // `userAddress` needed) and stable for minutes at a time — the\n // client memoises the universe and TanStack caches the resolved\n // value, so re-renders don't re-fetch. When the meta hasn't\n // loaded yet (or the venue doesn't expose it, e.g. the LiberFi\n // adapter), `maxLeverage` falls back to the consumer-provided\n // prop and `liquidationPrice` resolves to `undefined` (rendered\n // as `--` by the UI).\n const { data: assetMeta } = useAssetMetaQuery({ symbol });\n const szDecimals = assetMeta?.szDecimals;\n // Resolve the effective leverage ceiling. Priority: per-asset\n // value from `meta` (Hyperliquid varies it per coin — BTC 40x,\n // ETH 25x, niche perps 3x–10x) → consumer-provided prop fallback.\n // The fallback keeps the modal usable on the first paint before\n // `useAssetMetaQuery` resolves.\n const resolvedMaxLeverage = assetMeta?.maxLeverage ?? maxLeverageProp;\n\n // Two mutations run in parallel — only one fires per submit.\n //\n // - `createOrderViaClient` → SDK's `IPerpetualsClient.placeOrder`,\n // used by the LiberFi adapter (which holds the signing keys\n // server-side and exposes a single high-level API).\n // - `placeOrderViaHost` → fires the `onPlaceOrder` callback so the\n // host app can sign + relay the action itself (used by the\n // direct-Hyperliquid setup, where the wallet lives in the\n // browser).\n //\n // Both share the same success/error/reset wiring; `isSubmitting`\n // is the OR of their pending flags so the submit button's spinner\n // works regardless of which path is active.\n const { mutateAsync: createOrderViaClient, isPending: isClientPending } =\n useCreateOrderMutation({\n onSuccess: () => {\n form.reset();\n onSuccess?.();\n },\n onError: (error) => {\n onError?.(error);\n },\n });\n\n const placeOrderViaHostMutation = useMutation<\n PlaceOrderResult,\n Error,\n PlaceOrderRequest\n >({\n mutationFn: async (request) => {\n if (!onPlaceOrder) {\n throw new Error(\n \"onPlaceOrder is not configured; cannot submit via host path\",\n );\n }\n return await onPlaceOrder(request);\n },\n onSuccess: () => {\n form.reset();\n onSuccess?.();\n },\n onError: (error: Error) => {\n onError?.(error);\n },\n });\n\n const isSubmitting = isClientPending || placeOrderViaHostMutation.isPending;\n\n const watchedValues = form.watch();\n const { amount, leverage, price } = watchedValues;\n\n const currentPrice = useMemo(() => {\n if (orderType === \"limit\" && price) {\n return price;\n }\n return marketData?.price || 0;\n }, [orderType, price, marketData?.price]);\n\n // Notional size of the position in USDC: the user commits `amount`\n // USDC of margin, leveraged up to `amount * leverage`. Both fee and\n // total are computed off the notional, not the margin alone.\n const notional = useMemo(() => {\n if (!amount || amount <= 0 || !leverage) return 0;\n return amount * leverage;\n }, [amount, leverage]);\n\n const estimatedFee = useMemo(() => {\n if (!notional) return 0;\n const feeRate = 0.0005;\n return notional * feeRate;\n }, [notional]);\n\n const estimatedTotal = useMemo(() => {\n if (!notional) return 0;\n return notional + estimatedFee;\n }, [notional, estimatedFee]);\n\n // Estimated liquidation price for a fresh isolated position.\n //\n // ── Setup ─────────────────────────────────────────────────────\n // m margin (USDC the user commits)\n // lev leverage (e.g. 20)\n // p entry price\n // N = m × lev position notional in USDC\n // q = N / p position size in coin units\n // l = 1 / (2 × maxLeverage) per-asset maintenance margin rate;\n // Hyperliquid pins maintenance to half\n // of the initial margin rate cap (BTC\n // maxLev 40x → initial 2.5%, mmr 1.25%)\n //\n // ── Liquidation condition ─────────────────────────────────────\n // A position is liquidated when equity drops to the maintenance\n // requirement, where the requirement is computed off the\n // *current* notional (q × p_liq), not the entry notional:\n //\n // long : m + q × (p_liq - p) = q × p_liq × l\n // short : m − q × (p_liq - p) = q × p_liq × l\n //\n // Substituting q = m·lev/p, dividing by m, and letting\n // x = p_liq / p, both sides solve to:\n //\n // long : x = (1 − 1/lev) / (1 − l) ⇒ 1 − (1/lev − l)/(1 − l)\n // short : x = (1 + 1/lev) / (1 + l) ⇒ 1 + (1/lev − l)/(1 + l)\n //\n // ── Intuition ────────────────────────────────────────────────\n // • `1/lev` initial margin rate — price has to move this far\n // against you for equity to reach zero.\n // • `l` maintenance margin rate — but liquidation fires\n // *before* equity hits zero, leaving only a buffer\n // of `1/lev − l` to burn through.\n // • `/(1 ∓ l)` closed-form correction for the implicit equation:\n // the maintenance requirement scales with `p_liq`\n // itself (q × p_liq × l), so `l` ends up in the\n // denominator after solving.\n //\n // ── Why we gate on `maxLeverage` ─────────────────────────────\n // Without per-asset `l`, the only honest fallback is \"--\". A\n // hardcoded mmr (the previous 0.5%) is wrong for nearly every\n // coin — BTC's true `l` ≈ 1.25%, SOL's ≈ 2.5%, niche perps go up\n // to 16% — and produces estimates that drift several percent\n // from the venue's actual liquidation level. We'd rather show\n // `--` for a beat than mislead the user.\n const liquidationPrice = useMemo(() => {\n if (!amount || !currentPrice || !leverage || leverage === 1)\n return undefined;\n if (!assetMeta?.maxLeverage) return undefined;\n\n const l = 1 / (2 * assetMeta.maxLeverage);\n const offset = (1 / leverage - l) / (side === \"long\" ? 1 - l : 1 + l);\n return side === \"long\"\n ? currentPrice * (1 - offset)\n : currentPrice * (1 + offset);\n }, [amount, currentPrice, leverage, side, assetMeta?.maxLeverage]);\n\n // Real account / position data sourced from Hyperliquid `clearinghouseState`.\n // Falls back to 0 when the wallet isn't connected (the query stays disabled\n // until `userAddress` is set; see `usePositionsQuery`'s internal guard).\n const { data: positionsData } = usePositionsQuery({\n userAddress,\n symbol,\n });\n\n const accountValue = positionsData?.totalEquity ?? 0;\n const availableMargin = positionsData?.availableBalance ?? 0;\n const currentPosition = useMemo<\n UsePlaceOrderFormScriptResult[\"currentPosition\"]\n >(() => {\n const pos = positionsData?.positions?.[0];\n if (!pos) return undefined;\n // Symbols come from the venue as `BASE-USDC` (e.g. `BTC-USDC`).\n // Fall back to the full symbol if the format ever changes so the\n // UI never renders an empty string.\n const base = pos.symbol.includes(\"-\")\n ? pos.symbol.split(\"-\")[0]\n : pos.symbol;\n return {\n side: pos.side,\n quantity: pos.quantity,\n quantityRaw: pos.quantityRaw,\n margin: pos.margin,\n base,\n };\n }, [positionsData?.positions]);\n\n // Read open orders for `symbol` from the unified WS-driven account\n // snapshot, not a `useOrdersQuery({ userAddress, symbol })` call.\n // The `useAccountStateSubscription` hook writes to the\n // `[\"perps\", \"orders\", userAddress, \"\"]` slot (no symbol filter);\n // querying with a `symbol` would land in a different cache slot\n // and fall through to a REST fetch, defeating the WS migration.\n // Reading from `useAccountStateQuery` keeps us on the live channel\n // and we filter client-side — at most a handful of items.\n const { data: account } = useAccountStateQuery({\n userAddress,\n enabled: !!userAddress,\n });\n const hasOpenOrdersForSymbol = useMemo(() => {\n if (!account?.openOrders?.length) return false;\n return account.openOrders.some((o) => o.symbol === symbol);\n }, [account?.openOrders, symbol]);\n\n // Read the user's per-asset leverage from the venue's\n // `activeAssetData` endpoint. This is the canonical source — it\n // works whether or not an open position exists, so a page refresh\n // always shows the latest leverage the user pushed via\n // `updateLeverage`. The position object also carries leverage, but\n // only when a position is open; `activeAssetData` covers both cases\n // and is therefore the single source of truth.\n const { data: activeAssetLeverage } = useActiveAssetLeverageQuery({\n userAddress,\n symbol,\n });\n const currentLeverage = activeAssetLeverage?.value;\n\n // Single gate for the leverage display:\n // - When the wallet is connected, we wait for the venue's\n // configured leverage to arrive before showing a value. This\n // avoids a `20 → real value` flash on refresh — the UI renders\n // a skeleton in the meantime.\n // - When the wallet is NOT connected, there is no per-user\n // leverage to fetch and the query stays disabled. Rendering a\n // skeleton in that case is wrong (it would never resolve), so\n // we treat the form's default (`FALLBACK_LEVERAGE`, 20x) as\n // canonical and show it immediately.\n //\n // The first time the user signs in we re-evaluate, and the\n // skeleton appears only if the query is genuinely in flight.\n const isLeverageReady = !userAddress || currentLeverage !== undefined;\n\n // Sync the form's `leverage` field with the venue's configured value\n // whenever it arrives (or whenever the user switches symbol). Only\n // runs once per symbol to avoid clobbering manual adjustments the\n // user makes via the leverage modal between syncs.\n const lastSyncedSymbolRef = useRef<string | null>(null);\n useEffect(() => {\n if (lastSyncedSymbolRef.current === symbol) return;\n if (currentLeverage && currentLeverage > 0) {\n form.setValue(\"leverage\", currentLeverage);\n lastSyncedSymbolRef.current = symbol;\n }\n }, [symbol, currentLeverage, form]);\n\n // Reset the per-symbol sync guard whenever the user navigates to a\n // different symbol so the new symbol's leverage payload is allowed\n // to overwrite the form value.\n useEffect(() => {\n lastSyncedSymbolRef.current = null;\n }, [symbol]);\n\n // Hard ceiling on Buy Amount: the user can never spend more margin\n // than they have. If they paste / type a value larger than the\n // available margin we rewrite the field in place — the UI doesn't\n // need to do anything, the input is bound to this same form state.\n //\n // For \"below zero\" we deliberately do NOT snap to `0`. Snapping to\n // a hard `0` competes with two legitimate user actions:\n // - Clearing the input (select-all + delete) should leave it\n // empty so the placeholder (`0.0 USDC`) can render.\n // - Dragging the slider all the way to 0% should also clear the\n // field, not pin it to a literal \"0\".\n // Both flows go through the form as `undefined`. So we only react\n // to a *strictly negative* number that survived the keyboard guard\n // (e.g. a paste) and clear it the same way — by writing\n // `undefined`, which the RHNumberInput renders as empty.\n useEffect(() => {\n if (typeof amount !== \"number\" || Number.isNaN(amount)) return;\n if (amount < 0) {\n form.setValue(\"amount\", undefined, {\n shouldValidate: false,\n shouldDirty: false,\n });\n return;\n }\n if (availableMargin > 0 && amount > availableMargin) {\n form.setValue(\"amount\", availableMargin, {\n shouldValidate: false,\n shouldDirty: true,\n });\n }\n }, [amount, availableMargin, form]);\n\n const handleSubmit = useCallback(\n async (data: PlaceOrderFormData) => {\n if (!userAddress) {\n throw new Error(\"User address is required\");\n }\n if (!data.amount || data.amount <= 0) {\n throw new Error(\"Amount is required\");\n }\n\n const finalPrice = orderType === \"limit\" ? data.price : undefined;\n\n // Submit-time fallback. The UI keeps Price ↔ Percent in\n // lock-step on every keystroke, so under normal conditions\n // both fields land here populated. The fallback covers the\n // edge case where the partner couldn't be derived at typing\n // time (e.g. mark price hadn't loaded yet) — we recompute\n // here using the SAME leveraged-ROI formula the UI uses,\n // sourced from `tp-sl-math.ts`. Order matters: prefer the\n // user-typed price; only synthesise from percent when the\n // price field is blank. Submitting with neither field set\n // leaves the corresponding bracket order out of the request,\n // which is the right thing to do since the user explicitly\n // declined to set one.\n let takeProfitPrice = data.takeProfitPrice;\n let stopLossPrice = data.stopLossPrice;\n\n if (\n !takeProfitPrice &&\n data.takeProfitPercent &&\n data.takeProfitPercent > 0 &&\n currentPrice\n ) {\n takeProfitPrice = deriveTpSlPrice(\n data.takeProfitPercent,\n currentPrice,\n data.leverage,\n side,\n \"tp\",\n );\n }\n\n if (\n !stopLossPrice &&\n data.stopLossPercent &&\n data.stopLossPercent > 0 &&\n currentPrice\n ) {\n stopLossPrice = deriveTpSlPrice(\n data.stopLossPercent,\n currentPrice,\n data.leverage,\n side,\n \"sl\",\n );\n }\n\n if (onPlaceOrder) {\n // Host-signed path: gate on the data the host hook needs.\n // Both `currentPrice` and `szDecimals` are populated by the\n // SDK's own queries, so this only fails if the user submits\n // before the first market / meta refetch lands — in which\n // case retrying once those are ready is the right UX.\n if (!currentPrice || currentPrice <= 0) {\n throw new Error(\n \"Mark price is unavailable; please retry once the market loads\",\n );\n }\n if (szDecimals === undefined) {\n throw new Error(\n \"Asset metadata is loading; please retry in a moment\",\n );\n }\n\n // Coin-unit position size. Matches the converted-quantity\n // badge the user sees beside the amount input. Done here\n // (not in the host hook) so consumers can stay venue-only\n // and don't need to reach into the form's mark price.\n const size = (data.amount * data.leverage) / currentPrice;\n\n await placeOrderViaHostMutation.mutateAsync({\n symbol,\n side,\n orderType,\n amount: data.amount,\n price: finalPrice,\n leverage: data.leverage,\n takeProfitPrice,\n stopLossPrice,\n userAddress,\n size,\n refPrice: currentPrice,\n szDecimals,\n });\n return;\n }\n\n // Default path: SDK client owns submission (LiberFi adapter).\n await createOrderViaClient({\n symbol,\n side,\n orderType,\n amount: data.amount,\n price: finalPrice,\n leverage: data.leverage,\n takeProfitPrice,\n stopLossPrice,\n userAddress,\n });\n },\n [\n symbol,\n side,\n orderType,\n currentPrice,\n szDecimals,\n userAddress,\n onPlaceOrder,\n placeOrderViaHostMutation,\n createOrderViaClient,\n ],\n );\n\n return {\n form,\n side,\n orderType,\n setSide,\n setOrderType,\n handleSubmit,\n isSubmitting,\n currentPrice,\n estimatedFee,\n estimatedTotal,\n liquidationPrice,\n availableMargin,\n accountValue,\n currentPosition,\n maxLeverage: resolvedMaxLeverage,\n currentLeverage,\n isLeverageReady,\n hasOpenOrdersForSymbol,\n szDecimals,\n onUpdateLeverage,\n };\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport type { CSSProperties } from \"react\";\nimport type { UseFormReturn } from \"react-hook-form\";\nimport {\n ModalContent,\n RHForm,\n RHNumberInput,\n Slider,\n Spinner,\n StyledModal,\n StyledTooltip,\n XCloseIcon,\n} from \"@liberfi.io/ui\";\nimport { useAuthCallback } from \"@liberfi.io/wallet-connector\";\nimport { shimmer, ShimmerStyle } from \"../../internal/skeleton\";\nimport type { OrderSide, OrderType } from \"../../types\";\nimport type { PlaceOrderFormData } from \"./place-order-form.script\";\nimport {\n deriveTpSlPercent,\n deriveTpSlPrice,\n roundTpSlPercent,\n roundTpSlPrice,\n type TpSlKind,\n} from \"./tp-sl-math\";\n\n/** Brand primary green; mirrors the color used elsewhere in the form. */\nconst BRAND_PRIMARY = \"#C7FF2E\";\n/** Long side accent — used wherever Long/Short need symmetric styling. */\nconst SIDE_LONG_COLOR = BRAND_PRIMARY;\n/** Short side accent — Hyperliquid orange. */\nconst SIDE_SHORT_COLOR = \"#F76816\";\n/**\n * Warning / risk text color — same hue as the short-side accent so\n * the form's loss/risk vocabulary stays visually consistent.\n * Applied via inline `style` rather than `text-[#…]` because\n * Tailwind 4 only registers arbitrary-value classes it finds in\n * scanned source — and the consumer's `@source` glob points at the\n * tsup-compiled dist files where the class name may not survive\n * minification verbatim, leaving the hex unmatched and the text\n * falling back to the default zinc color. Inline style sidesteps\n * that entire scan path.\n */\nconst BRAND_DANGER = SIDE_SHORT_COLOR;\n\n/**\n * Append an 8-bit alpha to a `#RRGGBB` hex string.\n *\n * Used by the Available Margin capsule to layer translucent fills over\n * the brand primary without pulling in a CSS-vars + `color-mix` setup —\n * the form is already a single styled component island, so a tiny pure\n * helper keeps the capsule readable inline.\n *\n * @param hex `#RRGGBB` (case-insensitive). Returned as-is when the\n * caller passed something else; we don't try to parse\n * `rgb()`/`hsl()` values.\n * @param alpha 0–255 alpha byte (e.g. `0x1A` ≈ 10%, `0x33` ≈ 20%).\n */\nfunction withAlpha(hex: string, alpha: number): string {\n if (!/^#[0-9a-fA-F]{6}$/.test(hex)) return hex;\n const a = Math.max(0, Math.min(255, Math.round(alpha)));\n return `${hex}${a.toString(16).padStart(2, \"0\").toUpperCase()}`;\n}\n\n/**\n * Hyperliquid-hosted icon CDN. The path is `${tokenSymbol}.svg` for\n * every listed asset. The form falls back silently (icon hidden) when\n * a symbol isn't covered, matching the consumer's `CoinSelectorBar`\n * behaviour. We don't expose this as a prop yet because every\n * consumer of this widget points at Hyperliquid; if a different venue\n * ever ships, lift this to a `tokenIconUrl` prop.\n */\nconst HYPERLIQUID_ICON_CDN = \"https://app.hyperliquid.xyz/coins\";\n\n/**\n * Hyperliquid's documented minimum order size, expressed in USDC of\n * notional position value (margin × leverage). It's a venue-wide\n * constant, not per-asset, and isn't surfaced by any /info endpoint —\n * the platform documents it in its public SDK docs and we mirror the\n * constant here. Update this single line if Hyperliquid ever raises\n * the floor.\n *\n * The threshold the input is actually compared against is the\n * **margin** equivalent of this notional at the *current leverage*,\n * computed at validation time as `MIN_NOTIONAL_USDC / leverage`. That\n * derivation lives in the submit-state machine because `leverage`\n * changes whenever the user opens the leverage modal — a leverage-\n * agnostic margin floor would either let small orders through at low\n * leverage (venue rejects) or block legitimate orders at high\n * leverage (false negative).\n */\nconst MIN_NOTIONAL_USDC = 10;\n\n/**\n * Sanitise a user-typed string into the canonical \"valid partial\n * number\" form. Drops everything that isn't a digit or a dot, and\n * collapses any extra dots — so `1..2`, `1.2.3`, `abc1.2def` all\n * become `1.2`. Returns the cleaned string verbatim (callers decide\n * whether to commit it as a number or keep it as a transitional\n * `\"2.\"` text state).\n */\nfunction sanitiseAmountInput(raw: string): string {\n const cleaned = raw.replace(/[^\\d.]/g, \"\");\n const parts = cleaned.split(\".\");\n return parts.length > 1 ? `${parts[0]}.${parts.slice(1).join(\"\")}` : cleaned;\n}\n\n/**\n * Inline skeleton block used to placehold a few characters of text\n * (e.g. the leverage value `20x`). Composes the shared {@link shimmer}\n * style with the size + `inline-block` needed to slot inside the\n * leverage button's flex row. All visual tuning (base color, sweep\n * gradient, animation timing) lives in `internal/skeleton.tsx` so the\n * coin-info, orderbook, trades, and place-order placeholders share a\n * single source of truth.\n */\nconst inlineTextSkeleton: CSSProperties = {\n ...shimmer,\n display: \"inline-block\",\n width: 28,\n height: 14,\n borderRadius: 4,\n};\n\nexport type PlaceOrderFormUIProps = {\n methods: UseFormReturn<PlaceOrderFormData>;\n side: OrderSide;\n orderType: OrderType;\n onSideChange: (side: OrderSide) => void;\n onOrderTypeChange: (type: OrderType) => void;\n onSubmit: (data: PlaceOrderFormData) => Promise<void>;\n isSubmitting: boolean;\n symbol: string;\n currentPrice?: number;\n estimatedFee: number;\n estimatedTotal: number;\n liquidationPrice?: number;\n availableMargin: number;\n accountValue: number;\n /**\n * Position the user currently holds in the symbol shown by the form.\n * Shaped to match the Axiom layout — `Long 0.00045 BTC (1.19 USDC)`.\n * `undefined` when there is no open position for `symbol`, in which\n * case the row falls back to `--`.\n */\n currentPosition?: {\n side: \"long\" | \"short\";\n quantity: number;\n quantityRaw?: string;\n margin: number;\n base: string;\n };\n maxLeverage: number;\n /**\n * Whether the leverage value can be displayed. When `false` the\n * leverage button shows a skeleton instead of the form's default,\n * to avoid flashing `20x` before the venue's per-asset configuration\n * is loaded. Defaults to `true` for backwards compatibility.\n */\n isLeverageReady?: boolean;\n /**\n * Whether the user has at least one resting order on `symbol`.\n * Drives the leverage modal's \"Open order(s) will be affected\"\n * advisory — Hyperliquid recomputes resting-order margin when the\n * per-asset leverage changes, so the user should see this before\n * confirming. Purely informational; does NOT block the update.\n */\n hasOpenOrdersForSymbol?: boolean;\n /**\n * Number of decimal places the venue uses for the size of `symbol`\n * (e.g. BTC → 5, ETH → 4, SOL → 2, DOGE → 0). Sourced from\n * Hyperliquid's `meta` info endpoint via `useAssetMetaQuery`. The\n * UI uses this to format the converted token quantity badge with\n * per-asset precision. When omitted the form falls back to an\n * adaptive heuristic that keeps the badge readable across coins\n * with very different price magnitudes.\n */\n szDecimals?: number;\n /**\n * Optional callback fired when the user clicks the \"Add More Funds\"\n * button (typically wired by the host app to open a deposit dialog).\n * The button is hidden when this prop is omitted, so consumers that\n * don't support a deposit flow don't render a dead control.\n */\n onAddFunds?: () => void;\n /**\n * Optional callback fired when the user confirms a new leverage in\n * the leverage modal. The widget tracks the returned promise to\n * drive the modal's button loading state — when it rejects the\n * modal stays open so the caller can retry. When omitted, the\n * leverage value is committed to the form locally without contacting\n * the exchange.\n */\n onUpdateLeverage?: (leverage: number) => Promise<void>;\n};\n\nfunction formatNumber(num: number, decimals: number = 2): string {\n return num.toFixed(decimals);\n}\n\n/**\n * Format a USD price for the \"Est. Liq. Price\" line.\n *\n * Mirrors the venue convention used by Hyperliquid's hosted UI and\n * Axiom — a `$` prefix, thousand separators, and roughly five\n * significant figures, so the precision tracks the asset's\n * magnitude (BTC `$79,771` → 0 decimals, ETH `$2,267.5` → 1\n * decimal, SOL `$96.524` → 3 decimals).\n *\n * Decimals are derived from `floor(log10(value))` instead of an\n * `if/else` ladder so the rule is uniform across price ranges,\n * including sub-dollar perps where `value < 1` and we keep more\n * decimals to preserve significance.\n */\nfunction formatLiqPrice(value: number): string {\n if (!Number.isFinite(value) || value <= 0) return \"--\";\n const magnitude = Math.floor(Math.log10(value));\n const decimals = Math.max(0, 4 - magnitude);\n return `$${new Intl.NumberFormat(\"en-US\", {\n minimumFractionDigits: decimals,\n maximumFractionDigits: decimals,\n }).format(value)}`;\n}\n\n/**\n * Hyperliquid's `updateLeverage` schema rejects 0, so 1x is the\n * absolute floor. The upper bound is per-asset (BTC 40x, ETH 25x,\n * niche perps as low as 3x) and flows in via `maxLeverage`.\n */\nconst LEVERAGE_MIN = 1;\n\n/**\n * Build orientation tick marks for the leverage slider. The visible\n * range is `[LEVERAGE_MIN, max]`; we pin 1x and `max` as anchors and\n * fill in three quartile marks rounded to a \"nice\" integer (multiples\n * of 5 once we're above 10) so the labels stay legible across\n * different per-asset caps. The set is deduped and sorted, so\n * degenerate caps (e.g. max = 3) collapse cleanly to `[1, 2, 3]`.\n */\nfunction buildLeverageMarks(max: number): { value: number; label: string }[] {\n const ceiling = Math.max(LEVERAGE_MIN, Math.floor(max));\n const niceRound = (n: number): number => {\n const v = Math.round(n);\n if (v <= 10) return Math.max(LEVERAGE_MIN, v);\n return Math.round(v / 5) * 5;\n };\n const ticks = new Set<number>([LEVERAGE_MIN, ceiling]);\n for (const pct of [0.25, 0.5, 0.75]) {\n const t = niceRound(ceiling * pct);\n if (t > LEVERAGE_MIN && t < ceiling) ticks.add(t);\n }\n return Array.from(ticks)\n .sort((a, b) => a - b)\n .map((value) => ({ value, label: `${value}x` }));\n}\n\nfunction LeverageModal({\n isOpen,\n initialLeverage,\n maxLeverage,\n coinName,\n hasOpenPosition,\n hasOpenOrders,\n onConfirm,\n onUpdate,\n onClose,\n}: {\n isOpen: boolean;\n initialLeverage: number;\n /**\n * Per-asset leverage cap from the venue's universe metadata.\n * Drives the slider's `maxValue` and the rightmost tick mark so\n * the user can't pick a value the venue would reject.\n */\n maxLeverage: number;\n /**\n * Base asset name (e.g. `\"BTC\"`) used in the advisory copy. The\n * widget derives this from `currentPosition.base` or strips\n * `-USDC` from `symbol`, so the warning reads `... for BTC ...`\n * regardless of which path produced it.\n */\n coinName: string;\n /**\n * `true` when the user already holds a position on `symbol`.\n * Hyperliquid rejects `updateLeverage` while a position is open,\n * so the modal blocks the update path: the slider is disabled,\n * the CTA is greyed out, and an explanatory advisory is shown.\n */\n hasOpenPosition: boolean;\n /**\n * `true` when the user has at least one resting order on `symbol`.\n * Purely informational — the venue still accepts the update, but\n * resting-order margin will be recomputed under the new leverage,\n * so the modal surfaces a note before confirmation.\n */\n hasOpenOrders: boolean;\n /**\n * Called immediately on confirm with the new leverage value. The\n * modal uses this to commit the value to the form regardless of\n * whether `onUpdate` is provided.\n */\n onConfirm: (v: number) => void;\n /**\n * Optional async hook for relaying the change to the exchange (sign\n * + POST /exchange `updateLeverage`). When provided, the modal\n * tracks the returned promise to drive the button's loading state\n * and only closes on resolve. On reject the modal stays open so\n * the caller can retry. The caller is responsible for surfacing\n * success / error toasts; the SDK does not toast on its own.\n */\n onUpdate?: (v: number) => Promise<void>;\n onClose: () => void;\n}) {\n // The venue cap can legitimately be < `LEVERAGE_MIN` only if the\n // upstream meta is malformed; clamp defensively so the slider\n // bounds stay valid.\n const ceiling = Math.max(LEVERAGE_MIN, Math.floor(maxLeverage));\n // Modal-local state: only commit to the form when the user hits\n // \"Update Leverage\". Lets them cancel via X / backdrop without side\n // effects, matching the reference design's modal semantics.\n const [draft, setDraft] = useState(\n Math.max(LEVERAGE_MIN, Math.min(initialLeverage, ceiling)),\n );\n const [pending, setPending] = useState(false);\n\n // Re-seed the draft when the modal reopens with a new initial value\n // (e.g. the user changed symbol and the on-chain leverage refreshed)\n // OR when the per-asset ceiling drops below the previously-drafted\n // value (e.g. user switches from a 40x asset to a 5x one).\n useEffect(() => {\n if (isOpen) {\n setDraft(Math.max(LEVERAGE_MIN, Math.min(initialLeverage, ceiling)));\n setPending(false);\n }\n }, [isOpen, initialLeverage, ceiling]);\n\n const marks = useMemo(() => buildLeverageMarks(ceiling), [ceiling]);\n\n const handleConfirm = useCallback(async () => {\n if (pending) return;\n if (!onUpdate) {\n onConfirm(draft);\n onClose();\n return;\n }\n setPending(true);\n try {\n await onUpdate(draft);\n onConfirm(draft);\n onClose();\n } catch {\n // Caller already toasted; keep the modal open so the user can\n // pick a different value or retry.\n setPending(false);\n }\n }, [pending, onUpdate, draft, onConfirm, onClose]);\n\n // Auth-gate `handleConfirm` (not `onUpdate`). The wrap order matters:\n // wrapping `onUpdate` would let the unauth case land *inside* the\n // try block as a resolved-with-undefined promise, which the modal\n // would then misread as \"exchange accepted\" and incorrectly commit\n // the draft + close. Wrapping `handleConfirm` short-circuits the\n // entire click handler before `setPending` / the try block run, so\n // the modal stays in its pre-click state (no spinner, still open)\n // while `signIn()` fires in the background. After auth completes\n // the user clicks \"Update Leverage\" again and the full flow runs.\n const guardedConfirm = useAuthCallback(handleConfirm);\n\n return (\n <StyledModal\n isOpen={isOpen}\n onOpenChange={(next) => {\n // Block backdrop / Esc dismiss while the update is in flight so\n // the user doesn't accidentally drop the request mid-signature.\n if (pending) return;\n if (!next) onClose();\n }}\n size=\"md\"\n hideCloseButton\n backdrop=\"blur\"\n classNames={{\n base: \"!bg-[#18181b] !rounded-[14px] !border !border-[rgba(39,39,42,1)] !shadow-[0_25px_50px_-12px_rgba(0,0,0,0.5)] max-w-[420px]\",\n body: \"!p-0\",\n }}\n >\n <ModalContent>\n <div className=\"flex flex-col\">\n {/* Header — mirrors DepositHyperliquidUsdcModal layout */}\n <div className=\"flex items-center justify-between px-5 pt-5 pb-2\">\n <h3 className=\"text-base font-semibold text-white m-0\">\n Adjust Leverage\n </h3>\n <button\n type=\"button\"\n onClick={onClose}\n disabled={pending}\n aria-label=\"Close\"\n className=\"p-1 rounded-[10px] hover:bg-[rgba(39,39,42,0.5)] text-zinc-400 hover:text-white transition-colors cursor-pointer disabled:cursor-not-allowed disabled:opacity-50\"\n >\n <XCloseIcon width={16} height={16} />\n </button>\n </div>\n\n <div className=\"px-5 pb-5 pt-2 flex flex-col gap-4\">\n {/* Two independent advisories:\n - Position-blocking (red) — Hyperliquid rejects\n `updateLeverage` while a position is open. Replaces\n the default gray description so the user isn't told\n to \"manage exposure\" when they can't actually\n proceed. Gates the slider + CTA on it.\n - Open-orders advisory (red) — informational only;\n stacks below the gray description (or below the\n position warning) and the venue still accepts the\n update. Margin on resting orders is recomputed\n under the new leverage, hence the warning. */}\n <div className=\"flex flex-col gap-1\">\n {hasOpenPosition ? (\n <p\n className=\"text-[13px] leading-[18px] m-0\"\n style={{ color: BRAND_DANGER }}\n >\n You may not update leverage for {coinName} while a position is\n open.\n </p>\n ) : (\n <p className=\"text-[13px] text-zinc-400 leading-[18px] m-0\">\n Adjust your leverage to manage your exposure. Higher leverage\n increases both potential profits and risks.\n </p>\n )}\n {hasOpenOrders && (\n <p\n className=\"text-[13px] leading-[18px] m-0\"\n style={{ color: BRAND_DANGER }}\n >\n Open order(s) for {coinName} will be affected by leverage\n change.\n </p>\n )}\n </div>\n\n {/* Slider with tick marks */}\n <div\n className=\"perp-leverage-slider\"\n style={{ padding: \"8px 6px 4px\" }}\n >\n {/* HeroUI Slider colors are theme-driven; tsup-compiled template\n literals would be invisible to Tailwind's static scan, so we\n tint the track / filler / thumb via plain CSS overrides keyed\n on a wrapper className. */}\n <style>{`\n .perp-leverage-slider [data-slot=\"track\"] { background-color: rgba(255,255,255,0.08) !important; }\n .perp-leverage-slider [data-slot=\"filler\"] { background-color: ${BRAND_PRIMARY} !important; }\n .perp-leverage-slider [data-slot=\"thumb\"] { background-color: ${BRAND_PRIMARY} !important; }\n .perp-leverage-slider [data-slot=\"thumb\"]::after { background-color: ${BRAND_PRIMARY} !important; }\n .perp-leverage-slider [data-slot=\"mark\"] { color: #6b6b6b !important; }\n `}</style>\n <Slider\n value={[draft]}\n onChange={(value: number | number[]) =>\n setDraft(Array.isArray(value) ? value[0] : value)\n }\n isDisabled={pending || hasOpenPosition}\n minValue={LEVERAGE_MIN}\n maxValue={ceiling}\n step={1}\n marks={marks}\n aria-label=\"Leverage\"\n />\n </div>\n\n {/* Selected value */}\n <div className=\"text-sm text-white font-medium\">\n Leverage: {draft}x\n </div>\n\n {/* Confirm button — matches the deposit modal CTA shape.\n Uses `guardedConfirm` so signed-out users get an auth\n prompt instead of a no-op click. When a position is\n open the venue rejects the update, so the button is\n replaced with a permanently-disabled \"Unable to update\n leverage\" CTA — matching the reference UX. */}\n <button\n type=\"button\"\n onClick={() => void guardedConfirm()}\n disabled={pending || hasOpenPosition}\n className=\"cursor-pointer mt-1 w-full h-12 rounded-[12px] font-medium text-black bg-[#C7FF2E] hover:bg-[#b6ed1c] active:bg-[#a6d913] transition-colors flex items-center justify-center gap-2 disabled:bg-[#3f3f46] disabled:text-zinc-500 disabled:cursor-not-allowed\"\n >\n {pending && <Spinner size=\"sm\" color=\"current\" />}\n {hasOpenPosition\n ? \"Unable to update leverage\"\n : pending\n ? \"Updating Leverage...\"\n : \"Update Leverage\"}\n </button>\n </div>\n </div>\n </ModalContent>\n </StyledModal>\n );\n}\n\n/**\n * Live-syncing text input bound to the form's `amount` field.\n *\n * Two mutable values:\n * - `inputText` — the visible string. Holds transitional states\n * React can't represent as a number (`\"\"`, `\".\"`, `\"5.\"`).\n * - `field.value` (RHF) — the parsed number, or `undefined` for\n * \"no input\". This is what every other consumer of the form\n * (slider, clamp effect, submit handler) reads.\n *\n * Sync rules:\n * - User types → sanitise, store as `inputText`, push parsed\n * number to RHF (or `undefined` for empty).\n * - RHF changes externally (slider drag, clamp effect) AND the\n * input is NOT focused → re-derive `inputText` from the new\n * number. Skipping the sync while focused preserves transitional\n * text like `\"5.\"` while the user is mid-keystroke.\n *\n * Why a subcomponent: scoping `useState` here keeps the input's\n * local string state out of the parent's render tree, so cycles\n * triggered by `methods.watch` higher up don't re-evaluate this\n * input's effects.\n */\nfunction BuyAmountInput({\n methods,\n}: {\n methods: UseFormReturn<PlaceOrderFormData>;\n}) {\n const formValue = methods.watch(\"amount\");\n const numericValue =\n typeof formValue === \"number\" && Number.isFinite(formValue)\n ? formValue\n : undefined;\n\n // Seed the input text from whatever's already in the form (may\n // come from `defaultValues`, navigation back into the page, or a\n // prior session).\n const [inputText, setInputText] = useState<string>(() =>\n numericValue !== undefined ? String(numericValue) : \"\",\n );\n const inputRef = useRef<HTMLInputElement | null>(null);\n\n // Sync inputText from the form value when an external source\n // (slider drag, the script's clamp effect, programmatic reset, …)\n // updates it.\n //\n // Naive rule \"skip sync while focused\" is too coarse: it preserves\n // transitional text (`\"5.\"` mid-typing → form holds `5`) but also\n // suppresses *legitimate* overrides like the script's\n // `amount > availableMargin` clamp. After typing `999` the user\n // would see the visible input keep `999` even though the form has\n // already snapped to the cap — and that mismatch is exactly the\n // bug Axiom side-steps by aggressively overwriting the field on\n // every over-cap keystroke.\n //\n // The right rule is \"skip sync only when the visible text already\n // *agrees* numerically with the form value\". `\"5.\"` parses to `5`\n // and the form holds `5` — values agree, leave the dot in place.\n // `\"999\"` parses to `999` and the form holds `5.343352` — values\n // disagree, the form has won, mirror it back to the visible\n // input. While unfocused we always sync (the user isn't typing\n // anything we'd be in danger of clobbering).\n useEffect(() => {\n const isFocused =\n typeof document !== \"undefined\" &&\n document.activeElement === inputRef.current;\n setInputText((prev) => {\n const parsedPrev = parseFloat(prev);\n const valuesAgree =\n Number.isFinite(parsedPrev) && parsedPrev === numericValue;\n if (isFocused && valuesAgree) return prev;\n const next = numericValue !== undefined ? String(numericValue) : \"\";\n return prev === next ? prev : next;\n });\n }, [numericValue]);\n\n const handleChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const cleaned = sanitiseAmountInput(e.target.value);\n setInputText(cleaned);\n\n if (cleaned === \"\" || cleaned === \".\") {\n // Empty or just-a-dot — no committable number yet. Push\n // `undefined` to the form so the slider stays at 0% and any\n // submit-state machine that reads `amount` sees \"no value\".\n methods.setValue(\"amount\", undefined, {\n shouldValidate: false,\n shouldDirty: true,\n });\n return;\n }\n const parsed = Number(cleaned);\n if (!Number.isFinite(parsed)) return;\n methods.setValue(\"amount\", parsed, {\n shouldValidate: false,\n shouldDirty: true,\n });\n },\n [methods],\n );\n\n const handleKeyDownCapture = useCallback(\n (e: React.KeyboardEvent<HTMLInputElement>) => {\n // Block sign / scientific-notation keys at source. Pasted\n // signed/exponent strings are still neutralised by\n // `sanitiseAmountInput` in onChange.\n if (e.key === \"-\" || e.key === \"+\" || e.key === \"e\" || e.key === \"E\") {\n e.preventDefault();\n e.stopPropagation();\n }\n },\n [],\n );\n\n return (\n <input\n ref={inputRef}\n type=\"text\"\n inputMode=\"decimal\"\n pattern=\"[0-9.]*\"\n autoComplete=\"off\"\n autoCorrect=\"off\"\n spellCheck={false}\n name=\"amount\"\n placeholder=\"0.0 USDC\"\n aria-label=\"Buy amount\"\n className=\"flex-1 min-w-0 bg-transparent border-none outline-none w-full\"\n style={{\n color: \"#ffffff\",\n fontSize: 18,\n lineHeight: \"23px\",\n fontVariantNumeric: \"tabular-nums\",\n padding: 0,\n }}\n value={inputText}\n onChange={handleChange}\n onKeyDownCapture={handleKeyDownCapture}\n />\n );\n}\n\n/**\n * Pretty-print a numeric form value for the TP/SL input boxes.\n * Strips the `.000…` tail that `String(0)` / `String(1.0)` produce\n * by going through `Number.toString()`'s shortest-roundtrip\n * representation, which matches what axiom shows in its input\n * boxes (`105.81`, `7.30`, `89.866` rather than `105.81000`).\n */\nfunction formatTpSlNumber(value: number): string {\n if (!Number.isFinite(value)) return \"\";\n return String(value);\n}\n\n/**\n * One half of a TP/SL row — either the Price input or the Percent\n * input. Holds its own string state (so transitional text like\n * `\"5.\"` survives mid-typing the same way `BuyAmountInput` does)\n * and is keyed off the matching `react-hook-form` field.\n *\n * Bidirectional sync lives here, not in the script, because it's\n * an interaction concern: the partner field is recomputed only on\n * a *user-driven* keystroke. Pure form-state changes (slider\n * drags, programmatic resets, side / leverage changes) never\n * trigger derivation — they go through `setValue` which the\n * `useEffect` below mirrors back into the input text without\n * touching the partner field.\n *\n * Direction lookup uses the {@link TpSlKind} + side combo; see\n * `tp-sl-math.ts` for the closed-form derivation and the side ×\n * kind sign table.\n */\nfunction TpSlInput({\n methods,\n field,\n placeholder,\n refPrice,\n leverage,\n side,\n}: {\n methods: UseFormReturn<PlaceOrderFormData>;\n field:\n | \"takeProfitPrice\"\n | \"takeProfitPercent\"\n | \"stopLossPrice\"\n | \"stopLossPercent\";\n placeholder: string;\n refPrice?: number;\n leverage: number;\n side: OrderSide;\n}) {\n // Resolve the TP/SL row this input belongs to (\"tp\" or \"sl\") and\n // the partner field name from the field id alone — keeps the\n // call sites symmetrical (they pass only `field`).\n const kind: TpSlKind = field.startsWith(\"takeProfit\") ? \"tp\" : \"sl\";\n const isPriceField = field === \"takeProfitPrice\" || field === \"stopLossPrice\";\n const partnerField: typeof field = (() => {\n switch (field) {\n case \"takeProfitPrice\":\n return \"takeProfitPercent\";\n case \"takeProfitPercent\":\n return \"takeProfitPrice\";\n case \"stopLossPrice\":\n return \"stopLossPercent\";\n case \"stopLossPercent\":\n return \"stopLossPrice\";\n }\n })();\n\n const formValue = methods.watch(field);\n const numericValue =\n typeof formValue === \"number\" && Number.isFinite(formValue)\n ? formValue\n : undefined;\n\n const [inputText, setInputText] = useState<string>(() =>\n numericValue !== undefined ? formatTpSlNumber(numericValue) : \"\",\n );\n const inputRef = useRef<HTMLInputElement | null>(null);\n\n // Same focus-aware sync rule as `BuyAmountInput`: only suppress\n // the mirror when the visible text already *agrees* numerically\n // with the form value. Lets transitional text (`\"5.\"`) persist\n // without leaking stale text after side / leverage changes\n // re-derive the partner field.\n useEffect(() => {\n const isFocused =\n typeof document !== \"undefined\" &&\n document.activeElement === inputRef.current;\n setInputText((prev) => {\n const parsedPrev = parseFloat(prev);\n const valuesAgree =\n Number.isFinite(parsedPrev) && parsedPrev === numericValue;\n if (isFocused && valuesAgree) return prev;\n const next =\n numericValue !== undefined ? formatTpSlNumber(numericValue) : \"\";\n return prev === next ? prev : next;\n });\n }, [numericValue]);\n\n const handleChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const cleaned = sanitiseAmountInput(e.target.value);\n setInputText(cleaned);\n\n // Empty / dot-only → clear *both* fields in this row.\n // Mirrors axiom: emptying TP Price also empties TP %, so the\n // user starts fresh next time they open the row.\n if (cleaned === \"\" || cleaned === \".\") {\n methods.setValue(field, undefined, {\n shouldValidate: false,\n shouldDirty: true,\n });\n methods.setValue(partnerField, undefined, {\n shouldValidate: false,\n shouldDirty: false,\n });\n return;\n }\n\n const parsed = Number(cleaned);\n if (!Number.isFinite(parsed)) return;\n\n methods.setValue(field, parsed, {\n shouldValidate: false,\n shouldDirty: true,\n });\n\n // Derive partner field. When the live mark price hasn't\n // landed yet (first paint, or a cold WebSocket) we leave the\n // partner alone so we don't blow it away with an undefined\n // derivation — the script's submit-time fallback recomputes\n // from whichever field is filled.\n if (!refPrice || refPrice <= 0 || !leverage || leverage <= 0) return;\n\n const partnerValue = isPriceField\n ? deriveTpSlPercent(parsed, refPrice, leverage, side, kind)\n : deriveTpSlPrice(parsed, refPrice, leverage, side, kind);\n\n if (partnerValue === undefined || !Number.isFinite(partnerValue)) {\n return;\n }\n const rounded = isPriceField\n ? roundTpSlPercent(partnerValue)\n : roundTpSlPrice(partnerValue);\n methods.setValue(partnerField, rounded, {\n shouldValidate: false,\n shouldDirty: false,\n });\n },\n [\n methods,\n field,\n partnerField,\n isPriceField,\n refPrice,\n leverage,\n side,\n kind,\n ],\n );\n\n const handleKeyDownCapture = useCallback(\n (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === \"-\" || e.key === \"+\" || e.key === \"e\" || e.key === \"E\") {\n e.preventDefault();\n e.stopPropagation();\n }\n },\n [],\n );\n\n return (\n <input\n ref={inputRef}\n type=\"text\"\n inputMode=\"decimal\"\n pattern=\"[0-9.]*\"\n autoComplete=\"off\"\n autoCorrect=\"off\"\n spellCheck={false}\n name={field}\n placeholder={placeholder}\n aria-label={field}\n className=\"w-full bg-transparent outline-none\"\n style={{\n color: \"#ffffff\",\n fontSize: 12,\n height: 32,\n padding: \"0 8px\",\n border: \"1px solid #1c1c1c\",\n borderRadius: 4,\n fontVariantNumeric: \"tabular-nums\",\n }}\n value={inputText}\n onChange={handleChange}\n onKeyDownCapture={handleKeyDownCapture}\n />\n );\n}\n\nexport function PlaceOrderFormUI({\n methods,\n side,\n orderType,\n onSideChange,\n onOrderTypeChange,\n onSubmit,\n isSubmitting,\n symbol,\n currentPrice,\n estimatedFee,\n liquidationPrice,\n availableMargin,\n accountValue,\n currentPosition,\n // Per-asset leverage cap from Hyperliquid's universe metadata\n // (`assetMeta.maxLeverage`, resolved by the script). Drives the\n // modal's slider max so the user can't pick a value the venue\n // would reject. Falls back to the prop default until the meta\n // query resolves.\n maxLeverage,\n isLeverageReady = true,\n hasOpenOrdersForSymbol = false,\n szDecimals,\n onAddFunds,\n onUpdateLeverage,\n}: PlaceOrderFormUIProps) {\n // Auth-gate every action in the form so unauthenticated clicks open\n // the login flow and replay the action on success.\n //\n // `guardedSubmit` wraps the form's submit handler (which RHF calls\n // with the validated FormData) — covers both the Long/Short button\n // and any Enter-key submission via the form element.\n //\n // `guardedAddFunds` wraps the deposit action — covers both the\n // \"Add More Funds\" submit-button variant (shown when availableMargin\n // = 0, i.e. the not-logged-in case) and the Available Margin capsule.\n //\n // Using `useAuthCallback` at the UI layer (rather than delegating to\n // the consumer) means every render path that can result in a user\n // action is protected, regardless of whether the consumer remembered\n // to add an auth wrapper on `onAddFunds` / `onSubmit`.\n //\n // The noop fallback for `onAddFunds` is safe: the capsule button is\n // `disabled` when the prop is absent, and the \"Add More Funds\" submit\n // button has `disabled: !onAddFunds` in its state — so `guardedAddFunds`\n // only fires when `onAddFunds` is actually wired.\n const addFundsFallback = useCallback(() => {\n onAddFunds?.();\n }, [onAddFunds]);\n const guardedAddFunds = useAuthCallback(addFundsFallback);\n const guardedSubmit = useAuthCallback(onSubmit);\n const [showLeverageModal, setShowLeverageModal] = useState(false);\n const [showTpSl, setShowTpSl] = useState(false);\n const leverage = methods.watch(\"leverage\") || 20;\n // Watching as `number | undefined` so the input renders empty (and\n // its placeholder shows) until the user types or the slider sets a\n // value.\n //\n // Note: HeroUI's NumberInput surfaces an *empty* state as `NaN`, not\n // `undefined`. `typeof NaN === \"number\"` is true, which means a\n // naive `typeof === \"number\"` guard would let NaN through and then\n // every downstream calc (`amount / availableMargin`, the slider's\n // `value`) would propagate NaN. `<input type=range>` falls back to\n // its midpoint when handed NaN — that was the \"50% on first paint\"\n // bug. We require a finite number everywhere.\n const rawAmount = methods.watch(\"amount\");\n const amount =\n typeof rawAmount === \"number\" && Number.isFinite(rawAmount) ? rawAmount : 0;\n const hasAmount = amount > 0;\n const tokenSymbol = symbol.split(\"-\")[0];\n\n // Slider reflects how much of the user's available margin they're\n // committing — a pure ratio, decoupled from leverage and price. This\n // matches the spec (\"拖动进度条 = Available Margin 的百分比\") and\n // keeps the slider stable when the underlying token price moves.\n const positionPercent = useMemo(() => {\n if (!availableMargin || availableMargin <= 0) return 0;\n if (!hasAmount) return 0;\n const pct = (amount / availableMargin) * 100;\n if (!Number.isFinite(pct)) return 0;\n return Math.max(0, Math.min(100, pct));\n }, [hasAmount, amount, availableMargin]);\n\n const handlePositionSlider = useCallback(\n (value: number) => {\n if (availableMargin <= 0) return;\n const pct = Math.max(0, Math.min(100, value)) / 100;\n // Slider all the way to 0% clears the input (placeholder shows\n // again) instead of pinning it to a literal \"0\" — same\n // contract as the user manually emptying the field. Anything\n // above 0 lands at 4-decimal precision: keystroke entry is\n // free-form (whatever precision the user types survives), but\n // drag emits a sensible step so the field doesn't fill with\n // long-tail floats like `12.34567891234567`. Submission still\n // truncates to the venue's tick size at the API layer.\n if (pct === 0) {\n methods.setValue(\"amount\", undefined, {\n shouldValidate: false,\n shouldDirty: true,\n });\n return;\n }\n const next = Number((availableMargin * pct).toFixed(4));\n methods.setValue(\"amount\", next, {\n shouldValidate: false,\n shouldDirty: true,\n });\n },\n [availableMargin, methods],\n );\n\n // USDC margin → coin quantity conversion shown to the right of the\n // Buy Amount input.\n //\n // ── Formula ───────────────────────────────────────────────────\n // notional = amount × leverage // total position size in USDC\n // coins = notional / currentPrice // how many coins that buys\n //\n // Worked example (SOL @ $89.475, 10x leverage, $5 margin):\n // notional = 5 × 10 = $50\n // coins = 50 / 89.475 = 0.5589 SOL\n // display = 0.56 SOL // truncated to szDecimals = 2\n //\n // ── Inputs ────────────────────────────────────────────────────\n // • `amount` USDC the user committed (form field).\n // • `leverage` synced with `activeAssetData` from the venue\n // (NOT the leverage button's display value when\n // they diverge — the on-chain value wins).\n // • `currentPrice` mark/last from `useMarketQuery`. Re-renders\n // automatically when the ticker moves, so the\n // coin quantity stays live.\n //\n // ── Display only ─────────────────────────────────────────────\n // The SDK does not submit token quantity yet — order placement\n // is driven by `notional` once the venue order pipe is wired.\n // This number exists purely to give the user a visual sense of\n // how big a position the USDC amount opens.\n const tokenQuantity = useMemo(() => {\n if (!hasAmount || !currentPrice || currentPrice <= 0) return 0;\n return (amount * leverage) / currentPrice;\n }, [hasAmount, amount, leverage, currentPrice]);\n\n // Margin floor that satisfies Hyperliquid's $10-notional minimum at\n // the user's *current* leverage. We derive this on every render\n // because `leverage` is itself live (the user can open the leverage\n // modal mid-input). Clamping to 1x at the bottom guards against\n // transient zero/negative values during state transitions — the\n // modal already enforces `LEVERAGE_MIN = 1` so this is purely\n // defensive.\n const minMarginUsdc = useMemo(\n () => MIN_NOTIONAL_USDC / Math.max(1, leverage),\n [leverage],\n );\n\n // Submit button state machine. Mirrors the spec exactly:\n // 1. balance = 0 → \"Add More Funds\"\n // 2a. amount empty → \"Invalid Buy Amount\"\n // 2b. amount × leverage < $10 notional → \"Order size too small\"\n // 3. otherwise → \"Long HYPE-USD\" / \"Short HYPE-USD\"\n //\n // Cases 2a and 2b share the same `kind: \"invalid\"` styling (gray,\n // disabled) but the copy is split: an empty input is a \"type\n // something\" prompt, while a too-small amount is an \"actually you\n // typed something but the venue won't accept it\" hint. The user\n // takes the same action to fix either, but seeing the distinction\n // helps them learn the venue's $10-notional minimum the first time\n // they hit it.\n //\n // The \"Add More Funds\" branch also covers the *not-logged-in* case:\n // when there is no connected wallet the upstream queries gate on\n // `userAddress` and surface `availableMargin = 0`, so we land here\n // naturally. The consumer is expected to wrap `onAddFunds` with an\n // auth guard (e.g. `useAuthenticatedCallback`) so clicking the\n // button while signed-out triggers login first and then opens the\n // deposit dialog. Keeping auth out of the SDK preserves the\n // venue-agnostic boundary.\n //\n // We compute the state once so the JSX stays readable and the\n // button properties (text / onClick / disabled) stay in lockstep.\n const submitState = useMemo<{\n label: string;\n kind: \"deposit\" | \"invalid\" | \"submit\";\n disabled: boolean;\n }>(() => {\n if (availableMargin <= 0) {\n return {\n label: \"Add More Funds\",\n kind: \"deposit\",\n disabled: !onAddFunds,\n };\n }\n if (!hasAmount) {\n return {\n label: \"Invalid Buy Amount\",\n kind: \"invalid\",\n disabled: true,\n };\n }\n if (amount < minMarginUsdc) {\n return {\n label: \"Order size too small\",\n kind: \"invalid\",\n disabled: true,\n };\n }\n return {\n label: `${side === \"long\" ? \"Long\" : \"Short\"} ${tokenSymbol}-USD`,\n kind: \"submit\",\n disabled: isSubmitting,\n };\n }, [\n availableMargin,\n hasAmount,\n amount,\n minMarginUsdc,\n side,\n tokenSymbol,\n isSubmitting,\n onAddFunds,\n ]);\n\n const handleSubmitButtonClick = useCallback(() => {\n if (submitState.kind === \"deposit\") void guardedAddFunds();\n // \"submit\" delegates to native form submission (type=\"submit\");\n // \"invalid\" is disabled and cannot fire.\n }, [submitState.kind, guardedAddFunds]);\n\n // Pretty-format a token quantity. Coins span 6+ orders of magnitude\n // (e.g. BTC ~ 0.0001 vs PEPE ~ 1_000_000), so when the venue tells\n // us the canonical size precision (Hyperliquid's `szDecimals`) we\n // honour it exactly — that's what axiom does and it gives us\n // 1:1 fidelity with the venue (BTC → 5 dp, ETH → 4, SOL → 2,\n // DOGE → 0). Without it we fall back to an adaptive heuristic that\n // keeps the badge legible regardless of magnitude.\n const formatTokenQuantity = (n: number): string => {\n if (!Number.isFinite(n) || n <= 0) {\n // `0` is the resting state. When the venue declares 0 size\n // decimals (e.g. DOGE) emit a bare `0`; otherwise emit `0`\n // with no fraction to keep the row compact. Either way the\n // value is the same so we don't need to branch on szDecimals.\n return \"0\";\n }\n if (typeof szDecimals === \"number\" && szDecimals >= 0) {\n return n.toFixed(szDecimals);\n }\n if (n >= 1000) return n.toFixed(2);\n if (n >= 1) return n.toFixed(4);\n return n.toFixed(6);\n };\n\n return (\n <div\n className=\"flex flex-col h-full\"\n style={{ backgroundColor: \"#000000\" }}\n >\n {/* Inject the shimmer keyframes once per form mount so the\n inline leverage skeleton (and any future inline skeletons in\n this form) inherit the same sweep animation as the prediction\n module's card skeletons. The `<style>` tag is tiny and React\n dedupes duplicate same-body keyframe declarations. */}\n <ShimmerStyle />\n <div\n className=\"perp-order-form flex-1 overflow-y-auto\"\n style={{\n padding: \"16px 16px\",\n display: \"flex\",\n flexDirection: \"column\",\n gap: 16,\n }}\n >\n {/* Long / Short — bordered tab toggle */}\n <div\n className=\"perp-side-tabs flex\"\n style={{\n border: \"1px solid rgba(39,39,42,0.8)\",\n borderRadius: 8,\n padding: 4,\n gap: 4,\n }}\n >\n <StyledTooltip\n content=\"Buy asset, profit when price goes up\"\n placement=\"top\"\n delay={200}\n closeDelay={0}\n >\n <button\n type=\"button\"\n data-active={side === \"long\"}\n className=\"perp-side-tab perp-side-tab--long flex-1 cursor-pointer transition-colors\"\n style={{\n height: 32,\n fontSize: 14,\n borderRadius: 4,\n backgroundColor:\n side === \"long\" ? BRAND_PRIMARY : \"transparent\",\n color: side === \"long\" ? \"#000000\" : \"#b5b5b5\",\n fontWeight: side === \"long\" ? 500 : 400,\n border: \"none\",\n }}\n onClick={() => onSideChange(\"long\")}\n >\n Long\n </button>\n </StyledTooltip>\n <StyledTooltip\n content=\"Sell asset, profit when price goes down\"\n placement=\"top\"\n delay={200}\n closeDelay={0}\n >\n <button\n type=\"button\"\n data-active={side === \"short\"}\n className=\"perp-side-tab perp-side-tab--short flex-1 cursor-pointer transition-colors\"\n style={{\n height: 32,\n fontSize: 14,\n borderRadius: 4,\n backgroundColor: side === \"short\" ? \"#F76816\" : \"transparent\",\n color: side === \"short\" ? \"#000000\" : \"#b5b5b5\",\n fontWeight: side === \"short\" ? 500 : 400,\n border: \"none\",\n }}\n onClick={() => onSideChange(\"short\")}\n >\n Short\n </button>\n </StyledTooltip>\n </div>\n\n {/* Market / Limit + Leverage button */}\n <div className=\"flex items-center\" style={{ gap: 8 }}>\n <div className=\"flex\">\n {[\n { key: \"market\" as const, label: \"Market\" },\n { key: \"limit\" as const, label: \"Limit\" },\n ].map((tab) => (\n <div\n key={tab.key}\n style={{\n height: 32,\n display: \"flex\",\n alignItems: \"center\",\n borderBottom:\n orderType === tab.key\n ? \"2px solid #ffffff\"\n : \"2px solid transparent\",\n padding: \"2px 0 0\",\n cursor: \"pointer\",\n }}\n >\n <button\n type=\"button\"\n className=\"cursor-pointer transition-colors\"\n style={{\n padding: \"0 8px\",\n fontSize: 12,\n fontWeight: 500,\n backgroundColor: \"transparent\",\n color: orderType === tab.key ? \"#ffffff\" : \"#b5b5b5\",\n border: \"none\",\n }}\n onClick={() => onOrderTypeChange(tab.key)}\n >\n {tab.label}\n </button>\n </div>\n ))}\n </div>\n <div className=\"flex-1\" />\n {/* Leverage button — pill control sized to match the\n Market/Limit toggle text (12px / 400) so the controls in\n this row feel visually equal-weight. The focus ring uses\n the brand primary so keyboard navigation lands on the\n same accent color used everywhere else in the app.\n\n While the venue's configured leverage is loading we render\n a skeleton in place of the number so users don't see a\n jarring `20x → 35x` flash on refresh. The skeleton width\n is sized to roughly match a typical 1–2 digit value to\n avoid layout shift when the real number lands. */}\n <button\n type=\"button\"\n className=\"cursor-pointer flex items-center gap-1.5 px-3 py-1.5 rounded-[10px] transition-colors text-zinc-500 hover:text-zinc-200 hover:bg-zinc-800/40 focus:outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#C7FF2E] disabled:cursor-progress\"\n style={{ fontSize: 12, fontWeight: 400 }}\n onClick={() => setShowLeverageModal(true)}\n disabled={!isLeverageReady}\n >\n <span>Leverage:</span>\n {isLeverageReady ? (\n <span>{leverage}x</span>\n ) : (\n <span aria-hidden=\"true\" style={inlineTextSkeleton} />\n )}\n </button>\n </div>\n\n <RHForm methods={methods} onSubmit={guardedSubmit}>\n <div className=\"space-y-3 w-full\">\n {/* Limit price input */}\n {orderType === \"limit\" && (\n <div\n className=\"perp-price-box\"\n style={{\n borderRadius: 4,\n padding: 8,\n backgroundColor: \"rgba(26,26,26,0.5)\",\n border: \"1px solid #1c1c1c\",\n height: 64,\n display: \"flex\",\n flexDirection: \"column\",\n justifyContent: \"center\",\n }}\n >\n <div className=\"flex justify-between items-center\">\n <span style={{ fontSize: 12, color: \"#6b6b6b\" }}>Price</span>\n <span style={{ fontSize: 12, color: \"#6b6b6b\" }}>USDC</span>\n </div>\n <RHNumberInput\n name=\"price\"\n placeholder=\"0.0 USDC\"\n className=\"w-full\"\n />\n </div>\n )}\n\n {/* Buy Amount — input on the left in USDC, badge on the\n right showing the asset icon, ticker, and the converted\n token quantity (margin × leverage / price). The badge\n gives the user a live read of \"what am I actually\n buying\" without needing a second field. */}\n <div\n className=\"perp-buy-amt\"\n style={{\n borderRadius: 4,\n padding: 8,\n backgroundColor: \"rgba(26,26,26,0.5)\",\n border: \"1px solid #1c1c1c\",\n height: 64,\n display: \"flex\",\n flexDirection: \"column\",\n justifyContent: \"center\",\n }}\n >\n <div className=\"flex justify-between items-center\">\n <span style={{ fontSize: 12, color: \"#6b6b6b\" }}>\n Buy Amount\n </span>\n {/* Top-right slot is reserved for the asset symbol —\n a stable label that names the unit on the right\n side of the box, independent of whether the user\n has entered an amount yet. The numeric conversion\n sits below on the icon row. */}\n <span\n style={{\n fontSize: 14,\n fontWeight: 500,\n color: \"#ffffff\",\n }}\n >\n {tokenSymbol}\n </span>\n </div>\n <div\n className=\"flex items-center\"\n style={{ gap: 8, minHeight: 24 }}\n >\n {/* Plain controlled text input. We deliberately\n avoid `RHNumberInput` (HeroUI → React Aria\n NumberField) here because it commits its parsed\n value to RHF only on **blur**. That breaks live\n bidirectional sync with the slider: typing `5`\n keeps the slider thumb pinned at 0% until the\n input loses focus.\n \n `BuyAmountInput` keeps its own string state for\n the visible text, propagates a parsed number to\n RHF on every keystroke, and re-syncs when the\n form value changes externally (slider drag, the\n script's clamp effect). End result mirrors\n axiom's UX exactly. */}\n <BuyAmountInput methods={methods} />\n {/* Bottom-right slot — asset icon + the converted\n token quantity. Unit (e.g. \"BTC\") is implied by\n the symbol label up top; we show the bare number\n here so the row stays compact. The icon hides\n itself on a 404 so a missing CDN entry doesn't\n leave a broken image. */}\n <div className=\"flex items-center shrink-0\" style={{ gap: 6 }}>\n <img\n src={`${HYPERLIQUID_ICON_CDN}/${tokenSymbol}.svg`}\n alt={tokenSymbol}\n width={18}\n height={18}\n className=\"rounded-full\"\n style={{ width: 18, height: 18 }}\n onError={(e) => {\n (e.target as HTMLImageElement).style.display = \"none\";\n }}\n />\n {/* Font sizing intentionally matches the BuyAmountInput\n on the left (18 / 23) so the input value and its\n converted-token equivalent read as a single, balanced\n pair across the row instead of looking like a primary\n input + secondary caption. */}\n <span\n style={{\n fontSize: 18,\n lineHeight: \"23px\",\n color: \"#b5b5b5\",\n fontVariantNumeric: \"tabular-nums\",\n }}\n >\n {formatTokenQuantity(tokenQuantity)}\n </span>\n </div>\n </div>\n </div>\n\n {/* Position size slider — pure margin-percentage drag. The\n input above is the source of truth; we just project\n `amount / availableMargin` onto a 0–100 range. The\n slider is disabled when the user has no margin to\n spend (the spec's \"Deposit\" branch handles that\n case).\n \n Track fill: the visual rule is \"everything left of the\n thumb is brand green, everything to the right is the\n inert track\". WebKit doesn't expose a native filled\n pseudo-element on `<input type=range>`, so we fake it\n via a two-stop gradient on the runnable-track — driven\n by a `--pct` CSS variable set inline below. Firefox\n uses the native `::-moz-range-progress` pseudo, which\n handles the fill for free. */}\n <div>\n <style>{`\n .perp-buy-amt input, .perp-price-box input { font-size: 18px !important; line-height: 23px !important; }\n .perp-order-form .group,\n .perp-order-form .group div { background: transparent !important; border: none !important; padding: 0 !important; border-radius: 0 !important; min-height: 0 !important; height: auto !important; }\n .perp-order-form .group input { color: #ffffff !important; }\n .perp-slider { -webkit-appearance: none; appearance: none; background: transparent; cursor: pointer; width: 100%; height: 16px; --pct: 0%; --fill: ${BRAND_PRIMARY}; --track: #1c1c1c; }\n .perp-slider::-webkit-slider-runnable-track {\n height: 4px; border-radius: 2px;\n background: linear-gradient(to right, var(--fill) 0, var(--fill) var(--pct), var(--track) var(--pct), var(--track) 100%);\n }\n .perp-slider::-webkit-slider-thumb { -webkit-appearance: none; width: 12px; height: 12px; border-radius: 50%; background: ${BRAND_PRIMARY}; margin-top: -4px; border: none; box-shadow: 0 0 0 2px rgba(0,0,0,0.6); }\n .perp-slider::-moz-range-track { height: 4px; border-radius: 2px; background: #1c1c1c; border: none; }\n .perp-slider::-moz-range-progress { height: 4px; border-radius: 2px; background: ${BRAND_PRIMARY}; }\n .perp-slider::-moz-range-thumb { width: 12px; height: 12px; border-radius: 50%; background: ${BRAND_PRIMARY}; border: none; box-shadow: 0 0 0 2px rgba(0,0,0,0.6); }\n .perp-slider:disabled { cursor: not-allowed; opacity: 0.5; }\n .perp-side-tab[data-active=\"false\"]:hover { background-color: rgba(255,255,255,0.12) !important; color: #ffffff !important; }\n `}</style>\n <input\n type=\"range\"\n value={Math.round(positionPercent)}\n onChange={(e) => handlePositionSlider(Number(e.target.value))}\n min={0}\n max={100}\n step={1}\n disabled={availableMargin <= 0}\n className=\"perp-slider\"\n style={\n {\n // CSS var consumed by ::-webkit-slider-runnable-track\n // gradient. Pseudo-elements inherit custom properties\n // from the host, so the inline value flows down.\n [\"--pct\" as never]: `${Math.round(positionPercent)}%`,\n } as CSSProperties\n }\n />\n <div\n className=\"flex justify-between\"\n style={{ fontSize: 10, color: \"#b5b5b5\", marginTop: 4 }}\n >\n <span>0%</span>\n <span>25%</span>\n <span>50%</span>\n <span>75%</span>\n <span>100%</span>\n </div>\n </div>\n\n {/* TP/SL + Est. Liq. Price.\n Sits visually one tier below the percentage slider — the\n slider closes a \"size your order\" group and this row\n opens an \"advanced options\" group, so the gap here is\n intentionally wider than the form's default `space-y-3`\n rhythm. */}\n <div\n className=\"flex items-center justify-between\"\n style={{ marginTop: 16 }}\n >\n <div className=\"flex items-center\" style={{ gap: 6 }}>\n <div\n onClick={() => setShowTpSl((v) => !v)}\n style={{\n width: 16,\n height: 16,\n borderRadius: 4,\n border: \"1px solid #2a2a2a\",\n backgroundColor: showTpSl ? \"#C7FF2E\" : \"transparent\",\n flexShrink: 0,\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n }}\n >\n {showTpSl && (\n <svg width=\"10\" height=\"8\" viewBox=\"0 0 10 8\" fill=\"none\">\n <path\n d=\"M1 4L3.5 6.5L9 1\"\n stroke=\"#000000\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n )}\n </div>\n <span\n style={{ fontSize: 12, fontWeight: 500, color: \"#b5b5b5\" }}\n >\n TP/SL\n </span>\n </div>\n <div style={{ fontSize: 12, color: \"#6b6b6b\" }}>\n <span>Est. Liq. Price: </span>\n <span style={{ color: \"#b5b5b5\" }}>\n {liquidationPrice ? formatLiqPrice(liquidationPrice) : \"--\"}\n </span>\n </div>\n </div>\n\n {/* TP / SL rows (visible when TP/SL checked).\n Each row pairs a Price input with a Percent input.\n The two are bidirectionally linked: typing in either\n immediately rewrites the other, using the live mark\n price (`currentPrice`) as the entry reference and\n the on-chain `leverage` to convert raw priceΔ into\n leveraged ROI. The two rows are otherwise\n independent — the user can fill just TP, just SL,\n both, or neither, exactly like axiom. */}\n {showTpSl && (\n <div className=\"flex\" style={{ gap: 8 }}>\n <div className=\"flex-1\">\n <span\n style={{\n fontSize: 12,\n color: \"#6b6b6b\",\n marginBottom: 2,\n display: \"block\",\n }}\n >\n TP Price\n </span>\n <TpSlInput\n methods={methods}\n field=\"takeProfitPrice\"\n placeholder=\"Enter TP price\"\n refPrice={currentPrice}\n leverage={leverage}\n side={side}\n />\n </div>\n <div style={{ width: 70 }}>\n <span\n style={{\n fontSize: 12,\n color: \"#6b6b6b\",\n marginBottom: 2,\n display: \"block\",\n }}\n >\n TP %\n </span>\n <TpSlInput\n methods={methods}\n field=\"takeProfitPercent\"\n placeholder=\"0.0\"\n refPrice={currentPrice}\n leverage={leverage}\n side={side}\n />\n </div>\n </div>\n )}\n\n {showTpSl && (\n <div className=\"flex\" style={{ gap: 8 }}>\n <div className=\"flex-1\">\n <span\n style={{\n fontSize: 12,\n color: \"#6b6b6b\",\n marginBottom: 2,\n display: \"block\",\n }}\n >\n SL Price\n </span>\n <TpSlInput\n methods={methods}\n field=\"stopLossPrice\"\n placeholder=\"Enter SL price\"\n refPrice={currentPrice}\n leverage={leverage}\n side={side}\n />\n </div>\n <div style={{ width: 70 }}>\n <span\n style={{\n fontSize: 12,\n color: \"#6b6b6b\",\n marginBottom: 2,\n display: \"block\",\n }}\n >\n SL %\n </span>\n <TpSlInput\n methods={methods}\n field=\"stopLossPercent\"\n placeholder=\"0.0\"\n refPrice={currentPrice}\n leverage={leverage}\n side={side}\n />\n </div>\n </div>\n )}\n\n {/* Smart submit button — collapses what used to be a\n separate \"Add More Funds\" CTA into a single, context-\n sensitive action:\n - balance = 0 → \"Add More Funds\" (calls onAddFunds;\n consumer is expected to gate it\n with an auth callback so the\n signed-out path triggers login\n before opening the deposit dialog)\n - amount < $0.50 → \"Order size too small\" (disabled)\n - amount ∈ [0.5, max] → \"Long HYPE-USD\" / \"Short HYPE-USD\"\n The colour also tracks the side accent so users get a\n Long-green / Short-orange CTA matching the side toggle\n up top. */}\n {(() => {\n const isSubmit = submitState.kind === \"submit\";\n const buttonType = isSubmit ? \"submit\" : \"button\";\n const isLong = side === \"long\";\n const activeBg = isSubmit\n ? isLong\n ? SIDE_LONG_COLOR\n : SIDE_SHORT_COLOR\n : submitState.kind === \"deposit\"\n ? BRAND_PRIMARY\n : \"rgba(63,63,70,0.6)\";\n const activeColor =\n submitState.kind === \"invalid\" ? \"#71717a\" : \"#000000\";\n // While the submit mutation is in-flight, swap the\n // label for a spinner + \"Placing order...\" so the user\n // gets immediate feedback that the click registered.\n // Mirrors the LeverageModal's pending state above.\n const isPlacing = isSubmit && isSubmitting;\n return (\n <button\n type={buttonType}\n disabled={submitState.disabled}\n onClick={isSubmit ? undefined : handleSubmitButtonClick}\n className=\"w-full transition-colors disabled:cursor-not-allowed flex items-center justify-center gap-2\"\n style={{\n // Extra breathing room above the CTA so it reads as\n // a separate \"commit\" group from the TP/SL row (or\n // its expanded inputs) immediately above. Without\n // this the submit button feels glued to the\n // optional fields and is easy to mis-click while\n // adjusting them.\n marginTop: 16,\n height: 40,\n fontSize: 14,\n fontWeight: 600,\n color: activeColor,\n backgroundColor: activeBg,\n borderRadius: 9999,\n border: \"none\",\n cursor: submitState.disabled ? \"not-allowed\" : \"pointer\",\n opacity: submitState.disabled ? 0.9 : 1,\n }}\n >\n {isPlacing && <Spinner size=\"sm\" color=\"current\" />}\n {isPlacing ? \"Placing order...\" : submitState.label}\n </button>\n );\n })()}\n\n {/* Account info — sits directly under the Add More Funds CTA so\n Available Margin / Perps Account Value / Current Position\n stay near the action that funds them, instead of being\n pushed to the bottom of the form column. */}\n <div\n style={{\n fontSize: 12,\n display: \"flex\",\n flexDirection: \"column\",\n gap: 6,\n paddingTop: 4,\n }}\n >\n <div className=\"flex justify-between items-center\">\n <span style={{ color: \"#6b6b6b\" }}>Available Margin</span>\n {/* Capsule button — mirrors Axiom's \"tap-to-fund\" entry\n point. We intentionally use our own brand primary\n (green) instead of Axiom's blue, so the deposit CTA\n inherits the same accent as the rest of the form\n (Long color, slider fill, leverage thumb). The\n button degrades to a non-interactive pill when\n `onAddFunds` isn't wired, so headless consumers see\n the same shape without a dead click target. */}\n <button\n type=\"button\"\n onClick={() => void guardedAddFunds()}\n disabled={!onAddFunds}\n style={{\n height: 24,\n padding: \"0 8px\",\n borderRadius: 4,\n border: \"none\",\n backgroundColor: withAlpha(BRAND_PRIMARY, 0x1a),\n color: BRAND_PRIMARY,\n fontSize: 12,\n fontWeight: 500,\n lineHeight: \"16px\",\n cursor: onAddFunds ? \"pointer\" : \"default\",\n transition: \"background-color 150ms ease-in-out\",\n }}\n onMouseEnter={(e) => {\n if (onAddFunds) {\n e.currentTarget.style.backgroundColor = withAlpha(\n BRAND_PRIMARY,\n 0x33,\n );\n }\n }}\n onMouseLeave={(e) => {\n if (onAddFunds) {\n e.currentTarget.style.backgroundColor = withAlpha(\n BRAND_PRIMARY,\n 0x1a,\n );\n }\n }}\n >\n {formatNumber(availableMargin)} USDC\n </button>\n </div>\n <div className=\"flex justify-between\">\n <span style={{ color: \"#6b6b6b\" }}>Perps Account Value</span>\n <span style={{ color: \"#b5b5b5\", fontSize: 12 }}>\n {formatNumber(accountValue)} USDC\n </span>\n </div>\n <div className=\"flex justify-between\">\n <span style={{ color: \"#6b6b6b\" }}>Current Position</span>\n <span style={{ color: \"#b5b5b5\", fontSize: 12 }}>\n {currentPosition\n ? // Mirror Axiom's layout: `Long 0.00045 BTC (1.19 USDC)`.\n // `quantityRaw` preserves the venue's exact precision\n // (BTC's 5-dp `0.00045` survives instead of collapsing\n // to `0.00` like a `toFixed(2)` would), with the\n // parsed number as a fallback for adapters that don't\n // surface the raw string.\n `${currentPosition.side === \"long\" ? \"Long\" : \"Short\"} ${\n currentPosition.quantityRaw ??\n String(currentPosition.quantity)\n } ${currentPosition.base} (${currentPosition.margin.toFixed(2)} USDC)`\n : \"--\"}\n </span>\n </div>\n </div>\n </div>\n </RHForm>\n </div>\n\n {/* Branding footer */}\n <div\n style={{\n padding: \"10px 16px\",\n fontSize: 12,\n display: \"flex\",\n flexDirection: \"column\",\n }}\n >\n <div className=\"flex items-center justify-end\" style={{ gap: 6 }}>\n <span style={{ fontSize: 11, color: \"#6b6b6b\" }}>powered by</span>\n <img\n src=\"https://axiom-assets.sfo3.cdn.digitaloceanspaces.com/images/hyperliquid-logo.svg\"\n alt=\"Hyperliquid\"\n className=\"h-3 opacity-60\"\n onError={(e) => {\n const target = e.target as HTMLImageElement;\n target.style.display = \"none\";\n }}\n />\n </div>\n </div>\n\n {/* Leverage modal — kept always-mounted so HeroUI's open/close\n animations run smoothly, gated by `isOpen`. The modal\n locks updates when a position is open (venue-enforced) and\n shows an advisory when resting orders exist (caller-side\n info; the venue still accepts the update). */}\n <LeverageModal\n isOpen={showLeverageModal}\n initialLeverage={leverage}\n maxLeverage={maxLeverage}\n coinName={\n currentPosition?.base ??\n (symbol.includes(\"-\") ? symbol.split(\"-\")[0] : symbol)\n }\n hasOpenPosition={!!currentPosition}\n hasOpenOrders={hasOpenOrdersForSymbol}\n onConfirm={(v) => methods.setValue(\"leverage\", v)}\n onUpdate={onUpdateLeverage}\n onClose={() => setShowLeverageModal(false)}\n />\n </div>\n );\n}\n","import type { PlaceOrderRequest, PlaceOrderResult } from \"../../types\";\nimport { usePlaceOrderFormScript } from \"./place-order-form.script\";\nimport { PlaceOrderFormUI } from \"./place-order-form.ui\";\n\nexport type PlaceOrderFormWidgetProps = {\n symbol: string;\n userAddress?: string;\n maxLeverage?: number;\n onSuccess?: () => void;\n onError?: (error: Error) => void;\n /**\n * Optional callback fired when the user clicks \"Add More Funds\".\n * The host app typically opens its deposit dialog here. When omitted,\n * the button is hidden so the form doesn't expose a non-functional\n * control.\n */\n onAddFunds?: () => void;\n /**\n * Optional callback fired when the user confirms a new leverage value\n * in the leverage modal. The host app should sign + relay the\n * `updateLeverage` action to Hyperliquid and surface a toast. While\n * the returned promise is pending the modal's button shows a spinner;\n * if it rejects, the modal stays open so the user can retry.\n */\n onUpdateLeverage?: (leverage: number) => Promise<void>;\n /**\n * Optional callback that takes over order submission. When provided,\n * the widget bypasses its internal `client.placeOrder` mutation and\n * forwards the enriched {@link PlaceOrderRequest} (live mark price +\n * coin-unit size + per-asset `szDecimals`) so the host can sign and\n * relay the action against the venue directly. While the returned\n * promise is pending, the submit button shows a spinner; on\n * rejection, `onError` fires.\n *\n * Mirrors the `onUpdateLeverage` pattern. When omitted, the SDK\n * falls back to `IPerpetualsClient.placeOrder` (used by the LiberFi\n * adapter, which holds the signing keys server-side).\n */\n onPlaceOrder?: (request: PlaceOrderRequest) => Promise<PlaceOrderResult>;\n className?: string;\n};\n\nexport function PlaceOrderFormWidget({\n symbol,\n userAddress,\n maxLeverage,\n onSuccess,\n onError,\n onAddFunds,\n onUpdateLeverage,\n onPlaceOrder,\n className,\n}: PlaceOrderFormWidgetProps) {\n const {\n form,\n side,\n orderType,\n setSide,\n setOrderType,\n handleSubmit,\n isSubmitting,\n currentPrice,\n estimatedFee,\n estimatedTotal,\n liquidationPrice,\n availableMargin,\n accountValue,\n currentPosition,\n maxLeverage: resolvedMaxLeverage,\n isLeverageReady,\n hasOpenOrdersForSymbol,\n szDecimals,\n onUpdateLeverage: resolvedOnUpdateLeverage,\n } = usePlaceOrderFormScript({\n symbol,\n userAddress,\n maxLeverage,\n onSuccess,\n onError,\n onUpdateLeverage,\n onPlaceOrder,\n });\n\n return (\n <div className={className}>\n <PlaceOrderFormUI\n methods={form}\n side={side}\n orderType={orderType}\n onSideChange={setSide}\n onOrderTypeChange={setOrderType}\n onSubmit={handleSubmit}\n isSubmitting={isSubmitting}\n symbol={symbol}\n currentPrice={currentPrice}\n estimatedFee={estimatedFee}\n estimatedTotal={estimatedTotal}\n liquidationPrice={liquidationPrice}\n availableMargin={availableMargin}\n accountValue={accountValue}\n currentPosition={currentPosition}\n maxLeverage={resolvedMaxLeverage}\n isLeverageReady={isLeverageReady}\n hasOpenOrdersForSymbol={hasOpenOrdersForSymbol}\n szDecimals={szDecimals}\n onAddFunds={onAddFunds}\n onUpdateLeverage={resolvedOnUpdateLeverage}\n />\n </div>\n );\n}\n","import { useCallback, useMemo, useState } from \"react\";\nimport { useCreateOrderMutation } from \"../../hooks/useCreateOrderMutation\";\nimport { usePositionsQuery } from \"../../hooks/usePositionsQuery\";\nimport type { Position } from \"../../types\";\nimport type { PositionSortKey, SortDirection } from \"./positions.ui\";\n\nexport type UsePositionsScriptParams = {\n userAddress?: string;\n symbol?: string;\n onCloseSuccess?: () => void;\n onCloseError?: (error: Error) => void;\n};\n\nexport type UsePositionsScriptResult = {\n /** Positions already sorted by the active `sortKey` / `sortDir`. */\n positions: Position[];\n isLoading: boolean;\n error: Error | null;\n /** Active sort column (`null` only when the consumer overrides it). */\n sortKey: PositionSortKey | null;\n sortDir: SortDirection;\n /** Toggle the sort column / direction. Mirrors Axiom's 2-state cycle:\n * first click on a new column → asc, subsequent clicks toggle asc ↔\n * desc. There is no \"no-sort\" state. */\n onSort: (key: PositionSortKey) => void;\n handleClosePosition: (position: Position) => Promise<void>;\n isClosing: boolean;\n};\n\n// ---------------------------------------------------------------------------\n// Sort helpers\n// ---------------------------------------------------------------------------\n\n/** Map a sort key to the comparable scalar for a given position. */\nfunction getSortValue(\n position: Position,\n key: PositionSortKey,\n): number | string | null {\n switch (key) {\n case \"asset\":\n return position.symbol.split(\"-\")[0];\n case \"position\":\n return Math.abs(position.quantity);\n case \"value\":\n return position.notionalValue;\n case \"entry\":\n return position.entryPrice;\n case \"mark\":\n return position.markPrice;\n case \"liq\":\n // Empty liquidation price (very low leverage / cross-margin\n // surplus) is sorted to the end regardless of direction. We\n // signal this with `null` and the comparator handles ranking.\n return position.liquidationPrice ?? null;\n case \"marginPnl\":\n // Sort by the **margin amount**, not by PNL%. The column shows\n // both `$margin` and `(signed_$pnl / abs_pct%)`, but the sort\n // axis is the margin — biggest committed capital at the top\n // when `desc`. PNL% is a derived signal that depends on entry\n // and current mark, which makes it noisy as a sort key.\n return position.margin;\n }\n}\n\n/**\n * Compare two positions for the given column. `null` values (e.g.\n * unset `liquidationPrice`) always rank last, regardless of direction —\n * the standard \"missing data goes to the bottom\" UX convention.\n */\nfunction comparePositions(\n a: Position,\n b: Position,\n key: PositionSortKey,\n dir: SortDirection,\n): number {\n const aVal = getSortValue(a, key);\n const bVal = getSortValue(b, key);\n\n // Null ranking — always last, ignoring direction.\n if (aVal === null && bVal === null) return 0;\n if (aVal === null) return 1;\n if (bVal === null) return -1;\n\n let result: number;\n if (typeof aVal === \"string\" && typeof bVal === \"string\") {\n result = aVal.localeCompare(bVal);\n } else {\n // Both numbers (TS narrows from the union via the string check).\n result = (aVal as number) - (bVal as number);\n }\n\n return dir === \"asc\" ? result : -result;\n}\n\n// ---------------------------------------------------------------------------\n// Hook\n// ---------------------------------------------------------------------------\n\n/**\n * Container hook for the positions table. Responsibilities:\n * - read positions via `usePositionsQuery` (which the consumer's\n * `useAccountStateSubscription` keeps live via webData2 cache\n * write-through, so we do **not** subscribe to `userEvents` here —\n * doing so would clobber the TP/SL + mark-price enrichment that\n * the client adds on the webData2 path).\n * - own sort state (default `marginPnl ↓` — biggest margin first).\n * - expose a `handleClosePosition` shim over `useCreateOrderMutation`.\n */\nexport function usePositionsScript({\n userAddress,\n symbol,\n onCloseSuccess,\n onCloseError,\n}: UsePositionsScriptParams): UsePositionsScriptResult {\n // Default sort: `Margin Used (PNL) ↓` — biggest committed margin\n // at the top.\n const [sortKey, setSortKey] = useState<PositionSortKey | null>(\"marginPnl\");\n const [sortDir, setSortDir] = useState<SortDirection>(\"desc\");\n\n const onSort = useCallback((key: PositionSortKey) => {\n setSortKey((currentKey) => {\n if (currentKey === key) {\n // Same column → flip direction.\n setSortDir((d) => (d === \"asc\" ? \"desc\" : \"asc\"));\n return currentKey;\n }\n // New column → start ascending.\n setSortDir(\"asc\");\n return key;\n });\n }, []);\n\n const {\n data: positionsData,\n isLoading,\n error,\n } = usePositionsQuery({ userAddress, symbol }, { enabled: !!userAddress });\n\n const { mutateAsync: createOrder, isPending: isClosing } =\n useCreateOrderMutation({\n onSuccess: () => {\n onCloseSuccess?.();\n },\n onError: (err) => {\n onCloseError?.(err);\n },\n });\n\n const positions = useMemo(\n () => positionsData?.positions ?? [],\n [positionsData],\n );\n\n // Memoise the sorted view so React.memo'd children downstream skip\n // re-renders when sort state and source data are unchanged. Sorts a\n // copy — never mutate the source array, otherwise sibling\n // subscribers (e.g. account summary) would observe reordering.\n const sortedPositions = useMemo(() => {\n if (!sortKey) return positions;\n return [...positions].sort((a, b) =>\n comparePositions(a, b, sortKey, sortDir),\n );\n }, [positions, sortKey, sortDir]);\n\n const handleClosePosition = useCallback(\n async (position: Position) => {\n if (!userAddress) {\n throw new Error(\"User address is required\");\n }\n\n const closeSide = position.side === \"long\" ? \"short\" : \"long\";\n\n await createOrder({\n symbol: position.symbol,\n side: closeSide,\n orderType: \"market\",\n amount: Math.abs(position.quantity),\n leverage: position.leverage,\n userAddress,\n });\n },\n [userAddress, createOrder],\n );\n\n return {\n positions: sortedPositions,\n isLoading,\n error,\n sortKey,\n sortDir,\n onSort,\n handleClosePosition,\n isClosing,\n };\n}\n","import type { CSSProperties, ReactNode } from \"react\";\nimport { useTranslation } from \"@liberfi.io/i18n\";\nimport { cn, StyledTooltip } from \"@liberfi.io/ui\";\nimport type { Position } from \"../../types\";\n\n// ---------------------------------------------------------------------------\n// Sort\n// ---------------------------------------------------------------------------\n\n/**\n * Stable identifier for a sortable column. Mirrors Axiom's set: 7 of the\n * 9 columns are sortable; `tpsl` and `close` are interaction-only.\n *\n * Kept as a discriminated string union (rather than an enum) so it\n * survives a tsup build to a stable runtime string — consumers that\n * persist the active sort key to local-storage / URL params are\n * insulated from enum-numbering churn.\n */\nexport type PositionSortKey =\n | \"asset\"\n | \"position\"\n | \"value\"\n | \"entry\"\n | \"mark\"\n | \"liq\"\n | \"marginPnl\";\n\nexport type SortDirection = \"asc\" | \"desc\";\n\n// ---------------------------------------------------------------------------\n// Formatting\n// ---------------------------------------------------------------------------\n\n/**\n * Adaptive USD price formatter — mirrors Axiom's per-magnitude rounding\n * so a $80,564 BTC mark and a $0.0007 memecoin mark both render at a\n * useful precision without over- or under-reporting.\n *\n * ≥ 1000 → 0 fraction digits + thousands separator (e.g. `$80,564`)\n * ≥ 1 → 2 fraction digits (e.g. `$291.45`)\n * ≥ 0.01 → 4 fraction digits (e.g. `$0.0123`)\n * < 0.01 → 6 fraction digits (e.g. `$0.000123`)\n */\nfunction formatUsdPrice(n: number | undefined): string {\n if (n === undefined || !Number.isFinite(n)) return \"--\";\n const abs = Math.abs(n);\n let dp: number;\n if (abs >= 1000) dp = 0;\n else if (abs >= 1) dp = 2;\n else if (abs >= 0.01) dp = 4;\n else dp = 6;\n return (\n \"$\" +\n n.toLocaleString(\"en-US\", {\n minimumFractionDigits: dp,\n maximumFractionDigits: dp,\n })\n );\n}\n\n/** Notional / margin amount — always 2 decimals + `$` prefix. */\nfunction formatUsd2(n: number): string {\n if (!Number.isFinite(n)) return \"--\";\n return (\n \"$\" +\n n.toLocaleString(\"en-US\", {\n minimumFractionDigits: 2,\n maximumFractionDigits: 2,\n })\n );\n}\n\n/**\n * Signed PnL dollar amount, e.g. `+$0.06` / `-$0.06`. Sign is always\n * shown so the value remains intelligible if the row text colour is\n * lost (high-contrast modes, screenshots, copy-paste).\n */\nfunction formatSignedUsd2(n: number): string {\n if (!Number.isFinite(n)) return \"--\";\n const sign = n >= 0 ? \"+\" : \"-\";\n return (\n sign +\n \"$\" +\n Math.abs(n).toLocaleString(\"en-US\", {\n minimumFractionDigits: 2,\n maximumFractionDigits: 2,\n })\n );\n}\n\n/**\n * Absolute PnL percentage, e.g. `15.03%`. Direction is conveyed by the\n * cell colour (`text-bullish` / `text-bearish`), which removes the\n * redundant `+`/`-` clutter — matches Axiom and HL/Binance/Bybit\n * conventions.\n */\nfunction formatPercentAbs(percent: number): string {\n if (!Number.isFinite(percent)) return \"--\";\n return Math.abs(percent).toFixed(2) + \"%\";\n}\n\n/**\n * Position size string. Prefer the venue-supplied raw quantity to\n * preserve the exact precision (e.g. Hyperliquid's `pos.szi` may carry\n * trailing zeros that `parseFloat → toFixed` would erase). Fall back to\n * the parsed number with sensible defaults when the raw is missing.\n */\nfunction formatQuantity(quantity: number, raw?: string): string {\n if (raw) return raw;\n if (!Number.isFinite(quantity)) return \"--\";\n // 5 decimals covers BTC szDecimals (5); larger-precision assets are\n // rare on perp venues and will arrive with a `raw` string anyway.\n return quantity.toFixed(5).replace(/\\.?0+$/, \"\");\n}\n\n// ---------------------------------------------------------------------------\n// Column layout\n// ---------------------------------------------------------------------------\n\n/**\n * Flex-grow ratios per column, applied as **inline `style`** rather than\n * Tailwind arbitrary-value classes (e.g. `flex-[0.8]`).\n *\n * Why inline:\n * - Layout-critical: without these ratios cells collapse to text-content\n * width and the whole table reads as one mashed-up line.\n * - SDK self-containment: arbitrary-value classes only emit CSS when the\n * consumer's Tailwind v4 `@source` globs cover the file emitting them.\n * Common dev setups — `USE_LOCAL_SDK=true` aliasing imports from\n * `react-sdk/packages/*` — sidestep the consumer's `node_modules`\n * `@source` and silently drop the classes. Inline `style` always works.\n *\n * Total = 8.3, matching Axiom 1:1 so a 1440px-wide panel reproduces the\n * reference's column widths exactly. Position gets 1.2 to fit\n * `Long 0.000 12345 BTC` on one line; Margin (PNL) gets 1.5 — widest\n * column, has to host margin amount + signed PnL + abs %.\n */\nconst COL_STYLE: Record<string, CSSProperties> = {\n asset: { flex: \"0.8 1 0%\" },\n position: { flex: \"1.2 1 0%\" },\n value: { flex: \"0.8 1 0%\" },\n entry: { flex: \"0.8 1 0%\" },\n mark: { flex: \"0.8 1 0%\" },\n liq: { flex: \"0.8 1 0%\" },\n marginPnl: { flex: \"1.5 1 0%\" },\n tpsl: { flex: \"0.8 1 0%\" },\n close: { flex: \"0.8 1 0%\" },\n};\n\n/** Min-width of the inner table body — same rationale as `COL_STYLE`. */\nconst TABLE_MIN_WIDTH: CSSProperties = { minWidth: 1000 };\n\n/**\n * Header row: 28px tall, fixed.\n *\n * Uses `min-height` + `max-height` rather than `height` because the\n * row participates in a `flex-1` flex-col cascade (flex-basis: 0%\n * overrides the `height` property and lets the row collapse to its\n * content's font-size). `min-height` / `max-height` win over flex\n * sizing and clamp the row to exactly 28px regardless of flex grow.\n * Mirrors Axiom's `max-h-[28px] min-h-[28px]` pair.\n */\nconst HEADER_ROW_STYLE: CSSProperties = { minHeight: 28, maxHeight: 28 };\n\n/**\n * Body row: 36px tall, fixed. Same rationale as {@link HEADER_ROW_STYLE}\n * — clamps via `min-height` / `max-height` so flex-grow can't compress it.\n */\nconst BODY_ROW_STYLE: CSSProperties = { minHeight: 36, maxHeight: 36 };\n\n// ---------------------------------------------------------------------------\n// Header\n// ---------------------------------------------------------------------------\n\ntype HeaderAlign = \"start\" | \"center\" | \"end\";\n\ntype HeaderCellProps = {\n /** Inline `style` carrying the column's flex ratio (one of `COL_STYLE`). */\n style: CSSProperties;\n /** Cell content — usually a `<span>` with the column title. */\n children: ReactNode;\n /** When set, the cell is sortable and clicking toggles the sort. */\n sortKey?: PositionSortKey;\n activeSortKey?: PositionSortKey | null;\n sortDir?: SortDirection;\n onSort?: (key: PositionSortKey) => void;\n /**\n * Horizontal alignment of the header label. Defaults to `\"start\"`.\n * `\"end\"` is used by `Close` (right-aligned action column).\n * `\"center\"` is used by `TP/SL` so the header sits visually above\n * the slash divider in the body's `1fr auto 1fr` grid.\n */\n align?: HeaderAlign;\n};\n\nconst ALIGN_TO_JUSTIFY: Record<HeaderAlign, string> = {\n start: \"justify-start\",\n center: \"justify-center\",\n end: \"justify-end\",\n};\n\n/**\n * One header cell. Sortable cells get `cursor-pointer` + a hover white\n * tint, an `↑`/`↓` glyph appended when active, and an accessible\n * `<button>` semantic so keyboard users can sort with Enter / Space.\n */\nfunction HeaderCell({\n style,\n children,\n sortKey,\n activeSortKey,\n sortDir,\n onSort,\n align = \"start\",\n}: HeaderCellProps) {\n const isActive = sortKey !== undefined && sortKey === activeSortKey;\n const arrow = isActive ? (sortDir === \"asc\" ? \" \\u2191\" : \" \\u2193\") : \"\";\n const interactive = sortKey !== undefined && onSort !== undefined;\n const justify = ALIGN_TO_JUSTIFY[align];\n\n const inner = (\n <span className=\"text-xs font-normal text-default-500\">\n {children}\n {arrow}\n </span>\n );\n\n if (!interactive) {\n return (\n <div style={style} className={cn(\"flex flex-row items-center\", justify)}>\n {inner}\n </div>\n );\n }\n\n return (\n <button\n type=\"button\"\n onClick={() => onSort?.(sortKey)}\n style={style}\n className={cn(\n \"flex flex-row items-center cursor-pointer hover:text-foreground\",\n justify,\n )}\n >\n {inner}\n </button>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\nexport type PositionsUIProps = {\n /** Already-sorted positions. The script layer owns sort state. */\n positions: Position[];\n /** Currently active sort column, or `null` when no sort applied. */\n sortKey: PositionSortKey | null;\n sortDir: SortDirection;\n onSort: (key: PositionSortKey) => void;\n onClosePosition: (position: Position) => void;\n isClosing: boolean;\n /** Optional className for the outer container. */\n className?: string;\n};\n\nexport function PositionsUI({\n positions,\n sortKey,\n sortDir,\n onSort,\n onClosePosition,\n isClosing,\n className,\n}: PositionsUIProps) {\n const { t } = useTranslation();\n\n // Header is always rendered (even when empty) so the column legend\n // is visible while waiting for the first position. Mirrors Axiom.\n const header = (\n <div\n style={HEADER_ROW_STYLE}\n className=\"flex flex-1 flex-row items-center justify-start border-default-200 px-4 sm:border-b\"\n >\n <HeaderCell\n style={COL_STYLE.asset}\n sortKey=\"asset\"\n activeSortKey={sortKey}\n sortDir={sortDir}\n onSort={onSort}\n >\n {t(\"perpetuals.positions.col.asset\")}\n </HeaderCell>\n <HeaderCell\n style={COL_STYLE.position}\n sortKey=\"position\"\n activeSortKey={sortKey}\n sortDir={sortDir}\n onSort={onSort}\n >\n {t(\"perpetuals.positions.col.position\")}\n </HeaderCell>\n <HeaderCell\n style={COL_STYLE.value}\n sortKey=\"value\"\n activeSortKey={sortKey}\n sortDir={sortDir}\n onSort={onSort}\n >\n {t(\"perpetuals.positions.col.positionValue\")}\n </HeaderCell>\n <HeaderCell\n style={COL_STYLE.entry}\n sortKey=\"entry\"\n activeSortKey={sortKey}\n sortDir={sortDir}\n onSort={onSort}\n >\n {t(\"perpetuals.positions.col.entryPrice\")}\n </HeaderCell>\n <HeaderCell\n style={COL_STYLE.mark}\n sortKey=\"mark\"\n activeSortKey={sortKey}\n sortDir={sortDir}\n onSort={onSort}\n >\n {t(\"perpetuals.positions.col.markPrice\")}\n </HeaderCell>\n <HeaderCell\n style={COL_STYLE.liq}\n sortKey=\"liq\"\n activeSortKey={sortKey}\n sortDir={sortDir}\n onSort={onSort}\n >\n <StyledTooltip\n content={t(\"perpetuals.positions.tooltip.liqPrice\")}\n placement=\"top\"\n delay={200}\n closeDelay={0}\n >\n <span className=\"border-b border-dashed border-default-500/40\">\n <span className=\"hidden sm:inline\">\n {t(\"perpetuals.positions.col.liqPrice\")}\n </span>\n <span className=\"inline sm:hidden\">\n {t(\"perpetuals.positions.col.liqPriceShort\")}\n </span>\n </span>\n </StyledTooltip>\n </HeaderCell>\n <HeaderCell\n style={COL_STYLE.marginPnl}\n sortKey=\"marginPnl\"\n activeSortKey={sortKey}\n sortDir={sortDir}\n onSort={onSort}\n >\n <StyledTooltip\n content={t(\"perpetuals.positions.tooltip.marginPnl\")}\n placement=\"top\"\n delay={200}\n closeDelay={0}\n >\n <span className=\"border-b border-dashed border-default-500/40\">\n {t(\"perpetuals.positions.col.marginPnl\")}\n </span>\n </StyledTooltip>\n </HeaderCell>\n <HeaderCell style={COL_STYLE.tpsl} align=\"center\">\n {t(\"perpetuals.positions.col.tpsl\")}\n </HeaderCell>\n <HeaderCell style={COL_STYLE.close} align=\"end\">\n {t(\"perpetuals.positions.col.close\")}\n </HeaderCell>\n </div>\n );\n\n // Empty state: keep the header for layout context, render a centred\n // \"no positions\" line below.\n if (positions.length === 0) {\n return (\n <div\n className={cn(\n \"flex w-full min-w-0 flex-col overflow-hidden bg-transparent\",\n className,\n )}\n >\n <div className=\"flex flex-1 flex-col overflow-x-auto\">\n <div\n style={{ ...TABLE_MIN_WIDTH, ...HEADER_ROW_STYLE }}\n className=\"flex flex-1 flex-col\"\n >\n {header}\n </div>\n <div\n style={TABLE_MIN_WIDTH}\n className=\"flex flex-1 flex-col items-center justify-center py-6 text-xs text-default-700\"\n >\n {t(\"perpetuals.positions.empty\")}\n </div>\n </div>\n </div>\n );\n }\n\n return (\n <div\n className={cn(\n \"flex w-full min-w-0 flex-col overflow-hidden bg-transparent\",\n className,\n )}\n >\n <div className=\"flex flex-1 flex-col overflow-x-auto\">\n <div\n style={{ ...TABLE_MIN_WIDTH, ...HEADER_ROW_STYLE }}\n className=\"flex flex-1 flex-col\"\n >\n {header}\n </div>\n <div\n style={TABLE_MIN_WIDTH}\n className=\"flex flex-1 flex-col overflow-y-auto\"\n >\n {positions.map((position, index) => (\n <PositionRow\n key={position.symbol}\n position={position}\n striped={index % 2 === 1}\n isClosing={isClosing}\n onClose={onClosePosition}\n />\n ))}\n </div>\n </div>\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Row\n// ---------------------------------------------------------------------------\n\ntype PositionRowProps = {\n position: Position;\n /** Zebra striping — every other row gets a faint background. */\n striped: boolean;\n isClosing: boolean;\n onClose: (position: Position) => void;\n};\n\nfunction PositionRow({\n position,\n striped,\n isClosing,\n onClose,\n}: PositionRowProps) {\n const { t } = useTranslation();\n const tokenSymbol = position.symbol.split(\"-\")[0];\n const isLong = position.side === \"long\";\n const directionLabel = isLong\n ? t(\"perpetuals.positions.long\")\n : t(\"perpetuals.positions.short\");\n const directionColor = isLong ? \"text-bullish\" : \"text-bearish\";\n\n const isProfitable = position.unrealizedPnl >= 0;\n const pnlColor = isProfitable ? \"text-bullish\" : \"text-bearish\";\n\n return (\n <div className={cn(striped ? \"bg-default-100/30\" : \"bg-transparent\")}>\n <div\n style={BODY_ROW_STYLE}\n className=\"flex flex-1 flex-row items-center justify-start px-4\"\n >\n {/* Asset — icon + symbol, hover underline. Click target left\n for a future \"deep-link to chart\" wiring (PR3). */}\n <div\n style={COL_STYLE.asset}\n className=\"flex flex-row items-center justify-start gap-1.5\"\n >\n <img\n alt={tokenSymbol}\n src={`https://app.hyperliquid.xyz/coins/${tokenSymbol}.svg`}\n className=\"rounded-full\"\n style={{ width: 16, height: 16 }}\n onError={(e) => {\n (e.currentTarget as HTMLImageElement).style.display = \"none\";\n }}\n />\n <span className=\"text-xs font-medium text-foreground\">\n {tokenSymbol}\n </span>\n </div>\n\n {/* Position — `Long/Short` (themed) + size + coin */}\n <div\n style={COL_STYLE.position}\n className=\"flex flex-row items-center justify-start gap-1\"\n >\n <span className={cn(\"text-xs font-medium\", directionColor)}>\n {directionLabel}\n </span>\n <span className=\"text-xs font-normal text-default-700\">\n {formatQuantity(position.quantity, position.quantityRaw)}{\" \"}\n {tokenSymbol}\n </span>\n </div>\n\n {/* Position Value */}\n <div\n style={COL_STYLE.value}\n className=\"flex flex-row items-center justify-start\"\n >\n <span className=\"text-xs font-normal text-default-700\">\n {formatUsd2(position.notionalValue)}\n </span>\n </div>\n\n {/* Entry Price */}\n <div\n style={COL_STYLE.entry}\n className=\"flex flex-row items-center justify-start\"\n >\n <span className=\"text-xs font-normal text-default-700\">\n {formatUsdPrice(position.entryPrice)}\n </span>\n </div>\n\n {/* Mark Price */}\n <div\n style={COL_STYLE.mark}\n className=\"flex flex-row items-center justify-start\"\n >\n <span className=\"text-xs font-normal text-default-700\">\n {formatUsdPrice(position.markPrice)}\n </span>\n </div>\n\n {/* Liquidation Price */}\n <div\n style={COL_STYLE.liq}\n className=\"flex flex-row items-center justify-start\"\n >\n <span className=\"text-xs font-normal text-default-700\">\n {formatUsdPrice(position.liquidationPrice)}\n </span>\n </div>\n\n {/* Margin Used (PNL) — single row: `$margin (signedPnl / abs%)`\n with the PnL block tinted bullish/bearish so colour alone\n tells direction; sign + percent stay intelligible without\n colour for accessibility. */}\n <div\n style={COL_STYLE.marginPnl}\n className=\"flex flex-row items-center justify-start gap-1\"\n >\n <span className=\"text-xs font-normal text-default-700\">\n {formatUsd2(position.margin)}\n </span>\n <span className={cn(\"text-xs font-medium\", pnlColor)}>\n ({formatSignedUsd2(position.unrealizedPnl)} /{\" \"}\n {formatPercentAbs(position.unrealizedPnlPercent)})\n </span>\n </div>\n\n {/* TP / SL — derived client-side from the user's reduceOnly\n trigger orders. Layout mirrors Axiom: a 3-cell inline grid\n with TP right-aligned, slash divider, SL left-aligned, so\n the slash always sits at the cell's centre even when one\n side is missing. Picks the closing-side trigger only\n (Long → SELL, Short → BUY) so orphan triggers from a\n previously-closed opposite-direction position never bleed\n into this row.\n `display: grid` + `gridTemplateColumns` is inline because\n arbitrary-value classes (`grid-cols-[1fr_auto_1fr]`) only\n emit CSS when Tailwind scans the source; in `USE_LOCAL_SDK`\n mode the consumer's `@source` globs miss this file. */}\n <div\n style={{\n ...COL_STYLE.tpsl,\n display: \"grid\",\n gridTemplateColumns: \"1fr auto 1fr\",\n alignItems: \"center\",\n }}\n >\n <span className=\"pr-1 text-right text-xs font-normal text-default-700\">\n {position.takeProfitPrice !== undefined\n ? formatUsdPrice(position.takeProfitPrice)\n : \"--\"}\n </span>\n <span className=\"text-xs font-normal text-default-500\">/</span>\n <span className=\"pl-1 text-left text-xs font-normal text-default-700\">\n {position.stopLossPrice !== undefined\n ? formatUsdPrice(position.stopLossPrice)\n : \"--\"}\n </span>\n </div>\n\n {/* Close — single `Market` action in `text-bearish` (theme\n secondary). The Axiom split into `Market` / `Limit` is a\n future expansion: limit-close needs a price input and a\n second mutation path. Tracking as a follow-up. */}\n <div\n style={COL_STYLE.close}\n className=\"flex flex-row items-center justify-end gap-2\"\n >\n <button\n type=\"button\"\n onClick={() => onClose(position)}\n disabled={isClosing}\n className={cn(\n \"text-xs font-medium text-bearish\",\n \"transition-opacity duration-150 ease-in-out\",\n \"hover:opacity-80 disabled:cursor-not-allowed disabled:opacity-50\",\n )}\n >\n {t(\"perpetuals.positions.close.market\")}\n </button>\n </div>\n </div>\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Skeleton / Empty\n// ---------------------------------------------------------------------------\n\n/** Loading skeleton for positions panel */\nexport function PositionsSkeleton() {\n return (\n <div className=\"w-full space-y-4 p-4\">\n <div className=\"h-4 bg-neutral-800 rounded w-full animate-pulse\" />\n <div className=\"h-4 bg-neutral-800 rounded w-full animate-pulse\" />\n <div className=\"h-4 bg-neutral-800 rounded w-full animate-pulse\" />\n </div>\n );\n}\n\n/**\n * Standalone empty-state component. The main `PositionsUI` renders its\n * own empty layout (header + centred message) so this export exists for\n * consumers that wire their own empty state outside the widget.\n */\nexport function PositionsEmpty() {\n return (\n <div className=\"flex h-24 items-center justify-center text-[14px] text-default-700\">\n No open positions\n </div>\n );\n}\n","import { usePositionsScript } from \"./positions.script\";\nimport { PositionsUI, PositionsSkeleton } from \"./positions.ui\";\n\nexport type PositionsWidgetProps = {\n userAddress?: string;\n symbol?: string;\n onCloseSuccess?: () => void;\n onCloseError?: (error: Error) => void;\n className?: string;\n};\n\n/**\n * Positions table widget. Owns no business logic — wires the\n * `usePositionsScript` data layer (sort + close-mutation) to the\n * presentational `PositionsUI`. The host page just provides the\n * connected wallet address and (optionally) a symbol filter; the\n * widget handles everything else (sort state, realtime updates,\n * close-position toasts in the consumer's mutation lifecycle).\n */\nexport function PositionsWidget({\n userAddress,\n symbol,\n onCloseSuccess,\n onCloseError,\n className,\n}: PositionsWidgetProps) {\n const {\n positions,\n isLoading,\n sortKey,\n sortDir,\n onSort,\n handleClosePosition,\n isClosing,\n } = usePositionsScript({\n userAddress,\n symbol,\n onCloseSuccess,\n onCloseError,\n });\n\n if (isLoading) {\n return (\n <div className={className}>\n <PositionsSkeleton />\n </div>\n );\n }\n\n return (\n <PositionsUI\n positions={positions}\n sortKey={sortKey}\n sortDir={sortDir}\n onSort={onSort}\n onClosePosition={handleClosePosition}\n isClosing={isClosing}\n className={className}\n />\n );\n}\n","import { useState, useEffect, useCallback } from \"react\";\nimport { useCancelOrderMutation } from \"../../hooks/useCancelOrderMutation\";\nimport { useOrdersQuery } from \"../../hooks/useOrdersQuery\";\nimport { useUserDataSubscription } from \"../../hooks/useUserDataSubscription\";\nimport type { Order } from \"../../types\";\n\nexport type UseOpenOrdersScriptParams = {\n userAddress?: string;\n symbol?: string;\n onCancelSuccess?: () => void;\n onCancelError?: (error: Error) => void;\n};\n\nexport type UseOpenOrdersScriptResult = {\n orders: Order[];\n isLoading: boolean;\n error: Error | null;\n handleCancelOrder: (order: Order) => Promise<void>;\n isCanceling: boolean;\n};\n\nexport function useOpenOrdersScript({\n userAddress,\n symbol,\n onCancelSuccess,\n onCancelError,\n}: UseOpenOrdersScriptParams): UseOpenOrdersScriptResult {\n const [orders, setOrders] = useState<Order[]>([]);\n\n // Fetch initial orders data\n const {\n data: ordersData,\n isLoading,\n error,\n } = useOrdersQuery({ userAddress, symbol }, { enabled: !!userAddress });\n\n // Subscribe to realtime order updates\n const { data: realtimeOrder } = useUserDataSubscription<Order>({\n type: \"orders\",\n userAddress: userAddress || \"\",\n enabled: !!userAddress,\n });\n\n // Cancel order mutation\n const { mutateAsync: cancelOrder, isPending: isCanceling } =\n useCancelOrderMutation({\n onSuccess: () => {\n onCancelSuccess?.();\n },\n onError: (error) => {\n onCancelError?.(error);\n },\n });\n\n // Initialize orders data\n useEffect(() => {\n if (ordersData?.orders) {\n setOrders(ordersData.orders);\n }\n }, [ordersData]);\n\n // Handle realtime order updates\n useEffect(() => {\n if (realtimeOrder) {\n setOrders((prevOrders) => {\n const existingIndex = prevOrders.findIndex(\n (o) => o.orderId === realtimeOrder.orderId,\n );\n\n // If order is cancelled, filled or rejected, remove from list\n if (\n realtimeOrder.status === \"cancelled\" ||\n realtimeOrder.status === \"filled\" ||\n realtimeOrder.status === \"rejected\"\n ) {\n if (existingIndex !== -1) {\n return prevOrders.filter((_, i) => i !== existingIndex);\n }\n return prevOrders;\n }\n\n // Update existing order\n if (existingIndex !== -1) {\n const newOrders = [...prevOrders];\n newOrders[existingIndex] = realtimeOrder;\n return newOrders;\n }\n\n // Add new order\n return [realtimeOrder, ...prevOrders];\n });\n }\n }, [realtimeOrder]);\n\n // Handle cancel order\n const handleCancelOrder = useCallback(\n async (order: Order) => {\n if (!userAddress) {\n throw new Error(\"User address is required\");\n }\n\n await cancelOrder({\n orderId: order.orderId,\n symbol: order.symbol,\n userAddress,\n });\n },\n [userAddress, cancelOrder],\n );\n\n return {\n orders,\n isLoading,\n error,\n handleCancelOrder,\n isCanceling,\n };\n}\n","import { Button, cn } from \"@liberfi.io/ui\";\nimport type { Order } from \"../../types\";\n\nexport type OpenOrdersUIProps = {\n orders: Order[];\n onCancelOrder: (order: Order) => void;\n isCanceling: boolean;\n};\n\nfunction formatNumber(num: number, decimals: number = 2): string {\n return num.toFixed(decimals);\n}\n\nfunction formatPrice(price: number): string {\n return formatNumber(price, 4);\n}\n\nfunction formatQuantity(quantity: number): string {\n return formatNumber(quantity, 4);\n}\n\nfunction formatTime(timestamp: number): string {\n const date = new Date(timestamp);\n const hours = String(date.getHours()).padStart(2, \"0\");\n const minutes = String(date.getMinutes()).padStart(2, \"0\");\n const seconds = String(date.getSeconds()).padStart(2, \"0\");\n return `${hours}:${minutes}:${seconds}`;\n}\n\nexport function OpenOrdersUI({\n orders,\n onCancelOrder,\n isCanceling,\n}: OpenOrdersUIProps) {\n if (orders.length === 0) {\n return (\n <div\n className=\"flex items-center justify-center h-24\"\n style={{ fontSize: 11, color: \"#b5b5b5\" }}\n >\n No open orders\n </div>\n );\n }\n\n return (\n <div className=\"w-full overflow-x-auto bg-transparent\">\n <table className=\"w-full\" style={{ fontSize: 11 }}>\n <thead>\n <tr style={{ borderBottom: \"1px solid #1c1c1c\" }}>\n <th\n className=\"text-left py-1.5 px-3 font-normal\"\n style={{ fontSize: 11, color: \"#b5b5b5\" }}\n >\n Asset\n </th>\n <th\n className=\"text-left py-1.5 px-3 font-normal\"\n style={{ fontSize: 11, color: \"#b5b5b5\" }}\n >\n Type\n </th>\n <th\n className=\"text-right py-1.5 px-3 font-normal\"\n style={{ fontSize: 11, color: \"#b5b5b5\" }}\n >\n Price\n </th>\n <th\n className=\"text-right py-1.5 px-3 font-normal\"\n style={{ fontSize: 11, color: \"#b5b5b5\" }}\n >\n Amount\n </th>\n <th\n className=\"text-right py-1.5 px-3 font-normal\"\n style={{ fontSize: 11, color: \"#b5b5b5\" }}\n >\n Filled\n </th>\n <th\n className=\"text-right py-1.5 px-3 font-normal\"\n style={{ fontSize: 11, color: \"#b5b5b5\" }}\n >\n Remaining\n </th>\n <th\n className=\"text-right py-1.5 px-3 font-normal\"\n style={{ fontSize: 11, color: \"#b5b5b5\" }}\n >\n Status\n </th>\n <th\n className=\"text-right py-1.5 px-3 font-normal\"\n style={{ fontSize: 11, color: \"#b5b5b5\" }}\n >\n Time\n </th>\n <th\n className=\"text-right py-1.5 px-3 font-normal\"\n style={{ fontSize: 11, color: \"#b5b5b5\" }}\n >\n Action\n </th>\n </tr>\n </thead>\n <tbody>\n {orders.map((order) => {\n return (\n <tr\n key={order.orderId}\n className=\"hover:bg-neutral-900/50\"\n style={{ borderBottom: \"1px solid #1c1c1c\" }}\n >\n {/* Asset */}\n <td className=\"py-1.5 px-3\">\n <div className=\"flex flex-col\">\n <span className=\"font-medium\" style={{ color: \"#ffffff\" }}>\n {order.symbol.split(\"-\")[0]}\n </span>\n <span\n className={cn(\n order.side === \"long\" ? \"text-bullish\" : \"text-bearish\",\n )}\n >\n {order.side.toUpperCase()}\n {order.leverage ? ` ${order.leverage}x` : \"\"}\n </span>\n </div>\n </td>\n\n {/* Type */}\n <td\n className=\"py-1.5 px-3 capitalize\"\n style={{ color: \"#ffffff\" }}\n >\n {order.orderType}\n </td>\n\n {/* Price */}\n <td\n className=\"py-1.5 px-3 text-right\"\n style={{ color: \"#ffffff\" }}\n >\n {order.orderType === \"market\" ? (\n <span style={{ color: \"#b5b5b5\" }}>Market</span>\n ) : (\n `$${formatPrice(order.price)}`\n )}\n </td>\n\n {/* Amount */}\n <td\n className=\"py-1.5 px-3 text-right\"\n style={{ color: \"#ffffff\" }}\n >\n {formatQuantity(order.quantity)}\n </td>\n\n {/* Filled */}\n <td\n className=\"py-1.5 px-3 text-right\"\n style={{ color: \"#ffffff\" }}\n >\n {formatQuantity(order.filledQuantity)}\n </td>\n\n {/* Remaining */}\n <td\n className=\"py-1.5 px-3 text-right\"\n style={{ color: \"#ffffff\" }}\n >\n {formatQuantity(order.remainingQuantity)}\n </td>\n\n {/* Status */}\n <td className=\"py-1.5 px-3 text-right\">\n <span\n className={cn(\n \"px-2 py-0.5 rounded\",\n \"text-[11px]\",\n order.status === \"pending\" &&\n \"bg-yellow-600/20 text-yellow-500\",\n order.status === \"partially_filled\" &&\n \"bg-blue-600/20 text-blue-500\",\n order.status === \"filled\" &&\n \"bg-green-600/20 text-green-500\",\n order.status === \"cancelled\" &&\n \"bg-neutral-600/20 text-neutral-400\",\n order.status === \"rejected\" &&\n \"bg-red-600/20 text-red-500\",\n )}\n >\n {order.status.replace(\"_\", \" \")}\n </span>\n </td>\n\n {/* Time */}\n <td\n className=\"py-1.5 px-3 text-right\"\n style={{ color: \"#b5b5b5\" }}\n >\n {formatTime(order.timestamp)}\n </td>\n\n {/* Action */}\n <td className=\"py-1.5 px-3 text-right\">\n {order.status === \"pending\" ||\n order.status === \"partially_filled\" ? (\n <Button\n size=\"sm\"\n onClick={() => onCancelOrder(order)}\n isLoading={isCanceling}\n className=\"bg-red-600 hover:bg-red-700 text-white text-xs px-3 py-1\"\n >\n Cancel\n </Button>\n ) : (\n <span className=\"text-[11px]\" style={{ color: \"#6b6d7a\" }}>\n -\n </span>\n )}\n </td>\n </tr>\n );\n })}\n </tbody>\n </table>\n </div>\n );\n}\n\n// Loading skeleton component\nexport function OpenOrdersSkeleton() {\n return (\n <div className=\"w-full space-y-4 p-4\">\n <div className=\"h-4 bg-neutral-800 rounded w-full animate-pulse\" />\n <div className=\"h-4 bg-neutral-800 rounded w-full animate-pulse\" />\n <div className=\"h-4 bg-neutral-800 rounded w-full animate-pulse\" />\n </div>\n );\n}\n\n// Empty state component\nexport function OpenOrdersEmpty() {\n return (\n <div\n className=\"flex items-center justify-center h-24\"\n style={{ fontSize: 11, color: \"#b5b5b5\" }}\n >\n No open orders\n </div>\n );\n}\n","import { useOpenOrdersScript } from \"./open-orders.script\";\nimport {\n OpenOrdersUI,\n OpenOrdersSkeleton,\n OpenOrdersEmpty,\n} from \"./open-orders.ui\";\n\nexport type OpenOrdersWidgetProps = {\n userAddress?: string;\n symbol?: string;\n onCancelSuccess?: () => void;\n onCancelError?: (error: Error) => void;\n className?: string;\n};\n\nexport function OpenOrdersWidget({\n userAddress,\n symbol,\n onCancelSuccess,\n onCancelError,\n className,\n}: OpenOrdersWidgetProps) {\n const { orders, isLoading, handleCancelOrder, isCanceling } =\n useOpenOrdersScript({\n userAddress,\n symbol,\n onCancelSuccess,\n onCancelError,\n });\n\n if (isLoading) {\n return (\n <div className={className}>\n <OpenOrdersSkeleton />\n </div>\n );\n }\n\n if (orders.length === 0) {\n return (\n <div className={className}>\n <OpenOrdersEmpty />\n </div>\n );\n }\n\n return (\n <div className={className}>\n <OpenOrdersUI\n orders={orders}\n onCancelOrder={handleCancelOrder}\n isCanceling={isCanceling}\n />\n </div>\n );\n}\n","import { useState, useEffect } from \"react\";\nimport { useTradesQuery } from \"../../hooks/useTradesQuery\";\nimport type { TradeHistory } from \"../../types\";\n\nexport type TimeRange = \"today\" | \"7d\" | \"30d\" | \"all\";\n\nexport type UseTradeHistoryScriptParams = {\n userAddress?: string;\n symbol?: string;\n initialTimeRange?: TimeRange;\n pageSize?: number;\n};\n\nexport type UseTradeHistoryScriptResult = {\n trades: TradeHistory[];\n isLoading: boolean;\n error: Error | null;\n timeRange: TimeRange;\n setTimeRange: (range: TimeRange) => void;\n currentPage: number;\n totalPages: number;\n goToNextPage: () => void;\n goToPreviousPage: () => void;\n goToPage: (page: number) => void;\n};\n\nfunction getTimeRangeInMs(range: TimeRange): {\n startTime?: number;\n endTime?: number;\n} {\n const now = Date.now();\n const endTime = now;\n\n switch (range) {\n case \"today\":\n const today = new Date();\n today.setHours(0, 0, 0, 0);\n return { startTime: today.getTime(), endTime };\n case \"7d\":\n return { startTime: now - 7 * 24 * 60 * 60 * 1000, endTime };\n case \"30d\":\n return { startTime: now - 30 * 24 * 60 * 60 * 1000, endTime };\n case \"all\":\n default:\n return {};\n }\n}\n\nexport function useTradeHistoryScript({\n userAddress,\n symbol,\n initialTimeRange = \"7d\",\n pageSize = 50,\n}: UseTradeHistoryScriptParams): UseTradeHistoryScriptResult {\n const [timeRange, setTimeRange] = useState<TimeRange>(initialTimeRange);\n const [currentPage, setCurrentPage] = useState(1);\n const [allTrades, setAllTrades] = useState<TradeHistory[]>([]);\n\n const { startTime, endTime } = getTimeRangeInMs(timeRange);\n\n // Fetch trades with time range filter\n const {\n data: tradesData,\n isLoading,\n error,\n } = useTradesQuery(\n {\n userAddress,\n symbol,\n startTime,\n endTime,\n limit: 1000, // Fetch more data for client-side pagination\n },\n { enabled: !!userAddress },\n );\n\n // Update all trades when data changes\n useEffect(() => {\n if (tradesData?.trades) {\n setAllTrades(tradesData.trades);\n setCurrentPage(1); // Reset to first page when data changes\n }\n }, [tradesData]);\n\n // Reset page when time range changes\n useEffect(() => {\n setCurrentPage(1);\n }, [timeRange]);\n\n // Calculate pagination\n const totalPages = Math.ceil(allTrades.length / pageSize);\n const startIndex = (currentPage - 1) * pageSize;\n const endIndex = startIndex + pageSize;\n const trades = allTrades.slice(startIndex, endIndex);\n\n const goToNextPage = () => {\n if (currentPage < totalPages) {\n setCurrentPage(currentPage + 1);\n }\n };\n\n const goToPreviousPage = () => {\n if (currentPage > 1) {\n setCurrentPage(currentPage - 1);\n }\n };\n\n const goToPage = (page: number) => {\n if (page >= 1 && page <= totalPages) {\n setCurrentPage(page);\n }\n };\n\n return {\n trades,\n isLoading,\n error,\n timeRange,\n setTimeRange,\n currentPage,\n totalPages,\n goToNextPage,\n goToPreviousPage,\n goToPage,\n };\n}\n","import { Button, cn } from \"@liberfi.io/ui\";\nimport type { TradeHistory } from \"../../types\";\nimport type { TimeRange } from \"./trade-history.script\";\n\nexport type TradeHistoryUIProps = {\n trades: TradeHistory[];\n timeRange: TimeRange;\n onTimeRangeChange: (range: TimeRange) => void;\n currentPage: number;\n totalPages: number;\n onNextPage: () => void;\n onPreviousPage: () => void;\n onGoToPage: (page: number) => void;\n};\n\nfunction formatNumber(num: number, decimals: number = 2): string {\n return num.toFixed(decimals);\n}\n\nfunction formatPrice(price: number): string {\n return formatNumber(price, 4);\n}\n\nfunction formatQuantity(quantity: number): string {\n return formatNumber(quantity, 4);\n}\n\nfunction formatDateTime(timestamp: number): string {\n const date = new Date(timestamp);\n const month = String(date.getMonth() + 1).padStart(2, \"0\");\n const day = String(date.getDate()).padStart(2, \"0\");\n const hours = String(date.getHours()).padStart(2, \"0\");\n const minutes = String(date.getMinutes()).padStart(2, \"0\");\n const seconds = String(date.getSeconds()).padStart(2, \"0\");\n return `${month}/${day} ${hours}:${minutes}:${seconds}`;\n}\n\nconst TIME_RANGE_OPTIONS: { label: string; value: TimeRange }[] = [\n { label: \"Today\", value: \"today\" },\n { label: \"7 Days\", value: \"7d\" },\n { label: \"30 Days\", value: \"30d\" },\n { label: \"All\", value: \"all\" },\n];\n\nexport function TradeHistoryUI({\n trades,\n timeRange,\n onTimeRangeChange,\n currentPage,\n totalPages,\n onNextPage,\n onPreviousPage,\n onGoToPage,\n}: TradeHistoryUIProps) {\n return (\n <div className=\"w-full flex flex-col gap-4\">\n {/* Time range filter */}\n <div className=\"flex gap-2\">\n {TIME_RANGE_OPTIONS.map((option) => {\n const selected = timeRange === option.value;\n return (\n <button\n key={option.value}\n type=\"button\"\n className={cn(\n \"rounded px-3 transition-colors\",\n !selected && \"hover:bg-[#1A1A1A]\",\n )}\n style={{\n height: 24,\n fontSize: 11,\n border: \"1px solid #1c1c1c\",\n backgroundColor: selected ? \"#1c1c1c\" : \"transparent\",\n color: selected ? \"#ffffff\" : \"#b5b5b5\",\n }}\n onClick={() => onTimeRangeChange(option.value)}\n >\n {option.label}\n </button>\n );\n })}\n </div>\n\n {/* Trade history table */}\n {trades.length === 0 ? (\n <div\n className=\"flex items-center justify-center h-24\"\n style={{ fontSize: 11, color: \"#b5b5b5\" }}\n >\n No trade history\n </div>\n ) : (\n <>\n <div className=\"w-full overflow-x-auto bg-transparent\">\n <table className=\"w-full\" style={{ fontSize: 11 }}>\n <thead>\n <tr style={{ borderBottom: \"1px solid #1c1c1c\" }}>\n <th\n className=\"text-left py-1.5 px-3 font-normal\"\n style={{ fontSize: 11, color: \"#b5b5b5\" }}\n >\n Asset\n </th>\n <th\n className=\"text-left py-1.5 px-3 font-normal\"\n style={{ fontSize: 11, color: \"#b5b5b5\" }}\n >\n Side\n </th>\n <th\n className=\"text-right py-1.5 px-3 font-normal\"\n style={{ fontSize: 11, color: \"#b5b5b5\" }}\n >\n Price\n </th>\n <th\n className=\"text-right py-1.5 px-3 font-normal\"\n style={{ fontSize: 11, color: \"#b5b5b5\" }}\n >\n Quantity\n </th>\n <th\n className=\"text-right py-1.5 px-3 font-normal\"\n style={{ fontSize: 11, color: \"#b5b5b5\" }}\n >\n Fee\n </th>\n <th\n className=\"text-center py-1.5 px-3 font-normal\"\n style={{ fontSize: 11, color: \"#b5b5b5\" }}\n >\n Maker/Taker\n </th>\n <th\n className=\"text-right py-1.5 px-3 font-normal\"\n style={{ fontSize: 11, color: \"#b5b5b5\" }}\n >\n Time\n </th>\n </tr>\n </thead>\n <tbody>\n {trades.map((trade) => (\n <tr\n key={trade.tradeId}\n className=\"hover:bg-neutral-900/50\"\n style={{ borderBottom: \"1px solid #1c1c1c\" }}\n >\n {/* Asset */}\n <td\n className=\"py-1.5 px-3 font-medium\"\n style={{ color: \"#ffffff\" }}\n >\n {trade.symbol.split(\"-\")[0]}\n </td>\n\n {/* Side */}\n <td className=\"py-1.5 px-3\">\n <span\n className={cn(\n \"px-2 py-0.5 rounded text-[11px]\",\n trade.side === \"long\"\n ? \"bg-bullish/20 text-bullish\"\n : \"bg-bearish/20 text-bearish\",\n )}\n >\n {trade.side.toUpperCase()}\n </span>\n </td>\n\n {/* Price */}\n <td\n className=\"py-1.5 px-3 text-right\"\n style={{ color: \"#ffffff\" }}\n >\n ${formatPrice(trade.price)}\n </td>\n\n {/* Quantity */}\n <td\n className=\"py-1.5 px-3 text-right\"\n style={{ color: \"#ffffff\" }}\n >\n {formatQuantity(trade.quantity)}\n </td>\n\n {/* Fee */}\n <td\n className=\"py-1.5 px-3 text-right\"\n style={{ color: \"#ffffff\" }}\n >\n {formatNumber(trade.fee, 4)} {trade.feeCurrency}\n </td>\n\n {/* Maker/Taker */}\n <td className=\"py-1.5 px-3 text-center\">\n <span\n className={cn(\n \"px-2 py-0.5 rounded text-[11px]\",\n trade.isMaker\n ? \"bg-blue-600/20 text-blue-500\"\n : \"bg-purple-600/20 text-purple-500\",\n )}\n >\n {trade.isMaker ? \"Maker\" : \"Taker\"}\n </span>\n </td>\n\n {/* Time */}\n <td\n className=\"py-1.5 px-3 text-right\"\n style={{ color: \"#b5b5b5\" }}\n >\n {formatDateTime(trade.timestamp)}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n\n {/* Pagination */}\n {totalPages > 1 && (\n <div className=\"flex items-center justify-between\">\n <div className=\"text-sm text-neutral-400\">\n Page {currentPage} of {totalPages}\n </div>\n <div className=\"flex gap-2\">\n <Button\n size=\"sm\"\n onClick={onPreviousPage}\n disabled={currentPage === 1}\n className=\"bg-neutral-800 hover:bg-neutral-700 text-white disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n Previous\n </Button>\n {/* Page numbers */}\n <div className=\"flex gap-1\">\n {Array.from({ length: Math.min(5, totalPages) }, (_, i) => {\n let pageNum: number;\n if (totalPages <= 5) {\n pageNum = i + 1;\n } else if (currentPage <= 3) {\n pageNum = i + 1;\n } else if (currentPage >= totalPages - 2) {\n pageNum = totalPages - 4 + i;\n } else {\n pageNum = currentPage - 2 + i;\n }\n\n return (\n <button\n key={pageNum}\n type=\"button\"\n className={cn(\n \"w-8 h-8 text-sm rounded transition-colors\",\n currentPage === pageNum\n ? \"bg-neutral-700 text-white\"\n : \"text-neutral-400 hover:bg-neutral-800 hover:text-white\",\n )}\n onClick={() => onGoToPage(pageNum)}\n >\n {pageNum}\n </button>\n );\n })}\n </div>\n <Button\n size=\"sm\"\n onClick={onNextPage}\n disabled={currentPage === totalPages}\n className=\"bg-neutral-800 hover:bg-neutral-700 text-white disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n Next\n </Button>\n </div>\n </div>\n )}\n </>\n )}\n </div>\n );\n}\n\n// Loading skeleton component\nexport function TradeHistorySkeleton() {\n return (\n <div className=\"w-full space-y-4 p-4\">\n <div className=\"h-4 bg-neutral-800 rounded w-full animate-pulse\" />\n <div className=\"h-4 bg-neutral-800 rounded w-full animate-pulse\" />\n <div className=\"h-4 bg-neutral-800 rounded w-full animate-pulse\" />\n </div>\n );\n}\n\n// Empty state component\nexport function TradeHistoryEmpty() {\n return (\n <div\n className=\"flex items-center justify-center h-24\"\n style={{ fontSize: 11, color: \"#b5b5b5\" }}\n >\n No trade history\n </div>\n );\n}\n","import { useTradeHistoryScript } from \"./trade-history.script\";\nimport type { TimeRange } from \"./trade-history.script\";\nimport {\n TradeHistoryUI,\n TradeHistorySkeleton,\n TradeHistoryEmpty,\n} from \"./trade-history.ui\";\n\nexport type TradeHistoryWidgetProps = {\n userAddress?: string;\n symbol?: string;\n initialTimeRange?: TimeRange;\n pageSize?: number;\n className?: string;\n};\n\nexport function TradeHistoryWidget({\n userAddress,\n symbol,\n initialTimeRange = \"7d\",\n pageSize = 50,\n className,\n}: TradeHistoryWidgetProps) {\n const {\n trades,\n isLoading,\n timeRange,\n setTimeRange,\n currentPage,\n totalPages,\n goToNextPage,\n goToPreviousPage,\n goToPage,\n } = useTradeHistoryScript({\n userAddress,\n symbol,\n initialTimeRange,\n pageSize,\n });\n\n if (isLoading) {\n return (\n <div className={className}>\n <TradeHistorySkeleton />\n </div>\n );\n }\n\n if (trades.length === 0) {\n return (\n <div className={className}>\n <TradeHistoryEmpty />\n </div>\n );\n }\n\n return (\n <div className={className}>\n <TradeHistoryUI\n trades={trades}\n timeRange={timeRange}\n onTimeRangeChange={setTimeRange}\n currentPage={currentPage}\n totalPages={totalPages}\n onNextPage={goToNextPage}\n onPreviousPage={goToPreviousPage}\n onGoToPage={goToPage}\n />\n </div>\n );\n}\n","/**\n * Tiny number-formatting helpers shared by the deposit UI.\n *\n * We use plain `bigint` arithmetic here — never `Number(...)` on a\n * lamport / microUSDC value — so we never silently lose precision on\n * deposits that exceed `Number.MAX_SAFE_INTEGER` lamports.\n */\n\nconst LAMPORTS_PER_SOL = 1_000_000_000n;\n\n/**\n * Hyperliquid credits perp USDC at 8-decimal granularity (NOT the 6\n * decimals used by ERC-20 USDC on Arbitrum). Relay's `currencyOut.amount`\n * for a Hyperliquid bridge quote is therefore expressed in HL perp units\n * — divide by 1e8 to get the human-readable USDC amount.\n */\nexport const HL_USDC_DECIMALS = 8;\nconst HL_USDC_DIVISOR = 10n ** BigInt(HL_USDC_DECIMALS);\n\n/**\n * Convert a lamport amount (string bigint) to a SOL-denominated string\n * with `precision` decimals and trailing zeros stripped.\n */\nexport function lamportsToSol(value: string, precision = 4): string {\n if (!value) return \"0\";\n let n: bigint;\n try {\n n = BigInt(value);\n } catch {\n return \"0\";\n }\n return divToFixed(n, LAMPORTS_PER_SOL, precision);\n}\n\n/**\n * Convert a raw Hyperliquid USDC amount (8 decimals) to a USDC display\n * string with `precision` decimals and trailing zeros stripped.\n *\n * This is the unit returned by the perpetuals-server `/deposits/quote`\n * endpoint in `breakdown.expectedOutputUSDC` — it mirrors Hyperliquid's\n * internal perp-account precision, NOT the 6-decimal USDC token on\n * Arbitrum.\n */\nexport function hlUsdcRawToUsdc(\n value: string | undefined,\n precision = 2,\n): string {\n if (!value) return \"0\";\n let n: bigint;\n try {\n n = BigInt(value);\n } catch {\n return \"0\";\n }\n return divToFixed(n, HL_USDC_DIVISOR, precision);\n}\n\n/**\n * @deprecated Use {@link hlUsdcRawToUsdc} instead. The previous name\n * implied a 6-decimal microUSDC unit, but the Hyperliquid bridge actually\n * returns amounts at 8-decimal precision. Kept as a thin alias to avoid\n * a hard break for downstream callers; remove after consumers migrate.\n */\nexport const microUsdcToUsdc = hlUsdcRawToUsdc;\n\n/** Convert a SOL-denominated decimal string to a lamport `string` (bigint). */\nexport function solToLamports(value: string): string {\n if (!value) return \"0\";\n const [whole, frac = \"\"] = value.replace(/[\\s,]/g, \"\").split(\".\");\n if (!/^\\d*$/.test(whole) || !/^\\d*$/.test(frac)) return \"0\";\n // Pad / truncate the fractional component to 9 digits to match SOL.\n const fracPadded = (frac + \"000000000\").slice(0, 9);\n const combined = `${whole || \"0\"}${fracPadded}`.replace(/^0+(?=\\d)/, \"\");\n return combined === \"\" ? \"0\" : combined;\n}\n\nfunction divToFixed(\n numerator: bigint,\n denominator: bigint,\n precision: number,\n): string {\n const negative = numerator < 0n;\n const abs = negative ? -numerator : numerator;\n let whole = abs / denominator;\n const remainder = abs % denominator;\n if (precision <= 0) {\n // Round to nearest integer when precision is 0.\n if (remainder * 2n >= denominator) whole += 1n;\n return `${negative ? \"-\" : \"\"}${whole.toString()}`;\n }\n const scale = 10n ** BigInt(precision);\n let scaledRemainder = (remainder * scale + denominator / 2n) / denominator;\n // Carry over to the whole part when half-rounding pushed the fractional\n // component to or above `scale` (e.g. 0.999999 with precision 2 -> 1.00).\n if (scaledRemainder >= scale) {\n whole += 1n;\n scaledRemainder = 0n;\n }\n let frac = scaledRemainder.toString().padStart(precision, \"0\");\n // Trim trailing zeros for nicer display.\n frac = frac.replace(/0+$/, \"\");\n if (!frac) return `${negative ? \"-\" : \"\"}${whole.toString()}`;\n return `${negative ? \"-\" : \"\"}${whole.toString()}.${frac}`;\n}\n\n/** Returns whole-second countdown until `expiresAtMs`. Negative -> 0. */\nexport function secondsUntil(\n expiresAtMs: number,\n nowMs: number = Date.now(),\n): number {\n return Math.max(0, Math.floor((expiresAtMs - nowMs) / 1000));\n}\n\n/** Truncate an address to `head…tail` for display. */\nexport function shortAddress(addr: string, head = 6, tail = 4): string {\n if (!addr) return \"\";\n if (addr.length <= head + tail + 1) return addr;\n return `${addr.slice(0, head)}…${addr.slice(-tail)}`;\n}\n","import { useEffect, useState } from \"react\";\nimport { useTranslation } from \"@liberfi.io/i18n\";\nimport {\n Button,\n Modal,\n ModalBody,\n ModalContent,\n ModalFooter,\n ModalHeader,\n Spinner,\n} from \"@liberfi.io/ui\";\nimport type {\n DepositBreakdown,\n DepositQuoteResponse,\n} from \"../../client/liberfi/deposit-types\";\nimport { lamportsToSol, hlUsdcRawToUsdc, secondsUntil } from \"./format\";\n\n/**\n * Pure presentational confirm modal for the deposit flow.\n *\n * Owns no fetching or signing — it just renders the breakdown and\n * fires `onConfirm` / `onCancel`. The expiry countdown ticks locally\n * via setInterval and re-renders once a second; when it hits 0 the\n * `onExpire` callback fires (the parent should refetch the quote).\n */\nexport interface DepositConfirmUIProps {\n isOpen: boolean;\n /** Quote currently being shown to the user. Required when `isOpen`. */\n quote: DepositQuoteResponse | undefined;\n /** True while `/submit` (or wallet sign) is in flight. Disables the CTA. */\n isExecuting?: boolean;\n /** True when the displayed quote has already expired. */\n isExpired?: boolean;\n onConfirm: () => void;\n onCancel: () => void;\n /** Fires when the local countdown reaches zero. */\n onExpire?: () => void;\n /** Optional inline error to surface inside the modal. */\n error?: string;\n}\n\nexport function DepositConfirmUI({\n isOpen,\n quote,\n isExecuting,\n isExpired,\n onConfirm,\n onCancel,\n onExpire,\n error,\n}: DepositConfirmUIProps) {\n const { t } = useTranslation();\n\n const expiresAtMs = quote ? Date.parse(quote.expiresAt) : 0;\n const [secondsLeft, setSecondsLeft] = useState(() =>\n expiresAtMs ? secondsUntil(expiresAtMs) : 0,\n );\n\n useEffect(() => {\n if (!isOpen || !expiresAtMs) return;\n setSecondsLeft(secondsUntil(expiresAtMs));\n const id = setInterval(() => {\n const remaining = secondsUntil(expiresAtMs);\n setSecondsLeft(remaining);\n if (remaining === 0) {\n onExpire?.();\n clearInterval(id);\n }\n }, 1000);\n return () => clearInterval(id);\n }, [isOpen, expiresAtMs, onExpire]);\n\n return (\n <Modal\n isOpen={isOpen}\n onOpenChange={(next) => !next && onCancel()}\n hideCloseButton\n backdrop=\"blur\"\n >\n <ModalContent className=\"bg-content2 rounded-lg\">\n <ModalHeader>{t(\"perpDeposit.confirm.title\")}</ModalHeader>\n <ModalBody>\n {!quote ? (\n <div className=\"flex h-32 items-center justify-center\">\n <Spinner />\n </div>\n ) : (\n <BreakdownSummary breakdown={quote.breakdown} />\n )}\n\n {quote && !isExpired && (\n <div className=\"text-default-500 mt-4 text-xs\">\n {t(\"perpDeposit.confirm.expiresIn\", { seconds: secondsLeft })}\n </div>\n )}\n {isExpired && (\n <div className=\"text-warning-500 mt-4 text-xs\">\n {t(\"perpDeposit.confirm.expired\")}\n </div>\n )}\n {error && <div className=\"text-danger mt-4 text-xs\">{error}</div>}\n </ModalBody>\n <ModalFooter className=\"flex justify-between gap-2\">\n <Button\n variant=\"flat\"\n color=\"default\"\n onPress={onCancel}\n isDisabled={isExecuting}\n >\n {t(\"perpDeposit.confirm.cancel\")}\n </Button>\n <Button\n color=\"primary\"\n onPress={onConfirm}\n isDisabled={!quote || isExecuting || isExpired}\n isLoading={isExecuting}\n >\n {t(\"perpDeposit.confirm.cta\")}\n </Button>\n </ModalFooter>\n </ModalContent>\n </Modal>\n );\n}\n\ninterface BreakdownSummaryProps {\n breakdown: DepositBreakdown;\n}\n\nfunction BreakdownSummary({ breakdown }: BreakdownSummaryProps) {\n const { t } = useTranslation();\n return (\n <dl className=\"flex flex-col gap-2 text-sm\">\n <Row\n label={t(\"perpDeposit.confirm.send\")}\n value={`${lamportsToSol(breakdown.grossLamports)} SOL`}\n />\n <Row\n label={t(\"perpDeposit.confirm.receive\")}\n value={`${hlUsdcRawToUsdc(breakdown.expectedOutputUSDC)} USDC`}\n highlight\n />\n <Row\n label={t(\"perpDeposit.confirm.platformFee\")}\n value={`${lamportsToSol(breakdown.platformFeeLamports, 6)} SOL`}\n muted\n />\n <Row\n label={t(\"perpDeposit.confirm.relayFee\")}\n value={`${lamportsToSol(breakdown.relayDepositLamports, 6)} SOL`}\n muted\n />\n </dl>\n );\n}\n\ninterface RowProps {\n label: string;\n value: string;\n highlight?: boolean;\n muted?: boolean;\n}\n\nfunction Row({ label, value, highlight, muted }: RowProps) {\n return (\n <div className=\"flex items-center justify-between\">\n <dt className=\"text-default-500\">{label}</dt>\n <dd\n className={\n highlight\n ? \"text-foreground text-base font-semibold\"\n : muted\n ? \"text-default-500 text-xs\"\n : \"text-foreground\"\n }\n >\n {value}\n </dd>\n </div>\n );\n}\n","import { useTranslation } from \"@liberfi.io/i18n\";\nimport { Button, Input, cn } from \"@liberfi.io/ui\";\n\n/**\n * Pure presentational form for collecting the deposit amount + the\n * Hyperliquid recipient address.\n *\n * No data fetching, no state — every input is controlled from above.\n * Lets the host app decide when to show the wallet's connected SOL\n * balance (or omit it entirely).\n */\nexport interface DepositFormUIProps {\n amount: string;\n onAmountChange: (value: string) => void;\n recipient: string;\n onRecipientChange: (value: string) => void;\n /** Optional: shown as the \"Balance: …\" hint above the amount input. */\n balanceSol?: string;\n /** Disables every interactive control (e.g. while quoting). */\n disabled?: boolean;\n /** Inline error to render under the amount input. */\n amountError?: string;\n /** Inline error to render under the recipient input. */\n recipientError?: string;\n /** Click handler for \"Max\" — only rendered when `balanceSol` is set. */\n onMax?: () => void;\n className?: string;\n}\n\nexport function DepositFormUI({\n amount,\n onAmountChange,\n recipient,\n onRecipientChange,\n balanceSol,\n disabled,\n amountError,\n recipientError,\n onMax,\n className,\n}: DepositFormUIProps) {\n const { t } = useTranslation();\n return (\n <div className={cn(\"flex flex-col gap-4\", className)}>\n <div>\n <div className=\"flex items-center justify-between mb-1.5\">\n <label\n htmlFor=\"perp-deposit-amount\"\n className=\"text-sm font-medium text-foreground\"\n >\n {t(\"perpDeposit.amount\")}\n </label>\n {balanceSol && (\n <span className=\"text-xs text-default-500\">\n {t(\"perpDeposit.amount.balance\", { balance: balanceSol })}\n </span>\n )}\n </div>\n <div className=\"relative\">\n <Input\n id=\"perp-deposit-amount\"\n type=\"text\"\n inputMode=\"decimal\"\n placeholder={t(\"perpDeposit.amount.placeholder\")}\n value={amount}\n onValueChange={onAmountChange}\n isDisabled={disabled}\n isInvalid={Boolean(amountError)}\n errorMessage={amountError}\n endContent={\n <div className=\"flex items-center gap-2\">\n <span className=\"text-default-500 text-sm\">\n {t(\"perpDeposit.amount.unit\")}\n </span>\n {balanceSol && onMax && (\n <Button\n size=\"sm\"\n variant=\"flat\"\n color=\"primary\"\n onPress={onMax}\n isDisabled={disabled}\n >\n {t(\"perpDeposit.amount.max\")}\n </Button>\n )}\n </div>\n }\n />\n </div>\n </div>\n\n <div>\n <label\n htmlFor=\"perp-deposit-recipient\"\n className=\"text-sm font-medium text-foreground mb-1.5 block\"\n >\n {t(\"perpDeposit.recipient\")}\n </label>\n <Input\n id=\"perp-deposit-recipient\"\n type=\"text\"\n placeholder={t(\"perpDeposit.recipient.placeholder\")}\n value={recipient}\n onValueChange={onRecipientChange}\n isDisabled={disabled}\n isInvalid={Boolean(recipientError)}\n errorMessage={recipientError}\n autoComplete=\"off\"\n spellCheck=\"false\"\n />\n </div>\n </div>\n );\n}\n","import { useTranslation } from \"@liberfi.io/i18n\";\nimport { ModalContent, StyledModal, XCloseIcon, cn } from \"@liberfi.io/ui\";\nimport type { DepositPhase } from \"../../client/liberfi/deposit-state-machine\";\nimport type { DepositStatusResponse } from \"../../client/liberfi/deposit-types\";\nimport { shortAddress } from \"./format\";\n\n/**\n * Polished progress / result panel for the SOL → Hyperliquid USDC\n * deposit flow.\n *\n * Visual design intentionally mirrors the swap-style deposit form\n * modal (dark surface, 14 px radius, accent-color spinner / icons,\n * pill-style transaction links) so the in-flight, success and failure\n * states all feel like the same product surface rather than a generic\n * HeroUI dialog.\n *\n * Renders one of four visual states based on the FSM phase:\n * - in-progress (broadcasting / submitted / tracking)\n * - succeeded\n * - refunded\n * - failed\n *\n * Explorer URLs are caller-provided so the SDK never has to know which\n * RPC / explorer the host wants (Solscan vs Solana Beach, etc.).\n */\nexport interface DepositStatusUIProps {\n isOpen: boolean;\n /** The current FSM phase — drives the visual treatment. */\n phase: DepositPhase;\n /** Backend status record (may be unavailable on first frame). */\n status?: DepositStatusResponse;\n /** Optional Solana explorer URL (caller decides the network). */\n solanaExplorerUrl?: string;\n /** Optional Hyperliquid explorer URL. */\n hyperliquidExplorerUrl?: string;\n /** \"Try again\" handler — only rendered when `phase === \"failed\"`. */\n onRetry?: () => void;\n onClose: () => void;\n /** Optional override for the human-readable message. */\n errorMessage?: string;\n}\n\ntype Variant = \"progress\" | \"success\" | \"warning\" | \"error\";\n\nconst ACCENT = \"#C7FF2E\";\n\nexport function DepositStatusUI({\n isOpen,\n phase,\n status,\n solanaExplorerUrl,\n hyperliquidExplorerUrl,\n onRetry,\n onClose,\n errorMessage,\n}: DepositStatusUIProps) {\n const { t } = useTranslation();\n\n const variant = phaseToVariant(phase);\n const message = ((): string => {\n if (phase === \"failed\") {\n if (errorMessage) return errorMessage;\n if (status?.lastError?.message) {\n return t(\"perpDeposit.status.failed\", {\n message: status.lastError.message,\n });\n }\n return t(\"perpDeposit.status.failed\", { message: \"\" });\n }\n if (phase === \"succeeded\") return t(\"perpDeposit.status.settled\");\n if (phase === \"refunded\") return t(\"perpDeposit.status.refunded\");\n if (status?.status === \"broadcasted\")\n return t(\"perpDeposit.status.broadcasted\");\n if (status?.status === \"relay_waiting\")\n return t(\"perpDeposit.status.relay_waiting\");\n if (status?.status === \"relay_pending\")\n return t(\"perpDeposit.status.relay_pending\");\n if (status?.status === \"stuck\") return t(\"perpDeposit.status.stuck\");\n return t(\"perpDeposit.status.broadcasted\");\n })();\n\n const showRetry = phase === \"failed\" && !!onRetry;\n\n return (\n <StyledModal\n isOpen={isOpen}\n onOpenChange={(next) => !next && onClose()}\n size=\"md\"\n hideCloseButton\n backdrop=\"blur\"\n classNames={{\n base: \"!bg-[#18181b] !rounded-[14px] !border !border-[rgba(39,39,42,1)] !shadow-[0_25px_50px_-12px_rgba(0,0,0,0.5)] max-w-[420px]\",\n body: \"!p-0\",\n }}\n >\n <ModalContent>\n <div className=\"flex flex-col\">\n {/* Header */}\n <div className=\"flex items-start justify-between px-5 pt-5 pb-2\">\n <div className=\"flex items-center gap-2.5\">\n <h3 className=\"text-base font-semibold text-white\">\n {t(\"perpDeposit.status.title\")}\n </h3>\n </div>\n <button\n type=\"button\"\n onClick={onClose}\n className=\"cursor-pointer p-1 rounded-[10px] hover:bg-[rgba(39,39,42,0.5)] text-zinc-400 hover:text-white transition-colors\"\n aria-label={t(\"perpDeposit.status.close\")}\n >\n <XCloseIcon width={16} height={16} />\n </button>\n </div>\n\n {/* Body */}\n <div className=\"px-5 pb-3 pt-2\">\n <div className=\"rounded-[12px] bg-[#0a0a0b] border border-[#27272a] px-4 py-6 flex flex-col items-center text-center gap-4\">\n <PhaseIcon variant={variant} />\n <p\n className={cn(\n \"text-sm leading-relaxed max-w-[320px]\",\n variantTextClass(variant),\n )}\n >\n {message}\n </p>\n </div>\n\n {/* Transaction links */}\n {(status?.solanaTxHash || status?.hyperliquidTxHash) && (\n <div className=\"mt-3 flex flex-col gap-2\">\n {status?.solanaTxHash && solanaExplorerUrl && (\n <TxLink\n href={solanaExplorerUrl}\n label={t(\"perpDeposit.status.viewSolanaTx\")}\n hash={status.solanaTxHash}\n />\n )}\n {status?.hyperliquidTxHash && hyperliquidExplorerUrl && (\n <TxLink\n href={hyperliquidExplorerUrl}\n label={t(\"perpDeposit.status.viewHyperliquidTx\")}\n hash={status.hyperliquidTxHash}\n />\n )}\n </div>\n )}\n </div>\n\n {/* Footer */}\n <div\n className={cn(\n \"px-5 pb-5 pt-2 flex gap-2\",\n showRetry ? \"justify-between\" : \"justify-end\",\n )}\n >\n {showRetry && (\n <button\n type=\"button\"\n onClick={onRetry}\n className=\"cursor-pointer flex-1 h-10 rounded-[10px] font-medium text-black bg-[#C7FF2E] hover:bg-[#b6ed1c] active:bg-[#a6d913] transition-colors flex items-center justify-center\"\n >\n {t(\"perpDeposit.status.tryAgain\")}\n </button>\n )}\n <button\n type=\"button\"\n onClick={onClose}\n className={cn(\n \"cursor-pointer h-10 rounded-[10px] font-medium transition-colors flex items-center justify-center\",\n showRetry\n ? \"flex-1 bg-[rgba(39,39,42,1)] hover:bg-[rgba(63,63,70,1)] text-white\"\n : \"px-6 bg-[rgba(39,39,42,1)] hover:bg-[rgba(63,63,70,1)] text-white\",\n )}\n >\n {t(\"perpDeposit.status.close\")}\n </button>\n </div>\n </div>\n </ModalContent>\n </StyledModal>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Sub-components\n// ---------------------------------------------------------------------------\n\nfunction TxLink({\n href,\n label,\n hash,\n}: {\n href: string;\n label: string;\n hash: string;\n}) {\n return (\n <a\n href={href}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"group flex items-center justify-between gap-2 px-3 py-2 rounded-[10px] bg-[#0a0a0b] border border-[#27272a] hover:border-[rgba(199,255,46,0.4)] transition-colors\"\n >\n <span className=\"text-xs text-zinc-400 group-hover:text-white transition-colors\">\n {label}\n </span>\n <span className=\"flex items-center gap-1.5 text-xs tabular-nums text-zinc-300 group-hover:text-[#C7FF2E] transition-colors\">\n {shortAddress(hash, 6, 4)}\n <ExternalLinkIcon />\n </span>\n </a>\n );\n}\n\nfunction PhaseIcon({ variant }: { variant: Variant }) {\n if (variant === \"progress\") {\n return (\n <div className=\"relative w-14 h-14 flex items-center justify-center\">\n <AccentSpinner />\n </div>\n );\n }\n if (variant === \"success\") {\n return (\n <div className=\"w-14 h-14 rounded-full flex items-center justify-center bg-[rgba(199,255,46,0.12)]\">\n <CheckCircle className=\"w-8 h-8\" style={{ color: ACCENT }} />\n </div>\n );\n }\n if (variant === \"warning\") {\n return (\n <div className=\"w-14 h-14 rounded-full flex items-center justify-center bg-[rgba(245,158,11,0.12)]\">\n <AlertCircle className=\"w-8 h-8 text-amber-400\" />\n </div>\n );\n }\n return (\n <div className=\"w-14 h-14 rounded-full flex items-center justify-center bg-[rgba(239,68,68,0.12)]\">\n <XCircle className=\"w-8 h-8 text-rose-400\" />\n </div>\n );\n}\n\n/**\n * Accent-coloured circular spinner matching the deposit form's theme.\n *\n * Implemented as an inline SVG with a CSS keyframe rotation rather than\n * pulling HeroUI's `Spinner` (which doesn't expose a clean way to set\n * the active arc colour to our brand `#C7FF2E`).\n */\nfunction AccentSpinner() {\n return (\n <>\n <svg\n className=\"lfi-perp-deposit-spinner\"\n viewBox=\"0 0 50 50\"\n width={48}\n height={48}\n aria-hidden=\"true\"\n >\n <circle\n cx=\"25\"\n cy=\"25\"\n r=\"20\"\n fill=\"none\"\n stroke=\"rgba(255,255,255,0.08)\"\n strokeWidth=\"4\"\n />\n <circle\n cx=\"25\"\n cy=\"25\"\n r=\"20\"\n fill=\"none\"\n stroke={ACCENT}\n strokeWidth=\"4\"\n strokeLinecap=\"round\"\n strokeDasharray=\"90 60\"\n />\n </svg>\n <style>{`\n .lfi-perp-deposit-spinner {\n animation: lfi-perp-deposit-spin 0.9s linear infinite;\n transform-origin: center;\n }\n @keyframes lfi-perp-deposit-spin {\n to { transform: rotate(360deg); }\n }\n `}</style>\n </>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction phaseToVariant(phase: DepositPhase): Variant {\n switch (phase) {\n case \"succeeded\":\n return \"success\";\n case \"refunded\":\n return \"warning\";\n case \"failed\":\n return \"error\";\n default:\n return \"progress\";\n }\n}\n\nfunction variantTextClass(variant: Variant): string {\n switch (variant) {\n case \"success\":\n return \"text-white\";\n case \"warning\":\n return \"text-amber-200\";\n case \"error\":\n return \"text-rose-300\";\n default:\n return \"text-zinc-200\";\n }\n}\n\n// Inline icons — kept tiny so we don't pull a heavy icon dep into the bundle.\nfunction CheckCircle(props: {\n className?: string;\n style?: React.CSSProperties;\n}) {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2.5}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n className={props.className}\n style={props.style}\n >\n <path d=\"M20 6L9 17l-5-5\" />\n </svg>\n );\n}\n\nfunction AlertCircle(props: { className?: string }) {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n className={props.className}\n >\n <path d=\"M12 2a10 10 0 100 20 10 10 0 000-20zm0 4c.6 0 1 .4 1 1v6c0 .6-.4 1-1 1s-1-.4-1-1V7c0-.6.4-1 1-1zm0 12c-.7 0-1.2-.5-1.2-1.2s.5-1.2 1.2-1.2 1.2.5 1.2 1.2-.5 1.2-1.2 1.2z\" />\n </svg>\n );\n}\n\nfunction XCircle(props: { className?: string }) {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2.5}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n className={props.className}\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"M15 9l-6 6M9 9l6 6\" />\n </svg>\n );\n}\n\nfunction ExternalLinkIcon() {\n return (\n <svg\n width=\"11\"\n height=\"11\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\" />\n <polyline points=\"15 3 21 3 21 9\" />\n <line x1=\"10\" y1=\"14\" x2=\"21\" y2=\"3\" />\n </svg>\n );\n}\n","import { useCallback, useEffect, useMemo, useState } from \"react\";\nimport { useTranslation } from \"@liberfi.io/i18n\";\nimport { Button, Card, CardBody } from \"@liberfi.io/ui\";\nimport type {\n DepositQuoteRequest,\n DepositSource,\n} from \"../../client/liberfi/deposit-types\";\nimport {\n type SignAndBroadcastSolanaTx,\n usePerpDepositExecute,\n} from \"../../hooks/usePerpDepositExecute\";\nimport { usePerpDepositQuote } from \"../../hooks/usePerpDepositQuote\";\nimport { usePerpDepositStatus } from \"../../hooks/usePerpDepositStatus\";\nimport { DepositConfirmUI } from \"./deposit-confirm.ui\";\nimport { DepositFormUI } from \"./deposit-form.ui\";\nimport { DepositStatusUI } from \"./deposit-status.ui\";\nimport { solToLamports } from \"./format\";\n\n/**\n * Highest-level deposit widget. Wires the three presentational\n * components (form / confirm / status) to the deposit hooks +\n * state machine.\n *\n * Engineering principles:\n * - Single responsibility: this file is the *only* place that knows\n * how the three components compose. Anything richer (e.g. embedded\n * FAQ panel, support links) belongs to the host application.\n * - Inversion of control: every side effect the host might want to\n * own (sign + broadcast, success / failure callbacks, explorer\n * URLs, balance fetch, address validation) is a prop. The widget\n * never imports a wallet adapter directly.\n */\nexport interface DepositFlowWidgetProps {\n /** Connected Solana wallet — used as `userSolanaAddress` in /quote. */\n userSolanaAddress: string;\n /** Stable LiberFi user id (for fee attribution). */\n userId: string;\n /** Where the deposit was initiated from. */\n source: DepositSource;\n /** Optional referral / campaign code propagated to the backend. */\n campaign?: string;\n\n /** Initial Hyperliquid recipient (e.g. derived from the user's EVM wallet). */\n defaultRecipient?: string;\n\n /**\n * Wallet adapter — sign and broadcast a Solana transaction. The host\n * app supplies its own wallet integration (Phantom, Privy, Backpack,\n * …) and returns the resulting tx hash. See `SignAndBroadcastSolanaTx`.\n */\n signAndBroadcast: SignAndBroadcastSolanaTx;\n\n /** Optional balance display (in SOL units, e.g. \"12.345\"). */\n balanceSol?: string;\n /** Click handler for \"Max\" — only rendered when `balanceSol` is set. */\n onMaxClick?: () => void;\n /** Validates the recipient string. Return undefined when valid. */\n validateRecipient?: (value: string) => string | undefined;\n\n /** Build a Solana explorer URL from a tx hash. */\n buildSolanaExplorerUrl?: (txHash: string) => string;\n /** Build a Hyperliquid explorer URL from a tx hash. */\n buildHyperliquidExplorerUrl?: (txHash: string) => string;\n\n /** Fired when a deposit reaches `settled`. */\n onSettled?: (intentId: string) => void;\n /** Fired when a deposit fails (after the wallet signed). */\n onError?: (intentId: string | undefined, message: string) => void;\n\n className?: string;\n}\n\nexport function DepositFlowWidget({\n userSolanaAddress,\n userId,\n source,\n campaign,\n defaultRecipient,\n signAndBroadcast,\n balanceSol,\n onMaxClick,\n validateRecipient,\n buildSolanaExplorerUrl,\n buildHyperliquidExplorerUrl,\n onSettled,\n onError,\n className,\n}: DepositFlowWidgetProps) {\n const { t } = useTranslation();\n\n const [amount, setAmount] = useState(\"\");\n const [recipient, setRecipient] = useState(defaultRecipient ?? \"\");\n\n // Local validation. Backend re-validates everything; these only\n // gate the \"Continue\" button and surface inline errors.\n const amountError = useMemo<string | undefined>(() => {\n if (!amount) return undefined;\n if (!/^\\d+(\\.\\d+)?$/.test(amount.trim())) {\n return t(\"perpDeposit.error.amountInvalid\");\n }\n if (Number(amount) <= 0) return t(\"perpDeposit.error.amountInvalid\");\n return undefined;\n }, [amount, t]);\n\n const recipientError = useMemo<string | undefined>(() => {\n if (!recipient) return undefined;\n return validateRecipient ? validateRecipient(recipient) : undefined;\n }, [recipient, validateRecipient]);\n\n const grossLamports = useMemo(\n () => (amountError ? \"\" : solToLamports(amount)),\n [amount, amountError],\n );\n\n const quoteReq = useMemo<DepositQuoteRequest | null>(() => {\n if (!grossLamports || grossLamports === \"0\") return null;\n if (recipientError) return null;\n if (!recipient) return null;\n return {\n userSolanaAddress,\n hyperliquidRecipient: recipient,\n grossLamports,\n source,\n };\n }, [grossLamports, recipient, recipientError, source, userSolanaAddress]);\n\n const quoteQ = usePerpDepositQuote(quoteReq, {\n enabled: Boolean(quoteReq),\n });\n\n const { state, execute, reset, dispatch } =\n usePerpDepositExecute(signAndBroadcast);\n const intentId =\n state.phase === \"submitted\" ||\n state.phase === \"tracking\" ||\n state.phase === \"succeeded\" ||\n state.phase === \"refunded\"\n ? state.intentId\n : state.phase === \"failed\"\n ? state.intentId\n : undefined;\n\n const statusQ = usePerpDepositStatus(intentId, {\n enabled:\n Boolean(intentId) &&\n state.phase !== \"succeeded\" &&\n state.phase !== \"refunded\" &&\n state.phase !== \"failed\",\n });\n\n // Forward backend status into the FSM so the UI advances.\n useEffect(() => {\n if (statusQ.data) {\n dispatch({ type: \"STATUS_UPDATE\", status: statusQ.data });\n }\n }, [statusQ.data, dispatch]);\n\n // Funnel-end side effects.\n useEffect(() => {\n if (state.phase === \"succeeded\") {\n onSettled?.(state.intentId);\n } else if (state.phase === \"failed\") {\n onError?.(state.intentId, state.error.message);\n }\n }, [state, onSettled, onError]);\n\n const handleContinue = useCallback(() => {\n if (!quoteQ.data) return;\n dispatch({ type: \"QUOTE_REQUEST\" });\n dispatch({ type: \"QUOTE_RECEIVED\", quote: quoteQ.data });\n }, [dispatch, quoteQ.data]);\n\n const handleConfirm = useCallback(async () => {\n if (state.phase !== \"ready_to_sign\") return;\n try {\n await execute({\n quote: state.quote,\n userSolanaAddress,\n hyperliquidRecipient: recipient,\n userId,\n source,\n campaign,\n });\n } catch {\n // Hook already advanced FSM into `failed`; nothing to do here.\n }\n }, [state, execute, userSolanaAddress, recipient, userId, source, campaign]);\n\n const handleExpire = useCallback(() => {\n dispatch({ type: \"QUOTE_EXPIRED\" });\n }, [dispatch]);\n\n const handleRetry = useCallback(async () => {\n dispatch({ type: \"RESET\" });\n await quoteQ.refetch();\n }, [dispatch, quoteQ]);\n\n const showConfirm =\n state.phase === \"ready_to_sign\" ||\n state.phase === \"signing\" ||\n state.phase === \"broadcasting\" ||\n state.phase === \"expired\";\n\n const showStatus =\n state.phase === \"submitted\" ||\n state.phase === \"tracking\" ||\n state.phase === \"succeeded\" ||\n state.phase === \"refunded\" ||\n (state.phase === \"failed\" && Boolean(state.intentId));\n\n const status =\n state.phase === \"tracking\" ||\n state.phase === \"succeeded\" ||\n state.phase === \"refunded\"\n ? state.status\n : state.phase === \"failed\"\n ? state.status\n : undefined;\n\n const continueDisabled =\n !quoteQ.data ||\n quoteQ.isFetching ||\n Boolean(amountError) ||\n Boolean(recipientError) ||\n !quoteReq;\n\n return (\n <Card className={className}>\n <CardBody className=\"flex flex-col gap-4 p-6\">\n <div>\n <h3 className=\"text-lg font-semibold\">{t(\"perpDeposit.title\")}</h3>\n <p className=\"text-default-500 text-sm\">\n {t(\"perpDeposit.description\")}\n </p>\n </div>\n\n <DepositFormUI\n amount={amount}\n onAmountChange={setAmount}\n recipient={recipient}\n onRecipientChange={setRecipient}\n balanceSol={balanceSol}\n onMax={onMaxClick}\n amountError={amountError}\n recipientError={recipientError}\n disabled={\n state.phase !== \"idle\" &&\n state.phase !== \"expired\" &&\n state.phase !== \"failed\"\n }\n />\n\n <Button\n color=\"primary\"\n isDisabled={continueDisabled}\n isLoading={quoteQ.isFetching}\n onPress={handleContinue}\n >\n {quoteQ.isFetching\n ? t(\"perpDeposit.gettingQuote\")\n : t(\"perpDeposit.confirmQuote\")}\n </Button>\n\n {quoteQ.error && (\n <div className=\"text-danger text-xs\">\n {t(\"perpDeposit.error.quoteFailed\")}\n </div>\n )}\n </CardBody>\n\n <DepositConfirmUI\n isOpen={showConfirm}\n quote={\n state.phase === \"ready_to_sign\" ||\n state.phase === \"signing\" ||\n state.phase === \"broadcasting\" ||\n state.phase === \"expired\"\n ? state.quote\n : undefined\n }\n isExecuting={\n state.phase === \"signing\" || state.phase === \"broadcasting\"\n }\n isExpired={state.phase === \"expired\"}\n onConfirm={handleConfirm}\n onCancel={reset}\n onExpire={handleExpire}\n />\n\n <DepositStatusUI\n isOpen={showStatus}\n phase={state.phase}\n status={status}\n solanaExplorerUrl={\n status?.solanaTxHash && buildSolanaExplorerUrl\n ? buildSolanaExplorerUrl(status.solanaTxHash)\n : undefined\n }\n hyperliquidExplorerUrl={\n status?.hyperliquidTxHash && buildHyperliquidExplorerUrl\n ? buildHyperliquidExplorerUrl(status.hyperliquidTxHash)\n : undefined\n }\n onRetry={state.phase === \"failed\" ? handleRetry : undefined}\n onClose={reset}\n errorMessage={\n state.phase === \"failed\" ? state.error.message : undefined\n }\n />\n </Card>\n );\n}\n","import { useTranslation } from \"@liberfi.io/i18n\";\nimport {\n Button,\n Card,\n CardBody,\n CardFooter,\n CardHeader,\n Spinner,\n cn,\n} from \"@liberfi.io/ui\";\nimport type {\n SetupState,\n SetupStep,\n StepRecord,\n StepStatus,\n} from \"../../hooks/hyperliquid-setup/setup-state-machine\";\n\n/**\n * Pure presentational card for the Hyperliquid first-run setup flow.\n *\n * The component is fully driven by the FSM state from\n * `useHyperliquidSetup` plus a couple of action callbacks, so consumers\n * can wire it into either a modal, a sidebar panel, or an inline card\n * without forking the markup.\n */\nexport interface HyperliquidInitUIProps {\n /** FSM snapshot rendered as the checklist. */\n state: SetupState;\n /** Trigger the next runnable step (sequential default). */\n onContinue: () => void;\n /** Retry a specific step (used by per-row error recovery). */\n onRetryStep?: (index: number) => void;\n /** Refresh the on-chain state — typically rendered when the load failed. */\n onReload?: () => void;\n /** Optional dismiss handler — show a \"Skip for now\" CTA when set. */\n onDismiss?: () => void;\n /** Optional className override for embedding inside other cards. */\n className?: string;\n}\n\nexport function HyperliquidInitUI({\n state,\n onContinue,\n onRetryStep,\n onReload,\n onDismiss,\n className,\n}: HyperliquidInitUIProps) {\n const { t } = useTranslation();\n const phase = state.phase;\n const isExecuting = phase === \"executing\";\n const isLoading = phase === \"loading\";\n const isLoadError = phase === \"error\" && state.steps.length === 0;\n\n return (\n <Card className={cn(\"w-full max-w-md\", className)}>\n <CardHeader className=\"flex flex-col items-start gap-1\">\n <h3 className=\"text-lg font-semibold\">\n {t(\"perpDeposit.setup.title\")}\n </h3>\n <p className=\"text-foreground-500 text-sm\">\n {t(\"perpDeposit.setup.description\")}\n </p>\n </CardHeader>\n <CardBody className=\"gap-3\">\n {isLoading && <LoadingRow />}\n {isLoadError && (\n <p className=\"text-danger text-sm\">\n {t(\"perpDeposit.setup.loadFailed\", { message: state.error ?? \"\" })}\n </p>\n )}\n {!isLoading &&\n !isLoadError &&\n state.steps.map((rec, idx) => (\n <SetupStepRow\n key={`${rec.step.id}-${idx}`}\n rec={rec}\n index={idx}\n isCurrent={state.currentIndex === idx}\n onRetry={onRetryStep}\n />\n ))}\n {phase === \"done\" && (\n <p className=\"text-success text-sm\">\n {t(\"perpDeposit.setup.alreadyActive\")}\n </p>\n )}\n </CardBody>\n <CardFooter className=\"flex justify-between gap-2\">\n {onDismiss && (\n <Button variant=\"light\" onPress={onDismiss} isDisabled={isExecuting}>\n {phase === \"done\"\n ? t(\"perpDeposit.setup.dismiss\")\n : t(\"perpDeposit.setup.skip\")}\n </Button>\n )}\n <div className=\"flex-1\" />\n {isLoadError && onReload && (\n <Button color=\"primary\" onPress={onReload}>\n {t(\"perpDeposit.setup.retry\")}\n </Button>\n )}\n {!isLoadError && phase !== \"done\" && (\n <Button\n color=\"primary\"\n onPress={onContinue}\n isLoading={isExecuting}\n isDisabled={isExecuting || isLoading}\n >\n {state.steps.some((s) => s.status === \"done\")\n ? t(\"perpDeposit.setup.continue\")\n : t(\"perpDeposit.setup.cta\")}\n </Button>\n )}\n </CardFooter>\n </Card>\n );\n}\n\ninterface SetupStepRowProps {\n rec: StepRecord;\n index: number;\n isCurrent: boolean;\n onRetry?: (index: number) => void;\n}\n\nfunction SetupStepRow({ rec, index, isCurrent, onRetry }: SetupStepRowProps) {\n const { t } = useTranslation();\n const title = stepTitle(rec.step.id, () => {\n switch (rec.step.id) {\n case \"approveBuilderFee\":\n return t(\"perpDeposit.setup.builderFee.label\");\n case \"setReferrer\":\n return t(\"perpDeposit.setup.referrer.label\");\n case \"updateLeverage\":\n return t(\"perpDeposit.setup.leverage.label\");\n }\n });\n const description = ((): string => {\n switch (rec.step.id) {\n case \"approveBuilderFee\": {\n const bps = (rec.step.params.maxFeeRate / 10).toFixed(1);\n return t(\"perpDeposit.setup.builderFee.description\", { bps });\n }\n case \"setReferrer\":\n return t(\"perpDeposit.setup.referrer.description\", {\n code: rec.step.params.code,\n });\n case \"updateLeverage\":\n return t(\"perpDeposit.setup.leverage.description\");\n }\n })();\n const statusLabel = ((): string => {\n switch (rec.status) {\n case \"pending\":\n return t(\"perpDeposit.setup.step.pending\");\n case \"skipped\":\n return t(\"perpDeposit.setup.step.skipped\");\n case \"running\":\n return t(\"perpDeposit.setup.step.running\");\n case \"done\":\n return t(\"perpDeposit.setup.step.done\");\n case \"error\":\n return t(\"perpDeposit.setup.step.error\");\n }\n })();\n return (\n <div\n className={cn(\n \"border-divider flex items-start justify-between gap-3 rounded-md border p-3\",\n rec.status === \"error\" && \"border-danger\",\n rec.status === \"done\" && \"border-success/40 bg-success/5\",\n rec.status === \"skipped\" && \"border-default bg-default-100/40\",\n )}\n >\n <div className=\"flex-1\">\n <div className=\"flex items-center gap-2 text-sm font-medium\">\n <StepIcon status={rec.status} isCurrent={isCurrent} />\n <span>{title}</span>\n </div>\n <p className=\"text-foreground-500 mt-1 text-xs\">{description}</p>\n {rec.status === \"error\" && rec.error && (\n <p className=\"text-danger mt-1 text-xs\">{rec.error}</p>\n )}\n </div>\n <div className=\"flex flex-col items-end gap-1 text-xs\">\n <span className={cn(statusBadgeClass(rec.status))}>{statusLabel}</span>\n {rec.status === \"error\" && onRetry && (\n <Button\n size=\"sm\"\n variant=\"flat\"\n color=\"danger\"\n onPress={() => onRetry(index)}\n >\n {t(\"perpDeposit.setup.retry\")}\n </Button>\n )}\n </div>\n </div>\n );\n}\n\nfunction LoadingRow() {\n const { t } = useTranslation();\n return (\n <div className=\"flex items-center gap-2 py-2 text-sm\">\n <Spinner size=\"sm\" />\n <span>{t(\"perpDeposit.setup.loading\")}</span>\n </div>\n );\n}\n\nfunction StepIcon({\n status,\n isCurrent,\n}: {\n status: StepStatus;\n isCurrent: boolean;\n}) {\n if (status === \"running\" || isCurrent) {\n return <Spinner size=\"sm\" />;\n }\n if (status === \"done\" || status === \"skipped\") {\n return (\n <span aria-hidden className=\"text-success\">\n ✓\n </span>\n );\n }\n if (status === \"error\") {\n return (\n <span aria-hidden className=\"text-danger\">\n !\n </span>\n );\n }\n return (\n <span\n aria-hidden\n className=\"border-foreground-400 inline-block h-3 w-3 rounded-full border\"\n />\n );\n}\n\nfunction statusBadgeClass(status: StepStatus): string {\n switch (status) {\n case \"done\":\n return \"text-success\";\n case \"skipped\":\n return \"text-foreground-500\";\n case \"running\":\n return \"text-primary\";\n case \"error\":\n return \"text-danger\";\n default:\n return \"text-foreground-500\";\n }\n}\n\n/**\n * Tiny indirection to keep `SetupStepRow` flat — invokes a closure\n * the caller wrote inline so we don't pass `t` across function\n * boundaries (which would defeat its strict-key inference).\n */\nfunction stepTitle(_id: SetupStep[\"id\"], compute: () => string): string {\n return compute();\n}\n","import { useCallback } from \"react\";\nimport {\n useHyperliquidSetup,\n type UseHyperliquidSetupOptions,\n type SetupState,\n} from \"../../hooks/hyperliquid-setup\";\nimport { HyperliquidInitUI } from \"./hyperliquid-init.ui\";\n\n/**\n * Highest-level Hyperliquid setup widget.\n *\n * Wraps `useHyperliquidSetup` with the presentational card so consumers\n * can drop in a single component:\n *\n * <HyperliquidInitWidget\n * adapter={mySetupAdapter}\n * userAddress={evmAddress}\n * steps={[ ... ]}\n * onComplete={() => navigate(\"/perp\")}\n * onDismiss={() => closeModal()}\n * />\n *\n * The widget is a thin coordinator — all logic lives in the hook and\n * all presentation lives in `HyperliquidInitUI`. This split keeps the\n * UI testable in isolation (Storybook just hands it a `state` prop).\n */\nexport interface HyperliquidInitWidgetProps extends Pick<\n UseHyperliquidSetupOptions,\n \"adapter\" | \"userAddress\" | \"steps\" | \"autoLoad\" | \"onError\"\n> {\n /** Invoked once every step is `done` or `skipped`. */\n onComplete?: (state: SetupState) => void;\n /**\n * Optional dismiss callback — when supplied the card renders a\n * \"Skip for now\" / \"Close\" CTA so the user can leave the wizard.\n */\n onDismiss?: () => void;\n /** Optional className passthrough to the rendered card. */\n className?: string;\n}\n\nexport function HyperliquidInitWidget({\n adapter,\n userAddress,\n steps,\n autoLoad,\n onComplete,\n onError,\n onDismiss,\n className,\n}: HyperliquidInitWidgetProps) {\n const { state, runNext, runStep, reload } = useHyperliquidSetup({\n adapter,\n userAddress,\n steps,\n autoLoad,\n onComplete,\n onError,\n });\n\n const handleContinue = useCallback(() => {\n void runNext();\n }, [runNext]);\n\n const handleRetry = useCallback(\n (index: number) => {\n void runStep(index);\n },\n [runStep],\n );\n\n const handleReload = useCallback(() => {\n void reload();\n }, [reload]);\n\n return (\n <HyperliquidInitUI\n state={state}\n onContinue={handleContinue}\n onRetryStep={handleRetry}\n onReload={handleReload}\n onDismiss={onDismiss}\n className={className}\n />\n );\n}\n"]}