@pear-protocol/hyperliquid-sdk 0.0.41 → 0.0.43
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/README.md +562 -267
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/useMarketData.d.ts +7 -0
- package/dist/hooks/useTokenSelectionMetadata.d.ts +4 -0
- package/dist/index.d.ts +42 -3
- package/dist/index.js +161 -12
- package/dist/store/marketDataStore.d.ts +1 -0
- package/dist/store/tokenSelectionMetadataStore.d.ts +6 -1
- package/dist/types.d.ts +27 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Pear Hyperliquid SDK
|
|
2
2
|
|
|
3
|
-
A React SDK for integrating with Pear Protocol
|
|
3
|
+
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.
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
-
- **React
|
|
8
|
-
- **Real-time
|
|
9
|
-
- **Authentication
|
|
10
|
-
- **
|
|
11
|
-
- **
|
|
12
|
-
- **
|
|
7
|
+
- **React Context Provider** - Easy integration with React applications
|
|
8
|
+
- **Real-time WebSocket Connections** - Dual WebSocket support (Pear API + HyperLiquid native)
|
|
9
|
+
- **Authentication** - EIP-712 signature and Privy token authentication
|
|
10
|
+
- **Position Management** - Create, adjust, and close trading positions
|
|
11
|
+
- **Order Management** - Place, modify, and cancel orders (MARKET, LIMIT, TWAP, TP/SL)
|
|
12
|
+
- **Market Data** - Access real-time price feeds, asset information, and candle data
|
|
13
|
+
- **Agent Wallet** - Manage agent wallet creation and status
|
|
14
|
+
- **TypeScript** - Full type safety with comprehensive type definitions
|
|
15
|
+
- **Zustand State Management** - Efficient state management for market and user data
|
|
13
16
|
|
|
14
17
|
## Installation
|
|
15
18
|
|
|
@@ -21,17 +24,17 @@ yarn add @pear-protocol/hyperliquid-sdk
|
|
|
21
24
|
|
|
22
25
|
### Peer Dependencies
|
|
23
26
|
|
|
24
|
-
This
|
|
27
|
+
This SDK requires React 18 or higher:
|
|
25
28
|
|
|
26
29
|
```bash
|
|
27
30
|
npm install react react-dom
|
|
31
|
+
# or
|
|
32
|
+
yarn add react react-dom
|
|
28
33
|
```
|
|
29
34
|
|
|
30
35
|
## Quick Start
|
|
31
36
|
|
|
32
|
-
### 1. Provider
|
|
33
|
-
|
|
34
|
-
Wrap your application with the `PearHyperliquidProvider`:
|
|
37
|
+
### 1. Wrap your application with the Provider
|
|
35
38
|
|
|
36
39
|
```tsx
|
|
37
40
|
import { PearHyperliquidProvider } from '@pear-protocol/hyperliquid-sdk';
|
|
@@ -39,389 +42,681 @@ import { PearHyperliquidProvider } from '@pear-protocol/hyperliquid-sdk';
|
|
|
39
42
|
function App() {
|
|
40
43
|
return (
|
|
41
44
|
<PearHyperliquidProvider
|
|
42
|
-
apiBaseUrl="https://
|
|
43
|
-
wsUrl="wss://
|
|
44
|
-
clientId="
|
|
45
|
+
apiBaseUrl="https://hl-v2.pearprotocol.io"
|
|
46
|
+
wsUrl="wss://hl-v2.pearprotocol.io/ws"
|
|
47
|
+
clientId="YOUR_CLIENT_ID"
|
|
45
48
|
>
|
|
46
|
-
<
|
|
49
|
+
<YourApp />
|
|
47
50
|
</PearHyperliquidProvider>
|
|
48
51
|
);
|
|
49
52
|
}
|
|
50
53
|
```
|
|
51
54
|
|
|
52
|
-
### 2.
|
|
55
|
+
### 2. Use hooks in your components
|
|
56
|
+
|
|
57
|
+
```tsx
|
|
58
|
+
import {
|
|
59
|
+
usePearAuth,
|
|
60
|
+
usePearHyperliquid,
|
|
61
|
+
usePosition,
|
|
62
|
+
useOrders
|
|
63
|
+
} from '@pear-protocol/hyperliquid-sdk';
|
|
64
|
+
|
|
65
|
+
function TradingComponent() {
|
|
66
|
+
const { address, setAddress } = usePearHyperliquid();
|
|
67
|
+
const { isAuthenticated, loginWithSignedMessage } = usePearAuth();
|
|
68
|
+
const { openPositions, createPosition } = usePosition();
|
|
69
|
+
const { openOrders, cancelOrder } = useOrders();
|
|
70
|
+
|
|
71
|
+
// Your component logic
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Core Concepts
|
|
76
|
+
|
|
77
|
+
### Provider Configuration
|
|
78
|
+
|
|
79
|
+
The `PearHyperliquidProvider` accepts the following props:
|
|
80
|
+
|
|
81
|
+
| Prop | Type | Default | Description |
|
|
82
|
+
|------|------|---------|-------------|
|
|
83
|
+
| `apiBaseUrl` | `string` | `https://hl-v2.pearprotocol.io` | Pear API base URL |
|
|
84
|
+
| `wsUrl` | `string` | `wss://hl-v2.pearprotocol.io/ws` | Pear WebSocket URL |
|
|
85
|
+
| `clientId` | `string` | `PEARPROTOCOLUI` | Client identifier for authentication |
|
|
53
86
|
|
|
54
|
-
|
|
87
|
+
### Authentication
|
|
88
|
+
|
|
89
|
+
The SDK supports two authentication methods:
|
|
90
|
+
|
|
91
|
+
#### EIP-712 Signature Authentication
|
|
55
92
|
|
|
56
93
|
```tsx
|
|
57
94
|
import { usePearAuth } from '@pear-protocol/hyperliquid-sdk';
|
|
58
95
|
|
|
59
96
|
function LoginComponent() {
|
|
60
|
-
const {
|
|
61
|
-
isAuthenticated,
|
|
62
|
-
getEip712,
|
|
63
|
-
loginWithSignedMessage,
|
|
64
|
-
logout
|
|
65
|
-
} = usePearAuth();
|
|
66
|
-
|
|
67
|
-
const handleWalletConnect = async (address: string, signMessage: Function) => {
|
|
68
|
-
try {
|
|
69
|
-
// Get EIP-712 message to sign
|
|
70
|
-
const messageData = await getEip712(address);
|
|
97
|
+
const { getEip712, loginWithSignedMessage, isAuthenticated } = usePearAuth();
|
|
71
98
|
|
|
72
|
-
|
|
73
|
-
|
|
99
|
+
const handleLogin = async (address: string, signer: any) => {
|
|
100
|
+
// Get EIP-712 message
|
|
101
|
+
const eip712Data = await getEip712(address);
|
|
74
102
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
103
|
+
// Sign with wallet
|
|
104
|
+
const signature = await signer.signTypedData(
|
|
105
|
+
eip712Data.domain,
|
|
106
|
+
eip712Data.types,
|
|
107
|
+
eip712Data.message
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
// Authenticate
|
|
111
|
+
await loginWithSignedMessage(address, signature, eip712Data.timestamp);
|
|
80
112
|
};
|
|
81
113
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
114
|
+
return (
|
|
115
|
+
<div>
|
|
116
|
+
{isAuthenticated ? 'Logged In' : 'Logged Out'}
|
|
117
|
+
</div>
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
#### Privy Token Authentication
|
|
85
123
|
|
|
86
|
-
|
|
124
|
+
```tsx
|
|
125
|
+
import { usePearAuth } from '@pear-protocol/hyperliquid-sdk';
|
|
126
|
+
|
|
127
|
+
function PrivyLoginComponent() {
|
|
128
|
+
const { loginWithPrivyToken, isAuthenticated } = usePearAuth();
|
|
129
|
+
|
|
130
|
+
const handlePrivyLogin = async (address: string, appId: string, accessToken: string) => {
|
|
131
|
+
await loginWithPrivyToken(address, appId, accessToken);
|
|
132
|
+
};
|
|
87
133
|
}
|
|
88
134
|
```
|
|
89
135
|
|
|
90
|
-
|
|
136
|
+
## API Reference
|
|
137
|
+
|
|
138
|
+
### Hooks
|
|
139
|
+
|
|
140
|
+
#### Core Hooks
|
|
91
141
|
|
|
92
|
-
|
|
142
|
+
##### `usePearHyperliquid()`
|
|
143
|
+
|
|
144
|
+
Access the entire SDK context. Prefer using more specific hooks when possible.
|
|
93
145
|
|
|
94
146
|
```tsx
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
147
|
+
const {
|
|
148
|
+
apiBaseUrl,
|
|
149
|
+
wsUrl,
|
|
150
|
+
address,
|
|
151
|
+
setAddress,
|
|
152
|
+
connectionStatus,
|
|
153
|
+
isConnected,
|
|
154
|
+
nativeConnectionStatus,
|
|
155
|
+
nativeIsConnected,
|
|
156
|
+
authStatus,
|
|
157
|
+
isAuthenticated,
|
|
158
|
+
accessToken,
|
|
159
|
+
user,
|
|
160
|
+
// ... and more
|
|
161
|
+
} = usePearHyperliquid();
|
|
162
|
+
```
|
|
101
163
|
|
|
102
|
-
|
|
103
|
-
const { address, setAddress } = usePearHyperliquid();
|
|
104
|
-
const { data: positions, isLoading: positionsLoading } = useOpenPositions();
|
|
105
|
-
const { data: orders, isLoading: ordersLoading } = useOpenOrders();
|
|
106
|
-
const { data: accountSummary } = useAccountSummary();
|
|
164
|
+
##### `usePearAuth()`
|
|
107
165
|
|
|
108
|
-
|
|
109
|
-
useEffect(() => {
|
|
110
|
-
if (userWalletAddress) {
|
|
111
|
-
setAddress(userWalletAddress);
|
|
112
|
-
}
|
|
113
|
-
}, [userWalletAddress, setAddress]);
|
|
166
|
+
Authentication state and actions.
|
|
114
167
|
|
|
115
|
-
|
|
168
|
+
```tsx
|
|
169
|
+
const {
|
|
170
|
+
status, // AuthStatus enum
|
|
171
|
+
isAuthenticated, // boolean
|
|
172
|
+
user, // UserProfile | null
|
|
173
|
+
error, // string | null
|
|
174
|
+
getEip712, // (address: string) => Promise<EIP712MessageResponse>
|
|
175
|
+
loginWithSignedMessage, // (address, signature, timestamp) => Promise<void>
|
|
176
|
+
loginWithPrivyToken, // (address, appId, accessToken) => Promise<void>
|
|
177
|
+
refreshTokens, // () => Promise<any>
|
|
178
|
+
logout, // () => Promise<void>
|
|
179
|
+
} = usePearAuth();
|
|
180
|
+
```
|
|
116
181
|
|
|
117
|
-
|
|
118
|
-
<div>
|
|
119
|
-
<h2>Account Summary</h2>
|
|
120
|
-
<div>Total Value: ${accountSummary?.accountValue?.toFixed(2)}</div>
|
|
182
|
+
##### `usePearAgentWallet()`
|
|
121
183
|
|
|
122
|
-
|
|
123
|
-
{positions?.map((position) => (
|
|
124
|
-
<div key={position.coin}>
|
|
125
|
-
{position.coin}: {position.szi} @ ${position.entryPx}
|
|
126
|
-
</div>
|
|
127
|
-
))}
|
|
184
|
+
Agent wallet management.
|
|
128
185
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
)
|
|
137
|
-
|
|
186
|
+
```tsx
|
|
187
|
+
const {
|
|
188
|
+
agentWallet, // AgentWalletState
|
|
189
|
+
isReady, // boolean
|
|
190
|
+
loading, // boolean
|
|
191
|
+
error, // string | null
|
|
192
|
+
refreshAgentWalletStatus, // () => Promise<any>
|
|
193
|
+
createAgentWallet, // () => Promise<any>
|
|
194
|
+
notifyAgentWalletApproved, // () => Promise<any>
|
|
195
|
+
} = usePearAgentWallet();
|
|
138
196
|
```
|
|
139
197
|
|
|
140
|
-
|
|
198
|
+
#### Position Management
|
|
141
199
|
|
|
142
|
-
|
|
200
|
+
##### `usePosition()`
|
|
201
|
+
|
|
202
|
+
Manage trading positions.
|
|
143
203
|
|
|
144
204
|
```tsx
|
|
145
|
-
|
|
205
|
+
const {
|
|
206
|
+
createPosition, // (payload) => Promise<ApiResponse<CreatePositionResponseDto>>
|
|
207
|
+
updateRiskParameters, // (positionId, payload) => Promise<ApiResponse<UpdateRiskParametersResponseDto>>
|
|
208
|
+
closePosition, // (positionId, payload) => Promise<ApiResponse<ClosePositionResponseDto>>
|
|
209
|
+
closeAllPositions, // (payload) => Promise<ApiResponse<CloseAllPositionsResponseDto>>
|
|
210
|
+
adjustPosition, // (positionId, payload) => Promise<ApiResponse<AdjustPositionResponseDto>>
|
|
211
|
+
openPositions, // OpenPositionDto[] | null
|
|
212
|
+
isLoading, // boolean
|
|
213
|
+
} = usePosition();
|
|
214
|
+
```
|
|
146
215
|
|
|
147
|
-
|
|
148
|
-
const { createPosition, data: positions } = usePosition();
|
|
216
|
+
**Example: Create a Position**
|
|
149
217
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
}
|
|
218
|
+
```tsx
|
|
219
|
+
const { createPosition } = usePosition();
|
|
220
|
+
|
|
221
|
+
const handleCreatePosition = async () => {
|
|
222
|
+
try {
|
|
223
|
+
const response = await createPosition({
|
|
224
|
+
leverage: 5,
|
|
225
|
+
usdValue: 1000,
|
|
226
|
+
longAssets: [{ asset: 'ETH', weight: 1 }],
|
|
227
|
+
shortAssets: [{ asset: 'BTC', weight: 1 }],
|
|
228
|
+
orderType: 'MARKET',
|
|
229
|
+
});
|
|
230
|
+
console.log('Position created:', response.data);
|
|
231
|
+
} catch (error) {
|
|
232
|
+
console.error('Failed to create position:', error);
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
```
|
|
164
236
|
|
|
165
|
-
|
|
166
|
-
<div>
|
|
167
|
-
<button onClick={handleCreatePosition}>
|
|
168
|
-
Open ETH Long Position
|
|
169
|
-
</button>
|
|
237
|
+
**Example: Close a Position**
|
|
170
238
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
239
|
+
```tsx
|
|
240
|
+
const { closePosition } = usePosition();
|
|
241
|
+
|
|
242
|
+
const handleClosePosition = async (positionId: string) => {
|
|
243
|
+
try {
|
|
244
|
+
const response = await closePosition(positionId, {
|
|
245
|
+
orderType: 'MARKET',
|
|
246
|
+
});
|
|
247
|
+
console.log('Position closed:', response.data);
|
|
248
|
+
} catch (error) {
|
|
249
|
+
console.error('Failed to close position:', error);
|
|
250
|
+
}
|
|
251
|
+
};
|
|
177
252
|
```
|
|
178
253
|
|
|
179
|
-
|
|
254
|
+
#### Order Management
|
|
255
|
+
|
|
256
|
+
##### `useOrders()`
|
|
180
257
|
|
|
181
|
-
Manage
|
|
258
|
+
Manage orders (LIMIT, TP/SL, TWAP).
|
|
182
259
|
|
|
183
260
|
```tsx
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
refreshAgentWalletStatus
|
|
193
|
-
} = usePearAgentWallet();
|
|
194
|
-
|
|
195
|
-
const handleCreateWallet = async () => {
|
|
196
|
-
try {
|
|
197
|
-
await createAgentWallet();
|
|
198
|
-
console.log('Agent wallet created successfully');
|
|
199
|
-
} catch (error) {
|
|
200
|
-
console.error('Failed to create agent wallet:', error);
|
|
201
|
-
}
|
|
202
|
-
};
|
|
261
|
+
const {
|
|
262
|
+
adjustOrder, // (orderId, payload) => Promise<ApiResponse<AdjustOrderResponseDto>>
|
|
263
|
+
cancelOrder, // (orderId) => Promise<ApiResponse<CancelOrderResponseDto>>
|
|
264
|
+
cancelTwapOrder, // (orderId) => Promise<ApiResponse<CancelTwapResponseDto>>
|
|
265
|
+
openOrders, // OpenLimitOrderDto[] | null
|
|
266
|
+
isLoading, // boolean
|
|
267
|
+
} = useOrders();
|
|
268
|
+
```
|
|
203
269
|
|
|
204
|
-
|
|
270
|
+
**Example: Cancel an Order**
|
|
205
271
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
);
|
|
272
|
+
```tsx
|
|
273
|
+
const { cancelOrder } = useOrders();
|
|
274
|
+
|
|
275
|
+
const handleCancelOrder = async (orderId: string) => {
|
|
276
|
+
try {
|
|
277
|
+
await cancelOrder(orderId);
|
|
278
|
+
console.log('Order cancelled successfully');
|
|
279
|
+
} catch (error) {
|
|
280
|
+
console.error('Failed to cancel order:', error);
|
|
212
281
|
}
|
|
282
|
+
};
|
|
283
|
+
```
|
|
213
284
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
</div>
|
|
223
|
-
);
|
|
224
|
-
}
|
|
285
|
+
#### Trading Data
|
|
286
|
+
|
|
287
|
+
##### `useTradeHistories()`
|
|
288
|
+
|
|
289
|
+
Access trade history data.
|
|
290
|
+
|
|
291
|
+
```tsx
|
|
292
|
+
const { data, isLoading } = useTradeHistories();
|
|
225
293
|
```
|
|
226
294
|
|
|
227
|
-
|
|
295
|
+
##### `useOpenOrders()`
|
|
228
296
|
|
|
229
|
-
|
|
297
|
+
Access open orders with loading state.
|
|
298
|
+
|
|
299
|
+
```tsx
|
|
300
|
+
const { data, isLoading } = useOpenOrders();
|
|
301
|
+
```
|
|
230
302
|
|
|
231
|
-
|
|
303
|
+
##### `useAccountSummary()`
|
|
304
|
+
|
|
305
|
+
Access account summary with real-time calculations.
|
|
232
306
|
|
|
233
307
|
```tsx
|
|
234
|
-
|
|
308
|
+
const { data, isLoading } = useAccountSummary();
|
|
309
|
+
// data: AccountSummaryResponseDto | null
|
|
310
|
+
```
|
|
235
311
|
|
|
236
|
-
|
|
237
|
-
const { isConnected, lastError } = useHyperliquidWebSocket({
|
|
238
|
-
wsUrl: 'wss://api.pear.garden/ws',
|
|
239
|
-
address: userAddress
|
|
240
|
-
});
|
|
312
|
+
#### Market Data
|
|
241
313
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
314
|
+
##### `useMarketData()`
|
|
315
|
+
|
|
316
|
+
Access real-time market data from Zustand store.
|
|
317
|
+
|
|
318
|
+
```tsx
|
|
319
|
+
import { useMarketData } from '@pear-protocol/hyperliquid-sdk';
|
|
320
|
+
|
|
321
|
+
function MarketDataComponent() {
|
|
322
|
+
const activeAssets = useMarketData((state) => state.activeAssets);
|
|
247
323
|
|
|
248
324
|
return (
|
|
249
325
|
<div>
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
326
|
+
{activeAssets?.active.map((asset, idx) => (
|
|
327
|
+
<div key={idx}>
|
|
328
|
+
Long: {asset.longAssets.map(a => a.asset).join(', ')} vs
|
|
329
|
+
Short: {asset.shortAssets.map(a => a.asset).join(', ')}
|
|
330
|
+
</div>
|
|
331
|
+
))}
|
|
253
332
|
</div>
|
|
254
333
|
);
|
|
255
334
|
}
|
|
256
335
|
```
|
|
257
336
|
|
|
258
|
-
|
|
337
|
+
##### `useHistoricalPriceData()`
|
|
259
338
|
|
|
260
|
-
|
|
339
|
+
Fetch and manage historical price data for tokens.
|
|
261
340
|
|
|
262
341
|
```tsx
|
|
263
|
-
import {
|
|
264
|
-
useHistoricalPriceData,
|
|
265
|
-
useBasketCandles,
|
|
266
|
-
useHistoricalPriceDataStore
|
|
267
|
-
} from '@pear-protocol/hyperliquid-sdk';
|
|
342
|
+
import { useHistoricalPriceData } from '@pear-protocol/hyperliquid-sdk';
|
|
268
343
|
|
|
269
344
|
function ChartComponent() {
|
|
270
|
-
const {
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
345
|
+
const { fetchHistoricalData, getTokenData } = useHistoricalPriceData();
|
|
346
|
+
|
|
347
|
+
useEffect(() => {
|
|
348
|
+
fetchHistoricalData('ETH', '1d'); // 1 day range
|
|
349
|
+
}, []);
|
|
350
|
+
|
|
351
|
+
const ethData = getTokenData('ETH');
|
|
352
|
+
}
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
##### `useBasketCandles()`
|
|
356
|
+
|
|
357
|
+
Get candle data for basket (multi-asset) positions.
|
|
358
|
+
|
|
359
|
+
```tsx
|
|
360
|
+
import { useBasketCandles } from '@pear-protocol/hyperliquid-sdk';
|
|
274
361
|
|
|
275
|
-
|
|
276
|
-
|
|
362
|
+
function BasketChartComponent() {
|
|
363
|
+
const { candles, isLoading, error } = useBasketCandles({
|
|
364
|
+
longAssets: [{ symbol: 'ETH', weight: 0.5 }, { symbol: 'BTC', weight: 0.5 }],
|
|
365
|
+
shortAssets: [{ symbol: 'SOL', weight: 1 }],
|
|
277
366
|
interval: '1h',
|
|
278
|
-
|
|
367
|
+
lookbackHours: 24,
|
|
279
368
|
});
|
|
369
|
+
}
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
##### `useTokenSelectionMetadata()`
|
|
373
|
+
|
|
374
|
+
Get metadata for selected tokens including prices, funding, and leverage info.
|
|
375
|
+
|
|
376
|
+
```tsx
|
|
377
|
+
import { useTokenSelectionMetadata } from '@pear-protocol/hyperliquid-sdk';
|
|
378
|
+
|
|
379
|
+
function TokenSelector() {
|
|
380
|
+
const { getMetadata, isLoading } = useTokenSelectionMetadata();
|
|
381
|
+
|
|
382
|
+
const ethMetadata = getMetadata('ETH');
|
|
383
|
+
// ethMetadata: { currentPrice, priceChange24hPercent, maxLeverage, ... }
|
|
384
|
+
}
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
#### WebSocket Hooks
|
|
388
|
+
|
|
389
|
+
##### `useHyperliquidWebSocket()`
|
|
390
|
+
|
|
391
|
+
Access Pear API WebSocket connection (managed by provider).
|
|
392
|
+
|
|
393
|
+
##### `useHyperliquidNativeWebSocket()`
|
|
394
|
+
|
|
395
|
+
Access HyperLiquid native WebSocket connection (managed by provider).
|
|
396
|
+
|
|
397
|
+
#### TWAP Orders
|
|
398
|
+
|
|
399
|
+
##### `useTwap()`
|
|
400
|
+
|
|
401
|
+
Access TWAP (Time-Weighted Average Price) order monitoring.
|
|
402
|
+
|
|
403
|
+
```tsx
|
|
404
|
+
import { useTwap } from '@pear-protocol/hyperliquid-sdk';
|
|
405
|
+
|
|
406
|
+
function TwapMonitor() {
|
|
407
|
+
const { twapOrders, isLoading } = useTwap();
|
|
280
408
|
|
|
281
409
|
return (
|
|
282
410
|
<div>
|
|
283
|
-
{
|
|
411
|
+
{twapOrders?.map(order => (
|
|
412
|
+
<div key={order.orderId}>
|
|
413
|
+
Status: {order.status}
|
|
414
|
+
Progress: {order.filledUsdValue / order.totalUsdValue * 100}%
|
|
415
|
+
</div>
|
|
416
|
+
))}
|
|
284
417
|
</div>
|
|
285
418
|
);
|
|
286
419
|
}
|
|
287
420
|
```
|
|
288
421
|
|
|
289
|
-
|
|
422
|
+
#### Notifications
|
|
290
423
|
|
|
291
|
-
|
|
424
|
+
##### `useNotifications()`
|
|
292
425
|
|
|
293
|
-
|
|
294
|
-
import {
|
|
295
|
-
AccountSummaryCalculator,
|
|
296
|
-
ConflictDetector,
|
|
297
|
-
TokenMetadataExtractor,
|
|
298
|
-
calculateWeightedRatio
|
|
299
|
-
} from '@pear-protocol/hyperliquid-sdk';
|
|
426
|
+
Access user notifications.
|
|
300
427
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
const accountValue = calculator.getTotalAccountValue();
|
|
428
|
+
```tsx
|
|
429
|
+
import { useNotifications } from '@pear-protocol/hyperliquid-sdk';
|
|
304
430
|
|
|
305
|
-
|
|
306
|
-
const
|
|
307
|
-
const conflicts = detector.detectConflicts(tokenSelections);
|
|
431
|
+
function NotificationCenter() {
|
|
432
|
+
const { notifications, isLoading, markAsRead, markAllAsRead } = useNotifications();
|
|
308
433
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
434
|
+
return (
|
|
435
|
+
<div>
|
|
436
|
+
{notifications?.map(notif => (
|
|
437
|
+
<div key={notif.id} onClick={() => markAsRead(notif.id)}>
|
|
438
|
+
{notif.category}: {JSON.stringify(notif.parameters)}
|
|
439
|
+
</div>
|
|
440
|
+
))}
|
|
441
|
+
</div>
|
|
442
|
+
);
|
|
443
|
+
}
|
|
312
444
|
```
|
|
313
445
|
|
|
314
|
-
|
|
446
|
+
### Utility Classes
|
|
315
447
|
|
|
316
|
-
|
|
448
|
+
#### `AccountSummaryCalculator`
|
|
317
449
|
|
|
318
|
-
|
|
450
|
+
Calculate account summary with real-time data.
|
|
319
451
|
|
|
320
452
|
```tsx
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
wsUrl="wss://api.pear.garden/ws"
|
|
331
|
-
>
|
|
332
|
-
|
|
333
|
-
// Beta
|
|
334
|
-
<PearHyperliquidProvider
|
|
335
|
-
apiBaseUrl="https://beta-api.pear.garden"
|
|
336
|
-
wsUrl="wss://beta-api.pear.garden/ws"
|
|
337
|
-
>
|
|
453
|
+
import { AccountSummaryCalculator } from '@pear-protocol/hyperliquid-sdk';
|
|
454
|
+
|
|
455
|
+
const calculator = new AccountSummaryCalculator(webData2);
|
|
456
|
+
const summary = calculator.calculateAccountSummary(
|
|
457
|
+
accountSummary,
|
|
458
|
+
openOrders,
|
|
459
|
+
agentWalletAddress,
|
|
460
|
+
agentWalletStatus
|
|
461
|
+
);
|
|
338
462
|
```
|
|
339
463
|
|
|
340
|
-
|
|
464
|
+
#### `ConflictDetector`
|
|
341
465
|
|
|
342
|
-
|
|
466
|
+
Detect position conflicts for new trades.
|
|
343
467
|
|
|
344
468
|
```tsx
|
|
345
|
-
|
|
346
|
-
await loginWithSignedMessage(address, signature, timestamp);
|
|
469
|
+
import { ConflictDetector } from '@pear-protocol/hyperliquid-sdk';
|
|
347
470
|
|
|
348
|
-
|
|
349
|
-
|
|
471
|
+
const conflicts = ConflictDetector.detectConflicts(
|
|
472
|
+
longTokens,
|
|
473
|
+
shortTokens,
|
|
474
|
+
existingPositions
|
|
475
|
+
);
|
|
350
476
|
```
|
|
351
477
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
### Core Hooks
|
|
478
|
+
#### `TokenMetadataExtractor`
|
|
355
479
|
|
|
356
|
-
|
|
357
|
-
- `usePearAuth()` - Authentication state and methods
|
|
358
|
-
- `usePearAgentWallet()` - Agent wallet management
|
|
480
|
+
Extract token metadata from WebSocket data.
|
|
359
481
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
482
|
+
```tsx
|
|
483
|
+
import { TokenMetadataExtractor } from '@pear-protocol/hyperliquid-sdk';
|
|
484
|
+
|
|
485
|
+
const metadata = TokenMetadataExtractor.extractMetadata(
|
|
486
|
+
'ETH',
|
|
487
|
+
webData2,
|
|
488
|
+
allMids,
|
|
489
|
+
activeAssetData
|
|
490
|
+
);
|
|
491
|
+
```
|
|
367
492
|
|
|
368
|
-
###
|
|
493
|
+
### Direct API Clients
|
|
369
494
|
|
|
370
|
-
|
|
371
|
-
- `useHistoricalPriceData()` - Historical price charts
|
|
372
|
-
- `useBasketCandles()` - Basket/portfolio candle data
|
|
373
|
-
- `useTokenSelectionMetadata()` - Token metadata and conflicts
|
|
495
|
+
For advanced use cases, you can import and use API clients directly:
|
|
374
496
|
|
|
375
|
-
|
|
497
|
+
```tsx
|
|
498
|
+
import {
|
|
499
|
+
createPosition,
|
|
500
|
+
updateRiskParameters,
|
|
501
|
+
closePosition,
|
|
502
|
+
adjustOrder,
|
|
503
|
+
cancelOrder,
|
|
504
|
+
} from '@pear-protocol/hyperliquid-sdk';
|
|
376
505
|
|
|
377
|
-
|
|
378
|
-
|
|
506
|
+
// All client functions require baseUrl and accessToken
|
|
507
|
+
const response = await createPosition(baseUrl, accessToken, {
|
|
508
|
+
leverage: 5,
|
|
509
|
+
usdValue: 1000,
|
|
510
|
+
longAssets: [{ asset: 'ETH', weight: 1 }],
|
|
511
|
+
shortAssets: [{ asset: 'BTC', weight: 1 }],
|
|
512
|
+
orderType: 'MARKET',
|
|
513
|
+
});
|
|
514
|
+
```
|
|
379
515
|
|
|
380
516
|
## TypeScript Support
|
|
381
517
|
|
|
382
|
-
The SDK is
|
|
518
|
+
The SDK is written in TypeScript and provides comprehensive type definitions. All hooks, functions, and data structures are fully typed.
|
|
383
519
|
|
|
384
520
|
```tsx
|
|
385
521
|
import type {
|
|
386
522
|
OpenPositionDto,
|
|
523
|
+
OpenLimitOrderDto,
|
|
524
|
+
TradeHistoryDataDto,
|
|
387
525
|
AccountSummaryResponseDto,
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
526
|
+
WebSocketChannel,
|
|
527
|
+
CandleInterval,
|
|
528
|
+
TokenMetadata,
|
|
529
|
+
// ... and many more
|
|
391
530
|
} from '@pear-protocol/hyperliquid-sdk';
|
|
392
531
|
```
|
|
393
532
|
|
|
533
|
+
## WebSocket Data Flow
|
|
534
|
+
|
|
535
|
+
The SDK manages two WebSocket connections:
|
|
536
|
+
|
|
537
|
+
1. **Pear API WebSocket** - User-specific data (positions, orders, trade history, account summary)
|
|
538
|
+
2. **HyperLiquid Native WebSocket** - Market data (prices, asset info, candles)
|
|
539
|
+
|
|
540
|
+
Data is automatically stored in Zustand stores and accessible via hooks:
|
|
541
|
+
|
|
542
|
+
- `useUserData` store - User positions, orders, and account data
|
|
543
|
+
- `useHyperliquidData` store - Market data (webData2, allMids, activeAssetData)
|
|
544
|
+
- `useHistoricalPriceDataStore` - Historical price data
|
|
545
|
+
- `useMarketData` store - Active assets and market overview
|
|
546
|
+
|
|
394
547
|
## Error Handling
|
|
395
548
|
|
|
396
|
-
|
|
549
|
+
All API functions return promises and throw errors on failure. Always wrap API calls in try-catch blocks:
|
|
397
550
|
|
|
398
551
|
```tsx
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
console.error('Auth failed:', authError);
|
|
552
|
+
try {
|
|
553
|
+
await createPosition(payload);
|
|
554
|
+
} catch (error) {
|
|
555
|
+
if (error instanceof Error) {
|
|
556
|
+
console.error('Error:', error.message);
|
|
557
|
+
}
|
|
406
558
|
}
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
## Environment Variables
|
|
562
|
+
|
|
563
|
+
When using the SDK, you may want to configure different environments:
|
|
564
|
+
|
|
565
|
+
```tsx
|
|
566
|
+
// Production
|
|
567
|
+
<PearHyperliquidProvider
|
|
568
|
+
apiBaseUrl="https://hl-v2.pearprotocol.io"
|
|
569
|
+
wsUrl="wss://hl-v2.pearprotocol.io/ws"
|
|
570
|
+
/>
|
|
571
|
+
|
|
572
|
+
// Beta
|
|
573
|
+
<PearHyperliquidProvider
|
|
574
|
+
apiBaseUrl="https://hl-v2-beta.pearprotocol.io"
|
|
575
|
+
wsUrl="wss://hl-v2-beta.pearprotocol.io/ws"
|
|
576
|
+
/>
|
|
577
|
+
```
|
|
578
|
+
|
|
579
|
+
## Examples
|
|
580
|
+
|
|
581
|
+
### Complete Trading Component
|
|
582
|
+
|
|
583
|
+
```tsx
|
|
584
|
+
import { useState } from 'react';
|
|
585
|
+
import {
|
|
586
|
+
usePearAuth,
|
|
587
|
+
usePearHyperliquid,
|
|
588
|
+
usePosition,
|
|
589
|
+
useOrders,
|
|
590
|
+
useAccountSummary,
|
|
591
|
+
} from '@pear-protocol/hyperliquid-sdk';
|
|
407
592
|
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
593
|
+
function TradingDashboard() {
|
|
594
|
+
const { address, setAddress, isConnected } = usePearHyperliquid();
|
|
595
|
+
const { isAuthenticated, loginWithSignedMessage } = usePearAuth();
|
|
596
|
+
const { openPositions, createPosition, closePosition } = usePosition();
|
|
597
|
+
const { openOrders, cancelOrder } = useOrders();
|
|
598
|
+
const { data: accountSummary } = useAccountSummary();
|
|
599
|
+
|
|
600
|
+
const handleCreatePosition = async () => {
|
|
601
|
+
try {
|
|
602
|
+
await createPosition({
|
|
603
|
+
leverage: 3,
|
|
604
|
+
usdValue: 500,
|
|
605
|
+
longAssets: [{ asset: 'ETH', weight: 1 }],
|
|
606
|
+
shortAssets: [{ asset: 'BTC', weight: 1 }],
|
|
607
|
+
orderType: 'MARKET',
|
|
608
|
+
});
|
|
609
|
+
} catch (error) {
|
|
610
|
+
console.error('Failed to create position:', error);
|
|
611
|
+
}
|
|
612
|
+
};
|
|
613
|
+
|
|
614
|
+
return (
|
|
615
|
+
<div>
|
|
616
|
+
<h1>Trading Dashboard</h1>
|
|
617
|
+
|
|
618
|
+
<div>
|
|
619
|
+
<h2>Account</h2>
|
|
620
|
+
<p>Address: {address || 'Not connected'}</p>
|
|
621
|
+
<p>Status: {isAuthenticated ? 'Authenticated' : 'Not authenticated'}</p>
|
|
622
|
+
<p>WebSocket: {isConnected ? 'Connected' : 'Disconnected'}</p>
|
|
623
|
+
</div>
|
|
624
|
+
|
|
625
|
+
<div>
|
|
626
|
+
<h2>Account Summary</h2>
|
|
627
|
+
<p>Account Value: ${accountSummary?.balanceSummary.marginSummary.accountValue}</p>
|
|
628
|
+
<p>Withdrawable: ${accountSummary?.balanceSummary.withdrawable}</p>
|
|
629
|
+
</div>
|
|
630
|
+
|
|
631
|
+
<div>
|
|
632
|
+
<h2>Open Positions</h2>
|
|
633
|
+
{openPositions?.map(pos => (
|
|
634
|
+
<div key={pos.positionId}>
|
|
635
|
+
<p>PNL: ${pos.unrealizedPnl.toFixed(2)}</p>
|
|
636
|
+
<p>Value: ${pos.positionValue.toFixed(2)}</p>
|
|
637
|
+
<button onClick={() => closePosition(pos.positionId, { orderType: 'MARKET' })}>
|
|
638
|
+
Close
|
|
639
|
+
</button>
|
|
640
|
+
</div>
|
|
641
|
+
))}
|
|
642
|
+
</div>
|
|
643
|
+
|
|
644
|
+
<div>
|
|
645
|
+
<h2>Open Orders</h2>
|
|
646
|
+
{openOrders?.map(order => (
|
|
647
|
+
<div key={order.orderId}>
|
|
648
|
+
<p>Type: {order.orderType}</p>
|
|
649
|
+
<p>Value: ${order.usdValue}</p>
|
|
650
|
+
<button onClick={() => cancelOrder(order.orderId)}>Cancel</button>
|
|
651
|
+
</div>
|
|
652
|
+
))}
|
|
653
|
+
</div>
|
|
654
|
+
|
|
655
|
+
<button onClick={handleCreatePosition}>
|
|
656
|
+
Create New Position
|
|
657
|
+
</button>
|
|
658
|
+
</div>
|
|
659
|
+
);
|
|
411
660
|
}
|
|
661
|
+
|
|
662
|
+
export default TradingDashboard;
|
|
412
663
|
```
|
|
413
664
|
|
|
414
|
-
|
|
665
|
+
### Market Data Component
|
|
415
666
|
|
|
416
|
-
|
|
667
|
+
```tsx
|
|
668
|
+
import {
|
|
669
|
+
useMarketData,
|
|
670
|
+
useTokenSelectionMetadata,
|
|
671
|
+
useHyperliquidWebSocket,
|
|
672
|
+
} from '@pear-protocol/hyperliquid-sdk';
|
|
673
|
+
|
|
674
|
+
function MarketOverview() {
|
|
675
|
+
const activeAssets = useMarketData((state) => state.activeAssets);
|
|
676
|
+
const { getMetadata } = useTokenSelectionMetadata();
|
|
677
|
+
|
|
678
|
+
return (
|
|
679
|
+
<div>
|
|
680
|
+
<h2>Top Gainers</h2>
|
|
681
|
+
{activeAssets?.topGainers.slice(0, 5).map((asset, idx) => {
|
|
682
|
+
const longAsset = asset.longAssets[0]?.asset;
|
|
683
|
+
const metadata = longAsset ? getMetadata(longAsset) : null;
|
|
684
|
+
|
|
685
|
+
return (
|
|
686
|
+
<div key={idx}>
|
|
687
|
+
<p>{longAsset}: {metadata?.priceChange24hPercent.toFixed(2)}%</p>
|
|
688
|
+
</div>
|
|
689
|
+
);
|
|
690
|
+
})}
|
|
691
|
+
|
|
692
|
+
<h2>Top Losers</h2>
|
|
693
|
+
{activeAssets?.topLosers.slice(0, 5).map((asset, idx) => {
|
|
694
|
+
const shortAsset = asset.shortAssets[0]?.asset;
|
|
695
|
+
const metadata = shortAsset ? getMetadata(shortAsset) : null;
|
|
696
|
+
|
|
697
|
+
return (
|
|
698
|
+
<div key={idx}>
|
|
699
|
+
<p>{shortAsset}: {metadata?.priceChange24hPercent.toFixed(2)}%</p>
|
|
700
|
+
</div>
|
|
701
|
+
);
|
|
702
|
+
})}
|
|
703
|
+
</div>
|
|
704
|
+
);
|
|
705
|
+
}
|
|
706
|
+
```
|
|
417
707
|
|
|
418
708
|
## License
|
|
419
709
|
|
|
420
|
-
MIT
|
|
710
|
+
MIT
|
|
711
|
+
|
|
712
|
+
## Repository
|
|
713
|
+
|
|
714
|
+
GitHub: [https://github.com/pear-protocol/hyperliquid](https://github.com/pear-protocol/hyperliquid/tree/main/pear-hyperliquid-sdk)
|
|
421
715
|
|
|
422
716
|
## Support
|
|
423
717
|
|
|
424
|
-
For
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
718
|
+
For issues and questions, please visit the [GitHub Issues](https://github.com/pear-protocol/hyperliquid/issues) page.
|
|
719
|
+
|
|
720
|
+
## Contributing
|
|
721
|
+
|
|
722
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|