@liberfi.io/ui-perpetuals
v1.1.12
Published
Perpetuals for Liberfi React SDK
Downloads
5,902
Readme
@liberfi.io/ui-perpetuals
@liberfi.io/ui-perpetuals provides perpetual trading UI widgets, container hooks, and typed client contracts for the Liberfi React SDK. It is designed for host apps that want ready-to-use perpetual modules (order book, trades, place order, positions, orders, history) while still controlling networking, side effects, and provider wiring.
Design Philosophy
- Keep data logic and presentation separated (
*.script.tsx+*.ui.tsx+*.widget.tsx). - Keep client integration explicit via
PerpetualsProviderandusePerpetualsClient. - Prefer typed hooks over ad-hoc data fetching to keep cache keys and API calls consistent.
- Expose building blocks (UI + hooks + types) so consumers can compose custom flows.
Installation
pnpm add @liberfi.io/ui-perpetualsRequired peer dependencies:
reactreact-dom@tanstack/react-queryreact-hook-form
API Reference
Components
CoinInfoWidget(props: CoinInfoWidgetProps)CoinInfoUI(props: CoinInfoUIProps)CoinInfoSkeletonsUI()CoinInfoNotFoundUI()SearchCoinsWidget(props: SearchCoinsWidgetProps)SearchCoinsUI(props: SearchCoinsUIProps)OrderBookWidget(props: OrderBookWidgetProps)OrderBookUI(props: OrderBookUIProps)TradesWidget(props: TradesWidgetProps)TradesUI(props: TradesUIProps)PlaceOrderFormWidget(props: PlaceOrderFormWidgetProps)PlaceOrderFormUI(props: PlaceOrderFormUIProps)(usesreact-hook-formUseFormReturn)PositionsWidget(props: PositionsWidgetProps)— wiresusePositionsScripttoPositionsUI; owns sort state and the close-position mutationPositionsUI(props: PositionsUIProps)— controlled, presentational positions table (div+flex layout, 9 columns, sortable headers, header tooltips, zebra striping,min-w-[1000px]+ horizontal scroll). TheMark Price,Margin Used (PNL), andTP / SLcolumns are kept live byuseAccountStateSubscription(webData2): each push re-marks every position against the venue'smarkPx, recomputes PnL, and re-derives the closing-side TP/SL trigger prices client-side, so the table updates at the same cadence as the order book — no extra subscription needed at the widget level.PositionsSkeleton()PositionsEmpty()OpenOrdersWidget(props: OpenOrdersWidgetProps)— wiresuseOpenOrdersScripttoOpenOrdersUI; owns sort state, the per-row cancel mutation, and a confirmation dialog for the destructiveCancel AllactionOpenOrdersUI(props: OpenOrdersUIProps)— controlled, presentational open-orders table (div+flex layout, 12 columns mirroring Axiom 1:1, 9 sortable headers,Leverageheader tooltip, zebra striping,min-w-[1100px]+ horizontal scroll). TheCurrent Pricecolumn reads each order's live mark price;TP / SLreads the parent limit order'schildren[]array (Hyperliquid's authoritative bundled-exit field), so the table updates at the same cadence as the order book — no extra subscription needed at the widget level.OpenOrdersSkeleton()OpenOrdersEmpty()TradeHistoryWidget(props: TradeHistoryWidgetProps)— wiresuseTradeHistoryScripttoTradeHistoryUI; thin pass-through (no destructive actions to gate). Defaults to all-coin display so the bottom-panel UX matches Positions / Open Orders.TradeHistoryUI(props: TradeHistoryUIProps)— controlled, presentational user-fills table (div+flex layout, 7 columns mirroring Axiom 1:1 minus the Share column, all 7 headers sortable, virtualized viareact-windowsinceuserFillscan return thousands of records, zebra striping,min-w-[1100px]+ horizontal scroll). TheDescriptioncolumn passes through Hyperliquid'sdirstring ("Open Long"/"Close Short"/"Market liquidation triggered at <px>") and colours it by trade direction (buy=bullish, sell/liquidation=bearish).Closed PnLalways renders the signed value (+$0.06/-$0.06) so the dollar amount stays readable in copy-paste / high-contrast modes.TradeHistorySkeleton()TradeHistoryEmpty()PerpetualsProvider(props: PerpetualsProviderProps)DepositFormUI(props: DepositFormUIProps)— pure deposit form (amount + recipient)DepositConfirmUI(props: DepositConfirmUIProps)— quote confirmation modal with expiry countdownDepositStatusUI(props: DepositStatusUIProps)— terminal status modal (settled / refunded / failed)DepositFlowWidget(props: DepositFlowWidgetProps)— orchestrates form + confirm + status with hooksHyperliquidInitUI(props: HyperliquidInitUIProps)— first-run setup checklist (builder fee / referrer / leverage)HyperliquidInitWidget(props: HyperliquidInitWidgetProps)— wires the checklist touseHyperliquidSetup
Hooks
- Context hook:
usePerpetualsClient()
- Query hooks:
useCoinsQuery,useMarketQuery,useMarketsQuery,useKlinesQueryuseOrderBookQuery,useRecentTradesQueryusePositionsQuery,useOrdersQuery,useTradesQuery
- Mutation hooks:
useCreateOrderMutation,useCancelOrderMutation
- Subscription hooks:
useMarketDataSubscription,useCandlesSubscription,useUserDataSubscription
- Component script hooks:
useCoinInfo,useSearchCoinsScript,useOrderBookScript,useTradesScriptusePlaceOrderFormScript,usePositionsScript,useOpenOrdersScript,useTradeHistoryScript
- Deposit hooks (Solana → Hyperliquid USDC):
usePerpDepositClient— accessor for the deposit REST client fromPerpetualsProviderusePerpDepositQuote— TanStack Query wrapper aroundPOST /v1/deposits/quoteusePerpDepositExecute— orchestratesquote → sign → broadcast → submitvia theDepositStateFSMusePerpDepositStatus— long-pollGET /v1/deposits/{id}until terminal
- Hyperliquid first-run setup:
useHyperliquidSetup— runsapproveBuilderFee,setReferrer, andupdateLeverageidempotently against an injectedIHyperliquidSetupAdapter
- Also exported helpers from hook modules:
- Query keys and fetchers such as
coinsQueryKey/fetchCoins,marketQueryKey/fetchMarket,ordersQueryKey/fetchOrders, etc. - Trade operation helpers:
createOrder,cancelOrder.
- Query keys and fetchers such as
Functions / Utilities
HyperliquidPerpetualsClientclass implementingIPerpetualsClient.usePerpetualsClient()as the context accessor utility.LiberFiHttpTransport— shared HTTP layer (used by every LiberFi REST client; injectable for testing).LiberFiPerpetualsClient— REST client over LiberFi-managed perpetuals (talks to perpetuals-server).LiberFiPerpDepositClient— REST client over/v1/deposits/*(quote / submit / status / refresh).- Deposit state machine (pure functions) —
reduceDepositState,initialDepositState,isDepositTerminal,isDepositPolling,currentDepositStatus,currentDepositBreakdown,isTerminalDepositLifecycle. - Hyperliquid setup state machine (pure functions) —
reduceSetupState,initialSetupState,classifyStep,nextRunnableStep.
Types & Enums
- Client-related:
IPerpetualsClient,HyperliquidClientConfig,HyperliquidEnvironment,HyperliquidApiErrorPerpetualsContextValue,PerpetualsProviderPropsLiberFiHttpTransportConfig,LiberFiHttpMethod,LiberFiHttpRequestOptions,LiberFiApiErrorLiberFiPerpetualsClientConfig,SignTypedDataFnIPerpDepositClient,LiberFiPerpDepositClientConfig
- Deposit (Solana → Hyperliquid):
DepositSource,DepositStatus,DepositErrorInfo,DepositStatusTransition,DepositBreakdownDepositQuoteRequest,DepositQuoteResponse,DepositSubmitRequest,DepositSubmitResponse,DepositStatusResponseDepositPhase,DepositState,DepositEventTERMINAL_DEPOSIT_STATUSES
- Hyperliquid setup:
IHyperliquidSetupAdapter,HyperliquidAccountState,HyperliquidSetupActionResultApproveBuilderFeeParams,SetReferrerParams,UpdateLeverageParamsSetupStep,SetupStepId,StepRecord,StepStatus,SetupPhase,SetupState,SetupActionUseHyperliquidSetupOptions,UseHyperliquidSetupResult
- Domain enums/types:
Symbol,TradingProvider,OrderSide,OrderType,OrderStatus,KlineInterval,TradeSide
- Domain entities:
Coin,MarketData,Kline,OrderBookLevel,OrderBook,Trade,AccountPosition,Order,TradeHistory
- Request/response contracts:
PlaceOrderParams,CancelOrderParams,GetPositionsParams,GetOpenOrdersParams,GetTradesParamsPlaceOrderResult,CancelOrderResult,GetPositionsResult,GetOpenOrdersResult,GetTradesResult
- UI and script props/result types:
- All
*Props,Use*Params,Use*Resulttypes re-exported by each component/hook index.
- All
- Positions table sort:
PositionSortKey— discriminated string union of the seven sortable columns (asset,position,value,entry,mark,liq,marginPnl)SortDirection—"asc" | "desc"
- Trade History table sort:
TradeHistorySortKey— discriminated string union of the seven sortable columns (time,size,asset,description,price,tradeValue,closedPnl)SortDirection—"asc" | "desc"
Constants
version(package version string).
Usage Examples
import {
HyperliquidPerpetualsClient,
PerpetualsProvider,
PlaceOrderFormWidget,
OrderBookWidget,
TradesWidget,
} from "@liberfi.io/ui-perpetuals";
const client = new HyperliquidPerpetualsClient({ environment: "testnet" });
export function PerpsPanel() {
return (
<PerpetualsProvider client={client}>
<OrderBookWidget symbol="BTC-USDC" />
<TradesWidget symbol="BTC-USDC" />
<PlaceOrderFormWidget symbol="BTC-USDC" userAddress="0x..." />
</PerpetualsProvider>
);
}import { useForm } from "react-hook-form";
import {
PlaceOrderFormUI,
type PlaceOrderFormData,
} from "@liberfi.io/ui-perpetuals";
const methods = useForm<PlaceOrderFormData>({
defaultValues: {
amount: 0,
leverage: 1,
takeProfitPercent: 0,
stopLossPercent: 0,
},
});
// Pass methods directly to PlaceOrderFormUI if you build your own container.Deposit (Solana → Hyperliquid USDC)
The deposit flow is a single end-to-end widget plus three presentational
components for callers that want a custom layout. The widget consumes
the deposit client via PerpetualsProvider and delegates wallet signing
to the host application.
import {
DepositFlowWidget,
HyperliquidPerpetualsClient,
LiberFiHttpTransport,
LiberFiPerpDepositClient,
PerpetualsProvider,
} from "@liberfi.io/ui-perpetuals";
const transport = new LiberFiHttpTransport({
baseUrl: process.env.NEXT_PUBLIC_PERPETUALS_API!,
});
const perpetualsClient = new HyperliquidPerpetualsClient({
environment: "mainnet",
});
const depositClient = new LiberFiPerpDepositClient({ transport });
export function DepositPanel({ wallet }: { wallet: SolanaWalletAdapter }) {
return (
<PerpetualsProvider client={perpetualsClient} depositClient={depositClient}>
<DepositFlowWidget
userSolanaAddress={wallet.publicKey.toBase58()}
userId={user.id}
source="dex"
defaultRecipient={user.evmAddress}
signAndBroadcast={async (txBase64) => wallet.signAndSend(txBase64)}
buildSolanaExplorerUrl={(h) => `https://solscan.io/tx/${h}`}
buildHyperliquidExplorerUrl={(h) =>
`https://app.hyperliquid.xyz/explorer/tx/${h}`
}
onSettled={(intentId) => console.log("settled", intentId)}
/>
</PerpetualsProvider>
);
}For a fully custom layout, drive the lower-level UI components with
usePerpDepositQuote, usePerpDepositExecute, and usePerpDepositStatus
directly. The state-machine pure functions (reduceDepositState, etc.)
are also exported for tooling and tests.
Hyperliquid first-run setup
HyperliquidInitWidget orchestrates the three idempotent setup actions
Hyperliquid expects on a fresh account: approve a builder fee, set a
referrer, and pin a default leverage. Wallet signing is delegated to a
consumer-supplied adapter so this SDK does not pin a specific Hyperliquid
client library.
import {
HyperliquidInitWidget,
type IHyperliquidSetupAdapter,
} from "@liberfi.io/ui-perpetuals";
const adapter: IHyperliquidSetupAdapter = buildPrivyAdapter(/* … */);
export function FirstRunSetup({ user }: { user: { evmAddress: string } }) {
return (
<HyperliquidInitWidget
adapter={adapter}
userAddress={user.evmAddress}
steps={[
{
id: "approveBuilderFee",
params: { builder: BUILDER_ADDRESS, maxFeeRate: 45 },
},
{ id: "setReferrer", params: { code: "LIBERFI" } },
{
id: "updateLeverage",
params: { asset: "BTC", leverage: 5, isCross: true },
},
]}
onComplete={() => router.push("/perpetuals")}
/>
);
}The pure state machine (reduceSetupState, classifyStep,
nextRunnableStep) is exported separately so apps can build their own
checklist UI without reimplementing the transition rules.
Future Improvements
- Add integration tests for order submit/cancel and subscription lifecycle.
- Finish i18n wiring across the remaining widgets (
TradesUI); positions / open-orders / trade-history tables are fully translated under their respectiveperpetuals.*namespaces. - Wire a real-time
userFillspush subscription intouseTradeHistoryScriptso new fills appear instantly (today the script polls via React Query with a 5 sstaleTime). The hook surface already accepts the data path; the only missing piece is asubscribeUserData('fills')listener that prepends new fills to the React Query cache fortradesQueryKey. - Surface a per-position TP/SL editor behind the small
Editicon Axiom shows in the TP/SL cell. The data plumbing already lands the active trigger prices on eachPosition(takeProfitPrice/stopLossPrice); a popover that callsuseCreateOrderMutationwithreduceOnly: truetriggers would complete the loop. - Wire a Limit close action in the positions row's
Closecell. Today only theMarketclose button is rendered; reusing the place-order form's limit-price input from a popover would close the gap. - Replace placeholder account/margin values in place-order script with real account sources.
- Surface deposit status updates over a push channel (SSE/WebSocket) once the perpetuals-server exposes one — today the client polls.
- Ship a first-party
HyperliquidSetupAdapterimplementation via a dedicated@liberfi.io/wallet-connector-hyperliquidpackage so consumers don’t need to write their own.
