Package Exports
- @pear-protocol/hyperliquid-sdk
Readme
Pear Hyperliquid SDK
A comprehensive React SDK for integrating with the Pear Protocol Hyperliquid API. This SDK provides a complete toolkit for building trading applications with real-time WebSocket data, authentication, position management, order execution, and market data access.
Features
- React Context Provider - Easy integration with React applications
- Real-time WebSocket Connections - Dual WebSocket support (Pear API + HyperLiquid native)
- Authentication - EIP-712 signature and Privy token authentication
- Position Management - Create, adjust, and close trading positions
- Order Management - Place, modify, and cancel orders (MARKET, LIMIT, TWAP, TP/SL)
- Market Data - Access real-time price feeds, asset information, and candle data
- Agent Wallet - Manage agent wallet creation and status
- TypeScript - Full type safety with comprehensive type definitions
- Zustand State Management - Efficient state management for market and user data
Installation
npm install @pear-protocol/hyperliquid-sdk
# or
yarn add @pear-protocol/hyperliquid-sdkPeer Dependencies
This SDK requires React 18 or higher:
npm install react react-dom
# or
yarn add react react-domQuick Start
1. Wrap your application with the Provider
import { PearHyperliquidProvider } from "@pear-protocol/hyperliquid-sdk";
function App() {
return (
<PearHyperliquidProvider
apiBaseUrl="https://hl-v2.pearprotocol.io"
wsUrl="wss://hl-v2.pearprotocol.io/ws"
clientId="YOUR_CLIENT_ID"
>
<YourApp />
</PearHyperliquidProvider>
);
}2. Use hooks in your components
import {
usePearAuth,
usePearHyperliquid,
usePosition,
useOrders,
} from "@pear-protocol/hyperliquid-sdk";
function TradingComponent() {
const { address, setAddress } = usePearHyperliquid();
const { isAuthenticated, loginWithSignedMessage } = usePearAuth();
const { openPositions, createPosition } = usePosition();
const { openOrders, cancelOrder } = useOrders();
// Your component logic
}Core Concepts
Provider Configuration
The PearHyperliquidProvider accepts the following props:
| Prop | Type | Default | Description |
|---|---|---|---|
apiBaseUrl |
string |
https://hl-v2.pearprotocol.io |
Pear API base URL |
wsUrl |
string |
wss://hl-v2.pearprotocol.io/ws |
Pear WebSocket URL |
clientId |
string |
PEARPROTOCOLUI |
Client identifier for authentication |
Authentication
The SDK supports two authentication methods:
EIP-712 Signature Authentication
import { usePearAuth } from "@pear-protocol/hyperliquid-sdk";
function LoginComponent() {
const { getEip712, loginWithSignedMessage, isAuthenticated } = usePearAuth();
const handleLogin = async (address: string, signer: any) => {
// Get EIP-712 message
const eip712Data = await getEip712(address);
// Sign with wallet
const signature = await signer.signTypedData(
eip712Data.domain,
eip712Data.types,
eip712Data.message
);
// Authenticate
await loginWithSignedMessage(address, signature, eip712Data.timestamp);
};
return <div>{isAuthenticated ? "Logged In" : "Logged Out"}</div>;
}Privy Token Authentication
import { usePearAuth } from "@pear-protocol/hyperliquid-sdk";
function PrivyLoginComponent() {
const { loginWithPrivyToken, isAuthenticated } = usePearAuth();
const handlePrivyLogin = async (
address: string,
appId: string,
accessToken: string
) => {
await loginWithPrivyToken(address, appId, accessToken);
};
}API Reference
Hooks
Core Hooks
usePearHyperliquid()
Access the entire SDK context. Prefer using more specific hooks when possible.
const {
apiBaseUrl,
wsUrl,
address,
setAddress,
connectionStatus,
isConnected,
nativeConnectionStatus,
nativeIsConnected,
authStatus,
isAuthenticated,
accessToken,
user,
// ... and more
} = usePearHyperliquid();usePearAuth()
Authentication state and actions.
const {
status, // AuthStatus enum
isAuthenticated, // boolean
user, // UserProfile | null
error, // string | null
getEip712, // (address: string) => Promise<EIP712MessageResponse>
loginWithSignedMessage, // (address, signature, timestamp) => Promise<void>
loginWithPrivyToken, // (address, appId, accessToken) => Promise<void>
refreshTokens, // () => Promise<any>
logout, // () => Promise<void>
} = usePearAuth();usePearAgentWallet()
Agent wallet management.
const {
agentWallet, // AgentWalletState
isReady, // boolean
loading, // boolean
error, // string | null
refreshAgentWalletStatus, // () => Promise<any>
createAgentWallet, // () => Promise<any>
notifyAgentWalletApproved, // () => Promise<any>
} = usePearAgentWallet();Position Management
usePosition()
Manage trading positions.
const {
createPosition, // (payload) => Promise<ApiResponse<CreatePositionResponseDto>>
updateRiskParameters, // (positionId, payload) => Promise<ApiResponse<UpdateRiskParametersResponseDto>>
closePosition, // (positionId, payload) => Promise<ApiResponse<ClosePositionResponseDto>>
closeAllPositions, // (payload) => Promise<ApiResponse<CloseAllPositionsResponseDto>>
adjustPosition, // (positionId, payload) => Promise<ApiResponse<AdjustPositionResponseDto>>
openPositions, // OpenPositionDto[] | null
isLoading, // boolean
} = usePosition();Example: Create a Position
const { createPosition } = usePosition();
const handleCreatePosition = async () => {
try {
const response = await createPosition({
leverage: 5,
usdValue: 1000,
longAssets: [{ asset: "ETH", weight: 1 }],
shortAssets: [{ asset: "BTC", weight: 1 }],
orderType: "MARKET",
});
console.log("Position created:", response.data);
} catch (error) {
console.error("Failed to create position:", error);
}
};Example: Close a Position
const { closePosition } = usePosition();
const handleClosePosition = async (positionId: string) => {
try {
const response = await closePosition(positionId, {
orderType: "MARKET",
});
console.log("Position closed:", response.data);
} catch (error) {
console.error("Failed to close position:", error);
}
};Order Management
useOrders()
Manage orders (LIMIT, TP/SL, TWAP).
const {
adjustOrder, // (orderId, payload) => Promise<ApiResponse<AdjustOrderResponseDto>>
cancelOrder, // (orderId) => Promise<ApiResponse<CancelOrderResponseDto>>
cancelTwapOrder, // (orderId) => Promise<ApiResponse<CancelTwapResponseDto>>
openOrders, // OpenLimitOrderDto[] | null
isLoading, // boolean
} = useOrders();Example: Cancel an Order
const { cancelOrder } = useOrders();
const handleCancelOrder = async (orderId: string) => {
try {
await cancelOrder(orderId);
console.log("Order cancelled successfully");
} catch (error) {
console.error("Failed to cancel order:", error);
}
};Trading Data
useTradeHistories()
Access trade history data.
const { data, isLoading } = useTradeHistories();useOpenOrders()
Access open orders with loading state.
const { data, isLoading } = useOpenOrders();useAccountSummary()
Access account summary with real-time calculations.
const { data, isLoading } = useAccountSummary();
// data: AccountSummaryResponseDto | nullMarket Data
useMarketData()
Access real-time market data from Zustand store.
import { useMarketData } from "@pear-protocol/hyperliquid-sdk";
function MarketDataComponent() {
const activeAssets = useMarketData((state) => state.activeAssets);
return (
<div>
{activeAssets?.active.map((asset, idx) => (
<div key={idx}>
Long: {asset.longAssets.map((a) => a.asset).join(", ")} vs Short:{" "}
{asset.shortAssets.map((a) => a.asset).join(", ")}
</div>
))}
</div>
);
}useHistoricalPriceData()
Fetch and manage historical price data for tokens.
import { useHistoricalPriceData } from "@pear-protocol/hyperliquid-sdk";
function ChartComponent() {
const { fetchHistoricalData, getTokenData } = useHistoricalPriceData();
useEffect(() => {
fetchHistoricalData("ETH", "1d"); // 1 day range
}, []);
const ethData = getTokenData("ETH");
}useBasketCandles()
Get candle data for basket (multi-asset) positions.
import { useBasketCandles } from "@pear-protocol/hyperliquid-sdk";
function BasketChartComponent() {
const { candles, isLoading, error } = useBasketCandles({
longAssets: [
{ symbol: "ETH", weight: 0.5 },
{ symbol: "BTC", weight: 0.5 },
],
shortAssets: [{ symbol: "SOL", weight: 1 }],
interval: "1h",
lookbackHours: 24,
});
}useTokenSelectionMetadata()
Get metadata for selected tokens including prices, funding, and leverage info.
import { useTokenSelectionMetadata } from "@pear-protocol/hyperliquid-sdk";
function TokenSelector() {
const { getMetadata, isLoading } = useTokenSelectionMetadata();
const ethMetadata = getMetadata("ETH");
// ethMetadata: { currentPrice, priceChange24hPercent, maxLeverage, ... }
}WebSocket Hooks
useHyperliquidWebSocket()
Access Pear API WebSocket connection (managed by provider).
useHyperliquidNativeWebSocket()
Access HyperLiquid native WebSocket connection (managed by provider).
TWAP Orders
useTwap()
Access TWAP (Time-Weighted Average Price) order monitoring.
import { useTwap } from "@pear-protocol/hyperliquid-sdk";
function TwapMonitor() {
const { twapOrders, isLoading } = useTwap();
return (
<div>
{twapOrders?.map((order) => (
<div key={order.orderId}>
Status: {order.status}
Progress: {(order.filledUsdValue / order.totalUsdValue) * 100}%
</div>
))}
</div>
);
}Notifications
useNotifications()
Access user notifications.
import { useNotifications } from "@pear-protocol/hyperliquid-sdk";
function NotificationCenter() {
const { notifications, isLoading, markAsRead, markAllAsRead } =
useNotifications();
return (
<div>
{notifications?.map((notif) => (
<div key={notif.id} onClick={() => markAsRead(notif.id)}>
{notif.category}: {JSON.stringify(notif.parameters)}
</div>
))}
</div>
);
}Utility Classes
AccountSummaryCalculator
Calculate account summary with real-time data.
import { AccountSummaryCalculator } from "@pear-protocol/hyperliquid-sdk";
const calculator = new AccountSummaryCalculator(webData2);
const summary = calculator.calculateAccountSummary(
accountSummary,
openOrders,
agentWalletAddress,
agentWalletStatus
);ConflictDetector
Detect position conflicts for new trades.
import { ConflictDetector } from "@pear-protocol/hyperliquid-sdk";
const conflicts = ConflictDetector.detectConflicts(
longTokens,
shortTokens,
existingPositions
);TokenMetadataExtractor
Extract token metadata from WebSocket data.
import { TokenMetadataExtractor } from "@pear-protocol/hyperliquid-sdk";
const metadata = TokenMetadataExtractor.extractMetadata(
"ETH",
webData2,
allMids,
activeAssetData
);Direct API Clients
For advanced use cases, you can import and use API clients directly:
import {
createPosition,
updateRiskParameters,
closePosition,
adjustOrder,
cancelOrder,
} from "@pear-protocol/hyperliquid-sdk";
// All client functions require baseUrl and accessToken
const response = await createPosition(baseUrl, accessToken, {
leverage: 5,
usdValue: 1000,
longAssets: [{ asset: "ETH", weight: 1 }],
shortAssets: [{ asset: "BTC", weight: 1 }],
orderType: "MARKET",
});TypeScript Support
The SDK is written in TypeScript and provides comprehensive type definitions. All hooks, functions, and data structures are fully typed.
import type {
OpenPositionDto,
OpenLimitOrderDto,
TradeHistoryDataDto,
AccountSummaryResponseDto,
WebSocketChannel,
CandleInterval,
TokenMetadata,
// ... and many more
} from "@pear-protocol/hyperliquid-sdk";WebSocket Data Flow
The SDK manages two WebSocket connections:
- Pear API WebSocket - User-specific data (positions, orders, trade history, account summary)
- HyperLiquid Native WebSocket - Market data (prices, asset info, candles)
Data is automatically stored in Zustand stores and accessible via hooks:
useUserDatastore - User positions, orders, and account datauseHyperliquidDatastore - Market data (webData2, allMids, activeAssetData)useHistoricalPriceDataStore- Historical price datauseMarketDatastore - Active assets and market overview
Error Handling
All API functions return promises and throw errors on failure. Always wrap API calls in try-catch blocks:
try {
await createPosition(payload);
} catch (error) {
if (error instanceof Error) {
console.error("Error:", error.message);
}
}Environment Variables
When using the SDK, you may want to configure different environments:
// Production
<PearHyperliquidProvider
apiBaseUrl="https://hl-v2.pearprotocol.io"
wsUrl="wss://hl-v2.pearprotocol.io/ws"
/>
// Beta
<PearHyperliquidProvider
apiBaseUrl="https://hl-v2-beta.pearprotocol.io"
wsUrl="wss://hl-v2-beta.pearprotocol.io/ws"
/>Examples
Complete Trading Component
import { useState } from "react";
import {
usePearAuth,
usePearHyperliquid,
usePosition,
useOrders,
useAccountSummary,
} from "@pear-protocol/hyperliquid-sdk";
function TradingDashboard() {
const { address, setAddress, isConnected } = usePearHyperliquid();
const { isAuthenticated, loginWithSignedMessage } = usePearAuth();
const { openPositions, createPosition, closePosition } = usePosition();
const { openOrders, cancelOrder } = useOrders();
const { data: accountSummary } = useAccountSummary();
const handleCreatePosition = async () => {
try {
await createPosition({
leverage: 3,
usdValue: 500,
longAssets: [{ asset: "ETH", weight: 1 }],
shortAssets: [{ asset: "BTC", weight: 1 }],
orderType: "MARKET",
});
} catch (error) {
console.error("Failed to create position:", error);
}
};
return (
<div>
<h1>Trading Dashboard</h1>
<div>
<h2>Account</h2>
<p>Address: {address || "Not connected"}</p>
<p>Status: {isAuthenticated ? "Authenticated" : "Not authenticated"}</p>
<p>WebSocket: {isConnected ? "Connected" : "Disconnected"}</p>
</div>
<div>
<h2>Account Summary</h2>
<p>
Account Value: $
{accountSummary?.balanceSummary.marginSummary.accountValue}
</p>
<p>Withdrawable: ${accountSummary?.balanceSummary.withdrawable}</p>
</div>
<div>
<h2>Open Positions</h2>
{openPositions?.map((pos) => (
<div key={pos.positionId}>
<p>PNL: ${pos.unrealizedPnl.toFixed(2)}</p>
<p>Value: ${pos.positionValue.toFixed(2)}</p>
<button
onClick={() =>
closePosition(pos.positionId, { orderType: "MARKET" })
}
>
Close
</button>
</div>
))}
</div>
<div>
<h2>Open Orders</h2>
{openOrders?.map((order) => (
<div key={order.orderId}>
<p>Type: {order.orderType}</p>
<p>Value: ${order.usdValue}</p>
<button onClick={() => cancelOrder(order.orderId)}>Cancel</button>
</div>
))}
</div>
<button onClick={handleCreatePosition}>Create New Position</button>
</div>
);
}
export default TradingDashboard;Market Data Component
import {
useMarketData,
useTokenSelectionMetadata,
useHyperliquidWebSocket,
} from "@pear-protocol/hyperliquid-sdk";
function MarketOverview() {
const activeAssets = useMarketData((state) => state.activeAssets);
const { getMetadata } = useTokenSelectionMetadata();
return (
<div>
<h2>Top Gainers</h2>
{activeAssets?.topGainers.slice(0, 5).map((asset, idx) => {
const longAsset = asset.longAssets[0]?.asset;
const metadata = longAsset ? getMetadata(longAsset) : null;
return (
<div key={idx}>
<p>
{longAsset}: {metadata?.priceChange24hPercent.toFixed(2)}%
</p>
</div>
);
})}
<h2>Top Losers</h2>
{activeAssets?.topLosers.slice(0, 5).map((asset, idx) => {
const shortAsset = asset.shortAssets[0]?.asset;
const metadata = shortAsset ? getMetadata(shortAsset) : null;
return (
<div key={idx}>
<p>
{shortAsset}: {metadata?.priceChange24hPercent.toFixed(2)}%
</p>
</div>
);
})}
</div>
);
}License
MIT
Repository
GitHub: https://github.com/pear-protocol/hyperliquid
Support
For issues and questions, please visit the GitHub Issues page.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.