@rabby-wallet/hyperliquid-sdk 1.1.2-beta.9 → 1.1.3

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
  ```
@@ -1,5 +1,5 @@
1
1
  import { ExchangeType } from '../types/constants';
2
- import type { OrderResponse, CancelResponse, ExchangeClientConfig, PlaceOrderParams, MultiOrderParams, CancelOrderParams, ModifyOrderParams, WithdrawParams, ApproveBuilderFeeParams, PrepareApproveBuilderFeeResult, SendApproveParams, MarketOrderParams, UpdateLeverageParams, BindTpslByOrderIdParams, UpdateIsolatedMarginParams, TwapOrderParams, TwapCancelParams, TwapOrderResponse, PlaceTPSlMarketOrderParams, PlaceTPSlLimitOrderParams } from '../types';
2
+ import type { OrderResponse, CancelResponse, ExchangeClientConfig, PlaceOrderParams, MultiOrderParams, CancelOrderParams, ModifyOrderParams, WithdrawParams, ApproveBuilderFeeParams, PrepareApproveBuilderFeeResult, SendApproveParams, MarketOrderParams, UpdateLeverageParams, BindTpslByOrderIdParams, UpdateIsolatedMarginParams, TwapOrderParams, TwapCancelParams, TwapOrderResponse, PlaceTPSlMarketOrderParams, PlaceTPSlLimitOrderParams, ClearinghouseState, UpdateTpslByOrderIdParams, LimitOrderParams } from '../types';
3
3
  /**
4
4
  * Client for executing trades on Hyperliquid (perpetuals only)
5
5
  * Only includes essential trading APIs as specified
@@ -10,11 +10,19 @@ export declare class ExchangeClient {
10
10
  private agentPublicKey?;
11
11
  private agentName?;
12
12
  private readonly isTestnet;
13
+ slippage: number;
13
14
  private masterAddress;
14
15
  private builder?;
15
16
  private readonly symbolConversion;
16
17
  constructor(config: ExchangeClientConfig);
17
18
  initAccount(masterAddress: string, agentPrivateKey?: string, agentPublicKey?: string, agentName?: string): void;
19
+ /**
20
+ * Set the slippage for the exchange client
21
+ * default is 0.08
22
+ * 0 - 0.1
23
+ * @param slippage - The slippage to set
24
+ */
25
+ setSlippage(slippage?: number): void;
18
26
  initOrUpdateAgent(agentPrivateKey: string, agentPublicKey: string, agentName?: string): void;
19
27
  /**
20
28
  * Check if agent is set
@@ -47,7 +55,7 @@ export declare class ExchangeClient {
47
55
  * @param isBuy - True for buy orders, false for sell orders
48
56
  * @param szDecimals - Size decimals from meta endpoint (default 0)
49
57
  */
50
- private getSlippagePx;
58
+ getSlippagePx(midPx: string, slippage: number, isBuy: boolean, szDecimals?: number): string;
51
59
  /**
52
60
  * Round a number to specified decimal places
53
61
  */
@@ -59,6 +67,16 @@ export declare class ExchangeClient {
59
67
  */
60
68
  marketOrderOpen(params: MarketOrderParams): Promise<OrderResponse>;
61
69
  marketOrderClose(params: Omit<MarketOrderParams, 'tpTriggerPx' | 'slTriggerPx'>): Promise<OrderResponse>;
70
+ /**
71
+ * Place a market order
72
+ * default slippage is 0.08
73
+ * need to update leverage before place order
74
+ */
75
+ limitOrderOpen(params: LimitOrderParams): Promise<OrderResponse>;
76
+ closeAllPositions(clearinghouseState: ClearinghouseState, slippage?: number, builder?: {
77
+ address: string;
78
+ fee: number;
79
+ }): Promise<OrderResponse>;
62
80
  /**
63
81
  * Place a take profit or stop loss market order
64
82
  * default slippage is 0.08
@@ -66,7 +84,6 @@ export declare class ExchangeClient {
66
84
  placeTPSlMarketOrder(params: PlaceTPSlMarketOrderParams): Promise<OrderResponse>;
67
85
  /**
68
86
  * Place a take profit or stop loss limit order
69
- * default slippage is 0.08
70
87
  */
71
88
  placeTPSlLimitOrder(params: PlaceTPSlLimitOrderParams): Promise<OrderResponse>;
72
89
  /**
@@ -74,6 +91,7 @@ export declare class ExchangeClient {
74
91
  */
75
92
  multiOrder(params: MultiOrderParams): Promise<OrderResponse>;
76
93
  bindTpslByOrderId(params: BindTpslByOrderIdParams): Promise<OrderResponse>;
94
+ updateTpslByOrderId(params: UpdateTpslByOrderIdParams): Promise<OrderResponse>;
77
95
  /**
78
96
  * Cancel order(s)
79
97
  */
@@ -81,7 +99,8 @@ export declare class ExchangeClient {
81
99
  /**
82
100
  * Modify an existing order
83
101
  */
84
- modifyOrder(params: ModifyOrderParams): Promise<any>;
102
+ modifyOrder(params: ModifyOrderParams): Promise<OrderResponse>;
103
+ batchModifyOrder(params: ModifyOrderParams[]): Promise<OrderResponse>;
85
104
  updateIsolatedMargin(params: UpdateIsolatedMarginParams): Promise<any>;
86
105
  prepareSetReferrer(code: string): {
87
106
  typedData: import("@metamask/eth-sig-util").TypedMessage<import("@metamask/eth-sig-util").MessageTypes>;
@@ -55,6 +55,7 @@ const number_1 = require("../utils/number");
55
55
  */
56
56
  class ExchangeClient {
57
57
  constructor(config) {
58
+ this.slippage = constants_1.SLIPPAGE;
58
59
  this.masterAddress = config.masterAddress;
59
60
  this.httpClient = new http_client_1.HttpClient({
60
61
  isTestnet: config.isTestnet,
@@ -93,6 +94,21 @@ class ExchangeClient {
93
94
  this.agentName = undefined;
94
95
  }
95
96
  }
97
+ /**
98
+ * Set the slippage for the exchange client
99
+ * default is 0.08
100
+ * 0 - 0.1
101
+ * @param slippage - The slippage to set
102
+ */
103
+ setSlippage(slippage = constants_1.SLIPPAGE) {
104
+ if (Number.isNaN(slippage)) {
105
+ throw new Error('Slippage must be a number');
106
+ }
107
+ if (slippage < 0 || slippage > 0.1) {
108
+ throw new Error('Slippage must be between 0 and 0.1');
109
+ }
110
+ this.slippage = slippage;
111
+ }
96
112
  initOrUpdateAgent(agentPrivateKey, agentPublicKey, agentName) {
97
113
  this.agentPrivateKey = agentPrivateKey.startsWith('0x') ? agentPrivateKey : ethUtil.addHexPrefix(agentPrivateKey);
98
114
  this.agentPublicKey = agentPublicKey.startsWith('0x') ? agentPublicKey : ethUtil.addHexPrefix(agentPublicKey);
@@ -222,7 +238,7 @@ class ExchangeClient {
222
238
  marketOrderOpen(params) {
223
239
  return __awaiter(this, void 0, void 0, function* () {
224
240
  try {
225
- const slippage = params.slippage || constants_1.SLIPPAGE;
241
+ const slippage = params.slippage || this.slippage;
226
242
  const szDecimals = yield this.symbolConversion.getAssetSzDecimals(params.coin);
227
243
  const px = this.getSlippagePx((0, number_1.removeTrailingZeros)(params.midPx), slippage, params.isBuy, szDecimals);
228
244
  const orders = [{
@@ -231,14 +247,14 @@ class ExchangeClient {
231
247
  sz: (0, number_1.removeTrailingZeros)(params.size),
232
248
  limitPx: px,
233
249
  reduceOnly: params.reduceOnly || false,
234
- orderType: { limit: { tif: 'Ioc' } },
250
+ orderType: { limit: { tif: 'FrontendMarket' } },
235
251
  }];
236
252
  if (params.tpTriggerPx) {
237
253
  const tpOrder = {
238
254
  coin: params.coin,
239
255
  isBuy: !params.isBuy,
240
256
  sz: (0, number_1.removeTrailingZeros)(params.size),
241
- limitPx: (0, number_1.removeTrailingZeros)(params.tpTriggerPx),
257
+ limitPx: this.getSlippagePx((0, number_1.removeTrailingZeros)(params.tpTriggerPx), slippage, !params.isBuy, szDecimals),
242
258
  reduceOnly: true,
243
259
  orderType: {
244
260
  trigger: {
@@ -255,7 +271,7 @@ class ExchangeClient {
255
271
  coin: params.coin,
256
272
  isBuy: !params.isBuy,
257
273
  sz: (0, number_1.removeTrailingZeros)(params.size),
258
- limitPx: (0, number_1.removeTrailingZeros)(params.slTriggerPx),
274
+ limitPx: this.getSlippagePx((0, number_1.removeTrailingZeros)(params.slTriggerPx), slippage, !params.isBuy, szDecimals),
259
275
  reduceOnly: true,
260
276
  orderType: {
261
277
  trigger: {
@@ -267,9 +283,11 @@ class ExchangeClient {
267
283
  };
268
284
  orders.push(slOrder);
269
285
  }
286
+ const hasTpOrSl = params.slTriggerPx || params.tpTriggerPx;
270
287
  const res = yield this.multiOrder({
271
288
  orders,
272
289
  builder: params.builder,
290
+ grouping: hasTpOrSl ? 'normalTpsl' : 'na',
273
291
  });
274
292
  return res;
275
293
  }
@@ -280,8 +298,9 @@ class ExchangeClient {
280
298
  }
281
299
  marketOrderClose(params) {
282
300
  return __awaiter(this, void 0, void 0, function* () {
301
+ var _a;
283
302
  try {
284
- const slippage = params.slippage || constants_1.SLIPPAGE;
303
+ const slippage = params.slippage || this.slippage;
285
304
  const szDecimals = yield this.symbolConversion.getAssetSzDecimals(params.coin);
286
305
  const px = this.getSlippagePx(params.midPx, slippage, params.isBuy, szDecimals);
287
306
  const orders = [{
@@ -289,7 +308,7 @@ class ExchangeClient {
289
308
  isBuy: params.isBuy,
290
309
  sz: (0, number_1.removeTrailingZeros)(params.size),
291
310
  limitPx: px,
292
- reduceOnly: true,
311
+ reduceOnly: (_a = params.reduceOnly) !== null && _a !== void 0 ? _a : true,
293
312
  orderType: { limit: { tif: 'Ioc' } },
294
313
  }];
295
314
  const res = yield this.multiOrder({
@@ -303,6 +322,105 @@ class ExchangeClient {
303
322
  }
304
323
  });
305
324
  }
325
+ /**
326
+ * Place a market order
327
+ * default slippage is 0.08
328
+ * need to update leverage before place order
329
+ */
330
+ limitOrderOpen(params) {
331
+ return __awaiter(this, void 0, void 0, function* () {
332
+ try {
333
+ const slippage = params.slippage || this.slippage;
334
+ const szDecimals = yield this.symbolConversion.getAssetSzDecimals(params.coin);
335
+ // const px = this.getSlippagePx(removeTrailingZeros(params.limitPx), slippage, params.isBuy, szDecimals);
336
+ const orders = [{
337
+ coin: params.coin,
338
+ isBuy: params.isBuy,
339
+ sz: (0, number_1.removeTrailingZeros)(params.size),
340
+ limitPx: (0, number_1.removeTrailingZeros)(params.limitPx),
341
+ reduceOnly: params.reduceOnly || false,
342
+ orderType: { limit: { tif: params.tif || 'Gtc' } },
343
+ }];
344
+ if (params.tpTriggerPx) {
345
+ const tpOrder = {
346
+ coin: params.coin,
347
+ isBuy: !params.isBuy,
348
+ sz: (0, number_1.removeTrailingZeros)(params.size),
349
+ limitPx: this.getSlippagePx((0, number_1.removeTrailingZeros)(params.tpTriggerPx), slippage, !params.isBuy, szDecimals),
350
+ reduceOnly: true,
351
+ orderType: {
352
+ trigger: {
353
+ isMarket: true,
354
+ triggerPx: (0, number_1.removeTrailingZeros)(params.tpTriggerPx),
355
+ tpsl: 'tp',
356
+ }
357
+ },
358
+ };
359
+ orders.push(tpOrder);
360
+ }
361
+ if (params.slTriggerPx) {
362
+ const slOrder = {
363
+ coin: params.coin,
364
+ isBuy: !params.isBuy,
365
+ sz: (0, number_1.removeTrailingZeros)(params.size),
366
+ limitPx: this.getSlippagePx((0, number_1.removeTrailingZeros)(params.slTriggerPx), slippage, !params.isBuy, szDecimals),
367
+ reduceOnly: true,
368
+ orderType: {
369
+ trigger: {
370
+ isMarket: true,
371
+ triggerPx: (0, number_1.removeTrailingZeros)(params.slTriggerPx),
372
+ tpsl: 'sl',
373
+ }
374
+ }
375
+ };
376
+ orders.push(slOrder);
377
+ }
378
+ const hasTpOrSl = params.slTriggerPx || params.tpTriggerPx;
379
+ const res = yield this.multiOrder({
380
+ orders,
381
+ builder: params.builder,
382
+ grouping: hasTpOrSl ? 'normalTpsl' : 'na',
383
+ });
384
+ return res;
385
+ }
386
+ catch (error) {
387
+ throw error;
388
+ }
389
+ });
390
+ }
391
+ closeAllPositions(clearinghouseState_1) {
392
+ return __awaiter(this, arguments, void 0, function* (clearinghouseState, slippage = constants_1.SLIPPAGE, builder) {
393
+ try {
394
+ const closeOrders = [];
395
+ for (const position of clearinghouseState.assetPositions) {
396
+ const item = position.position;
397
+ if (parseFloat(item.szi) !== 0) {
398
+ const isBuy = parseFloat(item.szi) < 0;
399
+ const size = Math.abs(parseFloat(item.szi));
400
+ const markPx = parseFloat(item.positionValue) / size;
401
+ const szDecimals = yield this.symbolConversion.getAssetSzDecimals(item.coin);
402
+ const px = this.getSlippagePx(markPx.toString(), slippage, isBuy, szDecimals);
403
+ closeOrders.push({
404
+ coin: item.coin,
405
+ isBuy,
406
+ sz: (0, number_1.removeTrailingZeros)(size.toString()),
407
+ limitPx: px,
408
+ reduceOnly: true,
409
+ orderType: { limit: { tif: 'Ioc' } },
410
+ });
411
+ }
412
+ }
413
+ const res = yield this.multiOrder({
414
+ orders: closeOrders,
415
+ builder,
416
+ });
417
+ return res;
418
+ }
419
+ catch (error) {
420
+ throw error;
421
+ }
422
+ });
423
+ }
306
424
  /**
307
425
  * Place a take profit or stop loss market order
308
426
  * default slippage is 0.08
@@ -310,7 +428,7 @@ class ExchangeClient {
310
428
  placeTPSlMarketOrder(params) {
311
429
  return __awaiter(this, void 0, void 0, function* () {
312
430
  try {
313
- const slippage = params.slippage || constants_1.SLIPPAGE;
431
+ const slippage = params.slippage || this.slippage;
314
432
  const szDecimals = yield this.symbolConversion.getAssetSzDecimals(params.coin);
315
433
  const px = this.getSlippagePx((0, number_1.removeTrailingZeros)(params.triggerPx), slippage, params.isBuy, szDecimals);
316
434
  const orders = [{
@@ -340,7 +458,6 @@ class ExchangeClient {
340
458
  }
341
459
  /**
342
460
  * Place a take profit or stop loss limit order
343
- * default slippage is 0.08
344
461
  */
345
462
  placeTPSlLimitOrder(params) {
346
463
  return __awaiter(this, void 0, void 0, function* () {
@@ -421,13 +538,14 @@ class ExchangeClient {
421
538
  bindTpslByOrderId(params) {
422
539
  return __awaiter(this, void 0, void 0, function* () {
423
540
  let orders = [];
541
+ const slippage = params.slippage || this.slippage;
424
542
  const szDecimals = yield this.symbolConversion.getAssetSzDecimals(params.coin);
425
543
  if (params.tpTriggerPx) {
426
544
  orders.push({
427
545
  coin: params.coin,
428
546
  isBuy: !params.isBuy,
429
547
  sz: '0',
430
- limitPx: this.getSlippagePx((0, number_1.removeTrailingZeros)(params.tpTriggerPx), constants_1.SLIPPAGE, !params.isBuy, szDecimals),
548
+ limitPx: this.getSlippagePx((0, number_1.removeTrailingZeros)(params.tpTriggerPx), slippage, !params.isBuy, szDecimals),
431
549
  reduceOnly: true,
432
550
  orderType: {
433
551
  trigger: {
@@ -443,7 +561,7 @@ class ExchangeClient {
443
561
  coin: params.coin,
444
562
  isBuy: !params.isBuy,
445
563
  sz: '0',
446
- limitPx: this.getSlippagePx((0, number_1.removeTrailingZeros)(params.slTriggerPx), constants_1.SLIPPAGE, !params.isBuy, szDecimals),
564
+ limitPx: this.getSlippagePx((0, number_1.removeTrailingZeros)(params.slTriggerPx), slippage, !params.isBuy, szDecimals),
447
565
  reduceOnly: true,
448
566
  orderType: {
449
567
  trigger: {
@@ -464,6 +582,54 @@ class ExchangeClient {
464
582
  });
465
583
  });
466
584
  }
585
+ updateTpslByOrderId(params) {
586
+ return __awaiter(this, void 0, void 0, function* () {
587
+ let orders = [];
588
+ const szDecimals = yield this.symbolConversion.getAssetSzDecimals(params.coin);
589
+ const isBuy = !params.isBuy;
590
+ const slippage = params.slippage || this.slippage;
591
+ if (params.tp) {
592
+ const limitPx = params.tp.limitPx || this.getSlippagePx((0, number_1.removeTrailingZeros)(params.tp.triggerPx), slippage, isBuy, szDecimals);
593
+ orders.push({
594
+ oid: params.tp.oid,
595
+ coin: params.coin,
596
+ isBuy,
597
+ sz: '0',
598
+ limitPx,
599
+ reduceOnly: true,
600
+ orderType: {
601
+ trigger: {
602
+ isMarket: true,
603
+ triggerPx: (0, number_1.removeTrailingZeros)(params.tp.triggerPx),
604
+ tpsl: 'tp',
605
+ }
606
+ }
607
+ });
608
+ }
609
+ if (params.sl) {
610
+ const limitPx = params.sl.limitPx || this.getSlippagePx((0, number_1.removeTrailingZeros)(params.sl.triggerPx), slippage, isBuy, szDecimals);
611
+ orders.push({
612
+ oid: params.sl.oid,
613
+ coin: params.coin,
614
+ isBuy,
615
+ sz: '0',
616
+ limitPx,
617
+ reduceOnly: true,
618
+ orderType: {
619
+ trigger: {
620
+ isMarket: true,
621
+ triggerPx: (0, number_1.removeTrailingZeros)(params.sl.triggerPx),
622
+ tpsl: 'sl',
623
+ }
624
+ }
625
+ });
626
+ }
627
+ if (orders.length === 0) {
628
+ throw new Error('Must have at least one tp or sl');
629
+ }
630
+ return this.batchModifyOrder(orders);
631
+ });
632
+ }
467
633
  /**
468
634
  * Cancel order(s)
469
635
  */
@@ -495,7 +661,8 @@ class ExchangeClient {
495
661
  modifyOrder(params) {
496
662
  return __awaiter(this, void 0, void 0, function* () {
497
663
  const nonce = Date.now();
498
- const modify = {
664
+ const action = {
665
+ type: constants_1.ExchangeType.MODIFY,
499
666
  oid: params.oid,
500
667
  order: {
501
668
  a: yield this.symbolConversion.getAssetIndex(params.coin),
@@ -506,9 +673,39 @@ class ExchangeClient {
506
673
  t: params.orderType || { limit: { tif: 'Gtc' } },
507
674
  },
508
675
  };
676
+ const signature = (0, signer_1.signL1AgentAction)(this.getAgentPrivateKey(), action, this.isTestnet, nonce);
677
+ return this.httpClient.exchange({
678
+ action,
679
+ nonce,
680
+ signature,
681
+ });
682
+ });
683
+ }
684
+ batchModifyOrder(params) {
685
+ return __awaiter(this, void 0, void 0, function* () {
686
+ const nonce = Date.now();
687
+ const assetIndexCache = new Map();
688
+ const modifies = yield Promise.all(params.map((param) => __awaiter(this, void 0, void 0, function* () {
689
+ let assetIndex = assetIndexCache.get(param.coin);
690
+ if (assetIndex === undefined) {
691
+ assetIndex = yield this.symbolConversion.getAssetIndex(param.coin);
692
+ assetIndexCache.set(param.coin, assetIndex);
693
+ }
694
+ return {
695
+ oid: param.oid,
696
+ order: {
697
+ a: assetIndex,
698
+ b: param.isBuy,
699
+ p: (0, number_1.removeTrailingZeros)(param.limitPx),
700
+ s: (0, number_1.removeTrailingZeros)(param.sz),
701
+ r: param.reduceOnly || false,
702
+ t: param.orderType || { limit: { tif: 'Gtc' } },
703
+ }
704
+ };
705
+ })));
509
706
  const action = {
510
- type: constants_1.ExchangeType.MODIFY,
511
- modifies: [modify],
707
+ type: constants_1.ExchangeType.BATCH_MODIFY,
708
+ modifies,
512
709
  };
513
710
  const signature = (0, signer_1.signL1AgentAction)(this.getAgentPrivateKey(), action, this.isTestnet, nonce);
514
711
  return this.httpClient.exchange({
@@ -758,12 +955,11 @@ class ExchangeClient {
758
955
  cancelTwapOrder(params) {
759
956
  return __awaiter(this, void 0, void 0, function* () {
760
957
  const nonce = Date.now();
958
+ const a = yield this.symbolConversion.getAssetIndex(params.coin);
761
959
  const action = {
762
960
  type: constants_1.ExchangeType.TWAP_CANCEL,
763
- twap: {
764
- a: yield this.symbolConversion.getAssetIndex(params.coin),
765
- t: params.twapId,
766
- },
961
+ a,
962
+ t: params.twapId,
767
963
  };
768
964
  const signature = (0, signer_1.signL1AgentAction)(this.getAgentPrivateKey(), action, this.isTestnet, nonce);
769
965
  return this.httpClient.exchange({
@@ -52,7 +52,7 @@ class HttpClient {
52
52
  if (error.name === 'AbortError') {
53
53
  throw new Error('Request timeout');
54
54
  }
55
- throw new Error(`API Error: ${error.message}`);
55
+ throw new Error(error.message);
56
56
  }
57
57
  throw new Error('Unknown API error');
58
58
  }
@@ -1,4 +1,4 @@
1
- import type { Meta, AssetCtx, ClearinghouseState, UserFills, CandleSnapshot, AllMids, ExtraAgent, OpenOrder, FeeResponse, UserNonFundingLedgerUpdates, UserHistoricalOrders, ReferralResponse, L2BookSnapshot, UserTwapSliceFill, FundingHistoryItem, UserFunding } from '../types';
1
+ import type { Meta, AssetCtx, ClearinghouseState, CandleSnapshot, AllMids, ExtraAgent, OpenOrder, FeeResponse, UserNonFundingLedgerUpdates, UserHistoricalOrders, ReferralResponse, L2BookSnapshot, UserTwapSliceFill, FundingHistoryItem, UserFunding, WsFill } from '../types';
2
2
  export interface InfoClientConfig {
3
3
  isTestnet?: boolean;
4
4
  timeout?: number;
@@ -29,7 +29,7 @@ export declare class InfoClient {
29
29
  /**
30
30
  * Get user's fill history
31
31
  */
32
- getUserFills(address?: string, aggregateByTime?: boolean): Promise<UserFills>;
32
+ getUserFills(address?: string, aggregateByTime?: boolean): Promise<WsFill[]>;
33
33
  /**
34
34
  * Get user's fill and cancel and other all orders history
35
35
  */
@@ -209,6 +209,21 @@ export interface OrderResponse {
209
209
  };
210
210
  };
211
211
  }
212
+ export interface LimitOrderParams {
213
+ coin: string;
214
+ isBuy: boolean;
215
+ size: string;
216
+ limitPx: string;
217
+ tif: Tif;
218
+ reduceOnly?: boolean;
219
+ tpTriggerPx?: string;
220
+ slTriggerPx?: string;
221
+ slippage?: number;
222
+ builder?: {
223
+ address: string;
224
+ fee: number;
225
+ };
226
+ }
212
227
  export interface MarketOrderParams {
213
228
  coin: string;
214
229
  isBuy: boolean;
@@ -452,11 +467,27 @@ export interface BindTpslByOrderIdParams {
452
467
  slTriggerPx?: string;
453
468
  coin: string;
454
469
  isBuy: boolean;
470
+ slippage?: number;
455
471
  builder?: {
456
472
  address: string;
457
473
  fee: number;
458
474
  };
459
475
  }
476
+ export interface UpdateTpslByOrderIdParams {
477
+ tp?: {
478
+ oid: OrderId;
479
+ triggerPx: string;
480
+ limitPx?: string;
481
+ };
482
+ sl?: {
483
+ oid: OrderId;
484
+ triggerPx: string;
485
+ limitPx?: string;
486
+ };
487
+ coin: string;
488
+ isBuy: boolean;
489
+ slippage?: number;
490
+ }
460
491
  export interface MultiOrderParams {
461
492
  orders: PlaceOrderParams[];
462
493
  grouping?: "na" | "normalTpsl" | "positionTpsl";
@@ -559,7 +590,7 @@ export interface TwapOrderResponse {
559
590
  response: {
560
591
  type: 'twapOrder';
561
592
  data?: {
562
- statuses?: {
593
+ status?: {
563
594
  running?: {
564
595
  twapId?: number;
565
596
  };
@@ -568,60 +599,77 @@ export interface TwapOrderResponse {
568
599
  };
569
600
  };
570
601
  }
571
- export interface TwapState {
572
- twapId: number;
573
- coin: string;
574
- isBuy: boolean;
575
- sz: string;
576
- reduceOnly: boolean;
577
- totalSz: string;
578
- executedSz: string;
579
- remainingSz: string;
580
- startTime: number;
581
- endTime: number;
582
- status: 'active' | 'completed' | 'cancelled';
583
- }
602
+ type TwapStateArray = [
603
+ number,
604
+ {
605
+ coin: string;
606
+ user: string;
607
+ side: Side;
608
+ sz: string;
609
+ executedSz: string;
610
+ executedNtl: string;
611
+ minutes: number;
612
+ reduceOnly: boolean;
613
+ randomize: boolean;
614
+ timestamp: number;
615
+ }
616
+ ];
584
617
  export interface WsTwapStates {
585
618
  dex: string;
586
619
  user: string;
587
- states?: TwapState[];
620
+ states: TwapStateArray[];
588
621
  }
589
622
  export interface WsOpenOrders {
590
623
  user: string;
591
624
  orders?: OpenOrder[];
592
625
  }
626
+ export interface UserTwapSliceFill {
627
+ fill: {
628
+ closedPnl: string;
629
+ coin: string;
630
+ crossed: boolean;
631
+ dir: string;
632
+ fee: string;
633
+ feeToken: string;
634
+ hash: string;
635
+ oid: number;
636
+ px: string;
637
+ side: Side;
638
+ startPosition: string;
639
+ sz: string;
640
+ tid: number;
641
+ time: number;
642
+ };
643
+ twapId: number;
644
+ }
593
645
  export interface WsUserTwapSliceFills {
594
646
  user: string;
595
- fills?: UserTwapSliceFill[];
647
+ isSnapshot?: boolean;
648
+ twapSliceFills: UserTwapSliceFill[];
596
649
  }
597
650
  export interface WsUserTwapHistory {
598
651
  user: string;
599
- history?: UserTwapHistory[];
600
- }
601
- export interface UserTwapSliceFill {
602
- coin: string;
603
- px: string;
604
- sz: string;
605
- side: Side;
606
- time: number;
607
- hash: string;
608
- oid: number;
609
- crossed: boolean;
610
- fee: string;
611
- tid: number;
612
- twapId: number;
652
+ isSnapshot?: boolean;
653
+ history: UserTwapHistory[];
613
654
  }
614
655
  export interface UserTwapHistory {
656
+ state: {
657
+ coin: string;
658
+ executedNtl: string;
659
+ executedSz: string;
660
+ minutes: number;
661
+ randomize: boolean;
662
+ reduceOnly: boolean;
663
+ side: Side;
664
+ sz: string;
665
+ timestamp: number;
666
+ user: string;
667
+ };
668
+ status: {
669
+ status: 'finished' | 'terminated' | 'activated';
670
+ };
671
+ time: number;
615
672
  twapId: number;
616
- user: string;
617
- coin: string;
618
- side: Side;
619
- sz: string;
620
- totalFilled: string;
621
- avgFillPx: string;
622
- startTime: number;
623
- endTime: number;
624
- status: string;
625
673
  }
626
674
  export interface L2BookSnapshot {
627
675
  coin: string;
@@ -649,3 +697,4 @@ export interface UserFunding {
649
697
  export interface Notification {
650
698
  notification: string;
651
699
  }
700
+ export {};
package/package.json CHANGED
@@ -1,37 +1,37 @@
1
- {
2
- "name": "@rabby-wallet/hyperliquid-sdk",
3
- "version": "1.1.2-beta.9",
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.1.3",
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
+ }