skills/orderly-ui-components/SKILL.md
Build trading interfaces using pre-built React components - OrderEntry, Positions, TradingPage, WalletConnect, Sheets, Tables
npx skillsauth add orderlynetwork/skills orderly-ui-componentsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
This skill covers building trading interfaces using Orderly's pre-built React components from @orderly.network/react.
@orderly.network/react installednpm install @orderly.network/react @orderly.network/hooks @orderly.network/types
# Or with yarn
yarn add @orderly.network/react @orderly.network/hooks @orderly.network/types
Wrap your app with the required providers:
import {
OrderlyAppProvider,
TradingPageProvider,
SymbolProvider,
WalletConnector
} from '@orderly.network/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
const queryClient = new QueryClient();
function App() {
return (
<QueryClientProvider client={queryClient}>
<OrderlyAppProvider
brokerId="woofi_dex"
chainFilter={[42161, 421614]}
>
<SymbolProvider>
<TradingPageProvider>
<Layout>
<WalletConnector />
<TradingPage />
</Layout>
</TradingPageProvider>
</SymbolProvider>
</OrderlyAppProvider>
</QueryClientProvider>
);
}
import { OrderEntry, OrderEntryProvider } from '@orderly.network/ui-order-entry';
import { useOrderEntry } from '@orderly.network/hooks';
function OrderEntryContainer() {
const { onSubmit } = useOrderEntry();
const handleSubmit = async (params: any) => {
try {
await onSubmit(params);
console.log('Order submitted');
} catch (e) {
console.error('Order failed', e);
}
};
return (
<div className="bg-gray-900 rounded-lg p-4 border border-gray-800">
<OrderEntry
onSubmit={handleSubmit}
defaultTab="limit"
hideMarket={false}
/>
</div>
);
}
export function OrderEntryWidget() {
return (
<OrderEntryProvider symbol="PERP_BTC_USDC">
<OrderEntryContainer />
</OrderEntryProvider>
);
}
interface OrderEntryProps {
onSubmit?: (params: OrderParams) => Promise<void>;
defaultTab?: 'limit' | 'market';
hideMarket?: boolean;
hideLimit?: boolean;
showLeverage?: boolean;
className?: string;
}
import { Positions } from '@orderly.network/ui-positions';
export function PositionsWidget() {
const handleSymbolClick = (symbol: string) => {
console.log('Navigate to:', symbol);
};
return (
<div className="w-full">
<Positions
filter={{ symbol: 'PERP_ETH_USDC' }} // Optional filter
onSymbolClick={handleSymbolClick}
showPagination={true}
/>
</div>
);
}
interface PositionsProps {
filter?: {
symbol?: string;
side?: 'BUY' | 'SELL';
};
onSymbolClick?: (symbol: string) => void;
showPagination?: boolean;
pageSize?: number;
className?: string;
}
import { Orderbook, OrderbookProvider } from '@orderly.network/ui-orderbook';
export function OrderbookWidget({ symbol }: { symbol: string }) {
return (
<OrderbookProvider symbol={symbol}>
<Orderbook
level={10} // Number of levels to show
showTotal={true} // Show total column
onItemClick={(price, side) => {
console.log('Price clicked:', price, side);
}}
/>
</OrderbookProvider>
);
}
import { WalletConnect } from '@orderly.network/react';
export function Header() {
return (
<header className="flex justify-between items-center p-4">
<div className="logo">My DEX</div>
<WalletConnect />
</header>
);
}
import { useAccount, useWalletConnector } from '@orderly.network/hooks';
export function CustomWalletButton() {
const { account, state } = useAccount();
const wallet = useWalletConnector();
if (state.status !== 'connected') {
return (
<button
onClick={() => wallet.connect()}
className="btn-primary"
>
Connect Wallet
</button>
);
}
return (
<div className="wallet-menu">
<span>{account.address?.slice(0, 6)}...{account.address?.slice(-4)}</span>
<button onClick={() => wallet.disconnect()}>
Disconnect
</button>
</div>
);
}
import { TradingView } from '@orderly.network/ui-chart';
export function ChartWidget({ symbol }: { symbol: string }) {
return (
<div className="h-[500px]">
<TradingView
symbol={symbol}
interval="1h"
theme="dark"
autosize={true}
/>
</div>
);
}
import { LightweightChart } from '@orderly.network/ui-chart';
export function SimpleChart({ symbol }: { symbol: string }) {
return (
<div className="h-[400px]">
<LightweightChart
symbol={symbol}
interval="15m"
chartType="candlestick"
/>
</div>
);
}
import { Table } from '@orderly.network/ui';
type TradeRow = {
id: string;
price: number;
size: number;
time: string;
side: 'BUY' | 'SELL';
};
export function TradesTable({ data }: { data: TradeRow[] }) {
return (
<Table<TradeRow>
dataSource={data}
columns={[
{
title: 'Price',
dataIndex: 'price',
render: (value, record) => (
<span className={record.side === 'BUY' ? 'text-green-500' : 'text-red-500'}>
{value.toFixed(2)}
</span>
),
},
{
title: 'Size',
dataIndex: 'size',
render: (value) => value.toFixed(4),
},
{
title: 'Time',
dataIndex: 'time',
},
]}
rowKey="id"
pagination={{ pageSize: 20 }}
/>
);
}
import { Sheet, SheetTrigger, SheetContent, SheetHeader, SheetFooter } from '@orderly.network/ui';
export function OrderDetailsSheet({ order }: { order: Order }) {
return (
<Sheet>
<SheetTrigger asChild>
<button className="btn-secondary">View Details</button>
</SheetTrigger>
<SheetContent side="right">
<SheetHeader>
<h2>Order Details</h2>
</SheetHeader>
<div className="py-4">
<div className="grid grid-cols-2 gap-2">
<span>Symbol:</span>
<span>{order.symbol}</span>
<span>Side:</span>
<span>{order.side}</span>
<span>Price:</span>
<span>{order.price}</span>
<span>Quantity:</span>
<span>{order.order_qty}</span>
<span>Status:</span>
<span>{order.status}</span>
</div>
</div>
<SheetFooter>
<button className="btn-primary">Close Position</button>
</SheetFooter>
</SheetContent>
</Sheet>
);
}
import { Modal, ModalTrigger, ModalContent, ModalHeader, ModalBody, ModalFooter } from '@orderly.network/ui';
export function ConfirmOrderModal({ order, onConfirm }: { order: Order; onConfirm: () => void }) {
return (
<Modal>
<ModalTrigger asChild>
<button className="btn-primary">Place Order</button>
</ModalTrigger>
<ModalContent>
<ModalHeader>
<h2>Confirm Order</h2>
</ModalHeader>
<ModalBody>
<p>Are you sure you want to place this order?</p>
<div className="order-summary">
<p>{order.side} {order.quantity} {order.symbol} @ {order.price}</p>
</div>
</ModalBody>
<ModalFooter>
<button className="btn-secondary">Cancel</button>
<button className="btn-primary" onClick={onConfirm}>Confirm</button>
</ModalFooter>
</ModalContent>
</Modal>
);
}
import { NoData } from '@orderly.network/ui';
export function EmptyOrders() {
return (
<div className="flex flex-col items-center justify-center py-12">
<NoData width={200} height={200} className="text-gray-500" />
<p className="mt-4 text-gray-400">No open orders</p>
<button className="mt-2 btn-secondary">Place Order</button>
</div>
);
}
import { Toast, ToastProvider, useToast } from '@orderly.network/ui';
function TradingPage() {
const { toast } = useToast();
const handleOrderSubmit = async () => {
try {
await submitOrder();
toast({
title: 'Order Placed',
description: 'Your order has been submitted successfully',
variant: 'success',
});
} catch (error) {
toast({
title: 'Order Failed',
description: error.message,
variant: 'error',
});
}
};
return <button onClick={handleOrderSubmit}>Place Order</button>;
}
// In your app root
function App() {
return (
<ToastProvider>
<TradingPage />
</ToastProvider>
);
}
import {
OrderlyAppProvider,
TradingPageProvider,
SymbolProvider,
WalletConnect,
} from '@orderly.network/react';
import { OrderEntry, OrderEntryProvider } from '@orderly.network/ui-order-entry';
import { Positions } from '@orderly.network/ui-positions';
import { Orderbook, OrderbookProvider } from '@orderly.network/ui-orderbook';
import { TradingView } from '@orderly.network/ui-chart';
import { useOrderEntry } from '@orderly.network/hooks';
function TradingPage() {
const symbol = 'PERP_BTC_USDC';
return (
<div className="trading-layout">
{/* Header */}
<header className="flex justify-between items-center p-4 border-b">
<h1>My DEX</h1>
<WalletConnect />
</header>
{/* Main Content */}
<div className="grid grid-cols-12 gap-4 p-4">
{/* Left: Orderbook */}
<div className="col-span-2">
<OrderbookProvider symbol={symbol}>
<Orderbook level={15} />
</OrderbookProvider>
</div>
{/* Center: Chart + Order Entry */}
<div className="col-span-7">
<div className="h-[500px] mb-4">
<TradingView symbol={symbol} />
</div>
<OrderEntryProvider symbol={symbol}>
<OrderEntry defaultTab="limit" />
</OrderEntryProvider>
</div>
{/* Right: Positions */}
<div className="col-span-3">
<Positions showPagination={false} />
</div>
</div>
</div>
);
}
export function App() {
return (
<OrderlyAppProvider brokerId="woofi_dex">
<SymbolProvider>
<TradingPageProvider>
<TradingPage />
</TradingPageProvider>
</SymbolProvider>
</OrderlyAppProvider>
);
}
Orderly components use Tailwind CSS classes. Customize with:
/* Override component styles */
.order-entry-root {
/* Your styles */
}
.positions-table {
/* Your styles */
}
/* Use Tailwind dark mode */
.dark .order-entry-root {
/* Dark mode styles */
}
SymbolProvider is above symbol-dependent componentsclassName prop when availabledevelopment
Establish authenticated WebSocket connections for real-time orderbook, execution reports, positions, and balance updates
development
Place, manage, and cancel orders using REST API or SDK hooks. Covers market, limit, IOC, FOK, POST_ONLY order types and batch operations
development
Comprehensive guide to integrating wallet connection in Orderly Network DEX applications, supporting both EVM (Ethereum, Arbitrum, etc.) and Solana wallets.
development
Complete trading workflows for Orderly Network DEX applications, from wallet connection through order execution, position management, and withdrawal.