@rabby-wallet/hyperliquid-sdk 1.1.1 → 1.1.2-beta.1

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 } from '../types';
2
+ import type { OrderResponse, CancelResponse, ExchangeClientConfig, PlaceOrderParams, MultiOrderParams, CancelOrderParams, ModifyOrderParams, WithdrawParams, ApproveBuilderFeeParams, PrepareApproveBuilderFeeResult, SendApproveParams, MarketOrderParams, UpdateLeverageParams, BindTpslByOrderIdParams, UpdateIsolatedMarginParams, TwapOrderParams, TwapCancelParams, TwapOrderResponse } from '../types';
3
3
  /**
4
4
  * Client for executing trades on Hyperliquid (perpetuals only)
5
5
  * Only includes essential trading APIs as specified
@@ -125,4 +125,13 @@ export declare class ExchangeClient {
125
125
  */
126
126
  prepareWithdraw(params: WithdrawParams): PrepareApproveBuilderFeeResult;
127
127
  sendWithdraw(params: SendApproveParams): Promise<any>;
128
+ /**
129
+ * Place a TWAP order
130
+ * TWAP orders split a large order into smaller slices over time
131
+ */
132
+ placeTwapOrder(params: TwapOrderParams): Promise<TwapOrderResponse>;
133
+ /**
134
+ * Cancel a TWAP order
135
+ */
136
+ cancelTwapOrder(params: TwapCancelParams): Promise<any>;
128
137
  }
@@ -653,5 +653,54 @@ class ExchangeClient {
653
653
  signature: splitSignature,
654
654
  });
655
655
  }
656
+ /**
657
+ * Place a TWAP order
658
+ * TWAP orders split a large order into smaller slices over time
659
+ */
660
+ placeTwapOrder(params) {
661
+ return __awaiter(this, void 0, void 0, function* () {
662
+ const nonce = Date.now();
663
+ const action = {
664
+ type: constants_1.ExchangeType.TWAP_ORDER,
665
+ a: yield this.symbolConversion.getAssetIndex(params.coin),
666
+ b: params.isBuy,
667
+ s: (0, number_1.removeTrailingZeros)(params.sz),
668
+ r: params.reduceOnly || false,
669
+ m: params.durationMillis,
670
+ t: params.randomizeDelay || false,
671
+ };
672
+ if (params.builder) {
673
+ action.builder = {
674
+ b: params.builder.address,
675
+ f: params.builder.fee,
676
+ };
677
+ }
678
+ const signature = (0, signer_1.signL1AgentAction)(this.getAgentPrivateKey(), action, this.isTestnet, nonce);
679
+ return this.httpClient.exchange({
680
+ action,
681
+ nonce,
682
+ signature,
683
+ });
684
+ });
685
+ }
686
+ /**
687
+ * Cancel a TWAP order
688
+ */
689
+ cancelTwapOrder(params) {
690
+ return __awaiter(this, void 0, void 0, function* () {
691
+ const nonce = Date.now();
692
+ const action = {
693
+ type: constants_1.ExchangeType.TWAP_CANCEL,
694
+ a: yield this.symbolConversion.getAssetIndex(params.coin),
695
+ t: params.twapId,
696
+ };
697
+ const signature = (0, signer_1.signL1AgentAction)(this.getAgentPrivateKey(), action, this.isTestnet, nonce);
698
+ return this.httpClient.exchange({
699
+ action,
700
+ nonce,
701
+ signature,
702
+ });
703
+ });
704
+ }
656
705
  }
657
706
  exports.ExchangeClient = ExchangeClient;
@@ -1,4 +1,4 @@
1
- import type { Meta, AssetCtx, ClearinghouseState, UserFills, CandleSnapshot, AllMids, ExtraAgent, OpenOrder, FeeResponse, UserNonFundingLedgerUpdates, UserHistoricalOrders, ReferralResponse } from '../types';
1
+ import type { Meta, AssetCtx, ClearinghouseState, UserFills, CandleSnapshot, AllMids, ExtraAgent, OpenOrder, FeeResponse, UserNonFundingLedgerUpdates, UserHistoricalOrders, ReferralResponse, L2BookSnapshot, UserTwapSliceFill, FundingHistoryItem, UserFunding } from '../types';
2
2
  export interface InfoClientConfig {
3
3
  isTestnet?: boolean;
4
4
  timeout?: number;
@@ -61,4 +61,29 @@ export declare class InfoClient {
61
61
  * Get user's approved persistent agents
62
62
  */
63
63
  extraAgents(address?: string): Promise<ExtraAgent[]>;
64
+ /**
65
+ * get L2 order book for a specific coin
66
+ * nSigFigs: Optional field to aggregate levels to nSigFigs significant figures. Valid values are 2, 3, 4, 5, and null, which means full precision
67
+ * mantissa: Optional field to aggregate levels. This field is only allowed if nSigFigs is 5. Accepts values of 1(null), 2 or 5.
68
+ * total six level
69
+ * nSigFig: 5 default
70
+ * nSigFig: 5 mantissa: 2
71
+ * nSigFig: 5 mantissa: 5
72
+ * nSigFig: 4
73
+ * nSigFig: 3
74
+ * nSigFig: 2
75
+ */
76
+ getL2Book(coin: string, nSigFigs?: number, mantissa?: number): Promise<L2BookSnapshot>;
77
+ /**
78
+ * Get user's TWAP slice fills
79
+ */
80
+ getUserTwapSliceFills(address?: string, startTime?: number, endTime?: number): Promise<UserTwapSliceFill[]>;
81
+ /**
82
+ * Get funding history for a specific coin
83
+ */
84
+ getFundingHistory(coin: string, startTime: number, endTime?: number): Promise<FundingHistoryItem[]>;
85
+ /**
86
+ * Get user funding
87
+ */
88
+ getUserFunding(address?: string): Promise<UserFunding[]>;
64
89
  }
@@ -244,5 +244,74 @@ class InfoClient {
244
244
  });
245
245
  });
246
246
  }
247
+ /**
248
+ * get L2 order book for a specific coin
249
+ * nSigFigs: Optional field to aggregate levels to nSigFigs significant figures. Valid values are 2, 3, 4, 5, and null, which means full precision
250
+ * mantissa: Optional field to aggregate levels. This field is only allowed if nSigFigs is 5. Accepts values of 1(null), 2 or 5.
251
+ * total six level
252
+ * nSigFig: 5 default
253
+ * nSigFig: 5 mantissa: 2
254
+ * nSigFig: 5 mantissa: 5
255
+ * nSigFig: 4
256
+ * nSigFig: 3
257
+ * nSigFig: 2
258
+ */
259
+ getL2Book(coin, nSigFigs, mantissa) {
260
+ return __awaiter(this, void 0, void 0, function* () {
261
+ return this.httpClient.info({
262
+ type: constants_1.InfoType.L2_BOOK,
263
+ coin,
264
+ nSigFigs,
265
+ // Optional field to aggregate levels to nSigFigs significant figures. Valid values are 2, 3, 4, 5, and null, which means full precision
266
+ mantissa,
267
+ // Optional field to aggregate levels. This field is only allowed if nSigFigs is 5. Accepts values of 1, 2 or 5.
268
+ });
269
+ });
270
+ }
271
+ /**
272
+ * Get user's TWAP slice fills
273
+ */
274
+ getUserTwapSliceFills(address, startTime, endTime) {
275
+ return __awaiter(this, void 0, void 0, function* () {
276
+ const user = address || this.masterAddress;
277
+ if (!user) {
278
+ throw new Error('user address is empty');
279
+ }
280
+ return this.httpClient.info({
281
+ type: constants_1.InfoType.USER_TWAP_SLICE_FILLS,
282
+ user,
283
+ startTime: startTime || 0,
284
+ endTime,
285
+ });
286
+ });
287
+ }
288
+ /**
289
+ * Get funding history for a specific coin
290
+ */
291
+ getFundingHistory(coin, startTime, endTime) {
292
+ return __awaiter(this, void 0, void 0, function* () {
293
+ return this.httpClient.info({
294
+ type: constants_1.InfoType.FUNDING_HISTORY,
295
+ coin,
296
+ startTime,
297
+ endTime,
298
+ });
299
+ });
300
+ }
301
+ /**
302
+ * Get user funding
303
+ */
304
+ getUserFunding(address) {
305
+ return __awaiter(this, void 0, void 0, function* () {
306
+ const user = address || this.masterAddress;
307
+ if (!user) {
308
+ throw new Error('user address is empty');
309
+ }
310
+ return this.httpClient.info({
311
+ type: constants_1.InfoType.USER_FUNDING,
312
+ user,
313
+ });
314
+ });
315
+ }
247
316
  }
248
317
  exports.InfoClient = InfoClient;
@@ -1,4 +1,4 @@
1
- import type { AllMids, L2Book, Candle, WsOrder, WebData2, WsActiveAssetCtx, WsUserFills, WsClearinghouseState } from '../types';
1
+ import type { L2Book, Candle, WsOrder, WebData2, WsActiveAssetCtx, WsUserFills, WsClearinghouseState, Notification, WsTwapStates, WsOpenOrders, WsUserTwapSliceFills, WsUserTwapHistory, wsUserNonFundingLedgerUpdates, WsAllMids, WsTrade } from '../types';
2
2
  export interface WebSocketClientConfig {
3
3
  masterAddress?: string;
4
4
  isTestnet?: boolean;
@@ -17,7 +17,8 @@ export declare class WebSocketClient {
17
17
  private ws;
18
18
  private readonly url;
19
19
  private readonly config;
20
- private subscriptions;
20
+ private typeSubscriptions;
21
+ private userSubscriptions;
21
22
  private activeSubscriptions;
22
23
  private reconnectAttempts;
23
24
  private isConnecting;
@@ -44,6 +45,11 @@ export declare class WebSocketClient {
44
45
  */
45
46
  disconnect(): void;
46
47
  private getSubscriptionKey;
48
+ /**
49
+ * Dispatch message to matching subscriptions
50
+ * Uses direct lookup instead of iteration for better performance
51
+ */
52
+ private dispatchMessage;
47
53
  /**
48
54
  * Subscribe to a channel
49
55
  */
@@ -51,11 +57,24 @@ export declare class WebSocketClient {
51
57
  /**
52
58
  * Subscribe to all mid prices
53
59
  */
54
- subscribeToAllMids(callback: SubscriptionCallback<AllMids>): Subscription;
60
+ subscribeToAllMids(callback: SubscriptionCallback<WsAllMids>): Subscription;
55
61
  /**
56
62
  * Subscribe to L2 order book for a specific coin
57
- */
58
- subscribeToL2Book(coin: string, callback: SubscriptionCallback<L2Book>): Subscription;
63
+ * nSigFigs: Optional field to aggregate levels to nSigFigs significant figures. Valid values are 2, 3, 4, 5, and null, which means full precision
64
+ * mantissa: Optional field to aggregate levels. This field is only allowed if nSigFigs is 5. Accepts values of 1, 2 or 5.
65
+ * total six level
66
+ * nSigFig: 5 default
67
+ * nSigFig: 5 mantissa: 2
68
+ * nSigFig: 5 mantissa: 5
69
+ * nSigFig: 4
70
+ * nSigFig: 3
71
+ * nSigFig: 2
72
+ */
73
+ subscribeToL2Book({ coin, nSigFigs, mantissa, }: {
74
+ coin: string;
75
+ nSigFigs?: number;
76
+ mantissa?: number;
77
+ }, callback: SubscriptionCallback<L2Book>): Subscription;
59
78
  /**
60
79
  * Subscribe to active asset ctx
61
80
  */
@@ -63,7 +82,7 @@ export declare class WebSocketClient {
63
82
  /**
64
83
  * Subscribe to trades for a specific coin
65
84
  */
66
- subscribeToTrades(coin: string, callback: SubscriptionCallback<any[]>): Subscription;
85
+ subscribeToTrades(coin: string, callback: SubscriptionCallback<WsTrade[]>): Subscription;
67
86
  /**
68
87
  * Subscribe to candlestick data
69
88
  */
@@ -108,4 +127,28 @@ export declare class WebSocketClient {
108
127
  * @param state 'active' | 'background' | 'inactive'
109
128
  */
110
129
  handleAppStateChange(state: string): void;
130
+ /**
131
+ * Subscribe to notification messages
132
+ */
133
+ subscribeToNotification(callback: SubscriptionCallback<Notification>): Subscription;
134
+ /**
135
+ * Subscribe to TWAP order states
136
+ */
137
+ subscribeToTwapStates(callback: SubscriptionCallback<WsTwapStates>): Subscription;
138
+ /**
139
+ * Subscribe to open orders
140
+ */
141
+ subscribeToOpenOrders(callback: SubscriptionCallback<WsOpenOrders>): Subscription;
142
+ /**
143
+ * Subscribe to user non-funding ledger updates (deposits/withdrawals)
144
+ */
145
+ subscribeToUserNonFundingLedgerUpdates(callback: SubscriptionCallback<wsUserNonFundingLedgerUpdates>): Subscription;
146
+ /**
147
+ * Subscribe to user TWAP slice fills
148
+ */
149
+ subscribeToUserTwapSliceFills(callback: SubscriptionCallback<WsUserTwapSliceFills>): Subscription;
150
+ /**
151
+ * Subscribe to user TWAP history
152
+ */
153
+ subscribeToUserTwapHistory(callback: SubscriptionCallback<WsUserTwapHistory>): Subscription;
111
154
  }
@@ -17,7 +17,10 @@ const constants_1 = require("../types/constants");
17
17
  class WebSocketClient {
18
18
  constructor(config) {
19
19
  this.ws = null;
20
- this.subscriptions = new Map();
20
+ // Map<type, callback[]> for most subscription types
21
+ this.typeSubscriptions = new Map();
22
+ // Map<type:user, callback[]> for clearinghouseState (multi-account support)
23
+ this.userSubscriptions = new Map();
21
24
  this.activeSubscriptions = new Map();
22
25
  this.reconnectAttempts = 0;
23
26
  this.isConnecting = false;
@@ -78,7 +81,24 @@ class WebSocketClient {
78
81
  var _a;
79
82
  if (((_a = this.ws) === null || _a === void 0 ? void 0 : _a.readyState) === WebSocket.OPEN) {
80
83
  const subKey = this.getSubscriptionKey(message.subscription);
81
- this.subscriptions.set(message.subscription.type, callback);
84
+ const type = message.subscription.type;
85
+ const user = message.subscription.user;
86
+ // Register callback in appropriate map
87
+ if (type === constants_1.WsSubscriptionType.CLEARINGHOUSE_STATE && user) {
88
+ const userKey = `${type}:${user.toLowerCase()}`;
89
+ const callbacks = this.userSubscriptions.get(userKey) || [];
90
+ if (!callbacks.includes(callback)) {
91
+ callbacks.push(callback);
92
+ this.userSubscriptions.set(userKey, callbacks);
93
+ }
94
+ }
95
+ else {
96
+ const callbacks = this.typeSubscriptions.get(type) || [];
97
+ if (!callbacks.includes(callback)) {
98
+ callbacks.push(callback);
99
+ this.typeSubscriptions.set(type, callbacks);
100
+ }
101
+ }
82
102
  this.activeSubscriptions.set(subKey, { message, callback });
83
103
  this.ws.send(JSON.stringify(Object.assign(Object.assign({}, message), { method: 'subscribe' })));
84
104
  }
@@ -88,50 +108,15 @@ class WebSocketClient {
88
108
  resolve();
89
109
  };
90
110
  this.ws.onmessage = (event) => {
91
- var _a;
92
111
  try {
93
112
  const data = JSON.parse(event.data);
94
113
  // Handle pong response
95
114
  if (data.channel === 'pong') {
96
- // console.log('Received pong from server'); // 可以注释掉以减少日志输出
97
115
  return;
98
116
  }
99
117
  const type = data.channel;
100
- // Iterate through active subscriptions to find matching ones
101
- let hasDispatched = false;
102
- for (const { message, callback } of this.activeSubscriptions.values()) {
103
- const subParams = message.subscription;
104
- if (subParams.type === type) {
105
- let isMatch = true;
106
- // Filter based on subscription parameters
107
- if (type === 'l2Book' && data.data.coin !== subParams.coin)
108
- isMatch = false;
109
- if (type === 'trades' && ((_a = data.data[0]) === null || _a === void 0 ? void 0 : _a.coin) !== subParams.coin)
110
- isMatch = false;
111
- if (type === 'candle' && (data.data.s !== subParams.coin || data.data.i !== subParams.interval))
112
- isMatch = false;
113
- if (type === 'activeAssetCtx' && data.data.coin !== subParams.coin)
114
- isMatch = false;
115
- // For user-specific data
116
- if (subParams.user) {
117
- // If response data contains user, verify it matches
118
- if (data.data && data.data.user && data.data.user.toLowerCase() !== subParams.user.toLowerCase()) {
119
- isMatch = false;
120
- }
121
- }
122
- if (isMatch) {
123
- callback(data.data);
124
- hasDispatched = true;
125
- }
126
- }
127
- }
128
- // Fallback to simple type map if no active subscription matched (backward compatibility or if activeSubscriptions missing)
129
- if (!hasDispatched) {
130
- const callback = this.subscriptions.get(type);
131
- if (callback) {
132
- callback(data.data);
133
- }
134
- }
118
+ // Dispatch message to matching subscriptions
119
+ this.dispatchMessage(type, data.data);
135
120
  }
136
121
  catch (error) {
137
122
  console.error('Error parsing WebSocket message:', error);
@@ -207,7 +192,8 @@ class WebSocketClient {
207
192
  this.ws.close();
208
193
  this.ws = null;
209
194
  }
210
- this.subscriptions.clear();
195
+ this.typeSubscriptions.clear();
196
+ this.userSubscriptions.clear();
211
197
  this.activeSubscriptions.clear();
212
198
  this.pendingSubscriptions = [];
213
199
  this.reconnectAttempts = 0; // 重置重连计数
@@ -215,6 +201,26 @@ class WebSocketClient {
215
201
  getSubscriptionKey(subscription) {
216
202
  return JSON.stringify(subscription);
217
203
  }
204
+ /**
205
+ * Dispatch message to matching subscriptions
206
+ * Uses direct lookup instead of iteration for better performance
207
+ */
208
+ dispatchMessage(type, data) {
209
+ // Special handling for clearinghouseState: dispatch by type:user
210
+ if (type === constants_1.WsSubscriptionType.CLEARINGHOUSE_STATE && data.user) {
211
+ const userKey = `${type}:${data.user.toLowerCase()}`;
212
+ const callbacks = this.userSubscriptions.get(userKey);
213
+ if (callbacks && callbacks.length > 0) {
214
+ callbacks.forEach(callback => callback(data));
215
+ return;
216
+ }
217
+ }
218
+ // For all other types: direct lookup by type
219
+ const callbacks = this.typeSubscriptions.get(type);
220
+ if (callbacks && callbacks.length > 0) {
221
+ callbacks.forEach(callback => callback(data));
222
+ }
223
+ }
218
224
  /**
219
225
  * Subscribe to a channel
220
226
  */
@@ -223,8 +229,22 @@ class WebSocketClient {
223
229
  const subscriptionData = { message, callback };
224
230
  const subKey = this.getSubscriptionKey(message.subscription);
225
231
  const type = message.subscription.type;
232
+ const user = message.subscription.user;
233
+ // Register callback in appropriate map
234
+ if (type === constants_1.WsSubscriptionType.CLEARINGHOUSE_STATE && user) {
235
+ // Multi-account support: store by type:user
236
+ const userKey = `${type}:${user.toLowerCase()}`;
237
+ const callbacks = this.userSubscriptions.get(userKey) || [];
238
+ callbacks.push(callback);
239
+ this.userSubscriptions.set(userKey, callbacks);
240
+ }
241
+ else {
242
+ // Normal subscriptions: store by type
243
+ const callbacks = this.typeSubscriptions.get(type) || [];
244
+ callbacks.push(callback);
245
+ this.typeSubscriptions.set(type, callbacks);
246
+ }
226
247
  if (((_a = this.ws) === null || _a === void 0 ? void 0 : _a.readyState) === WebSocket.OPEN) {
227
- this.subscriptions.set(type, callback);
228
248
  this.activeSubscriptions.set(subKey, subscriptionData);
229
249
  this.ws.send(JSON.stringify(Object.assign(Object.assign({}, message), { method: 'subscribe' })));
230
250
  }
@@ -240,16 +260,31 @@ class WebSocketClient {
240
260
  unsubscribe: () => {
241
261
  var _a;
242
262
  this.activeSubscriptions.delete(subKey);
243
- // Only remove the global callback if no other active subscriptions use this channel type
244
- let hasOtherSubs = false;
245
- for (const sub of this.activeSubscriptions.values()) {
246
- if (sub.message.subscription.type === type) {
247
- hasOtherSubs = true;
248
- break;
263
+ // Remove callback from appropriate map
264
+ if (type === constants_1.WsSubscriptionType.CLEARINGHOUSE_STATE && user) {
265
+ const userKey = `${type}:${user.toLowerCase()}`;
266
+ const callbacks = this.userSubscriptions.get(userKey);
267
+ if (callbacks) {
268
+ const filtered = callbacks.filter(cb => cb !== callback);
269
+ if (filtered.length > 0) {
270
+ this.userSubscriptions.set(userKey, filtered);
271
+ }
272
+ else {
273
+ this.userSubscriptions.delete(userKey);
274
+ }
249
275
  }
250
276
  }
251
- if (!hasOtherSubs) {
252
- this.subscriptions.delete(type);
277
+ else {
278
+ const callbacks = this.typeSubscriptions.get(type);
279
+ if (callbacks) {
280
+ const filtered = callbacks.filter(cb => cb !== callback);
281
+ if (filtered.length > 0) {
282
+ this.typeSubscriptions.set(type, filtered);
283
+ }
284
+ else {
285
+ this.typeSubscriptions.delete(type);
286
+ }
287
+ }
253
288
  }
254
289
  if (((_a = this.ws) === null || _a === void 0 ? void 0 : _a.readyState) === WebSocket.OPEN) {
255
290
  this.ws.send(JSON.stringify(Object.assign(Object.assign({}, message), { method: 'unsubscribe' })));
@@ -264,15 +299,24 @@ class WebSocketClient {
264
299
  */
265
300
  subscribeToAllMids(callback) {
266
301
  return this.subscribe({
267
- subscription: { type: 'allMids' },
302
+ subscription: { type: constants_1.WsSubscriptionType.ALL_MIDS },
268
303
  }, callback);
269
304
  }
270
305
  /**
271
306
  * Subscribe to L2 order book for a specific coin
307
+ * nSigFigs: Optional field to aggregate levels to nSigFigs significant figures. Valid values are 2, 3, 4, 5, and null, which means full precision
308
+ * mantissa: Optional field to aggregate levels. This field is only allowed if nSigFigs is 5. Accepts values of 1, 2 or 5.
309
+ * total six level
310
+ * nSigFig: 5 default
311
+ * nSigFig: 5 mantissa: 2
312
+ * nSigFig: 5 mantissa: 5
313
+ * nSigFig: 4
314
+ * nSigFig: 3
315
+ * nSigFig: 2
272
316
  */
273
- subscribeToL2Book(coin, callback) {
317
+ subscribeToL2Book({ coin, nSigFigs, mantissa, }, callback) {
274
318
  return this.subscribe({
275
- subscription: { type: 'l2Book', coin },
319
+ subscription: { type: constants_1.WsSubscriptionType.L2_BOOK, coin, nSigFigs: nSigFigs !== null && nSigFigs !== void 0 ? nSigFigs : null, mantissa: mantissa !== null && mantissa !== void 0 ? mantissa : null },
276
320
  }, callback);
277
321
  }
278
322
  /**
@@ -280,7 +324,7 @@ class WebSocketClient {
280
324
  */
281
325
  subscribeToActiveAssetCtx(coin, callback) {
282
326
  return this.subscribe({
283
- subscription: { type: 'activeAssetCtx', coin },
327
+ subscription: { type: constants_1.WsSubscriptionType.ACTIVE_ASSET_CTX, coin },
284
328
  }, callback);
285
329
  }
286
330
  /**
@@ -288,7 +332,7 @@ class WebSocketClient {
288
332
  */
289
333
  subscribeToTrades(coin, callback) {
290
334
  return this.subscribe({
291
- subscription: { type: 'trades', coin },
335
+ subscription: { type: constants_1.WsSubscriptionType.TRADES, coin },
292
336
  }, callback);
293
337
  }
294
338
  /**
@@ -296,7 +340,7 @@ class WebSocketClient {
296
340
  */
297
341
  subscribeToCandles(coin, interval, callback) {
298
342
  return this.subscribe({
299
- subscription: { type: 'candle', coin, interval },
343
+ subscription: { type: constants_1.WsSubscriptionType.CANDLE, coin, interval },
300
344
  }, callback);
301
345
  }
302
346
  /**
@@ -307,7 +351,7 @@ class WebSocketClient {
307
351
  throw new Error('masterAddress is empty');
308
352
  }
309
353
  return this.subscribe({
310
- subscription: { type: 'userFills', user: this.config.masterAddress, aggregateByTime: true },
354
+ subscription: { type: constants_1.WsSubscriptionType.USER_FILLS, user: this.config.masterAddress, aggregateByTime: true },
311
355
  }, callback);
312
356
  }
313
357
  /**
@@ -318,7 +362,7 @@ class WebSocketClient {
318
362
  throw new Error('masterAddress is empty');
319
363
  }
320
364
  return this.subscribe({
321
- subscription: { type: 'orderUpdates', user: this.config.masterAddress },
365
+ subscription: { type: constants_1.WsSubscriptionType.ORDER_UPDATES, user: this.config.masterAddress },
322
366
  }, callback);
323
367
  }
324
368
  /**
@@ -329,7 +373,7 @@ class WebSocketClient {
329
373
  throw new Error('masterAddress is empty');
330
374
  }
331
375
  return this.subscribe({
332
- subscription: { type: 'userFundings', user: this.config.masterAddress },
376
+ subscription: { type: constants_1.WsSubscriptionType.USER_FUNDINGS, user: this.config.masterAddress },
333
377
  }, callback);
334
378
  }
335
379
  /**
@@ -341,7 +385,7 @@ class WebSocketClient {
341
385
  throw new Error('masterAddress is empty');
342
386
  }
343
387
  return this.subscribe({
344
- subscription: { type: 'webData2', user: this.config.masterAddress },
388
+ subscription: { type: constants_1.WsSubscriptionType.WEB_DATA2, user: this.config.masterAddress },
345
389
  }, callback);
346
390
  }
347
391
  subscribeToClearinghouseState(user, callback) {
@@ -350,7 +394,7 @@ class WebSocketClient {
350
394
  throw new Error('user address is empty');
351
395
  }
352
396
  const subscriptions = users.map(u => this.subscribe({
353
- subscription: { type: 'clearinghouseState', user: u || this.config.masterAddress },
397
+ subscription: { type: constants_1.WsSubscriptionType.CLEARINGHOUSE_STATE, user: u || this.config.masterAddress },
354
398
  }, callback));
355
399
  return {
356
400
  unsubscribe: () => {
@@ -412,5 +456,71 @@ class WebSocketClient {
412
456
  }
413
457
  }
414
458
  }
459
+ /**
460
+ * Subscribe to notification messages
461
+ */
462
+ subscribeToNotification(callback) {
463
+ if (!this.config.masterAddress) {
464
+ throw new Error('masterAddress is empty');
465
+ }
466
+ return this.subscribe({
467
+ subscription: { type: constants_1.WsSubscriptionType.NOTIFICATION, user: this.config.masterAddress },
468
+ }, callback);
469
+ }
470
+ /**
471
+ * Subscribe to TWAP order states
472
+ */
473
+ subscribeToTwapStates(callback) {
474
+ if (!this.config.masterAddress) {
475
+ throw new Error('masterAddress is empty');
476
+ }
477
+ return this.subscribe({
478
+ subscription: { type: constants_1.WsSubscriptionType.TWAP_STATES, user: this.config.masterAddress },
479
+ }, callback);
480
+ }
481
+ /**
482
+ * Subscribe to open orders
483
+ */
484
+ subscribeToOpenOrders(callback) {
485
+ if (!this.config.masterAddress) {
486
+ throw new Error('masterAddress is empty');
487
+ }
488
+ return this.subscribe({
489
+ subscription: { type: constants_1.WsSubscriptionType.OPEN_ORDERS, user: this.config.masterAddress },
490
+ }, callback);
491
+ }
492
+ /**
493
+ * Subscribe to user non-funding ledger updates (deposits/withdrawals)
494
+ */
495
+ subscribeToUserNonFundingLedgerUpdates(callback) {
496
+ if (!this.config.masterAddress) {
497
+ throw new Error('masterAddress is empty');
498
+ }
499
+ return this.subscribe({
500
+ subscription: { type: constants_1.WsSubscriptionType.USER_NON_FUNDING_LEDGER_UPDATES, user: this.config.masterAddress },
501
+ }, callback);
502
+ }
503
+ /**
504
+ * Subscribe to user TWAP slice fills
505
+ */
506
+ subscribeToUserTwapSliceFills(callback) {
507
+ if (!this.config.masterAddress) {
508
+ throw new Error('masterAddress is empty');
509
+ }
510
+ return this.subscribe({
511
+ subscription: { type: constants_1.WsSubscriptionType.USER_TWAP_SLICE_FILLS, user: this.config.masterAddress },
512
+ }, callback);
513
+ }
514
+ /**
515
+ * Subscribe to user TWAP history
516
+ */
517
+ subscribeToUserTwapHistory(callback) {
518
+ if (!this.config.masterAddress) {
519
+ throw new Error('masterAddress is empty');
520
+ }
521
+ return this.subscribe({
522
+ subscription: { type: constants_1.WsSubscriptionType.USER_TWAP_HISTORY, user: this.config.masterAddress },
523
+ }, callback);
524
+ }
415
525
  }
416
526
  exports.WebSocketClient = WebSocketClient;
package/dist/index.d.ts CHANGED
@@ -6,4 +6,4 @@ export { HttpClient, HttpClientConfig } from './client/http-client';
6
6
  export * from './types';
7
7
  export * from './types/constants';
8
8
  export { BASE_URLS, WSS_URLS, ENDPOINTS } from './types/constants';
9
- export { InfoType, ExchangeType, OrderType, TimeInForce } from './types/constants';
9
+ export { InfoType, ExchangeType, OrderType, TimeInForce, WsSubscriptionType } from './types/constants';
package/dist/index.js CHANGED
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.TimeInForce = exports.OrderType = exports.ExchangeType = exports.InfoType = exports.ENDPOINTS = exports.WSS_URLS = exports.BASE_URLS = exports.HttpClient = exports.WebSocketClient = exports.ExchangeClient = exports.InfoClient = exports.HyperliquidSDK = void 0;
17
+ exports.WsSubscriptionType = exports.TimeInForce = exports.OrderType = exports.ExchangeType = exports.InfoType = exports.ENDPOINTS = exports.WSS_URLS = exports.BASE_URLS = exports.HttpClient = exports.WebSocketClient = exports.ExchangeClient = exports.InfoClient = exports.HyperliquidSDK = void 0;
18
18
  // Main SDK
19
19
  var hyperliquid_sdk_1 = require("./hyperliquid-sdk");
20
20
  Object.defineProperty(exports, "HyperliquidSDK", { enumerable: true, get: function () { return hyperliquid_sdk_1.HyperliquidSDK; } });
@@ -40,3 +40,4 @@ Object.defineProperty(exports, "InfoType", { enumerable: true, get: function ()
40
40
  Object.defineProperty(exports, "ExchangeType", { enumerable: true, get: function () { return constants_2.ExchangeType; } });
41
41
  Object.defineProperty(exports, "OrderType", { enumerable: true, get: function () { return constants_2.OrderType; } });
42
42
  Object.defineProperty(exports, "TimeInForce", { enumerable: true, get: function () { return constants_2.TimeInForce; } });
43
+ Object.defineProperty(exports, "WsSubscriptionType", { enumerable: true, get: function () { return constants_2.WsSubscriptionType; } });
@@ -23,17 +23,22 @@ export declare enum ExchangeType {
23
23
  APPROVE_AGENT = "approveAgent",
24
24
  APPROVE_BUILDER_FEE = "approveBuilderFee",
25
25
  SUB_ACCOUNT_TRANSFER = "subAccountTransfer",
26
- SET_REFERRER = "setReferrer"
26
+ SET_REFERRER = "setReferrer",
27
+ TWAP_ORDER = "twapOrder",
28
+ TWAP_CANCEL = "twapCancel"
27
29
  }
28
30
  export declare enum InfoType {
29
31
  ALL_MIDS = "allMids",
32
+ NOTIFICATION = "notification",
30
33
  USER_NON_FUNDING_LEDGER_UPDATES = "userNonFundingLedgerUpdates",
31
34
  USER_HISTORICAL_ORDERS = "historicalOrders",
32
35
  USER_OPEN_ORDERS = "openOrders",
33
36
  USER_FILLS = "userFills",
34
37
  USER_FILLS_BY_TIME = "userFillsByTime",
38
+ USER_TWAP_SLICE_FILLS = "userTwapSliceFills",
35
39
  ORDER_STATUS = "orderStatus",
36
40
  L2_BOOK = "l2Book",
41
+ TRADES = "trades",
37
42
  CANDLES_SNAPSHOT = "candleSnapshot",
38
43
  META_AND_ASSET_CTXS = "metaAndAssetCtxs",
39
44
  USER_FUNDING = "userFunding",
@@ -68,3 +73,21 @@ export declare const CHAIN_IDS: {
68
73
  readonly HYPERLIQUID_MAINNET: 1337;
69
74
  };
70
75
  export declare const SLIPPAGE = 0.08;
76
+ export declare enum WsSubscriptionType {
77
+ ALL_MIDS = "allMids",
78
+ L2_BOOK = "l2Book",
79
+ TRADES = "trades",
80
+ CANDLE = "candle",
81
+ ACTIVE_ASSET_CTX = "activeAssetCtx",
82
+ USER_FILLS = "userFills",
83
+ ORDER_UPDATES = "orderUpdates",
84
+ USER_FUNDINGS = "userFundings",
85
+ WEB_DATA2 = "webData2",
86
+ CLEARINGHOUSE_STATE = "clearinghouseState",
87
+ NOTIFICATION = "notification",
88
+ TWAP_STATES = "twapStates",
89
+ OPEN_ORDERS = "openOrders",
90
+ USER_NON_FUNDING_LEDGER_UPDATES = "userNonFundingLedgerUpdates",
91
+ USER_TWAP_SLICE_FILLS = "userTwapSliceFills",
92
+ USER_TWAP_HISTORY = "userTwapHistory"
93
+ }
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SLIPPAGE = exports.CHAIN_IDS = exports.TimeInForce = exports.OrderType = exports.InfoType = exports.ExchangeType = exports.ENDPOINTS = exports.WSS_URLS = exports.BASE_URLS = void 0;
3
+ exports.WsSubscriptionType = exports.SLIPPAGE = exports.CHAIN_IDS = exports.TimeInForce = exports.OrderType = exports.InfoType = exports.ExchangeType = exports.ENDPOINTS = exports.WSS_URLS = exports.BASE_URLS = void 0;
4
4
  // API endpoints
5
5
  exports.BASE_URLS = {
6
6
  PRODUCTION: 'https://api.hyperliquid.xyz',
@@ -30,18 +30,23 @@ var ExchangeType;
30
30
  ExchangeType["APPROVE_BUILDER_FEE"] = "approveBuilderFee";
31
31
  ExchangeType["SUB_ACCOUNT_TRANSFER"] = "subAccountTransfer";
32
32
  ExchangeType["SET_REFERRER"] = "setReferrer";
33
+ ExchangeType["TWAP_ORDER"] = "twapOrder";
34
+ ExchangeType["TWAP_CANCEL"] = "twapCancel";
33
35
  })(ExchangeType || (exports.ExchangeType = ExchangeType = {}));
34
36
  // Info types for API requests (perpetuals only)
35
37
  var InfoType;
36
38
  (function (InfoType) {
37
39
  InfoType["ALL_MIDS"] = "allMids";
40
+ InfoType["NOTIFICATION"] = "notification";
38
41
  InfoType["USER_NON_FUNDING_LEDGER_UPDATES"] = "userNonFundingLedgerUpdates";
39
42
  InfoType["USER_HISTORICAL_ORDERS"] = "historicalOrders";
40
43
  InfoType["USER_OPEN_ORDERS"] = "openOrders";
41
44
  InfoType["USER_FILLS"] = "userFills";
42
45
  InfoType["USER_FILLS_BY_TIME"] = "userFillsByTime";
46
+ InfoType["USER_TWAP_SLICE_FILLS"] = "userTwapSliceFills";
43
47
  InfoType["ORDER_STATUS"] = "orderStatus";
44
48
  InfoType["L2_BOOK"] = "l2Book";
49
+ InfoType["TRADES"] = "trades";
45
50
  InfoType["CANDLES_SNAPSHOT"] = "candleSnapshot";
46
51
  InfoType["META_AND_ASSET_CTXS"] = "metaAndAssetCtxs";
47
52
  InfoType["USER_FUNDING"] = "userFunding";
@@ -81,3 +86,23 @@ exports.CHAIN_IDS = {
81
86
  HYPERLIQUID_MAINNET: 1337,
82
87
  };
83
88
  exports.SLIPPAGE = 0.08;
89
+ // WebSocket subscription types
90
+ var WsSubscriptionType;
91
+ (function (WsSubscriptionType) {
92
+ WsSubscriptionType["ALL_MIDS"] = "allMids";
93
+ WsSubscriptionType["L2_BOOK"] = "l2Book";
94
+ WsSubscriptionType["TRADES"] = "trades";
95
+ WsSubscriptionType["CANDLE"] = "candle";
96
+ WsSubscriptionType["ACTIVE_ASSET_CTX"] = "activeAssetCtx";
97
+ WsSubscriptionType["USER_FILLS"] = "userFills";
98
+ WsSubscriptionType["ORDER_UPDATES"] = "orderUpdates";
99
+ WsSubscriptionType["USER_FUNDINGS"] = "userFundings";
100
+ WsSubscriptionType["WEB_DATA2"] = "webData2";
101
+ WsSubscriptionType["CLEARINGHOUSE_STATE"] = "clearinghouseState";
102
+ WsSubscriptionType["NOTIFICATION"] = "notification";
103
+ WsSubscriptionType["TWAP_STATES"] = "twapStates";
104
+ WsSubscriptionType["OPEN_ORDERS"] = "openOrders";
105
+ WsSubscriptionType["USER_NON_FUNDING_LEDGER_UPDATES"] = "userNonFundingLedgerUpdates";
106
+ WsSubscriptionType["USER_TWAP_SLICE_FILLS"] = "userTwapSliceFills";
107
+ WsSubscriptionType["USER_TWAP_HISTORY"] = "userTwapHistory";
108
+ })(WsSubscriptionType || (exports.WsSubscriptionType = WsSubscriptionType = {}));
@@ -154,6 +154,11 @@ export interface UserFill {
154
154
  export type UserFills = {
155
155
  [asset: string]: UserFill[];
156
156
  };
157
+ export type wsUserNonFundingLedgerUpdates = {
158
+ user: string;
159
+ isSnapshot: boolean;
160
+ nonFundingLedgerUpdates: UserNonFundingLedgerUpdates[];
161
+ };
157
162
  export type UserNonFundingLedgerUpdates = {
158
163
  time: number;
159
164
  hash: string;
@@ -281,6 +286,9 @@ export interface AssetCtx {
281
286
  export interface AllMids {
282
287
  [coin: string]: string;
283
288
  }
289
+ export interface WsAllMids {
290
+ mids: AllMids;
291
+ }
284
292
  export interface L2Book {
285
293
  coin: string;
286
294
  levels: [WsLevel[], WsLevel[]];
@@ -298,6 +306,15 @@ export interface WsActiveAssetCtx {
298
306
  oraclePx: string;
299
307
  };
300
308
  }
309
+ export interface WsTrade {
310
+ coin: string;
311
+ hash: string;
312
+ px: string;
313
+ sz: string;
314
+ side: Side;
315
+ tid: number;
316
+ time: number;
317
+ }
301
318
  export interface Candle {
302
319
  t: number;
303
320
  T: number;
@@ -467,3 +484,104 @@ export interface ReferralResponse {
467
484
  };
468
485
  rewardHistory: any[];
469
486
  }
487
+ export interface TwapOrderParams {
488
+ coin: string;
489
+ isBuy: boolean;
490
+ sz: string;
491
+ reduceOnly?: boolean;
492
+ durationMillis: number;
493
+ randomizeDelay?: boolean;
494
+ builder?: {
495
+ address: string;
496
+ fee: number;
497
+ };
498
+ }
499
+ export interface TwapCancelParams {
500
+ coin: string;
501
+ twapId: number;
502
+ }
503
+ export interface TwapOrderResponse {
504
+ status: 'ok';
505
+ response: {
506
+ type: 'twapOrder';
507
+ data: {
508
+ twapId: number;
509
+ };
510
+ };
511
+ }
512
+ export interface TwapState {
513
+ twapId: number;
514
+ coin: string;
515
+ isBuy: boolean;
516
+ sz: string;
517
+ reduceOnly: boolean;
518
+ totalSz: string;
519
+ executedSz: string;
520
+ remainingSz: string;
521
+ startTime: number;
522
+ endTime: number;
523
+ status: 'active' | 'completed' | 'cancelled';
524
+ }
525
+ export interface WsTwapStates {
526
+ dex: string;
527
+ user: string;
528
+ states?: TwapState[];
529
+ }
530
+ export interface WsOpenOrders {
531
+ user: string;
532
+ orders?: OpenOrder[];
533
+ }
534
+ export interface WsUserTwapSliceFills {
535
+ user: string;
536
+ fills?: UserTwapSliceFill[];
537
+ }
538
+ export interface WsUserTwapHistory {
539
+ user: string;
540
+ history?: UserTwapHistory[];
541
+ }
542
+ export interface UserTwapSliceFill {
543
+ coin: string;
544
+ px: string;
545
+ sz: string;
546
+ side: Side;
547
+ time: number;
548
+ hash: string;
549
+ oid: number;
550
+ crossed: boolean;
551
+ fee: string;
552
+ tid: number;
553
+ twapId: number;
554
+ }
555
+ export interface UserTwapHistory {
556
+ twapId: number;
557
+ user: string;
558
+ coin: string;
559
+ side: Side;
560
+ sz: string;
561
+ totalFilled: string;
562
+ avgFillPx: string;
563
+ startTime: number;
564
+ endTime: number;
565
+ status: string;
566
+ }
567
+ export interface L2BookSnapshot {
568
+ coin: string;
569
+ levels: [WsLevel[], WsLevel[]];
570
+ time: number;
571
+ }
572
+ export interface FundingHistoryItem {
573
+ coin: string;
574
+ fundingRate: string;
575
+ premium: string;
576
+ time: number;
577
+ }
578
+ export interface UserFunding {
579
+ time: number;
580
+ coin: string;
581
+ usdc: string;
582
+ szi: string;
583
+ fundingRate: string;
584
+ }
585
+ export interface Notification {
586
+ notification: string;
587
+ }
@@ -1,2 +1,3 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ ;
package/package.json CHANGED
@@ -1,37 +1,38 @@
1
- {
2
- "name": "@rabby-wallet/hyperliquid-sdk",
3
- "version": "1.1.1",
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.2-beta.1",
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
+
12
+ "access": "public"
13
+ },
14
+ "scripts": {
15
+ "build": "rimraf dist && tsc",
16
+ "preversion": "npm run build",
17
+ "prepublishOnly": "npm run build"
18
+ },
19
+ "author": "",
20
+ "license": "UNLICENSED",
21
+ "dependencies": {
22
+ "@ethereumjs/util": "9.0.0",
23
+ "@metamask/eth-sig-util": "5.1.0",
24
+ "@msgpack/msgpack": "3.1.2",
25
+ "@noble/hashes": "1.8.0",
26
+ "ethereum-cryptography": "2.2.1"
27
+ },
28
+ "devDependencies": {
29
+ "@types/node": "24.3.1",
30
+ "prettier": "2.7.1",
31
+ "rimraf": "6.0.0",
32
+ "typescript": "5.9.2"
33
+ },
34
+ "engines": {
35
+ "node": ">=16.0.0"
36
+ },
37
+ "packageManager": "yarn@1.22.22"
38
+ }