1
1
# Hyperliquid API TypeScript SDK
2
2
3
- [ ![ NPM ] ( https://img.shields.io/npm/v/@nktkas/hyperliquid?style=flat-square&color=blue )] ( https://www.npmjs.com/package/@nktkas/hyperliquid )
4
- [ ![ JSR ] ( https://img.shields.io/jsr/v/@nktkas/hyperliquid?style=flat-square&color=blue )] ( https://jsr.io/@nktkas/hyperliquid )
5
- [ ![ Coveralls ] ( https://img.shields.io/coverallsCoverage/github/nktkas/hyperliquid?style=flat-square )] ( https://coveralls.io/github/nktkas/hyperliquid )
6
- [ ![ bundlejs ] ( https://img.shields.io/bundlejs/size /@nktkas/hyperliquid?style=flat-square )] ( https://bundlejs .com/?q= @nktkas/hyperliquid )
3
+ [ ![ npm ] ( https://img.shields.io/npm/v/@nktkas/hyperliquid?style=flat-square&color=blue )] ( https://www.npmjs.com/package/@nktkas/hyperliquid )
4
+ [ ![ jsr ] ( https://img.shields.io/jsr/v/@nktkas/hyperliquid?style=flat-square&color=blue )] ( https://jsr.io/@nktkas/hyperliquid )
5
+ [ ![ coveralls ] ( https://img.shields.io/coverallsCoverage/github/nktkas/hyperliquid?style=flat-square )] ( https://coveralls.io/github/nktkas/hyperliquid )
6
+ [ ![ bundlephobia ] ( https://img.shields.io/bundlephobia/minzip /@nktkas/hyperliquid?style=flat-square )] ( https://bundlephobia .com/package/ @nktkas/hyperliquid )
7
7
8
8
Unofficial [ Hyperliquid API] ( https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api ) SDK for all major JS
9
9
runtimes, written in TypeScript and provided with tests.
@@ -44,19 +44,18 @@ deno add jsr:@nktkas/hyperliquid
44
44
``` html
45
45
<script type =" module" >
46
46
import * as hl from " https://esm.sh/jsr/@nktkas/hyperliquid" ;
47
- // Use hl.InfoClient, hl.ExchangeClient, etc.
48
47
</script >
49
48
```
50
49
51
50
### React Native
52
51
53
52
<details >
54
- <summary >For React Native, you need to import several polyfills before importing the SDK:</summary >
53
+ <summary >For React Native, you need to import polyfills before importing the SDK:</summary >
55
54
56
55
``` js
57
- // React Native 0 .76.3
56
+ // React Native v0 .76.3 / Expo v52
58
57
// Issues:
59
- // - signing: does not support private keys directly as an abstract wallet
58
+ // - signing: does not support private keys directly, use viem or ethers
60
59
import { Event , EventTarget } from " event-target-shim" ;
61
60
62
61
if (! globalThis .EventTarget || ! globalThis .Event ) {
@@ -176,16 +175,15 @@ const signers = [
176
175
] as const ;
177
176
178
177
const transport = new hl.HttpTransport ();
179
- const multiSignClient = new hl.MultiSignClient ({ transport, multiSignAddress, signers }); // extends ExchangeClient
178
+ const multiSignClient = new hl.MultiSignClient ({ transport, multiSignAddress, signers }); // extends ` ExchangeClient`
180
179
181
- const data = await multiSignClient .approveAgent ({ // same API as ExchangeClient
180
+ const data = await multiSignClient .approveAgent ({ // same API as ` ExchangeClient`
182
181
agentAddress: " 0x..." ,
183
182
agentName: " agentName" ,
184
183
});
185
184
` ` `
186
185
187
- <details>
188
- <summary><h2>Usage</h2></summary>
186
+ ## Usage
189
187
190
188
### 1) Initialize Transport
191
189
@@ -194,11 +192,11 @@ First, choose and configure your transport layer (more details in the [API Refer
194
192
` ` ` ts
195
193
import * as hl from " @nktkas/hyperliquid" ;
196
194
197
- // HTTP Transport
198
- const httpTransport = new hl.HttpTransport (); // Accepts optional parameters
195
+ // 1. HTTP Transport: suitable for one-time requests or serverless environments
196
+ const httpTransport = new hl.HttpTransport (); // Accepts optional parameters (e.g. isTestnet, timeout, etc.)
199
197
200
- // WebSocket Transport
201
- const wsTransport = new hl.WebSocketTransport (); // Accepts optional parameters
198
+ // 2. WebSocket Transport: has better network latency than HTTP transport
199
+ const wsTransport = new hl.WebSocketTransport (); // Accepts optional parameters (e.g. url, timeout, reconnect, etc.)
202
200
` ` `
203
201
204
202
### 2) Initialize Client
@@ -210,7 +208,7 @@ Next, initialize a client with the transport layer (more details in the [API Ref
210
208
` ` ` ts
211
209
import * as hl from " @nktkas/hyperliquid" ;
212
210
213
- const transport = new hl.HttpTransport (); // or WebSocketTransport
211
+ const transport = new hl.HttpTransport (); // or ` WebSocketTransport`
214
212
const infoClient = new hl.InfoClient ({ transport });
215
213
` ` `
216
214
@@ -222,17 +220,17 @@ import { createWalletClient, custom } from "viem";
222
220
import { privateKeyToAccount } from " viem/accounts" ;
223
221
import { ethers } from " ethers" ;
224
222
225
- const transport = new hl.HttpTransport (); // or WebSocketTransport
223
+ const transport = new hl.HttpTransport (); // or ` WebSocketTransport`
226
224
227
- // 1. Using private key
225
+ // 1. Using private key directly
228
226
const privateKey = " 0x..." ;
229
227
const exchClient_privateKey = new hl.ExchangeClient ({ wallet: privateKey, transport });
230
228
231
- // 2. Using Viem with private key
229
+ // 2. Using Viem
232
230
const viemAccount = privateKeyToAccount (" 0x..." );
233
231
const exchClient_viem = new hl.ExchangeClient ({ wallet: viemAccount, transport });
234
232
235
- // 3. Using Ethers (or Ethers V5) with private key
233
+ // 3. Using Ethers (or Ethers V5)
236
234
const ethersWallet = new ethers.Wallet (" 0x..." );
237
235
const exchClient_ethers = new hl.ExchangeClient ({ wallet: ethersWallet, transport });
238
236
@@ -241,7 +239,7 @@ const [account] = await window.ethereum.request({ method: "eth_requestAccounts"
241
239
const externalWallet = createWalletClient ({ account, transport: custom (window .ethereum ) });
242
240
const exchClient_viemMetamask = new hl.ExchangeClient ({ wallet: externalWallet, transport });
243
241
244
- // 5. Using external wallet (e.g. MetaMask) via `window.ethereum` (EIP-1193)
242
+ // 5. Using external wallet (e.g. MetaMask) via `window.ethereum`
245
243
const exchClient_windowMetamask = new hl.ExchangeClient ({ wallet: window .ethereum , transport });
246
244
` ` `
247
245
@@ -250,7 +248,7 @@ const exchClient_windowMetamask = new hl.ExchangeClient({ wallet: window.ethereu
250
248
` ` ` ts
251
249
import * as hl from " @nktkas/hyperliquid" ;
252
250
253
- const transport = new hl.WebSocketTransport (); // only WebSocketTransport
251
+ const transport = new hl.WebSocketTransport (); // only ` WebSocketTransport`
254
252
const subsClient = new hl.SubscriptionClient ({ transport });
255
253
` ` `
256
254
@@ -266,7 +264,7 @@ const signers = [
266
264
privateKeyToAccount (" 0x..." ), // first is leader for multi-sign transaction, must contain own address
267
265
new ethers.Wallet (" 0x..." ),
268
266
{ // can be a custom async wallet
269
- signTypedData (params: {
267
+ async signTypedData (params: {
270
268
domain: {
271
269
name: string;
272
270
version: string;
@@ -283,14 +281,14 @@ const signers = [
283
281
message: Record< string, unknown> ;
284
282
}): Promise < Hex> {
285
283
// Custom signer logic
286
- return " 0x..." ; // return signature
284
+ return " 0x..." ; // return hex signature
287
285
},
288
286
},
289
287
" 0x..." , // private key directly
290
288
];
291
289
292
290
const transport = new hl.HttpTransport ();
293
- const multiSignClient = new hl.MultiSignClient ({ transport, multiSignAddress, signers }); // extends ExchangeClient
291
+ const multiSignClient = new hl.MultiSignClient ({ transport, multiSignAddress, signers }); // extends ` ExchangeClient`
294
292
` ` `
295
293
296
294
### 3) Use Client
@@ -392,7 +390,7 @@ const signers = [
392
390
const transport = new hl.HttpTransport ();
393
391
const multiSignClient = new hl.MultiSignClient ({ transport, multiSignAddress, signers });
394
392
395
- // Interaction is the same as with ExchangeClient
393
+ // Interaction is the same as with ` ExchangeClient`
396
394
397
395
// Place an orders
398
396
const result = await multiSignClient .order ({
@@ -424,10 +422,7 @@ const result = await multiSignClient.withdraw3({
424
422
});
425
423
` ` `
426
424
427
- </details>
428
-
429
- <details>
430
- <summary><h2>API Reference</h2></summary>
425
+ ## API Reference
431
426
432
427
### Clients
433
428
@@ -515,6 +510,7 @@ class ExchangeClient {
515
510
constructor (args : {
516
511
transport: HttpTransport | WebSocketTransport;
517
512
wallet:
513
+ | Hex // Private key directly
518
514
| AbstractViemWalletClient // viem
519
515
| AbstractEthersSigner // ethers
520
516
| AbstractEthersV5Signer // ethers v5
@@ -552,6 +548,7 @@ class ExchangeClient {
552
548
553
549
// Transfer
554
550
perpDexClassTransfer(args: PerpDexClassTransferParameters): Promise<SuccessResponse>;
551
+ perpDexTransfer(args: PerpDexTransferParameters): Promise<SuccessResponse>;
555
552
spotSend(args: SpotSendParameters): Promise<SuccessResponse>;
556
553
subAccountSpotTransfer(args: SubAccountSpotTransferParameters): Promise<SuccessResponse>;
557
554
subAccountTransfer(args: SubAccountTransferParameters): Promise<SuccessResponse>;
@@ -637,16 +634,18 @@ class MultiSignClient extends ExchangeClient {
637
634
},
638
635
);
639
636
640
- // Same methods as ExchangeClient
637
+ // Same methods as ` ExchangeClient`
641
638
}
642
639
` ` `
643
640
644
641
### Transports
645
642
646
- Transport acts as a layer between the class and Hyperliquid servers.
643
+ Transport acts as a layer between class requests and Hyperliquid servers.
647
644
648
645
#### HTTP Transport
649
646
647
+ HTTP transport is suitable for one-off requests or serverless environments.
648
+
650
649
` ` ` ts
651
650
class HttpTransport {
652
651
constructor (options ?: {
@@ -665,6 +664,8 @@ class HttpTransport {
665
664
666
665
#### WebSocket Transport
667
666
667
+ WebSocket transport has better network latency than HTTP transport.
668
+
668
669
` ` ` ts
669
670
class WebSocketTransport {
670
671
constructor (options ?: {
@@ -688,10 +689,7 @@ class WebSocketTransport {
688
689
}
689
690
` ` `
690
691
691
- </details>
692
-
693
- <details>
694
- <summary><h2>Additional Import Points</h2></summary>
692
+ ## Additional Import Points
695
693
696
694
### ` / types`
697
695
@@ -711,22 +709,22 @@ import { actionSorter, signL1Action } from "@nktkas/hyperliquid/signing";
711
709
712
710
const privateKey = " 0x..." ; // or `viem`, `ethers`
713
711
712
+ const nonce = Date .now ();
714
713
const action = {
715
714
type: " cancel" ,
716
715
cancels: [
717
716
{ a: 0 , o: 12345 },
718
717
],
719
- };
720
- const nonce = Date .now ();
718
+ } as const ;
721
719
722
720
const signature = await signL1Action ({
723
721
wallet: privateKey,
724
- action: actionSorter[action .type ](action), // key order affects signature
722
+ action: actionSorter[action .type ](action),
725
723
nonce,
726
- isTestnet: true , // change to `false` for mainnet
727
724
});
728
725
729
- const response = await fetch (" https://api.hyperliquid-testnet.xyz/exchange" , {
726
+ // Send the signed action to the Hyperliquid API
727
+ const response = await fetch (" https://api.hyperliquid.xyz/exchange" , {
730
728
method: " POST" ,
731
729
headers: { " Content-Type" : " application/json" },
732
730
body: JSON .stringify ({ action, signature, nonce }),
@@ -743,30 +741,28 @@ const privateKey = "0x..."; // or `viem`, `ethers`
743
741
744
742
const action = {
745
743
type: " approveAgent" ,
746
- signatureChainId: " 0x66eee" , // must match the current wallet network
747
- hyperliquidChain: " Testnet " , // Mainnet | Testnet
744
+ signatureChainId: " 0x66eee" ,
745
+ hyperliquidChain: " Mainnet " ,
748
746
agentAddress: " 0x..." ,
749
747
agentName: " Agent" ,
750
748
nonce: Date .now (),
751
- };
749
+ } as const ;
752
750
753
751
const signature = await signUserSignedAction ({
754
752
wallet: privateKey,
755
753
action,
756
- types: userSignedActionEip712Types[action .type ], // key order affects signature
757
- chainId: parseInt (action .signatureChainId , 16 ),
754
+ types: userSignedActionEip712Types[action .type ],
758
755
});
759
756
760
- const response = await fetch (" https://api.hyperliquid-testnet.xyz/exchange" , {
757
+ // Send the signed action to the Hyperliquid API
758
+ const response = await fetch (" https://api.hyperliquid.xyz/exchange" , {
761
759
method: " POST" ,
762
760
headers: { " Content-Type" : " application/json" },
763
761
body: JSON .stringify ({ action, signature, nonce: action .nonce }),
764
762
});
765
763
const body = await response .json ();
766
764
` ` `
767
765
768
- </details>
769
-
770
766
## Contributing
771
767
772
768
We appreciate your help! To contribute, please read the [contributing instructions](CONTRIBUTING.md).
0 commit comments