@liberfi.io/ui-perpetuals 0.3.1 → 0.3.2

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/RateLimiter.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/useUniverseQuery.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/useHyperliquidUserBootstrap.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/close-position-modal.ui.tsx","../src/components/positions/use-close-position.ts","../src/components/positions/positions.script.tsx","../src/components/_internal/table.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","HEAVY_INFO_TYPES","weightForInfoType","type","EXCHANGE_REQUEST_WEIGHT","RateLimiter","config","weight","charge","wait","resolve","now","aggregationKey","param","aggregation","m","WebSocketManager","wsEndpoint","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","UNIVERSE_SNAPSHOT_TTL_MS","USER_STATE_SNAPSHOT_TTL_MS","HyperliquidPerpetualsClient","endpoint","body","t","url","controller","timeoutId","response","HyperliquidApiError","entry","markets","symbols","snap","symbolSet","fetchPromise","snapshot","meta","assetCtxs","assets","asset","index","currentPrice","prevPrice","market","assetMeta","bySymbol","userAddress","key","cached","inflight","clearinghouse","openOrders","limitOrOptions","coin","options","intervalMs","limit","startTime","endTime","bars","candle","maxLevel","_params","params","userState","universe","result","parseClearinghouseState","markByCoin","buildMarkPriceMapFromUniverse","enrichPositions","sum","p","lev","map","openOrdersRaw","buildLeverageMap","orders","o","parseOpenOrder","filteredOrders","trades","isLong","subscriptionType","raw","parseWebData2","symbolFilter","positions","assetPos","pos","quantity","entryPrice","unrealizedPnl","positionValue","filteredPositions","withdrawableRaw","availableBalance","extractBundledTpSl","order","tp","sl","child","orderTypeStr","triggerPxStr","px","origSz","remainingSz","filledSz","isBuySide","rawOrderType","baseOrderType","isTrigger","triggerType","triggerPx","triggerCondition","takeProfitPrice","stopLossPrice","leverage","markPrice","ap","parseSpotBalances","balances","b","positionsResult","spotBalances","buildMarkPriceMap","leverageByCoinMap","enrichedPositions","totalUnrealizedPnl","buildUniverseSnapshot","leverageByCoin","buildLeverageRecord","serverTime","prevDayPx","szDecimals","maxLeverage","out","metaAndCtxs","ctxs","pickPositionTpSl","position","closingSide","closingSideBool","tpOrder","slOrder","isTp","isSl","marks","next","dir","pnl","statusCode","responseBody","LiberFiApiError","DEFAULT_TIMEOUT_MS","LiberFiHttpTransport","path","query","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","universeQueryKey","fetchUniverse","supportsUniverseSnapshot","useUniverseQuery","enabled","marketQueryKey","fetchMarket","useMarketQuery","universeBacked","universeQuery","fallbackQuery","marketsQueryKey","fetchMarkets","useMarketsQuery","a","filter","klinesQueryKey","fetchKlines","useKlinesQuery","orderBookQueryKey","agg","aggKey","fetchOrderBook","useOrderBookQuery","recentTradesQueryKey","fetchRecentTrades","useRecentTradesQuery","positionsQueryKey","fetchPositions","filterPositionsBySymbol","usePositionsQuery","ordersQueryKey","fetchOrders","filterOrdersBySymbol","useOrdersQuery","tradesQueryKey","fetchTrades","useTradesQuery","queryParams","activeAssetLeverageQueryKey","fetchActiveAssetLeverage","useActiveAssetLeverageQuery","DEFAULT_STALE_TIME_MS","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","useHyperliquidUserBootstrap","cancelled","timer","usePerpDepositClient","usePerpDepositClientMaybe","perpDepositQuoteQueryKey","fetchPerpDepositQuote","usePerpDepositQuote","isQuoteReady","usePerpDepositExecute","signAndBroadcast","dispatch","useReducer","reset","execute","input","quote","solanaTxHash","info","toErrorInfo","submitReq","fallbackCode","parsed","parseJsonSafe","perpDepositStatusQueryKey","fetchPerpDepositStatus","usePerpDepositStatus","pollIntervalMs","initialSetupState","classifyStep","step","current","sameAddress","reduceSetupState","action","rec","i","mergedAccount","mergeAccountState","s","nextRunnableStep","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","deriveTpSlPrice","percent","sign","priceΔ","roundTpSlPrice","magnitude","factor","roundTpSlPercent","FALLBACK_LEVERAGE","usePlaceOrderFormScript","maxLeverageProp","onSuccess","onUpdateLeverage","onPlaceOrder","setSide","orderType","setOrderType","form","useForm","resolvedMaxLeverage","createOrderViaClient","isClientPending","placeOrderViaHostMutation","request","isSubmitting","watchedValues","amount","marketPrice","notional","estimatedFee","estimatedTotal","liquidationPrice","l","offset","positionsData","accountValue","availableMargin","currentPosition","account","hasOpenOrdersForSymbol","activeAssetLeverage","currentLeverage","isLeverageReady","lastSyncedSymbolRef","handleSubmit","finalPrice","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","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","LimitPriceInput","placeholder","formatTpSlNumber","TpSlInput","field","refPrice","isPriceField","partnerField","partnerValue","rounded","PlaceOrderFormUI","onSideChange","onOrderTypeChange","onSubmit","onAddFunds","addFundsFallback","guardedAddFunds","guardedSubmit","showLeverageModal","setShowLeverageModal","showTpSl","setShowTpSl","rawAmount","hasAmount","rawPrice","hasLimitPrice","tokenSymbol","positionPercent","handlePositionSlider","tokenQuantity","minMarginUsdc","submitState","handleSubmitButtonClick","formatTokenQuantity","n","StyledTooltip","tab","RHForm","isSubmit","buttonType","activeBg","activeColor","isPlacing","PlaceOrderFormWidget","resolvedOnUpdateLeverage","ClosePositionModal","closeType","useTranslation","maxSize","maxSizeRaw","sideLabel","sizeText","setSizeText","percentText","setPercentText","priceText","setPriceText","sizeRef","percentRef","priceRef","sizeNumeric","sliderPercent","handleSizeChange","handleSizeBlur","handlePercentChange","clamped","newSize","handlePercentBlur","handleSliderChange","handlePriceChange","isLimitMode","priceNumeric","hasValidPrice","canSubmit","title","description","confirmLabel","currentPriceDisplay","useClosePosition","onCloseSuccess","onCloseError","isModalOpen","setIsModalOpen","selectedPosition","setSelectedPosition","setCloseType","submitClose","isClosing","openMarketClose","openLimitClose","closeModal","closeSide","getSortValue","comparePositions","aVal","bVal","usePositionsScript","sortKey","setSortKey","sortDir","setSortDir","onSort","currentKey","d","closePosition","ALIGN_TO_JUSTIFY","HEADER_ROW_STYLE","BODY_ROW_STYLE","STRIPE_BG_STYLE","formatUsdPrice","abs","dp","formatUsd2","formatSignedUsd2","formatPercentAbs","formatDateTime","timestamp","yyyy","M","D","hh","mm","ss","HeaderCell","activeSortKey","align","arrow","interactive","justify","inner","cn","COL_STYLE","TABLE_MIN_WIDTH","PositionsUI","onMarketClose","onLimitClose","header","PositionRow","striped","directionLabel","directionColor","pnlColor","PositionsSkeleton","PositionsEmpty","PositionsWidget","compareOrders","useOpenOrdersScript","onCancelSuccess","onCancelError","cancelOrderImpl","cancelOrdersImpl","ordersData","cancelingIdsRef","setIdsVersion","bumpIdsVersion","addCancelingId","id","removeCancelingId","batchPending","setBatchPending","cancelOrderMutate","isFallbackPending","dispatchCancel","sortedOrders","handleCancelOrder","handleCancelAll","isCanceling","describeOrderType","isLimit","OpenOrdersUI","onCancelOrder","onCancelAll","cancelingOrderIds","isCancelingAll","marketLabel","OrderRow","isThisRowCanceling","isBatchCanceling","onCancel","typeLabel","orderValueText","executePriceText","OpenOrdersSkeleton","OpenOrdersEmpty","OpenOrdersWidget","cancelOrders","confirmOpen","setConfirmOpen","requestCancelAll","closeConfirm","confirmCancelAll","compareTrades","useTradeHistoryScript","tradesData","ROW_OUTER_HEIGHT","isBuyDirection","TradeHistoryUI","VirtualBody","containerRef","Row","tradeValue","closedPnl","buy","descriptionColor","TradeHistorySkeleton","TradeHistoryEmpty","TradeHistoryWidget","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","onExpire","secondsLeft","setSecondsLeft","remaining","Modal","ModalHeader","ModalBody","BreakdownSummary","ModalFooter","Button","breakdown","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","stepTitle","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.3.1\";\n}\n\nexport default \"0.3.1\";\n","/**\n * Configuration for {@link RateLimiter}.\n *\n * Defaults track Hyperliquid's documented `/info` budget (1200 weight\n * per minute per IP) and the per-type weight table reverse-engineered\n * from axiom.trade's deployed `hyperliquid-ts-sdk`. The defaults are\n * conservative — leaving the same headroom Axiom does — but every\n * field is overridable so consumers can tighten the budget under\n * shared egress IPs.\n */\nexport interface RateLimiterConfig {\n /** Total weight the bucket can spend per window. Default 1200. */\n capacity?: number;\n /** Window duration in milliseconds. Default 60_000 (1 minute). */\n windowMs?: number;\n}\n\nconst DEFAULT_CAPACITY = 1200;\nconst DEFAULT_WINDOW_MS = 60_000;\nconst MIN_WAIT_MS = 25;\n\n/**\n * Hyperliquid `/info` weight table mirrored from axiom.trade's\n * deployed `hyperliquid-ts-sdk` (see plan §1).\n *\n * Heavy endpoints (user-time-range / paginated) cost 20; metadata and\n * l2/recent endpoints cost 2; signed `/exchange` actions cost 1 per\n * request (HL bills writes against a separate, much smaller bucket).\n *\n * Unknown types fall back to `defaultWeight` (2). Callers can\n * customise via the override map passed to {@link RateLimiter}.\n */\nconst DEFAULT_INFO_WEIGHT = 2;\nconst HEAVY_INFO_WEIGHT = 20;\nconst EXCHANGE_WEIGHT = 1;\n\nconst HEAVY_INFO_TYPES = new Set<string>([\n \"userFills\",\n \"userFillsByTime\",\n \"userFunding\",\n \"userNonFundingLedgerUpdates\",\n \"frontendOpenOrders\",\n \"userRateLimit\",\n \"historicalOrders\",\n \"userTwapSliceFills\",\n \"predictedFundings\",\n]);\n\n/**\n * Resolve the bucket weight for a Hyperliquid `/info` `type`. Returns\n * 2 for unrecognised types so future HL endpoints are treated like the\n * cheaper bulk reads until a deliberate override pins them otherwise.\n */\nexport function weightForInfoType(type: string | undefined): number {\n if (!type) return DEFAULT_INFO_WEIGHT;\n return HEAVY_INFO_TYPES.has(type) ? HEAVY_INFO_WEIGHT : DEFAULT_INFO_WEIGHT;\n}\n\n/** Bucket weight charged for a signed `/exchange` action. */\nexport const EXCHANGE_REQUEST_WEIGHT = EXCHANGE_WEIGHT;\n\n/**\n * Browser-side token bucket aligned with HL's `/info` weight budget.\n *\n * Mirrors the `RateLimiter` in axiom.trade's deployed\n * `hyperliquid-ts-sdk` byte-for-byte: capacity 1200, refill once per\n * minute (not continuous), `waitForToken(weight)` blocks until the\n * next refill when the bucket is empty.\n *\n * Treat this as a process-wide singleton — all calls into the same\n * Hyperliquid REST client share one bucket so concurrent ticker /\n * order-form / portfolio components cooperate against the upstream\n * cap.\n */\nexport class RateLimiter {\n private readonly capacity: number;\n private readonly windowMs: number;\n\n private tokens: number;\n private lastRefill: number;\n\n constructor(config: RateLimiterConfig = {}) {\n this.capacity = config.capacity ?? DEFAULT_CAPACITY;\n this.windowMs = config.windowMs ?? DEFAULT_WINDOW_MS;\n this.tokens = this.capacity;\n this.lastRefill = Date.now();\n }\n\n /**\n * Reset the bucket to full capacity. Useful for tests; production\n * callers should not need this.\n */\n reset(): void {\n this.tokens = this.capacity;\n this.lastRefill = Date.now();\n }\n\n /**\n * Block until `weight` tokens are available, then deduct them and\n * resolve. Re-checks the refill boundary each pass so a long sleep\n * never spins past more than one window.\n */\n async waitForToken(weight: number): Promise<void> {\n const charge = Math.max(1, Math.floor(weight));\n while (true) {\n this.refill();\n if (this.tokens >= charge) {\n this.tokens -= charge;\n return;\n }\n const wait = Math.max(\n MIN_WAIT_MS,\n this.windowMs - (Date.now() - this.lastRefill),\n );\n await new Promise<void>((resolve) => setTimeout(resolve, wait));\n }\n }\n\n /**\n * Top up the bucket if a full window has elapsed since the last\n * refill. Mirrors axiom's discrete-window refill (vs continuous\n * refill) so the bucket never lets a request through that HL would\n * reject — the upstream weight counter snaps back at the same\n * boundary.\n */\n private refill(): void {\n const now = Date.now();\n if (now - this.lastRefill >= this.windowMs) {\n this.tokens = this.capacity;\n this.lastRefill = now;\n }\n }\n}\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 UniverseAssetEntry,\n UniverseSnapshot,\n} from \"../../types\";\nimport {\n EXCHANGE_REQUEST_WEIGHT,\n RateLimiter,\n type RateLimiterConfig,\n weightForInfoType,\n} from \"./RateLimiter\";\nimport {\n WebSocketManager,\n type OrderBookAggregation,\n} from \"./WebSocketManager\";\n\nexport type { OrderBookAggregation };\nexport { RateLimiter, type RateLimiterConfig, weightForInfoType };\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 * Outbound rate-limiter configuration. Defaults align with HL's\n * documented `/info` budget (1200 weight per minute per IP) and the\n * per-type weight table reverse-engineered from axiom.trade's\n * deployed hyperliquid-ts-sdk.\n *\n * Pass `false` to disable client-side rate limiting (e.g. when\n * a server-side proxy is already throttling on our behalf). Pass an\n * existing {@link RateLimiter} instance to share a bucket across\n * multiple client instances. Pass a partial config to tune capacity\n * / window for a custom IP egress topology.\n */\n rateLimit?: RateLimiter | RateLimiterConfig | false;\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 * Cache lifetime for the universe snapshot (`metaAndAssetCtxs`).\n *\n * Short — the snapshot carries live mark prices, funding, OI and 24h\n * volume, which all move on the seconds timescale. The role of this\n * cache is **not** to extend freshness past what consumers expect, but\n * to **collapse concurrent fan-outs** that happen during page mount:\n * when `useUniverseQuery`, `getPositions()` and `getOpenOrders()`\n * land within the same tick, a 1.5 s TTL guarantees they share one\n * `metaAndAssetCtxs` round-trip rather than racing to fire three.\n *\n * `webData2` updates the React Query cache for the universe directly,\n * so this client-side cache is purely a deduplication safety-net for\n * concurrent direct callers; it doesn't affect freshness for the WS\n * push path.\n */\nconst UNIVERSE_SNAPSHOT_TTL_MS = 1_500;\n\n/**\n * Cache lifetime for the per-user state snapshot (`clearinghouseState`\n * + `frontendOpenOrders`).\n *\n * Same role as {@link UNIVERSE_SNAPSHOT_TTL_MS}: collapse concurrent\n * fan-outs during page mount. `getPositions()` and `getOpenOrders()`\n * each fan out a `clearinghouseState` + a `frontendOpenOrders` leg,\n * so when both hooks mount in the same render tick the user can\n * watch them race to fire two of each. A short TTL on a combined\n * snapshot means the second fan-out reuses the first's payload — one\n * `clearinghouseState` and one `frontendOpenOrders` per user, even\n * with five symbol-scoped widgets on the page.\n *\n * `webData2` updates positions and openOrders React Query caches\n * directly, so this client-side cache is again only a safety-net\n * for the brief window before the WS push lands.\n */\nconst USER_STATE_SNAPSHOT_TTL_MS = 1_500;\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 * Process-local cache of the venue's universe snapshot. Concurrent\n * `getUniverseSnapshot()` callers within {@link UNIVERSE_SNAPSHOT_TTL_MS}\n * share the same parsed object (and the underlying\n * `metaAndAssetCtxs` HTTP call) instead of each firing their own.\n */\n private universeSnapshotCache: {\n fetchedAt: number;\n snapshot: UniverseSnapshot;\n } | null = null;\n /**\n * In-flight `getUniverseSnapshot` request, deduped via\n * singleflight semantics so concurrent fan-outs (e.g.\n * `useUniverseQuery` + `getPositions()` + `getOpenOrders()` mounted\n * in the same render tick) collapse onto a single network request.\n */\n private universeSnapshotPending: Promise<UniverseSnapshot> | null = null;\n\n /**\n * Process-local cache of per-user state snapshots\n * (`clearinghouseState` + `frontendOpenOrders`), keyed by lowercased\n * user address. Concurrent `getPositions(user)` / `getOpenOrders(user)`\n * callers within {@link USER_STATE_SNAPSHOT_TTL_MS} share the same\n * parsed object (and the underlying two HL round-trips) instead of\n * each firing their own pair.\n */\n private userStateCache: Map<\n string,\n {\n fetchedAt: number;\n snapshot: HyperliquidUserStateSnapshot;\n }\n > = new Map();\n /**\n * In-flight `getUserStateSnapshot` requests, deduped per user via\n * singleflight semantics. Keyed the same way as\n * {@link userStateCache}.\n */\n private userStatePending: Map<string, Promise<HyperliquidUserStateSnapshot>> =\n new Map();\n\n /**\n * Outbound rate limiter shared across every REST call this client\n * issues. `null` when explicitly disabled via\n * `config.rateLimit === false` — the request path then becomes a\n * straight fetch with no bucket bookkeeping.\n */\n private readonly rateLimiter: RateLimiter | null;\n\n /**\n * 构造 Hyperliquid 客户端\n *\n * @param config 客户端配置,不传则使用默认配置(testnet)\n */\n constructor(config: HyperliquidClientConfig = {}) {\n this.environment = config.environment || \"testnet\";\n\n this.apiEndpoint =\n config.apiEndpoint || HYPERLIQUID_ENDPOINTS[this.environment].api;\n\n this._wsEndpoint =\n config.wsEndpoint || HYPERLIQUID_ENDPOINTS[this.environment].ws;\n\n this.timeout = config.timeout || 30000;\n\n // Rate limiting is opt-out. By default, every client instance\n // gets a fresh 1200-weight/minute bucket aligned with HL's docs.\n // Hosts that share a bucket across multiple clients (e.g. a\n // multi-page app re-instantiating the client per route) can\n // pass an explicit RateLimiter and reuse it.\n if (config.rateLimit === false) {\n this.rateLimiter = null;\n } else if (config.rateLimit instanceof RateLimiter) {\n this.rateLimiter = config.rateLimit;\n } else {\n this.rateLimiter = new RateLimiter(config.rateLimit);\n }\n }\n\n /**\n * Compute the bucket weight to charge for a given endpoint + body.\n *\n * Mirrors axiom.trade's `hyperliquid-ts-sdk` weight table:\n * - `/info` payload `type` → see {@link weightForInfoType}\n * - `/exchange` (signed actions) → 1\n * - everything else → default 2 (matches HL's \"miscellaneous read\"\n * weight)\n */\n private weightFor(endpoint: string, body: any): number {\n if (endpoint.startsWith(\"/exchange\")) {\n return EXCHANGE_REQUEST_WEIGHT;\n }\n if (endpoint.startsWith(\"/info\")) {\n const t =\n body && typeof body === \"object\" && typeof body.type === \"string\"\n ? (body.type as string)\n : undefined;\n return weightForInfoType(t);\n }\n return weightForInfoType(undefined);\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 // Charge the bucket BEFORE dispatching the request. waitForToken\n // blocks when the bucket is empty so concurrent callers naturally\n // serialise against the upstream cap instead of all eating a 429.\n if (this.rateLimiter) {\n await this.rateLimiter.waitForToken(this.weightFor(endpoint, body));\n }\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 snap = await this.getUniverseSnapshot();\n return snap.assets.map((entry) => entry.symbol);\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 *\n * Backed by {@link getUniverseSnapshot} so this and `useMarketsQuery`\n * share the same single `metaAndAssetCtxs` round-trip — keeps the\n * legacy contract green while the SDK migrates to the universe\n * singleton.\n */\n async getMarkets(symbols?: string[]): Promise<MarketData[]> {\n const snap = await this.getUniverseSnapshot();\n if (symbols && symbols.length > 0) {\n const symbolSet = new Set(symbols);\n return snap.assets\n .map((entry) => entry.market)\n .filter((m) => symbolSet.has(m.symbol));\n }\n return snap.assets.map((entry) => entry.market);\n }\n\n /**\n * Snapshot the venue's full perp universe in a single network call.\n *\n * Mirrors axiom.trade's `SymbolConversion.refreshAssetMaps()` — one\n * `metaAndAssetCtxs` round-trip yields both the live market context\n * (price / funding / OI / 24h vol) AND the static metadata\n * (`szDecimals` / `maxLeverage`) for every coin. The SDK funnels every\n * per-symbol consumer (`useMarketQuery`, `useAssetMetaQuery`,\n * ticker bars, `getPositions()` / `getOpenOrders()` mark price\n * enrichment, ...) through this, so 100 components watching the\n * universe still trigger only one HL request per refresh cycle.\n *\n * Backed by a 1.5 s TTL + singleflight cache on the client instance,\n * so concurrent direct callers within the same tick collapse onto a\n * single in-flight request — the React Query layer above adds\n * another tier of dedup keyed by `staleTime`, but caching here too\n * keeps the contract correct for non-React callers and for\n * cross-method fan-outs (positions / orders / markets) that go\n * through `client.*` directly.\n *\n * @see {@link IPerpetualsClient.getUniverseSnapshot}\n */\n async getUniverseSnapshot(): Promise<UniverseSnapshot> {\n const now = Date.now();\n if (\n this.universeSnapshotCache &&\n now - this.universeSnapshotCache.fetchedAt < UNIVERSE_SNAPSHOT_TTL_MS\n ) {\n return this.universeSnapshotCache.snapshot;\n }\n if (this.universeSnapshotPending) {\n return this.universeSnapshotPending;\n }\n\n const fetchPromise = this.fetchUniverseSnapshot();\n this.universeSnapshotPending = fetchPromise;\n try {\n const snapshot = await fetchPromise;\n this.universeSnapshotCache = { fetchedAt: Date.now(), snapshot };\n return snapshot;\n } finally {\n // Clear regardless of outcome so a transient failure doesn't\n // pin every future caller to a rejected promise.\n this.universeSnapshotPending = null;\n }\n }\n\n /**\n * Internal: actually fetch and parse a fresh universe snapshot.\n * Always issues one `metaAndAssetCtxs` round-trip — call\n * {@link getUniverseSnapshot} (which guards this with TTL +\n * singleflight) instead of invoking directly.\n */\n private async fetchUniverseSnapshot(): Promise<UniverseSnapshot> {\n const [meta, assetCtxs] = await this.request<\n [\n {\n universe: Array<{\n name: string;\n szDecimals?: number;\n maxLeverage?: number;\n }>;\n },\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 const assets: UniverseAssetEntry[] = meta.universe.map((asset, index) => {\n const ctx = assetCtxs[index] ?? {};\n const symbol = `${asset.name}-USDC`;\n\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 const market: MarketData = {\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 };\n\n const assetMeta: AssetMeta | null =\n typeof asset.szDecimals === \"number\"\n ? { szDecimals: asset.szDecimals, maxLeverage: asset.maxLeverage }\n : null;\n\n return { coin: asset.name, symbol, market, meta: assetMeta };\n });\n\n const bySymbol = new Map<string, UniverseAssetEntry>();\n for (const entry of assets) {\n bySymbol.set(entry.symbol, entry);\n }\n\n return { assets, bySymbol, fetchedAt: Date.now() };\n }\n\n /**\n * Snapshot the user's full venue state (`clearinghouseState` +\n * `frontendOpenOrders`) in a single coordinated fetch, with an\n * instance-level TTL + singleflight cache.\n *\n * Why this exists: `getPositions()` and `getOpenOrders()` each\n * naturally fan out a `clearinghouseState` and a\n * `frontendOpenOrders` request to enrich their respective return\n * shapes. When `usePositionsQuery` and `useOrdersQuery` mount in\n * the same render tick, that's 2× CHS + 2× FOO over the wire, all\n * for the same user. Routing both through this snapshot collapses\n * the burst into a single pair of HL calls (per\n * {@link USER_STATE_SNAPSHOT_TTL_MS} window). When `webData2` is\n * online it overwrites the React Query caches directly, so this\n * REST path stops firing entirely after the first WS frame.\n *\n * `clearinghouseState` is mandatory; `frontendOpenOrders` is\n * fault-tolerant — the venue occasionally errors on the second leg\n * for fresh users, and we still want positions to render.\n */\n private async getUserStateSnapshot(\n userAddress: string,\n ): Promise<HyperliquidUserStateSnapshot> {\n const key = userAddress.toLowerCase();\n const now = Date.now();\n const cached = this.userStateCache.get(key);\n if (cached && now - cached.fetchedAt < USER_STATE_SNAPSHOT_TTL_MS) {\n return cached.snapshot;\n }\n const inflight = this.userStatePending.get(key);\n if (inflight) {\n return inflight;\n }\n\n const fetchPromise = (async (): Promise<HyperliquidUserStateSnapshot> => {\n const [clearinghouse, openOrders] = await Promise.all([\n this.request<HyperliquidClearinghouseState>(\"/info\", {\n type: \"clearinghouseState\",\n user: userAddress,\n }),\n this.request<HyperliquidOpenOrder[]>(\"/info\", {\n type: \"frontendOpenOrders\",\n user: userAddress,\n }).catch(() => undefined),\n ]);\n return { clearinghouse, openOrders, fetchedAt: Date.now() };\n })();\n\n this.userStatePending.set(key, fetchPromise);\n try {\n const snapshot = await fetchPromise;\n this.userStateCache.set(key, { fetchedAt: Date.now(), snapshot });\n return snapshot;\n } finally {\n // Clear regardless of outcome so a transient failure doesn't\n // pin every future caller to a rejected promise.\n this.userStatePending.delete(key);\n }\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 // Two snapshots, both backed by instance-level TTL + singleflight:\n // - userState: clearinghouseState + frontendOpenOrders (1 round-trip\n // each, shared with getOpenOrders if it lands in the same tick)\n // - universe : metaAndAssetCtxs for the live mark price\n // `Promise.all` keeps the slowest leg the overall latency budget.\n // First-paint render with `usePositionsQuery + useOrdersQuery`\n // mounted simultaneously now collapses to 1× CHS + 1× FOO + 1× MAC\n // (down from 2/2/3 previously) per ~1.5 s window.\n const [userState, universe] = await Promise.all([\n this.getUserStateSnapshot(params.userAddress),\n this.getUniverseSnapshot(),\n ]);\n\n const result = parseClearinghouseState(\n userState.clearinghouse,\n params.symbol,\n );\n const markByCoin = buildMarkPriceMapFromUniverse(universe);\n result.positions = enrichPositions(\n result.positions,\n userState.openOrders ?? [],\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 // We rely on `frontendOpenOrders` (not the bare `openOrders`) so\n // the payload includes `triggerPx`, `triggerCondition`,\n // `isTrigger` and the `children[]` array that bundles TP/SL with\n // their parent limit order. Axiom uses the same venue field, so\n // consuming it directly keeps our data shape identical to theirs.\n //\n // Both `frontendOpenOrders` and `clearinghouseState` are sourced\n // through {@link getUserStateSnapshot}, which the positions\n // fan-out also rides on — that means a same-tick mount of\n // `usePositionsQuery + useOrdersQuery` collapses to **one** pair\n // of CHS + FOO requests instead of two of each.\n //\n // The universe snapshot is again routed through\n // {@link getUniverseSnapshot} so it shares an in-flight\n // `metaAndAssetCtxs` request with positions / ticker bars /\n // useUniverseQuery during the same render tick.\n const [userState, universe] = await Promise.all([\n this.getUserStateSnapshot(params.userAddress).catch(() => null),\n this.getUniverseSnapshot().catch(() => undefined),\n ]);\n\n const openOrdersRaw = userState?.openOrders ?? [];\n const ctx: OpenOrderParseContext = {\n leverageByCoin: buildLeverageMap(userState?.clearinghouse),\n markByCoin: universe\n ? buildMarkPriceMapFromUniverse(universe)\n : undefined,\n };\n\n const orders = openOrdersRaw.map((o) => parseOpenOrder(o, ctx));\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: openOrdersRaw,\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 closedPnl?: 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 dir: fill.dir,\n closedPnl: parseFloat(fill.closedPnl || \"0\"),\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 * Combined per-user state snapshot shared by `getPositions()` and\n * `getOpenOrders()`. Holding both the venue's `clearinghouseState` and\n * `frontendOpenOrders` as a single value lets us cache them together\n * (one TTL, one singleflight) so two simultaneous fan-outs collapse\n * to a single pair of HL round-trips.\n *\n * `openOrders` is optional because Hyperliquid occasionally errors on\n * that leg for accounts that have never placed an order; callers\n * should treat `undefined` as \"no orders\" rather than as a fatal\n * failure for the snapshot.\n */\ninterface HyperliquidUserStateSnapshot {\n clearinghouse: HyperliquidClearinghouseState;\n openOrders: HyperliquidOpenOrder[] | undefined;\n fetchedAt: number;\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 /**\n * Bundled child orders, populated by `frontendOpenOrders` for\n * limit parents that were submitted via the `normalTpsl` grouping.\n * Each child carries `triggerPx` + `orderType` strings, which is the\n * venue's authoritative way to surface bundled TP/SL — no\n * cloid/oid heuristics required.\n */\n children?: HyperliquidOpenOrder[];\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, including the static metadata\n * (`szDecimals` + `maxLeverage`) so consumers can rebuild a\n * {@link UniverseSnapshot} without an extra REST round-trip.\n */\n meta?: {\n universe: Array<{\n name: string;\n szDecimals?: number;\n maxLeverage?: number;\n }>;\n };\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 prevDayPx?: 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 * Optional enrichment context passed to {@link parseOpenOrder}. Both\n * maps are sourced from data the venue surfaces alongside\n * `frontendOpenOrders` (clearinghouseState, metaAndAssetCtxs / webData2),\n * so consumers always have them when calling from the open-orders path.\n */\ninterface OpenOrderParseContext {\n /**\n * `coin → leverage value` derived from\n * `clearinghouseState.assetPositions[].position.leverage.value`.\n * Hyperliquid's order endpoints do not echo leverage per order, so\n * we look it up by coin (matching Axiom's behaviour). When the user\n * has no open position for the order's coin, leverage stays\n * `undefined` and the UI hides the chip.\n */\n leverageByCoin?: Map<string, number>;\n /**\n * `coin → live mark price` from `metaAndAssetCtxs` / webData2. Used\n * to populate the \"Current Price\" column without each row\n * subscribing individually.\n */\n markByCoin?: Map<string, number>;\n}\n\n/**\n * Extract bundled TP / SL trigger prices from a parent limit order's\n * `children` array. Hyperliquid's `frontendOpenOrders` populates\n * `children` directly when an order was submitted via the\n * `normalTpsl` grouping — the children's `orderType` string\n * unambiguously discriminates TP from SL, so no cloid / oid\n * heuristics are required.\n *\n * Returns `{}` for trigger orders themselves (their `children` is\n * always empty) and for limit orders without bundled exits.\n */\nfunction extractBundledTpSl(order: HyperliquidOpenOrder): {\n takeProfitPrice?: number;\n stopLossPrice?: number;\n} {\n if (!order.children || order.children.length === 0) return {};\n let tp: number | undefined;\n let sl: number | undefined;\n for (const child of order.children) {\n const orderTypeStr =\n typeof child.orderType === \"string\" ? child.orderType : \"\";\n const triggerPxStr = child.triggerPx;\n if (typeof triggerPxStr !== \"string\" || triggerPxStr.length === 0) continue;\n const px = parseFloat(triggerPxStr);\n if (!Number.isFinite(px) || px <= 0) continue;\n\n if (/take\\s*profit/i.test(orderTypeStr)) tp = px;\n else if (/stop/i.test(orderTypeStr)) sl = px;\n }\n return { takeProfitPrice: tp, stopLossPrice: sl };\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, `children`) and\n * the simpler `webData2.openOrders` push (boolean side, no trigger\n * metadata).\n *\n * Optional `ctx` injects per-coin leverage and mark price so the\n * resulting {@link Order} is self-contained for the Open Orders table.\n * When omitted (callers that only need the basic shape), those fields\n * stay `undefined`.\n */\nfunction parseOpenOrder(\n order: HyperliquidOpenOrder,\n ctx?: OpenOrderParseContext,\n): 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 const { takeProfitPrice, stopLossPrice } = extractBundledTpSl(order);\n const leverage = ctx?.leverageByCoin?.get(order.coin);\n const markPrice = ctx?.markByCoin?.get(order.coin);\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 leverage,\n reduceOnly: order.reduceOnly === true,\n isTrigger: isTrigger || undefined,\n triggerPx,\n triggerType,\n triggerCondition,\n markPrice,\n takeProfitPrice,\n stopLossPrice,\n };\n}\n\n/**\n * Build a `coin → leverage value` map from a clearinghouseState\n * payload. Mirrors Axiom's lookup: open orders don't carry leverage,\n * but each open position does, and the user is virtually always\n * looking at orders for a coin they also have a position on (or are\n * about to open one for).\n */\nfunction buildLeverageMap(\n data: HyperliquidClearinghouseState | undefined,\n): Map<string, number> {\n const map = new Map<string, number>();\n if (!data) return map;\n for (const ap of data.assetPositions ?? []) {\n const lev = ap.position?.leverage?.value;\n if (typeof lev === \"number\" && Number.isFinite(lev) && lev > 0) {\n map.set(ap.position.coin, lev);\n }\n }\n return map;\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 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 // Build the same maps for the open-orders enrichment so the live\n // table sees leverage/mark identical to what the REST `getOpenOrders`\n // call would return. Reusing the already-decoded clearinghouseState\n // / assetCtxs avoids a second request.\n const leverageByCoinMap = buildLeverageMap(clearinghouse);\n const openOrders = openOrdersRaw.map((o) =>\n parseOpenOrder(o, {\n leverageByCoin: leverageByCoinMap,\n markByCoin: markByCoin ?? undefined,\n }),\n );\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 // Build a universe snapshot from the embedded `meta` + `assetCtxs`\n // so consumers can keep `useUniverseQuery` fresh without an extra\n // `metaAndAssetCtxs` round-trip. We mirror the wire format produced\n // by `getUniverseSnapshot()` so downstream selectors stay agnostic\n // about whether the data came from REST or WS.\n const universe =\n raw.meta && raw.assetCtxs\n ? buildUniverseSnapshot(raw.meta, raw.assetCtxs, raw.serverTime)\n : undefined;\n\n // Surface leverage as a plain Record so the React Query cache stays\n // serialisable; consumers (e.g. useAccountStateSubscription) write\n // through into `useActiveAssetLeverageQuery` from this map. Pull the\n // explicit `type` (isolated/cross) directly off the clearinghouse\n // payload — leverageByCoinMap only carries the value.\n const leverageByCoin = clearinghouse\n ? buildLeverageRecord(clearinghouse)\n : undefined;\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 leverageByCoin,\n universe,\n raw,\n };\n}\n\n/**\n * Build a {@link UniverseSnapshot} from the `meta` + `assetCtxs` slices\n * Hyperliquid embeds in `webData2`.\n *\n * Mirrors {@link HyperliquidPerpetualsClient.getUniverseSnapshot} so\n * consumers can write either source into the same React Query cache\n * slot without introducing a venue→SDK shape divergence.\n */\nfunction buildUniverseSnapshot(\n meta: NonNullable<HyperliquidWebData2Payload[\"meta\"]>,\n assetCtxs: NonNullable<HyperliquidWebData2Payload[\"assetCtxs\"]>,\n serverTime?: number,\n): UniverseSnapshot {\n const assets: UniverseAssetEntry[] = meta.universe.map((asset, index) => {\n const ctx = assetCtxs[index] ?? {};\n const symbol = `${asset.name}-USDC`;\n const currentPrice = parseFloat(ctx.midPx || ctx.markPx || \"0\");\n const prevDayPx = (ctx as { prevDayPx?: string }).prevDayPx;\n const prevPrice = prevDayPx ? parseFloat(prevDayPx) : currentPrice;\n const change24h =\n prevPrice > 0 ? ((currentPrice - prevPrice) / prevPrice) * 100 : 0;\n\n const market: MarketData = {\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 };\n\n const szDecimals = (asset as { szDecimals?: number }).szDecimals;\n const maxLeverage = (asset as { maxLeverage?: number }).maxLeverage;\n const assetMeta: AssetMeta | null =\n typeof szDecimals === \"number\" ? { szDecimals, maxLeverage } : null;\n\n return { coin: asset.name, symbol, market, meta: assetMeta };\n });\n\n const bySymbol = new Map<string, UniverseAssetEntry>();\n for (const entry of assets) {\n bySymbol.set(entry.symbol, entry);\n }\n\n return {\n assets,\n bySymbol,\n fetchedAt: serverTime ?? Date.now(),\n };\n}\n\n/**\n * Build a `coin → { value, type }` Record from a clearinghouseState\n * payload. Used by {@link parseWebData2} to expose per-coin leverage\n * to consumers via {@link AccountState.leverageByCoin}.\n */\nfunction buildLeverageRecord(\n data: HyperliquidClearinghouseState,\n): Record<string, { value: number; type: \"isolated\" | \"cross\" }> {\n const out: Record<string, { value: number; type: \"isolated\" | \"cross\" }> = {};\n for (const ap of data.assetPositions ?? []) {\n const lev = ap.position?.leverage;\n if (!lev || typeof lev.value !== \"number\") continue;\n const type =\n lev.type === \"isolated\" || lev.type === \"cross\" ? lev.type : \"cross\";\n out[ap.position.coin] = { value: lev.value, type };\n }\n return out;\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 * Same shape as {@link buildMarkPriceMap} but sources its inputs from\n * a parsed {@link UniverseSnapshot}. Lets `getPositions()` /\n * `getOpenOrders()` reuse the already-decoded snapshot returned by\n * {@link HyperliquidPerpetualsClient.getUniverseSnapshot} instead of\n * issuing their own `metaAndAssetCtxs` round-trip.\n *\n * Mark price preference: `markPrice` (the venue's authoritative\n * value) → `price` (the mid/mark composite the snapshot computes for\n * display). Both fall back to 0 when the venue omits them, which we\n * filter out so the map only contains usable positive prices.\n */\nfunction buildMarkPriceMapFromUniverse(\n universe: UniverseSnapshot,\n): Map<string, number> {\n const map = new Map<string, number>();\n for (const entry of universe.assets) {\n const px =\n entry.market.markPrice && entry.market.markPrice > 0\n ? entry.market.markPrice\n : entry.market.price;\n if (Number.isFinite(px) && px > 0) {\n map.set(entry.coin, 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 UniverseAssetEntry,\n UniverseSnapshot,\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 /**\n * Snapshot the venue's full perp universe via a single `/v1/markets`\n * call.\n *\n * Hosts the SDK's `useUniverseQuery` global singleton — every\n * per-symbol consumer (ticker bars, market headers, asset meta\n * lookups, ...) derives from this so 100 components watching the\n * universe still trigger only one request per refresh cycle.\n *\n * `meta` stays `null` because the LiberFi backend does not yet\n * expose `szDecimals` / `maxLeverage`. Consumers that need that data\n * fall back to their own heuristics (the form already does this).\n */\n async getUniverseSnapshot(): Promise<UniverseSnapshot> {\n const markets = await this.getMarkets();\n const assets: UniverseAssetEntry[] = markets.map((market) => {\n const coin = market.symbol.split(\"-\")[0];\n return { coin, symbol: market.symbol, market, meta: null };\n });\n const bySymbol = new Map<string, UniverseAssetEntry>();\n for (const entry of assets) {\n bySymbol.set(entry.symbol, entry);\n }\n return { assets, bySymbol, fetchedAt: Date.now() };\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, type UseQueryOptions } from \"@tanstack/react-query\";\nimport type { IPerpetualsClient, UniverseSnapshot } from \"../types\";\nimport { usePerpetualsClient } from \"./usePerpetualsClient\";\n\n/**\n * Default polling cadence for the universe snapshot. Mirrors what we\n * observed on axiom.trade's perps page (`SymbolConversion.refreshIntervalMs\n * = 6e4`) — they refresh meta + asset contexts (mark price, funding rate,\n * open interest, 24h volume) once a minute and feed every per-symbol\n * consumer from that single global cache.\n *\n * 60s is well below the cadence at which Hyperliquid actually adjusts\n * the universe (listing additions / leverage caps move on a weekly\n * basis at most), but small enough that funding / OI numbers don't\n * drift visibly between updates.\n */\nconst DEFAULT_REFETCH_INTERVAL_MS = 60_000;\n\n/**\n * Stable React Query key for the global universe snapshot.\n *\n * The key is intentionally argument-free so every consumer in the\n * application reads from the same cache slot. Hooks like\n * {@link useMarketQuery}, {@link useMarketsQuery},\n * {@link useAssetMetaQuery} and ticker bars derive their data from\n * here via `select`, sharing one network round-trip per refresh cycle.\n */\nexport function universeQueryKey(): string[] {\n return [\"perps\", \"universe\"];\n}\n\n/**\n * Fetch the venue's universe snapshot through the active client.\n *\n * Throws when the active adapter doesn't implement\n * `getUniverseSnapshot` — callers should gate on\n * {@link supportsUniverseSnapshot} first or rely on\n * {@link useUniverseQuery}'s `enabled` guard, which checks the same\n * thing.\n */\nexport async function fetchUniverse(\n client: IPerpetualsClient,\n): Promise<UniverseSnapshot> {\n if (typeof client.getUniverseSnapshot !== \"function\") {\n throw new Error(\n \"useUniverseQuery: the active perpetuals client does not implement getUniverseSnapshot()\",\n );\n }\n return client.getUniverseSnapshot();\n}\n\n/**\n * Reports whether the active client can back {@link useUniverseQuery}.\n *\n * Adapters that omit `getUniverseSnapshot` (e.g. legacy LiberFi\n * deployments that still proxy market data per symbol) leave\n * `useUniverseQuery` disabled; consumers gracefully fall back to the\n * legacy per-symbol queries in that case.\n */\nexport function supportsUniverseSnapshot(client: IPerpetualsClient): boolean {\n return typeof client.getUniverseSnapshot === \"function\";\n}\n\n/**\n * Subscribe to the venue's universe snapshot.\n *\n * One global singleton: every {@link useUniverseQuery} call shares the\n * same `[\"perps\", \"universe\"]` cache slot, so React Query collapses\n * concurrent consumers onto a single in-flight request and a single\n * 60-second polling timer regardless of how many components mount.\n *\n * Per-symbol hooks (`useMarketQuery`, `useMarketsQuery`,\n * `useAssetMetaQuery`) read this cache via `select` so they don't\n * issue their own network requests — the cure for the N-ticker fan-out\n * pattern that triggers Hyperliquid 429s.\n *\n * The cache is also populated by `useAccountStateSubscription` when\n * `webData2` pushes meta / assetCtxs, so an active WebSocket session\n * keeps the universe fresh between polls without extra REST traffic.\n */\nexport function useUniverseQuery(\n options: Omit<\n UseQueryOptions<UniverseSnapshot, Error, UniverseSnapshot, string[]>,\n \"queryKey\" | \"queryFn\"\n > = {},\n) {\n const { client } = usePerpetualsClient();\n const enabled = supportsUniverseSnapshot(client) && options.enabled !== false;\n\n return useQuery({\n queryKey: universeQueryKey(),\n queryFn: () => fetchUniverse(client),\n refetchInterval: DEFAULT_REFETCH_INTERVAL_MS,\n // Treat the snapshot 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 ...options,\n enabled,\n });\n}\n","import { useQuery, type UseQueryOptions } from \"@tanstack/react-query\";\nimport type { IPerpetualsClient, MarketData, UniverseSnapshot } from \"../types\";\nimport { usePerpetualsClient } from \"./usePerpetualsClient\";\nimport {\n supportsUniverseSnapshot,\n universeQueryKey,\n fetchUniverse,\n} from \"./useUniverseQuery\";\n\nexport interface UseMarketQueryParams {\n symbol: string;\n}\n\n/**\n * Default polling cadence for the legacy per-symbol fallback. Used\n * only when the active adapter does not implement\n * `getUniverseSnapshot` — modern Hyperliquid / LiberFi paths derive\n * from {@link useUniverseQuery}'s 60s singleton instead.\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\n/**\n * Read the live market snapshot for `symbol`.\n *\n * When the active adapter exposes {@link IPerpetualsClient.getUniverseSnapshot}\n * (Hyperliquid + LiberFi today), this hook becomes a thin selector\n * over the global {@link useUniverseQuery} cache — every ticker /\n * header / order form in the page shares the same single 60s poll.\n * Otherwise we fall back to the legacy per-symbol REST query so older\n * deployments keep working unchanged.\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\n // Modern adapter path: derive from the universe singleton.\n const universeBacked = supportsUniverseSnapshot(client);\n const universeQuery = useQuery<\n UniverseSnapshot,\n Error,\n MarketData | null,\n string[]\n >({\n queryKey: universeQueryKey(),\n queryFn: () => fetchUniverse(client),\n refetchInterval: DEFAULT_REFETCH_INTERVAL_MS,\n staleTime: DEFAULT_REFETCH_INTERVAL_MS / 2,\n enabled: universeBacked && options.enabled !== false && !!params.symbol,\n select: (snap) => snap.bySymbol.get(params.symbol)?.market ?? null,\n });\n\n // Legacy fallback for adapters without a universe snapshot.\n const fallbackQuery = useQuery({\n queryKey: marketQueryKey(params),\n queryFn: async () => fetchMarket(client, params),\n staleTime: DEFAULT_REFETCH_INTERVAL_MS / 2,\n refetchInterval: DEFAULT_REFETCH_INTERVAL_MS,\n ...options,\n enabled: !universeBacked && options.enabled !== false && !!params.symbol,\n });\n\n return universeBacked ? universeQuery : fallbackQuery;\n}\n","import { useQuery, type UseQueryOptions } from \"@tanstack/react-query\";\nimport type { IPerpetualsClient, MarketData, UniverseSnapshot } from \"../types\";\nimport { usePerpetualsClient } from \"./usePerpetualsClient\";\nimport {\n supportsUniverseSnapshot,\n universeQueryKey,\n fetchUniverse,\n} from \"./useUniverseQuery\";\n\nexport interface UseMarketsQueryParams {\n symbols?: string[];\n}\n\n/**\n * Default polling cadence for the legacy fallback path — kept in sync\n * with {@link useUniverseQuery}'s singleton so user-visible refresh\n * cadence is identical regardless of which path is active.\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\n/**\n * Read live market snapshots for one or more symbols.\n *\n * When the active adapter exposes\n * {@link IPerpetualsClient.getUniverseSnapshot}, this is a derived\n * read over the global {@link useUniverseQuery} cache — a 100-ticker\n * bar still triggers only one HL `metaAndAssetCtxs` request per 60s.\n * Otherwise we fall back to the legacy `getMarkets()` REST poll.\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\n const universeBacked = supportsUniverseSnapshot(client);\n const universeQuery = useQuery<\n UniverseSnapshot,\n Error,\n MarketData[],\n string[]\n >({\n queryKey: universeQueryKey(),\n queryFn: () => fetchUniverse(client),\n refetchInterval: DEFAULT_REFETCH_INTERVAL_MS,\n staleTime: DEFAULT_REFETCH_INTERVAL_MS / 2,\n enabled: universeBacked && options.enabled !== false,\n select: (snap) => {\n if (!params.symbols || params.symbols.length === 0) {\n return snap.assets.map((a) => a.market);\n }\n const filter = new Set(params.symbols);\n return snap.assets\n .filter((a) => filter.has(a.symbol))\n .map((a) => a.market);\n },\n });\n\n const fallbackQuery = useQuery({\n queryKey: marketsQueryKey(params),\n queryFn: async () => fetchMarkets(client, params),\n staleTime: DEFAULT_REFETCH_INTERVAL_MS / 2,\n refetchInterval: DEFAULT_REFETCH_INTERVAL_MS,\n ...options,\n enabled: !universeBacked && options.enabled !== false,\n });\n\n return universeBacked ? universeQuery : fallbackQuery;\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\n/**\n * Canonical query key for the user's full positions snapshot. Always\n * keyed by `userAddress` only — per-symbol consumers derive a filtered\n * view via TanStack Query's `select` option so the entire app shares\n * one in-flight request per user, regardless of how many symbol-scoped\n * widgets are mounted (positions table + order form + position card +\n * ...).\n *\n * Backwards-compatibility: callers that previously passed a `symbol`\n * still get the same shape they expect (filtered positions), just\n * without firing an extra `clearinghouseState` / `frontendOpenOrders` /\n * `metaAndAssetCtxs` round-trip.\n */\nexport function positionsQueryKey(\n params: Omit<UsePositionsQueryParams, \"enabled\" | \"symbol\">,\n): string[] {\n return [\"perps\", \"positions\", params.userAddress ?? \"\"];\n}\n\nexport async function fetchPositions(\n client: IPerpetualsClient,\n params: GetPositionsParams,\n): Promise<GetPositionsResult> {\n return await client.getPositions(params);\n}\n\n/**\n * Filter the global positions snapshot down to a single symbol while\n * keeping the totals (`totalUnrealizedPnl`, `totalMarginUsed`, ...)\n * intact — those are user-level aggregates, not per-symbol.\n */\nfunction filterPositionsBySymbol(\n result: GetPositionsResult,\n symbol: string,\n): GetPositionsResult {\n return {\n ...result,\n positions: result.positions.filter((p) => p.symbol === symbol),\n };\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, userAddress, symbol } = params;\n\n // Single, user-level fetch — the per-symbol case is a pure derive.\n return useQuery<GetPositionsResult, Error, GetPositionsResult, string[]>({\n queryKey: positionsQueryKey({ userAddress }),\n queryFn: async () => fetchPositions(client, { userAddress }),\n enabled: enabled && !!userAddress,\n staleTime: 10 * 1000,\n select: symbol\n ? (data) => filterPositionsBySymbol(data, symbol)\n : undefined,\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\n/**\n * Canonical query key for the user's full open-orders snapshot. Like\n * {@link positionsQueryKey}, the symbol is intentionally absent from\n * the key — per-symbol callers derive a filtered view via `select`\n * so the entire app shares one in-flight `frontendOpenOrders` /\n * `clearinghouseState` / `metaAndAssetCtxs` fan-out per user.\n */\nexport function ordersQueryKey(\n params: Omit<UseOrdersQueryParams, \"enabled\" | \"symbol\">,\n): string[] {\n return [\"perps\", \"orders\", params.userAddress ?? \"\"];\n}\n\nexport async function fetchOrders(\n client: IPerpetualsClient,\n params: GetOpenOrdersParams,\n): Promise<GetOpenOrdersResult> {\n return await client.getOpenOrders(params);\n}\n\n/**\n * Filter the global orders snapshot down to a single symbol. Keeps\n * the raw payload intact for advanced consumers that may want the\n * unfiltered venue response (e.g. cross-coin bulk cancels).\n */\nfunction filterOrdersBySymbol(\n result: GetOpenOrdersResult,\n symbol: string,\n): GetOpenOrdersResult {\n const orders = result.orders.filter((o) => o.symbol === symbol);\n return {\n ...result,\n orders,\n totalCount: orders.length,\n };\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, userAddress, symbol } = params;\n\n return useQuery<GetOpenOrdersResult, Error, GetOpenOrdersResult, string[]>({\n queryKey: ordersQueryKey({ userAddress }),\n queryFn: async () => fetchOrders(client, { userAddress }),\n enabled: enabled && !!userAddress,\n staleTime: 5 * 1000,\n select: symbol ? (data) => filterOrdersBySymbol(data, symbol) : undefined,\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, type UseQueryOptions } from \"@tanstack/react-query\";\nimport type {\n AssetMeta,\n GetAssetMetaParams,\n IPerpetualsClient,\n UniverseSnapshot,\n} from \"../types\";\nimport { usePerpetualsClient } from \"./usePerpetualsClient\";\nimport {\n supportsUniverseSnapshot,\n universeQueryKey,\n fetchUniverse,\n} from \"./useUniverseQuery\";\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 * Refresh cadence for the legacy fallback path. Asset metadata is\n * stable on the timescale of weeks (listings / leverage caps) but the\n * universe singleton already polls every minute, so we keep the\n * fallback aligned to avoid surprising drift between the two paths.\n */\nconst DEFAULT_STALE_TIME_MS = 60_000;\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`.\n *\n * When the active adapter exposes `getUniverseSnapshot` (Hyperliquid +\n * LiberFi today), this is a derived read over the\n * {@link useUniverseQuery} cache — no extra `meta` round-trip is\n * issued per symbol. Otherwise we fall back to the legacy\n * `client.getAssetMeta(...)` call.\n *\n * The data is process-stable for minutes at a time, so the fallback\n * uses a 60s `staleTime`; consumers don't need to invalidate this on\n * user actions — the data is keyed on 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 const universeBacked = supportsUniverseSnapshot(client);\n const universeQuery = useQuery<\n UniverseSnapshot,\n Error,\n AssetMeta | null,\n string[]\n >({\n queryKey: universeQueryKey(),\n queryFn: () => fetchUniverse(client),\n refetchInterval: DEFAULT_STALE_TIME_MS,\n staleTime: DEFAULT_STALE_TIME_MS / 2,\n enabled: universeBacked && enabled && !!symbol,\n select: (snap) =>\n symbol ? (snap.bySymbol.get(symbol)?.meta ?? null) : null,\n });\n\n const fallbackQuery = useQuery({\n queryKey: assetMetaQueryKey({ symbol }),\n queryFn: async () => {\n if (!symbol) {\n throw new Error(\"useAssetMetaQuery: symbol is required\");\n }\n return fetchAssetMeta(client, { symbol });\n },\n enabled: !universeBacked && enabled && !!symbol,\n staleTime: DEFAULT_STALE_TIME_MS,\n ...options,\n });\n\n return universeBacked ? universeQuery : fallbackQuery;\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 { activeAssetLeverageQueryKey } from \"./useActiveAssetLeverageQuery\";\nimport { ordersQueryKey } from \"./useOrdersQuery\";\nimport { usePerpetualsClient } from \"./usePerpetualsClient\";\nimport { positionsQueryKey } from \"./usePositionsQuery\";\nimport { universeQueryKey } from \"./useUniverseQuery\";\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 // Positions: write through to the canonical user-level cache\n // slot. Per-symbol consumers derive a filtered view via\n // `usePositionsQuery({ userAddress, symbol })`'s `select`\n // option — they share the same cache entry and re-render\n // automatically on every push without a separate REST poll.\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 // Open orders: same write-through pattern — one cache slot per\n // user, per-symbol consumers derive via `select`.\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 // Universe write-through: when the venue's unified push embeds\n // the asset universe (Hyperliquid `webData2` carries `meta` +\n // `assetCtxs`), feed it straight into useUniverseQuery's cache.\n // A live WS session keeps the universe fresh between polls — the\n // 60s REST refresh from useUniverseQuery is only needed as a\n // backstop when the WS reconnects.\n if (state.universe) {\n queryClient.setQueryData(universeQueryKey(), state.universe);\n }\n\n // Per-asset leverage write-through: webData2 carries every\n // coin's leverage configuration on each push, so the place-order\n // form can read it from the same React Query cache without\n // issuing a per-(user,symbol) REST hit.\n if (state.leverageByCoin) {\n for (const [coin, lev] of Object.entries(state.leverageByCoin)) {\n queryClient.setQueryData(\n activeAssetLeverageQueryKey({\n userAddress,\n symbol: `${coin}-USDC`,\n }),\n lev,\n );\n }\n }\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","\"use client\";\n\nimport { useEffect } from \"react\";\nimport { useQueryClient } from \"@tanstack/react-query\";\nimport type { GetOpenOrdersResult, GetPositionsResult } from \"../types\";\nimport { accountStateQueryKey } from \"./useAccountStateQuery\";\nimport { ordersQueryKey } from \"./useOrdersQuery\";\nimport { usePerpetualsClient } from \"./usePerpetualsClient\";\nimport { positionsQueryKey } from \"./usePositionsQuery\";\n\nexport interface UseHyperliquidUserBootstrapParams {\n /**\n * Wallet address whose positions / open orders should be seeded.\n * The hook is a no-op when undefined or empty so it's safe to mount\n * before authentication completes.\n */\n userAddress?: string;\n /**\n * Disable the bootstrap entirely (useful for SSR). Defaults to true.\n */\n enabled?: boolean;\n /**\n * Grace period before falling back to REST. webData2's initial\n * snapshot typically lands within ~500ms; we wait a little longer\n * to cover slow WS handshakes / network blips before paying for a\n * REST round-trip. Defaults to 3 000 ms.\n */\n timeoutMs?: number;\n}\n\n/**\n * One-shot REST bootstrap for the user's perpetuals state.\n *\n * Mirrors axiom.trade's first-connect behaviour: when the page\n * mounts, the WS singleton (`useAccountStateSubscription`) is the\n * primary channel for positions / orders / spot balances, and any\n * subsequent updates are pushed via `webData2`. The first frame\n * usually arrives before any UI gating matters, but on slow WS\n * handshakes the place-order form can blink a \"loading\" state for\n * seconds.\n *\n * This hook covers that gap: after `timeoutMs` of inactivity it\n * issues exactly **one** REST round-trip (positions + open orders) to\n * seed the React Query cache, then stops. If `webData2`'s initial\n * snapshot has already populated the cache by the time the timer\n * fires, the fallback is skipped — keeping HL `/info` traffic at a\n * minimum even on cold pages.\n *\n * Mount this hook **once** at the same level as\n * `useAccountStateSubscription` (typically the perpetuals shell /\n * layout). Children read positions / orders through the existing\n * query hooks; nothing else needs to know the bootstrap exists.\n */\nexport function useHyperliquidUserBootstrap(\n params: UseHyperliquidUserBootstrapParams,\n): void {\n const { userAddress, enabled = true, timeoutMs = 3000 } = params;\n const { client } = usePerpetualsClient();\n const queryClient = useQueryClient();\n\n useEffect(() => {\n if (!enabled || !userAddress) return;\n\n let cancelled = false;\n const timer = setTimeout(() => {\n if (cancelled) return;\n\n // Skip the fallback when the WS subscription has already\n // primed the canonical accountState slot — that means\n // webData2's first frame landed inside the grace window and a\n // REST hit would be redundant.\n const primed = queryClient.getQueryData(\n accountStateQueryKey({ userAddress }),\n );\n if (primed) return;\n\n void (async () => {\n try {\n const [positions, orders] = await Promise.all([\n client.getPositions({ userAddress }),\n client.getOpenOrders({ userAddress }),\n ]);\n if (cancelled) return;\n\n // Write into the same cache slots `useAccountStateSubscription`\n // would populate, so per-symbol forms reading from\n // `usePositionsQuery({ userAddress, symbol })` see the data\n // immediately. We do NOT touch the accountState slot\n // (positions + orders alone can't reconstruct it) — the WS\n // push is the canonical source for that.\n queryClient.setQueryData<GetPositionsResult>(\n positionsQueryKey({ userAddress }),\n positions,\n );\n queryClient.setQueryData<GetOpenOrdersResult>(\n ordersQueryKey({ userAddress }),\n orders,\n );\n } catch (err) {\n // Bootstrap is best-effort — don't disrupt the page if it\n // fails, the WS subscription remains the source of truth.\n if (process.env.NODE_ENV !== \"production\") {\n console.warn(\n \"[useHyperliquidUserBootstrap] fallback REST failed:\",\n err,\n );\n }\n }\n })();\n }, timeoutMs);\n\n return () => {\n cancelled = true;\n clearTimeout(timer);\n };\n }, [client, queryClient, userAddress, enabled, timeoutMs]);\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 /** Raw venue mark price, unaffected by user's limit price input. */\n marketPrice: 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 marketPrice = marketData?.price || 0;\n\n const currentPrice = useMemo(() => {\n if (orderType === \"limit\" && price) {\n return price;\n }\n return marketPrice;\n }, [orderType, price, marketPrice]);\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 marketPrice,\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 /** Raw venue mark price for display reference (unaffected by limit price input). */\n marketPrice?: 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 * Plain controlled input for the limit price field. Uses the same\n * pattern as `BuyAmountInput` — own string state, keystroke-level\n * sync to RHF — to avoid HeroUI NumberField's blur-only commit\n * which clobbers mid-typing text and feeds back into `currentPrice`.\n */\nfunction LimitPriceInput({\n methods,\n placeholder,\n}: {\n methods: UseFormReturn<PlaceOrderFormData>;\n placeholder: string;\n}) {\n const formValue = methods.watch(\"price\");\n const numericValue =\n typeof formValue === \"number\" && Number.isFinite(formValue)\n ? formValue\n : undefined;\n\n const [inputText, setInputText] = useState<string>(() =>\n numericValue !== undefined ? String(numericValue) : \"\",\n );\n const inputRef = useRef<HTMLInputElement | null>(null);\n\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 methods.setValue(\"price\", 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(\"price\", parsed, {\n shouldValidate: false,\n shouldDirty: true,\n });\n },\n [methods],\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=\"price\"\n placeholder={placeholder}\n aria-label=\"Limit price\"\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 marketPrice,\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 rawPrice = methods.watch(\"price\");\n const hasLimitPrice =\n typeof rawPrice === \"number\" && Number.isFinite(rawPrice) && rawPrice > 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 if (orderType === \"limit\" && !hasLimitPrice) {\n return {\n label: \"Invalid Limit Price\",\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 orderType,\n hasLimitPrice,\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 {/* 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 {/* Limit price input — placed below the slider so the user\n sizes their margin first, then sets the price target.\n The right-side label shows the live mark price for\n reference; the placeholder mirrors it so an empty field\n communicates \"current price\". Both update in real-time\n as the mark price streams in. */}\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\" }}>\n Limit Price\n </span>\n <span style={{ fontSize: 12, color: \"#6b6b6b\" }}>\n {marketPrice && marketPrice > 0\n ? `Current Price: ${formatLiqPrice(marketPrice)}`\n : \"--\"}\n </span>\n </div>\n <LimitPriceInput\n methods={methods}\n placeholder={\n marketPrice && marketPrice > 0\n ? formatLiqPrice(marketPrice)\n : \"$0.0\"\n }\n />\n </div>\n )}\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 marketPrice,\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 marketPrice={marketPrice}\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 {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n type CSSProperties,\n} from \"react\";\nimport { useTranslation } from \"@liberfi.io/i18n\";\nimport { ModalContent, Spinner, StyledModal, XCloseIcon } from \"@liberfi.io/ui\";\nimport { useAuthCallback } from \"@liberfi.io/wallet-connector\";\nimport type { Position } from \"../../types\";\nimport type { CloseType } from \"./use-close-position\";\n\nconst BRAND_PRIMARY = \"#C7FF2E\";\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\nexport type ClosePositionModalProps = {\n isOpen: boolean;\n position: Position | null;\n closeType: CloseType;\n isSubmitting: boolean;\n onClose: () => void;\n onConfirm: (size: number, price?: number) => Promise<void>;\n};\n\nexport function ClosePositionModal({\n isOpen,\n position,\n closeType,\n isSubmitting,\n onClose,\n onConfirm,\n}: ClosePositionModalProps) {\n const { t } = useTranslation();\n\n const maxSize = position ? Math.abs(position.quantity) : 0;\n const maxSizeRaw = position?.quantityRaw ?? String(maxSize);\n const tokenSymbol = position?.symbol.split(\"-\")[0] ?? \"\";\n const isLong = position?.side === \"long\";\n const sideLabel = isLong\n ? t(\"perpetuals.positions.long\")\n : t(\"perpetuals.positions.short\");\n\n // Local input state\n const [sizeText, setSizeText] = useState(\"\");\n const [percentText, setPercentText] = useState(\"100\");\n const [priceText, setPriceText] = useState(\"\");\n const sizeRef = useRef<HTMLInputElement>(null);\n const percentRef = useRef<HTMLInputElement>(null);\n const priceRef = useRef<HTMLInputElement>(null);\n\n // Reset state when modal opens or position changes\n useEffect(() => {\n if (isOpen && position) {\n const qty = Math.abs(position.quantity);\n setSizeText(position.quantityRaw ?? String(qty));\n setPercentText(\"100\");\n setPriceText(\"\");\n }\n }, [isOpen, position]);\n\n const sizeNumeric = useMemo(() => {\n const v = parseFloat(sizeText);\n return Number.isFinite(v) && v > 0 ? v : 0;\n }, [sizeText]);\n\n const percentNumeric = useMemo(() => {\n const v = parseFloat(percentText);\n return Number.isFinite(v) ? Math.max(0, Math.min(100, v)) : 0;\n }, [percentText]);\n\n const sliderPercent = useMemo(() => {\n if (maxSize <= 0 || sizeNumeric <= 0) return 0;\n const pct = (sizeNumeric / maxSize) * 100;\n return Math.max(0, Math.min(100, pct));\n }, [sizeNumeric, maxSize]);\n\n // --- Handlers ---\n\n const handleSizeChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const cleaned = sanitiseAmountInput(e.target.value);\n const parsed = parseFloat(cleaned);\n if (Number.isFinite(parsed) && parsed > maxSize && maxSize > 0) {\n setSizeText(position?.quantityRaw ?? String(maxSize));\n setPercentText(\"100\");\n return;\n }\n setSizeText(cleaned);\n if (Number.isFinite(parsed) && maxSize > 0) {\n const pct = Math.round((parsed / maxSize) * 100);\n setPercentText(String(Math.min(100, pct)));\n } else if (cleaned === \"\" || cleaned === \".\") {\n setPercentText(\"0\");\n }\n },\n [maxSize, position?.quantityRaw],\n );\n\n const handleSizeBlur = useCallback(() => {\n const parsed = parseFloat(sizeText);\n if (!Number.isFinite(parsed) || parsed <= 0) {\n setSizeText(\"0\");\n setPercentText(\"0\");\n } else if (parsed > maxSize && maxSize > 0) {\n setSizeText(position?.quantityRaw ?? String(maxSize));\n setPercentText(\"100\");\n }\n }, [sizeText, maxSize, position?.quantityRaw]);\n\n const handlePercentChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const cleaned = sanitiseAmountInput(e.target.value);\n const parsed = parseFloat(cleaned);\n if (Number.isFinite(parsed) && parsed > 100) {\n setPercentText(\"100\");\n if (maxSize > 0) {\n setSizeText(position?.quantityRaw ?? String(maxSize));\n }\n return;\n }\n setPercentText(cleaned);\n if (Number.isFinite(parsed) && maxSize > 0) {\n const clamped = Math.max(0, Math.min(100, parsed));\n const newSize = maxSize * (clamped / 100);\n setSizeText(newSize > 0 ? String(Number(newSize.toPrecision(6))) : \"0\");\n } else if (cleaned === \"\" || cleaned === \".\") {\n setSizeText(\"0\");\n }\n },\n [maxSize, position?.quantityRaw],\n );\n\n const handlePercentBlur = useCallback(() => {\n const parsed = parseFloat(percentText);\n if (!Number.isFinite(parsed) || parsed < 0) {\n setPercentText(\"0\");\n setSizeText(\"0\");\n } else if (parsed > 100) {\n setPercentText(\"100\");\n if (maxSize > 0) {\n setSizeText(position?.quantityRaw ?? String(maxSize));\n }\n }\n }, [percentText, maxSize, position?.quantityRaw]);\n\n const handleSliderChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const pct = Number(e.target.value);\n setPercentText(String(pct));\n if (maxSize > 0) {\n const newSize = maxSize * (pct / 100);\n setSizeText(\n pct === 100\n ? (position?.quantityRaw ?? String(maxSize))\n : newSize > 0\n ? String(Number(newSize.toPrecision(6)))\n : \"0\",\n );\n }\n },\n [maxSize, position?.quantityRaw],\n );\n\n const handlePriceChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n setPriceText(sanitiseAmountInput(e.target.value));\n },\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 // Submit\n const isLimitMode = closeType === \"limit\";\n const priceNumeric = parseFloat(priceText);\n const hasValidPrice =\n isLimitMode && Number.isFinite(priceNumeric) && priceNumeric > 0;\n const canSubmit =\n sizeNumeric > 0 && (!isLimitMode || hasValidPrice) && !isSubmitting;\n\n const handleSubmit = useCallback(async () => {\n if (!canSubmit) return;\n await onConfirm(sizeNumeric, isLimitMode ? priceNumeric : undefined);\n }, [canSubmit, onConfirm, sizeNumeric, isLimitMode, priceNumeric]);\n\n const guardedSubmit = useAuthCallback(handleSubmit);\n\n // Title\n const title = isLimitMode\n ? t(\"perpetuals.positions.close.limitTitle\", {\n side: sideLabel,\n size: maxSizeRaw,\n symbol: tokenSymbol,\n })\n : t(\"perpetuals.positions.close.marketTitle\", {\n side: sideLabel,\n size: maxSizeRaw,\n symbol: tokenSymbol,\n });\n\n const description = isLimitMode\n ? t(\"perpetuals.positions.close.limitDesc\")\n : t(\"perpetuals.positions.close.marketDesc\");\n\n const confirmLabel = isLimitMode\n ? t(\"perpetuals.positions.close.confirmLimit\")\n : t(\"perpetuals.positions.close.confirmMarket\");\n\n const currentPriceDisplay =\n position?.markPrice && position.markPrice > 0\n ? String(position.markPrice)\n : \"\";\n\n return (\n <StyledModal\n isOpen={isOpen}\n onOpenChange={(next) => {\n if (isSubmitting) 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 */}\n <div className=\"flex items-center justify-between px-5 pt-5 pb-2\">\n <h3 className=\"text-sm font-semibold text-white m-0\">{title}</h3>\n <button\n type=\"button\"\n onClick={onClose}\n disabled={isSubmitting}\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-1 flex flex-col gap-4\">\n {/* Description */}\n <p className=\"text-[13px] text-zinc-400 leading-[18px] m-0\">\n {description}\n </p>\n\n {/* Limit Price (only in limit mode) */}\n {isLimitMode && (\n <div className=\"flex flex-col gap-1\">\n <span style={{ fontSize: 12, color: \"#6b6b6b\" }}>\n {t(\"perpetuals.positions.close.price\")}\n </span>\n <input\n ref={priceRef}\n type=\"text\"\n inputMode=\"decimal\"\n pattern=\"[0-9.]*\"\n autoComplete=\"off\"\n autoCorrect=\"off\"\n spellCheck={false}\n placeholder={\n currentPriceDisplay\n ? t(\"perpetuals.positions.close.currentPrice\", {\n price: currentPriceDisplay,\n })\n : \"0.0\"\n }\n value={priceText}\n onChange={handlePriceChange}\n onKeyDownCapture={handleKeyDownCapture}\n className=\"w-full bg-transparent outline-none\"\n style={{\n color: \"#ffffff\",\n fontSize: 14,\n height: 40,\n padding: \"0 12px\",\n border: \"1px solid rgba(39,39,42,0.8)\",\n borderRadius: 8,\n fontVariantNumeric: \"tabular-nums\",\n }}\n />\n </div>\n )}\n\n {/* Size + Percentage row */}\n <div className=\"flex flex-col gap-1\">\n <div className=\"flex items-center justify-between\">\n <span style={{ fontSize: 12, color: \"#6b6b6b\" }}>\n {t(\"perpetuals.positions.close.size\")}\n </span>\n <span style={{ fontSize: 12, color: \"#6b6b6b\" }}>%</span>\n </div>\n <div className=\"flex items-center gap-2\">\n {/* Size input */}\n <div\n className=\"flex items-center flex-1\"\n style={{\n border: \"1px solid rgba(39,39,42,0.8)\",\n borderRadius: 8,\n height: 40,\n padding: \"0 12px\",\n }}\n >\n <input\n ref={sizeRef}\n type=\"text\"\n inputMode=\"decimal\"\n pattern=\"[0-9.]*\"\n autoComplete=\"off\"\n autoCorrect=\"off\"\n spellCheck={false}\n value={sizeText}\n onChange={handleSizeChange}\n onBlur={handleSizeBlur}\n onKeyDownCapture={handleKeyDownCapture}\n className=\"flex-1 min-w-0 bg-transparent border-none outline-none\"\n style={{\n color: \"#ffffff\",\n fontSize: 14,\n fontVariantNumeric: \"tabular-nums\",\n padding: 0,\n }}\n />\n <span\n style={{\n fontSize: 12,\n color: \"#6b6b6b\",\n marginLeft: 8,\n flexShrink: 0,\n }}\n >\n $\n </span>\n </div>\n\n {/* Percentage input */}\n <div\n className=\"flex items-center\"\n style={{\n border: \"1px solid rgba(39,39,42,0.8)\",\n borderRadius: 8,\n height: 40,\n padding: \"0 12px\",\n width: 80,\n }}\n >\n <input\n ref={percentRef}\n type=\"text\"\n inputMode=\"decimal\"\n pattern=\"[0-9.]*\"\n autoComplete=\"off\"\n autoCorrect=\"off\"\n spellCheck={false}\n value={percentText}\n onChange={handlePercentChange}\n onBlur={handlePercentBlur}\n onKeyDownCapture={handleKeyDownCapture}\n className=\"flex-1 min-w-0 bg-transparent border-none outline-none text-right\"\n style={{\n color: \"#ffffff\",\n fontSize: 14,\n fontVariantNumeric: \"tabular-nums\",\n padding: 0,\n }}\n />\n <span\n style={{\n fontSize: 12,\n color: \"#6b6b6b\",\n marginLeft: 4,\n flexShrink: 0,\n }}\n >\n %\n </span>\n </div>\n </div>\n\n {/* Max size label */}\n <span style={{ fontSize: 12, color: \"#6b6b6b\", marginTop: 2 }}>\n {t(\"perpetuals.positions.close.maxSize\", {\n size: maxSizeRaw,\n symbol: tokenSymbol,\n })}\n </span>\n </div>\n\n {/* Slider */}\n <div>\n <style>{`\n .perp-close-slider { -webkit-appearance: none; appearance: none; background: transparent; cursor: pointer; width: 100%; height: 16px; --pct: 0%; --fill: ${BRAND_PRIMARY}; --track: rgba(39,39,42,0.8); }\n .perp-close-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-close-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-close-slider::-moz-range-track { height: 4px; border-radius: 2px; background: rgba(39,39,42,0.8); border: none; }\n .perp-close-slider::-moz-range-progress { height: 4px; border-radius: 2px; background: ${BRAND_PRIMARY}; }\n .perp-close-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-close-slider:disabled { cursor: not-allowed; opacity: 0.5; }\n `}</style>\n <input\n type=\"range\"\n value={Math.round(sliderPercent)}\n onChange={handleSliderChange}\n min={0}\n max={100}\n step={1}\n disabled={maxSize <= 0}\n className=\"perp-close-slider\"\n style={\n {\n [\"--pct\" as never]: `${Math.round(sliderPercent)}%`,\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 {/* Confirm button */}\n <button\n type=\"button\"\n onClick={() => void guardedSubmit()}\n disabled={!canSubmit}\n className=\"w-full transition-colors disabled:cursor-not-allowed flex items-center justify-center gap-2\"\n style={{\n marginTop: 4,\n height: 44,\n fontSize: 14,\n fontWeight: 600,\n color: \"#000000\",\n backgroundColor: canSubmit\n ? BRAND_PRIMARY\n : \"rgba(63,63,70,0.6)\",\n borderRadius: 9999,\n border: \"none\",\n cursor: canSubmit ? \"pointer\" : \"not-allowed\",\n opacity: canSubmit ? 1 : 0.9,\n }}\n >\n {isSubmitting && <Spinner size=\"sm\" color=\"current\" />}\n {isSubmitting ? \"Closing...\" : confirmLabel}\n </button>\n </div>\n </div>\n </ModalContent>\n </StyledModal>\n );\n}\n","import { useCallback, useState } from \"react\";\nimport { useMutation } from \"@tanstack/react-query\";\nimport { useAssetMetaQuery } from \"../../hooks/useAssetMetaQuery\";\nimport type {\n OrderType,\n Position,\n PlaceOrderRequest,\n PlaceOrderResult,\n} from \"../../types\";\n\nexport type CloseType = \"market\" | \"limit\";\n\nexport type UseClosePositionParams = {\n userAddress?: string;\n onCloseSuccess?: () => void;\n onCloseError?: (error: Error) => void;\n /**\n * Callback that signs + relays the close order directly to the venue.\n * Same contract as the place-order form's `onPlaceOrder` — the host\n * hook (e.g. `useHyperliquidPlaceOrder`) receives a full\n * {@link PlaceOrderRequest} with `size`, `refPrice`, `szDecimals`\n * already computed.\n */\n onPlaceOrder?: (request: PlaceOrderRequest) => Promise<PlaceOrderResult>;\n};\n\nexport type UseClosePositionResult = {\n isModalOpen: boolean;\n selectedPosition: Position | null;\n closeType: CloseType;\n isClosing: boolean;\n openMarketClose: (position: Position) => void;\n openLimitClose: (position: Position) => void;\n handleConfirm: (size: number, price?: number) => Promise<void>;\n closeModal: () => void;\n};\n\n/**\n * Hook that owns the close-position modal lifecycle:\n * - Which position is selected and which close type (market / limit)\n * - Submitting the close order via `onPlaceOrder` (direct venue relay)\n *\n * The UI layer (modal component) owns the size / percentage / price\n * input state — this hook only cares about the final confirmed values.\n */\nexport function useClosePosition({\n userAddress,\n onCloseSuccess,\n onCloseError,\n onPlaceOrder,\n}: UseClosePositionParams): UseClosePositionResult {\n const [isModalOpen, setIsModalOpen] = useState(false);\n const [selectedPosition, setSelectedPosition] = useState<Position | null>(\n null,\n );\n const [closeType, setCloseType] = useState<CloseType>(\"market\");\n\n const { data: assetMeta } = useAssetMetaQuery({\n symbol: selectedPosition?.symbol,\n });\n\n const { mutateAsync: submitClose, isPending: isClosing } = 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 close order\",\n );\n }\n return await onPlaceOrder(request);\n },\n onSuccess: () => {\n setIsModalOpen(false);\n setSelectedPosition(null);\n onCloseSuccess?.();\n },\n onError: (err) => {\n onCloseError?.(err);\n },\n });\n\n const openMarketClose = useCallback((position: Position) => {\n setSelectedPosition(position);\n setCloseType(\"market\");\n setIsModalOpen(true);\n }, []);\n\n const openLimitClose = useCallback((position: Position) => {\n setSelectedPosition(position);\n setCloseType(\"limit\");\n setIsModalOpen(true);\n }, []);\n\n const closeModal = useCallback(() => {\n if (isClosing) return;\n setIsModalOpen(false);\n setSelectedPosition(null);\n }, [isClosing]);\n\n const handleConfirm = useCallback(\n async (size: number, price?: number) => {\n if (!selectedPosition || !userAddress) {\n throw new Error(\"Position and user address are required\");\n }\n\n const closeSide: \"long\" | \"short\" =\n selectedPosition.side === \"long\" ? \"short\" : \"long\";\n const orderType: OrderType = closeType === \"limit\" ? \"limit\" : \"market\";\n const refPrice =\n selectedPosition.markPrice || selectedPosition.entryPrice;\n\n const szDecimals = assetMeta?.szDecimals ?? 5;\n\n await submitClose({\n symbol: selectedPosition.symbol,\n side: closeSide,\n orderType,\n amount: size * refPrice,\n price: orderType === \"limit\" ? price : undefined,\n leverage: selectedPosition.leverage,\n reduceOnly: true,\n userAddress,\n size,\n refPrice,\n szDecimals,\n });\n },\n [selectedPosition, userAddress, closeType, assetMeta, submitClose],\n );\n\n return {\n isModalOpen,\n selectedPosition,\n closeType,\n isClosing,\n openMarketClose,\n openLimitClose,\n handleConfirm,\n closeModal,\n };\n}\n","import { useCallback, useMemo, useState } from \"react\";\nimport { usePositionsQuery } from \"../../hooks/usePositionsQuery\";\nimport type { Position } from \"../../types\";\nimport type { PositionSortKey, SortDirection } from \"./positions.ui\";\nimport {\n useClosePosition,\n type UseClosePositionParams,\n type UseClosePositionResult,\n} from \"./use-close-position\";\n\nexport type UsePositionsScriptParams = {\n userAddress?: string;\n symbol?: string;\n onCloseSuccess?: () => void;\n onCloseError?: (error: Error) => void;\n onPlaceOrder?: UseClosePositionParams[\"onPlaceOrder\"];\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 /** Close-position modal lifecycle (market + limit). */\n closePosition: UseClosePositionResult;\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 onPlaceOrder,\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 closePosition = useClosePosition({\n userAddress,\n onCloseSuccess,\n onCloseError,\n onPlaceOrder,\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 return {\n positions: sortedPositions,\n isLoading,\n error,\n sortKey,\n sortDir,\n onSort,\n closePosition,\n };\n}\n","import type { CSSProperties, ReactNode } from \"react\";\nimport { cn } from \"@liberfi.io/ui\";\n\n// ---------------------------------------------------------------------------\n// Sort primitives\n// ---------------------------------------------------------------------------\n\n/**\n * Two-state sort direction. We deliberately do not model a \"no sort\"\n * state: when a user clicks a fresh column the table starts at `asc`\n * (or `desc` if that's the column's natural default) and toggles\n * between `asc` ↔ `desc` thereafter — mirroring Axiom's UX so users\n * never have to click three times to clear an accidental sort.\n */\nexport type SortDirection = \"asc\" | \"desc\";\n\n/**\n * Horizontal alignment for a header cell label. `start` is the default\n * (matches the body cell alignment); `center` is used by columns whose\n * body uses a `1fr auto 1fr` grid (e.g. TP/SL) so the label sits above\n * the centre divider; `end` is for right-aligned action columns.\n */\nexport type HeaderAlign = \"start\" | \"center\" | \"end\";\n\nconst ALIGN_TO_JUSTIFY: Record<HeaderAlign, string> = {\n start: \"justify-start\",\n center: \"justify-center\",\n end: \"justify-end\",\n};\n\n// ---------------------------------------------------------------------------\n// Row layout constants\n// ---------------------------------------------------------------------------\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 */\nexport const HEADER_ROW_STYLE: CSSProperties = {\n minHeight: 28,\n maxHeight: 28,\n};\n\n/**\n * Body row: 36px tall, fixed. Same rationale as\n * {@link HEADER_ROW_STYLE} — clamps via `min-height` / `max-height`\n * so flex-grow can't compress it.\n */\nexport const BODY_ROW_STYLE: CSSProperties = { minHeight: 36, maxHeight: 36 };\n\n/**\n * Zebra-stripe background for odd body rows (Positions / Open Orders /\n * Trade History), applied via inline `style` rather than a Tailwind\n * utility because:\n *\n * - Container backgrounds in this SDK's host pages are pure `#000000`\n * (e.g. PerpetualsPage's `<div style={{ backgroundColor: '#000' }}>`).\n * A `bg-default-100/30` token resolves to roughly `oklab(0.20 / 0.3)`,\n * which on `#000` blends back into near-black — the stripe looks\n * missing. We need a colour that's *visibly distinct from `#000`*,\n * not visibly distinct from the consumer's theme palette mid-grey.\n *\n * - White at 6 % opacity matches the \"table stripe\" treatment used by\n * OrderBook / market-trades hover (`hover:bg-white/5`), so the three\n * tables and the live streams agree on the visual language. We pick\n * 6 % rather than 4 % because Axiom's reference (`bg-primaryStroke/20`\n * ≈ rgba(34,36,45,0.2)) sits on their `rgb(6,7,11)` non-black wrapper\n * and produces only a ~3 % luminance step; on our `#000000` wrapper\n * a 4 % white needs another bump to read just as clearly to the eye.\n *\n * - Inline style sidesteps any Tailwind v4 + `USE_LOCAL_SDK=true`\n * class-purge edge cases when the consumer's `@source` glob doesn't\n * reach the SDK source. The other layout constants in this file\n * follow the same convention for the same reason.\n */\nexport const STRIPE_BG_STYLE: CSSProperties = {\n backgroundColor: \"rgba(255, 255, 255, 0.06)\",\n};\n\n// ---------------------------------------------------------------------------\n// Format helpers — shared across tables (positions, open orders, …)\n// ---------------------------------------------------------------------------\n\n/**\n * Adaptive USD price formatter — mirrors Axiom's per-magnitude\n * rounding so a $80,564 BTC mark and a $0.0007 memecoin mark both\n * render at a useful precision without over- or under-reporting.\n *\n * ≥ 10000 → 0 fraction digits + thousands separator (e.g. `$80,564`)\n * ≥ 1000 → 1 fraction digit + thousands separator (e.g. `$2,301.5`)\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 *\n * The 1000–10000 band gets 1 dp (instead of falling to 0 dp like the\n * 10k+ band) because mid-price assets such as ETH at $2,301.5 lose\n * meaningful precision at integer rounding — verified against Axiom's\n * Trade History column, which renders ETH fills as `$2,301.5`,\n * `$2,325.9`, etc.\n */\nexport function 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 >= 10000) dp = 0;\n else if (abs >= 1000) dp = 1;\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. */\nexport function 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 *\n * Round-to-zero special case: when `|n| < 0.005` (rounds to 0 at 2 dp)\n * the function returns `+$0` instead of `+$0.00` / `-$0.00`. Mirrors\n * Axiom's PnL column, where a closing fill that nets out near-zero\n * after fees shows as `+$0` rather than a misleading `-$0.00`.\n */\nexport function formatSignedUsd2(n: number): string {\n if (!Number.isFinite(n)) return \"--\";\n if (Math.abs(n) < 0.005) return \"+$0\";\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 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 */\nexport function formatPercentAbs(percent: number): string {\n if (!Number.isFinite(percent)) return \"--\";\n return Math.abs(percent).toFixed(2) + \"%\";\n}\n\n/**\n * Quantity / size string. Prefer the venue-supplied raw quantity to\n * preserve the exact precision (e.g. Hyperliquid's `pos.szi` may\n * carry trailing zeros that `parseFloat → toFixed` would erase).\n * Fall back to the parsed number with sensible defaults when the raw\n * is missing.\n */\nexport function 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 * Format a millisecond timestamp as `YYYY/M/D HH:mm:ss` (24h, locale\n * separator). Matches Axiom's open-orders Time column.\n *\n * Uses the user's local timezone by design — the visual cue beside an\n * order is always \"what wall-clock time did I place this\", not UTC.\n */\nexport function formatDateTime(timestamp: number | undefined): string {\n if (timestamp === undefined || !Number.isFinite(timestamp)) return \"--\";\n const d = new Date(timestamp);\n if (Number.isNaN(d.getTime())) return \"--\";\n const yyyy = d.getFullYear();\n const M = d.getMonth() + 1;\n const D = d.getDate();\n const hh = String(d.getHours()).padStart(2, \"0\");\n const mm = String(d.getMinutes()).padStart(2, \"0\");\n const ss = String(d.getSeconds()).padStart(2, \"0\");\n return `${yyyy}/${M}/${D} ${hh}:${mm}:${ss}`;\n}\n\n// ---------------------------------------------------------------------------\n// Header cell — generic over the sort-key type\n// ---------------------------------------------------------------------------\n\n/**\n * Props for {@link HeaderCell}. The `K` generic is the table's\n * sort-key string union, so each table can use its own typed keys\n * (`PositionSortKey`, `OpenOrderSortKey`, …) without colliding.\n */\nexport type HeaderCellProps<K extends string> = {\n /** Inline `style` carrying the column's flex / max-width rules. */\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?: K;\n activeSortKey?: K | null;\n sortDir?: SortDirection;\n onSort?: (key: K) => void;\n /** Horizontal alignment of the label. Defaults to `\"start\"`. */\n align?: HeaderAlign;\n};\n\n/**\n * One header cell.\n *\n * Sortable cells get `cursor-pointer` + a hover white tint, an\n * `↑`/`↓` glyph appended when active, and an accessible `<button>`\n * semantic so keyboard users can sort with Enter / Space.\n *\n * Static (non-sortable) cells render a plain `<div>` to keep the\n * accessibility tree clean.\n */\nexport function HeaderCell<K extends string>({\n style,\n children,\n sortKey,\n activeSortKey,\n sortDir,\n onSort,\n align = \"start\",\n}: HeaderCellProps<K>) {\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","import type { CSSProperties } from \"react\";\nimport { useTranslation } from \"@liberfi.io/i18n\";\nimport { cn, StyledTooltip } from \"@liberfi.io/ui\";\nimport type { Position } from \"../../types\";\nimport {\n BODY_ROW_STYLE,\n HEADER_ROW_STYLE,\n HeaderCell,\n STRIPE_BG_STYLE,\n formatPercentAbs,\n formatQuantity,\n formatSignedUsd2,\n formatUsd2,\n formatUsdPrice,\n type SortDirection,\n} from \"../_internal/table\";\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 };\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// 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 onMarketClose: (position: Position) => void;\n onLimitClose: (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 onMarketClose,\n onLimitClose,\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 onMarketClose={onMarketClose}\n onLimitClose={onLimitClose}\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 onMarketClose: (position: Position) => void;\n onLimitClose: (position: Position) => void;\n};\n\nfunction PositionRow({\n position,\n striped,\n isClosing,\n onMarketClose,\n onLimitClose,\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 style={striped ? STRIPE_BG_STYLE : undefined}>\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 — Market / Limit text links, each opens a confirm modal. */}\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={() => onMarketClose(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 <button\n type=\"button\"\n onClick={() => onLimitClose(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.limit\")}\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 { ClosePositionModal } from \"./close-position-modal.ui\";\nimport { usePositionsScript } from \"./positions.script\";\nimport { PositionsUI, PositionsSkeleton } from \"./positions.ui\";\nimport type { UseClosePositionParams } from \"./use-close-position\";\n\nexport type PositionsWidgetProps = {\n userAddress?: string;\n symbol?: string;\n onCloseSuccess?: () => void;\n onCloseError?: (error: Error) => void;\n onPlaceOrder?: UseClosePositionParams[\"onPlaceOrder\"];\n className?: string;\n};\n\n/**\n * Positions table widget. Owns no business logic — wires the\n * `usePositionsScript` data layer (sort + close-modal) to the\n * presentational `PositionsUI` and the `ClosePositionModal`. The host\n * page just provides the connected wallet address and (optionally) a\n * symbol filter; the widget handles everything else.\n */\nexport function PositionsWidget({\n userAddress,\n symbol,\n onCloseSuccess,\n onCloseError,\n onPlaceOrder,\n className,\n}: PositionsWidgetProps) {\n const { positions, isLoading, sortKey, sortDir, onSort, closePosition } =\n usePositionsScript({\n userAddress,\n symbol,\n onCloseSuccess,\n onCloseError,\n onPlaceOrder,\n });\n\n if (isLoading) {\n return (\n <div className={className}>\n <PositionsSkeleton />\n </div>\n );\n }\n\n return (\n <>\n <PositionsUI\n positions={positions}\n sortKey={sortKey}\n sortDir={sortDir}\n onSort={onSort}\n onMarketClose={closePosition.openMarketClose}\n onLimitClose={closePosition.openLimitClose}\n isClosing={closePosition.isClosing}\n className={className}\n />\n <ClosePositionModal\n isOpen={closePosition.isModalOpen}\n position={closePosition.selectedPosition}\n closeType={closePosition.closeType}\n isSubmitting={closePosition.isClosing}\n onClose={closePosition.closeModal}\n onConfirm={closePosition.handleConfirm}\n />\n </>\n );\n}\n","import { useCallback, useMemo, useRef, useState } from \"react\";\nimport { useCancelOrderMutation } from \"../../hooks/useCancelOrderMutation\";\nimport { useOrdersQuery } from \"../../hooks/useOrdersQuery\";\nimport type { CancelOrderParams, CancelOrderResult, Order } from \"../../types\";\nimport type { OpenOrderSortKey, SortDirection } from \"./open-orders.ui\";\n\n/**\n * Caller-provided cancel implementation for a single order. Mirrors\n * the `onPlaceOrder` IoC point on the place-order form: when supplied,\n * the script / widget delegates the actual signing + submit to the\n * host instead of routing through the active\n * `IPerpetualsClient.cancelOrder`.\n *\n * Hosts that talk directly to a venue from the browser (e.g. signing\n * Hyperliquid `cancel` actions with the user's wallet) inject this\n * to bypass the SDK's read-only `HyperliquidPerpetualsClient.cancelOrder`\n * stub. Hosts that proxy through perpetuals-server (LiberFi TEE) leave\n * it undefined and let the default path run.\n */\nexport type CancelOrderImpl = (\n params: CancelOrderParams,\n) => Promise<CancelOrderResult>;\n\n/**\n * Optional batch counterpart to {@link CancelOrderImpl}. When supplied,\n * `handleCancelAll` invokes this once with every leg, so direct-venue\n * hosts (Hyperliquid, Lighter, etc.) can issue a single signature\n * covering all cancels rather than prompting the user N times.\n *\n * When omitted, the script falls back to\n * `Promise.allSettled(orders.map(cancelOrder))` — correct behaviour\n * for backends like perpetuals-server that own the signature flow\n * (each leg is a no-op API call), but a UX trap when the host signs\n * locally because every leg will trigger a fresh wallet prompt.\n */\nexport type CancelOrdersImpl = (\n params: CancelOrderParams[],\n) => Promise<CancelOrderResult[]>;\n\nexport type UseOpenOrdersScriptParams = {\n userAddress?: string;\n symbol?: string;\n onCancelSuccess?: () => void;\n onCancelError?: (error: Error) => void;\n /**\n * Optional host-provided single-order cancel implementation. When\n * omitted, the script falls back to {@link useCancelOrderMutation}\n * which routes through the active client — appropriate for backends\n * that own the signature flow (e.g. LiberFi perpetuals-server). For\n * direct-venue setups (consumer holds the wallet keys), pass an\n * implementation that signs + relays the cancel itself.\n */\n cancelOrder?: CancelOrderImpl;\n /**\n * Optional host-provided batch cancel implementation. When supplied\n * it is used by `handleCancelAll` (and by single cancels too —\n * the script wraps the param into a 1-element array so the host\n * can keep one entry point). When omitted, batch cancels fan out to\n * the per-order path with `Promise.allSettled`.\n */\n cancelOrders?: CancelOrdersImpl;\n};\n\nexport type UseOpenOrdersScriptResult = {\n /** Orders already sorted by the active `sortKey` / `sortDir`. */\n orders: Order[];\n isLoading: boolean;\n error: Error | null;\n /** Active sort column. Default: `time` desc — newest first, like Axiom. */\n sortKey: OpenOrderSortKey | null;\n sortDir: SortDirection;\n /**\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 */\n onSort: (key: OpenOrderSortKey) => void;\n /** Cancel a single order by id. */\n handleCancelOrder: (order: Order) => Promise<void>;\n /**\n * Cancel every currently-loaded order. Resolves once every leg has\n * finished (success **or** failure — leg failures are reported via\n * `onCancelError` per-leg, but do not abort the batch). The widget's\n * confirmation dialog calls this only after the user explicitly\n * confirms — the script does not gate on a dialog itself.\n */\n handleCancelAll: () => Promise<void>;\n /**\n * `true` while *any* cancel mutation (single OR batch) is in flight.\n * Kept for backwards-compatibility with hosts that only need the\n * coarse-grained \"is anything cancelling?\" signal. New UI surfaces\n * (per-row spinners, header `Cancel All` spinner) should prefer\n * the more specific signals below — this flag is intentionally\n * **not** the recommended way to drive a row's spinner because it\n * would light up every row whenever any row is cancelling.\n */\n isCanceling: boolean;\n /**\n * Set of order ids currently being cancelled via the per-row path.\n * The UI uses this to render an inline spinner on the exact row(s)\n * the user clicked while leaving sibling rows untouched — clicks\n * on different rows can run concurrently, so a single boolean\n * would conflate them.\n *\n * Returned as a `ReadonlySet` so consumers can't accidentally\n * mutate the script's internal state. `Set` (not `Array`) keeps\n * `has(orderId)` O(1) for the row-render hot path.\n */\n cancelingOrderIds: ReadonlySet<string>;\n /**\n * `true` while a `Cancel All` batch is in flight (regardless of\n * whether the host injected a batch impl or we fanned out to\n * per-leg cancels). The UI uses this to swap the header's\n * `Cancel All` text for a spinner so the user gets feedback the\n * click was registered. Distinct from `cancelingOrderIds` so the\n * header spinner doesn't fire when only a single per-row cancel\n * is running, and vice versa.\n */\n isCancelingAll: boolean;\n};\n\n// ---------------------------------------------------------------------------\n// Sort helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Map a sort key to the comparable scalar for a given order. Returns\n * `null` for missing values so the comparator can rank them last\n * regardless of direction (the standard \"missing data goes to the\n * bottom\" UX convention).\n */\nfunction getSortValue(\n order: Order,\n key: OpenOrderSortKey,\n): number | string | null {\n switch (key) {\n case \"time\":\n return order.timestamp;\n case \"size\":\n return order.quantity;\n case \"asset\":\n return order.symbol.split(\"-\")[0];\n case \"direction\":\n // Sort `Long` before `Short` in `asc` (alpha), `Short` before\n // `Long` in `desc` — matches Axiom's behaviour where the\n // direction column is a string sort, not a \"buy intent first\"\n // semantic sort.\n return order.side;\n case \"type\":\n // Sort by the binary axis (limit/market) since the SDK collapses\n // trigger info there. Trigger orders thus group with their base\n // type, which is consistent with how the column displays.\n return order.orderType;\n case \"leverage\":\n return order.leverage ?? null;\n case \"orderValue\":\n // Trigger orders show `Market` (no notional value) — sort them\n // last regardless of direction by returning `null`. Same\n // convention as `liquidationPrice` in Positions.\n return order.isTrigger ? null : order.price * order.quantity;\n case \"executePrice\":\n return order.isTrigger ? null : order.price;\n case \"currentPrice\":\n return order.markPrice ?? null;\n }\n}\n\nfunction compareOrders(\n a: Order,\n b: Order,\n key: OpenOrderSortKey,\n dir: SortDirection,\n): number {\n const aVal = getSortValue(a, key);\n const bVal = getSortValue(b, key);\n\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 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 Open Orders table.\n *\n * Responsibilities:\n * - Read open orders via {@link useOrdersQuery}. The consumer's\n * `useAccountStateSubscription` keeps the cache live via the\n * `webData2` write-through path, which already enriches each\n * order with leverage / mark-price / bundled TP/SL — so we\n * deliberately do **not** subscribe to a per-order user-data\n * stream here. Doing so would clobber that enrichment.\n * - Own sort state (default `time ↓` — newest order first).\n * - Expose `handleCancelOrder` (single) and `handleCancelAll`\n * (batch) shims over `useCancelOrderMutation`.\n *\n * Cancel-all does not present a confirmation prompt itself — that\n * responsibility lives in the widget, which renders the dialog and\n * only calls `handleCancelAll()` after the user confirms. Keeping the\n * confirmation in the widget makes the script trivially testable\n * (deterministic mutation calls) and lets headless consumers skip the\n * dialog entirely.\n */\nexport function useOpenOrdersScript({\n userAddress,\n symbol,\n onCancelSuccess,\n onCancelError,\n cancelOrder: cancelOrderImpl,\n cancelOrders: cancelOrdersImpl,\n}: UseOpenOrdersScriptParams): UseOpenOrdersScriptResult {\n // Default sort: `Time ↓` — most recent order at the top.\n const [sortKey, setSortKey] = useState<OpenOrderSortKey | null>(\"time\");\n const [sortDir, setSortDir] = useState<SortDirection>(\"desc\");\n\n const onSort = useCallback((key: OpenOrderSortKey) => {\n setSortKey((currentKey) => {\n if (currentKey === key) {\n setSortDir((d) => (d === \"asc\" ? \"desc\" : \"asc\"));\n return currentKey;\n }\n setSortDir(\"asc\");\n return key;\n });\n }, []);\n\n const {\n data: ordersData,\n isLoading,\n error,\n } = useOrdersQuery({ userAddress, symbol }, { enabled: !!userAddress });\n\n // Track in-flight cancels at row granularity so per-row spinners\n // light up exactly on the row(s) the user clicked, not on every\n // row in the table. Concurrency is intentional — clicking cancel\n // on three rows in quick succession should fire three independent\n // requests, each with its own spinner.\n //\n // We expose a `Set` to consumers (O(1) `has(orderId)` for row\n // render). Internally we hold it in a ref so per-row updates\n // don't have to spread the previous `Set` on every change, then\n // bump a version counter to trigger React renders. This keeps\n // hot-path mutations cheap while preserving the immutable-snapshot\n // contract on the public API.\n const cancelingIdsRef = useRef<Set<string>>(new Set<string>());\n const [, setIdsVersion] = useState(0);\n const bumpIdsVersion = useCallback(() => setIdsVersion((v) => v + 1), []);\n const addCancelingId = useCallback(\n (id: string) => {\n cancelingIdsRef.current.add(id);\n bumpIdsVersion();\n },\n [bumpIdsVersion],\n );\n const removeCancelingId = useCallback(\n (id: string) => {\n cancelingIdsRef.current.delete(id);\n bumpIdsVersion();\n },\n [bumpIdsVersion],\n );\n\n // `Cancel All` runs as a single conceptual action even when it\n // fans out into per-leg cancels under the hood, so it gets its\n // own boolean. Drives the header button's spinner separately\n // from the per-row set above.\n const [batchPending, setBatchPending] = useState(false);\n\n // Default fallback mutation — used when the host does not inject\n // a `cancelOrder` impl. Routes through the active client, so\n // `LiberFiPerpetualsClient` (perpetuals-server proxy) works\n // out of the box; `HyperliquidPerpetualsClient` does not (its\n // cancel is a deliberate stub — host must inject to use it).\n const { mutateAsync: cancelOrderMutate, isPending: isFallbackPending } =\n useCancelOrderMutation({\n onSuccess: () => {\n onCancelSuccess?.();\n },\n onError: (err) => {\n onCancelError?.(err);\n },\n });\n\n // Single-order dispatcher. Preference order:\n // 1. Host-injected `cancelOrder` (per-leg impl)\n // 2. Host-injected `cancelOrders` of size 1 (batch impl reused —\n // lets hosts ship a single batch hook and have it cover both\n // paths without writing a single-order variant separately)\n // 3. Fallback to `useCancelOrderMutation` against the active client\n // Success/error callbacks are wired here for the injected paths\n // (the mutation hook owns them on the fallback path).\n const dispatchCancel = useCallback(\n async (params: CancelOrderParams): Promise<CancelOrderResult> => {\n if (cancelOrderImpl) {\n try {\n const result = await cancelOrderImpl(params);\n onCancelSuccess?.();\n return result;\n } catch (err) {\n onCancelError?.(err instanceof Error ? err : new Error(String(err)));\n throw err;\n }\n }\n if (cancelOrdersImpl) {\n try {\n const [result] = await cancelOrdersImpl([params]);\n if (!result) {\n throw new Error(\"cancelOrders returned no result\");\n }\n onCancelSuccess?.();\n return result;\n } catch (err) {\n onCancelError?.(err instanceof Error ? err : new Error(String(err)));\n throw err;\n }\n }\n return cancelOrderMutate(params);\n },\n [\n cancelOrderImpl,\n cancelOrdersImpl,\n cancelOrderMutate,\n onCancelSuccess,\n onCancelError,\n ],\n );\n\n const orders = useMemo(() => ordersData?.orders ?? [], [ordersData]);\n\n const sortedOrders = useMemo(() => {\n if (!sortKey) return orders;\n return [...orders].sort((a, b) => compareOrders(a, b, sortKey, sortDir));\n }, [orders, sortKey, sortDir]);\n\n const handleCancelOrder = useCallback(\n async (order: Order) => {\n if (!userAddress) {\n throw new Error(\"User address is required\");\n }\n addCancelingId(order.orderId);\n try {\n await dispatchCancel({\n orderId: order.orderId,\n symbol: order.symbol,\n userAddress,\n });\n } finally {\n // Remove regardless of outcome — error toasts surface\n // through `onCancelError`, the spinner doesn't need to\n // linger as a failure indicator.\n removeCancelingId(order.orderId);\n }\n },\n [userAddress, dispatchCancel, addCancelingId, removeCancelingId],\n );\n\n const handleCancelAll = useCallback(async () => {\n if (!userAddress) {\n throw new Error(\"User address is required\");\n }\n if (orders.length === 0) return;\n\n setBatchPending(true);\n try {\n const params = orders.map((o) => ({\n orderId: o.orderId,\n symbol: o.symbol,\n userAddress,\n }));\n\n // Prefer the batch impl when supplied — direct-venue hosts can\n // sign all legs in a single wallet prompt that way. The result\n // array index-matches `params`, so we still emit per-leg\n // success / error callbacks for the embedding UI.\n if (cancelOrdersImpl) {\n try {\n await cancelOrdersImpl(params);\n for (let i = 0; i < params.length; i++) onCancelSuccess?.();\n } catch (err) {\n // Whole-batch reject: surface once via onCancelError so\n // the host can toast a single failure instead of N noisy\n // duplicates.\n onCancelError?.(err instanceof Error ? err : new Error(String(err)));\n }\n return;\n }\n\n // Fallback: fan out to the per-order path. `Promise.allSettled`\n // (not `all`) so one rejected leg doesn't abort the rest;\n // per-leg outcomes are already reported through\n // `dispatchCancel`'s success / error callbacks.\n await Promise.allSettled(params.map((p) => dispatchCancel(p)));\n } finally {\n setBatchPending(false);\n }\n }, [\n userAddress,\n orders,\n cancelOrdersImpl,\n dispatchCancel,\n onCancelSuccess,\n onCancelError,\n ]);\n\n // Coarse \"anything cancelling?\" signal — kept for backwards\n // compat with hosts already wired to it. Internally we now have\n // finer-grained signals (`cancelingOrderIds` for rows, `batchPending`\n // for header) which the bundled UI prefers. ORs every source\n // together so neither path leaves the flag stuck.\n const isCanceling =\n cancelingIdsRef.current.size > 0 || batchPending || isFallbackPending;\n\n return {\n orders: sortedOrders,\n isLoading,\n error,\n sortKey,\n sortDir,\n onSort,\n handleCancelOrder,\n handleCancelAll,\n isCanceling,\n cancelingOrderIds: cancelingIdsRef.current,\n isCancelingAll: batchPending,\n };\n}\n","import type { CSSProperties } from \"react\";\nimport { useTranslation } from \"@liberfi.io/i18n\";\nimport { cn, Spinner, StyledTooltip } from \"@liberfi.io/ui\";\nimport type { Order } from \"../../types\";\nimport {\n BODY_ROW_STYLE,\n HEADER_ROW_STYLE,\n HeaderCell,\n STRIPE_BG_STYLE,\n formatDateTime,\n formatQuantity,\n formatUsd2,\n formatUsdPrice,\n type SortDirection,\n} from \"../_internal/table\";\n\n// ---------------------------------------------------------------------------\n// Sort\n// ---------------------------------------------------------------------------\n\n/**\n * Stable identifier for a sortable column. 9 of the 12 columns are\n * sortable; `triggerCondition`, `tpsl`, `cancel` 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 OpenOrderSortKey =\n | \"time\"\n | \"size\"\n | \"asset\"\n | \"direction\"\n | \"type\"\n | \"leverage\"\n | \"orderValue\"\n | \"executePrice\"\n | \"currentPrice\";\n\nexport type { SortDirection };\n\n// ---------------------------------------------------------------------------\n// Column layout\n// ---------------------------------------------------------------------------\n\n/**\n * Per-column inline styles. Mirrors Axiom's open-orders layout 1:1:\n * - 9 columns are clamped via `maxWidth` while still flex-growing\n * until they hit that cap (Axiom's `max-w-[Npx]` + `flex-1`).\n * - `triggerCondition` has **no `maxWidth`** so it absorbs leftover\n * row space when the panel is wider than the sum of fixed columns.\n *\n * Why inline (not Tailwind arbitrary classes): the same SDK-self-\n * containment reasoning as positions.ui — `USE_LOCAL_SDK=true` mode\n * skips the consumer's `node_modules` `@source` glob, dropping any\n * arbitrary-value classes emitted from the local source files.\n * Inline `style` always works.\n */\nconst COL_STYLE: Record<string, CSSProperties> = {\n time: { flex: \"1 1 0%\", maxWidth: 160 },\n size: { flex: \"1 1 0%\", maxWidth: 80 },\n asset: { flex: \"1 1 0%\", maxWidth: 70 },\n direction: { flex: \"1 1 0%\", maxWidth: 70 },\n type: { flex: \"1 1 0%\", maxWidth: 160 },\n leverage: { flex: \"1 1 0%\", maxWidth: 80 },\n orderValue: { flex: \"1 1 0%\", maxWidth: 100 },\n executePrice: { flex: \"1 1 0%\", maxWidth: 100 },\n currentPrice: { flex: \"1 1 0%\", maxWidth: 100 },\n triggerCondition: { flex: \"1 1 0%\" },\n tpsl: { flex: \"1 1 0%\", maxWidth: 120 },\n cancel: { flex: \"1 1 0%\", maxWidth: 70 },\n};\n\n/**\n * Min-width of the inner table body. Axiom uses 1100 — slightly less\n * than the sum of fixed column widths (1110px) so on a tight viewport\n * the `triggerCondition` column compresses first instead of forcing\n * horizontal scroll. Same effect for us.\n */\nconst TABLE_MIN_WIDTH: CSSProperties = { minWidth: 1100 };\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Reconstruct the venue's full order-type label from an {@link Order}.\n * The SDK collapses Hyperliquid's strings to the binary `limit | market`\n * axis to keep the type narrow, but the Open Orders table needs the\n * full \"Take Profit Market\" / \"Stop Limit\" / etc. text. The combination\n * of `isTrigger` + `triggerType` + `orderType` reproduces all six\n * variants Hyperliquid emits.\n */\nfunction describeOrderType(order: Order, market: string): string {\n const isLimit = order.orderType === \"limit\";\n if (!order.isTrigger) {\n return isLimit ? \"Limit\" : market;\n }\n if (order.triggerType === \"tp\") {\n return isLimit ? \"Take Profit Limit\" : \"Take Profit Market\";\n }\n if (order.triggerType === \"sl\") {\n return isLimit ? \"Stop Limit\" : \"Stop Market\";\n }\n // Trigger order with no explicit type discriminator: fall back to\n // the base limit/market label so the column never reads blank.\n return isLimit ? \"Limit\" : market;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\nexport type OpenOrdersUIProps = {\n /** Already-sorted orders. The script layer owns sort state. */\n orders: Order[];\n /** Currently active sort column, or `null` when no sort applied. */\n sortKey: OpenOrderSortKey | null;\n sortDir: SortDirection;\n onSort: (key: OpenOrderSortKey) => void;\n onCancelOrder: (order: Order) => void;\n onCancelAll: () => void;\n /**\n * Set of order ids currently being cancelled via the per-row path.\n * The row whose id is present in the set renders an inline spinner\n * in place of its `x` icon; sibling rows stay clickable so the\n * user can cancel several orders concurrently.\n */\n cancelingOrderIds: ReadonlySet<string>;\n /**\n * `true` while a `Cancel All` batch is in flight. Drives the\n * header button's spinner and gates *every* row's cancel button\n * (mid-batch, individual rows shouldn't accept new clicks).\n */\n isCancelingAll: boolean;\n /** Optional className for the outer container. */\n className?: string;\n};\n\nexport function OpenOrdersUI({\n orders,\n sortKey,\n sortDir,\n onSort,\n onCancelOrder,\n onCancelAll,\n cancelingOrderIds,\n isCancelingAll,\n className,\n}: OpenOrdersUIProps) {\n const { t } = useTranslation();\n const marketLabel = t(\"perpetuals.openOrders.market\");\n\n // Header is always rendered (even when empty) so the column legend\n // is visible while waiting for the first order. 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<OpenOrderSortKey>\n style={COL_STYLE.time}\n sortKey=\"time\"\n activeSortKey={sortKey}\n sortDir={sortDir}\n onSort={onSort}\n >\n {t(\"perpetuals.openOrders.col.time\")}\n </HeaderCell>\n <HeaderCell<OpenOrderSortKey>\n style={COL_STYLE.size}\n sortKey=\"size\"\n activeSortKey={sortKey}\n sortDir={sortDir}\n onSort={onSort}\n >\n {t(\"perpetuals.openOrders.col.size\")}\n </HeaderCell>\n <HeaderCell<OpenOrderSortKey>\n style={COL_STYLE.asset}\n sortKey=\"asset\"\n activeSortKey={sortKey}\n sortDir={sortDir}\n onSort={onSort}\n >\n {t(\"perpetuals.openOrders.col.asset\")}\n </HeaderCell>\n <HeaderCell<OpenOrderSortKey>\n style={COL_STYLE.direction}\n sortKey=\"direction\"\n activeSortKey={sortKey}\n sortDir={sortDir}\n onSort={onSort}\n >\n {t(\"perpetuals.openOrders.col.direction\")}\n </HeaderCell>\n <HeaderCell<OpenOrderSortKey>\n style={COL_STYLE.type}\n sortKey=\"type\"\n activeSortKey={sortKey}\n sortDir={sortDir}\n onSort={onSort}\n >\n {t(\"perpetuals.openOrders.col.type\")}\n </HeaderCell>\n <HeaderCell<OpenOrderSortKey>\n style={COL_STYLE.leverage}\n sortKey=\"leverage\"\n activeSortKey={sortKey}\n sortDir={sortDir}\n onSort={onSort}\n >\n <StyledTooltip\n content={t(\"perpetuals.openOrders.tooltip.leverage\")}\n placement=\"top\"\n delay={200}\n closeDelay={0}\n >\n <span className=\"border-b border-dashed border-default-500/40\">\n {t(\"perpetuals.openOrders.col.leverage\")}\n </span>\n </StyledTooltip>\n </HeaderCell>\n <HeaderCell<OpenOrderSortKey>\n style={COL_STYLE.orderValue}\n sortKey=\"orderValue\"\n activeSortKey={sortKey}\n sortDir={sortDir}\n onSort={onSort}\n >\n {t(\"perpetuals.openOrders.col.orderValue\")}\n </HeaderCell>\n <HeaderCell<OpenOrderSortKey>\n style={COL_STYLE.executePrice}\n sortKey=\"executePrice\"\n activeSortKey={sortKey}\n sortDir={sortDir}\n onSort={onSort}\n >\n {t(\"perpetuals.openOrders.col.executePrice\")}\n </HeaderCell>\n <HeaderCell<OpenOrderSortKey>\n style={COL_STYLE.currentPrice}\n sortKey=\"currentPrice\"\n activeSortKey={sortKey}\n sortDir={sortDir}\n onSort={onSort}\n >\n {t(\"perpetuals.openOrders.col.currentPrice\")}\n </HeaderCell>\n <HeaderCell<OpenOrderSortKey> style={COL_STYLE.triggerCondition}>\n {t(\"perpetuals.openOrders.col.triggerCondition\")}\n </HeaderCell>\n <HeaderCell<OpenOrderSortKey> style={COL_STYLE.tpsl} align=\"center\">\n {t(\"perpetuals.openOrders.col.tpsl\")}\n </HeaderCell>\n <div\n style={COL_STYLE.cancel}\n className=\"flex flex-row items-center justify-center\"\n >\n {/* `Cancel All` header trigger.\n - Strips the default browser focus ring and HeroUI's\n focus-visible outline so the button reads as a plain\n text link (matches Axiom). Tabbable users still see\n the underline shift via `hover:text-bearish/80`.\n - Spinner replaces the label while the batch is in flight\n (we keep the column width fixed via `min-w-[60px]` so\n the surrounding header doesn't reflow when the label\n swaps).\n - Disabled while the batch is running OR when there are\n no orders to cancel. We intentionally don't disable\n on per-row cancels — the user should still be able to\n kick off a `Cancel All` while an individual cancel is\n pending. */}\n <button\n type=\"button\"\n onClick={onCancelAll}\n disabled={isCancelingAll || orders.length === 0}\n className={cn(\n \"inline-flex min-w-[60px] items-center justify-center gap-1\",\n \"text-xs font-medium text-bearish\",\n \"cursor-pointer transition-colors duration-150\",\n \"hover:text-bearish/80 disabled:cursor-not-allowed disabled:opacity-50\",\n \"outline-none focus:outline-none focus-visible:outline-none\",\n \"focus:ring-0 focus-visible:ring-0\",\n )}\n >\n {isCancelingAll ? (\n <Spinner size=\"sm\" color=\"current\" />\n ) : (\n t(\"perpetuals.openOrders.col.cancelAll\")\n )}\n </button>\n </div>\n </div>\n );\n\n // Empty state: keep the header for layout context, render a centred\n // \"no orders\" line below.\n if (orders.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.openOrders.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 {orders.map((order, index) => (\n <OrderRow\n key={order.orderId}\n order={order}\n striped={index % 2 === 1}\n isThisRowCanceling={cancelingOrderIds.has(order.orderId)}\n isBatchCanceling={isCancelingAll}\n marketLabel={marketLabel}\n onCancel={onCancelOrder}\n />\n ))}\n </div>\n </div>\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Row\n// ---------------------------------------------------------------------------\n\ntype OrderRowProps = {\n order: Order;\n /** Zebra striping — every other row gets a faint background. */\n striped: boolean;\n /**\n * `true` while this *specific* row's per-row cancel is in flight.\n * Triggers the inline spinner that replaces the row's `x` glyph\n * and disables the row's button.\n */\n isThisRowCanceling: boolean;\n /**\n * `true` while a `Cancel All` batch is running. Disables the\n * row's cancel button (so individual rows don't fire a second\n * request mid-batch) but does **not** show a spinner here —\n * that lives in the header. Sibling rows might individually\n * resolve at different times during the batch, so we still\n * want the per-row spinner story (above) for those.\n */\n isBatchCanceling: boolean;\n marketLabel: string;\n onCancel: (order: Order) => void;\n};\n\nfunction OrderRow({\n order,\n striped,\n isThisRowCanceling,\n isBatchCanceling,\n marketLabel,\n onCancel,\n}: OrderRowProps) {\n const { t } = useTranslation();\n const tokenSymbol = order.symbol.split(\"-\")[0];\n const isLong = order.side === \"long\";\n const directionLabel = isLong\n ? t(\"perpetuals.openOrders.long\")\n : t(\"perpetuals.openOrders.short\");\n const directionColor = isLong ? \"text-bullish\" : \"text-bearish\";\n\n const typeLabel = describeOrderType(order, marketLabel);\n\n // Trigger orders show \"Market\" for both notional and execute price\n // (the venue settles them at the prevailing mark when triggered);\n // limit orders show numeric values.\n const orderValueText = order.isTrigger\n ? marketLabel\n : formatUsd2(order.price * order.quantity);\n const executePriceText = order.isTrigger\n ? marketLabel\n : formatUsdPrice(order.price);\n\n return (\n <div style={striped ? STRIPE_BG_STYLE : undefined}>\n <div\n style={BODY_ROW_STYLE}\n className=\"flex flex-1 flex-row items-center justify-start px-4\"\n >\n {/* Time */}\n <div\n style={COL_STYLE.time}\n className=\"flex flex-row items-center justify-start\"\n >\n <span className=\"text-xs font-normal text-default-700\">\n {formatDateTime(order.timestamp)}\n </span>\n </div>\n\n {/* Size — raw token quantity, no symbol suffix (Axiom keeps the\n symbol in the dedicated `Asset` column so this column stays\n narrow). */}\n <div\n style={COL_STYLE.size}\n className=\"flex flex-row items-center justify-start\"\n >\n <span className=\"text-xs font-normal text-default-700\">\n {formatQuantity(order.quantity)}\n </span>\n </div>\n\n {/* Asset — plain text (no icon, unlike Positions). Mirrors Axiom. */}\n <div\n style={COL_STYLE.asset}\n className=\"flex flex-row items-center justify-start\"\n >\n <span className=\"text-xs font-medium text-foreground\">\n {tokenSymbol}\n </span>\n </div>\n\n {/* Direction */}\n <div\n style={COL_STYLE.direction}\n className=\"flex flex-row items-center justify-start\"\n >\n <span className={cn(\"text-xs font-medium\", directionColor)}>\n {directionLabel}\n </span>\n </div>\n\n {/* Type — human-readable venue label (Limit / Stop Market / …) */}\n <div\n style={COL_STYLE.type}\n className=\"flex flex-row items-center justify-start\"\n >\n <span className=\"text-xs font-normal text-default-700\">\n {typeLabel}\n </span>\n </div>\n\n {/* Leverage — small chip; hidden when leverage is unknown\n (e.g. user has no open position for this coin so the venue\n never echoed a leverage value). Matches Axiom's behaviour\n of not falling back to a stale/inferred number. */}\n <div\n style={COL_STYLE.leverage}\n className=\"flex flex-row items-center justify-start\"\n >\n {order.leverage !== undefined ? (\n <span\n className={cn(\n \"inline-flex flex-row items-center justify-start gap-1\",\n \"rounded p-1 bg-default-200/50\",\n \"text-xs font-normal text-default-700\",\n )}\n style={{ height: 18 }}\n >\n {order.leverage}x\n </span>\n ) : (\n <span className=\"text-xs font-normal text-default-500\">--</span>\n )}\n </div>\n\n {/* Order Value */}\n <div\n style={COL_STYLE.orderValue}\n className=\"flex flex-row items-center justify-start\"\n >\n <span className=\"text-xs font-normal text-default-700\">\n {orderValueText}\n </span>\n </div>\n\n {/* Execute Price */}\n <div\n style={COL_STYLE.executePrice}\n className=\"flex flex-row items-center justify-start\"\n >\n <span className=\"text-xs font-normal text-default-700\">\n {executePriceText}\n </span>\n </div>\n\n {/* Current Price — live mark price from the venue's\n `metaAndAssetCtxs` (or webData2). Falls back to `--` when\n the market context isn't available yet. */}\n <div\n style={COL_STYLE.currentPrice}\n className=\"flex flex-row items-center justify-start\"\n >\n <span className=\"text-xs font-normal text-default-700\">\n {formatUsdPrice(order.markPrice)}\n </span>\n </div>\n\n {/* Trigger Condition — venue-supplied human-readable string for\n trigger orders (e.g. \"Price below $75,050\"). Limit orders\n display `--` since they have no condition. */}\n <div\n style={COL_STYLE.triggerCondition}\n className=\"flex flex-row items-center justify-start\"\n >\n <span className=\"text-xs font-normal text-default-700\">\n {order.triggerCondition ?? \"--\"}\n </span>\n </div>\n\n {/* TP / SL — bundled exits read from Hyperliquid's parent\n order's `children[]` array (no heuristics). Trigger orders\n themselves never carry children, so they always render\n `-- / --`. Layout reuses the `1fr auto 1fr` grid pattern\n established by the Positions table for visual consistency. */}\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 {order.takeProfitPrice !== undefined\n ? formatUsdPrice(order.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 {order.stopLossPrice !== undefined\n ? formatUsdPrice(order.stopLossPrice)\n : \"--\"}\n </span>\n </div>\n\n {/* Cancel — single-order cancel button (per-row), 24×24 icon\n target with a subtle red hover background. Right-aligned\n within the column to match Axiom (header is centred, row\n is end-aligned). */}\n <div\n style={COL_STYLE.cancel}\n className=\"flex flex-row items-center justify-end gap-1\"\n >\n <button\n type=\"button\"\n onClick={() => onCancel(order)}\n disabled={isThisRowCanceling || isBatchCanceling}\n aria-label={t(\"perpetuals.openOrders.cancelOne.aria\")}\n aria-busy={isThisRowCanceling || undefined}\n className={cn(\n \"inline-flex items-center justify-center rounded p-1\",\n \"cursor-pointer text-bearish transition-colors duration-150 ease-in-out\",\n \"hover:bg-bearish/10\",\n \"disabled:cursor-not-allowed disabled:opacity-50\",\n \"outline-none focus:outline-none focus-visible:outline-none\",\n \"focus:ring-0 focus-visible:ring-0\",\n )}\n style={{ height: 24, width: 24 }}\n >\n {/* Spinner replaces the X glyph mid-cancel so the user gets\n immediate feedback the click landed. We use the same\n 24×24 button frame regardless so the row doesn't\n jitter on transition.\n\n Sizing via `transform: scale` rather than Tailwind\n class overrides on the wrapper / circle slots:\n - HeroUI's smallest preset (`size=\"sm\"`) renders at\n 20×20 with a 2px `border-2` stroke. We want 12×12\n visually, so we scale the whole thing by 0.6\n (20 × 0.6 = 12, 2 × 0.6 = 1.2 — radius/stroke\n ratio stays in proportion, no visual heaviness\n inversion).\n - We don't use `classNames={{ wrapper: \"!w-3 !h-3\" }}`\n because consumer apps in USE_LOCAL_SDK=true mode\n scan a curated set of SDK paths via Tailwind's\n `@source` directive — arbitrary utility classes\n we emit from this file aren't guaranteed to make\n it into the consumer's compiled CSS, especially\n `!`-prefixed ones. Inline `transform` is plain\n CSS, doesn't touch the class graph, always works.\n - The 24×24 button frame already centres the\n spinner via `inline-flex justify-center` from the\n parent `<button>`, so the `transform-origin`\n default of `center` keeps it on-axis. */}\n {isThisRowCanceling ? (\n <Spinner\n size=\"sm\"\n color=\"current\"\n style={{ transform: \"scale(0.6)\" }}\n />\n ) : (\n /* Inline cross icon — keeps the SDK self-contained\n without pulling a new icon-set dep just for one glyph. */\n <svg\n viewBox=\"0 0 14 14\"\n width={12}\n height={12}\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={1.6}\n strokeLinecap=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M3 3 L11 11 M11 3 L3 11\" />\n </svg>\n )}\n </button>\n </div>\n </div>\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Skeleton / Empty\n// ---------------------------------------------------------------------------\n\n/** Loading skeleton for open orders panel */\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/**\n * Standalone empty-state component. The main `OpenOrdersUI` renders\n * its own empty layout (header + centred message) so this export\n * exists for consumers that wire their own empty state outside the\n * widget.\n */\nexport function OpenOrdersEmpty() {\n return (\n <div className=\"flex h-24 items-center justify-center text-[14px] text-default-700\">\n No open orders\n </div>\n );\n}\n","import { useCallback, useState } from \"react\";\nimport { useTranslation } from \"@liberfi.io/i18n\";\nimport {\n cn,\n ModalContent,\n Spinner,\n StyledModal,\n XCloseIcon,\n} from \"@liberfi.io/ui\";\nimport {\n useOpenOrdersScript,\n type CancelOrderImpl,\n type CancelOrdersImpl,\n} from \"./open-orders.script\";\nimport { OpenOrdersUI } from \"./open-orders.ui\";\n\nexport type OpenOrdersWidgetProps = {\n userAddress?: string;\n symbol?: string;\n onCancelSuccess?: () => void;\n onCancelError?: (error: Error) => void;\n /**\n * Optional host-provided single-order cancel implementation — see\n * {@link CancelOrderImpl}. Forwarded verbatim to\n * {@link useOpenOrdersScript}. Hosts that own the wallet keys\n * (direct-venue setups) inject this; hosts that proxy via a\n * server with TEE signing leave it undefined.\n */\n cancelOrder?: CancelOrderImpl;\n /**\n * Optional host-provided batch cancel implementation — see\n * {@link CancelOrdersImpl}. When supplied, `Cancel All` issues a\n * single signature for every open order at once (the recommended\n * UX for direct-venue setups; perpetuals-server proxies don't need\n * it because each leg is a no-op API call from the user's\n * perspective).\n */\n cancelOrders?: CancelOrdersImpl;\n className?: string;\n};\n\n/**\n * Convenience widget that wires {@link useOpenOrdersScript} (data + sort\n * + cancel mutations) to {@link OpenOrdersUI} (presentation), and adds\n * a confirmation dialog for the destructive `Cancel All` action.\n *\n * The dialog state lives here (not in the script) so:\n * - The script stays trivially testable — its `handleCancelAll` is a\n * deterministic mutation call without any UI side effects.\n * - Headless / programmatic callers that import the script directly\n * can skip the dialog entirely (e.g. CI tooling, batch scripts).\n *\n * Single-order cancels go through directly: clicking the per-row `x`\n * button is already an explicit, low-impact gesture, and adding a\n * second prompt for every row would feel obstructive — matches Axiom.\n *\n * The confirm dialog matches the visual language of the place-order\n * `LeverageModal` and `DepositHyperliquidUsdcModal` (zinc-900 surface,\n * 14px corner radius, soft shadow, custom 5-px-padded header with an\n * X close button) so all destructive / confirm modals in the\n * perpetuals UI feel like one family.\n */\nexport function OpenOrdersWidget({\n userAddress,\n symbol,\n onCancelSuccess,\n onCancelError,\n cancelOrder,\n cancelOrders,\n className,\n}: OpenOrdersWidgetProps) {\n const { t } = useTranslation();\n const {\n orders,\n sortKey,\n sortDir,\n onSort,\n handleCancelOrder,\n handleCancelAll,\n cancelingOrderIds,\n isCancelingAll,\n } = useOpenOrdersScript({\n userAddress,\n symbol,\n onCancelSuccess,\n onCancelError,\n cancelOrder,\n cancelOrders,\n });\n\n const [confirmOpen, setConfirmOpen] = useState(false);\n\n const requestCancelAll = useCallback(() => {\n if (orders.length === 0) return;\n setConfirmOpen(true);\n }, [orders.length]);\n\n const closeConfirm = useCallback(() => {\n // Don't let the user dismiss the modal mid-batch — once the\n // signed cancel(s) are airborne we want them to see the spinner\n // resolve before the modal disappears, otherwise the \"is it\n // working?\" anxiety we tried to fix re-emerges.\n if (isCancelingAll) return;\n setConfirmOpen(false);\n }, [isCancelingAll]);\n\n // Confirm flow: keep the modal open until the batch settles, then\n // close it ourselves. We do NOT pre-close on click — that's how\n // the previous incarnation lost feedback. Mid-flight, both buttons\n // gate on `isCancelingAll`: the destructive CTA shows a spinner,\n // the dismiss CTA goes disabled.\n const confirmCancelAll = useCallback(async () => {\n try {\n await handleCancelAll();\n } finally {\n setConfirmOpen(false);\n }\n }, [handleCancelAll]);\n\n return (\n <>\n <OpenOrdersUI\n className={className}\n orders={orders}\n sortKey={sortKey}\n sortDir={sortDir}\n onSort={onSort}\n onCancelOrder={handleCancelOrder}\n onCancelAll={requestCancelAll}\n cancelingOrderIds={cancelingOrderIds}\n isCancelingAll={isCancelingAll}\n />\n <StyledModal\n isOpen={confirmOpen}\n onOpenChange={(open) => {\n // Block backdrop / Esc dismiss while cancellation is in\n // flight — same pattern as the leverage modal's pending\n // guard.\n if (isCancelingAll) return;\n if (!open) closeConfirm();\n }}\n size=\"md\"\n hideCloseButton\n backdrop=\"blur\"\n classNames={{\n base: cn(\n \"!bg-[#18181b] !rounded-[14px] !border !border-[rgba(39,39,42,1)]\",\n \"!shadow-[0_25px_50px_-12px_rgba(0,0,0,0.5)] max-w-[420px]\",\n ),\n body: \"!p-0\",\n }}\n >\n <ModalContent>\n <div className=\"flex flex-col\">\n {/* Header — mirrors LeverageModal / DepositHyperliquidUsdcModal */}\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 {t(\"perpetuals.openOrders.cancelAll.confirmTitle\")}\n </h3>\n <button\n type=\"button\"\n onClick={closeConfirm}\n disabled={isCancelingAll}\n aria-label=\"Close\"\n className={cn(\n \"p-1 rounded-[10px] cursor-pointer\",\n \"hover:bg-[rgba(39,39,42,0.5)]\",\n \"text-zinc-400 hover:text-white transition-colors\",\n \"disabled:cursor-not-allowed disabled:opacity-50\",\n \"outline-none focus:outline-none focus-visible:outline-none\",\n \"focus:ring-0 focus-visible:ring-0\",\n )}\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 <p className=\"text-[13px] text-zinc-400 leading-[18px] m-0\">\n {t(\"perpetuals.openOrders.cancelAll.confirmBody\")}\n </p>\n\n {/* Single destructive CTA — no companion `Keep orders`\n button. Three independent dismiss paths already cover\n reversal (X close button, backdrop click, Esc key),\n so a second equal-weight button would dilute the\n primary action and contribute decision fatigue\n without adding real reversibility.\n Borrows the leverage CTA's geometry\n (h-12 / rounded-[12px] / font-medium / w-full) so\n the modal feels like part of the same family, but\n swaps the brand-green palette for `bg-bearish` to\n signal destructive intent. */}\n <button\n type=\"button\"\n onClick={() => void confirmCancelAll()}\n disabled={isCancelingAll}\n className={cn(\n \"cursor-pointer mt-1 w-full h-12 rounded-[12px]\",\n \"font-medium text-white\",\n \"bg-bearish hover:bg-bearish/90 active:bg-bearish/80\",\n \"transition-colors flex items-center justify-center gap-2\",\n \"disabled:bg-[#3f3f46] disabled:text-zinc-500 disabled:cursor-not-allowed\",\n \"outline-none focus:outline-none focus-visible:outline-none\",\n \"focus:ring-0 focus-visible:ring-0\",\n )}\n >\n {isCancelingAll && <Spinner size=\"sm\" color=\"current\" />}\n {isCancelingAll\n ? t(\"perpetuals.openOrders.cancelAll.confirming\")\n : t(\"perpetuals.openOrders.cancelAll.confirm\")}\n </button>\n </div>\n </div>\n </ModalContent>\n </StyledModal>\n </>\n );\n}\n","import { useCallback, useMemo, useState } from \"react\";\nimport { useTradesQuery } from \"../../hooks/useTradesQuery\";\nimport type { TradeHistory } from \"../../types\";\nimport type { TradeHistorySortKey, SortDirection } from \"./trade-history.ui\";\n\nexport type UseTradeHistoryScriptParams = {\n userAddress?: string;\n /**\n * Optional venue-side filter. Omit (the default consumed by\n * `TradeHistoryWidget`) to surface fills from every coin — Axiom's\n * bottom Trades tab is all-coin, and our Positions / Open Orders\n * widgets follow the same convention.\n */\n symbol?: string;\n};\n\nexport type UseTradeHistoryScriptResult = {\n /** Trades already sorted by the active `sortKey` / `sortDir`. */\n trades: TradeHistory[];\n isLoading: boolean;\n error: Error | null;\n /**\n * Active sort column. Defaults to `time` — Axiom never exits the sort\n * state, so we model this as a non-nullable union (the UI assumes\n * a column is always active).\n */\n sortKey: TradeHistorySortKey;\n sortDir: SortDirection;\n /**\n * Toggle the sort column / direction. Mirrors Axiom's 2-state cycle:\n * clicking the active column flips `asc` ↔ `desc`; clicking a fresh\n * column starts at `desc` (newest / largest first — the natural\n * default for time, money, and PnL columns alike).\n */\n onSort: (key: TradeHistorySortKey) => void;\n};\n\n// ---------------------------------------------------------------------------\n// Sort helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Map a sort key to the comparable scalar for a given trade. Returns\n * `null` for missing values so the comparator can rank them last\n * regardless of direction (the standard \"missing data goes to the\n * bottom\" UX convention used elsewhere in the SDK).\n */\nfunction getSortValue(\n trade: TradeHistory,\n key: TradeHistorySortKey,\n): number | string | null {\n switch (key) {\n case \"time\":\n return trade.timestamp;\n case \"size\":\n return trade.quantity;\n case \"asset\":\n return trade.symbol.split(\"-\")[0];\n case \"description\":\n // Sort by the venue's raw `dir` string (e.g. \"Open Long\",\n // \"Close Short\", \"Market liquidation triggered at 2316.9\"). Pure\n // alphabetic sort matches Axiom — no semantic re-ordering of\n // open/close/liquidation.\n return trade.dir ?? null;\n case \"price\":\n return trade.price;\n case \"tradeValue\":\n return trade.price * trade.quantity;\n case \"closedPnl\":\n return trade.closedPnl ?? null;\n }\n}\n\nfunction compareTrades(\n a: TradeHistory,\n b: TradeHistory,\n key: TradeHistorySortKey,\n dir: SortDirection,\n): number {\n const aVal = getSortValue(a, key);\n const bVal = getSortValue(b, key);\n\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 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 Trade History (user fills) table.\n *\n * Responsibilities:\n * - Read fills via {@link useTradesQuery}. Hyperliquid's `webData2`\n * stream does **not** carry fill events (only state snapshots), so\n * we can't piggy-back on the same WS write-through path used by\n * Positions / Open Orders. Instead the query uses a tighter\n * `staleTime` so refocusing the tab triggers a near-instant\n * refresh — close enough to real-time for a fills view that the\n * user only consults episodically.\n * - Own sort state (default `time ↓` — newest fill first, Axiom-\n * style).\n */\nexport function useTradeHistoryScript({\n userAddress,\n symbol,\n}: UseTradeHistoryScriptParams): UseTradeHistoryScriptResult {\n // Default sort: `time` desc — most recent fill at the top.\n const [sortKey, setSortKey] = useState<TradeHistorySortKey>(\"time\");\n const [sortDir, setSortDir] = useState<SortDirection>(\"desc\");\n\n const onSort = useCallback((key: TradeHistorySortKey) => {\n setSortKey((currentKey) => {\n if (currentKey === key) {\n setSortDir((d) => (d === \"asc\" ? \"desc\" : \"asc\"));\n return currentKey;\n }\n // Fresh column: start at `desc`. For time / size / value /\n // closedPnl this surfaces the most-relevant rows first; for\n // alphabetic columns (asset / description) it's a stylistic\n // choice but matches the all-columns-default-desc UX of Axiom.\n setSortDir(\"desc\");\n return key;\n });\n }, []);\n\n const {\n data: tradesData,\n isLoading,\n error,\n } = useTradesQuery(\n {\n userAddress,\n symbol,\n // Hyperliquid's `userFills` returns up to ~2000 most recent fills\n // — we don't pass a `limit` here so the query stays aligned with\n // Axiom's \"show everything I've ever traded\" panel. Virtualization\n // in the UI keeps the cost flat regardless of list length.\n },\n { enabled: !!userAddress, staleTime: 5_000 },\n );\n\n const trades = useMemo(() => tradesData?.trades ?? [], [tradesData]);\n\n const sortedTrades = useMemo(() => {\n return [...trades].sort((a, b) => compareTrades(a, b, sortKey, sortDir));\n }, [trades, sortKey, sortDir]);\n\n return {\n trades: sortedTrades,\n isLoading,\n error,\n sortKey,\n sortDir,\n onSort,\n };\n}\n","import type { CSSProperties, ReactElement } from \"react\";\nimport { useMemo, useRef } from \"react\";\nimport { List, type RowComponentProps } from \"react-window\";\nimport { useResizeObserver } from \"@liberfi.io/hooks\";\nimport { useTranslation } from \"@liberfi.io/i18n\";\nimport { cn } from \"@liberfi.io/ui\";\nimport type { TradeHistory } from \"../../types\";\nimport {\n HEADER_ROW_STYLE,\n HeaderCell,\n STRIPE_BG_STYLE,\n formatDateTime,\n formatQuantity,\n formatSignedUsd2,\n formatUsd2,\n formatUsdPrice,\n type SortDirection,\n} from \"../_internal/table\";\n\n// ---------------------------------------------------------------------------\n// Sort\n// ---------------------------------------------------------------------------\n\n/**\n * Stable identifier for a sortable column. All 7 visible columns are\n * sortable; mirrors Axiom's bottom-Trades panel 1:1. Using a discriminated\n * string union (rather than an enum) so the value survives a tsup build\n * to a stable runtime string — consumers persisting the active sort to\n * local-storage / URL params don't pay an enum-numbering tax.\n */\nexport type TradeHistorySortKey =\n | \"time\"\n | \"size\"\n | \"asset\"\n | \"description\"\n | \"price\"\n | \"tradeValue\"\n | \"closedPnl\";\n\nexport type { SortDirection };\n\n// ---------------------------------------------------------------------------\n// Column layout — hoisted to module scope so React doesn't reallocate the\n// styles on every render of the (potentially long) virtualized list.\n// ---------------------------------------------------------------------------\n\n/**\n * Per-column inline styles. Mirrors Axiom's bottom-Trades layout 1:1\n * minus the Share column (we ship as a callback-less variant for now —\n * see the widget docstring for the rationale):\n * - 4 columns are clamped via `maxWidth` (Axiom's `max-w-[Npx]` + `flex-1`).\n * - `price`, `tradeValue`, `closedPnl` are pure `flex: 1 1 0%` so they\n * share the row's leftover width.\n *\n * Why inline (not Tailwind arbitrary classes): same rationale as\n * positions / open-orders — `USE_LOCAL_SDK=true` skips the consumer's\n * `node_modules` `@source` glob, and arbitrary-value classes emitted\n * from local source files get purged. Inline `style` always works.\n */\nconst COL_STYLE: Record<string, CSSProperties> = {\n time: { flex: \"1 1 0%\", maxWidth: 200 },\n size: { flex: \"1 1 0%\", maxWidth: 80 },\n asset: { flex: \"1 1 0%\", maxWidth: 100 },\n description: { flex: \"1 1 0%\", maxWidth: 300 },\n price: { flex: \"1 1 0%\" },\n tradeValue: { flex: \"1 1 0%\" },\n closedPnl: { flex: \"1 1 0%\" },\n};\n\n/**\n * Min-width of the inner table body. Axiom uses 1120 (with their Share\n * column); without that 24-px column we drop to 1100 — same value used\n * by Open Orders so the bottom panels share a horizontal-scroll\n * threshold.\n */\nconst TABLE_MIN_WIDTH: CSSProperties = { minWidth: 1100 };\n\n/**\n * Virtualized row outer height. Axiom uses 48 — that's 36 px of zebra-\n * coloured content row plus a 12 px transparent gap below it. We mirror\n * the layout exactly:\n *\n * ┌─ virtualizer slot (48 px, transparent) ────────────────────────┐\n * │ ┌─ stripe layer (36 px, STRIPE_BG_STYLE or transparent) ───┐ │\n * │ │ content row (flex, 16 px horizontal padding) │ │\n * │ └────────────────────────────────────────────────────────────┘ │\n * │ (12 px gap, always transparent — never striped) │\n * └────────────────────────────────────────────────────────────────┘\n *\n * Crucially the stripe is on the **36 px inner layer**, not the 48 px\n * slot — otherwise rows visually fuse into a continuous striped block,\n * making the table look chunkier than Positions / Open Orders (which\n * use 36 px rows with no gap). Verified against Axiom via DOM\n * inspection — their `bg-primaryStroke/20` lives on the 36 px content\n * layer too.\n */\nconst ROW_OUTER_HEIGHT = 48;\n\n/**\n * Inner row content style — fixed 36 px high, padding 0 16. Same as\n * Positions / Open Orders body rows, kept here as a hoisted constant\n * so we don't reallocate on every virtual row render.\n */\nconst ROW_INNER_STYLE: CSSProperties = {\n minHeight: 36,\n maxHeight: 36,\n padding: \"0 16px\",\n};\n\n// ---------------------------------------------------------------------------\n// Description colour mapping — by trade direction, not position side.\n// \"Open Long\" / \"Close Short\" are buy-side actions → bullish.\n// \"Open Short\" / \"Close Long\" / liquidations are sell-side → bearish.\n// Axiom uses the same convention; we mirror it 1:1.\n// ---------------------------------------------------------------------------\nfunction isBuyDirection(dir: string | undefined): boolean {\n if (!dir) return false;\n // \"Open Long\" / \"Close Short\" → buy.\n if (/^Open\\s+Long\\b/i.test(dir)) return true;\n if (/^Close\\s+Short\\b/i.test(dir)) return true;\n // Everything else (Open Short / Close Long / \"Market liquidation\n // triggered at …\") is treated as a sell-side action.\n return false;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\nexport type TradeHistoryUIProps = {\n /** Already-sorted trades. The script layer owns sort state. */\n trades: TradeHistory[];\n /** Currently active sort column. Always non-null — Axiom never exits\n * the sort state, defaulting to `Time ↓`. */\n sortKey: TradeHistorySortKey;\n sortDir: SortDirection;\n onSort: (key: TradeHistorySortKey) => void;\n /** Optional className on the outermost container. */\n className?: string;\n};\n\nexport function TradeHistoryUI({\n trades,\n sortKey,\n sortDir,\n onSort,\n className,\n}: TradeHistoryUIProps) {\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 fill. 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<TradeHistorySortKey>\n style={COL_STYLE.time}\n sortKey=\"time\"\n activeSortKey={sortKey}\n sortDir={sortDir}\n onSort={onSort}\n >\n {t(\"perpetuals.tradeHistory.col.time\")}\n </HeaderCell>\n <HeaderCell<TradeHistorySortKey>\n style={COL_STYLE.size}\n sortKey=\"size\"\n activeSortKey={sortKey}\n sortDir={sortDir}\n onSort={onSort}\n >\n {t(\"perpetuals.tradeHistory.col.size\")}\n </HeaderCell>\n <HeaderCell<TradeHistorySortKey>\n style={COL_STYLE.asset}\n sortKey=\"asset\"\n activeSortKey={sortKey}\n sortDir={sortDir}\n onSort={onSort}\n >\n {t(\"perpetuals.tradeHistory.col.asset\")}\n </HeaderCell>\n <HeaderCell<TradeHistorySortKey>\n style={COL_STYLE.description}\n sortKey=\"description\"\n activeSortKey={sortKey}\n sortDir={sortDir}\n onSort={onSort}\n >\n {t(\"perpetuals.tradeHistory.col.description\")}\n </HeaderCell>\n <HeaderCell<TradeHistorySortKey>\n style={COL_STYLE.price}\n sortKey=\"price\"\n activeSortKey={sortKey}\n sortDir={sortDir}\n onSort={onSort}\n >\n {t(\"perpetuals.tradeHistory.col.price\")}\n </HeaderCell>\n <HeaderCell<TradeHistorySortKey>\n style={COL_STYLE.tradeValue}\n sortKey=\"tradeValue\"\n activeSortKey={sortKey}\n sortDir={sortDir}\n onSort={onSort}\n >\n {t(\"perpetuals.tradeHistory.col.tradeValue\")}\n </HeaderCell>\n <HeaderCell<TradeHistorySortKey>\n style={COL_STYLE.closedPnl}\n sortKey=\"closedPnl\"\n activeSortKey={sortKey}\n sortDir={sortDir}\n onSort={onSort}\n >\n {t(\"perpetuals.tradeHistory.col.closedPnl\")}\n </HeaderCell>\n </div>\n );\n\n // Layout contract (mirrors `trades.ui.tsx` — the other react-window\n // table in this package):\n // - Root: `h-full` — the widget *must* fill its parent's height,\n // otherwise a `flex flex-col` root falls back to the natural\n // content height (≈ header) and the virtualized body's\n // ResizeObserver permanently reads 0 → `<List>` never renders.\n // - Header wrapper: `flex-none` — fixed-height row that never\n // fights the body for vertical space.\n // - Body wrapper: `flex-1 min-h-0` — soaks up the remaining height\n // so the virtualizer has something to measure. `min-h-0` is the\n // standard flex-shrink override that lets `overflow-y-auto`\n // actually scroll instead of pushing the parent.\n return (\n <div\n className={cn(\n \"flex h-full w-full min-w-0 flex-col overflow-hidden bg-transparent\",\n className,\n )}\n >\n <div className=\"flex flex-1 min-h-0 flex-col overflow-x-auto\">\n {/* Header lives outside the virtualizer so it stays sticky at\n the top regardless of body scroll. */}\n <div\n style={{ ...TABLE_MIN_WIDTH, ...HEADER_ROW_STYLE }}\n className=\"flex flex-none flex-col\"\n >\n {header}\n </div>\n {trades.length === 0 ? (\n <div\n style={TABLE_MIN_WIDTH}\n className=\"flex flex-1 min-h-0 flex-col items-center justify-center py-6 text-xs text-default-700\"\n >\n {t(\"perpetuals.tradeHistory.empty\")}\n </div>\n ) : (\n <VirtualBody trades={trades} />\n )}\n </div>\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Virtualized body\n// ---------------------------------------------------------------------------\n\ntype RowData = {\n trades: TradeHistory[];\n};\n\nfunction VirtualBody({ trades }: { trades: TradeHistory[] }) {\n // Resize observation: react-window v2 needs an explicit `height` prop.\n // Same pattern as the market-trades stream (`trades.ui.tsx`).\n const containerRef = useRef<HTMLDivElement | null>(null);\n const { height = 0 } = useResizeObserver<HTMLDivElement>({\n ref: containerRef,\n });\n\n // Memoise so the reference is stable when `trades` doesn't change —\n // keeps react-window's internal bailouts effective.\n const rowProps = useMemo<RowData>(() => ({ trades }), [trades]);\n\n return (\n <div\n ref={containerRef}\n style={TABLE_MIN_WIDTH}\n className=\"flex flex-1 min-h-0 flex-col overflow-y-auto\"\n >\n {height > 0 && (\n <List\n style={{ height }}\n rowComponent={Row}\n rowCount={trades.length}\n rowHeight={ROW_OUTER_HEIGHT}\n rowProps={rowProps}\n overscanCount={4}\n />\n )}\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Row\n// ---------------------------------------------------------------------------\n\nfunction Row({\n index,\n style,\n trades,\n}: RowComponentProps<RowData>): ReactElement | null {\n const trade = trades[index];\n if (!trade) return null;\n\n // Zebra stripe — odd rows get a faint white-4% fill (see\n // STRIPE_BG_STYLE), even rows stay transparent. Mirrors Axiom's\n // `bg-primaryStroke/20` pattern but corrected for our pure-black\n // page background where mid-grey tokens blend invisibly.\n const striped = index % 2 === 1;\n\n const tokenSymbol = trade.symbol.split(\"-\")[0];\n const tradeValue = trade.price * trade.quantity;\n const closedPnl = trade.closedPnl ?? 0;\n const buy = isBuyDirection(trade.dir);\n const description = trade.dir ?? \"\";\n const descriptionColor = buy ? \"text-bullish\" : \"text-bearish\";\n const pnlColor = closedPnl >= 0 ? \"text-bullish\" : \"text-bearish\";\n\n // The stripe lives on the **36 px content layer** (same height as\n // Positions / Open Orders rows), not the 48 px virtualizer slot —\n // see the ROW_OUTER_HEIGHT docstring. The remaining 12 px of the slot\n // is always transparent, producing the row gap Axiom uses.\n return (\n <div style={style}>\n <div\n style={\n striped ? { ...ROW_INNER_STYLE, ...STRIPE_BG_STYLE } : ROW_INNER_STYLE\n }\n className=\"flex flex-1 flex-row items-center justify-start\"\n >\n {/* Time */}\n <div\n style={COL_STYLE.time}\n className=\"flex flex-row items-center justify-start\"\n >\n <span className=\"text-xs font-normal text-default-500\">\n {formatDateTime(trade.timestamp)}\n </span>\n </div>\n\n {/* Size — raw token quantity, no symbol suffix (Asset column\n shows the coin separately, Axiom-style). */}\n <div\n style={COL_STYLE.size}\n className=\"flex flex-row items-center justify-start\"\n >\n <span className=\"text-xs font-normal text-default-700\">\n {formatQuantity(trade.quantity)}\n </span>\n </div>\n\n {/* Asset — plain text, no icon. */}\n <div\n style={COL_STYLE.asset}\n className=\"flex flex-row items-center justify-start\"\n >\n <span className=\"text-xs font-medium text-foreground\">\n {tokenSymbol}\n </span>\n </div>\n\n {/* Description — venue-supplied `dir` string (Open Long /\n Close Short / Market liquidation triggered at …). Coloured\n by trade direction (buy=bullish, sell/liquidation=bearish). */}\n <div\n style={COL_STYLE.description}\n className=\"flex flex-row items-center justify-start\"\n >\n <span className={cn(\"text-xs font-normal\", descriptionColor)}>\n {description}\n </span>\n </div>\n\n {/* Price — Axiom uses 11px here (every other column is 12px).\n We preserve the same micro-detail to keep the column from\n looking visually heavy when the price has many digits. */}\n <div\n style={COL_STYLE.price}\n className=\"flex flex-row items-center justify-start\"\n >\n <span\n className=\"font-normal text-default-700\"\n style={{ fontSize: 11, lineHeight: \"16px\" }}\n >\n {formatUsdPrice(trade.price)}\n </span>\n </div>\n\n {/* Trade Value — px × sz, always 2dp + thousands separator. */}\n <div\n style={COL_STYLE.tradeValue}\n className=\"flex flex-row items-center justify-start\"\n >\n <span className=\"text-xs font-normal text-default-700\">\n {formatUsd2(tradeValue)}\n </span>\n </div>\n\n {/* Closed PnL — Axiom shows venue-supplied `closedPnl` verbatim.\n For an opening fill it's essentially `-fee` (≈ -$0.01); for a\n closing fill it's `(closePrice - entryPrice) × size - fee`\n (sign-flipped for shorts). Format follows Axiom: 2 dp + sign\n for non-zero values, plain `+$0` when the value rounds to\n zero — see `formatSignedUsd2` for the round-to-zero rule. */}\n <div\n style={COL_STYLE.closedPnl}\n className=\"flex flex-row items-center justify-start\"\n >\n <span className={cn(\"text-xs font-medium\", pnlColor)}>\n {formatSignedUsd2(closedPnl)}\n </span>\n </div>\n </div>\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Skeleton / Empty\n// ---------------------------------------------------------------------------\n\n/** Loading skeleton for the trade-history panel. */\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/**\n * Standalone empty-state component. The main `TradeHistoryUI` renders\n * its own empty layout (header + centred message) so this export\n * exists for consumers wiring their own empty state outside the widget.\n */\nexport function TradeHistoryEmpty() {\n return (\n <div className=\"flex h-24 items-center justify-center text-[14px] text-default-700\">\n No trades\n </div>\n );\n}\n","import { useTradeHistoryScript } from \"./trade-history.script\";\nimport { TradeHistoryUI } from \"./trade-history.ui\";\n\nexport type TradeHistoryWidgetProps = {\n /** User wallet address. The widget gates the underlying query on this. */\n userAddress?: string;\n /**\n * Optional venue-side filter. Omit to show fills from every coin —\n * Axiom's bottom-Trades panel is all-coin, and the consumer-facing\n * widgets (Positions / Open Orders / Trades) follow the same\n * convention so the three tabs share a coherent UX.\n */\n symbol?: string;\n /** Optional className on the outermost container. */\n className?: string;\n};\n\n/**\n * Convenience widget that wires {@link useTradeHistoryScript} (data +\n * sort) to {@link TradeHistoryUI} (presentation). Intentionally thin —\n * unlike Open Orders there's no destructive action to gate behind a\n * confirmation dialog, so the widget is just a pass-through.\n *\n * Headless callers (CI, programmatic exports) can import the script\n * directly without the UI; the script's return shape is the public\n * contract.\n */\nexport function TradeHistoryWidget({\n userAddress,\n symbol,\n className,\n}: TradeHistoryWidgetProps) {\n const { trades, sortKey, sortDir, onSort } = useTradeHistoryScript({\n userAddress,\n symbol,\n });\n\n return (\n <TradeHistoryUI\n className={className}\n trades={trades}\n sortKey={sortKey}\n sortDir={sortDir}\n onSort={onSort}\n />\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/RateLimiter.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/useUniverseQuery.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/useHyperliquidUserBootstrap.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/close-position-modal.ui.tsx","../src/components/positions/use-close-position.ts","../src/components/positions/positions.script.tsx","../src/components/_internal/table.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","HEAVY_INFO_TYPES","weightForInfoType","type","EXCHANGE_REQUEST_WEIGHT","RateLimiter","config","weight","charge","wait","resolve","now","aggregationKey","param","aggregation","m","WebSocketManager","wsEndpoint","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","UNIVERSE_SNAPSHOT_TTL_MS","USER_STATE_SNAPSHOT_TTL_MS","HyperliquidPerpetualsClient","endpoint","body","t","url","controller","timeoutId","response","HyperliquidApiError","entry","markets","symbols","snap","symbolSet","fetchPromise","snapshot","meta","assetCtxs","assets","asset","index","currentPrice","prevPrice","market","assetMeta","bySymbol","userAddress","key","cached","inflight","clearinghouse","openOrders","limitOrOptions","coin","options","intervalMs","limit","startTime","endTime","bars","candle","maxLevel","_params","params","userState","universe","result","parseClearinghouseState","markByCoin","buildMarkPriceMapFromUniverse","enrichPositions","sum","p","lev","map","openOrdersRaw","buildLeverageMap","orders","o","parseOpenOrder","filteredOrders","trades","isLong","subscriptionType","raw","parseWebData2","symbolFilter","positions","assetPos","pos","quantity","entryPrice","unrealizedPnl","positionValue","filteredPositions","withdrawableRaw","availableBalance","extractBundledTpSl","order","tp","sl","child","orderTypeStr","triggerPxStr","px","origSz","remainingSz","filledSz","isBuySide","rawOrderType","baseOrderType","isTrigger","triggerType","triggerPx","triggerCondition","takeProfitPrice","stopLossPrice","leverage","markPrice","ap","parseSpotBalances","balances","b","positionsResult","spotBalances","buildMarkPriceMap","leverageByCoinMap","enrichedPositions","totalUnrealizedPnl","buildUniverseSnapshot","leverageByCoin","buildLeverageRecord","serverTime","prevDayPx","szDecimals","maxLeverage","out","metaAndCtxs","ctxs","pickPositionTpSl","position","closingSide","closingSideBool","tpOrder","slOrder","isTp","isSl","marks","next","dir","pnl","statusCode","responseBody","LiberFiApiError","DEFAULT_TIMEOUT_MS","LiberFiHttpTransport","path","query","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","universeQueryKey","fetchUniverse","supportsUniverseSnapshot","useUniverseQuery","enabled","marketQueryKey","fetchMarket","useMarketQuery","universeBacked","universeQuery","fallbackQuery","marketsQueryKey","fetchMarkets","useMarketsQuery","a","filter","klinesQueryKey","fetchKlines","useKlinesQuery","orderBookQueryKey","agg","aggKey","fetchOrderBook","useOrderBookQuery","recentTradesQueryKey","fetchRecentTrades","useRecentTradesQuery","positionsQueryKey","fetchPositions","filterPositionsBySymbol","usePositionsQuery","ordersQueryKey","fetchOrders","filterOrdersBySymbol","useOrdersQuery","tradesQueryKey","fetchTrades","useTradesQuery","queryParams","activeAssetLeverageQueryKey","fetchActiveAssetLeverage","useActiveAssetLeverageQuery","DEFAULT_STALE_TIME_MS","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","useHyperliquidUserBootstrap","cancelled","timer","usePerpDepositClient","usePerpDepositClientMaybe","perpDepositQuoteQueryKey","fetchPerpDepositQuote","usePerpDepositQuote","isQuoteReady","usePerpDepositExecute","signAndBroadcast","dispatch","useReducer","reset","execute","input","quote","solanaTxHash","info","toErrorInfo","submitReq","fallbackCode","parsed","parseJsonSafe","perpDepositStatusQueryKey","fetchPerpDepositStatus","usePerpDepositStatus","pollIntervalMs","initialSetupState","classifyStep","step","current","sameAddress","reduceSetupState","action","rec","i","mergedAccount","mergeAccountState","s","nextRunnableStep","base","patch","useHyperliquidSetup","adapter","steps","autoLoad","onComplete","onError","adapterRef","stepsRef","onCompleteRef","onErrorRef","reload","accountState","records","e","toError","runStep","record","invokeAdapter","runNext","idx","completedRef","CoinInfoNotFoundUI","useTranslation","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","SkeletonHeader","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","TradesSkeletonHeader","TradeSkelRow","TradesSkeleton","rows","TradesEmpty","TradesWidget","signFor","kind","deriveTpSlPercent","deriveTpSlPrice","percent","sign","priceΔ","roundTpSlPrice","magnitude","factor","roundTpSlPercent","FALLBACK_LEVERAGE","usePlaceOrderFormScript","maxLeverageProp","onSuccess","onUpdateLeverage","onPlaceOrder","setSide","orderType","setOrderType","form","useForm","resolvedMaxLeverage","createOrderViaClient","isClientPending","placeOrderViaHostMutation","request","isSubmitting","watchedValues","amount","marketPrice","notional","estimatedFee","estimatedTotal","liquidationPrice","l","offset","positionsData","accountValue","availableMargin","currentPosition","account","hasOpenOrdersForSymbol","activeAssetLeverage","currentLeverage","isLeverageReady","lastSyncedSymbolRef","handleSubmit","finalPrice","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","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","LimitPriceInput","placeholder","formatTpSlNumber","TpSlInput","field","refPrice","isPriceField","partnerField","partnerValue","rounded","PlaceOrderFormUI","onSideChange","onOrderTypeChange","onSubmit","onAddFunds","addFundsFallback","guardedAddFunds","guardedSubmit","showLeverageModal","setShowLeverageModal","showTpSl","setShowTpSl","rawAmount","hasAmount","rawPrice","hasLimitPrice","tokenSymbol","positionPercent","handlePositionSlider","tokenQuantity","minMarginUsdc","submitState","handleSubmitButtonClick","formatTokenQuantity","n","StyledTooltip","tab","RHForm","isSubmit","buttonType","activeBg","activeColor","isPlacing","PlaceOrderFormWidget","resolvedOnUpdateLeverage","ClosePositionModal","closeType","maxSize","maxSizeRaw","sideLabel","sizeText","setSizeText","percentText","setPercentText","priceText","setPriceText","sizeRef","percentRef","priceRef","sizeNumeric","sliderPercent","handleSizeChange","handleSizeBlur","handlePercentChange","clamped","newSize","handlePercentBlur","handleSliderChange","handlePriceChange","isLimitMode","priceNumeric","hasValidPrice","canSubmit","title","description","confirmLabel","currentPriceDisplay","useClosePosition","onCloseSuccess","onCloseError","isModalOpen","setIsModalOpen","selectedPosition","setSelectedPosition","setCloseType","submitClose","isClosing","openMarketClose","openLimitClose","closeModal","closeSide","getSortValue","comparePositions","aVal","bVal","usePositionsScript","sortKey","setSortKey","sortDir","setSortDir","onSort","currentKey","d","closePosition","ALIGN_TO_JUSTIFY","HEADER_ROW_STYLE","BODY_ROW_STYLE","STRIPE_BG_STYLE","formatUsdPrice","abs","dp","formatUsd2","formatSignedUsd2","formatPercentAbs","formatDateTime","timestamp","yyyy","M","D","hh","mm","ss","HeaderCell","activeSortKey","align","arrow","interactive","justify","inner","cn","COL_STYLE","TABLE_MIN_WIDTH","PositionsUI","onMarketClose","onLimitClose","header","PositionRow","striped","directionLabel","directionColor","pnlColor","PositionsSkeleton","PositionsEmpty","PositionsWidget","compareOrders","useOpenOrdersScript","onCancelSuccess","onCancelError","cancelOrderImpl","cancelOrdersImpl","ordersData","cancelingIdsRef","setIdsVersion","bumpIdsVersion","addCancelingId","id","removeCancelingId","batchPending","setBatchPending","cancelOrderMutate","isFallbackPending","dispatchCancel","sortedOrders","handleCancelOrder","handleCancelAll","isCanceling","describeOrderType","isLimit","OpenOrdersUI","onCancelOrder","onCancelAll","cancelingOrderIds","isCancelingAll","marketLabel","OrderRow","isThisRowCanceling","isBatchCanceling","onCancel","typeLabel","orderValueText","executePriceText","OpenOrdersSkeleton","OpenOrdersEmpty","OpenOrdersWidget","cancelOrders","confirmOpen","setConfirmOpen","requestCancelAll","closeConfirm","confirmCancelAll","compareTrades","useTradeHistoryScript","tradesData","ROW_OUTER_HEIGHT","isBuyDirection","TradeHistoryUI","VirtualBody","containerRef","Row","tradeValue","closedPnl","buy","descriptionColor","TradeHistorySkeleton","TradeHistoryEmpty","TradeHistoryWidget","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","onExpire","secondsLeft","setSecondsLeft","remaining","Modal","ModalHeader","ModalBody","BreakdownSummary","ModalFooter","Button","breakdown","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","stepTitle","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.3.2\";\n}\n\nexport default \"0.3.2\";\n","/**\n * Configuration for {@link RateLimiter}.\n *\n * Defaults track Hyperliquid's documented `/info` budget (1200 weight\n * per minute per IP) and the per-type weight table reverse-engineered\n * from axiom.trade's deployed `hyperliquid-ts-sdk`. The defaults are\n * conservative — leaving the same headroom Axiom does — but every\n * field is overridable so consumers can tighten the budget under\n * shared egress IPs.\n */\nexport interface RateLimiterConfig {\n /** Total weight the bucket can spend per window. Default 1200. */\n capacity?: number;\n /** Window duration in milliseconds. Default 60_000 (1 minute). */\n windowMs?: number;\n}\n\nconst DEFAULT_CAPACITY = 1200;\nconst DEFAULT_WINDOW_MS = 60_000;\nconst MIN_WAIT_MS = 25;\n\n/**\n * Hyperliquid `/info` weight table mirrored from axiom.trade's\n * deployed `hyperliquid-ts-sdk` (see plan §1).\n *\n * Heavy endpoints (user-time-range / paginated) cost 20; metadata and\n * l2/recent endpoints cost 2; signed `/exchange` actions cost 1 per\n * request (HL bills writes against a separate, much smaller bucket).\n *\n * Unknown types fall back to `defaultWeight` (2). Callers can\n * customise via the override map passed to {@link RateLimiter}.\n */\nconst DEFAULT_INFO_WEIGHT = 2;\nconst HEAVY_INFO_WEIGHT = 20;\nconst EXCHANGE_WEIGHT = 1;\n\nconst HEAVY_INFO_TYPES = new Set<string>([\n \"userFills\",\n \"userFillsByTime\",\n \"userFunding\",\n \"userNonFundingLedgerUpdates\",\n \"frontendOpenOrders\",\n \"userRateLimit\",\n \"historicalOrders\",\n \"userTwapSliceFills\",\n \"predictedFundings\",\n]);\n\n/**\n * Resolve the bucket weight for a Hyperliquid `/info` `type`. Returns\n * 2 for unrecognised types so future HL endpoints are treated like the\n * cheaper bulk reads until a deliberate override pins them otherwise.\n */\nexport function weightForInfoType(type: string | undefined): number {\n if (!type) return DEFAULT_INFO_WEIGHT;\n return HEAVY_INFO_TYPES.has(type) ? HEAVY_INFO_WEIGHT : DEFAULT_INFO_WEIGHT;\n}\n\n/** Bucket weight charged for a signed `/exchange` action. */\nexport const EXCHANGE_REQUEST_WEIGHT = EXCHANGE_WEIGHT;\n\n/**\n * Browser-side token bucket aligned with HL's `/info` weight budget.\n *\n * Mirrors the `RateLimiter` in axiom.trade's deployed\n * `hyperliquid-ts-sdk` byte-for-byte: capacity 1200, refill once per\n * minute (not continuous), `waitForToken(weight)` blocks until the\n * next refill when the bucket is empty.\n *\n * Treat this as a process-wide singleton — all calls into the same\n * Hyperliquid REST client share one bucket so concurrent ticker /\n * order-form / portfolio components cooperate against the upstream\n * cap.\n */\nexport class RateLimiter {\n private readonly capacity: number;\n private readonly windowMs: number;\n\n private tokens: number;\n private lastRefill: number;\n\n constructor(config: RateLimiterConfig = {}) {\n this.capacity = config.capacity ?? DEFAULT_CAPACITY;\n this.windowMs = config.windowMs ?? DEFAULT_WINDOW_MS;\n this.tokens = this.capacity;\n this.lastRefill = Date.now();\n }\n\n /**\n * Reset the bucket to full capacity. Useful for tests; production\n * callers should not need this.\n */\n reset(): void {\n this.tokens = this.capacity;\n this.lastRefill = Date.now();\n }\n\n /**\n * Block until `weight` tokens are available, then deduct them and\n * resolve. Re-checks the refill boundary each pass so a long sleep\n * never spins past more than one window.\n */\n async waitForToken(weight: number): Promise<void> {\n const charge = Math.max(1, Math.floor(weight));\n while (true) {\n this.refill();\n if (this.tokens >= charge) {\n this.tokens -= charge;\n return;\n }\n const wait = Math.max(\n MIN_WAIT_MS,\n this.windowMs - (Date.now() - this.lastRefill),\n );\n await new Promise<void>((resolve) => setTimeout(resolve, wait));\n }\n }\n\n /**\n * Top up the bucket if a full window has elapsed since the last\n * refill. Mirrors axiom's discrete-window refill (vs continuous\n * refill) so the bucket never lets a request through that HL would\n * reject — the upstream weight counter snaps back at the same\n * boundary.\n */\n private refill(): void {\n const now = Date.now();\n if (now - this.lastRefill >= this.windowMs) {\n this.tokens = this.capacity;\n this.lastRefill = now;\n }\n }\n}\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 UniverseAssetEntry,\n UniverseSnapshot,\n} from \"../../types\";\nimport {\n EXCHANGE_REQUEST_WEIGHT,\n RateLimiter,\n type RateLimiterConfig,\n weightForInfoType,\n} from \"./RateLimiter\";\nimport {\n WebSocketManager,\n type OrderBookAggregation,\n} from \"./WebSocketManager\";\n\nexport type { OrderBookAggregation };\nexport { RateLimiter, type RateLimiterConfig, weightForInfoType };\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 * Outbound rate-limiter configuration. Defaults align with HL's\n * documented `/info` budget (1200 weight per minute per IP) and the\n * per-type weight table reverse-engineered from axiom.trade's\n * deployed hyperliquid-ts-sdk.\n *\n * Pass `false` to disable client-side rate limiting (e.g. when\n * a server-side proxy is already throttling on our behalf). Pass an\n * existing {@link RateLimiter} instance to share a bucket across\n * multiple client instances. Pass a partial config to tune capacity\n * / window for a custom IP egress topology.\n */\n rateLimit?: RateLimiter | RateLimiterConfig | false;\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 * Cache lifetime for the universe snapshot (`metaAndAssetCtxs`).\n *\n * Short — the snapshot carries live mark prices, funding, OI and 24h\n * volume, which all move on the seconds timescale. The role of this\n * cache is **not** to extend freshness past what consumers expect, but\n * to **collapse concurrent fan-outs** that happen during page mount:\n * when `useUniverseQuery`, `getPositions()` and `getOpenOrders()`\n * land within the same tick, a 1.5 s TTL guarantees they share one\n * `metaAndAssetCtxs` round-trip rather than racing to fire three.\n *\n * `webData2` updates the React Query cache for the universe directly,\n * so this client-side cache is purely a deduplication safety-net for\n * concurrent direct callers; it doesn't affect freshness for the WS\n * push path.\n */\nconst UNIVERSE_SNAPSHOT_TTL_MS = 1_500;\n\n/**\n * Cache lifetime for the per-user state snapshot (`clearinghouseState`\n * + `frontendOpenOrders`).\n *\n * Same role as {@link UNIVERSE_SNAPSHOT_TTL_MS}: collapse concurrent\n * fan-outs during page mount. `getPositions()` and `getOpenOrders()`\n * each fan out a `clearinghouseState` + a `frontendOpenOrders` leg,\n * so when both hooks mount in the same render tick the user can\n * watch them race to fire two of each. A short TTL on a combined\n * snapshot means the second fan-out reuses the first's payload — one\n * `clearinghouseState` and one `frontendOpenOrders` per user, even\n * with five symbol-scoped widgets on the page.\n *\n * `webData2` updates positions and openOrders React Query caches\n * directly, so this client-side cache is again only a safety-net\n * for the brief window before the WS push lands.\n */\nconst USER_STATE_SNAPSHOT_TTL_MS = 1_500;\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 * Process-local cache of the venue's universe snapshot. Concurrent\n * `getUniverseSnapshot()` callers within {@link UNIVERSE_SNAPSHOT_TTL_MS}\n * share the same parsed object (and the underlying\n * `metaAndAssetCtxs` HTTP call) instead of each firing their own.\n */\n private universeSnapshotCache: {\n fetchedAt: number;\n snapshot: UniverseSnapshot;\n } | null = null;\n /**\n * In-flight `getUniverseSnapshot` request, deduped via\n * singleflight semantics so concurrent fan-outs (e.g.\n * `useUniverseQuery` + `getPositions()` + `getOpenOrders()` mounted\n * in the same render tick) collapse onto a single network request.\n */\n private universeSnapshotPending: Promise<UniverseSnapshot> | null = null;\n\n /**\n * Process-local cache of per-user state snapshots\n * (`clearinghouseState` + `frontendOpenOrders`), keyed by lowercased\n * user address. Concurrent `getPositions(user)` / `getOpenOrders(user)`\n * callers within {@link USER_STATE_SNAPSHOT_TTL_MS} share the same\n * parsed object (and the underlying two HL round-trips) instead of\n * each firing their own pair.\n */\n private userStateCache: Map<\n string,\n {\n fetchedAt: number;\n snapshot: HyperliquidUserStateSnapshot;\n }\n > = new Map();\n /**\n * In-flight `getUserStateSnapshot` requests, deduped per user via\n * singleflight semantics. Keyed the same way as\n * {@link userStateCache}.\n */\n private userStatePending: Map<string, Promise<HyperliquidUserStateSnapshot>> =\n new Map();\n\n /**\n * Outbound rate limiter shared across every REST call this client\n * issues. `null` when explicitly disabled via\n * `config.rateLimit === false` — the request path then becomes a\n * straight fetch with no bucket bookkeeping.\n */\n private readonly rateLimiter: RateLimiter | null;\n\n /**\n * 构造 Hyperliquid 客户端\n *\n * @param config 客户端配置,不传则使用默认配置(testnet)\n */\n constructor(config: HyperliquidClientConfig = {}) {\n this.environment = config.environment || \"testnet\";\n\n this.apiEndpoint =\n config.apiEndpoint || HYPERLIQUID_ENDPOINTS[this.environment].api;\n\n this._wsEndpoint =\n config.wsEndpoint || HYPERLIQUID_ENDPOINTS[this.environment].ws;\n\n this.timeout = config.timeout || 30000;\n\n // Rate limiting is opt-out. By default, every client instance\n // gets a fresh 1200-weight/minute bucket aligned with HL's docs.\n // Hosts that share a bucket across multiple clients (e.g. a\n // multi-page app re-instantiating the client per route) can\n // pass an explicit RateLimiter and reuse it.\n if (config.rateLimit === false) {\n this.rateLimiter = null;\n } else if (config.rateLimit instanceof RateLimiter) {\n this.rateLimiter = config.rateLimit;\n } else {\n this.rateLimiter = new RateLimiter(config.rateLimit);\n }\n }\n\n /**\n * Compute the bucket weight to charge for a given endpoint + body.\n *\n * Mirrors axiom.trade's `hyperliquid-ts-sdk` weight table:\n * - `/info` payload `type` → see {@link weightForInfoType}\n * - `/exchange` (signed actions) → 1\n * - everything else → default 2 (matches HL's \"miscellaneous read\"\n * weight)\n */\n private weightFor(endpoint: string, body: any): number {\n if (endpoint.startsWith(\"/exchange\")) {\n return EXCHANGE_REQUEST_WEIGHT;\n }\n if (endpoint.startsWith(\"/info\")) {\n const t =\n body && typeof body === \"object\" && typeof body.type === \"string\"\n ? (body.type as string)\n : undefined;\n return weightForInfoType(t);\n }\n return weightForInfoType(undefined);\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 // Charge the bucket BEFORE dispatching the request. waitForToken\n // blocks when the bucket is empty so concurrent callers naturally\n // serialise against the upstream cap instead of all eating a 429.\n if (this.rateLimiter) {\n await this.rateLimiter.waitForToken(this.weightFor(endpoint, body));\n }\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 snap = await this.getUniverseSnapshot();\n return snap.assets.map((entry) => entry.symbol);\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 *\n * Backed by {@link getUniverseSnapshot} so this and `useMarketsQuery`\n * share the same single `metaAndAssetCtxs` round-trip — keeps the\n * legacy contract green while the SDK migrates to the universe\n * singleton.\n */\n async getMarkets(symbols?: string[]): Promise<MarketData[]> {\n const snap = await this.getUniverseSnapshot();\n if (symbols && symbols.length > 0) {\n const symbolSet = new Set(symbols);\n return snap.assets\n .map((entry) => entry.market)\n .filter((m) => symbolSet.has(m.symbol));\n }\n return snap.assets.map((entry) => entry.market);\n }\n\n /**\n * Snapshot the venue's full perp universe in a single network call.\n *\n * Mirrors axiom.trade's `SymbolConversion.refreshAssetMaps()` — one\n * `metaAndAssetCtxs` round-trip yields both the live market context\n * (price / funding / OI / 24h vol) AND the static metadata\n * (`szDecimals` / `maxLeverage`) for every coin. The SDK funnels every\n * per-symbol consumer (`useMarketQuery`, `useAssetMetaQuery`,\n * ticker bars, `getPositions()` / `getOpenOrders()` mark price\n * enrichment, ...) through this, so 100 components watching the\n * universe still trigger only one HL request per refresh cycle.\n *\n * Backed by a 1.5 s TTL + singleflight cache on the client instance,\n * so concurrent direct callers within the same tick collapse onto a\n * single in-flight request — the React Query layer above adds\n * another tier of dedup keyed by `staleTime`, but caching here too\n * keeps the contract correct for non-React callers and for\n * cross-method fan-outs (positions / orders / markets) that go\n * through `client.*` directly.\n *\n * @see {@link IPerpetualsClient.getUniverseSnapshot}\n */\n async getUniverseSnapshot(): Promise<UniverseSnapshot> {\n const now = Date.now();\n if (\n this.universeSnapshotCache &&\n now - this.universeSnapshotCache.fetchedAt < UNIVERSE_SNAPSHOT_TTL_MS\n ) {\n return this.universeSnapshotCache.snapshot;\n }\n if (this.universeSnapshotPending) {\n return this.universeSnapshotPending;\n }\n\n const fetchPromise = this.fetchUniverseSnapshot();\n this.universeSnapshotPending = fetchPromise;\n try {\n const snapshot = await fetchPromise;\n this.universeSnapshotCache = { fetchedAt: Date.now(), snapshot };\n return snapshot;\n } finally {\n // Clear regardless of outcome so a transient failure doesn't\n // pin every future caller to a rejected promise.\n this.universeSnapshotPending = null;\n }\n }\n\n /**\n * Internal: actually fetch and parse a fresh universe snapshot.\n * Always issues one `metaAndAssetCtxs` round-trip — call\n * {@link getUniverseSnapshot} (which guards this with TTL +\n * singleflight) instead of invoking directly.\n */\n private async fetchUniverseSnapshot(): Promise<UniverseSnapshot> {\n const [meta, assetCtxs] = await this.request<\n [\n {\n universe: Array<{\n name: string;\n szDecimals?: number;\n maxLeverage?: number;\n }>;\n },\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 const assets: UniverseAssetEntry[] = meta.universe.map((asset, index) => {\n const ctx = assetCtxs[index] ?? {};\n const symbol = `${asset.name}-USDC`;\n\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 const market: MarketData = {\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 };\n\n const assetMeta: AssetMeta | null =\n typeof asset.szDecimals === \"number\"\n ? { szDecimals: asset.szDecimals, maxLeverage: asset.maxLeverage }\n : null;\n\n return { coin: asset.name, symbol, market, meta: assetMeta };\n });\n\n const bySymbol = new Map<string, UniverseAssetEntry>();\n for (const entry of assets) {\n bySymbol.set(entry.symbol, entry);\n }\n\n return { assets, bySymbol, fetchedAt: Date.now() };\n }\n\n /**\n * Snapshot the user's full venue state (`clearinghouseState` +\n * `frontendOpenOrders`) in a single coordinated fetch, with an\n * instance-level TTL + singleflight cache.\n *\n * Why this exists: `getPositions()` and `getOpenOrders()` each\n * naturally fan out a `clearinghouseState` and a\n * `frontendOpenOrders` request to enrich their respective return\n * shapes. When `usePositionsQuery` and `useOrdersQuery` mount in\n * the same render tick, that's 2× CHS + 2× FOO over the wire, all\n * for the same user. Routing both through this snapshot collapses\n * the burst into a single pair of HL calls (per\n * {@link USER_STATE_SNAPSHOT_TTL_MS} window). When `webData2` is\n * online it overwrites the React Query caches directly, so this\n * REST path stops firing entirely after the first WS frame.\n *\n * `clearinghouseState` is mandatory; `frontendOpenOrders` is\n * fault-tolerant — the venue occasionally errors on the second leg\n * for fresh users, and we still want positions to render.\n */\n private async getUserStateSnapshot(\n userAddress: string,\n ): Promise<HyperliquidUserStateSnapshot> {\n const key = userAddress.toLowerCase();\n const now = Date.now();\n const cached = this.userStateCache.get(key);\n if (cached && now - cached.fetchedAt < USER_STATE_SNAPSHOT_TTL_MS) {\n return cached.snapshot;\n }\n const inflight = this.userStatePending.get(key);\n if (inflight) {\n return inflight;\n }\n\n const fetchPromise = (async (): Promise<HyperliquidUserStateSnapshot> => {\n const [clearinghouse, openOrders] = await Promise.all([\n this.request<HyperliquidClearinghouseState>(\"/info\", {\n type: \"clearinghouseState\",\n user: userAddress,\n }),\n this.request<HyperliquidOpenOrder[]>(\"/info\", {\n type: \"frontendOpenOrders\",\n user: userAddress,\n }).catch(() => undefined),\n ]);\n return { clearinghouse, openOrders, fetchedAt: Date.now() };\n })();\n\n this.userStatePending.set(key, fetchPromise);\n try {\n const snapshot = await fetchPromise;\n this.userStateCache.set(key, { fetchedAt: Date.now(), snapshot });\n return snapshot;\n } finally {\n // Clear regardless of outcome so a transient failure doesn't\n // pin every future caller to a rejected promise.\n this.userStatePending.delete(key);\n }\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 // Two snapshots, both backed by instance-level TTL + singleflight:\n // - userState: clearinghouseState + frontendOpenOrders (1 round-trip\n // each, shared with getOpenOrders if it lands in the same tick)\n // - universe : metaAndAssetCtxs for the live mark price\n // `Promise.all` keeps the slowest leg the overall latency budget.\n // First-paint render with `usePositionsQuery + useOrdersQuery`\n // mounted simultaneously now collapses to 1× CHS + 1× FOO + 1× MAC\n // (down from 2/2/3 previously) per ~1.5 s window.\n const [userState, universe] = await Promise.all([\n this.getUserStateSnapshot(params.userAddress),\n this.getUniverseSnapshot(),\n ]);\n\n const result = parseClearinghouseState(\n userState.clearinghouse,\n params.symbol,\n );\n const markByCoin = buildMarkPriceMapFromUniverse(universe);\n result.positions = enrichPositions(\n result.positions,\n userState.openOrders ?? [],\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 // We rely on `frontendOpenOrders` (not the bare `openOrders`) so\n // the payload includes `triggerPx`, `triggerCondition`,\n // `isTrigger` and the `children[]` array that bundles TP/SL with\n // their parent limit order. Axiom uses the same venue field, so\n // consuming it directly keeps our data shape identical to theirs.\n //\n // Both `frontendOpenOrders` and `clearinghouseState` are sourced\n // through {@link getUserStateSnapshot}, which the positions\n // fan-out also rides on — that means a same-tick mount of\n // `usePositionsQuery + useOrdersQuery` collapses to **one** pair\n // of CHS + FOO requests instead of two of each.\n //\n // The universe snapshot is again routed through\n // {@link getUniverseSnapshot} so it shares an in-flight\n // `metaAndAssetCtxs` request with positions / ticker bars /\n // useUniverseQuery during the same render tick.\n const [userState, universe] = await Promise.all([\n this.getUserStateSnapshot(params.userAddress).catch(() => null),\n this.getUniverseSnapshot().catch(() => undefined),\n ]);\n\n const openOrdersRaw = userState?.openOrders ?? [];\n const ctx: OpenOrderParseContext = {\n leverageByCoin: buildLeverageMap(userState?.clearinghouse),\n markByCoin: universe\n ? buildMarkPriceMapFromUniverse(universe)\n : undefined,\n };\n\n const orders = openOrdersRaw.map((o) => parseOpenOrder(o, ctx));\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: openOrdersRaw,\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 closedPnl?: 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 dir: fill.dir,\n closedPnl: parseFloat(fill.closedPnl || \"0\"),\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 * Combined per-user state snapshot shared by `getPositions()` and\n * `getOpenOrders()`. Holding both the venue's `clearinghouseState` and\n * `frontendOpenOrders` as a single value lets us cache them together\n * (one TTL, one singleflight) so two simultaneous fan-outs collapse\n * to a single pair of HL round-trips.\n *\n * `openOrders` is optional because Hyperliquid occasionally errors on\n * that leg for accounts that have never placed an order; callers\n * should treat `undefined` as \"no orders\" rather than as a fatal\n * failure for the snapshot.\n */\ninterface HyperliquidUserStateSnapshot {\n clearinghouse: HyperliquidClearinghouseState;\n openOrders: HyperliquidOpenOrder[] | undefined;\n fetchedAt: number;\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 /**\n * Bundled child orders, populated by `frontendOpenOrders` for\n * limit parents that were submitted via the `normalTpsl` grouping.\n * Each child carries `triggerPx` + `orderType` strings, which is the\n * venue's authoritative way to surface bundled TP/SL — no\n * cloid/oid heuristics required.\n */\n children?: HyperliquidOpenOrder[];\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, including the static metadata\n * (`szDecimals` + `maxLeverage`) so consumers can rebuild a\n * {@link UniverseSnapshot} without an extra REST round-trip.\n */\n meta?: {\n universe: Array<{\n name: string;\n szDecimals?: number;\n maxLeverage?: number;\n }>;\n };\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 prevDayPx?: 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 * Optional enrichment context passed to {@link parseOpenOrder}. Both\n * maps are sourced from data the venue surfaces alongside\n * `frontendOpenOrders` (clearinghouseState, metaAndAssetCtxs / webData2),\n * so consumers always have them when calling from the open-orders path.\n */\ninterface OpenOrderParseContext {\n /**\n * `coin → leverage value` derived from\n * `clearinghouseState.assetPositions[].position.leverage.value`.\n * Hyperliquid's order endpoints do not echo leverage per order, so\n * we look it up by coin (matching Axiom's behaviour). When the user\n * has no open position for the order's coin, leverage stays\n * `undefined` and the UI hides the chip.\n */\n leverageByCoin?: Map<string, number>;\n /**\n * `coin → live mark price` from `metaAndAssetCtxs` / webData2. Used\n * to populate the \"Current Price\" column without each row\n * subscribing individually.\n */\n markByCoin?: Map<string, number>;\n}\n\n/**\n * Extract bundled TP / SL trigger prices from a parent limit order's\n * `children` array. Hyperliquid's `frontendOpenOrders` populates\n * `children` directly when an order was submitted via the\n * `normalTpsl` grouping — the children's `orderType` string\n * unambiguously discriminates TP from SL, so no cloid / oid\n * heuristics are required.\n *\n * Returns `{}` for trigger orders themselves (their `children` is\n * always empty) and for limit orders without bundled exits.\n */\nfunction extractBundledTpSl(order: HyperliquidOpenOrder): {\n takeProfitPrice?: number;\n stopLossPrice?: number;\n} {\n if (!order.children || order.children.length === 0) return {};\n let tp: number | undefined;\n let sl: number | undefined;\n for (const child of order.children) {\n const orderTypeStr =\n typeof child.orderType === \"string\" ? child.orderType : \"\";\n const triggerPxStr = child.triggerPx;\n if (typeof triggerPxStr !== \"string\" || triggerPxStr.length === 0) continue;\n const px = parseFloat(triggerPxStr);\n if (!Number.isFinite(px) || px <= 0) continue;\n\n if (/take\\s*profit/i.test(orderTypeStr)) tp = px;\n else if (/stop/i.test(orderTypeStr)) sl = px;\n }\n return { takeProfitPrice: tp, stopLossPrice: sl };\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, `children`) and\n * the simpler `webData2.openOrders` push (boolean side, no trigger\n * metadata).\n *\n * Optional `ctx` injects per-coin leverage and mark price so the\n * resulting {@link Order} is self-contained for the Open Orders table.\n * When omitted (callers that only need the basic shape), those fields\n * stay `undefined`.\n */\nfunction parseOpenOrder(\n order: HyperliquidOpenOrder,\n ctx?: OpenOrderParseContext,\n): 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 const { takeProfitPrice, stopLossPrice } = extractBundledTpSl(order);\n const leverage = ctx?.leverageByCoin?.get(order.coin);\n const markPrice = ctx?.markByCoin?.get(order.coin);\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 leverage,\n reduceOnly: order.reduceOnly === true,\n isTrigger: isTrigger || undefined,\n triggerPx,\n triggerType,\n triggerCondition,\n markPrice,\n takeProfitPrice,\n stopLossPrice,\n };\n}\n\n/**\n * Build a `coin → leverage value` map from a clearinghouseState\n * payload. Mirrors Axiom's lookup: open orders don't carry leverage,\n * but each open position does, and the user is virtually always\n * looking at orders for a coin they also have a position on (or are\n * about to open one for).\n */\nfunction buildLeverageMap(\n data: HyperliquidClearinghouseState | undefined,\n): Map<string, number> {\n const map = new Map<string, number>();\n if (!data) return map;\n for (const ap of data.assetPositions ?? []) {\n const lev = ap.position?.leverage?.value;\n if (typeof lev === \"number\" && Number.isFinite(lev) && lev > 0) {\n map.set(ap.position.coin, lev);\n }\n }\n return map;\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 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 // Build the same maps for the open-orders enrichment so the live\n // table sees leverage/mark identical to what the REST `getOpenOrders`\n // call would return. Reusing the already-decoded clearinghouseState\n // / assetCtxs avoids a second request.\n const leverageByCoinMap = buildLeverageMap(clearinghouse);\n const openOrders = openOrdersRaw.map((o) =>\n parseOpenOrder(o, {\n leverageByCoin: leverageByCoinMap,\n markByCoin: markByCoin ?? undefined,\n }),\n );\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 // Build a universe snapshot from the embedded `meta` + `assetCtxs`\n // so consumers can keep `useUniverseQuery` fresh without an extra\n // `metaAndAssetCtxs` round-trip. We mirror the wire format produced\n // by `getUniverseSnapshot()` so downstream selectors stay agnostic\n // about whether the data came from REST or WS.\n const universe =\n raw.meta && raw.assetCtxs\n ? buildUniverseSnapshot(raw.meta, raw.assetCtxs, raw.serverTime)\n : undefined;\n\n // Surface leverage as a plain Record so the React Query cache stays\n // serialisable; consumers (e.g. useAccountStateSubscription) write\n // through into `useActiveAssetLeverageQuery` from this map. Pull the\n // explicit `type` (isolated/cross) directly off the clearinghouse\n // payload — leverageByCoinMap only carries the value.\n const leverageByCoin = clearinghouse\n ? buildLeverageRecord(clearinghouse)\n : undefined;\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 leverageByCoin,\n universe,\n raw,\n };\n}\n\n/**\n * Build a {@link UniverseSnapshot} from the `meta` + `assetCtxs` slices\n * Hyperliquid embeds in `webData2`.\n *\n * Mirrors {@link HyperliquidPerpetualsClient.getUniverseSnapshot} so\n * consumers can write either source into the same React Query cache\n * slot without introducing a venue→SDK shape divergence.\n */\nfunction buildUniverseSnapshot(\n meta: NonNullable<HyperliquidWebData2Payload[\"meta\"]>,\n assetCtxs: NonNullable<HyperliquidWebData2Payload[\"assetCtxs\"]>,\n serverTime?: number,\n): UniverseSnapshot {\n const assets: UniverseAssetEntry[] = meta.universe.map((asset, index) => {\n const ctx = assetCtxs[index] ?? {};\n const symbol = `${asset.name}-USDC`;\n const currentPrice = parseFloat(ctx.midPx || ctx.markPx || \"0\");\n const prevDayPx = (ctx as { prevDayPx?: string }).prevDayPx;\n const prevPrice = prevDayPx ? parseFloat(prevDayPx) : currentPrice;\n const change24h =\n prevPrice > 0 ? ((currentPrice - prevPrice) / prevPrice) * 100 : 0;\n\n const market: MarketData = {\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 };\n\n const szDecimals = (asset as { szDecimals?: number }).szDecimals;\n const maxLeverage = (asset as { maxLeverage?: number }).maxLeverage;\n const assetMeta: AssetMeta | null =\n typeof szDecimals === \"number\" ? { szDecimals, maxLeverage } : null;\n\n return { coin: asset.name, symbol, market, meta: assetMeta };\n });\n\n const bySymbol = new Map<string, UniverseAssetEntry>();\n for (const entry of assets) {\n bySymbol.set(entry.symbol, entry);\n }\n\n return {\n assets,\n bySymbol,\n fetchedAt: serverTime ?? Date.now(),\n };\n}\n\n/**\n * Build a `coin → { value, type }` Record from a clearinghouseState\n * payload. Used by {@link parseWebData2} to expose per-coin leverage\n * to consumers via {@link AccountState.leverageByCoin}.\n */\nfunction buildLeverageRecord(\n data: HyperliquidClearinghouseState,\n): Record<string, { value: number; type: \"isolated\" | \"cross\" }> {\n const out: Record<string, { value: number; type: \"isolated\" | \"cross\" }> = {};\n for (const ap of data.assetPositions ?? []) {\n const lev = ap.position?.leverage;\n if (!lev || typeof lev.value !== \"number\") continue;\n const type =\n lev.type === \"isolated\" || lev.type === \"cross\" ? lev.type : \"cross\";\n out[ap.position.coin] = { value: lev.value, type };\n }\n return out;\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 * Same shape as {@link buildMarkPriceMap} but sources its inputs from\n * a parsed {@link UniverseSnapshot}. Lets `getPositions()` /\n * `getOpenOrders()` reuse the already-decoded snapshot returned by\n * {@link HyperliquidPerpetualsClient.getUniverseSnapshot} instead of\n * issuing their own `metaAndAssetCtxs` round-trip.\n *\n * Mark price preference: `markPrice` (the venue's authoritative\n * value) → `price` (the mid/mark composite the snapshot computes for\n * display). Both fall back to 0 when the venue omits them, which we\n * filter out so the map only contains usable positive prices.\n */\nfunction buildMarkPriceMapFromUniverse(\n universe: UniverseSnapshot,\n): Map<string, number> {\n const map = new Map<string, number>();\n for (const entry of universe.assets) {\n const px =\n entry.market.markPrice && entry.market.markPrice > 0\n ? entry.market.markPrice\n : entry.market.price;\n if (Number.isFinite(px) && px > 0) {\n map.set(entry.coin, 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 UniverseAssetEntry,\n UniverseSnapshot,\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 /**\n * Snapshot the venue's full perp universe via a single `/v1/markets`\n * call.\n *\n * Hosts the SDK's `useUniverseQuery` global singleton — every\n * per-symbol consumer (ticker bars, market headers, asset meta\n * lookups, ...) derives from this so 100 components watching the\n * universe still trigger only one request per refresh cycle.\n *\n * `meta` stays `null` because the LiberFi backend does not yet\n * expose `szDecimals` / `maxLeverage`. Consumers that need that data\n * fall back to their own heuristics (the form already does this).\n */\n async getUniverseSnapshot(): Promise<UniverseSnapshot> {\n const markets = await this.getMarkets();\n const assets: UniverseAssetEntry[] = markets.map((market) => {\n const coin = market.symbol.split(\"-\")[0];\n return { coin, symbol: market.symbol, market, meta: null };\n });\n const bySymbol = new Map<string, UniverseAssetEntry>();\n for (const entry of assets) {\n bySymbol.set(entry.symbol, entry);\n }\n return { assets, bySymbol, fetchedAt: Date.now() };\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, type UseQueryOptions } from \"@tanstack/react-query\";\nimport type { IPerpetualsClient, UniverseSnapshot } from \"../types\";\nimport { usePerpetualsClient } from \"./usePerpetualsClient\";\n\n/**\n * Default polling cadence for the universe snapshot. Mirrors what we\n * observed on axiom.trade's perps page (`SymbolConversion.refreshIntervalMs\n * = 6e4`) — they refresh meta + asset contexts (mark price, funding rate,\n * open interest, 24h volume) once a minute and feed every per-symbol\n * consumer from that single global cache.\n *\n * 60s is well below the cadence at which Hyperliquid actually adjusts\n * the universe (listing additions / leverage caps move on a weekly\n * basis at most), but small enough that funding / OI numbers don't\n * drift visibly between updates.\n */\nconst DEFAULT_REFETCH_INTERVAL_MS = 60_000;\n\n/**\n * Stable React Query key for the global universe snapshot.\n *\n * The key is intentionally argument-free so every consumer in the\n * application reads from the same cache slot. Hooks like\n * {@link useMarketQuery}, {@link useMarketsQuery},\n * {@link useAssetMetaQuery} and ticker bars derive their data from\n * here via `select`, sharing one network round-trip per refresh cycle.\n */\nexport function universeQueryKey(): string[] {\n return [\"perps\", \"universe\"];\n}\n\n/**\n * Fetch the venue's universe snapshot through the active client.\n *\n * Throws when the active adapter doesn't implement\n * `getUniverseSnapshot` — callers should gate on\n * {@link supportsUniverseSnapshot} first or rely on\n * {@link useUniverseQuery}'s `enabled` guard, which checks the same\n * thing.\n */\nexport async function fetchUniverse(\n client: IPerpetualsClient,\n): Promise<UniverseSnapshot> {\n if (typeof client.getUniverseSnapshot !== \"function\") {\n throw new Error(\n \"useUniverseQuery: the active perpetuals client does not implement getUniverseSnapshot()\",\n );\n }\n return client.getUniverseSnapshot();\n}\n\n/**\n * Reports whether the active client can back {@link useUniverseQuery}.\n *\n * Adapters that omit `getUniverseSnapshot` (e.g. legacy LiberFi\n * deployments that still proxy market data per symbol) leave\n * `useUniverseQuery` disabled; consumers gracefully fall back to the\n * legacy per-symbol queries in that case.\n */\nexport function supportsUniverseSnapshot(client: IPerpetualsClient): boolean {\n return typeof client.getUniverseSnapshot === \"function\";\n}\n\n/**\n * Subscribe to the venue's universe snapshot.\n *\n * One global singleton: every {@link useUniverseQuery} call shares the\n * same `[\"perps\", \"universe\"]` cache slot, so React Query collapses\n * concurrent consumers onto a single in-flight request and a single\n * 60-second polling timer regardless of how many components mount.\n *\n * Per-symbol hooks (`useMarketQuery`, `useMarketsQuery`,\n * `useAssetMetaQuery`) read this cache via `select` so they don't\n * issue their own network requests — the cure for the N-ticker fan-out\n * pattern that triggers Hyperliquid 429s.\n *\n * The cache is also populated by `useAccountStateSubscription` when\n * `webData2` pushes meta / assetCtxs, so an active WebSocket session\n * keeps the universe fresh between polls without extra REST traffic.\n */\nexport function useUniverseQuery(\n options: Omit<\n UseQueryOptions<UniverseSnapshot, Error, UniverseSnapshot, string[]>,\n \"queryKey\" | \"queryFn\"\n > = {},\n) {\n const { client } = usePerpetualsClient();\n const enabled = supportsUniverseSnapshot(client) && options.enabled !== false;\n\n return useQuery({\n queryKey: universeQueryKey(),\n queryFn: () => fetchUniverse(client),\n refetchInterval: DEFAULT_REFETCH_INTERVAL_MS,\n // Treat the snapshot 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 ...options,\n enabled,\n });\n}\n","import { useQuery, type UseQueryOptions } from \"@tanstack/react-query\";\nimport type { IPerpetualsClient, MarketData, UniverseSnapshot } from \"../types\";\nimport { usePerpetualsClient } from \"./usePerpetualsClient\";\nimport {\n supportsUniverseSnapshot,\n universeQueryKey,\n fetchUniverse,\n} from \"./useUniverseQuery\";\n\nexport interface UseMarketQueryParams {\n symbol: string;\n}\n\n/**\n * Default polling cadence for the legacy per-symbol fallback. Used\n * only when the active adapter does not implement\n * `getUniverseSnapshot` — modern Hyperliquid / LiberFi paths derive\n * from {@link useUniverseQuery}'s 60s singleton instead.\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\n/**\n * Read the live market snapshot for `symbol`.\n *\n * When the active adapter exposes {@link IPerpetualsClient.getUniverseSnapshot}\n * (Hyperliquid + LiberFi today), this hook becomes a thin selector\n * over the global {@link useUniverseQuery} cache — every ticker /\n * header / order form in the page shares the same single 60s poll.\n * Otherwise we fall back to the legacy per-symbol REST query so older\n * deployments keep working unchanged.\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\n // Modern adapter path: derive from the universe singleton.\n const universeBacked = supportsUniverseSnapshot(client);\n const universeQuery = useQuery<\n UniverseSnapshot,\n Error,\n MarketData | null,\n string[]\n >({\n queryKey: universeQueryKey(),\n queryFn: () => fetchUniverse(client),\n refetchInterval: DEFAULT_REFETCH_INTERVAL_MS,\n staleTime: DEFAULT_REFETCH_INTERVAL_MS / 2,\n enabled: universeBacked && options.enabled !== false && !!params.symbol,\n select: (snap) => snap.bySymbol.get(params.symbol)?.market ?? null,\n });\n\n // Legacy fallback for adapters without a universe snapshot.\n const fallbackQuery = useQuery({\n queryKey: marketQueryKey(params),\n queryFn: async () => fetchMarket(client, params),\n staleTime: DEFAULT_REFETCH_INTERVAL_MS / 2,\n refetchInterval: DEFAULT_REFETCH_INTERVAL_MS,\n ...options,\n enabled: !universeBacked && options.enabled !== false && !!params.symbol,\n });\n\n return universeBacked ? universeQuery : fallbackQuery;\n}\n","import { useQuery, type UseQueryOptions } from \"@tanstack/react-query\";\nimport type { IPerpetualsClient, MarketData, UniverseSnapshot } from \"../types\";\nimport { usePerpetualsClient } from \"./usePerpetualsClient\";\nimport {\n supportsUniverseSnapshot,\n universeQueryKey,\n fetchUniverse,\n} from \"./useUniverseQuery\";\n\nexport interface UseMarketsQueryParams {\n symbols?: string[];\n}\n\n/**\n * Default polling cadence for the legacy fallback path — kept in sync\n * with {@link useUniverseQuery}'s singleton so user-visible refresh\n * cadence is identical regardless of which path is active.\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\n/**\n * Read live market snapshots for one or more symbols.\n *\n * When the active adapter exposes\n * {@link IPerpetualsClient.getUniverseSnapshot}, this is a derived\n * read over the global {@link useUniverseQuery} cache — a 100-ticker\n * bar still triggers only one HL `metaAndAssetCtxs` request per 60s.\n * Otherwise we fall back to the legacy `getMarkets()` REST poll.\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\n const universeBacked = supportsUniverseSnapshot(client);\n const universeQuery = useQuery<\n UniverseSnapshot,\n Error,\n MarketData[],\n string[]\n >({\n queryKey: universeQueryKey(),\n queryFn: () => fetchUniverse(client),\n refetchInterval: DEFAULT_REFETCH_INTERVAL_MS,\n staleTime: DEFAULT_REFETCH_INTERVAL_MS / 2,\n enabled: universeBacked && options.enabled !== false,\n select: (snap) => {\n if (!params.symbols || params.symbols.length === 0) {\n return snap.assets.map((a) => a.market);\n }\n const filter = new Set(params.symbols);\n return snap.assets\n .filter((a) => filter.has(a.symbol))\n .map((a) => a.market);\n },\n });\n\n const fallbackQuery = useQuery({\n queryKey: marketsQueryKey(params),\n queryFn: async () => fetchMarkets(client, params),\n staleTime: DEFAULT_REFETCH_INTERVAL_MS / 2,\n refetchInterval: DEFAULT_REFETCH_INTERVAL_MS,\n ...options,\n enabled: !universeBacked && options.enabled !== false,\n });\n\n return universeBacked ? universeQuery : fallbackQuery;\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\n/**\n * Canonical query key for the user's full positions snapshot. Always\n * keyed by `userAddress` only — per-symbol consumers derive a filtered\n * view via TanStack Query's `select` option so the entire app shares\n * one in-flight request per user, regardless of how many symbol-scoped\n * widgets are mounted (positions table + order form + position card +\n * ...).\n *\n * Backwards-compatibility: callers that previously passed a `symbol`\n * still get the same shape they expect (filtered positions), just\n * without firing an extra `clearinghouseState` / `frontendOpenOrders` /\n * `metaAndAssetCtxs` round-trip.\n */\nexport function positionsQueryKey(\n params: Omit<UsePositionsQueryParams, \"enabled\" | \"symbol\">,\n): string[] {\n return [\"perps\", \"positions\", params.userAddress ?? \"\"];\n}\n\nexport async function fetchPositions(\n client: IPerpetualsClient,\n params: GetPositionsParams,\n): Promise<GetPositionsResult> {\n return await client.getPositions(params);\n}\n\n/**\n * Filter the global positions snapshot down to a single symbol while\n * keeping the totals (`totalUnrealizedPnl`, `totalMarginUsed`, ...)\n * intact — those are user-level aggregates, not per-symbol.\n */\nfunction filterPositionsBySymbol(\n result: GetPositionsResult,\n symbol: string,\n): GetPositionsResult {\n return {\n ...result,\n positions: result.positions.filter((p) => p.symbol === symbol),\n };\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, userAddress, symbol } = params;\n\n // Single, user-level fetch — the per-symbol case is a pure derive.\n return useQuery<GetPositionsResult, Error, GetPositionsResult, string[]>({\n queryKey: positionsQueryKey({ userAddress }),\n queryFn: async () => fetchPositions(client, { userAddress }),\n enabled: enabled && !!userAddress,\n staleTime: 10 * 1000,\n select: symbol\n ? (data) => filterPositionsBySymbol(data, symbol)\n : undefined,\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\n/**\n * Canonical query key for the user's full open-orders snapshot. Like\n * {@link positionsQueryKey}, the symbol is intentionally absent from\n * the key — per-symbol callers derive a filtered view via `select`\n * so the entire app shares one in-flight `frontendOpenOrders` /\n * `clearinghouseState` / `metaAndAssetCtxs` fan-out per user.\n */\nexport function ordersQueryKey(\n params: Omit<UseOrdersQueryParams, \"enabled\" | \"symbol\">,\n): string[] {\n return [\"perps\", \"orders\", params.userAddress ?? \"\"];\n}\n\nexport async function fetchOrders(\n client: IPerpetualsClient,\n params: GetOpenOrdersParams,\n): Promise<GetOpenOrdersResult> {\n return await client.getOpenOrders(params);\n}\n\n/**\n * Filter the global orders snapshot down to a single symbol. Keeps\n * the raw payload intact for advanced consumers that may want the\n * unfiltered venue response (e.g. cross-coin bulk cancels).\n */\nfunction filterOrdersBySymbol(\n result: GetOpenOrdersResult,\n symbol: string,\n): GetOpenOrdersResult {\n const orders = result.orders.filter((o) => o.symbol === symbol);\n return {\n ...result,\n orders,\n totalCount: orders.length,\n };\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, userAddress, symbol } = params;\n\n return useQuery<GetOpenOrdersResult, Error, GetOpenOrdersResult, string[]>({\n queryKey: ordersQueryKey({ userAddress }),\n queryFn: async () => fetchOrders(client, { userAddress }),\n enabled: enabled && !!userAddress,\n staleTime: 5 * 1000,\n select: symbol ? (data) => filterOrdersBySymbol(data, symbol) : undefined,\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, type UseQueryOptions } from \"@tanstack/react-query\";\nimport type {\n AssetMeta,\n GetAssetMetaParams,\n IPerpetualsClient,\n UniverseSnapshot,\n} from \"../types\";\nimport { usePerpetualsClient } from \"./usePerpetualsClient\";\nimport {\n supportsUniverseSnapshot,\n universeQueryKey,\n fetchUniverse,\n} from \"./useUniverseQuery\";\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 * Refresh cadence for the legacy fallback path. Asset metadata is\n * stable on the timescale of weeks (listings / leverage caps) but the\n * universe singleton already polls every minute, so we keep the\n * fallback aligned to avoid surprising drift between the two paths.\n */\nconst DEFAULT_STALE_TIME_MS = 60_000;\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`.\n *\n * When the active adapter exposes `getUniverseSnapshot` (Hyperliquid +\n * LiberFi today), this is a derived read over the\n * {@link useUniverseQuery} cache — no extra `meta` round-trip is\n * issued per symbol. Otherwise we fall back to the legacy\n * `client.getAssetMeta(...)` call.\n *\n * The data is process-stable for minutes at a time, so the fallback\n * uses a 60s `staleTime`; consumers don't need to invalidate this on\n * user actions — the data is keyed on 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 const universeBacked = supportsUniverseSnapshot(client);\n const universeQuery = useQuery<\n UniverseSnapshot,\n Error,\n AssetMeta | null,\n string[]\n >({\n queryKey: universeQueryKey(),\n queryFn: () => fetchUniverse(client),\n refetchInterval: DEFAULT_STALE_TIME_MS,\n staleTime: DEFAULT_STALE_TIME_MS / 2,\n enabled: universeBacked && enabled && !!symbol,\n select: (snap) =>\n symbol ? (snap.bySymbol.get(symbol)?.meta ?? null) : null,\n });\n\n const fallbackQuery = useQuery({\n queryKey: assetMetaQueryKey({ symbol }),\n queryFn: async () => {\n if (!symbol) {\n throw new Error(\"useAssetMetaQuery: symbol is required\");\n }\n return fetchAssetMeta(client, { symbol });\n },\n enabled: !universeBacked && enabled && !!symbol,\n staleTime: DEFAULT_STALE_TIME_MS,\n ...options,\n });\n\n return universeBacked ? universeQuery : fallbackQuery;\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 { activeAssetLeverageQueryKey } from \"./useActiveAssetLeverageQuery\";\nimport { ordersQueryKey } from \"./useOrdersQuery\";\nimport { usePerpetualsClient } from \"./usePerpetualsClient\";\nimport { positionsQueryKey } from \"./usePositionsQuery\";\nimport { universeQueryKey } from \"./useUniverseQuery\";\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 // Positions: write through to the canonical user-level cache\n // slot. Per-symbol consumers derive a filtered view via\n // `usePositionsQuery({ userAddress, symbol })`'s `select`\n // option — they share the same cache entry and re-render\n // automatically on every push without a separate REST poll.\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 // Open orders: same write-through pattern — one cache slot per\n // user, per-symbol consumers derive via `select`.\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 // Universe write-through: when the venue's unified push embeds\n // the asset universe (Hyperliquid `webData2` carries `meta` +\n // `assetCtxs`), feed it straight into useUniverseQuery's cache.\n // A live WS session keeps the universe fresh between polls — the\n // 60s REST refresh from useUniverseQuery is only needed as a\n // backstop when the WS reconnects.\n if (state.universe) {\n queryClient.setQueryData(universeQueryKey(), state.universe);\n }\n\n // Per-asset leverage write-through: webData2 carries every\n // coin's leverage configuration on each push, so the place-order\n // form can read it from the same React Query cache without\n // issuing a per-(user,symbol) REST hit.\n if (state.leverageByCoin) {\n for (const [coin, lev] of Object.entries(state.leverageByCoin)) {\n queryClient.setQueryData(\n activeAssetLeverageQueryKey({\n userAddress,\n symbol: `${coin}-USDC`,\n }),\n lev,\n );\n }\n }\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","\"use client\";\n\nimport { useEffect } from \"react\";\nimport { useQueryClient } from \"@tanstack/react-query\";\nimport type { GetOpenOrdersResult, GetPositionsResult } from \"../types\";\nimport { accountStateQueryKey } from \"./useAccountStateQuery\";\nimport { ordersQueryKey } from \"./useOrdersQuery\";\nimport { usePerpetualsClient } from \"./usePerpetualsClient\";\nimport { positionsQueryKey } from \"./usePositionsQuery\";\n\nexport interface UseHyperliquidUserBootstrapParams {\n /**\n * Wallet address whose positions / open orders should be seeded.\n * The hook is a no-op when undefined or empty so it's safe to mount\n * before authentication completes.\n */\n userAddress?: string;\n /**\n * Disable the bootstrap entirely (useful for SSR). Defaults to true.\n */\n enabled?: boolean;\n /**\n * Grace period before falling back to REST. webData2's initial\n * snapshot typically lands within ~500ms; we wait a little longer\n * to cover slow WS handshakes / network blips before paying for a\n * REST round-trip. Defaults to 3 000 ms.\n */\n timeoutMs?: number;\n}\n\n/**\n * One-shot REST bootstrap for the user's perpetuals state.\n *\n * Mirrors axiom.trade's first-connect behaviour: when the page\n * mounts, the WS singleton (`useAccountStateSubscription`) is the\n * primary channel for positions / orders / spot balances, and any\n * subsequent updates are pushed via `webData2`. The first frame\n * usually arrives before any UI gating matters, but on slow WS\n * handshakes the place-order form can blink a \"loading\" state for\n * seconds.\n *\n * This hook covers that gap: after `timeoutMs` of inactivity it\n * issues exactly **one** REST round-trip (positions + open orders) to\n * seed the React Query cache, then stops. If `webData2`'s initial\n * snapshot has already populated the cache by the time the timer\n * fires, the fallback is skipped — keeping HL `/info` traffic at a\n * minimum even on cold pages.\n *\n * Mount this hook **once** at the same level as\n * `useAccountStateSubscription` (typically the perpetuals shell /\n * layout). Children read positions / orders through the existing\n * query hooks; nothing else needs to know the bootstrap exists.\n */\nexport function useHyperliquidUserBootstrap(\n params: UseHyperliquidUserBootstrapParams,\n): void {\n const { userAddress, enabled = true, timeoutMs = 3000 } = params;\n const { client } = usePerpetualsClient();\n const queryClient = useQueryClient();\n\n useEffect(() => {\n if (!enabled || !userAddress) return;\n\n let cancelled = false;\n const timer = setTimeout(() => {\n if (cancelled) return;\n\n // Skip the fallback when the WS subscription has already\n // primed the canonical accountState slot — that means\n // webData2's first frame landed inside the grace window and a\n // REST hit would be redundant.\n const primed = queryClient.getQueryData(\n accountStateQueryKey({ userAddress }),\n );\n if (primed) return;\n\n void (async () => {\n try {\n const [positions, orders] = await Promise.all([\n client.getPositions({ userAddress }),\n client.getOpenOrders({ userAddress }),\n ]);\n if (cancelled) return;\n\n // Write into the same cache slots `useAccountStateSubscription`\n // would populate, so per-symbol forms reading from\n // `usePositionsQuery({ userAddress, symbol })` see the data\n // immediately. We do NOT touch the accountState slot\n // (positions + orders alone can't reconstruct it) — the WS\n // push is the canonical source for that.\n queryClient.setQueryData<GetPositionsResult>(\n positionsQueryKey({ userAddress }),\n positions,\n );\n queryClient.setQueryData<GetOpenOrdersResult>(\n ordersQueryKey({ userAddress }),\n orders,\n );\n } catch (err) {\n // Bootstrap is best-effort — don't disrupt the page if it\n // fails, the WS subscription remains the source of truth.\n if (process.env.NODE_ENV !== \"production\") {\n console.warn(\n \"[useHyperliquidUserBootstrap] fallback REST failed:\",\n err,\n );\n }\n }\n })();\n }, timeoutMs);\n\n return () => {\n cancelled = true;\n clearTimeout(timer);\n };\n }, [client, queryClient, userAddress, enabled, timeoutMs]);\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","import { useTranslation } from \"@liberfi.io/i18n\";\n\nexport function CoinInfoNotFoundUI() {\n const { t } = useTranslation();\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 {t(\"perpetuals.coinInfo.notAvailable\")}\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 { useTranslation } from \"@liberfi.io/i18n\";\nimport { 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 { t } = useTranslation();\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 {t(\"perpetuals.coinInfo.oraclePrice\")}\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 {t(\"perpetuals.coinInfo.volume24h\")}\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 {t(\"perpetuals.coinInfo.openInterest\")}\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 {t(\"perpetuals.coinInfo.funding\")}\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 { useTranslation } from \"@liberfi.io/i18n\";\nimport { 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 const { t } = useTranslation();\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={t(\"perpetuals.searchCoins.placeholder\")}\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 {t(\"perpetuals.searchCoins.col.token\")}\n </span>\n <span\n style={{\n flex: \"0 0 100px\",\n fontSize: 12,\n color: \"#6b6b6b\",\n textAlign: \"right\",\n }}\n >\n {t(\"perpetuals.searchCoins.col.lastPrice\")}\n </span>\n <span\n style={{\n flex: \"0 0 120px\",\n fontSize: 12,\n color: \"#6b6b6b\",\n textAlign: \"right\",\n }}\n >\n {t(\"perpetuals.searchCoins.col.change24h\")}\n </span>\n <span\n style={{\n flex: \"0 0 100px\",\n fontSize: 12,\n color: \"#6b6b6b\",\n textAlign: \"right\",\n }}\n >\n {t(\"perpetuals.searchCoins.col.funding8h\")}\n </span>\n <span\n style={{\n flex: \"0 0 100px\",\n fontSize: 12,\n color: \"#6b6b6b\",\n textAlign: \"right\",\n }}\n >\n {t(\"perpetuals.searchCoins.col.volume24h\")}\n </span>\n <span\n style={{\n flex: \"1\",\n fontSize: 12,\n color: \"#6b6b6b\",\n textAlign: \"right\",\n }}\n >\n {t(\"perpetuals.searchCoins.col.openInterest\")}\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\" }}>\n {t(\"perpetuals.searchCoins.loading\")}\n </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\n ? t(\"perpetuals.searchCoins.noCoins\")\n : t(\"perpetuals.searchCoins.noCoinsAvailable\")}\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 { useTranslation } from \"@liberfi.io/i18n\";\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 { t } = useTranslation();\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}>\n {t(\"perpetuals.orderbook.spread\")}\n </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 { t } = useTranslation();\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 {t(\"perpetuals.orderbook.col.price\")}\n </div>\n <div\n className=\"flex items-center justify-end\"\n style={HEADER_CELL_STYLE}\n >\n {t(\"perpetuals.orderbook.col.amount\")}\n </div>\n <div\n className=\"flex items-center justify-end\"\n style={HEADER_CELL_STYLE}\n >\n {t(\"perpetuals.orderbook.col.total\")}\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 { useTranslation } from \"@liberfi.io/i18n\";\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 SkeletonHeader() {\n const { t } = useTranslation();\n return (\n <div className=\"flex items-center flex-none\" style={SKEL_HEADER_STYLE}>\n <div className=\"flex items-center\" style={SKEL_HEADER_CELL_STYLE}>\n {t(\"perpetuals.orderbook.col.price\")}\n </div>\n <div\n className=\"flex items-center justify-end\"\n style={SKEL_HEADER_CELL_STYLE}\n >\n {t(\"perpetuals.orderbook.col.amount\")}\n </div>\n <div\n className=\"flex items-center justify-end\"\n style={SKEL_HEADER_CELL_STYLE}\n >\n {t(\"perpetuals.orderbook.col.total\")}\n </div>\n </div>\n );\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 <SkeletonHeader />\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 const { t } = useTranslation();\n return (\n <div className=\"flex items-center justify-center h-full\">\n <span className=\"text-neutral-400 text-sm\">\n {t(\"perpetuals.orderbook.empty\")}\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 { useTranslation } from \"@liberfi.io/i18n\";\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 const { t } = useTranslation();\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}>{t(\"perpetuals.trades.col.price\")}</div>\n <div style={HEADER_SIZE_CELL}>{t(\"perpetuals.trades.col.size\")}</div>\n <div style={HEADER_AGE_CELL}>{t(\"perpetuals.trades.col.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 { useTranslation } from \"@liberfi.io/i18n\";\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 TradesSkeletonHeader() {\n const { t } = useTranslation();\n return (\n <div className=\"flex items-center flex-none\" style={SKEL_HEADER_STYLE}>\n <div style={SKEL_HEADER_PRICE_CELL}>\n {t(\"perpetuals.trades.col.price\")}\n </div>\n <div style={SKEL_HEADER_SIZE_CELL}>{t(\"perpetuals.trades.col.size\")}</div>\n <div style={SKEL_HEADER_AGE_CELL}>{t(\"perpetuals.trades.col.age\")}</div>\n </div>\n );\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 <TradesSkeletonHeader />\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 const { t } = useTranslation();\n return (\n <div className=\"flex items-center justify-center h-full\">\n <span className=\"text-neutral-400 text-sm\">\n {t(\"perpetuals.trades.empty\")}\n </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 /** Raw venue mark price, unaffected by user's limit price input. */\n marketPrice: 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 marketPrice = marketData?.price || 0;\n\n const currentPrice = useMemo(() => {\n if (orderType === \"limit\" && price) {\n return price;\n }\n return marketPrice;\n }, [orderType, price, marketPrice]);\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 marketPrice,\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 { useTranslation } from \"@liberfi.io/i18n\";\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 /** Raw venue mark price for display reference (unaffected by limit price input). */\n marketPrice?: 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 const { t } = useTranslation();\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 {t(\"perpetuals.placeOrder.leverage.title\")}\n </h3>\n <button\n type=\"button\"\n onClick={onClose}\n disabled={pending}\n aria-label={t(\"common.cancel\")}\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 {t(\"perpetuals.placeOrder.leverage.cannotUpdate\", {\n symbol: coinName,\n })}\n </p>\n ) : (\n <p className=\"text-[13px] text-zinc-400 leading-[18px] m-0\">\n {t(\"perpetuals.placeOrder.leverage.desc\")}\n </p>\n )}\n {hasOpenOrders && (\n <p\n className=\"text-[13px] leading-[18px] m-0\"\n style={{ color: BRAND_DANGER }}\n >\n {t(\"perpetuals.placeOrder.leverage.ordersAffected\", {\n symbol: coinName,\n })}\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 {t(\"perpetuals.placeOrder.leverage.label\")} {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 ? t(\"perpetuals.placeOrder.leverage.failed\")\n : pending\n ? t(\"perpetuals.placeOrder.leverage.updating\")\n : t(\"perpetuals.placeOrder.leverage.update\")}\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 { t } = useTranslation();\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={t(\"perpetuals.placeOrder.buyAmount\")}\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 * Plain controlled input for the limit price field. Uses the same\n * pattern as `BuyAmountInput` — own string state, keystroke-level\n * sync to RHF — to avoid HeroUI NumberField's blur-only commit\n * which clobbers mid-typing text and feeds back into `currentPrice`.\n */\nfunction LimitPriceInput({\n methods,\n placeholder,\n}: {\n methods: UseFormReturn<PlaceOrderFormData>;\n placeholder: string;\n}) {\n const formValue = methods.watch(\"price\");\n const numericValue =\n typeof formValue === \"number\" && Number.isFinite(formValue)\n ? formValue\n : undefined;\n\n const [inputText, setInputText] = useState<string>(() =>\n numericValue !== undefined ? String(numericValue) : \"\",\n );\n const inputRef = useRef<HTMLInputElement | null>(null);\n\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 methods.setValue(\"price\", 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(\"price\", parsed, {\n shouldValidate: false,\n shouldDirty: true,\n });\n },\n [methods],\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=\"price\"\n placeholder={placeholder}\n aria-label=\"Limit price\"\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 marketPrice,\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 { t } = useTranslation();\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 rawPrice = methods.watch(\"price\");\n const hasLimitPrice =\n typeof rawPrice === \"number\" && Number.isFinite(rawPrice) && rawPrice > 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: t(\"perpetuals.placeOrder.btn.addFunds\"),\n kind: \"deposit\",\n disabled: !onAddFunds,\n };\n }\n if (!hasAmount) {\n return {\n label: t(\"perpetuals.placeOrder.err.invalidAmount\"),\n kind: \"invalid\",\n disabled: true,\n };\n }\n if (amount < minMarginUsdc) {\n return {\n label: t(\"perpetuals.placeOrder.err.tooSmall\"),\n kind: \"invalid\",\n disabled: true,\n };\n }\n if (orderType === \"limit\" && !hasLimitPrice) {\n return {\n label: t(\"perpetuals.placeOrder.err.invalidLimit\"),\n kind: \"invalid\",\n disabled: true,\n };\n }\n return {\n label: `${t(side === \"long\" ? \"perpetuals.placeOrder.long\" : \"perpetuals.placeOrder.short\")} ${tokenSymbol}-USD`,\n kind: \"submit\",\n disabled: isSubmitting,\n };\n }, [\n availableMargin,\n hasAmount,\n amount,\n minMarginUsdc,\n orderType,\n hasLimitPrice,\n side,\n tokenSymbol,\n isSubmitting,\n onAddFunds,\n t,\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={t(\"perpetuals.placeOrder.tooltip.long\")}\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 {t(\"perpetuals.placeOrder.long\")}\n </button>\n </StyledTooltip>\n <StyledTooltip\n content={t(\"perpetuals.placeOrder.tooltip.short\")}\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 {t(\"perpetuals.placeOrder.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 {\n key: \"market\" as const,\n label: t(\"perpetuals.placeOrder.market\"),\n },\n {\n key: \"limit\" as const,\n label: t(\"perpetuals.placeOrder.limit\"),\n },\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>{t(\"perpetuals.placeOrder.leverage.label\")}</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 {/* 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 {t(\"perpetuals.placeOrder.buyAmount\")}\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 {/* Limit price input — placed below the slider so the user\n sizes their margin first, then sets the price target.\n The right-side label shows the live mark price for\n reference; the placeholder mirrors it so an empty field\n communicates \"current price\". Both update in real-time\n as the mark price streams in. */}\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\" }}>\n {t(\"perpetuals.placeOrder.limitPrice\")}\n </span>\n <span style={{ fontSize: 12, color: \"#6b6b6b\" }}>\n {marketPrice && marketPrice > 0\n ? t(\"perpetuals.placeOrder.currentPrice\", {\n price: formatLiqPrice(marketPrice),\n })\n : \"--\"}\n </span>\n </div>\n <LimitPriceInput\n methods={methods}\n placeholder={\n marketPrice && marketPrice > 0\n ? formatLiqPrice(marketPrice)\n : \"$0.0\"\n }\n />\n </div>\n )}\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 {t(\"perpetuals.placeOrder.tpsl\")}\n </span>\n </div>\n <div style={{ fontSize: 12, color: \"#6b6b6b\" }}>\n <span>{t(\"perpetuals.placeOrder.estLiqPrice\")} </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 {t(\"perpetuals.placeOrder.tpPrice\")}\n </span>\n <TpSlInput\n methods={methods}\n field=\"takeProfitPrice\"\n placeholder={t(\"perpetuals.placeOrder.enterTpPrice\")}\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 {t(\"perpetuals.placeOrder.slPrice\")}\n </span>\n <TpSlInput\n methods={methods}\n field=\"stopLossPrice\"\n placeholder={t(\"perpetuals.placeOrder.enterSlPrice\")}\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\n ? t(\"perpetuals.placeOrder.btn.placing\")\n : 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\" }}>\n {t(\"perpetuals.placeOrder.availableMargin\")}\n </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\" }}>\n {t(\"perpetuals.placeOrder.perpsAccountValue\")}\n </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\" }}>\n {t(\"perpetuals.placeOrder.currentPosition\")}\n </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 `${t(currentPosition.side === \"long\" ? \"perpetuals.placeOrder.long\" : \"perpetuals.placeOrder.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\" }}>\n {t(\"perpetuals.placeOrder.poweredBy\")}\n </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 marketPrice,\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 marketPrice={marketPrice}\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 {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n type CSSProperties,\n} from \"react\";\nimport { useTranslation } from \"@liberfi.io/i18n\";\nimport { ModalContent, Spinner, StyledModal, XCloseIcon } from \"@liberfi.io/ui\";\nimport { useAuthCallback } from \"@liberfi.io/wallet-connector\";\nimport type { Position } from \"../../types\";\nimport type { CloseType } from \"./use-close-position\";\n\nconst BRAND_PRIMARY = \"#C7FF2E\";\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\nexport type ClosePositionModalProps = {\n isOpen: boolean;\n position: Position | null;\n closeType: CloseType;\n isSubmitting: boolean;\n onClose: () => void;\n onConfirm: (size: number, price?: number) => Promise<void>;\n};\n\nexport function ClosePositionModal({\n isOpen,\n position,\n closeType,\n isSubmitting,\n onClose,\n onConfirm,\n}: ClosePositionModalProps) {\n const { t } = useTranslation();\n\n const maxSize = position ? Math.abs(position.quantity) : 0;\n const maxSizeRaw = position?.quantityRaw ?? String(maxSize);\n const tokenSymbol = position?.symbol.split(\"-\")[0] ?? \"\";\n const isLong = position?.side === \"long\";\n const sideLabel = isLong\n ? t(\"perpetuals.positions.long\")\n : t(\"perpetuals.positions.short\");\n\n // Local input state\n const [sizeText, setSizeText] = useState(\"\");\n const [percentText, setPercentText] = useState(\"100\");\n const [priceText, setPriceText] = useState(\"\");\n const sizeRef = useRef<HTMLInputElement>(null);\n const percentRef = useRef<HTMLInputElement>(null);\n const priceRef = useRef<HTMLInputElement>(null);\n\n // Reset state when modal opens or position changes\n useEffect(() => {\n if (isOpen && position) {\n const qty = Math.abs(position.quantity);\n setSizeText(position.quantityRaw ?? String(qty));\n setPercentText(\"100\");\n setPriceText(\"\");\n }\n }, [isOpen, position]);\n\n const sizeNumeric = useMemo(() => {\n const v = parseFloat(sizeText);\n return Number.isFinite(v) && v > 0 ? v : 0;\n }, [sizeText]);\n\n const percentNumeric = useMemo(() => {\n const v = parseFloat(percentText);\n return Number.isFinite(v) ? Math.max(0, Math.min(100, v)) : 0;\n }, [percentText]);\n\n const sliderPercent = useMemo(() => {\n if (maxSize <= 0 || sizeNumeric <= 0) return 0;\n const pct = (sizeNumeric / maxSize) * 100;\n return Math.max(0, Math.min(100, pct));\n }, [sizeNumeric, maxSize]);\n\n // --- Handlers ---\n\n const handleSizeChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const cleaned = sanitiseAmountInput(e.target.value);\n const parsed = parseFloat(cleaned);\n if (Number.isFinite(parsed) && parsed > maxSize && maxSize > 0) {\n setSizeText(position?.quantityRaw ?? String(maxSize));\n setPercentText(\"100\");\n return;\n }\n setSizeText(cleaned);\n if (Number.isFinite(parsed) && maxSize > 0) {\n const pct = Math.round((parsed / maxSize) * 100);\n setPercentText(String(Math.min(100, pct)));\n } else if (cleaned === \"\" || cleaned === \".\") {\n setPercentText(\"0\");\n }\n },\n [maxSize, position?.quantityRaw],\n );\n\n const handleSizeBlur = useCallback(() => {\n const parsed = parseFloat(sizeText);\n if (!Number.isFinite(parsed) || parsed <= 0) {\n setSizeText(\"0\");\n setPercentText(\"0\");\n } else if (parsed > maxSize && maxSize > 0) {\n setSizeText(position?.quantityRaw ?? String(maxSize));\n setPercentText(\"100\");\n }\n }, [sizeText, maxSize, position?.quantityRaw]);\n\n const handlePercentChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const cleaned = sanitiseAmountInput(e.target.value);\n const parsed = parseFloat(cleaned);\n if (Number.isFinite(parsed) && parsed > 100) {\n setPercentText(\"100\");\n if (maxSize > 0) {\n setSizeText(position?.quantityRaw ?? String(maxSize));\n }\n return;\n }\n setPercentText(cleaned);\n if (Number.isFinite(parsed) && maxSize > 0) {\n const clamped = Math.max(0, Math.min(100, parsed));\n const newSize = maxSize * (clamped / 100);\n setSizeText(newSize > 0 ? String(Number(newSize.toPrecision(6))) : \"0\");\n } else if (cleaned === \"\" || cleaned === \".\") {\n setSizeText(\"0\");\n }\n },\n [maxSize, position?.quantityRaw],\n );\n\n const handlePercentBlur = useCallback(() => {\n const parsed = parseFloat(percentText);\n if (!Number.isFinite(parsed) || parsed < 0) {\n setPercentText(\"0\");\n setSizeText(\"0\");\n } else if (parsed > 100) {\n setPercentText(\"100\");\n if (maxSize > 0) {\n setSizeText(position?.quantityRaw ?? String(maxSize));\n }\n }\n }, [percentText, maxSize, position?.quantityRaw]);\n\n const handleSliderChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const pct = Number(e.target.value);\n setPercentText(String(pct));\n if (maxSize > 0) {\n const newSize = maxSize * (pct / 100);\n setSizeText(\n pct === 100\n ? (position?.quantityRaw ?? String(maxSize))\n : newSize > 0\n ? String(Number(newSize.toPrecision(6)))\n : \"0\",\n );\n }\n },\n [maxSize, position?.quantityRaw],\n );\n\n const handlePriceChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n setPriceText(sanitiseAmountInput(e.target.value));\n },\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 // Submit\n const isLimitMode = closeType === \"limit\";\n const priceNumeric = parseFloat(priceText);\n const hasValidPrice =\n isLimitMode && Number.isFinite(priceNumeric) && priceNumeric > 0;\n const canSubmit =\n sizeNumeric > 0 && (!isLimitMode || hasValidPrice) && !isSubmitting;\n\n const handleSubmit = useCallback(async () => {\n if (!canSubmit) return;\n await onConfirm(sizeNumeric, isLimitMode ? priceNumeric : undefined);\n }, [canSubmit, onConfirm, sizeNumeric, isLimitMode, priceNumeric]);\n\n const guardedSubmit = useAuthCallback(handleSubmit);\n\n // Title\n const title = isLimitMode\n ? t(\"perpetuals.positions.close.limitTitle\", {\n side: sideLabel,\n size: maxSizeRaw,\n symbol: tokenSymbol,\n })\n : t(\"perpetuals.positions.close.marketTitle\", {\n side: sideLabel,\n size: maxSizeRaw,\n symbol: tokenSymbol,\n });\n\n const description = isLimitMode\n ? t(\"perpetuals.positions.close.limitDesc\")\n : t(\"perpetuals.positions.close.marketDesc\");\n\n const confirmLabel = isLimitMode\n ? t(\"perpetuals.positions.close.confirmLimit\")\n : t(\"perpetuals.positions.close.confirmMarket\");\n\n const currentPriceDisplay =\n position?.markPrice && position.markPrice > 0\n ? String(position.markPrice)\n : \"\";\n\n return (\n <StyledModal\n isOpen={isOpen}\n onOpenChange={(next) => {\n if (isSubmitting) 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 */}\n <div className=\"flex items-center justify-between px-5 pt-5 pb-2\">\n <h3 className=\"text-sm font-semibold text-white m-0\">{title}</h3>\n <button\n type=\"button\"\n onClick={onClose}\n disabled={isSubmitting}\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-1 flex flex-col gap-4\">\n {/* Description */}\n <p className=\"text-[13px] text-zinc-400 leading-[18px] m-0\">\n {description}\n </p>\n\n {/* Limit Price (only in limit mode) */}\n {isLimitMode && (\n <div className=\"flex flex-col gap-1\">\n <span style={{ fontSize: 12, color: \"#6b6b6b\" }}>\n {t(\"perpetuals.positions.close.price\")}\n </span>\n <input\n ref={priceRef}\n type=\"text\"\n inputMode=\"decimal\"\n pattern=\"[0-9.]*\"\n autoComplete=\"off\"\n autoCorrect=\"off\"\n spellCheck={false}\n placeholder={\n currentPriceDisplay\n ? t(\"perpetuals.positions.close.currentPrice\", {\n price: currentPriceDisplay,\n })\n : \"0.0\"\n }\n value={priceText}\n onChange={handlePriceChange}\n onKeyDownCapture={handleKeyDownCapture}\n className=\"w-full bg-transparent outline-none\"\n style={{\n color: \"#ffffff\",\n fontSize: 14,\n height: 40,\n padding: \"0 12px\",\n border: \"1px solid rgba(39,39,42,0.8)\",\n borderRadius: 8,\n fontVariantNumeric: \"tabular-nums\",\n }}\n />\n </div>\n )}\n\n {/* Size + Percentage row */}\n <div className=\"flex flex-col gap-1\">\n <div className=\"flex items-center justify-between\">\n <span style={{ fontSize: 12, color: \"#6b6b6b\" }}>\n {t(\"perpetuals.positions.close.size\")}\n </span>\n <span style={{ fontSize: 12, color: \"#6b6b6b\" }}>%</span>\n </div>\n <div className=\"flex items-center gap-2\">\n {/* Size input */}\n <div\n className=\"flex items-center flex-1\"\n style={{\n border: \"1px solid rgba(39,39,42,0.8)\",\n borderRadius: 8,\n height: 40,\n padding: \"0 12px\",\n }}\n >\n <input\n ref={sizeRef}\n type=\"text\"\n inputMode=\"decimal\"\n pattern=\"[0-9.]*\"\n autoComplete=\"off\"\n autoCorrect=\"off\"\n spellCheck={false}\n value={sizeText}\n onChange={handleSizeChange}\n onBlur={handleSizeBlur}\n onKeyDownCapture={handleKeyDownCapture}\n className=\"flex-1 min-w-0 bg-transparent border-none outline-none\"\n style={{\n color: \"#ffffff\",\n fontSize: 14,\n fontVariantNumeric: \"tabular-nums\",\n padding: 0,\n }}\n />\n <span\n style={{\n fontSize: 12,\n color: \"#6b6b6b\",\n marginLeft: 8,\n flexShrink: 0,\n }}\n >\n $\n </span>\n </div>\n\n {/* Percentage input */}\n <div\n className=\"flex items-center\"\n style={{\n border: \"1px solid rgba(39,39,42,0.8)\",\n borderRadius: 8,\n height: 40,\n padding: \"0 12px\",\n width: 80,\n }}\n >\n <input\n ref={percentRef}\n type=\"text\"\n inputMode=\"decimal\"\n pattern=\"[0-9.]*\"\n autoComplete=\"off\"\n autoCorrect=\"off\"\n spellCheck={false}\n value={percentText}\n onChange={handlePercentChange}\n onBlur={handlePercentBlur}\n onKeyDownCapture={handleKeyDownCapture}\n className=\"flex-1 min-w-0 bg-transparent border-none outline-none text-right\"\n style={{\n color: \"#ffffff\",\n fontSize: 14,\n fontVariantNumeric: \"tabular-nums\",\n padding: 0,\n }}\n />\n <span\n style={{\n fontSize: 12,\n color: \"#6b6b6b\",\n marginLeft: 4,\n flexShrink: 0,\n }}\n >\n %\n </span>\n </div>\n </div>\n\n {/* Max size label */}\n <span style={{ fontSize: 12, color: \"#6b6b6b\", marginTop: 2 }}>\n {t(\"perpetuals.positions.close.maxSize\", {\n size: maxSizeRaw,\n symbol: tokenSymbol,\n })}\n </span>\n </div>\n\n {/* Slider */}\n <div>\n <style>{`\n .perp-close-slider { -webkit-appearance: none; appearance: none; background: transparent; cursor: pointer; width: 100%; height: 16px; --pct: 0%; --fill: ${BRAND_PRIMARY}; --track: rgba(39,39,42,0.8); }\n .perp-close-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-close-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-close-slider::-moz-range-track { height: 4px; border-radius: 2px; background: rgba(39,39,42,0.8); border: none; }\n .perp-close-slider::-moz-range-progress { height: 4px; border-radius: 2px; background: ${BRAND_PRIMARY}; }\n .perp-close-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-close-slider:disabled { cursor: not-allowed; opacity: 0.5; }\n `}</style>\n <input\n type=\"range\"\n value={Math.round(sliderPercent)}\n onChange={handleSliderChange}\n min={0}\n max={100}\n step={1}\n disabled={maxSize <= 0}\n className=\"perp-close-slider\"\n style={\n {\n [\"--pct\" as never]: `${Math.round(sliderPercent)}%`,\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 {/* Confirm button */}\n <button\n type=\"button\"\n onClick={() => void guardedSubmit()}\n disabled={!canSubmit}\n className=\"w-full transition-colors disabled:cursor-not-allowed flex items-center justify-center gap-2\"\n style={{\n marginTop: 4,\n height: 44,\n fontSize: 14,\n fontWeight: 600,\n color: \"#000000\",\n backgroundColor: canSubmit\n ? BRAND_PRIMARY\n : \"rgba(63,63,70,0.6)\",\n borderRadius: 9999,\n border: \"none\",\n cursor: canSubmit ? \"pointer\" : \"not-allowed\",\n opacity: canSubmit ? 1 : 0.9,\n }}\n >\n {isSubmitting && <Spinner size=\"sm\" color=\"current\" />}\n {isSubmitting ? \"Closing...\" : confirmLabel}\n </button>\n </div>\n </div>\n </ModalContent>\n </StyledModal>\n );\n}\n","import { useCallback, useState } from \"react\";\nimport { useMutation } from \"@tanstack/react-query\";\nimport { useAssetMetaQuery } from \"../../hooks/useAssetMetaQuery\";\nimport type {\n OrderType,\n Position,\n PlaceOrderRequest,\n PlaceOrderResult,\n} from \"../../types\";\n\nexport type CloseType = \"market\" | \"limit\";\n\nexport type UseClosePositionParams = {\n userAddress?: string;\n onCloseSuccess?: () => void;\n onCloseError?: (error: Error) => void;\n /**\n * Callback that signs + relays the close order directly to the venue.\n * Same contract as the place-order form's `onPlaceOrder` — the host\n * hook (e.g. `useHyperliquidPlaceOrder`) receives a full\n * {@link PlaceOrderRequest} with `size`, `refPrice`, `szDecimals`\n * already computed.\n */\n onPlaceOrder?: (request: PlaceOrderRequest) => Promise<PlaceOrderResult>;\n};\n\nexport type UseClosePositionResult = {\n isModalOpen: boolean;\n selectedPosition: Position | null;\n closeType: CloseType;\n isClosing: boolean;\n openMarketClose: (position: Position) => void;\n openLimitClose: (position: Position) => void;\n handleConfirm: (size: number, price?: number) => Promise<void>;\n closeModal: () => void;\n};\n\n/**\n * Hook that owns the close-position modal lifecycle:\n * - Which position is selected and which close type (market / limit)\n * - Submitting the close order via `onPlaceOrder` (direct venue relay)\n *\n * The UI layer (modal component) owns the size / percentage / price\n * input state — this hook only cares about the final confirmed values.\n */\nexport function useClosePosition({\n userAddress,\n onCloseSuccess,\n onCloseError,\n onPlaceOrder,\n}: UseClosePositionParams): UseClosePositionResult {\n const [isModalOpen, setIsModalOpen] = useState(false);\n const [selectedPosition, setSelectedPosition] = useState<Position | null>(\n null,\n );\n const [closeType, setCloseType] = useState<CloseType>(\"market\");\n\n const { data: assetMeta } = useAssetMetaQuery({\n symbol: selectedPosition?.symbol,\n });\n\n const { mutateAsync: submitClose, isPending: isClosing } = 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 close order\",\n );\n }\n return await onPlaceOrder(request);\n },\n onSuccess: () => {\n setIsModalOpen(false);\n setSelectedPosition(null);\n onCloseSuccess?.();\n },\n onError: (err) => {\n onCloseError?.(err);\n },\n });\n\n const openMarketClose = useCallback((position: Position) => {\n setSelectedPosition(position);\n setCloseType(\"market\");\n setIsModalOpen(true);\n }, []);\n\n const openLimitClose = useCallback((position: Position) => {\n setSelectedPosition(position);\n setCloseType(\"limit\");\n setIsModalOpen(true);\n }, []);\n\n const closeModal = useCallback(() => {\n if (isClosing) return;\n setIsModalOpen(false);\n setSelectedPosition(null);\n }, [isClosing]);\n\n const handleConfirm = useCallback(\n async (size: number, price?: number) => {\n if (!selectedPosition || !userAddress) {\n throw new Error(\"Position and user address are required\");\n }\n\n const closeSide: \"long\" | \"short\" =\n selectedPosition.side === \"long\" ? \"short\" : \"long\";\n const orderType: OrderType = closeType === \"limit\" ? \"limit\" : \"market\";\n const refPrice =\n selectedPosition.markPrice || selectedPosition.entryPrice;\n\n const szDecimals = assetMeta?.szDecimals ?? 5;\n\n await submitClose({\n symbol: selectedPosition.symbol,\n side: closeSide,\n orderType,\n amount: size * refPrice,\n price: orderType === \"limit\" ? price : undefined,\n leverage: selectedPosition.leverage,\n reduceOnly: true,\n userAddress,\n size,\n refPrice,\n szDecimals,\n });\n },\n [selectedPosition, userAddress, closeType, assetMeta, submitClose],\n );\n\n return {\n isModalOpen,\n selectedPosition,\n closeType,\n isClosing,\n openMarketClose,\n openLimitClose,\n handleConfirm,\n closeModal,\n };\n}\n","import { useCallback, useMemo, useState } from \"react\";\nimport { usePositionsQuery } from \"../../hooks/usePositionsQuery\";\nimport type { Position } from \"../../types\";\nimport type { PositionSortKey, SortDirection } from \"./positions.ui\";\nimport {\n useClosePosition,\n type UseClosePositionParams,\n type UseClosePositionResult,\n} from \"./use-close-position\";\n\nexport type UsePositionsScriptParams = {\n userAddress?: string;\n symbol?: string;\n onCloseSuccess?: () => void;\n onCloseError?: (error: Error) => void;\n onPlaceOrder?: UseClosePositionParams[\"onPlaceOrder\"];\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 /** Close-position modal lifecycle (market + limit). */\n closePosition: UseClosePositionResult;\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 onPlaceOrder,\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 closePosition = useClosePosition({\n userAddress,\n onCloseSuccess,\n onCloseError,\n onPlaceOrder,\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 return {\n positions: sortedPositions,\n isLoading,\n error,\n sortKey,\n sortDir,\n onSort,\n closePosition,\n };\n}\n","import type { CSSProperties, ReactNode } from \"react\";\nimport { cn } from \"@liberfi.io/ui\";\n\n// ---------------------------------------------------------------------------\n// Sort primitives\n// ---------------------------------------------------------------------------\n\n/**\n * Two-state sort direction. We deliberately do not model a \"no sort\"\n * state: when a user clicks a fresh column the table starts at `asc`\n * (or `desc` if that's the column's natural default) and toggles\n * between `asc` ↔ `desc` thereafter — mirroring Axiom's UX so users\n * never have to click three times to clear an accidental sort.\n */\nexport type SortDirection = \"asc\" | \"desc\";\n\n/**\n * Horizontal alignment for a header cell label. `start` is the default\n * (matches the body cell alignment); `center` is used by columns whose\n * body uses a `1fr auto 1fr` grid (e.g. TP/SL) so the label sits above\n * the centre divider; `end` is for right-aligned action columns.\n */\nexport type HeaderAlign = \"start\" | \"center\" | \"end\";\n\nconst ALIGN_TO_JUSTIFY: Record<HeaderAlign, string> = {\n start: \"justify-start\",\n center: \"justify-center\",\n end: \"justify-end\",\n};\n\n// ---------------------------------------------------------------------------\n// Row layout constants\n// ---------------------------------------------------------------------------\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 */\nexport const HEADER_ROW_STYLE: CSSProperties = {\n minHeight: 28,\n maxHeight: 28,\n};\n\n/**\n * Body row: 36px tall, fixed. Same rationale as\n * {@link HEADER_ROW_STYLE} — clamps via `min-height` / `max-height`\n * so flex-grow can't compress it.\n */\nexport const BODY_ROW_STYLE: CSSProperties = { minHeight: 36, maxHeight: 36 };\n\n/**\n * Zebra-stripe background for odd body rows (Positions / Open Orders /\n * Trade History), applied via inline `style` rather than a Tailwind\n * utility because:\n *\n * - Container backgrounds in this SDK's host pages are pure `#000000`\n * (e.g. PerpetualsPage's `<div style={{ backgroundColor: '#000' }}>`).\n * A `bg-default-100/30` token resolves to roughly `oklab(0.20 / 0.3)`,\n * which on `#000` blends back into near-black — the stripe looks\n * missing. We need a colour that's *visibly distinct from `#000`*,\n * not visibly distinct from the consumer's theme palette mid-grey.\n *\n * - White at 6 % opacity matches the \"table stripe\" treatment used by\n * OrderBook / market-trades hover (`hover:bg-white/5`), so the three\n * tables and the live streams agree on the visual language. We pick\n * 6 % rather than 4 % because Axiom's reference (`bg-primaryStroke/20`\n * ≈ rgba(34,36,45,0.2)) sits on their `rgb(6,7,11)` non-black wrapper\n * and produces only a ~3 % luminance step; on our `#000000` wrapper\n * a 4 % white needs another bump to read just as clearly to the eye.\n *\n * - Inline style sidesteps any Tailwind v4 + `USE_LOCAL_SDK=true`\n * class-purge edge cases when the consumer's `@source` glob doesn't\n * reach the SDK source. The other layout constants in this file\n * follow the same convention for the same reason.\n */\nexport const STRIPE_BG_STYLE: CSSProperties = {\n backgroundColor: \"rgba(255, 255, 255, 0.06)\",\n};\n\n// ---------------------------------------------------------------------------\n// Format helpers — shared across tables (positions, open orders, …)\n// ---------------------------------------------------------------------------\n\n/**\n * Adaptive USD price formatter — mirrors Axiom's per-magnitude\n * rounding so a $80,564 BTC mark and a $0.0007 memecoin mark both\n * render at a useful precision without over- or under-reporting.\n *\n * ≥ 10000 → 0 fraction digits + thousands separator (e.g. `$80,564`)\n * ≥ 1000 → 1 fraction digit + thousands separator (e.g. `$2,301.5`)\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 *\n * The 1000–10000 band gets 1 dp (instead of falling to 0 dp like the\n * 10k+ band) because mid-price assets such as ETH at $2,301.5 lose\n * meaningful precision at integer rounding — verified against Axiom's\n * Trade History column, which renders ETH fills as `$2,301.5`,\n * `$2,325.9`, etc.\n */\nexport function 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 >= 10000) dp = 0;\n else if (abs >= 1000) dp = 1;\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. */\nexport function 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 *\n * Round-to-zero special case: when `|n| < 0.005` (rounds to 0 at 2 dp)\n * the function returns `+$0` instead of `+$0.00` / `-$0.00`. Mirrors\n * Axiom's PnL column, where a closing fill that nets out near-zero\n * after fees shows as `+$0` rather than a misleading `-$0.00`.\n */\nexport function formatSignedUsd2(n: number): string {\n if (!Number.isFinite(n)) return \"--\";\n if (Math.abs(n) < 0.005) return \"+$0\";\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 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 */\nexport function formatPercentAbs(percent: number): string {\n if (!Number.isFinite(percent)) return \"--\";\n return Math.abs(percent).toFixed(2) + \"%\";\n}\n\n/**\n * Quantity / size string. Prefer the venue-supplied raw quantity to\n * preserve the exact precision (e.g. Hyperliquid's `pos.szi` may\n * carry trailing zeros that `parseFloat → toFixed` would erase).\n * Fall back to the parsed number with sensible defaults when the raw\n * is missing.\n */\nexport function 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 * Format a millisecond timestamp as `YYYY/M/D HH:mm:ss` (24h, locale\n * separator). Matches Axiom's open-orders Time column.\n *\n * Uses the user's local timezone by design — the visual cue beside an\n * order is always \"what wall-clock time did I place this\", not UTC.\n */\nexport function formatDateTime(timestamp: number | undefined): string {\n if (timestamp === undefined || !Number.isFinite(timestamp)) return \"--\";\n const d = new Date(timestamp);\n if (Number.isNaN(d.getTime())) return \"--\";\n const yyyy = d.getFullYear();\n const M = d.getMonth() + 1;\n const D = d.getDate();\n const hh = String(d.getHours()).padStart(2, \"0\");\n const mm = String(d.getMinutes()).padStart(2, \"0\");\n const ss = String(d.getSeconds()).padStart(2, \"0\");\n return `${yyyy}/${M}/${D} ${hh}:${mm}:${ss}`;\n}\n\n// ---------------------------------------------------------------------------\n// Header cell — generic over the sort-key type\n// ---------------------------------------------------------------------------\n\n/**\n * Props for {@link HeaderCell}. The `K` generic is the table's\n * sort-key string union, so each table can use its own typed keys\n * (`PositionSortKey`, `OpenOrderSortKey`, …) without colliding.\n */\nexport type HeaderCellProps<K extends string> = {\n /** Inline `style` carrying the column's flex / max-width rules. */\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?: K;\n activeSortKey?: K | null;\n sortDir?: SortDirection;\n onSort?: (key: K) => void;\n /** Horizontal alignment of the label. Defaults to `\"start\"`. */\n align?: HeaderAlign;\n};\n\n/**\n * One header cell.\n *\n * Sortable cells get `cursor-pointer` + a hover white tint, an\n * `↑`/`↓` glyph appended when active, and an accessible `<button>`\n * semantic so keyboard users can sort with Enter / Space.\n *\n * Static (non-sortable) cells render a plain `<div>` to keep the\n * accessibility tree clean.\n */\nexport function HeaderCell<K extends string>({\n style,\n children,\n sortKey,\n activeSortKey,\n sortDir,\n onSort,\n align = \"start\",\n}: HeaderCellProps<K>) {\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","import type { CSSProperties } from \"react\";\nimport { useTranslation } from \"@liberfi.io/i18n\";\nimport { cn, StyledTooltip } from \"@liberfi.io/ui\";\nimport type { Position } from \"../../types\";\nimport {\n BODY_ROW_STYLE,\n HEADER_ROW_STYLE,\n HeaderCell,\n STRIPE_BG_STYLE,\n formatPercentAbs,\n formatQuantity,\n formatSignedUsd2,\n formatUsd2,\n formatUsdPrice,\n type SortDirection,\n} from \"../_internal/table\";\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 };\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// 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 onMarketClose: (position: Position) => void;\n onLimitClose: (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 onMarketClose,\n onLimitClose,\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 onMarketClose={onMarketClose}\n onLimitClose={onLimitClose}\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 onMarketClose: (position: Position) => void;\n onLimitClose: (position: Position) => void;\n};\n\nfunction PositionRow({\n position,\n striped,\n isClosing,\n onMarketClose,\n onLimitClose,\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 style={striped ? STRIPE_BG_STYLE : undefined}>\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 — Market / Limit text links, each opens a confirm modal. */}\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={() => onMarketClose(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 <button\n type=\"button\"\n onClick={() => onLimitClose(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.limit\")}\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 { ClosePositionModal } from \"./close-position-modal.ui\";\nimport { usePositionsScript } from \"./positions.script\";\nimport { PositionsUI, PositionsSkeleton } from \"./positions.ui\";\nimport type { UseClosePositionParams } from \"./use-close-position\";\n\nexport type PositionsWidgetProps = {\n userAddress?: string;\n symbol?: string;\n onCloseSuccess?: () => void;\n onCloseError?: (error: Error) => void;\n onPlaceOrder?: UseClosePositionParams[\"onPlaceOrder\"];\n className?: string;\n};\n\n/**\n * Positions table widget. Owns no business logic — wires the\n * `usePositionsScript` data layer (sort + close-modal) to the\n * presentational `PositionsUI` and the `ClosePositionModal`. The host\n * page just provides the connected wallet address and (optionally) a\n * symbol filter; the widget handles everything else.\n */\nexport function PositionsWidget({\n userAddress,\n symbol,\n onCloseSuccess,\n onCloseError,\n onPlaceOrder,\n className,\n}: PositionsWidgetProps) {\n const { positions, isLoading, sortKey, sortDir, onSort, closePosition } =\n usePositionsScript({\n userAddress,\n symbol,\n onCloseSuccess,\n onCloseError,\n onPlaceOrder,\n });\n\n if (isLoading) {\n return (\n <div className={className}>\n <PositionsSkeleton />\n </div>\n );\n }\n\n return (\n <>\n <PositionsUI\n positions={positions}\n sortKey={sortKey}\n sortDir={sortDir}\n onSort={onSort}\n onMarketClose={closePosition.openMarketClose}\n onLimitClose={closePosition.openLimitClose}\n isClosing={closePosition.isClosing}\n className={className}\n />\n <ClosePositionModal\n isOpen={closePosition.isModalOpen}\n position={closePosition.selectedPosition}\n closeType={closePosition.closeType}\n isSubmitting={closePosition.isClosing}\n onClose={closePosition.closeModal}\n onConfirm={closePosition.handleConfirm}\n />\n </>\n );\n}\n","import { useCallback, useMemo, useRef, useState } from \"react\";\nimport { useCancelOrderMutation } from \"../../hooks/useCancelOrderMutation\";\nimport { useOrdersQuery } from \"../../hooks/useOrdersQuery\";\nimport type { CancelOrderParams, CancelOrderResult, Order } from \"../../types\";\nimport type { OpenOrderSortKey, SortDirection } from \"./open-orders.ui\";\n\n/**\n * Caller-provided cancel implementation for a single order. Mirrors\n * the `onPlaceOrder` IoC point on the place-order form: when supplied,\n * the script / widget delegates the actual signing + submit to the\n * host instead of routing through the active\n * `IPerpetualsClient.cancelOrder`.\n *\n * Hosts that talk directly to a venue from the browser (e.g. signing\n * Hyperliquid `cancel` actions with the user's wallet) inject this\n * to bypass the SDK's read-only `HyperliquidPerpetualsClient.cancelOrder`\n * stub. Hosts that proxy through perpetuals-server (LiberFi TEE) leave\n * it undefined and let the default path run.\n */\nexport type CancelOrderImpl = (\n params: CancelOrderParams,\n) => Promise<CancelOrderResult>;\n\n/**\n * Optional batch counterpart to {@link CancelOrderImpl}. When supplied,\n * `handleCancelAll` invokes this once with every leg, so direct-venue\n * hosts (Hyperliquid, Lighter, etc.) can issue a single signature\n * covering all cancels rather than prompting the user N times.\n *\n * When omitted, the script falls back to\n * `Promise.allSettled(orders.map(cancelOrder))` — correct behaviour\n * for backends like perpetuals-server that own the signature flow\n * (each leg is a no-op API call), but a UX trap when the host signs\n * locally because every leg will trigger a fresh wallet prompt.\n */\nexport type CancelOrdersImpl = (\n params: CancelOrderParams[],\n) => Promise<CancelOrderResult[]>;\n\nexport type UseOpenOrdersScriptParams = {\n userAddress?: string;\n symbol?: string;\n onCancelSuccess?: () => void;\n onCancelError?: (error: Error) => void;\n /**\n * Optional host-provided single-order cancel implementation. When\n * omitted, the script falls back to {@link useCancelOrderMutation}\n * which routes through the active client — appropriate for backends\n * that own the signature flow (e.g. LiberFi perpetuals-server). For\n * direct-venue setups (consumer holds the wallet keys), pass an\n * implementation that signs + relays the cancel itself.\n */\n cancelOrder?: CancelOrderImpl;\n /**\n * Optional host-provided batch cancel implementation. When supplied\n * it is used by `handleCancelAll` (and by single cancels too —\n * the script wraps the param into a 1-element array so the host\n * can keep one entry point). When omitted, batch cancels fan out to\n * the per-order path with `Promise.allSettled`.\n */\n cancelOrders?: CancelOrdersImpl;\n};\n\nexport type UseOpenOrdersScriptResult = {\n /** Orders already sorted by the active `sortKey` / `sortDir`. */\n orders: Order[];\n isLoading: boolean;\n error: Error | null;\n /** Active sort column. Default: `time` desc — newest first, like Axiom. */\n sortKey: OpenOrderSortKey | null;\n sortDir: SortDirection;\n /**\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 */\n onSort: (key: OpenOrderSortKey) => void;\n /** Cancel a single order by id. */\n handleCancelOrder: (order: Order) => Promise<void>;\n /**\n * Cancel every currently-loaded order. Resolves once every leg has\n * finished (success **or** failure — leg failures are reported via\n * `onCancelError` per-leg, but do not abort the batch). The widget's\n * confirmation dialog calls this only after the user explicitly\n * confirms — the script does not gate on a dialog itself.\n */\n handleCancelAll: () => Promise<void>;\n /**\n * `true` while *any* cancel mutation (single OR batch) is in flight.\n * Kept for backwards-compatibility with hosts that only need the\n * coarse-grained \"is anything cancelling?\" signal. New UI surfaces\n * (per-row spinners, header `Cancel All` spinner) should prefer\n * the more specific signals below — this flag is intentionally\n * **not** the recommended way to drive a row's spinner because it\n * would light up every row whenever any row is cancelling.\n */\n isCanceling: boolean;\n /**\n * Set of order ids currently being cancelled via the per-row path.\n * The UI uses this to render an inline spinner on the exact row(s)\n * the user clicked while leaving sibling rows untouched — clicks\n * on different rows can run concurrently, so a single boolean\n * would conflate them.\n *\n * Returned as a `ReadonlySet` so consumers can't accidentally\n * mutate the script's internal state. `Set` (not `Array`) keeps\n * `has(orderId)` O(1) for the row-render hot path.\n */\n cancelingOrderIds: ReadonlySet<string>;\n /**\n * `true` while a `Cancel All` batch is in flight (regardless of\n * whether the host injected a batch impl or we fanned out to\n * per-leg cancels). The UI uses this to swap the header's\n * `Cancel All` text for a spinner so the user gets feedback the\n * click was registered. Distinct from `cancelingOrderIds` so the\n * header spinner doesn't fire when only a single per-row cancel\n * is running, and vice versa.\n */\n isCancelingAll: boolean;\n};\n\n// ---------------------------------------------------------------------------\n// Sort helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Map a sort key to the comparable scalar for a given order. Returns\n * `null` for missing values so the comparator can rank them last\n * regardless of direction (the standard \"missing data goes to the\n * bottom\" UX convention).\n */\nfunction getSortValue(\n order: Order,\n key: OpenOrderSortKey,\n): number | string | null {\n switch (key) {\n case \"time\":\n return order.timestamp;\n case \"size\":\n return order.quantity;\n case \"asset\":\n return order.symbol.split(\"-\")[0];\n case \"direction\":\n // Sort `Long` before `Short` in `asc` (alpha), `Short` before\n // `Long` in `desc` — matches Axiom's behaviour where the\n // direction column is a string sort, not a \"buy intent first\"\n // semantic sort.\n return order.side;\n case \"type\":\n // Sort by the binary axis (limit/market) since the SDK collapses\n // trigger info there. Trigger orders thus group with their base\n // type, which is consistent with how the column displays.\n return order.orderType;\n case \"leverage\":\n return order.leverage ?? null;\n case \"orderValue\":\n // Trigger orders show `Market` (no notional value) — sort them\n // last regardless of direction by returning `null`. Same\n // convention as `liquidationPrice` in Positions.\n return order.isTrigger ? null : order.price * order.quantity;\n case \"executePrice\":\n return order.isTrigger ? null : order.price;\n case \"currentPrice\":\n return order.markPrice ?? null;\n }\n}\n\nfunction compareOrders(\n a: Order,\n b: Order,\n key: OpenOrderSortKey,\n dir: SortDirection,\n): number {\n const aVal = getSortValue(a, key);\n const bVal = getSortValue(b, key);\n\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 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 Open Orders table.\n *\n * Responsibilities:\n * - Read open orders via {@link useOrdersQuery}. The consumer's\n * `useAccountStateSubscription` keeps the cache live via the\n * `webData2` write-through path, which already enriches each\n * order with leverage / mark-price / bundled TP/SL — so we\n * deliberately do **not** subscribe to a per-order user-data\n * stream here. Doing so would clobber that enrichment.\n * - Own sort state (default `time ↓` — newest order first).\n * - Expose `handleCancelOrder` (single) and `handleCancelAll`\n * (batch) shims over `useCancelOrderMutation`.\n *\n * Cancel-all does not present a confirmation prompt itself — that\n * responsibility lives in the widget, which renders the dialog and\n * only calls `handleCancelAll()` after the user confirms. Keeping the\n * confirmation in the widget makes the script trivially testable\n * (deterministic mutation calls) and lets headless consumers skip the\n * dialog entirely.\n */\nexport function useOpenOrdersScript({\n userAddress,\n symbol,\n onCancelSuccess,\n onCancelError,\n cancelOrder: cancelOrderImpl,\n cancelOrders: cancelOrdersImpl,\n}: UseOpenOrdersScriptParams): UseOpenOrdersScriptResult {\n // Default sort: `Time ↓` — most recent order at the top.\n const [sortKey, setSortKey] = useState<OpenOrderSortKey | null>(\"time\");\n const [sortDir, setSortDir] = useState<SortDirection>(\"desc\");\n\n const onSort = useCallback((key: OpenOrderSortKey) => {\n setSortKey((currentKey) => {\n if (currentKey === key) {\n setSortDir((d) => (d === \"asc\" ? \"desc\" : \"asc\"));\n return currentKey;\n }\n setSortDir(\"asc\");\n return key;\n });\n }, []);\n\n const {\n data: ordersData,\n isLoading,\n error,\n } = useOrdersQuery({ userAddress, symbol }, { enabled: !!userAddress });\n\n // Track in-flight cancels at row granularity so per-row spinners\n // light up exactly on the row(s) the user clicked, not on every\n // row in the table. Concurrency is intentional — clicking cancel\n // on three rows in quick succession should fire three independent\n // requests, each with its own spinner.\n //\n // We expose a `Set` to consumers (O(1) `has(orderId)` for row\n // render). Internally we hold it in a ref so per-row updates\n // don't have to spread the previous `Set` on every change, then\n // bump a version counter to trigger React renders. This keeps\n // hot-path mutations cheap while preserving the immutable-snapshot\n // contract on the public API.\n const cancelingIdsRef = useRef<Set<string>>(new Set<string>());\n const [, setIdsVersion] = useState(0);\n const bumpIdsVersion = useCallback(() => setIdsVersion((v) => v + 1), []);\n const addCancelingId = useCallback(\n (id: string) => {\n cancelingIdsRef.current.add(id);\n bumpIdsVersion();\n },\n [bumpIdsVersion],\n );\n const removeCancelingId = useCallback(\n (id: string) => {\n cancelingIdsRef.current.delete(id);\n bumpIdsVersion();\n },\n [bumpIdsVersion],\n );\n\n // `Cancel All` runs as a single conceptual action even when it\n // fans out into per-leg cancels under the hood, so it gets its\n // own boolean. Drives the header button's spinner separately\n // from the per-row set above.\n const [batchPending, setBatchPending] = useState(false);\n\n // Default fallback mutation — used when the host does not inject\n // a `cancelOrder` impl. Routes through the active client, so\n // `LiberFiPerpetualsClient` (perpetuals-server proxy) works\n // out of the box; `HyperliquidPerpetualsClient` does not (its\n // cancel is a deliberate stub — host must inject to use it).\n const { mutateAsync: cancelOrderMutate, isPending: isFallbackPending } =\n useCancelOrderMutation({\n onSuccess: () => {\n onCancelSuccess?.();\n },\n onError: (err) => {\n onCancelError?.(err);\n },\n });\n\n // Single-order dispatcher. Preference order:\n // 1. Host-injected `cancelOrder` (per-leg impl)\n // 2. Host-injected `cancelOrders` of size 1 (batch impl reused —\n // lets hosts ship a single batch hook and have it cover both\n // paths without writing a single-order variant separately)\n // 3. Fallback to `useCancelOrderMutation` against the active client\n // Success/error callbacks are wired here for the injected paths\n // (the mutation hook owns them on the fallback path).\n const dispatchCancel = useCallback(\n async (params: CancelOrderParams): Promise<CancelOrderResult> => {\n if (cancelOrderImpl) {\n try {\n const result = await cancelOrderImpl(params);\n onCancelSuccess?.();\n return result;\n } catch (err) {\n onCancelError?.(err instanceof Error ? err : new Error(String(err)));\n throw err;\n }\n }\n if (cancelOrdersImpl) {\n try {\n const [result] = await cancelOrdersImpl([params]);\n if (!result) {\n throw new Error(\"cancelOrders returned no result\");\n }\n onCancelSuccess?.();\n return result;\n } catch (err) {\n onCancelError?.(err instanceof Error ? err : new Error(String(err)));\n throw err;\n }\n }\n return cancelOrderMutate(params);\n },\n [\n cancelOrderImpl,\n cancelOrdersImpl,\n cancelOrderMutate,\n onCancelSuccess,\n onCancelError,\n ],\n );\n\n const orders = useMemo(() => ordersData?.orders ?? [], [ordersData]);\n\n const sortedOrders = useMemo(() => {\n if (!sortKey) return orders;\n return [...orders].sort((a, b) => compareOrders(a, b, sortKey, sortDir));\n }, [orders, sortKey, sortDir]);\n\n const handleCancelOrder = useCallback(\n async (order: Order) => {\n if (!userAddress) {\n throw new Error(\"User address is required\");\n }\n addCancelingId(order.orderId);\n try {\n await dispatchCancel({\n orderId: order.orderId,\n symbol: order.symbol,\n userAddress,\n });\n } finally {\n // Remove regardless of outcome — error toasts surface\n // through `onCancelError`, the spinner doesn't need to\n // linger as a failure indicator.\n removeCancelingId(order.orderId);\n }\n },\n [userAddress, dispatchCancel, addCancelingId, removeCancelingId],\n );\n\n const handleCancelAll = useCallback(async () => {\n if (!userAddress) {\n throw new Error(\"User address is required\");\n }\n if (orders.length === 0) return;\n\n setBatchPending(true);\n try {\n const params = orders.map((o) => ({\n orderId: o.orderId,\n symbol: o.symbol,\n userAddress,\n }));\n\n // Prefer the batch impl when supplied — direct-venue hosts can\n // sign all legs in a single wallet prompt that way. The result\n // array index-matches `params`, so we still emit per-leg\n // success / error callbacks for the embedding UI.\n if (cancelOrdersImpl) {\n try {\n await cancelOrdersImpl(params);\n for (let i = 0; i < params.length; i++) onCancelSuccess?.();\n } catch (err) {\n // Whole-batch reject: surface once via onCancelError so\n // the host can toast a single failure instead of N noisy\n // duplicates.\n onCancelError?.(err instanceof Error ? err : new Error(String(err)));\n }\n return;\n }\n\n // Fallback: fan out to the per-order path. `Promise.allSettled`\n // (not `all`) so one rejected leg doesn't abort the rest;\n // per-leg outcomes are already reported through\n // `dispatchCancel`'s success / error callbacks.\n await Promise.allSettled(params.map((p) => dispatchCancel(p)));\n } finally {\n setBatchPending(false);\n }\n }, [\n userAddress,\n orders,\n cancelOrdersImpl,\n dispatchCancel,\n onCancelSuccess,\n onCancelError,\n ]);\n\n // Coarse \"anything cancelling?\" signal — kept for backwards\n // compat with hosts already wired to it. Internally we now have\n // finer-grained signals (`cancelingOrderIds` for rows, `batchPending`\n // for header) which the bundled UI prefers. ORs every source\n // together so neither path leaves the flag stuck.\n const isCanceling =\n cancelingIdsRef.current.size > 0 || batchPending || isFallbackPending;\n\n return {\n orders: sortedOrders,\n isLoading,\n error,\n sortKey,\n sortDir,\n onSort,\n handleCancelOrder,\n handleCancelAll,\n isCanceling,\n cancelingOrderIds: cancelingIdsRef.current,\n isCancelingAll: batchPending,\n };\n}\n","import type { CSSProperties } from \"react\";\nimport { useTranslation } from \"@liberfi.io/i18n\";\nimport { cn, Spinner, StyledTooltip } from \"@liberfi.io/ui\";\nimport type { Order } from \"../../types\";\nimport {\n BODY_ROW_STYLE,\n HEADER_ROW_STYLE,\n HeaderCell,\n STRIPE_BG_STYLE,\n formatDateTime,\n formatQuantity,\n formatUsd2,\n formatUsdPrice,\n type SortDirection,\n} from \"../_internal/table\";\n\n// ---------------------------------------------------------------------------\n// Sort\n// ---------------------------------------------------------------------------\n\n/**\n * Stable identifier for a sortable column. 9 of the 12 columns are\n * sortable; `triggerCondition`, `tpsl`, `cancel` 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 OpenOrderSortKey =\n | \"time\"\n | \"size\"\n | \"asset\"\n | \"direction\"\n | \"type\"\n | \"leverage\"\n | \"orderValue\"\n | \"executePrice\"\n | \"currentPrice\";\n\nexport type { SortDirection };\n\n// ---------------------------------------------------------------------------\n// Column layout\n// ---------------------------------------------------------------------------\n\n/**\n * Per-column inline styles. Mirrors Axiom's open-orders layout 1:1:\n * - 9 columns are clamped via `maxWidth` while still flex-growing\n * until they hit that cap (Axiom's `max-w-[Npx]` + `flex-1`).\n * - `triggerCondition` has **no `maxWidth`** so it absorbs leftover\n * row space when the panel is wider than the sum of fixed columns.\n *\n * Why inline (not Tailwind arbitrary classes): the same SDK-self-\n * containment reasoning as positions.ui — `USE_LOCAL_SDK=true` mode\n * skips the consumer's `node_modules` `@source` glob, dropping any\n * arbitrary-value classes emitted from the local source files.\n * Inline `style` always works.\n */\nconst COL_STYLE: Record<string, CSSProperties> = {\n time: { flex: \"1 1 0%\", maxWidth: 160 },\n size: { flex: \"1 1 0%\", maxWidth: 80 },\n asset: { flex: \"1 1 0%\", maxWidth: 70 },\n direction: { flex: \"1 1 0%\", maxWidth: 70 },\n type: { flex: \"1 1 0%\", maxWidth: 160 },\n leverage: { flex: \"1 1 0%\", maxWidth: 80 },\n orderValue: { flex: \"1 1 0%\", maxWidth: 100 },\n executePrice: { flex: \"1 1 0%\", maxWidth: 100 },\n currentPrice: { flex: \"1 1 0%\", maxWidth: 100 },\n triggerCondition: { flex: \"1 1 0%\" },\n tpsl: { flex: \"1 1 0%\", maxWidth: 120 },\n cancel: { flex: \"1 1 0%\", maxWidth: 70 },\n};\n\n/**\n * Min-width of the inner table body. Axiom uses 1100 — slightly less\n * than the sum of fixed column widths (1110px) so on a tight viewport\n * the `triggerCondition` column compresses first instead of forcing\n * horizontal scroll. Same effect for us.\n */\nconst TABLE_MIN_WIDTH: CSSProperties = { minWidth: 1100 };\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Reconstruct the venue's full order-type label from an {@link Order}.\n * The SDK collapses Hyperliquid's strings to the binary `limit | market`\n * axis to keep the type narrow, but the Open Orders table needs the\n * full \"Take Profit Market\" / \"Stop Limit\" / etc. text. The combination\n * of `isTrigger` + `triggerType` + `orderType` reproduces all six\n * variants Hyperliquid emits.\n */\nfunction describeOrderType(order: Order, market: string): string {\n const isLimit = order.orderType === \"limit\";\n if (!order.isTrigger) {\n return isLimit ? \"Limit\" : market;\n }\n if (order.triggerType === \"tp\") {\n return isLimit ? \"Take Profit Limit\" : \"Take Profit Market\";\n }\n if (order.triggerType === \"sl\") {\n return isLimit ? \"Stop Limit\" : \"Stop Market\";\n }\n // Trigger order with no explicit type discriminator: fall back to\n // the base limit/market label so the column never reads blank.\n return isLimit ? \"Limit\" : market;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\nexport type OpenOrdersUIProps = {\n /** Already-sorted orders. The script layer owns sort state. */\n orders: Order[];\n /** Currently active sort column, or `null` when no sort applied. */\n sortKey: OpenOrderSortKey | null;\n sortDir: SortDirection;\n onSort: (key: OpenOrderSortKey) => void;\n onCancelOrder: (order: Order) => void;\n onCancelAll: () => void;\n /**\n * Set of order ids currently being cancelled via the per-row path.\n * The row whose id is present in the set renders an inline spinner\n * in place of its `x` icon; sibling rows stay clickable so the\n * user can cancel several orders concurrently.\n */\n cancelingOrderIds: ReadonlySet<string>;\n /**\n * `true` while a `Cancel All` batch is in flight. Drives the\n * header button's spinner and gates *every* row's cancel button\n * (mid-batch, individual rows shouldn't accept new clicks).\n */\n isCancelingAll: boolean;\n /** Optional className for the outer container. */\n className?: string;\n};\n\nexport function OpenOrdersUI({\n orders,\n sortKey,\n sortDir,\n onSort,\n onCancelOrder,\n onCancelAll,\n cancelingOrderIds,\n isCancelingAll,\n className,\n}: OpenOrdersUIProps) {\n const { t } = useTranslation();\n const marketLabel = t(\"perpetuals.openOrders.market\");\n\n // Header is always rendered (even when empty) so the column legend\n // is visible while waiting for the first order. 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<OpenOrderSortKey>\n style={COL_STYLE.time}\n sortKey=\"time\"\n activeSortKey={sortKey}\n sortDir={sortDir}\n onSort={onSort}\n >\n {t(\"perpetuals.openOrders.col.time\")}\n </HeaderCell>\n <HeaderCell<OpenOrderSortKey>\n style={COL_STYLE.size}\n sortKey=\"size\"\n activeSortKey={sortKey}\n sortDir={sortDir}\n onSort={onSort}\n >\n {t(\"perpetuals.openOrders.col.size\")}\n </HeaderCell>\n <HeaderCell<OpenOrderSortKey>\n style={COL_STYLE.asset}\n sortKey=\"asset\"\n activeSortKey={sortKey}\n sortDir={sortDir}\n onSort={onSort}\n >\n {t(\"perpetuals.openOrders.col.asset\")}\n </HeaderCell>\n <HeaderCell<OpenOrderSortKey>\n style={COL_STYLE.direction}\n sortKey=\"direction\"\n activeSortKey={sortKey}\n sortDir={sortDir}\n onSort={onSort}\n >\n {t(\"perpetuals.openOrders.col.direction\")}\n </HeaderCell>\n <HeaderCell<OpenOrderSortKey>\n style={COL_STYLE.type}\n sortKey=\"type\"\n activeSortKey={sortKey}\n sortDir={sortDir}\n onSort={onSort}\n >\n {t(\"perpetuals.openOrders.col.type\")}\n </HeaderCell>\n <HeaderCell<OpenOrderSortKey>\n style={COL_STYLE.leverage}\n sortKey=\"leverage\"\n activeSortKey={sortKey}\n sortDir={sortDir}\n onSort={onSort}\n >\n <StyledTooltip\n content={t(\"perpetuals.openOrders.tooltip.leverage\")}\n placement=\"top\"\n delay={200}\n closeDelay={0}\n >\n <span className=\"border-b border-dashed border-default-500/40\">\n {t(\"perpetuals.openOrders.col.leverage\")}\n </span>\n </StyledTooltip>\n </HeaderCell>\n <HeaderCell<OpenOrderSortKey>\n style={COL_STYLE.orderValue}\n sortKey=\"orderValue\"\n activeSortKey={sortKey}\n sortDir={sortDir}\n onSort={onSort}\n >\n {t(\"perpetuals.openOrders.col.orderValue\")}\n </HeaderCell>\n <HeaderCell<OpenOrderSortKey>\n style={COL_STYLE.executePrice}\n sortKey=\"executePrice\"\n activeSortKey={sortKey}\n sortDir={sortDir}\n onSort={onSort}\n >\n {t(\"perpetuals.openOrders.col.executePrice\")}\n </HeaderCell>\n <HeaderCell<OpenOrderSortKey>\n style={COL_STYLE.currentPrice}\n sortKey=\"currentPrice\"\n activeSortKey={sortKey}\n sortDir={sortDir}\n onSort={onSort}\n >\n {t(\"perpetuals.openOrders.col.currentPrice\")}\n </HeaderCell>\n <HeaderCell<OpenOrderSortKey> style={COL_STYLE.triggerCondition}>\n {t(\"perpetuals.openOrders.col.triggerCondition\")}\n </HeaderCell>\n <HeaderCell<OpenOrderSortKey> style={COL_STYLE.tpsl} align=\"center\">\n {t(\"perpetuals.openOrders.col.tpsl\")}\n </HeaderCell>\n <div\n style={COL_STYLE.cancel}\n className=\"flex flex-row items-center justify-center\"\n >\n {/* `Cancel All` header trigger.\n - Strips the default browser focus ring and HeroUI's\n focus-visible outline so the button reads as a plain\n text link (matches Axiom). Tabbable users still see\n the underline shift via `hover:text-bearish/80`.\n - Spinner replaces the label while the batch is in flight\n (we keep the column width fixed via `min-w-[60px]` so\n the surrounding header doesn't reflow when the label\n swaps).\n - Disabled while the batch is running OR when there are\n no orders to cancel. We intentionally don't disable\n on per-row cancels — the user should still be able to\n kick off a `Cancel All` while an individual cancel is\n pending. */}\n <button\n type=\"button\"\n onClick={onCancelAll}\n disabled={isCancelingAll || orders.length === 0}\n className={cn(\n \"inline-flex min-w-[60px] items-center justify-center gap-1\",\n \"text-xs font-medium text-bearish\",\n \"cursor-pointer transition-colors duration-150\",\n \"hover:text-bearish/80 disabled:cursor-not-allowed disabled:opacity-50\",\n \"outline-none focus:outline-none focus-visible:outline-none\",\n \"focus:ring-0 focus-visible:ring-0\",\n )}\n >\n {isCancelingAll ? (\n <Spinner size=\"sm\" color=\"current\" />\n ) : (\n t(\"perpetuals.openOrders.col.cancelAll\")\n )}\n </button>\n </div>\n </div>\n );\n\n // Empty state: keep the header for layout context, render a centred\n // \"no orders\" line below.\n if (orders.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.openOrders.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 {orders.map((order, index) => (\n <OrderRow\n key={order.orderId}\n order={order}\n striped={index % 2 === 1}\n isThisRowCanceling={cancelingOrderIds.has(order.orderId)}\n isBatchCanceling={isCancelingAll}\n marketLabel={marketLabel}\n onCancel={onCancelOrder}\n />\n ))}\n </div>\n </div>\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Row\n// ---------------------------------------------------------------------------\n\ntype OrderRowProps = {\n order: Order;\n /** Zebra striping — every other row gets a faint background. */\n striped: boolean;\n /**\n * `true` while this *specific* row's per-row cancel is in flight.\n * Triggers the inline spinner that replaces the row's `x` glyph\n * and disables the row's button.\n */\n isThisRowCanceling: boolean;\n /**\n * `true` while a `Cancel All` batch is running. Disables the\n * row's cancel button (so individual rows don't fire a second\n * request mid-batch) but does **not** show a spinner here —\n * that lives in the header. Sibling rows might individually\n * resolve at different times during the batch, so we still\n * want the per-row spinner story (above) for those.\n */\n isBatchCanceling: boolean;\n marketLabel: string;\n onCancel: (order: Order) => void;\n};\n\nfunction OrderRow({\n order,\n striped,\n isThisRowCanceling,\n isBatchCanceling,\n marketLabel,\n onCancel,\n}: OrderRowProps) {\n const { t } = useTranslation();\n const tokenSymbol = order.symbol.split(\"-\")[0];\n const isLong = order.side === \"long\";\n const directionLabel = isLong\n ? t(\"perpetuals.openOrders.long\")\n : t(\"perpetuals.openOrders.short\");\n const directionColor = isLong ? \"text-bullish\" : \"text-bearish\";\n\n const typeLabel = describeOrderType(order, marketLabel);\n\n // Trigger orders show \"Market\" for both notional and execute price\n // (the venue settles them at the prevailing mark when triggered);\n // limit orders show numeric values.\n const orderValueText = order.isTrigger\n ? marketLabel\n : formatUsd2(order.price * order.quantity);\n const executePriceText = order.isTrigger\n ? marketLabel\n : formatUsdPrice(order.price);\n\n return (\n <div style={striped ? STRIPE_BG_STYLE : undefined}>\n <div\n style={BODY_ROW_STYLE}\n className=\"flex flex-1 flex-row items-center justify-start px-4\"\n >\n {/* Time */}\n <div\n style={COL_STYLE.time}\n className=\"flex flex-row items-center justify-start\"\n >\n <span className=\"text-xs font-normal text-default-700\">\n {formatDateTime(order.timestamp)}\n </span>\n </div>\n\n {/* Size — raw token quantity, no symbol suffix (Axiom keeps the\n symbol in the dedicated `Asset` column so this column stays\n narrow). */}\n <div\n style={COL_STYLE.size}\n className=\"flex flex-row items-center justify-start\"\n >\n <span className=\"text-xs font-normal text-default-700\">\n {formatQuantity(order.quantity)}\n </span>\n </div>\n\n {/* Asset — plain text (no icon, unlike Positions). Mirrors Axiom. */}\n <div\n style={COL_STYLE.asset}\n className=\"flex flex-row items-center justify-start\"\n >\n <span className=\"text-xs font-medium text-foreground\">\n {tokenSymbol}\n </span>\n </div>\n\n {/* Direction */}\n <div\n style={COL_STYLE.direction}\n className=\"flex flex-row items-center justify-start\"\n >\n <span className={cn(\"text-xs font-medium\", directionColor)}>\n {directionLabel}\n </span>\n </div>\n\n {/* Type — human-readable venue label (Limit / Stop Market / …) */}\n <div\n style={COL_STYLE.type}\n className=\"flex flex-row items-center justify-start\"\n >\n <span className=\"text-xs font-normal text-default-700\">\n {typeLabel}\n </span>\n </div>\n\n {/* Leverage — small chip; hidden when leverage is unknown\n (e.g. user has no open position for this coin so the venue\n never echoed a leverage value). Matches Axiom's behaviour\n of not falling back to a stale/inferred number. */}\n <div\n style={COL_STYLE.leverage}\n className=\"flex flex-row items-center justify-start\"\n >\n {order.leverage !== undefined ? (\n <span\n className={cn(\n \"inline-flex flex-row items-center justify-start gap-1\",\n \"rounded p-1 bg-default-200/50\",\n \"text-xs font-normal text-default-700\",\n )}\n style={{ height: 18 }}\n >\n {order.leverage}x\n </span>\n ) : (\n <span className=\"text-xs font-normal text-default-500\">--</span>\n )}\n </div>\n\n {/* Order Value */}\n <div\n style={COL_STYLE.orderValue}\n className=\"flex flex-row items-center justify-start\"\n >\n <span className=\"text-xs font-normal text-default-700\">\n {orderValueText}\n </span>\n </div>\n\n {/* Execute Price */}\n <div\n style={COL_STYLE.executePrice}\n className=\"flex flex-row items-center justify-start\"\n >\n <span className=\"text-xs font-normal text-default-700\">\n {executePriceText}\n </span>\n </div>\n\n {/* Current Price — live mark price from the venue's\n `metaAndAssetCtxs` (or webData2). Falls back to `--` when\n the market context isn't available yet. */}\n <div\n style={COL_STYLE.currentPrice}\n className=\"flex flex-row items-center justify-start\"\n >\n <span className=\"text-xs font-normal text-default-700\">\n {formatUsdPrice(order.markPrice)}\n </span>\n </div>\n\n {/* Trigger Condition — venue-supplied human-readable string for\n trigger orders (e.g. \"Price below $75,050\"). Limit orders\n display `--` since they have no condition. */}\n <div\n style={COL_STYLE.triggerCondition}\n className=\"flex flex-row items-center justify-start\"\n >\n <span className=\"text-xs font-normal text-default-700\">\n {order.triggerCondition ?? \"--\"}\n </span>\n </div>\n\n {/* TP / SL — bundled exits read from Hyperliquid's parent\n order's `children[]` array (no heuristics). Trigger orders\n themselves never carry children, so they always render\n `-- / --`. Layout reuses the `1fr auto 1fr` grid pattern\n established by the Positions table for visual consistency. */}\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 {order.takeProfitPrice !== undefined\n ? formatUsdPrice(order.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 {order.stopLossPrice !== undefined\n ? formatUsdPrice(order.stopLossPrice)\n : \"--\"}\n </span>\n </div>\n\n {/* Cancel — single-order cancel button (per-row), 24×24 icon\n target with a subtle red hover background. Right-aligned\n within the column to match Axiom (header is centred, row\n is end-aligned). */}\n <div\n style={COL_STYLE.cancel}\n className=\"flex flex-row items-center justify-end gap-1\"\n >\n <button\n type=\"button\"\n onClick={() => onCancel(order)}\n disabled={isThisRowCanceling || isBatchCanceling}\n aria-label={t(\"perpetuals.openOrders.cancelOne.aria\")}\n aria-busy={isThisRowCanceling || undefined}\n className={cn(\n \"inline-flex items-center justify-center rounded p-1\",\n \"cursor-pointer text-bearish transition-colors duration-150 ease-in-out\",\n \"hover:bg-bearish/10\",\n \"disabled:cursor-not-allowed disabled:opacity-50\",\n \"outline-none focus:outline-none focus-visible:outline-none\",\n \"focus:ring-0 focus-visible:ring-0\",\n )}\n style={{ height: 24, width: 24 }}\n >\n {/* Spinner replaces the X glyph mid-cancel so the user gets\n immediate feedback the click landed. We use the same\n 24×24 button frame regardless so the row doesn't\n jitter on transition.\n\n Sizing via `transform: scale` rather than Tailwind\n class overrides on the wrapper / circle slots:\n - HeroUI's smallest preset (`size=\"sm\"`) renders at\n 20×20 with a 2px `border-2` stroke. We want 12×12\n visually, so we scale the whole thing by 0.6\n (20 × 0.6 = 12, 2 × 0.6 = 1.2 — radius/stroke\n ratio stays in proportion, no visual heaviness\n inversion).\n - We don't use `classNames={{ wrapper: \"!w-3 !h-3\" }}`\n because consumer apps in USE_LOCAL_SDK=true mode\n scan a curated set of SDK paths via Tailwind's\n `@source` directive — arbitrary utility classes\n we emit from this file aren't guaranteed to make\n it into the consumer's compiled CSS, especially\n `!`-prefixed ones. Inline `transform` is plain\n CSS, doesn't touch the class graph, always works.\n - The 24×24 button frame already centres the\n spinner via `inline-flex justify-center` from the\n parent `<button>`, so the `transform-origin`\n default of `center` keeps it on-axis. */}\n {isThisRowCanceling ? (\n <Spinner\n size=\"sm\"\n color=\"current\"\n style={{ transform: \"scale(0.6)\" }}\n />\n ) : (\n /* Inline cross icon — keeps the SDK self-contained\n without pulling a new icon-set dep just for one glyph. */\n <svg\n viewBox=\"0 0 14 14\"\n width={12}\n height={12}\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={1.6}\n strokeLinecap=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M3 3 L11 11 M11 3 L3 11\" />\n </svg>\n )}\n </button>\n </div>\n </div>\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Skeleton / Empty\n// ---------------------------------------------------------------------------\n\n/** Loading skeleton for open orders panel */\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/**\n * Standalone empty-state component. The main `OpenOrdersUI` renders\n * its own empty layout (header + centred message) so this export\n * exists for consumers that wire their own empty state outside the\n * widget.\n */\nexport function OpenOrdersEmpty() {\n return (\n <div className=\"flex h-24 items-center justify-center text-[14px] text-default-700\">\n No open orders\n </div>\n );\n}\n","import { useCallback, useState } from \"react\";\nimport { useTranslation } from \"@liberfi.io/i18n\";\nimport {\n cn,\n ModalContent,\n Spinner,\n StyledModal,\n XCloseIcon,\n} from \"@liberfi.io/ui\";\nimport {\n useOpenOrdersScript,\n type CancelOrderImpl,\n type CancelOrdersImpl,\n} from \"./open-orders.script\";\nimport { OpenOrdersUI } from \"./open-orders.ui\";\n\nexport type OpenOrdersWidgetProps = {\n userAddress?: string;\n symbol?: string;\n onCancelSuccess?: () => void;\n onCancelError?: (error: Error) => void;\n /**\n * Optional host-provided single-order cancel implementation — see\n * {@link CancelOrderImpl}. Forwarded verbatim to\n * {@link useOpenOrdersScript}. Hosts that own the wallet keys\n * (direct-venue setups) inject this; hosts that proxy via a\n * server with TEE signing leave it undefined.\n */\n cancelOrder?: CancelOrderImpl;\n /**\n * Optional host-provided batch cancel implementation — see\n * {@link CancelOrdersImpl}. When supplied, `Cancel All` issues a\n * single signature for every open order at once (the recommended\n * UX for direct-venue setups; perpetuals-server proxies don't need\n * it because each leg is a no-op API call from the user's\n * perspective).\n */\n cancelOrders?: CancelOrdersImpl;\n className?: string;\n};\n\n/**\n * Convenience widget that wires {@link useOpenOrdersScript} (data + sort\n * + cancel mutations) to {@link OpenOrdersUI} (presentation), and adds\n * a confirmation dialog for the destructive `Cancel All` action.\n *\n * The dialog state lives here (not in the script) so:\n * - The script stays trivially testable — its `handleCancelAll` is a\n * deterministic mutation call without any UI side effects.\n * - Headless / programmatic callers that import the script directly\n * can skip the dialog entirely (e.g. CI tooling, batch scripts).\n *\n * Single-order cancels go through directly: clicking the per-row `x`\n * button is already an explicit, low-impact gesture, and adding a\n * second prompt for every row would feel obstructive — matches Axiom.\n *\n * The confirm dialog matches the visual language of the place-order\n * `LeverageModal` and `DepositHyperliquidUsdcModal` (zinc-900 surface,\n * 14px corner radius, soft shadow, custom 5-px-padded header with an\n * X close button) so all destructive / confirm modals in the\n * perpetuals UI feel like one family.\n */\nexport function OpenOrdersWidget({\n userAddress,\n symbol,\n onCancelSuccess,\n onCancelError,\n cancelOrder,\n cancelOrders,\n className,\n}: OpenOrdersWidgetProps) {\n const { t } = useTranslation();\n const {\n orders,\n sortKey,\n sortDir,\n onSort,\n handleCancelOrder,\n handleCancelAll,\n cancelingOrderIds,\n isCancelingAll,\n } = useOpenOrdersScript({\n userAddress,\n symbol,\n onCancelSuccess,\n onCancelError,\n cancelOrder,\n cancelOrders,\n });\n\n const [confirmOpen, setConfirmOpen] = useState(false);\n\n const requestCancelAll = useCallback(() => {\n if (orders.length === 0) return;\n setConfirmOpen(true);\n }, [orders.length]);\n\n const closeConfirm = useCallback(() => {\n // Don't let the user dismiss the modal mid-batch — once the\n // signed cancel(s) are airborne we want them to see the spinner\n // resolve before the modal disappears, otherwise the \"is it\n // working?\" anxiety we tried to fix re-emerges.\n if (isCancelingAll) return;\n setConfirmOpen(false);\n }, [isCancelingAll]);\n\n // Confirm flow: keep the modal open until the batch settles, then\n // close it ourselves. We do NOT pre-close on click — that's how\n // the previous incarnation lost feedback. Mid-flight, both buttons\n // gate on `isCancelingAll`: the destructive CTA shows a spinner,\n // the dismiss CTA goes disabled.\n const confirmCancelAll = useCallback(async () => {\n try {\n await handleCancelAll();\n } finally {\n setConfirmOpen(false);\n }\n }, [handleCancelAll]);\n\n return (\n <>\n <OpenOrdersUI\n className={className}\n orders={orders}\n sortKey={sortKey}\n sortDir={sortDir}\n onSort={onSort}\n onCancelOrder={handleCancelOrder}\n onCancelAll={requestCancelAll}\n cancelingOrderIds={cancelingOrderIds}\n isCancelingAll={isCancelingAll}\n />\n <StyledModal\n isOpen={confirmOpen}\n onOpenChange={(open) => {\n // Block backdrop / Esc dismiss while cancellation is in\n // flight — same pattern as the leverage modal's pending\n // guard.\n if (isCancelingAll) return;\n if (!open) closeConfirm();\n }}\n size=\"md\"\n hideCloseButton\n backdrop=\"blur\"\n classNames={{\n base: cn(\n \"!bg-[#18181b] !rounded-[14px] !border !border-[rgba(39,39,42,1)]\",\n \"!shadow-[0_25px_50px_-12px_rgba(0,0,0,0.5)] max-w-[420px]\",\n ),\n body: \"!p-0\",\n }}\n >\n <ModalContent>\n <div className=\"flex flex-col\">\n {/* Header — mirrors LeverageModal / DepositHyperliquidUsdcModal */}\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 {t(\"perpetuals.openOrders.cancelAll.confirmTitle\")}\n </h3>\n <button\n type=\"button\"\n onClick={closeConfirm}\n disabled={isCancelingAll}\n aria-label=\"Close\"\n className={cn(\n \"p-1 rounded-[10px] cursor-pointer\",\n \"hover:bg-[rgba(39,39,42,0.5)]\",\n \"text-zinc-400 hover:text-white transition-colors\",\n \"disabled:cursor-not-allowed disabled:opacity-50\",\n \"outline-none focus:outline-none focus-visible:outline-none\",\n \"focus:ring-0 focus-visible:ring-0\",\n )}\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 <p className=\"text-[13px] text-zinc-400 leading-[18px] m-0\">\n {t(\"perpetuals.openOrders.cancelAll.confirmBody\")}\n </p>\n\n {/* Single destructive CTA — no companion `Keep orders`\n button. Three independent dismiss paths already cover\n reversal (X close button, backdrop click, Esc key),\n so a second equal-weight button would dilute the\n primary action and contribute decision fatigue\n without adding real reversibility.\n Borrows the leverage CTA's geometry\n (h-12 / rounded-[12px] / font-medium / w-full) so\n the modal feels like part of the same family, but\n swaps the brand-green palette for `bg-bearish` to\n signal destructive intent. */}\n <button\n type=\"button\"\n onClick={() => void confirmCancelAll()}\n disabled={isCancelingAll}\n className={cn(\n \"cursor-pointer mt-1 w-full h-12 rounded-[12px]\",\n \"font-medium text-white\",\n \"bg-bearish hover:bg-bearish/90 active:bg-bearish/80\",\n \"transition-colors flex items-center justify-center gap-2\",\n \"disabled:bg-[#3f3f46] disabled:text-zinc-500 disabled:cursor-not-allowed\",\n \"outline-none focus:outline-none focus-visible:outline-none\",\n \"focus:ring-0 focus-visible:ring-0\",\n )}\n >\n {isCancelingAll && <Spinner size=\"sm\" color=\"current\" />}\n {isCancelingAll\n ? t(\"perpetuals.openOrders.cancelAll.confirming\")\n : t(\"perpetuals.openOrders.cancelAll.confirm\")}\n </button>\n </div>\n </div>\n </ModalContent>\n </StyledModal>\n </>\n );\n}\n","import { useCallback, useMemo, useState } from \"react\";\nimport { useTradesQuery } from \"../../hooks/useTradesQuery\";\nimport type { TradeHistory } from \"../../types\";\nimport type { TradeHistorySortKey, SortDirection } from \"./trade-history.ui\";\n\nexport type UseTradeHistoryScriptParams = {\n userAddress?: string;\n /**\n * Optional venue-side filter. Omit (the default consumed by\n * `TradeHistoryWidget`) to surface fills from every coin — Axiom's\n * bottom Trades tab is all-coin, and our Positions / Open Orders\n * widgets follow the same convention.\n */\n symbol?: string;\n};\n\nexport type UseTradeHistoryScriptResult = {\n /** Trades already sorted by the active `sortKey` / `sortDir`. */\n trades: TradeHistory[];\n isLoading: boolean;\n error: Error | null;\n /**\n * Active sort column. Defaults to `time` — Axiom never exits the sort\n * state, so we model this as a non-nullable union (the UI assumes\n * a column is always active).\n */\n sortKey: TradeHistorySortKey;\n sortDir: SortDirection;\n /**\n * Toggle the sort column / direction. Mirrors Axiom's 2-state cycle:\n * clicking the active column flips `asc` ↔ `desc`; clicking a fresh\n * column starts at `desc` (newest / largest first — the natural\n * default for time, money, and PnL columns alike).\n */\n onSort: (key: TradeHistorySortKey) => void;\n};\n\n// ---------------------------------------------------------------------------\n// Sort helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Map a sort key to the comparable scalar for a given trade. Returns\n * `null` for missing values so the comparator can rank them last\n * regardless of direction (the standard \"missing data goes to the\n * bottom\" UX convention used elsewhere in the SDK).\n */\nfunction getSortValue(\n trade: TradeHistory,\n key: TradeHistorySortKey,\n): number | string | null {\n switch (key) {\n case \"time\":\n return trade.timestamp;\n case \"size\":\n return trade.quantity;\n case \"asset\":\n return trade.symbol.split(\"-\")[0];\n case \"description\":\n // Sort by the venue's raw `dir` string (e.g. \"Open Long\",\n // \"Close Short\", \"Market liquidation triggered at 2316.9\"). Pure\n // alphabetic sort matches Axiom — no semantic re-ordering of\n // open/close/liquidation.\n return trade.dir ?? null;\n case \"price\":\n return trade.price;\n case \"tradeValue\":\n return trade.price * trade.quantity;\n case \"closedPnl\":\n return trade.closedPnl ?? null;\n }\n}\n\nfunction compareTrades(\n a: TradeHistory,\n b: TradeHistory,\n key: TradeHistorySortKey,\n dir: SortDirection,\n): number {\n const aVal = getSortValue(a, key);\n const bVal = getSortValue(b, key);\n\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 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 Trade History (user fills) table.\n *\n * Responsibilities:\n * - Read fills via {@link useTradesQuery}. Hyperliquid's `webData2`\n * stream does **not** carry fill events (only state snapshots), so\n * we can't piggy-back on the same WS write-through path used by\n * Positions / Open Orders. Instead the query uses a tighter\n * `staleTime` so refocusing the tab triggers a near-instant\n * refresh — close enough to real-time for a fills view that the\n * user only consults episodically.\n * - Own sort state (default `time ↓` — newest fill first, Axiom-\n * style).\n */\nexport function useTradeHistoryScript({\n userAddress,\n symbol,\n}: UseTradeHistoryScriptParams): UseTradeHistoryScriptResult {\n // Default sort: `time` desc — most recent fill at the top.\n const [sortKey, setSortKey] = useState<TradeHistorySortKey>(\"time\");\n const [sortDir, setSortDir] = useState<SortDirection>(\"desc\");\n\n const onSort = useCallback((key: TradeHistorySortKey) => {\n setSortKey((currentKey) => {\n if (currentKey === key) {\n setSortDir((d) => (d === \"asc\" ? \"desc\" : \"asc\"));\n return currentKey;\n }\n // Fresh column: start at `desc`. For time / size / value /\n // closedPnl this surfaces the most-relevant rows first; for\n // alphabetic columns (asset / description) it's a stylistic\n // choice but matches the all-columns-default-desc UX of Axiom.\n setSortDir(\"desc\");\n return key;\n });\n }, []);\n\n const {\n data: tradesData,\n isLoading,\n error,\n } = useTradesQuery(\n {\n userAddress,\n symbol,\n // Hyperliquid's `userFills` returns up to ~2000 most recent fills\n // — we don't pass a `limit` here so the query stays aligned with\n // Axiom's \"show everything I've ever traded\" panel. Virtualization\n // in the UI keeps the cost flat regardless of list length.\n },\n { enabled: !!userAddress, staleTime: 5_000 },\n );\n\n const trades = useMemo(() => tradesData?.trades ?? [], [tradesData]);\n\n const sortedTrades = useMemo(() => {\n return [...trades].sort((a, b) => compareTrades(a, b, sortKey, sortDir));\n }, [trades, sortKey, sortDir]);\n\n return {\n trades: sortedTrades,\n isLoading,\n error,\n sortKey,\n sortDir,\n onSort,\n };\n}\n","import type { CSSProperties, ReactElement } from \"react\";\nimport { useMemo, useRef } from \"react\";\nimport { List, type RowComponentProps } from \"react-window\";\nimport { useResizeObserver } from \"@liberfi.io/hooks\";\nimport { useTranslation } from \"@liberfi.io/i18n\";\nimport { cn } from \"@liberfi.io/ui\";\nimport type { TradeHistory } from \"../../types\";\nimport {\n HEADER_ROW_STYLE,\n HeaderCell,\n STRIPE_BG_STYLE,\n formatDateTime,\n formatQuantity,\n formatSignedUsd2,\n formatUsd2,\n formatUsdPrice,\n type SortDirection,\n} from \"../_internal/table\";\n\n// ---------------------------------------------------------------------------\n// Sort\n// ---------------------------------------------------------------------------\n\n/**\n * Stable identifier for a sortable column. All 7 visible columns are\n * sortable; mirrors Axiom's bottom-Trades panel 1:1. Using a discriminated\n * string union (rather than an enum) so the value survives a tsup build\n * to a stable runtime string — consumers persisting the active sort to\n * local-storage / URL params don't pay an enum-numbering tax.\n */\nexport type TradeHistorySortKey =\n | \"time\"\n | \"size\"\n | \"asset\"\n | \"description\"\n | \"price\"\n | \"tradeValue\"\n | \"closedPnl\";\n\nexport type { SortDirection };\n\n// ---------------------------------------------------------------------------\n// Column layout — hoisted to module scope so React doesn't reallocate the\n// styles on every render of the (potentially long) virtualized list.\n// ---------------------------------------------------------------------------\n\n/**\n * Per-column inline styles. Mirrors Axiom's bottom-Trades layout 1:1\n * minus the Share column (we ship as a callback-less variant for now —\n * see the widget docstring for the rationale):\n * - 4 columns are clamped via `maxWidth` (Axiom's `max-w-[Npx]` + `flex-1`).\n * - `price`, `tradeValue`, `closedPnl` are pure `flex: 1 1 0%` so they\n * share the row's leftover width.\n *\n * Why inline (not Tailwind arbitrary classes): same rationale as\n * positions / open-orders — `USE_LOCAL_SDK=true` skips the consumer's\n * `node_modules` `@source` glob, and arbitrary-value classes emitted\n * from local source files get purged. Inline `style` always works.\n */\nconst COL_STYLE: Record<string, CSSProperties> = {\n time: { flex: \"1 1 0%\", maxWidth: 200 },\n size: { flex: \"1 1 0%\", maxWidth: 80 },\n asset: { flex: \"1 1 0%\", maxWidth: 100 },\n description: { flex: \"1 1 0%\", maxWidth: 300 },\n price: { flex: \"1 1 0%\" },\n tradeValue: { flex: \"1 1 0%\" },\n closedPnl: { flex: \"1 1 0%\" },\n};\n\n/**\n * Min-width of the inner table body. Axiom uses 1120 (with their Share\n * column); without that 24-px column we drop to 1100 — same value used\n * by Open Orders so the bottom panels share a horizontal-scroll\n * threshold.\n */\nconst TABLE_MIN_WIDTH: CSSProperties = { minWidth: 1100 };\n\n/**\n * Virtualized row outer height. Axiom uses 48 — that's 36 px of zebra-\n * coloured content row plus a 12 px transparent gap below it. We mirror\n * the layout exactly:\n *\n * ┌─ virtualizer slot (48 px, transparent) ────────────────────────┐\n * │ ┌─ stripe layer (36 px, STRIPE_BG_STYLE or transparent) ───┐ │\n * │ │ content row (flex, 16 px horizontal padding) │ │\n * │ └────────────────────────────────────────────────────────────┘ │\n * │ (12 px gap, always transparent — never striped) │\n * └────────────────────────────────────────────────────────────────┘\n *\n * Crucially the stripe is on the **36 px inner layer**, not the 48 px\n * slot — otherwise rows visually fuse into a continuous striped block,\n * making the table look chunkier than Positions / Open Orders (which\n * use 36 px rows with no gap). Verified against Axiom via DOM\n * inspection — their `bg-primaryStroke/20` lives on the 36 px content\n * layer too.\n */\nconst ROW_OUTER_HEIGHT = 48;\n\n/**\n * Inner row content style — fixed 36 px high, padding 0 16. Same as\n * Positions / Open Orders body rows, kept here as a hoisted constant\n * so we don't reallocate on every virtual row render.\n */\nconst ROW_INNER_STYLE: CSSProperties = {\n minHeight: 36,\n maxHeight: 36,\n padding: \"0 16px\",\n};\n\n// ---------------------------------------------------------------------------\n// Description colour mapping — by trade direction, not position side.\n// \"Open Long\" / \"Close Short\" are buy-side actions → bullish.\n// \"Open Short\" / \"Close Long\" / liquidations are sell-side → bearish.\n// Axiom uses the same convention; we mirror it 1:1.\n// ---------------------------------------------------------------------------\nfunction isBuyDirection(dir: string | undefined): boolean {\n if (!dir) return false;\n // \"Open Long\" / \"Close Short\" → buy.\n if (/^Open\\s+Long\\b/i.test(dir)) return true;\n if (/^Close\\s+Short\\b/i.test(dir)) return true;\n // Everything else (Open Short / Close Long / \"Market liquidation\n // triggered at …\") is treated as a sell-side action.\n return false;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\nexport type TradeHistoryUIProps = {\n /** Already-sorted trades. The script layer owns sort state. */\n trades: TradeHistory[];\n /** Currently active sort column. Always non-null — Axiom never exits\n * the sort state, defaulting to `Time ↓`. */\n sortKey: TradeHistorySortKey;\n sortDir: SortDirection;\n onSort: (key: TradeHistorySortKey) => void;\n /** Optional className on the outermost container. */\n className?: string;\n};\n\nexport function TradeHistoryUI({\n trades,\n sortKey,\n sortDir,\n onSort,\n className,\n}: TradeHistoryUIProps) {\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 fill. 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<TradeHistorySortKey>\n style={COL_STYLE.time}\n sortKey=\"time\"\n activeSortKey={sortKey}\n sortDir={sortDir}\n onSort={onSort}\n >\n {t(\"perpetuals.tradeHistory.col.time\")}\n </HeaderCell>\n <HeaderCell<TradeHistorySortKey>\n style={COL_STYLE.size}\n sortKey=\"size\"\n activeSortKey={sortKey}\n sortDir={sortDir}\n onSort={onSort}\n >\n {t(\"perpetuals.tradeHistory.col.size\")}\n </HeaderCell>\n <HeaderCell<TradeHistorySortKey>\n style={COL_STYLE.asset}\n sortKey=\"asset\"\n activeSortKey={sortKey}\n sortDir={sortDir}\n onSort={onSort}\n >\n {t(\"perpetuals.tradeHistory.col.asset\")}\n </HeaderCell>\n <HeaderCell<TradeHistorySortKey>\n style={COL_STYLE.description}\n sortKey=\"description\"\n activeSortKey={sortKey}\n sortDir={sortDir}\n onSort={onSort}\n >\n {t(\"perpetuals.tradeHistory.col.description\")}\n </HeaderCell>\n <HeaderCell<TradeHistorySortKey>\n style={COL_STYLE.price}\n sortKey=\"price\"\n activeSortKey={sortKey}\n sortDir={sortDir}\n onSort={onSort}\n >\n {t(\"perpetuals.tradeHistory.col.price\")}\n </HeaderCell>\n <HeaderCell<TradeHistorySortKey>\n style={COL_STYLE.tradeValue}\n sortKey=\"tradeValue\"\n activeSortKey={sortKey}\n sortDir={sortDir}\n onSort={onSort}\n >\n {t(\"perpetuals.tradeHistory.col.tradeValue\")}\n </HeaderCell>\n <HeaderCell<TradeHistorySortKey>\n style={COL_STYLE.closedPnl}\n sortKey=\"closedPnl\"\n activeSortKey={sortKey}\n sortDir={sortDir}\n onSort={onSort}\n >\n {t(\"perpetuals.tradeHistory.col.closedPnl\")}\n </HeaderCell>\n </div>\n );\n\n // Layout contract (mirrors `trades.ui.tsx` — the other react-window\n // table in this package):\n // - Root: `h-full` — the widget *must* fill its parent's height,\n // otherwise a `flex flex-col` root falls back to the natural\n // content height (≈ header) and the virtualized body's\n // ResizeObserver permanently reads 0 → `<List>` never renders.\n // - Header wrapper: `flex-none` — fixed-height row that never\n // fights the body for vertical space.\n // - Body wrapper: `flex-1 min-h-0` — soaks up the remaining height\n // so the virtualizer has something to measure. `min-h-0` is the\n // standard flex-shrink override that lets `overflow-y-auto`\n // actually scroll instead of pushing the parent.\n return (\n <div\n className={cn(\n \"flex h-full w-full min-w-0 flex-col overflow-hidden bg-transparent\",\n className,\n )}\n >\n <div className=\"flex flex-1 min-h-0 flex-col overflow-x-auto\">\n {/* Header lives outside the virtualizer so it stays sticky at\n the top regardless of body scroll. */}\n <div\n style={{ ...TABLE_MIN_WIDTH, ...HEADER_ROW_STYLE }}\n className=\"flex flex-none flex-col\"\n >\n {header}\n </div>\n {trades.length === 0 ? (\n <div\n style={TABLE_MIN_WIDTH}\n className=\"flex flex-1 min-h-0 flex-col items-center justify-center py-6 text-xs text-default-700\"\n >\n {t(\"perpetuals.tradeHistory.empty\")}\n </div>\n ) : (\n <VirtualBody trades={trades} />\n )}\n </div>\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Virtualized body\n// ---------------------------------------------------------------------------\n\ntype RowData = {\n trades: TradeHistory[];\n};\n\nfunction VirtualBody({ trades }: { trades: TradeHistory[] }) {\n // Resize observation: react-window v2 needs an explicit `height` prop.\n // Same pattern as the market-trades stream (`trades.ui.tsx`).\n const containerRef = useRef<HTMLDivElement | null>(null);\n const { height = 0 } = useResizeObserver<HTMLDivElement>({\n ref: containerRef,\n });\n\n // Memoise so the reference is stable when `trades` doesn't change —\n // keeps react-window's internal bailouts effective.\n const rowProps = useMemo<RowData>(() => ({ trades }), [trades]);\n\n return (\n <div\n ref={containerRef}\n style={TABLE_MIN_WIDTH}\n className=\"flex flex-1 min-h-0 flex-col overflow-y-auto\"\n >\n {height > 0 && (\n <List\n style={{ height }}\n rowComponent={Row}\n rowCount={trades.length}\n rowHeight={ROW_OUTER_HEIGHT}\n rowProps={rowProps}\n overscanCount={4}\n />\n )}\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Row\n// ---------------------------------------------------------------------------\n\nfunction Row({\n index,\n style,\n trades,\n}: RowComponentProps<RowData>): ReactElement | null {\n const trade = trades[index];\n if (!trade) return null;\n\n // Zebra stripe — odd rows get a faint white-4% fill (see\n // STRIPE_BG_STYLE), even rows stay transparent. Mirrors Axiom's\n // `bg-primaryStroke/20` pattern but corrected for our pure-black\n // page background where mid-grey tokens blend invisibly.\n const striped = index % 2 === 1;\n\n const tokenSymbol = trade.symbol.split(\"-\")[0];\n const tradeValue = trade.price * trade.quantity;\n const closedPnl = trade.closedPnl ?? 0;\n const buy = isBuyDirection(trade.dir);\n const description = trade.dir ?? \"\";\n const descriptionColor = buy ? \"text-bullish\" : \"text-bearish\";\n const pnlColor = closedPnl >= 0 ? \"text-bullish\" : \"text-bearish\";\n\n // The stripe lives on the **36 px content layer** (same height as\n // Positions / Open Orders rows), not the 48 px virtualizer slot —\n // see the ROW_OUTER_HEIGHT docstring. The remaining 12 px of the slot\n // is always transparent, producing the row gap Axiom uses.\n return (\n <div style={style}>\n <div\n style={\n striped ? { ...ROW_INNER_STYLE, ...STRIPE_BG_STYLE } : ROW_INNER_STYLE\n }\n className=\"flex flex-1 flex-row items-center justify-start\"\n >\n {/* Time */}\n <div\n style={COL_STYLE.time}\n className=\"flex flex-row items-center justify-start\"\n >\n <span className=\"text-xs font-normal text-default-500\">\n {formatDateTime(trade.timestamp)}\n </span>\n </div>\n\n {/* Size — raw token quantity, no symbol suffix (Asset column\n shows the coin separately, Axiom-style). */}\n <div\n style={COL_STYLE.size}\n className=\"flex flex-row items-center justify-start\"\n >\n <span className=\"text-xs font-normal text-default-700\">\n {formatQuantity(trade.quantity)}\n </span>\n </div>\n\n {/* Asset — plain text, no icon. */}\n <div\n style={COL_STYLE.asset}\n className=\"flex flex-row items-center justify-start\"\n >\n <span className=\"text-xs font-medium text-foreground\">\n {tokenSymbol}\n </span>\n </div>\n\n {/* Description — venue-supplied `dir` string (Open Long /\n Close Short / Market liquidation triggered at …). Coloured\n by trade direction (buy=bullish, sell/liquidation=bearish). */}\n <div\n style={COL_STYLE.description}\n className=\"flex flex-row items-center justify-start\"\n >\n <span className={cn(\"text-xs font-normal\", descriptionColor)}>\n {description}\n </span>\n </div>\n\n {/* Price — Axiom uses 11px here (every other column is 12px).\n We preserve the same micro-detail to keep the column from\n looking visually heavy when the price has many digits. */}\n <div\n style={COL_STYLE.price}\n className=\"flex flex-row items-center justify-start\"\n >\n <span\n className=\"font-normal text-default-700\"\n style={{ fontSize: 11, lineHeight: \"16px\" }}\n >\n {formatUsdPrice(trade.price)}\n </span>\n </div>\n\n {/* Trade Value — px × sz, always 2dp + thousands separator. */}\n <div\n style={COL_STYLE.tradeValue}\n className=\"flex flex-row items-center justify-start\"\n >\n <span className=\"text-xs font-normal text-default-700\">\n {formatUsd2(tradeValue)}\n </span>\n </div>\n\n {/* Closed PnL — Axiom shows venue-supplied `closedPnl` verbatim.\n For an opening fill it's essentially `-fee` (≈ -$0.01); for a\n closing fill it's `(closePrice - entryPrice) × size - fee`\n (sign-flipped for shorts). Format follows Axiom: 2 dp + sign\n for non-zero values, plain `+$0` when the value rounds to\n zero — see `formatSignedUsd2` for the round-to-zero rule. */}\n <div\n style={COL_STYLE.closedPnl}\n className=\"flex flex-row items-center justify-start\"\n >\n <span className={cn(\"text-xs font-medium\", pnlColor)}>\n {formatSignedUsd2(closedPnl)}\n </span>\n </div>\n </div>\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Skeleton / Empty\n// ---------------------------------------------------------------------------\n\n/** Loading skeleton for the trade-history panel. */\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/**\n * Standalone empty-state component. The main `TradeHistoryUI` renders\n * its own empty layout (header + centred message) so this export\n * exists for consumers wiring their own empty state outside the widget.\n */\nexport function TradeHistoryEmpty() {\n return (\n <div className=\"flex h-24 items-center justify-center text-[14px] text-default-700\">\n No trades\n </div>\n );\n}\n","import { useTradeHistoryScript } from \"./trade-history.script\";\nimport { TradeHistoryUI } from \"./trade-history.ui\";\n\nexport type TradeHistoryWidgetProps = {\n /** User wallet address. The widget gates the underlying query on this. */\n userAddress?: string;\n /**\n * Optional venue-side filter. Omit to show fills from every coin —\n * Axiom's bottom-Trades panel is all-coin, and the consumer-facing\n * widgets (Positions / Open Orders / Trades) follow the same\n * convention so the three tabs share a coherent UX.\n */\n symbol?: string;\n /** Optional className on the outermost container. */\n className?: string;\n};\n\n/**\n * Convenience widget that wires {@link useTradeHistoryScript} (data +\n * sort) to {@link TradeHistoryUI} (presentation). Intentionally thin —\n * unlike Open Orders there's no destructive action to gate behind a\n * confirmation dialog, so the widget is just a pass-through.\n *\n * Headless callers (CI, programmatic exports) can import the script\n * directly without the UI; the script's return shape is the public\n * contract.\n */\nexport function TradeHistoryWidget({\n userAddress,\n symbol,\n className,\n}: TradeHistoryWidgetProps) {\n const { trades, sortKey, sortDir, onSort } = useTradeHistoryScript({\n userAddress,\n symbol,\n });\n\n return (\n <TradeHistoryUI\n className={className}\n trades={trades}\n sortKey={sortKey}\n sortDir={sortDir}\n onSort={onSort}\n />\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"]}