@rabby-wallet/hyperliquid-sdk 1.0.7 → 1.0.8-beta3

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 CHANGED
@@ -1,140 +1,140 @@
1
- # Hyperliquid Perpetuals SDK
2
-
3
- 一个简化的 Hyperliquid 永续合约交易 SDK,专为前端应用设计。
4
-
5
- ## 特性
6
-
7
- - ✅ 仅核心API:最重要的交易与查询能力
8
- - ✅ 永续合约专用:不包含现货功能
9
- - ✅ TypeScript:完善的类型定义
10
- - ✅ WebSocket:实时数据订阅
11
- - ✅ 前端友好:基于 fetch API 的轻量实现
12
-
13
- ## 安装
14
-
15
- ```bash
16
- yarn add @debank/hyperliquid-perp-sdk
17
- # or
18
- npm i @debank/hyperliquid-perp-sdk
19
- ```
20
-
21
- ## 快速开始
22
-
23
- ### 仅查询(无需私钥)
24
- ```ts
25
- import { HyperliquidSDK } from '@debank/hyperliquid-perp-sdk';
26
-
27
- const sdk = new HyperliquidSDK({
28
- masterAddress: '0xYourEOA',
29
- isTestnet: true,
30
- });
31
-
32
- // 获取所有中间价
33
- const prices = await sdk.info.getAllMids();
34
-
35
- // 获取市场元数据与资产上下文
36
- const canUseCache = true; //默认使用缓存,多次请求并发去重 ,需要刷新传false
37
- const [meta, assetCtxs] = await sdk.info.metaAndAssetCtxs(canUseCache);
38
-
39
-
40
- // 获取账户综合状态
41
- const account = await sdk.info.getClearingHouseState();
42
- ```
43
-
44
- ### 交易(需要提供代理私钥、公钥、名称)
45
- ```ts
46
- const sdk = new HyperliquidSDK({
47
- masterAddress: '0xYourEOA',
48
- agentPrivateKey: '0xYourAgentPrivKey',
49
- agentPublicKey: '0xYourAgentPubKey',
50
- agentName: 'MyAgent',
51
- isTestnet: true,
52
- });
53
-
54
- // 限价下单
55
- await sdk.exchange!.placeOrder({
56
- coin: 'BTC',
57
- isBuy: true,
58
- sz: '0.1',
59
- limitPx: '45000',
60
- orderType: { limit: { tif: 'Gtc' } },
61
- });
62
-
63
- // 批量下单
64
- await sdk.exchange!.multiOrder({
65
- orders: [
66
- { coin: 'ETH', isBuy: true, sz: '1', limitPx: '3000', orderType: { limit: { tif: 'Ioc' } } },
67
- { coin: 'SOL', isBuy: false, sz: '10', limitPx: '150', orderType: { limit: { tif: 'Ioc' } } },
68
- ],
69
- });
70
-
71
- // 市价开仓(带可选的 TP/SL 触发单)
72
- await sdk.exchange!.marketOrderOpen({
73
- coin: 'BTC',
74
- isBuy: true,
75
- size: '0.05',
76
- midPx: '45200',
77
- tpTriggerPx: '47000',
78
- slTriggerPx: '44000',
79
- // slippage 默认 0.08
80
- });
81
-
82
- // 市价平仓
83
- await sdk.exchange!.marketOrderClose({
84
- coin: 'BTC',
85
- isBuy: false,
86
- size: '0.05',
87
- midPx: '45000',
88
- });
89
-
90
- // 绑定 TP/SL 到已有持仓(按位置绑定)
91
- await sdk.exchange!.bindTpslByOrderId({
92
- coin: 'BTC',
93
- isBuy: true, // 持仓方向
94
- tpTriggerPx: '47000',
95
- slTriggerPx: '44000',
96
- });
97
-
98
- // 更新杠杆
99
- await sdk.exchange!.updateLeverage({
100
- coin: 'BTC',
101
- leverage: 5,
102
- isCross: true,
103
- });
104
-
105
- // 撤单(可批量)
106
- await sdk.exchange!.cancelOrder([
107
- { coin: 'BTC', oid: 12345 },
108
- { coin: 'ETH', oid: 67890 },
109
- ]);
110
- ```
111
-
112
- ### 授权持久化代理(主钱包签名)
113
- ```ts
114
- // 准备主钱包签名的 EIP-712 数据(Approve Agent)
115
- const approve = sdk.exchange!.prepareApproveAgent();
116
- // 业务方使用主钱包签名(示例)
117
- const signature = await mainWallet.signTypedData(approve.domain, approve.types, approve.message);
118
- // 发送请求
119
- await sdk.exchange!.sendApproveAgent({ action: approve.message, nonce: approve.nonce, signature });
120
-
121
- // 准备并签名 Builder 费用
122
- const builderFee = sdk.exchange!.prepareApproveBuilderFee({ builder: '0xBuilder', maxFee: '0.1%' });
123
- const sig2 = await mainWallet.signTypedData(builderFee.domain, builderFee.types, builderFee.message);
124
- await sdk.exchange!.sendApproveBuilderFee({ action: builderFee.message, nonce: builderFee.nonce, signature: sig2 });
125
- ```
126
-
127
- ### WebSocket 实时数据
128
- ```ts
129
- await sdk.connectWebSocket();
130
-
131
- // 订阅价格
132
- sdk.ws.subscribeToAllMids((prices) => {
133
- console.log('价格更新:', prices);
134
- });
135
-
136
- // 订阅用户综合数据
137
- sdk.ws.subscribeToWebData2('0xYourEOA', (webData2) => {
138
- console.log('用户数据:', webData2);
139
- });
1
+ # Hyperliquid Perpetuals SDK
2
+
3
+ 一个简化的 Hyperliquid 永续合约交易 SDK,专为前端应用设计。
4
+
5
+ ## 特性
6
+
7
+ - ✅ 仅核心API:最重要的交易与查询能力
8
+ - ✅ 永续合约专用:不包含现货功能
9
+ - ✅ TypeScript:完善的类型定义
10
+ - ✅ WebSocket:实时数据订阅
11
+ - ✅ 前端友好:基于 fetch API 的轻量实现
12
+
13
+ ## 安装
14
+
15
+ ```bash
16
+ yarn add @debank/hyperliquid-perp-sdk
17
+ # or
18
+ npm i @debank/hyperliquid-perp-sdk
19
+ ```
20
+
21
+ ## 快速开始
22
+
23
+ ### 仅查询(无需私钥)
24
+ ```ts
25
+ import { HyperliquidSDK } from '@debank/hyperliquid-perp-sdk';
26
+
27
+ const sdk = new HyperliquidSDK({
28
+ masterAddress: '0xYourEOA',
29
+ isTestnet: true,
30
+ });
31
+
32
+ // 获取所有中间价
33
+ const prices = await sdk.info.getAllMids();
34
+
35
+ // 获取市场元数据与资产上下文
36
+ const canUseCache = true; //默认使用缓存,多次请求并发去重 ,需要刷新传false
37
+ const [meta, assetCtxs] = await sdk.info.metaAndAssetCtxs(canUseCache);
38
+
39
+
40
+ // 获取账户综合状态
41
+ const account = await sdk.info.getClearingHouseState();
42
+ ```
43
+
44
+ ### 交易(需要提供代理私钥、公钥、名称)
45
+ ```ts
46
+ const sdk = new HyperliquidSDK({
47
+ masterAddress: '0xYourEOA',
48
+ agentPrivateKey: '0xYourAgentPrivKey',
49
+ agentPublicKey: '0xYourAgentPubKey',
50
+ agentName: 'MyAgent',
51
+ isTestnet: true,
52
+ });
53
+
54
+ // 限价下单
55
+ await sdk.exchange!.placeOrder({
56
+ coin: 'BTC',
57
+ isBuy: true,
58
+ sz: '0.1',
59
+ limitPx: '45000',
60
+ orderType: { limit: { tif: 'Gtc' } },
61
+ });
62
+
63
+ // 批量下单
64
+ await sdk.exchange!.multiOrder({
65
+ orders: [
66
+ { coin: 'ETH', isBuy: true, sz: '1', limitPx: '3000', orderType: { limit: { tif: 'Ioc' } } },
67
+ { coin: 'SOL', isBuy: false, sz: '10', limitPx: '150', orderType: { limit: { tif: 'Ioc' } } },
68
+ ],
69
+ });
70
+
71
+ // 市价开仓(带可选的 TP/SL 触发单)
72
+ await sdk.exchange!.marketOrderOpen({
73
+ coin: 'BTC',
74
+ isBuy: true,
75
+ size: '0.05',
76
+ midPx: '45200',
77
+ tpTriggerPx: '47000',
78
+ slTriggerPx: '44000',
79
+ // slippage 默认 0.08
80
+ });
81
+
82
+ // 市价平仓
83
+ await sdk.exchange!.marketOrderClose({
84
+ coin: 'BTC',
85
+ isBuy: false,
86
+ size: '0.05',
87
+ midPx: '45000',
88
+ });
89
+
90
+ // 绑定 TP/SL 到已有持仓(按位置绑定)
91
+ await sdk.exchange!.bindTpslByOrderId({
92
+ coin: 'BTC',
93
+ isBuy: true, // 持仓方向
94
+ tpTriggerPx: '47000',
95
+ slTriggerPx: '44000',
96
+ });
97
+
98
+ // 更新杠杆
99
+ await sdk.exchange!.updateLeverage({
100
+ coin: 'BTC',
101
+ leverage: 5,
102
+ isCross: true,
103
+ });
104
+
105
+ // 撤单(可批量)
106
+ await sdk.exchange!.cancelOrder([
107
+ { coin: 'BTC', oid: 12345 },
108
+ { coin: 'ETH', oid: 67890 },
109
+ ]);
110
+ ```
111
+
112
+ ### 授权持久化代理(主钱包签名)
113
+ ```ts
114
+ // 准备主钱包签名的 EIP-712 数据(Approve Agent)
115
+ const approve = sdk.exchange!.prepareApproveAgent();
116
+ // 业务方使用主钱包签名(示例)
117
+ const signature = await mainWallet.signTypedData(approve.domain, approve.types, approve.message);
118
+ // 发送请求
119
+ await sdk.exchange!.sendApproveAgent({ action: approve.message, nonce: approve.nonce, signature });
120
+
121
+ // 准备并签名 Builder 费用
122
+ const builderFee = sdk.exchange!.prepareApproveBuilderFee({ builder: '0xBuilder', maxFee: '0.1%' });
123
+ const sig2 = await mainWallet.signTypedData(builderFee.domain, builderFee.types, builderFee.message);
124
+ await sdk.exchange!.sendApproveBuilderFee({ action: builderFee.message, nonce: builderFee.nonce, signature: sig2 });
125
+ ```
126
+
127
+ ### WebSocket 实时数据
128
+ ```ts
129
+ await sdk.connectWebSocket();
130
+
131
+ // 订阅价格
132
+ sdk.ws.subscribeToAllMids((prices) => {
133
+ console.log('价格更新:', prices);
134
+ });
135
+
136
+ // 订阅用户综合数据
137
+ sdk.ws.subscribeToWebData2('0xYourEOA', (webData2) => {
138
+ console.log('用户数据:', webData2);
139
+ });
140
140
  ```
@@ -20,13 +20,34 @@ export declare class ExchangeClient {
20
20
  get address(): string;
21
21
  updateExchangeAgent(agentPrivateKey: string, agentPublicKey: string, agentName?: string): void;
22
22
  private getAgentPrivateKey;
23
+ /**
24
+ * @deprecated This method is deprecated. Use the new builder configuration in constructor instead.
25
+ */
23
26
  updateBuilder(address: string, fee: number): Promise<any>;
24
27
  updateLeverage(params: UpdateLeverageParams): Promise<any>;
25
28
  /**
26
29
  * Place a single order
27
30
  */
28
31
  placeOrder(params: PlaceOrderParams): Promise<OrderResponse>;
32
+ /**
33
+ * Calculate slippage price for market orders following Hyperliquid price rules
34
+ * Based on official Python SDK logic
35
+ *
36
+ * Rules:
37
+ * - Round to 5 significant figures
38
+ * - Round to (6 - szDecimals) decimal places for perps
39
+ *
40
+ * @param midPx - Middle price as string
41
+ * @param slippage - Slippage rate (e.g., 0.08 for 8%)
42
+ * @param isBuy - True for buy orders, false for sell orders
43
+ * @param szDecimals - Size decimals from meta endpoint (default 0)
44
+ * @param isSpot - Whether this is a spot asset (default false for perps)
45
+ */
29
46
  private getSlippagePx;
47
+ /**
48
+ * Round a number to specified decimal places
49
+ */
50
+ private roundToDecimals;
30
51
  /**
31
52
  * Place a market order
32
53
  * default slippage is 0.08
@@ -103,7 +103,9 @@ class ExchangeClient {
103
103
  }
104
104
  return this.agentPrivateKey;
105
105
  }
106
- // 50 = '0.05%'
106
+ /**
107
+ * @deprecated This method is deprecated. Use the new builder configuration in constructor instead.
108
+ */
107
109
  updateBuilder(address, fee) {
108
110
  return __awaiter(this, void 0, void 0, function* () {
109
111
  if (fee < 0 || fee > 100) {
@@ -151,10 +153,10 @@ class ExchangeClient {
151
153
  orders: [orderWire],
152
154
  grouping: 'na',
153
155
  };
154
- if (this.builder) {
156
+ if (params.builder) {
155
157
  action.builder = {
156
- b: this.builder.address,
157
- f: this.builder.fee,
158
+ b: params.builder.address,
159
+ f: params.builder.fee,
158
160
  };
159
161
  }
160
162
  const signature = (0, signer_1.signL1AgentAction)(this.getAgentPrivateKey(), action, this.isTestnet, nonce);
@@ -165,12 +167,40 @@ class ExchangeClient {
165
167
  });
166
168
  });
167
169
  }
168
- getSlippagePx(midPx, slippage, isBuy) {
169
- var _a;
170
- const decimals = ((_a = midPx.toString().split('.')[1]) === null || _a === void 0 ? void 0 : _a.length) || 0;
171
- const prepDecimals = Math.max(0, decimals - 1);
172
- const px = isBuy ? (Number(midPx) * (1 + slippage)).toFixed(prepDecimals) : (Number(midPx) * (1 - slippage)).toFixed(prepDecimals);
173
- return (0, number_1.removeTrailingZeros)(px);
170
+ /**
171
+ * Calculate slippage price for market orders following Hyperliquid price rules
172
+ * Based on official Python SDK logic
173
+ *
174
+ * Rules:
175
+ * - Round to 5 significant figures
176
+ * - Round to (6 - szDecimals) decimal places for perps
177
+ *
178
+ * @param midPx - Middle price as string
179
+ * @param slippage - Slippage rate (e.g., 0.08 for 8%)
180
+ * @param isBuy - True for buy orders, false for sell orders
181
+ * @param szDecimals - Size decimals from meta endpoint (default 0)
182
+ * @param isSpot - Whether this is a spot asset (default false for perps)
183
+ */
184
+ getSlippagePx(midPx, slippage, isBuy, szDecimals = 0) {
185
+ let px = parseFloat(midPx);
186
+ if (isNaN(px) || px <= 0) {
187
+ throw new Error('Invalid midPx: must be a positive number');
188
+ }
189
+ // Calculate slippage price
190
+ px *= isBuy ? (1 + slippage) : (1 - slippage);
191
+ // Round to 5 significant figures
192
+ const sigFigRounded = parseFloat(px.toPrecision(5));
193
+ // Round to (6 - szDecimals) decimals for perps
194
+ const maxDecimals = 6 - szDecimals;
195
+ const decimalRounded = this.roundToDecimals(sigFigRounded, maxDecimals);
196
+ return (0, number_1.removeTrailingZeros)(decimalRounded.toFixed(maxDecimals));
197
+ }
198
+ /**
199
+ * Round a number to specified decimal places
200
+ */
201
+ roundToDecimals(value, decimals) {
202
+ const multiplier = Math.pow(10, decimals);
203
+ return Math.round(value * multiplier) / multiplier;
174
204
  }
175
205
  /**
176
206
  * Place a market order
@@ -226,6 +256,7 @@ class ExchangeClient {
226
256
  }
227
257
  const res = yield this.multiOrder({
228
258
  orders,
259
+ builder: params.builder,
229
260
  });
230
261
  return res;
231
262
  }
@@ -249,6 +280,7 @@ class ExchangeClient {
249
280
  }];
250
281
  const res = yield this.multiOrder({
251
282
  orders,
283
+ builder: params.builder,
252
284
  });
253
285
  return res;
254
286
  }
@@ -284,10 +316,10 @@ class ExchangeClient {
284
316
  orders: orderWires,
285
317
  grouping: params.grouping || 'na',
286
318
  };
287
- if (this.builder) {
319
+ if (params.builder) {
288
320
  action.builder = {
289
- b: this.builder.address,
290
- f: this.builder.fee,
321
+ b: params.builder.address,
322
+ f: params.builder.fee,
291
323
  };
292
324
  }
293
325
  const signature = (0, signer_1.signL1AgentAction)(this.getAgentPrivateKey(), action, this.isTestnet, nonce);
@@ -338,7 +370,8 @@ class ExchangeClient {
338
370
  }
339
371
  return this.multiOrder({
340
372
  orders,
341
- grouping: 'positionTpsl'
373
+ grouping: 'positionTpsl',
374
+ builder: params.builder,
342
375
  });
343
376
  });
344
377
  }
@@ -2,6 +2,7 @@ import { HttpClientConfig } from "./http-client";
2
2
  import { InfoClient } from "./info-client";
3
3
  export declare class SymbolConversion {
4
4
  private assetToIndexMap;
5
+ private assetSzDecimalsMap;
5
6
  private httpClient;
6
7
  private initialized;
7
8
  private infoClient?;
@@ -10,6 +11,7 @@ export declare class SymbolConversion {
10
11
  private ensureInitialized;
11
12
  private refreshAssetMaps;
12
13
  getAssetIndex(assetSymbol: string): Promise<number>;
14
+ getAssetSzDecimals(assetSymbol: string): Promise<number>;
13
15
  getAllAssets(): Promise<{
14
16
  perp: string[];
15
17
  }>;
@@ -15,6 +15,7 @@ const http_client_1 = require("./http-client");
15
15
  class SymbolConversion {
16
16
  constructor(config, infoClient) {
17
17
  this.assetToIndexMap = new Map();
18
+ this.assetSzDecimalsMap = new Map();
18
19
  this.initialized = false;
19
20
  this.infoClient = infoClient;
20
21
  this.httpClient = new http_client_1.HttpClient({
@@ -64,9 +65,11 @@ class SymbolConversion {
64
65
  throw new Error('Invalid perpetual metadata response');
65
66
  }
66
67
  this.assetToIndexMap.clear();
68
+ this.assetSzDecimalsMap.clear();
67
69
  // Handle perpetual assets
68
70
  perpMeta[0].universe.forEach((asset, index) => {
69
71
  this.assetToIndexMap.set(asset.name, index);
72
+ this.assetSzDecimalsMap.set(asset.name, asset.szDecimals);
70
73
  });
71
74
  }
72
75
  catch (error) {
@@ -84,6 +87,16 @@ class SymbolConversion {
84
87
  return index;
85
88
  });
86
89
  }
90
+ getAssetSzDecimals(assetSymbol) {
91
+ return __awaiter(this, void 0, void 0, function* () {
92
+ yield this.ensureInitialized();
93
+ const szDecimals = this.assetSzDecimalsMap.get(assetSymbol);
94
+ if (szDecimals === undefined) {
95
+ throw new Error(`Unknown asset index: ${assetSymbol}`);
96
+ }
97
+ return szDecimals;
98
+ });
99
+ }
87
100
  getAllAssets() {
88
101
  return __awaiter(this, void 0, void 0, function* () {
89
102
  yield this.ensureInitialized();
@@ -194,6 +194,10 @@ export interface MarketOrderParams {
194
194
  tpTriggerPx?: string;
195
195
  slTriggerPx?: string;
196
196
  slippage?: number;
197
+ builder?: {
198
+ address: string;
199
+ fee: number;
200
+ };
197
201
  }
198
202
  export interface CancelResponse {
199
203
  status: 'ok';
@@ -357,6 +361,10 @@ export interface PlaceOrderParams {
357
361
  limitPx: string;
358
362
  reduceOnly?: boolean;
359
363
  orderType?: any;
364
+ builder?: {
365
+ address: string;
366
+ fee: number;
367
+ };
360
368
  }
361
369
  export interface UpdateLeverageParams {
362
370
  coin: string;
@@ -368,10 +376,18 @@ export interface BindTpslByOrderIdParams {
368
376
  slTriggerPx?: string;
369
377
  coin: string;
370
378
  isBuy: boolean;
379
+ builder?: {
380
+ address: string;
381
+ fee: number;
382
+ };
371
383
  }
372
384
  export interface MultiOrderParams {
373
385
  orders: PlaceOrderParams[];
374
386
  grouping?: string;
387
+ builder?: {
388
+ address: string;
389
+ fee: number;
390
+ };
375
391
  }
376
392
  export interface CancelOrderParams {
377
393
  coin: string;
package/package.json CHANGED
@@ -1,37 +1,37 @@
1
- {
2
- "name": "@rabby-wallet/hyperliquid-sdk",
3
- "version": "1.0.7",
4
- "description": "Simplified Hyperliquid Perpetuals Trading SDK for Frontend Applications",
5
- "main": "dist/index.js",
6
- "types": "dist/index.d.ts",
7
- "files": [
8
- "dist"
9
- ],
10
- "publishConfig": {
11
- "access": "public"
12
- },
13
- "scripts": {
14
- "build": "rimraf dist && tsc",
15
- "preversion": "npm run build",
16
- "prepublishOnly": "npm run build"
17
- },
18
- "author": "",
19
- "license": "UNLICENSED",
20
- "dependencies": {
21
- "@ethereumjs/util": "9.0.0",
22
- "@metamask/eth-sig-util": "5.1.0",
23
- "@msgpack/msgpack": "3.1.2",
24
- "@noble/hashes": "1.8.0",
25
- "ethereum-cryptography": "2.2.1"
26
- },
27
- "devDependencies": {
28
- "@types/node": "24.3.1",
29
- "prettier": "2.7.1",
30
- "rimraf": "6.0.0",
31
- "typescript": "5.9.2"
32
- },
33
- "engines": {
34
- "node": ">=16.0.0"
35
- },
36
- "packageManager": "yarn@1.22.22"
37
- }
1
+ {
2
+ "name": "@rabby-wallet/hyperliquid-sdk",
3
+ "version": "1.0.8-beta3",
4
+ "description": "Simplified Hyperliquid Perpetuals Trading SDK for Frontend Applications",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "files": [
8
+ "dist"
9
+ ],
10
+ "publishConfig": {
11
+ "access": "public"
12
+ },
13
+ "scripts": {
14
+ "build": "rimraf dist && tsc",
15
+ "preversion": "npm run build",
16
+ "prepublishOnly": "npm run build"
17
+ },
18
+ "author": "",
19
+ "license": "UNLICENSED",
20
+ "dependencies": {
21
+ "@ethereumjs/util": "9.0.0",
22
+ "@metamask/eth-sig-util": "5.1.0",
23
+ "@msgpack/msgpack": "3.1.2",
24
+ "@noble/hashes": "1.8.0",
25
+ "ethereum-cryptography": "2.2.1"
26
+ },
27
+ "devDependencies": {
28
+ "@types/node": "24.3.1",
29
+ "prettier": "2.7.1",
30
+ "rimraf": "6.0.0",
31
+ "typescript": "5.9.2"
32
+ },
33
+ "engines": {
34
+ "node": ">=16.0.0"
35
+ },
36
+ "packageManager": "yarn@1.22.22"
37
+ }