@rabby-wallet/hyperliquid-sdk 1.1.8 → 1.1.9-beta.0
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 +139 -139
- package/dist/client/exchange-client.d.ts +12 -1
- package/dist/client/exchange-client.js +43 -15
- package/dist/hyperliquid-sdk.d.ts +7 -1
- package/dist/hyperliquid-sdk.js +11 -0
- package/dist/types/index.d.ts +13 -0
- package/dist/utils/signer.d.ts +1 -1
- package/dist/utils/signer.js +3 -3
- package/package.json +37 -37
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, SendAssetParams, ApproveBuilderFeeParams, PrepareApproveBuilderFeeResult, SendApproveParams, MarketOrderParams, UpdateLeverageParams, BindTpslByOrderIdParams, UpdateIsolatedMarginParams, TwapOrderParams, TwapCancelParams, TwapOrderResponse, PlaceTPSlMarketOrderParams, PlaceTPSlLimitOrderParams, ClearinghouseState, UpdateTpslByOrderIdParams, LimitOrderParams, Abstraction, UserSetAbstractionParams, Tif } from '../types';
|
|
2
|
+
import type { OrderResponse, CancelResponse, ExchangeClientConfig, PlaceOrderParams, MultiOrderParams, CancelOrderParams, ModifyOrderParams, WithdrawParams, SendAssetParams, ApproveBuilderFeeParams, PrepareApproveBuilderFeeResult, SendApproveParams, MarketOrderParams, UpdateLeverageParams, BindTpslByOrderIdParams, UpdateIsolatedMarginParams, TwapOrderParams, TwapCancelParams, TwapOrderResponse, PlaceTPSlMarketOrderParams, PlaceTPSlLimitOrderParams, ClearinghouseState, UpdateTpslByOrderIdParams, LimitOrderParams, Abstraction, UserSetAbstractionParams, Tif, ExternalSign } from '../types';
|
|
3
3
|
/**
|
|
4
4
|
* Client for executing trades on Hyperliquid (perpetuals only)
|
|
5
5
|
* Only includes essential trading APIs as specified
|
|
@@ -9,6 +9,7 @@ export declare class ExchangeClient {
|
|
|
9
9
|
private agentPrivateKey?;
|
|
10
10
|
private agentPublicKey?;
|
|
11
11
|
private agentName?;
|
|
12
|
+
private externalSign?;
|
|
12
13
|
private readonly isTestnet;
|
|
13
14
|
slippage: number;
|
|
14
15
|
private masterAddress;
|
|
@@ -24,6 +25,11 @@ export declare class ExchangeClient {
|
|
|
24
25
|
*/
|
|
25
26
|
setSlippage(slippage?: number): void;
|
|
26
27
|
initOrUpdateAgent(agentPrivateKey: string, agentPublicKey: string, agentName?: string): void;
|
|
28
|
+
/**
|
|
29
|
+
* Install (or clear with undefined) an external async signer. When present,
|
|
30
|
+
* L1 actions are signed through it instead of the built-in agent key.
|
|
31
|
+
*/
|
|
32
|
+
setExternalSign(externalSign?: ExternalSign): void;
|
|
27
33
|
/**
|
|
28
34
|
* Check if agent is set
|
|
29
35
|
*/
|
|
@@ -33,6 +39,11 @@ export declare class ExchangeClient {
|
|
|
33
39
|
*/
|
|
34
40
|
get address(): string;
|
|
35
41
|
private getAgentPrivateKey;
|
|
42
|
+
/**
|
|
43
|
+
* Sign an L1 agent action. Prefers the external signer (async, master-wallet
|
|
44
|
+
* keyring) when set; otherwise falls back to the built-in agent private key.
|
|
45
|
+
*/
|
|
46
|
+
private signL1Action;
|
|
36
47
|
/**
|
|
37
48
|
* @deprecated This method is deprecated. Use the new builder configuration in constructor instead.
|
|
38
49
|
*/
|
|
@@ -79,6 +79,9 @@ class ExchangeClient {
|
|
|
79
79
|
if (config.agentName) {
|
|
80
80
|
this.agentName = config.agentName;
|
|
81
81
|
}
|
|
82
|
+
if (config.externalSign) {
|
|
83
|
+
this.externalSign = config.externalSign;
|
|
84
|
+
}
|
|
82
85
|
this.isTestnet = config.isTestnet || false;
|
|
83
86
|
}
|
|
84
87
|
initAccount(masterAddress, agentPrivateKey, agentPublicKey, agentName) {
|
|
@@ -114,11 +117,18 @@ class ExchangeClient {
|
|
|
114
117
|
this.agentPublicKey = agentPublicKey.startsWith('0x') ? agentPublicKey : ethUtil.addHexPrefix(agentPublicKey);
|
|
115
118
|
this.agentName = agentName || '';
|
|
116
119
|
}
|
|
120
|
+
/**
|
|
121
|
+
* Install (or clear with undefined) an external async signer. When present,
|
|
122
|
+
* L1 actions are signed through it instead of the built-in agent key.
|
|
123
|
+
*/
|
|
124
|
+
setExternalSign(externalSign) {
|
|
125
|
+
this.externalSign = externalSign;
|
|
126
|
+
}
|
|
117
127
|
/**
|
|
118
128
|
* Check if agent is set
|
|
119
129
|
*/
|
|
120
130
|
get isHaveAgent() {
|
|
121
|
-
return !!this.agentPrivateKey && !!this.agentPublicKey;
|
|
131
|
+
return (!!this.agentPrivateKey && !!this.agentPublicKey) || !!this.externalSign;
|
|
122
132
|
}
|
|
123
133
|
/**
|
|
124
134
|
* Get the wallet address
|
|
@@ -132,6 +142,24 @@ class ExchangeClient {
|
|
|
132
142
|
}
|
|
133
143
|
return this.agentPrivateKey;
|
|
134
144
|
}
|
|
145
|
+
/**
|
|
146
|
+
* Sign an L1 agent action. Prefers the external signer (async, master-wallet
|
|
147
|
+
* keyring) when set; otherwise falls back to the built-in agent private key.
|
|
148
|
+
*/
|
|
149
|
+
signL1Action(action, nonce) {
|
|
150
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
151
|
+
if (this.externalSign) {
|
|
152
|
+
const typedData = (0, signer_1.prepareL1ActionTypedData)({
|
|
153
|
+
action: action,
|
|
154
|
+
isTestnet: this.isTestnet,
|
|
155
|
+
nonce,
|
|
156
|
+
});
|
|
157
|
+
const hexSig = yield this.externalSign(typedData);
|
|
158
|
+
return (0, signer_1.splitSig)(hexSig);
|
|
159
|
+
}
|
|
160
|
+
return (0, signer_1.signL1AgentAction)(this.getAgentPrivateKey(), action, this.isTestnet, nonce);
|
|
161
|
+
});
|
|
162
|
+
}
|
|
135
163
|
/**
|
|
136
164
|
* @deprecated This method is deprecated. Use the new builder configuration in constructor instead.
|
|
137
165
|
*/
|
|
@@ -155,7 +183,7 @@ class ExchangeClient {
|
|
|
155
183
|
isCross: params.isCross || false,
|
|
156
184
|
leverage: params.leverage,
|
|
157
185
|
};
|
|
158
|
-
const signature =
|
|
186
|
+
const signature = yield this.signL1Action(action, nonce);
|
|
159
187
|
return this.httpClient.exchange({
|
|
160
188
|
action,
|
|
161
189
|
nonce,
|
|
@@ -188,7 +216,7 @@ class ExchangeClient {
|
|
|
188
216
|
f: params.builder.fee,
|
|
189
217
|
};
|
|
190
218
|
}
|
|
191
|
-
const signature =
|
|
219
|
+
const signature = yield this.signL1Action(action, nonce);
|
|
192
220
|
return this.httpClient.exchange({
|
|
193
221
|
action,
|
|
194
222
|
nonce,
|
|
@@ -521,7 +549,7 @@ class ExchangeClient {
|
|
|
521
549
|
f: params.builder.fee,
|
|
522
550
|
};
|
|
523
551
|
}
|
|
524
|
-
const signature =
|
|
552
|
+
const signature = yield this.signL1Action(action, nonce);
|
|
525
553
|
const res = yield this.httpClient.exchange({
|
|
526
554
|
action,
|
|
527
555
|
nonce,
|
|
@@ -647,7 +675,7 @@ class ExchangeClient {
|
|
|
647
675
|
type: constants_1.ExchangeType.CANCEL,
|
|
648
676
|
cancels: cancels,
|
|
649
677
|
};
|
|
650
|
-
const signature =
|
|
678
|
+
const signature = yield this.signL1Action(action, nonce);
|
|
651
679
|
return this.httpClient.exchange({
|
|
652
680
|
action,
|
|
653
681
|
nonce,
|
|
@@ -673,7 +701,7 @@ class ExchangeClient {
|
|
|
673
701
|
t: params.orderType || { limit: { tif: 'Gtc' } },
|
|
674
702
|
},
|
|
675
703
|
};
|
|
676
|
-
const signature =
|
|
704
|
+
const signature = yield this.signL1Action(action, nonce);
|
|
677
705
|
return this.httpClient.exchange({
|
|
678
706
|
action,
|
|
679
707
|
nonce,
|
|
@@ -707,7 +735,7 @@ class ExchangeClient {
|
|
|
707
735
|
type: constants_1.ExchangeType.BATCH_MODIFY,
|
|
708
736
|
modifies,
|
|
709
737
|
};
|
|
710
|
-
const signature =
|
|
738
|
+
const signature = yield this.signL1Action(action, nonce);
|
|
711
739
|
return this.httpClient.exchange({
|
|
712
740
|
action,
|
|
713
741
|
nonce,
|
|
@@ -725,7 +753,7 @@ class ExchangeClient {
|
|
|
725
753
|
isBuy: true,
|
|
726
754
|
ntli: (0, number_1.floatToInt)(params.value, 6), // 6 decimals
|
|
727
755
|
};
|
|
728
|
-
const signature =
|
|
756
|
+
const signature = yield this.signL1Action(action, nonce);
|
|
729
757
|
return this.httpClient.exchange({
|
|
730
758
|
action,
|
|
731
759
|
nonce,
|
|
@@ -740,7 +768,7 @@ class ExchangeClient {
|
|
|
740
768
|
type: constants_1.ExchangeType.SET_REFERRER,
|
|
741
769
|
code,
|
|
742
770
|
};
|
|
743
|
-
const typedData = (0, signer_1.
|
|
771
|
+
const typedData = (0, signer_1.prepareL1ActionTypedData)({ action, isTestnet: this.isTestnet, nonce });
|
|
744
772
|
return { typedData, action, nonce };
|
|
745
773
|
}
|
|
746
774
|
catch (error) {
|
|
@@ -766,7 +794,7 @@ class ExchangeClient {
|
|
|
766
794
|
type: constants_1.ExchangeType.SET_REFERRER,
|
|
767
795
|
code,
|
|
768
796
|
};
|
|
769
|
-
const signature =
|
|
797
|
+
const signature = yield this.signL1Action(action, nonce);
|
|
770
798
|
return this.httpClient.exchange({
|
|
771
799
|
action,
|
|
772
800
|
nonce,
|
|
@@ -785,7 +813,7 @@ class ExchangeClient {
|
|
|
785
813
|
const action = {
|
|
786
814
|
type: constants_1.ExchangeType.AGENT_ENABLE_DEX_ABSTRACTION,
|
|
787
815
|
};
|
|
788
|
-
const signature =
|
|
816
|
+
const signature = yield this.signL1Action(action, nonce);
|
|
789
817
|
return this.httpClient.exchange({
|
|
790
818
|
action,
|
|
791
819
|
nonce,
|
|
@@ -851,7 +879,7 @@ class ExchangeClient {
|
|
|
851
879
|
type: constants_1.ExchangeType.AGENT_SET_ABSTRACTION,
|
|
852
880
|
abstraction: abstraction,
|
|
853
881
|
};
|
|
854
|
-
const signature =
|
|
882
|
+
const signature = yield this.signL1Action(action, nonce);
|
|
855
883
|
return this.httpClient.exchange({
|
|
856
884
|
action,
|
|
857
885
|
nonce,
|
|
@@ -1075,7 +1103,7 @@ class ExchangeClient {
|
|
|
1075
1103
|
f: params.builder.fee,
|
|
1076
1104
|
};
|
|
1077
1105
|
}
|
|
1078
|
-
const signature =
|
|
1106
|
+
const signature = yield this.signL1Action(action, nonce);
|
|
1079
1107
|
return this.httpClient.exchange({
|
|
1080
1108
|
action,
|
|
1081
1109
|
nonce,
|
|
@@ -1095,7 +1123,7 @@ class ExchangeClient {
|
|
|
1095
1123
|
a,
|
|
1096
1124
|
t: params.twapId,
|
|
1097
1125
|
};
|
|
1098
|
-
const signature =
|
|
1126
|
+
const signature = yield this.signL1Action(action, nonce);
|
|
1099
1127
|
return this.httpClient.exchange({
|
|
1100
1128
|
action,
|
|
1101
1129
|
nonce,
|
|
@@ -1138,7 +1166,7 @@ class ExchangeClient {
|
|
|
1138
1166
|
orders: [orderRequest],
|
|
1139
1167
|
grouping: 'na',
|
|
1140
1168
|
};
|
|
1141
|
-
const signature =
|
|
1169
|
+
const signature = yield this.signL1Action(action, nonce);
|
|
1142
1170
|
return this.httpClient.exchange({
|
|
1143
1171
|
action,
|
|
1144
1172
|
nonce,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { InfoClient } from './client/info-client';
|
|
2
2
|
import { ExchangeClient } from './client/exchange-client';
|
|
3
|
-
import type { ClearinghouseState } from './types';
|
|
3
|
+
import type { ClearinghouseState, ExternalSign } from './types';
|
|
4
4
|
import { WebSocketClient, WebSocketClientConfig } from './client/websocket-client';
|
|
5
5
|
import { SymbolConversion } from './client/symbolConversion';
|
|
6
6
|
export interface HyperliquidSDKConfig {
|
|
@@ -11,6 +11,7 @@ export interface HyperliquidSDKConfig {
|
|
|
11
11
|
isTestnet?: boolean;
|
|
12
12
|
timeout?: number;
|
|
13
13
|
wsConfig?: WebSocketClientConfig;
|
|
14
|
+
externalSign?: ExternalSign;
|
|
14
15
|
}
|
|
15
16
|
/**
|
|
16
17
|
* Main Hyperliquid SDK class for perpetuals trading
|
|
@@ -35,6 +36,11 @@ export declare class HyperliquidSDK {
|
|
|
35
36
|
*/
|
|
36
37
|
get isHaveAgent(): boolean;
|
|
37
38
|
initOrUpdateAgent(agentPrivateKey: string, agentPublicKey: string, agentName?: string): void;
|
|
39
|
+
/**
|
|
40
|
+
* Install (or clear with undefined) the external async signer on the exchange
|
|
41
|
+
* client. Call after initAccount when using master-wallet self-signing.
|
|
42
|
+
*/
|
|
43
|
+
setExternalSign(externalSign?: ExternalSign): void;
|
|
38
44
|
/**
|
|
39
45
|
* Connect to WebSocket for real-time data
|
|
40
46
|
*/
|
package/dist/hyperliquid-sdk.js
CHANGED
|
@@ -39,6 +39,7 @@ class HyperliquidSDK {
|
|
|
39
39
|
agentPrivateKey: config.agentPrivateKey,
|
|
40
40
|
agentPublicKey: config.agentPublicKey,
|
|
41
41
|
agentName: config.agentName,
|
|
42
|
+
externalSign: config.externalSign,
|
|
42
43
|
isTestnet: config.isTestnet,
|
|
43
44
|
timeout: config.timeout,
|
|
44
45
|
symbolConversion: this.symbolConversion,
|
|
@@ -66,6 +67,7 @@ class HyperliquidSDK {
|
|
|
66
67
|
agentPrivateKey,
|
|
67
68
|
agentPublicKey,
|
|
68
69
|
agentName,
|
|
70
|
+
externalSign: this.configParams.externalSign,
|
|
69
71
|
isTestnet: this.configParams.isTestnet,
|
|
70
72
|
timeout: this.configParams.timeout,
|
|
71
73
|
});
|
|
@@ -86,6 +88,15 @@ class HyperliquidSDK {
|
|
|
86
88
|
this.exchange.initOrUpdateAgent(agentPrivateKey, agentPublicKey, agentName);
|
|
87
89
|
}
|
|
88
90
|
}
|
|
91
|
+
/**
|
|
92
|
+
* Install (or clear with undefined) the external async signer on the exchange
|
|
93
|
+
* client. Call after initAccount when using master-wallet self-signing.
|
|
94
|
+
*/
|
|
95
|
+
setExternalSign(externalSign) {
|
|
96
|
+
if (this.exchange) {
|
|
97
|
+
this.exchange.setExternalSign(externalSign);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
89
100
|
/**
|
|
90
101
|
* Connect to WebSocket for real-time data
|
|
91
102
|
*/
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,4 +1,16 @@
|
|
|
1
1
|
import { SymbolConversion } from '../client/symbolConversion';
|
|
2
|
+
import type { TypedMessage, MessageTypes } from '@metamask/eth-sig-util';
|
|
3
|
+
/**
|
|
4
|
+
* EIP-712 typed data handed to an external signer (shape of
|
|
5
|
+
* prepareL1ActionTypedData's return value).
|
|
6
|
+
*/
|
|
7
|
+
export type ExternalSignTypedData = TypedMessage<MessageTypes>;
|
|
8
|
+
/**
|
|
9
|
+
* External async signer for L1 actions. Receives EIP-712 typed data and returns
|
|
10
|
+
* a 0x-prefixed 65-byte hex signature. When set, the SDK uses it instead of the
|
|
11
|
+
* built-in agent private key, so the master wallet can sign orders itself.
|
|
12
|
+
*/
|
|
13
|
+
export type ExternalSign = (typedData: ExternalSignTypedData) => Promise<string>;
|
|
2
14
|
export type Tif = 'Alo' | 'Ioc' | 'Gtc';
|
|
3
15
|
export type TriggerType = 'tp' | 'sl';
|
|
4
16
|
export type Side = 'A' | 'B';
|
|
@@ -526,6 +538,7 @@ export interface ExchangeClientConfig {
|
|
|
526
538
|
isTestnet?: boolean;
|
|
527
539
|
timeout?: number;
|
|
528
540
|
symbolConversion?: SymbolConversion;
|
|
541
|
+
externalSign?: ExternalSign;
|
|
529
542
|
}
|
|
530
543
|
export interface PlaceOrderParams {
|
|
531
544
|
coin: string;
|
package/dist/utils/signer.d.ts
CHANGED
|
@@ -23,7 +23,7 @@ export declare const signTypedDataV4: ({ privateKey, domain, primaryType, payloa
|
|
|
23
23
|
message: Record<string, unknown>;
|
|
24
24
|
}) => Signature;
|
|
25
25
|
export declare const signL1AgentAction: (privateKey: string, action: unknown, isTestnet: boolean, nonce: number) => Signature;
|
|
26
|
-
export declare const
|
|
26
|
+
export declare const prepareL1ActionTypedData: ({ action, isTestnet, nonce, }: {
|
|
27
27
|
action: Record<string, unknown>;
|
|
28
28
|
isTestnet: boolean;
|
|
29
29
|
nonce: number;
|
package/dist/utils/signer.js
CHANGED
|
@@ -33,7 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.prepareMasterSignData = exports.
|
|
36
|
+
exports.prepareMasterSignData = exports.prepareL1ActionTypedData = exports.signL1AgentAction = exports.signTypedDataV4 = exports.splitSig = exports.EIP712_DOMAIN_TYPES = void 0;
|
|
37
37
|
const ethUtil = __importStar(require("@ethereumjs/util"));
|
|
38
38
|
const sigUtil = __importStar(require("@metamask/eth-sig-util"));
|
|
39
39
|
const keccak_1 = require("ethereum-cryptography/keccak");
|
|
@@ -109,7 +109,7 @@ const signL1AgentAction = (privateKey, action, isTestnet, nonce) => {
|
|
|
109
109
|
return (0, exports.signTypedDataV4)({ privateKey, domain, primaryType: 'Agent', payloadTypes, message });
|
|
110
110
|
};
|
|
111
111
|
exports.signL1AgentAction = signL1AgentAction;
|
|
112
|
-
const
|
|
112
|
+
const prepareL1ActionTypedData = ({ action, isTestnet, nonce, }) => {
|
|
113
113
|
const domain = {
|
|
114
114
|
name: 'Exchange',
|
|
115
115
|
version: '1',
|
|
@@ -136,7 +136,7 @@ const prepareSetReferrerTypedData = ({ action, isTestnet, nonce, }) => {
|
|
|
136
136
|
};
|
|
137
137
|
return typedData;
|
|
138
138
|
};
|
|
139
|
-
exports.
|
|
139
|
+
exports.prepareL1ActionTypedData = prepareL1ActionTypedData;
|
|
140
140
|
/**
|
|
141
141
|
* Prepare some action sign must by master wallet so we need to prepare the typed data
|
|
142
142
|
* Returns typed data that needs to be signed by the main wallet
|
package/package.json
CHANGED
|
@@ -1,37 +1,37 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@rabby-wallet/hyperliquid-sdk",
|
|
3
|
-
"version": "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.9-beta.0",
|
|
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
|
+
}
|