@pear-protocol/hyperliquid-sdk 0.0.42 → 0.0.44
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/clients/watchlist.d.ts +2 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/useMarketData.d.ts +1 -0
- package/dist/hooks/useWatchlist.d.ts +6 -0
- package/dist/index.d.ts +24 -2
- package/dist/index.js +69 -12
- package/dist/types.d.ts +13 -0
- 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.
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import type { ApiResponse, ToggleWatchlistResponseDto, WatchlistAssetDto } from '../types';
|
|
2
|
+
export declare function toggleWatchlist(baseUrl: string, accessToken: string, longAssets: WatchlistAssetDto[], shortAssets: WatchlistAssetDto[]): Promise<ApiResponse<ToggleWatchlistResponseDto>>;
|
package/dist/hooks/index.d.ts
CHANGED
|
@@ -4,4 +4,5 @@ export declare const useActiveBaskets: () => ActiveAssetGroupItem[];
|
|
|
4
4
|
export declare const useTopGainers: (limit?: number) => ActiveAssetGroupItem[];
|
|
5
5
|
export declare const useTopLosers: (limit?: number) => ActiveAssetGroupItem[];
|
|
6
6
|
export declare const useHighlightedBaskets: () => ActiveAssetGroupItem[];
|
|
7
|
+
export declare const useWatchlistBaskets: () => ActiveAssetGroupItem[];
|
|
7
8
|
export declare const useFindBasket: (longs: string[], shorts: string[]) => ActiveAssetGroupItem | undefined;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ApiResponse, ToggleWatchlistResponseDto, WatchlistAssetDto, ActiveAssetGroupItem } from '../types';
|
|
2
|
+
export declare function useWatchlist(): {
|
|
3
|
+
readonly watchlists: ActiveAssetGroupItem[] | null;
|
|
4
|
+
readonly isLoading: boolean;
|
|
5
|
+
readonly toggle: (longAssets: WatchlistAssetDto[], shortAssets: WatchlistAssetDto[]) => Promise<ApiResponse<ToggleWatchlistResponseDto>>;
|
|
6
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -53,6 +53,18 @@ interface WebSocketDataMessage<T = unknown> {
|
|
|
53
53
|
channel: WebSocketChannel;
|
|
54
54
|
data: T;
|
|
55
55
|
}
|
|
56
|
+
interface WatchlistAssetDto {
|
|
57
|
+
asset: string;
|
|
58
|
+
weight: number;
|
|
59
|
+
}
|
|
60
|
+
interface WatchlistItemDto {
|
|
61
|
+
id: string;
|
|
62
|
+
longAssets: WatchlistAssetDto[];
|
|
63
|
+
shortAssets: WatchlistAssetDto[];
|
|
64
|
+
}
|
|
65
|
+
interface ToggleWatchlistResponseDto {
|
|
66
|
+
items: WatchlistItemDto[];
|
|
67
|
+
}
|
|
56
68
|
type NotificationCategory = 'TRADE_OPENED_OUTSIDE_PEAR' | 'TRADE_CLOSED_OUTSIDE_PEAR' | 'POSITION_LIQUIDATED' | 'LIMIT_ORDER_FILLED' | 'LIMIT_ORDER_FAILED' | 'TP_ORDER_FILLED' | 'TP_ORDER_FAILED' | 'SL_ORDER_FILLED' | 'SL_ORDER_FAILED';
|
|
57
69
|
interface NotificationDto {
|
|
58
70
|
id: string;
|
|
@@ -532,6 +544,7 @@ interface ActiveAssetsResponse {
|
|
|
532
544
|
topGainers: ActiveAssetGroupItem[];
|
|
533
545
|
topLosers: ActiveAssetGroupItem[];
|
|
534
546
|
highlighted: ActiveAssetGroupItem[];
|
|
547
|
+
watchlist: ActiveAssetGroupItem[];
|
|
535
548
|
}
|
|
536
549
|
/**
|
|
537
550
|
* Candle interval options
|
|
@@ -1011,8 +1024,15 @@ declare const useActiveBaskets: () => ActiveAssetGroupItem[];
|
|
|
1011
1024
|
declare const useTopGainers: (limit?: number) => ActiveAssetGroupItem[];
|
|
1012
1025
|
declare const useTopLosers: (limit?: number) => ActiveAssetGroupItem[];
|
|
1013
1026
|
declare const useHighlightedBaskets: () => ActiveAssetGroupItem[];
|
|
1027
|
+
declare const useWatchlistBaskets: () => ActiveAssetGroupItem[];
|
|
1014
1028
|
declare const useFindBasket: (longs: string[], shorts: string[]) => ActiveAssetGroupItem | undefined;
|
|
1015
1029
|
|
|
1030
|
+
declare function useWatchlist(): {
|
|
1031
|
+
readonly watchlists: ActiveAssetGroupItem[] | null;
|
|
1032
|
+
readonly isLoading: boolean;
|
|
1033
|
+
readonly toggle: (longAssets: WatchlistAssetDto[], shortAssets: WatchlistAssetDto[]) => Promise<ApiResponse<ToggleWatchlistResponseDto>>;
|
|
1034
|
+
};
|
|
1035
|
+
|
|
1016
1036
|
interface UseHyperliquidWebSocketProps {
|
|
1017
1037
|
wsUrl: string;
|
|
1018
1038
|
address: string | null;
|
|
@@ -1047,6 +1067,8 @@ declare function markNotificationReadById(baseUrl: string, accessToken: string,
|
|
|
1047
1067
|
updated: number;
|
|
1048
1068
|
}>>;
|
|
1049
1069
|
|
|
1070
|
+
declare function toggleWatchlist(baseUrl: string, accessToken: string, longAssets: WatchlistAssetDto[], shortAssets: WatchlistAssetDto[]): Promise<ApiResponse<ToggleWatchlistResponseDto>>;
|
|
1071
|
+
|
|
1050
1072
|
/**
|
|
1051
1073
|
* Account summary calculation utility class
|
|
1052
1074
|
*/
|
|
@@ -1151,5 +1173,5 @@ declare function mapCandleIntervalToTradingViewInterval(interval: CandleInterval
|
|
|
1151
1173
|
|
|
1152
1174
|
declare const useMarketData: any;
|
|
1153
1175
|
|
|
1154
|
-
export { AccountSummaryCalculator, AuthStatus, ConflictDetector, PearHyperliquidProvider, TokenMetadataExtractor, adjustOrder, adjustPosition, calculateWeightedRatio, cancelOrder, cancelTwap, cancelTwapOrder, closeAllPositions, closePosition, computeBasketCandles, createCandleLookups, createPosition, getCompleteTimestamps, mapCandleIntervalToTradingViewInterval, mapTradingViewIntervalToCandleInterval, markNotificationReadById, markNotificationsRead, updateRiskParameters, useAccountSummary, useActiveBaskets, useAddress, useAgentWallet, useAuth, useAutoSyncFills, useBasketCandles, useFindBasket, useHighlightedBaskets, useHistoricalPriceData, useHistoricalPriceDataStore, useHyperliquidNativeWebSocket, useHyperliquidWebSocket, useMarketData, useMarketDataPayload, useNotifications, useOpenOrders, useOrders, usePearAgentWallet, usePearAuth, usePearHyperliquid, usePerformanceOverlays, usePosition, useTokenSelectionMetadata, useTopGainers, useTopLosers, useTradeHistories, useTwap, useUserSelection, useWebData };
|
|
1155
|
-
export type { AccountSummaryResponseDto, ActiveAssetGroupItem, ActiveAssetsResponse, AdjustExecutionType, AdjustOrderRequestInput, AdjustOrderResponseDto, AdjustPositionRequestInput, AdjustPositionResponseDto, AgentWalletDto, AgentWalletState, ApiErrorResponse, ApiResponse, AssetCtx, AssetInformationDetail, AssetMarketData, AssetPosition, AutoSyncFillsOptions, AutoSyncFillsState, BalanceSummaryDto, CancelOrderResponseDto, CancelTwapResponseDto, CandleChartData, CandleData, CandleInterval, CandleSnapshotRequest, ClearinghouseState, CloseAllPositionsResponseDto, CloseAllPositionsResultDto, CloseExecutionType, ClosePositionRequestInput, ClosePositionResponseDto, CreatePositionRequestInput, CreatePositionResponseDto, CrossMarginSummaryDto, CumFundingDto, ExecutionType, HLWebSocketResponse, HistoricalRange, LadderConfigInput, MarginSummaryDto, NotificationCategory, NotificationDto, OpenLimitOrderDto, OpenPositionDto, OrderAssetDto, OrderStatus, PairAssetDto, PairAssetInput, PerformanceOverlay, PositionAdjustmentType, PositionAssetDetailDto, PositionAssetSummaryDto, PositionResponseStatus, RealtimeBar, RealtimeBarsCallback, TokenConflict, TokenHistoricalPriceData, TokenMetadata, TokenSelection, TpSlThresholdInput, TpSlThresholdType, TradeHistoryAssetDataDto, TradeHistoryDataDto, TwapChunkStatusDto, TwapMonitoringDto, UniverseAsset, UpdateRiskParametersRequestInput, UpdateRiskParametersResponseDto, UseAgentWalletOptions, UseAuthOptions, UseBasketCandlesReturn, UseHistoricalPriceDataReturn, UseNotificationsResult, UsePerformanceOverlaysReturn, UseTokenSelectionMetadataReturn, UserProfile, UserSelectionState, WebData2Response, WebSocketAckResponse, WebSocketChannel, WebSocketConnectionState, WebSocketDataMessage, WebSocketMessage, WebSocketSubscribeMessage, WsAllMidsData };
|
|
1176
|
+
export { AccountSummaryCalculator, AuthStatus, ConflictDetector, PearHyperliquidProvider, TokenMetadataExtractor, adjustOrder, adjustPosition, calculateWeightedRatio, cancelOrder, cancelTwap, cancelTwapOrder, closeAllPositions, closePosition, computeBasketCandles, createCandleLookups, createPosition, getCompleteTimestamps, mapCandleIntervalToTradingViewInterval, mapTradingViewIntervalToCandleInterval, markNotificationReadById, markNotificationsRead, toggleWatchlist, updateRiskParameters, useAccountSummary, useActiveBaskets, useAddress, useAgentWallet, useAuth, useAutoSyncFills, useBasketCandles, useFindBasket, useHighlightedBaskets, useHistoricalPriceData, useHistoricalPriceDataStore, useHyperliquidNativeWebSocket, useHyperliquidWebSocket, useMarketData, useMarketDataPayload, useNotifications, useOpenOrders, useOrders, usePearAgentWallet, usePearAuth, usePearHyperliquid, usePerformanceOverlays, usePosition, useTokenSelectionMetadata, useTopGainers, useTopLosers, useTradeHistories, useTwap, useUserSelection, useWatchlist, useWatchlistBaskets, useWebData };
|
|
1177
|
+
export type { AccountSummaryResponseDto, ActiveAssetGroupItem, ActiveAssetsResponse, AdjustExecutionType, AdjustOrderRequestInput, AdjustOrderResponseDto, AdjustPositionRequestInput, AdjustPositionResponseDto, AgentWalletDto, AgentWalletState, ApiErrorResponse, ApiResponse, AssetCtx, AssetInformationDetail, AssetMarketData, AssetPosition, AutoSyncFillsOptions, AutoSyncFillsState, BalanceSummaryDto, CancelOrderResponseDto, CancelTwapResponseDto, CandleChartData, CandleData, CandleInterval, CandleSnapshotRequest, ClearinghouseState, CloseAllPositionsResponseDto, CloseAllPositionsResultDto, CloseExecutionType, ClosePositionRequestInput, ClosePositionResponseDto, CreatePositionRequestInput, CreatePositionResponseDto, CrossMarginSummaryDto, CumFundingDto, ExecutionType, HLWebSocketResponse, HistoricalRange, LadderConfigInput, MarginSummaryDto, NotificationCategory, NotificationDto, OpenLimitOrderDto, OpenPositionDto, OrderAssetDto, OrderStatus, PairAssetDto, PairAssetInput, PerformanceOverlay, PositionAdjustmentType, PositionAssetDetailDto, PositionAssetSummaryDto, PositionResponseStatus, RealtimeBar, RealtimeBarsCallback, ToggleWatchlistResponseDto, TokenConflict, TokenHistoricalPriceData, TokenMetadata, TokenSelection, TpSlThresholdInput, TpSlThresholdType, TradeHistoryAssetDataDto, TradeHistoryDataDto, TwapChunkStatusDto, TwapMonitoringDto, UniverseAsset, UpdateRiskParametersRequestInput, UpdateRiskParametersResponseDto, UseAgentWalletOptions, UseAuthOptions, UseBasketCandlesReturn, UseHistoricalPriceDataReturn, UseNotificationsResult, UsePerformanceOverlaysReturn, UseTokenSelectionMetadataReturn, UserProfile, UserSelectionState, WatchlistItemDto, WebData2Response, WebSocketAckResponse, WebSocketChannel, WebSocketConnectionState, WebSocketDataMessage, WebSocketMessage, WebSocketSubscribeMessage, WsAllMidsData };
|
package/dist/index.js
CHANGED
|
@@ -2459,7 +2459,7 @@ const useMarketData = create((set) => ({
|
|
|
2459
2459
|
|
|
2460
2460
|
const useHyperliquidWebSocket = ({ wsUrl, address }) => {
|
|
2461
2461
|
const { setTradeHistories, setRawOpenPositions, setOpenOrders, setAccountSummary, setTwapDetails, setNotifications, clean, } = useUserData();
|
|
2462
|
-
const { setMarketData
|
|
2462
|
+
const { setMarketData } = useMarketData();
|
|
2463
2463
|
const [lastError, setLastError] = useState(null);
|
|
2464
2464
|
const [lastSubscribedAddress, setLastSubscribedAddress] = useState(null);
|
|
2465
2465
|
// WebSocket connection
|
|
@@ -2521,39 +2521,61 @@ const useHyperliquidWebSocket = ({ wsUrl, address }) => {
|
|
|
2521
2521
|
const isConnected = readyState === dist.ReadyState.OPEN;
|
|
2522
2522
|
// Handle subscription management
|
|
2523
2523
|
useEffect(() => {
|
|
2524
|
-
if (isConnected
|
|
2525
|
-
|
|
2524
|
+
if (!isConnected)
|
|
2525
|
+
return;
|
|
2526
|
+
// Define all available channels
|
|
2527
|
+
const addressSpecificChannels = [
|
|
2528
|
+
'trade-histories',
|
|
2529
|
+
'open-positions',
|
|
2530
|
+
'account-summary',
|
|
2531
|
+
'open-orders',
|
|
2532
|
+
'twap-details',
|
|
2533
|
+
'fills-checkpoint',
|
|
2534
|
+
'notifications'
|
|
2535
|
+
];
|
|
2536
|
+
const globalChannels = ['market-data'];
|
|
2537
|
+
if (address && address !== lastSubscribedAddress) {
|
|
2538
|
+
// Unsubscribe from previous address-specific channels if exists
|
|
2526
2539
|
if (lastSubscribedAddress) {
|
|
2527
2540
|
sendMessage(JSON.stringify({
|
|
2528
2541
|
action: 'unsubscribe',
|
|
2529
|
-
address: lastSubscribedAddress
|
|
2542
|
+
address: lastSubscribedAddress,
|
|
2543
|
+
channels: addressSpecificChannels
|
|
2530
2544
|
}));
|
|
2531
2545
|
}
|
|
2532
|
-
// Subscribe to
|
|
2546
|
+
// Subscribe to all channels (global + address-specific)
|
|
2533
2547
|
sendMessage(JSON.stringify({
|
|
2534
2548
|
action: 'subscribe',
|
|
2535
|
-
address: address
|
|
2549
|
+
address: address,
|
|
2550
|
+
channels: [...globalChannels, ...addressSpecificChannels]
|
|
2536
2551
|
}));
|
|
2537
2552
|
setLastSubscribedAddress(address);
|
|
2538
2553
|
setLastError(null);
|
|
2539
2554
|
}
|
|
2540
2555
|
else if (isConnected && !address && lastSubscribedAddress) {
|
|
2541
|
-
//
|
|
2556
|
+
// Unsubscribe from address-specific channels when address is removed
|
|
2542
2557
|
sendMessage(JSON.stringify({
|
|
2543
2558
|
action: 'unsubscribe',
|
|
2544
|
-
address: lastSubscribedAddress
|
|
2559
|
+
address: lastSubscribedAddress,
|
|
2560
|
+
channels: addressSpecificChannels
|
|
2545
2561
|
}));
|
|
2546
2562
|
setLastSubscribedAddress(null);
|
|
2547
2563
|
}
|
|
2564
|
+
else if (isConnected && !address && !lastSubscribedAddress) {
|
|
2565
|
+
// If no address but connected, subscribe to global channels only
|
|
2566
|
+
sendMessage(JSON.stringify({
|
|
2567
|
+
action: 'subscribe',
|
|
2568
|
+
channels: globalChannels
|
|
2569
|
+
}));
|
|
2570
|
+
}
|
|
2548
2571
|
}, [isConnected, address, lastSubscribedAddress, sendMessage]);
|
|
2549
|
-
// Clear data when address changes
|
|
2572
|
+
// Clear user data when address changes (but keep market data)
|
|
2550
2573
|
useEffect(() => {
|
|
2551
2574
|
if (address !== lastSubscribedAddress) {
|
|
2552
2575
|
clean();
|
|
2553
|
-
cleanMarketData();
|
|
2554
2576
|
setLastError(null);
|
|
2555
2577
|
}
|
|
2556
|
-
}, [address, lastSubscribedAddress]);
|
|
2578
|
+
}, [address, lastSubscribedAddress, clean]);
|
|
2557
2579
|
return {
|
|
2558
2580
|
connectionStatus: readyState,
|
|
2559
2581
|
isConnected,
|
|
@@ -8749,6 +8771,12 @@ const useHighlightedBaskets = () => {
|
|
|
8749
8771
|
const data = useMarketDataPayload();
|
|
8750
8772
|
return (_a = data === null || data === void 0 ? void 0 : data.highlighted) !== null && _a !== void 0 ? _a : [];
|
|
8751
8773
|
};
|
|
8774
|
+
// Watchlist baskets (from market-data payload when subscribed with address)
|
|
8775
|
+
const useWatchlistBaskets = () => {
|
|
8776
|
+
var _a;
|
|
8777
|
+
const data = useMarketDataPayload();
|
|
8778
|
+
return (_a = data === null || data === void 0 ? void 0 : data.watchlist) !== null && _a !== void 0 ? _a : [];
|
|
8779
|
+
};
|
|
8752
8780
|
// Find a basket by its exact asset composition (order-insensitive)
|
|
8753
8781
|
const useFindBasket = (longs, shorts) => {
|
|
8754
8782
|
const data = useMarketDataPayload();
|
|
@@ -8770,6 +8798,35 @@ const useFindBasket = (longs, shorts) => {
|
|
|
8770
8798
|
}, [data, longs, shorts]);
|
|
8771
8799
|
};
|
|
8772
8800
|
|
|
8801
|
+
async function toggleWatchlist(baseUrl, accessToken, longAssets, shortAssets) {
|
|
8802
|
+
const url = joinUrl(baseUrl, '/watchlist');
|
|
8803
|
+
try {
|
|
8804
|
+
const response = await axios$1.post(url, { longAssets, shortAssets }, { headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${accessToken}` } });
|
|
8805
|
+
return { data: response.data, status: response.status, headers: response.headers };
|
|
8806
|
+
}
|
|
8807
|
+
catch (error) {
|
|
8808
|
+
throw toApiError(error);
|
|
8809
|
+
}
|
|
8810
|
+
}
|
|
8811
|
+
|
|
8812
|
+
function useWatchlist() {
|
|
8813
|
+
const context = useContext(PearHyperliquidContext);
|
|
8814
|
+
if (!context)
|
|
8815
|
+
throw new Error('useWatchlist must be used within a PearHyperliquidProvider');
|
|
8816
|
+
const { apiBaseUrl, accessToken, isConnected } = context;
|
|
8817
|
+
const marketData = useMarketDataPayload();
|
|
8818
|
+
const isLoading = useMemo(() => !marketData && isConnected, [marketData, isConnected]);
|
|
8819
|
+
const toggle = async (longAssets, shortAssets) => {
|
|
8820
|
+
if (!accessToken)
|
|
8821
|
+
throw new Error('Not authenticated');
|
|
8822
|
+
const resp = await toggleWatchlist(apiBaseUrl, accessToken, longAssets, shortAssets);
|
|
8823
|
+
// Server will push updated market-data over WS; nothing to set here
|
|
8824
|
+
return resp;
|
|
8825
|
+
};
|
|
8826
|
+
const watchlists = marketData === null || marketData === void 0 ? void 0 : marketData.watchlist;
|
|
8827
|
+
return { watchlists: watchlists !== null && watchlists !== void 0 ? watchlists : null, isLoading, toggle };
|
|
8828
|
+
}
|
|
8829
|
+
|
|
8773
8830
|
const PearHyperliquidContext = createContext(undefined);
|
|
8774
8831
|
/**
|
|
8775
8832
|
* React Provider for PearHyperliquidClient
|
|
@@ -9068,4 +9125,4 @@ function mapCandleIntervalToTradingViewInterval(interval) {
|
|
|
9068
9125
|
}
|
|
9069
9126
|
}
|
|
9070
9127
|
|
|
9071
|
-
export { AccountSummaryCalculator, AuthStatus, ConflictDetector, PearHyperliquidProvider, TokenMetadataExtractor, adjustOrder, adjustPosition, calculateWeightedRatio, cancelOrder, cancelTwap, cancelTwapOrder, closeAllPositions, closePosition, computeBasketCandles, createCandleLookups, createPosition, getCompleteTimestamps, mapCandleIntervalToTradingViewInterval, mapTradingViewIntervalToCandleInterval, markNotificationReadById, markNotificationsRead, updateRiskParameters, useAccountSummary, useActiveBaskets, useAddress, useAgentWallet, useAuth, useAutoSyncFills, useBasketCandles, useFindBasket, useHighlightedBaskets, useHistoricalPriceData, useHistoricalPriceDataStore, useHyperliquidNativeWebSocket, useHyperliquidWebSocket, useMarketData, useMarketDataPayload, useNotifications, useOpenOrders, useOrders, usePearAgentWallet, usePearAuth, usePearHyperliquid, usePerformanceOverlays, usePosition, useTokenSelectionMetadata, useTopGainers, useTopLosers, useTradeHistories, useTwap, useUserSelection, useWebData };
|
|
9128
|
+
export { AccountSummaryCalculator, AuthStatus, ConflictDetector, PearHyperliquidProvider, TokenMetadataExtractor, adjustOrder, adjustPosition, calculateWeightedRatio, cancelOrder, cancelTwap, cancelTwapOrder, closeAllPositions, closePosition, computeBasketCandles, createCandleLookups, createPosition, getCompleteTimestamps, mapCandleIntervalToTradingViewInterval, mapTradingViewIntervalToCandleInterval, markNotificationReadById, markNotificationsRead, toggleWatchlist, updateRiskParameters, useAccountSummary, useActiveBaskets, useAddress, useAgentWallet, useAuth, useAutoSyncFills, useBasketCandles, useFindBasket, useHighlightedBaskets, useHistoricalPriceData, useHistoricalPriceDataStore, useHyperliquidNativeWebSocket, useHyperliquidWebSocket, useMarketData, useMarketDataPayload, useNotifications, useOpenOrders, useOrders, usePearAgentWallet, usePearAuth, usePearHyperliquid, usePerformanceOverlays, usePosition, useTokenSelectionMetadata, useTopGainers, useTopLosers, useTradeHistories, useTwap, useUserSelection, useWatchlist, useWatchlistBaskets, useWebData };
|
package/dist/types.d.ts
CHANGED
|
@@ -74,6 +74,18 @@ export interface WebSocketDataMessage<T = unknown> {
|
|
|
74
74
|
channel: WebSocketChannel;
|
|
75
75
|
data: T;
|
|
76
76
|
}
|
|
77
|
+
export interface WatchlistAssetDto {
|
|
78
|
+
asset: string;
|
|
79
|
+
weight: number;
|
|
80
|
+
}
|
|
81
|
+
export interface WatchlistItemDto {
|
|
82
|
+
id: string;
|
|
83
|
+
longAssets: WatchlistAssetDto[];
|
|
84
|
+
shortAssets: WatchlistAssetDto[];
|
|
85
|
+
}
|
|
86
|
+
export interface ToggleWatchlistResponseDto {
|
|
87
|
+
items: WatchlistItemDto[];
|
|
88
|
+
}
|
|
77
89
|
export type NotificationCategory = 'TRADE_OPENED_OUTSIDE_PEAR' | 'TRADE_CLOSED_OUTSIDE_PEAR' | 'POSITION_LIQUIDATED' | 'LIMIT_ORDER_FILLED' | 'LIMIT_ORDER_FAILED' | 'TP_ORDER_FILLED' | 'TP_ORDER_FAILED' | 'SL_ORDER_FILLED' | 'SL_ORDER_FAILED';
|
|
78
90
|
export interface NotificationDto {
|
|
79
91
|
id: string;
|
|
@@ -617,6 +629,7 @@ export interface ActiveAssetsResponse {
|
|
|
617
629
|
topGainers: ActiveAssetGroupItem[];
|
|
618
630
|
topLosers: ActiveAssetGroupItem[];
|
|
619
631
|
highlighted: ActiveAssetGroupItem[];
|
|
632
|
+
watchlist: ActiveAssetGroupItem[];
|
|
620
633
|
}
|
|
621
634
|
/**
|
|
622
635
|
* Candle interval options
|