@rabby-wallet/hyperliquid-sdk 1.0.0-beta.2 → 1.0.0-beta.20
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 +4 -2
- package/dist/client/exchange-client.d.ts +3 -2
- package/dist/client/exchange-client.js +35 -30
- package/dist/client/http-client.js +1 -1
- package/dist/client/info-client.d.ts +16 -8
- package/dist/client/info-client.js +99 -18
- package/dist/client/symbolConversion.d.ts +3 -1
- package/dist/client/symbolConversion.js +11 -4
- package/dist/client/websocket-client.d.ts +8 -4
- package/dist/client/websocket-client.js +48 -23
- package/dist/hyperliquid-sdk.d.ts +3 -7
- package/dist/hyperliquid-sdk.js +23 -24
- package/dist/types/constants.d.ts +3 -2
- package/dist/types/constants.js +3 -2
- package/dist/types/index.d.ts +70 -0
- package/dist/utils/number.d.ts +12 -0
- package/dist/utils/number.js +22 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -32,8 +32,10 @@ const sdk = new HyperliquidSDK({
|
|
|
32
32
|
// 获取所有中间价
|
|
33
33
|
const prices = await sdk.info.getAllMids();
|
|
34
34
|
|
|
35
|
-
// 获取市场元数据与资产上下文
|
|
36
|
-
const
|
|
35
|
+
// 获取市场元数据与资产上下文
|
|
36
|
+
const canUseCache = true; //默认使用缓存,多次请求并发去重 ,需要刷新传false
|
|
37
|
+
const [meta, assetCtxs] = await sdk.info.metaAndAssetCtxs(canUseCache);
|
|
38
|
+
|
|
37
39
|
|
|
38
40
|
// 获取账户综合状态
|
|
39
41
|
const account = await sdk.info.getClearingHouseState();
|
|
@@ -9,10 +9,11 @@ export declare class ExchangeClient {
|
|
|
9
9
|
private agentPublicKey?;
|
|
10
10
|
private agentName?;
|
|
11
11
|
private readonly isTestnet;
|
|
12
|
-
private
|
|
12
|
+
private masterAddress;
|
|
13
13
|
private builder?;
|
|
14
14
|
private readonly symbolConversion;
|
|
15
15
|
constructor(config: ExchangeClientConfig);
|
|
16
|
+
initAccount(masterAddress: string, agentPrivateKey: string, agentPublicKey: string, agentName?: string): void;
|
|
16
17
|
/**
|
|
17
18
|
* Get the wallet address
|
|
18
19
|
*/
|
|
@@ -32,7 +33,7 @@ export declare class ExchangeClient {
|
|
|
32
33
|
* need to update leverage before place order
|
|
33
34
|
*/
|
|
34
35
|
marketOrderOpen(params: MarketOrderParams): Promise<OrderResponse>;
|
|
35
|
-
marketOrderClose(params: MarketOrderParams): Promise<OrderResponse>;
|
|
36
|
+
marketOrderClose(params: Omit<MarketOrderParams, 'tpTriggerPx' | 'slTriggerPx'>): Promise<OrderResponse>;
|
|
36
37
|
/**
|
|
37
38
|
* Place multiple orders at once
|
|
38
39
|
*/
|
|
@@ -48,6 +48,7 @@ const http_client_1 = require("./http-client");
|
|
|
48
48
|
const constants_1 = require("../types/constants");
|
|
49
49
|
const signer_1 = require("../utils/signer");
|
|
50
50
|
const symbolConversion_1 = require("./symbolConversion");
|
|
51
|
+
const number_1 = require("../utils/number");
|
|
51
52
|
/**
|
|
52
53
|
* Client for executing trades on Hyperliquid (perpetuals only)
|
|
53
54
|
* Only includes essential trading APIs as specified
|
|
@@ -79,6 +80,12 @@ class ExchangeClient {
|
|
|
79
80
|
}
|
|
80
81
|
this.isTestnet = config.isTestnet || false;
|
|
81
82
|
}
|
|
83
|
+
initAccount(masterAddress, agentPrivateKey, agentPublicKey, agentName) {
|
|
84
|
+
this.masterAddress = masterAddress;
|
|
85
|
+
this.agentPrivateKey = agentPrivateKey.startsWith('0x') ? agentPrivateKey : ethUtil.addHexPrefix(agentPrivateKey);
|
|
86
|
+
this.agentPublicKey = agentPublicKey.startsWith('0x') ? agentPublicKey : ethUtil.addHexPrefix(agentPublicKey);
|
|
87
|
+
this.agentName = agentName || '';
|
|
88
|
+
}
|
|
82
89
|
/**
|
|
83
90
|
* Get the wallet address
|
|
84
91
|
*/
|
|
@@ -163,7 +170,7 @@ class ExchangeClient {
|
|
|
163
170
|
const decimals = ((_a = midPx.toString().split('.')[1]) === null || _a === void 0 ? void 0 : _a.length) || 0;
|
|
164
171
|
const prepDecimals = Math.max(0, decimals - 1);
|
|
165
172
|
const px = isBuy ? (Number(midPx) * (1 + slippage)).toFixed(prepDecimals) : (Number(midPx) * (1 - slippage)).toFixed(prepDecimals);
|
|
166
|
-
return px;
|
|
173
|
+
return (0, number_1.removeTrailingZeros)(px);
|
|
167
174
|
}
|
|
168
175
|
/**
|
|
169
176
|
* Place a market order
|
|
@@ -174,11 +181,11 @@ class ExchangeClient {
|
|
|
174
181
|
return __awaiter(this, void 0, void 0, function* () {
|
|
175
182
|
try {
|
|
176
183
|
const slippage = params.slippage || constants_1.SLIPPAGE;
|
|
177
|
-
const px = this.getSlippagePx(params.midPx, slippage, params.isBuy);
|
|
184
|
+
const px = this.getSlippagePx((0, number_1.removeTrailingZeros)(params.midPx), slippage, params.isBuy);
|
|
178
185
|
const orders = [{
|
|
179
186
|
coin: params.coin,
|
|
180
187
|
isBuy: params.isBuy,
|
|
181
|
-
sz: params.size,
|
|
188
|
+
sz: (0, number_1.removeTrailingZeros)(params.size),
|
|
182
189
|
limitPx: px,
|
|
183
190
|
reduceOnly: false,
|
|
184
191
|
orderType: { limit: { tif: 'Ioc' } },
|
|
@@ -187,13 +194,13 @@ class ExchangeClient {
|
|
|
187
194
|
const tpOrder = {
|
|
188
195
|
coin: params.coin,
|
|
189
196
|
isBuy: !params.isBuy,
|
|
190
|
-
sz: params.size,
|
|
191
|
-
limitPx: params.tpTriggerPx,
|
|
197
|
+
sz: (0, number_1.removeTrailingZeros)(params.size),
|
|
198
|
+
limitPx: (0, number_1.removeTrailingZeros)(params.tpTriggerPx),
|
|
192
199
|
reduceOnly: true,
|
|
193
200
|
orderType: {
|
|
194
201
|
trigger: {
|
|
195
202
|
isMarket: true,
|
|
196
|
-
triggerPx: params.tpTriggerPx,
|
|
203
|
+
triggerPx: (0, number_1.removeTrailingZeros)(params.tpTriggerPx),
|
|
197
204
|
tpsl: 'tp',
|
|
198
205
|
}
|
|
199
206
|
}
|
|
@@ -204,13 +211,13 @@ class ExchangeClient {
|
|
|
204
211
|
const slOrder = {
|
|
205
212
|
coin: params.coin,
|
|
206
213
|
isBuy: !params.isBuy,
|
|
207
|
-
sz: params.size,
|
|
208
|
-
limitPx: params.slTriggerPx,
|
|
214
|
+
sz: (0, number_1.removeTrailingZeros)(params.size),
|
|
215
|
+
limitPx: (0, number_1.removeTrailingZeros)(params.slTriggerPx),
|
|
209
216
|
reduceOnly: true,
|
|
210
217
|
orderType: {
|
|
211
218
|
trigger: {
|
|
212
219
|
isMarket: true,
|
|
213
|
-
triggerPx: params.slTriggerPx,
|
|
220
|
+
triggerPx: (0, number_1.removeTrailingZeros)(params.slTriggerPx),
|
|
214
221
|
tpsl: 'sl',
|
|
215
222
|
}
|
|
216
223
|
}
|
|
@@ -235,7 +242,7 @@ class ExchangeClient {
|
|
|
235
242
|
const orders = [{
|
|
236
243
|
coin: params.coin,
|
|
237
244
|
isBuy: params.isBuy,
|
|
238
|
-
sz: params.size,
|
|
245
|
+
sz: (0, number_1.removeTrailingZeros)(params.size),
|
|
239
246
|
limitPx: px,
|
|
240
247
|
reduceOnly: true,
|
|
241
248
|
orderType: { limit: { tif: 'Ioc' } },
|
|
@@ -266,8 +273,8 @@ class ExchangeClient {
|
|
|
266
273
|
return {
|
|
267
274
|
a: assetIndex,
|
|
268
275
|
b: order.isBuy,
|
|
269
|
-
p: order.limitPx,
|
|
270
|
-
s: order.sz,
|
|
276
|
+
p: (0, number_1.removeTrailingZeros)(order.limitPx),
|
|
277
|
+
s: (0, number_1.removeTrailingZeros)(order.sz),
|
|
271
278
|
r: order.reduceOnly || false,
|
|
272
279
|
t: order.orderType || { limit: { tif: 'Gtc' } },
|
|
273
280
|
};
|
|
@@ -299,12 +306,12 @@ class ExchangeClient {
|
|
|
299
306
|
coin: params.coin,
|
|
300
307
|
isBuy: !params.isBuy,
|
|
301
308
|
sz: '0',
|
|
302
|
-
limitPx: this.getSlippagePx(params.tpTriggerPx, constants_1.SLIPPAGE, !params.isBuy),
|
|
309
|
+
limitPx: this.getSlippagePx((0, number_1.removeTrailingZeros)(params.tpTriggerPx), constants_1.SLIPPAGE, !params.isBuy),
|
|
303
310
|
reduceOnly: true,
|
|
304
311
|
orderType: {
|
|
305
312
|
trigger: {
|
|
306
313
|
isMarket: true,
|
|
307
|
-
triggerPx: params.tpTriggerPx,
|
|
314
|
+
triggerPx: (0, number_1.removeTrailingZeros)(params.tpTriggerPx),
|
|
308
315
|
tpsl: 'tp',
|
|
309
316
|
}
|
|
310
317
|
}
|
|
@@ -315,12 +322,12 @@ class ExchangeClient {
|
|
|
315
322
|
coin: params.coin,
|
|
316
323
|
isBuy: !params.isBuy,
|
|
317
324
|
sz: '0',
|
|
318
|
-
limitPx: this.getSlippagePx(params.slTriggerPx, constants_1.SLIPPAGE, !params.isBuy),
|
|
325
|
+
limitPx: this.getSlippagePx((0, number_1.removeTrailingZeros)(params.slTriggerPx), constants_1.SLIPPAGE, !params.isBuy),
|
|
319
326
|
reduceOnly: true,
|
|
320
327
|
orderType: {
|
|
321
328
|
trigger: {
|
|
322
329
|
isMarket: true,
|
|
323
|
-
triggerPx: params.slTriggerPx,
|
|
330
|
+
triggerPx: (0, number_1.removeTrailingZeros)(params.slTriggerPx),
|
|
324
331
|
tpsl: 'sl',
|
|
325
332
|
}
|
|
326
333
|
}
|
|
@@ -371,8 +378,8 @@ class ExchangeClient {
|
|
|
371
378
|
order: {
|
|
372
379
|
a: yield this.symbolConversion.getAssetIndex(params.coin),
|
|
373
380
|
b: params.isBuy,
|
|
374
|
-
p: params.limitPx,
|
|
375
|
-
s: params.sz,
|
|
381
|
+
p: (0, number_1.removeTrailingZeros)(params.limitPx),
|
|
382
|
+
s: (0, number_1.removeTrailingZeros)(params.sz),
|
|
376
383
|
r: params.reduceOnly || false,
|
|
377
384
|
t: params.orderType || { limit: { tif: 'Gtc' } },
|
|
378
385
|
},
|
|
@@ -469,19 +476,17 @@ class ExchangeClient {
|
|
|
469
476
|
const action = {
|
|
470
477
|
type: constants_1.ExchangeType.APPROVE_BUILDER_FEE,
|
|
471
478
|
hyperliquidChain: this.isTestnet ? 'Testnet' : 'Mainnet',
|
|
472
|
-
signatureChainId: this.isTestnet ? '0x66eee' : '
|
|
479
|
+
signatureChainId: this.isTestnet ? '0x66eee' : '0xa4b1',
|
|
480
|
+
maxFeeRate: params.maxFee || '0.1%',
|
|
473
481
|
builder: params.builder.toLowerCase(),
|
|
474
|
-
maxFee: params.maxFee || '0.1%',
|
|
475
482
|
nonce,
|
|
476
483
|
};
|
|
477
484
|
const { domain, types, primaryType, message } = (0, signer_1.prepareMasterSignData)({
|
|
478
485
|
action,
|
|
479
486
|
payloadTypes: [
|
|
480
|
-
{ name: 'type', type: 'string' },
|
|
481
487
|
{ name: 'hyperliquidChain', type: 'string' },
|
|
482
|
-
{ name: '
|
|
483
|
-
{ name: 'builder', type: '
|
|
484
|
-
{ name: 'maxFee', type: 'string' },
|
|
488
|
+
{ name: 'maxFeeRate', type: 'string' },
|
|
489
|
+
{ name: 'builder', type: 'address' },
|
|
485
490
|
{ name: 'nonce', type: 'uint64' },
|
|
486
491
|
],
|
|
487
492
|
primaryType: 'HyperliquidTransaction:ApproveBuilderFee',
|
|
@@ -502,10 +507,11 @@ class ExchangeClient {
|
|
|
502
507
|
*/
|
|
503
508
|
sendApproveBuilderFee(params) {
|
|
504
509
|
return __awaiter(this, void 0, void 0, function* () {
|
|
510
|
+
const splitSignature = (0, signer_1.splitSig)(params.signature);
|
|
505
511
|
return this.httpClient.exchange({
|
|
506
512
|
action: params.action,
|
|
507
513
|
nonce: params.nonce,
|
|
508
|
-
signature:
|
|
514
|
+
signature: splitSignature,
|
|
509
515
|
});
|
|
510
516
|
});
|
|
511
517
|
}
|
|
@@ -517,17 +523,15 @@ class ExchangeClient {
|
|
|
517
523
|
const action = {
|
|
518
524
|
type: constants_1.ExchangeType.WITHDRAW,
|
|
519
525
|
hyperliquidChain: this.isTestnet ? 'Testnet' : 'Mainnet',
|
|
520
|
-
signatureChainId: this.isTestnet ? '0x66eee' : '
|
|
526
|
+
signatureChainId: this.isTestnet ? '0x66eee' : '0xa4b1',
|
|
521
527
|
destination: params.destination,
|
|
522
528
|
amount: params.amount,
|
|
523
|
-
time:
|
|
529
|
+
time: nonce,
|
|
524
530
|
};
|
|
525
531
|
const { domain, types, primaryType, message } = (0, signer_1.prepareMasterSignData)({
|
|
526
532
|
action,
|
|
527
533
|
payloadTypes: [
|
|
528
|
-
{ name: 'type', type: 'string' },
|
|
529
534
|
{ name: 'hyperliquidChain', type: 'string' },
|
|
530
|
-
{ name: 'signatureChainId', type: 'string' },
|
|
531
535
|
{ name: 'destination', type: 'string' },
|
|
532
536
|
{ name: 'amount', type: 'string' },
|
|
533
537
|
{ name: 'time', type: 'uint64' },
|
|
@@ -544,10 +548,11 @@ class ExchangeClient {
|
|
|
544
548
|
};
|
|
545
549
|
}
|
|
546
550
|
sendWithdraw(params) {
|
|
551
|
+
const splitSignature = (0, signer_1.splitSig)(params.signature);
|
|
547
552
|
return this.httpClient.exchange({
|
|
548
553
|
action: params.action,
|
|
549
554
|
nonce: params.nonce,
|
|
550
|
-
signature:
|
|
555
|
+
signature: splitSignature,
|
|
551
556
|
});
|
|
552
557
|
}
|
|
553
558
|
}
|
|
@@ -41,7 +41,7 @@ class HttpClient {
|
|
|
41
41
|
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
42
42
|
}
|
|
43
43
|
const result = yield response.json();
|
|
44
|
-
if (result.status === 'error') {
|
|
44
|
+
if (result.status === 'error' || result.status === 'fail' || result.status === 'err') {
|
|
45
45
|
throw new Error(JSON.stringify(result.response));
|
|
46
46
|
}
|
|
47
47
|
return result;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type { Meta, AssetCtx, ClearinghouseState, UserFills, CandleSnapshot, AllMids, ExtraAgent, OpenOrder, FeeResponse } from '../types';
|
|
1
|
+
import type { Meta, AssetCtx, ClearinghouseState, UserFills, CandleSnapshot, AllMids, ExtraAgent, OpenOrder, FeeResponse, UserNonFundingLedgerUpdates, UserHistoricalOrders } from '../types';
|
|
2
2
|
export interface InfoClientConfig {
|
|
3
3
|
isTestnet?: boolean;
|
|
4
4
|
timeout?: number;
|
|
5
|
-
masterAddress
|
|
5
|
+
masterAddress?: string;
|
|
6
6
|
}
|
|
7
7
|
/**
|
|
8
8
|
* Client for querying Hyperliquid info endpoints (perpetuals only)
|
|
@@ -10,31 +10,39 @@ export interface InfoClientConfig {
|
|
|
10
10
|
*/
|
|
11
11
|
export declare class InfoClient {
|
|
12
12
|
private readonly httpClient;
|
|
13
|
-
private
|
|
13
|
+
private masterAddress?;
|
|
14
|
+
private metaAndAssetCtxsCache;
|
|
15
|
+
private metaAndAssetCtxsInFlight;
|
|
14
16
|
constructor(config: InfoClientConfig);
|
|
15
17
|
/**
|
|
16
18
|
* Get all mid prices for all assets
|
|
17
19
|
*/
|
|
18
20
|
getAllMids(): Promise<AllMids>;
|
|
21
|
+
initMasterAddress(masterAddress: string): void;
|
|
19
22
|
/**
|
|
20
23
|
* Get metadata and asset contexts
|
|
21
24
|
*/
|
|
22
|
-
metaAndAssetCtxs(): Promise<[Meta, AssetCtx[]]>;
|
|
25
|
+
metaAndAssetCtxs(canUseCache?: boolean): Promise<[Meta, AssetCtx[]]>;
|
|
23
26
|
getClearingHouseState(address?: string): Promise<ClearinghouseState>;
|
|
24
27
|
getFrontendOpenOrders(address?: string): Promise<OpenOrder[]>;
|
|
28
|
+
getUserNonFundingLedgerUpdates(address?: string, startTime?: number, endTime?: number): Promise<UserNonFundingLedgerUpdates[]>;
|
|
25
29
|
/**
|
|
26
30
|
* Get user's fill history
|
|
27
31
|
*/
|
|
28
|
-
getUserFills(address?: string): Promise<UserFills>;
|
|
32
|
+
getUserFills(address?: string, aggregateByTime?: boolean): Promise<UserFills>;
|
|
33
|
+
/**
|
|
34
|
+
* Get user's fill and cancel and other all orders history
|
|
35
|
+
*/
|
|
36
|
+
getUserHistoricalOrders(address?: string, startTime?: number, endTime?: number): Promise<UserHistoricalOrders[]>;
|
|
29
37
|
/**
|
|
30
38
|
* Get candlestick data snapshot
|
|
31
39
|
* Supported intervals: "1m", "3m", "5m", "15m", "30m", "1h", "2h", "4h", "8h", "12h", "1d", "3d", "1w", "1M"
|
|
32
40
|
*/
|
|
33
|
-
candleSnapshot(coin: string, interval: string, startTime
|
|
41
|
+
candleSnapshot(coin: string, interval: string, startTime: number, endTime: number): Promise<CandleSnapshot>;
|
|
34
42
|
/**
|
|
35
|
-
* Check builder fee
|
|
43
|
+
* Check max builder fee
|
|
36
44
|
*/
|
|
37
|
-
|
|
45
|
+
getMaxBuilderFee(builder: string, address?: string): Promise<number>;
|
|
38
46
|
/**
|
|
39
47
|
* Get user role
|
|
40
48
|
*/
|
|
@@ -18,6 +18,8 @@ const constants_1 = require("../types/constants");
|
|
|
18
18
|
*/
|
|
19
19
|
class InfoClient {
|
|
20
20
|
constructor(config) {
|
|
21
|
+
this.metaAndAssetCtxsCache = null;
|
|
22
|
+
this.metaAndAssetCtxsInFlight = null;
|
|
21
23
|
this.masterAddress = config.masterAddress;
|
|
22
24
|
this.httpClient = new http_client_1.HttpClient({
|
|
23
25
|
isTestnet: config.isTestnet,
|
|
@@ -34,30 +36,58 @@ class InfoClient {
|
|
|
34
36
|
});
|
|
35
37
|
});
|
|
36
38
|
}
|
|
39
|
+
initMasterAddress(masterAddress) {
|
|
40
|
+
this.masterAddress = masterAddress;
|
|
41
|
+
}
|
|
37
42
|
/**
|
|
38
43
|
* Get metadata and asset contexts
|
|
39
44
|
*/
|
|
40
45
|
metaAndAssetCtxs() {
|
|
41
|
-
return __awaiter(this,
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
46
|
+
return __awaiter(this, arguments, void 0, function* (canUseCache = true) {
|
|
47
|
+
if (canUseCache && this.metaAndAssetCtxsCache) {
|
|
48
|
+
return this.metaAndAssetCtxsCache;
|
|
49
|
+
}
|
|
50
|
+
// De-duplicate concurrent requests
|
|
51
|
+
if (this.metaAndAssetCtxsInFlight) {
|
|
52
|
+
return this.metaAndAssetCtxsInFlight;
|
|
53
|
+
}
|
|
54
|
+
this.metaAndAssetCtxsInFlight = (() => __awaiter(this, void 0, void 0, function* () {
|
|
55
|
+
try {
|
|
56
|
+
const [meta, assetCtxs] = yield this.httpClient.info({
|
|
57
|
+
type: constants_1.InfoType.META_AND_ASSET_CTXS,
|
|
58
|
+
});
|
|
59
|
+
this.metaAndAssetCtxsCache = [meta, assetCtxs];
|
|
60
|
+
return [meta, assetCtxs];
|
|
61
|
+
}
|
|
62
|
+
finally {
|
|
63
|
+
this.metaAndAssetCtxsInFlight = null;
|
|
64
|
+
}
|
|
65
|
+
}))();
|
|
66
|
+
return this.metaAndAssetCtxsInFlight;
|
|
45
67
|
});
|
|
46
68
|
}
|
|
47
69
|
getClearingHouseState(address) {
|
|
48
70
|
return __awaiter(this, void 0, void 0, function* () {
|
|
71
|
+
const user = address || this.masterAddress;
|
|
72
|
+
if (!user) {
|
|
73
|
+
throw new Error('user address is empty');
|
|
74
|
+
}
|
|
49
75
|
return this.httpClient.info({
|
|
50
76
|
type: constants_1.InfoType.CLEARINGHOUSE_STATE,
|
|
51
|
-
user
|
|
77
|
+
user,
|
|
52
78
|
});
|
|
53
79
|
});
|
|
54
80
|
}
|
|
55
81
|
// frontendOpenOrders
|
|
56
82
|
getFrontendOpenOrders(address) {
|
|
57
83
|
return __awaiter(this, void 0, void 0, function* () {
|
|
84
|
+
const user = address || this.masterAddress;
|
|
85
|
+
if (!user) {
|
|
86
|
+
throw new Error('user address is empty');
|
|
87
|
+
}
|
|
58
88
|
return this.httpClient.info({
|
|
59
89
|
type: constants_1.InfoType.FRONTEND_OPEN_ORDERS,
|
|
60
|
-
user
|
|
90
|
+
user,
|
|
61
91
|
});
|
|
62
92
|
});
|
|
63
93
|
}
|
|
@@ -68,14 +98,50 @@ class InfoClient {
|
|
|
68
98
|
// user: this.masterAddress,
|
|
69
99
|
// });
|
|
70
100
|
// }
|
|
101
|
+
getUserNonFundingLedgerUpdates(address, startTime, endTime) {
|
|
102
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
103
|
+
const user = address || this.masterAddress;
|
|
104
|
+
if (!user) {
|
|
105
|
+
throw new Error('user address is empty');
|
|
106
|
+
}
|
|
107
|
+
return this.httpClient.info({
|
|
108
|
+
type: constants_1.InfoType.USER_NON_FUNDING_LEDGER_UPDATES,
|
|
109
|
+
user,
|
|
110
|
+
startTime: startTime || 0,
|
|
111
|
+
endTime,
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
}
|
|
71
115
|
/**
|
|
72
116
|
* Get user's fill history
|
|
73
117
|
*/
|
|
74
|
-
getUserFills(address) {
|
|
118
|
+
getUserFills(address, aggregateByTime) {
|
|
75
119
|
return __awaiter(this, void 0, void 0, function* () {
|
|
120
|
+
const user = address || this.masterAddress;
|
|
121
|
+
if (!user) {
|
|
122
|
+
throw new Error('user address is empty');
|
|
123
|
+
}
|
|
76
124
|
return this.httpClient.info({
|
|
77
125
|
type: constants_1.InfoType.USER_FILLS,
|
|
78
|
-
user
|
|
126
|
+
user,
|
|
127
|
+
aggregateByTime: aggregateByTime || true,
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Get user's fill and cancel and other all orders history
|
|
133
|
+
*/
|
|
134
|
+
getUserHistoricalOrders(address, startTime, endTime) {
|
|
135
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
136
|
+
const user = address || this.masterAddress;
|
|
137
|
+
if (!user) {
|
|
138
|
+
throw new Error('user address is empty');
|
|
139
|
+
}
|
|
140
|
+
return this.httpClient.info({
|
|
141
|
+
type: constants_1.InfoType.USER_HISTORICAL_ORDERS,
|
|
142
|
+
user,
|
|
143
|
+
startTime: startTime || 0,
|
|
144
|
+
endTime,
|
|
79
145
|
});
|
|
80
146
|
});
|
|
81
147
|
}
|
|
@@ -87,26 +153,29 @@ class InfoClient {
|
|
|
87
153
|
return __awaiter(this, void 0, void 0, function* () {
|
|
88
154
|
// if no time range is specified, default to 24 hours ago
|
|
89
155
|
const now = Date.now();
|
|
90
|
-
const defaultStartTime = now - 24 * 60 * 60 * 1000; // 24 hours ago
|
|
91
156
|
return this.httpClient.info({
|
|
92
157
|
type: constants_1.InfoType.CANDLES_SNAPSHOT,
|
|
93
158
|
req: {
|
|
94
159
|
coin,
|
|
95
160
|
interval,
|
|
96
|
-
startTime: startTime
|
|
97
|
-
endTime: endTime
|
|
161
|
+
startTime: startTime,
|
|
162
|
+
endTime: endTime !== null && endTime !== void 0 ? endTime : now,
|
|
98
163
|
},
|
|
99
164
|
});
|
|
100
165
|
});
|
|
101
166
|
}
|
|
102
167
|
/**
|
|
103
|
-
* Check builder fee
|
|
168
|
+
* Check max builder fee
|
|
104
169
|
*/
|
|
105
|
-
|
|
170
|
+
getMaxBuilderFee(builder, address) {
|
|
106
171
|
return __awaiter(this, void 0, void 0, function* () {
|
|
172
|
+
const user = address || this.masterAddress;
|
|
173
|
+
if (!user) {
|
|
174
|
+
throw new Error('user address is empty');
|
|
175
|
+
}
|
|
107
176
|
return this.httpClient.info({
|
|
108
|
-
type: constants_1.InfoType.
|
|
109
|
-
user
|
|
177
|
+
type: constants_1.InfoType.MAX_BUILDER_FEE,
|
|
178
|
+
user,
|
|
110
179
|
builder,
|
|
111
180
|
});
|
|
112
181
|
});
|
|
@@ -116,9 +185,13 @@ class InfoClient {
|
|
|
116
185
|
*/
|
|
117
186
|
getUserRole(address) {
|
|
118
187
|
return __awaiter(this, void 0, void 0, function* () {
|
|
188
|
+
const user = address || this.masterAddress;
|
|
189
|
+
if (!user) {
|
|
190
|
+
throw new Error('user address is empty');
|
|
191
|
+
}
|
|
119
192
|
const res = yield this.httpClient.info({
|
|
120
193
|
type: constants_1.InfoType.USER_ROLE,
|
|
121
|
-
user
|
|
194
|
+
user,
|
|
122
195
|
});
|
|
123
196
|
return res;
|
|
124
197
|
});
|
|
@@ -128,9 +201,13 @@ class InfoClient {
|
|
|
128
201
|
*/
|
|
129
202
|
getUsersFees(address) {
|
|
130
203
|
return __awaiter(this, void 0, void 0, function* () {
|
|
204
|
+
const user = address || this.masterAddress;
|
|
205
|
+
if (!user) {
|
|
206
|
+
throw new Error('user address is empty');
|
|
207
|
+
}
|
|
131
208
|
const res = yield this.httpClient.info({
|
|
132
209
|
type: constants_1.InfoType.USER_FEES,
|
|
133
|
-
user
|
|
210
|
+
user,
|
|
134
211
|
});
|
|
135
212
|
// const perpFee = Number(res.userCrossRate) * (1 - Number(res.activeReferralDiscount));
|
|
136
213
|
return res;
|
|
@@ -141,9 +218,13 @@ class InfoClient {
|
|
|
141
218
|
*/
|
|
142
219
|
extraAgents(address) {
|
|
143
220
|
return __awaiter(this, void 0, void 0, function* () {
|
|
221
|
+
const user = address || this.masterAddress;
|
|
222
|
+
if (!user) {
|
|
223
|
+
throw new Error('user address is empty');
|
|
224
|
+
}
|
|
144
225
|
return this.httpClient.info({
|
|
145
226
|
type: constants_1.InfoType.EXTRA_AGENTS,
|
|
146
|
-
user
|
|
227
|
+
user,
|
|
147
228
|
});
|
|
148
229
|
});
|
|
149
230
|
}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { HttpClientConfig } from "./http-client";
|
|
2
|
+
import { InfoClient } from "./info-client";
|
|
2
3
|
export declare class SymbolConversion {
|
|
3
4
|
private assetToIndexMap;
|
|
4
5
|
private httpClient;
|
|
5
6
|
private initialized;
|
|
6
|
-
|
|
7
|
+
private infoClient?;
|
|
8
|
+
constructor(config: HttpClientConfig, infoClient?: InfoClient);
|
|
7
9
|
initialize(): Promise<void>;
|
|
8
10
|
private ensureInitialized;
|
|
9
11
|
private refreshAssetMaps;
|
|
@@ -13,9 +13,10 @@ exports.SymbolConversion = void 0;
|
|
|
13
13
|
const constants_1 = require("../types/constants");
|
|
14
14
|
const http_client_1 = require("./http-client");
|
|
15
15
|
class SymbolConversion {
|
|
16
|
-
constructor(config) {
|
|
16
|
+
constructor(config, infoClient) {
|
|
17
17
|
this.assetToIndexMap = new Map();
|
|
18
18
|
this.initialized = false;
|
|
19
|
+
this.infoClient = infoClient;
|
|
19
20
|
this.httpClient = new http_client_1.HttpClient({
|
|
20
21
|
isTestnet: config.isTestnet,
|
|
21
22
|
timeout: config.timeout,
|
|
@@ -46,9 +47,15 @@ class SymbolConversion {
|
|
|
46
47
|
refreshAssetMaps() {
|
|
47
48
|
return __awaiter(this, void 0, void 0, function* () {
|
|
48
49
|
try {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
let perpMeta = null;
|
|
51
|
+
if (!this.infoClient) {
|
|
52
|
+
perpMeta = yield this.httpClient.info({
|
|
53
|
+
type: constants_1.InfoType.META_AND_ASSET_CTXS,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
perpMeta = yield this.infoClient.metaAndAssetCtxs(false);
|
|
58
|
+
}
|
|
52
59
|
// Verify responses are valid before proceeding
|
|
53
60
|
if (!perpMeta ||
|
|
54
61
|
!perpMeta[0] ||
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { AllMids, L2Book, Candle,
|
|
1
|
+
import type { AllMids, L2Book, Candle, WsOrder, WebData2, WsActiveAssetCtx, WsUserFills } from '../types';
|
|
2
2
|
export interface WebSocketClientConfig {
|
|
3
|
-
masterAddress
|
|
3
|
+
masterAddress?: string;
|
|
4
4
|
isTestnet?: boolean;
|
|
5
5
|
autoReconnect?: boolean;
|
|
6
6
|
reconnectDelay?: number;
|
|
@@ -18,11 +18,11 @@ export declare class WebSocketClient {
|
|
|
18
18
|
private readonly url;
|
|
19
19
|
private readonly config;
|
|
20
20
|
private subscriptions;
|
|
21
|
-
private subscriptionId;
|
|
22
21
|
private reconnectAttempts;
|
|
23
22
|
private isConnecting;
|
|
24
23
|
private pendingSubscriptions;
|
|
25
24
|
constructor(config: WebSocketClientConfig);
|
|
25
|
+
initMasterAddress(masterAddress: string): void;
|
|
26
26
|
/**
|
|
27
27
|
* Connect to the WebSocket
|
|
28
28
|
*/
|
|
@@ -43,6 +43,10 @@ export declare class WebSocketClient {
|
|
|
43
43
|
* Subscribe to L2 order book for a specific coin
|
|
44
44
|
*/
|
|
45
45
|
subscribeToL2Book(coin: string, callback: SubscriptionCallback<L2Book>): Subscription;
|
|
46
|
+
/**
|
|
47
|
+
* Subscribe to active asset ctx
|
|
48
|
+
*/
|
|
49
|
+
subscribeToActiveAssetCtx(coin: string, callback: SubscriptionCallback<WsActiveAssetCtx>): Subscription;
|
|
46
50
|
/**
|
|
47
51
|
* Subscribe to trades for a specific coin
|
|
48
52
|
*/
|
|
@@ -54,7 +58,7 @@ export declare class WebSocketClient {
|
|
|
54
58
|
/**
|
|
55
59
|
* Subscribe to user fills
|
|
56
60
|
*/
|
|
57
|
-
subscribeToUserFills(callback: SubscriptionCallback<
|
|
61
|
+
subscribeToUserFills(callback: SubscriptionCallback<WsUserFills>): Subscription;
|
|
58
62
|
/**
|
|
59
63
|
* Subscribe to user order updates
|
|
60
64
|
*/
|
|
@@ -18,13 +18,21 @@ class WebSocketClient {
|
|
|
18
18
|
constructor(config) {
|
|
19
19
|
this.ws = null;
|
|
20
20
|
this.subscriptions = new Map();
|
|
21
|
-
this.subscriptionId = 0;
|
|
22
21
|
this.reconnectAttempts = 0;
|
|
23
22
|
this.isConnecting = false;
|
|
24
23
|
this.pendingSubscriptions = [];
|
|
25
|
-
this.config =
|
|
24
|
+
this.config = {
|
|
25
|
+
isTestnet: false,
|
|
26
|
+
autoReconnect: true,
|
|
27
|
+
reconnectDelay: 3000,
|
|
28
|
+
maxReconnectAttempts: 5,
|
|
29
|
+
masterAddress: config.masterAddress || '',
|
|
30
|
+
};
|
|
26
31
|
this.url = this.config.isTestnet ? constants_1.WSS_URLS.TESTNET : constants_1.WSS_URLS.PRODUCTION;
|
|
27
32
|
}
|
|
33
|
+
initMasterAddress(masterAddress) {
|
|
34
|
+
this.config.masterAddress = masterAddress;
|
|
35
|
+
}
|
|
28
36
|
/**
|
|
29
37
|
* Connect to the WebSocket
|
|
30
38
|
*/
|
|
@@ -57,13 +65,13 @@ class WebSocketClient {
|
|
|
57
65
|
this.ws.onopen = () => {
|
|
58
66
|
this.isConnecting = false;
|
|
59
67
|
this.reconnectAttempts = 0;
|
|
60
|
-
console.log('WebSocket connected');
|
|
68
|
+
console.log('hyperliquid sdk WebSocket connected');
|
|
61
69
|
// Resubscribe to pending subscriptions
|
|
62
|
-
this.pendingSubscriptions.forEach(({
|
|
70
|
+
this.pendingSubscriptions.forEach(({ message, callback }) => {
|
|
63
71
|
var _a;
|
|
64
|
-
this.subscriptions.set(id, callback);
|
|
65
72
|
if (((_a = this.ws) === null || _a === void 0 ? void 0 : _a.readyState) === WebSocket.OPEN) {
|
|
66
|
-
this.
|
|
73
|
+
this.subscriptions.set(message.subscription.type, callback);
|
|
74
|
+
this.ws.send(JSON.stringify(Object.assign(Object.assign({}, message), { method: 'subscribe' })));
|
|
67
75
|
}
|
|
68
76
|
});
|
|
69
77
|
this.pendingSubscriptions = [];
|
|
@@ -72,12 +80,10 @@ class WebSocketClient {
|
|
|
72
80
|
this.ws.onmessage = (event) => {
|
|
73
81
|
try {
|
|
74
82
|
const data = JSON.parse(event.data);
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
callback(data.data);
|
|
80
|
-
}
|
|
83
|
+
const type = data.channel;
|
|
84
|
+
const callback = this.subscriptions.get(type);
|
|
85
|
+
if (callback) {
|
|
86
|
+
callback(data.data);
|
|
81
87
|
}
|
|
82
88
|
}
|
|
83
89
|
catch (error) {
|
|
@@ -85,9 +91,10 @@ class WebSocketClient {
|
|
|
85
91
|
}
|
|
86
92
|
};
|
|
87
93
|
this.ws.onclose = () => {
|
|
94
|
+
var _a;
|
|
88
95
|
this.isConnecting = false;
|
|
89
96
|
console.log('WebSocket disconnected');
|
|
90
|
-
if (this.config.autoReconnect && this.reconnectAttempts < this.config.maxReconnectAttempts) {
|
|
97
|
+
if (this.config.autoReconnect && this.reconnectAttempts < this.config.maxReconnectAttempts && ((_a = this.ws) === null || _a === void 0 ? void 0 : _a.readyState) === WebSocket.OPEN) {
|
|
91
98
|
this.reconnectAttempts++;
|
|
92
99
|
console.log(`Reconnecting... (${this.reconnectAttempts}/${this.config.maxReconnectAttempts})`);
|
|
93
100
|
setTimeout(() => this.connect(), this.config.reconnectDelay);
|
|
@@ -117,15 +124,13 @@ class WebSocketClient {
|
|
|
117
124
|
*/
|
|
118
125
|
subscribe(message, callback) {
|
|
119
126
|
var _a;
|
|
120
|
-
const id = ++this.subscriptionId;
|
|
121
|
-
const subscriptionMessage = Object.assign(Object.assign({}, message), { id });
|
|
122
127
|
if (((_a = this.ws) === null || _a === void 0 ? void 0 : _a.readyState) === WebSocket.OPEN) {
|
|
123
|
-
this.subscriptions.set(
|
|
124
|
-
this.ws.send(JSON.stringify(Object.assign(Object.assign({},
|
|
128
|
+
this.subscriptions.set(message.subscription.type, callback);
|
|
129
|
+
this.ws.send(JSON.stringify(Object.assign(Object.assign({}, message), { method: 'subscribe' })));
|
|
125
130
|
}
|
|
126
131
|
else {
|
|
127
132
|
// Store pending subscription for when connection is established
|
|
128
|
-
this.pendingSubscriptions.push({
|
|
133
|
+
this.pendingSubscriptions.push({ message, callback });
|
|
129
134
|
// Auto-connect if not connected
|
|
130
135
|
if (!this.isConnecting && (!this.ws || this.ws.readyState === WebSocket.CLOSED)) {
|
|
131
136
|
this.connect().catch(console.error);
|
|
@@ -134,12 +139,12 @@ class WebSocketClient {
|
|
|
134
139
|
return {
|
|
135
140
|
unsubscribe: () => {
|
|
136
141
|
var _a;
|
|
137
|
-
this.subscriptions.delete(
|
|
142
|
+
this.subscriptions.delete(message.subscription.type);
|
|
138
143
|
if (((_a = this.ws) === null || _a === void 0 ? void 0 : _a.readyState) === WebSocket.OPEN) {
|
|
139
|
-
this.ws.send(JSON.stringify(Object.assign(Object.assign({},
|
|
144
|
+
this.ws.send(JSON.stringify(Object.assign(Object.assign({}, message), { method: 'unsubscribe' })));
|
|
140
145
|
}
|
|
141
146
|
// Remove from pending subscriptions
|
|
142
|
-
this.pendingSubscriptions = this.pendingSubscriptions.filter(sub => sub.
|
|
147
|
+
this.pendingSubscriptions = this.pendingSubscriptions.filter(sub => sub.message.subscription.type !== message.subscription.type);
|
|
143
148
|
},
|
|
144
149
|
};
|
|
145
150
|
}
|
|
@@ -159,6 +164,14 @@ class WebSocketClient {
|
|
|
159
164
|
subscription: { type: 'l2Book', coin },
|
|
160
165
|
}, callback);
|
|
161
166
|
}
|
|
167
|
+
/**
|
|
168
|
+
* Subscribe to active asset ctx
|
|
169
|
+
*/
|
|
170
|
+
subscribeToActiveAssetCtx(coin, callback) {
|
|
171
|
+
return this.subscribe({
|
|
172
|
+
subscription: { type: 'activeAssetCtx', coin },
|
|
173
|
+
}, callback);
|
|
174
|
+
}
|
|
162
175
|
/**
|
|
163
176
|
* Subscribe to trades for a specific coin
|
|
164
177
|
*/
|
|
@@ -179,22 +192,31 @@ class WebSocketClient {
|
|
|
179
192
|
* Subscribe to user fills
|
|
180
193
|
*/
|
|
181
194
|
subscribeToUserFills(callback) {
|
|
195
|
+
if (!this.config.masterAddress) {
|
|
196
|
+
throw new Error('masterAddress is empty');
|
|
197
|
+
}
|
|
182
198
|
return this.subscribe({
|
|
183
|
-
subscription: { type: 'userFills', user: this.config.masterAddress },
|
|
199
|
+
subscription: { type: 'userFills', user: this.config.masterAddress, aggregateByTime: true },
|
|
184
200
|
}, callback);
|
|
185
201
|
}
|
|
186
202
|
/**
|
|
187
203
|
* Subscribe to user order updates
|
|
188
204
|
*/
|
|
189
205
|
subscribeToUserOrders(callback) {
|
|
206
|
+
if (!this.config.masterAddress) {
|
|
207
|
+
throw new Error('masterAddress is empty');
|
|
208
|
+
}
|
|
190
209
|
return this.subscribe({
|
|
191
|
-
subscription: { type: '
|
|
210
|
+
subscription: { type: 'orderUpdates', user: this.config.masterAddress },
|
|
192
211
|
}, callback);
|
|
193
212
|
}
|
|
194
213
|
/**
|
|
195
214
|
* Subscribe to user funding updates
|
|
196
215
|
*/
|
|
197
216
|
subscribeToUserFunding(callback) {
|
|
217
|
+
if (!this.config.masterAddress) {
|
|
218
|
+
throw new Error('masterAddress is empty');
|
|
219
|
+
}
|
|
198
220
|
return this.subscribe({
|
|
199
221
|
subscription: { type: 'userFundings', user: this.config.masterAddress },
|
|
200
222
|
}, callback);
|
|
@@ -204,6 +226,9 @@ class WebSocketClient {
|
|
|
204
226
|
* Includes positions, margin summary, open orders, and other user data
|
|
205
227
|
*/
|
|
206
228
|
subscribeToWebData2(callback) {
|
|
229
|
+
if (!this.config.masterAddress) {
|
|
230
|
+
throw new Error('masterAddress is empty');
|
|
231
|
+
}
|
|
207
232
|
return this.subscribe({
|
|
208
233
|
subscription: { type: 'webData2', user: this.config.masterAddress },
|
|
209
234
|
}, callback);
|
|
@@ -4,7 +4,7 @@ import type { ClearinghouseState } from './types';
|
|
|
4
4
|
import { WebSocketClient, WebSocketClientConfig } from './client/websocket-client';
|
|
5
5
|
import { SymbolConversion } from './client/symbolConversion';
|
|
6
6
|
export interface HyperliquidSDKConfig {
|
|
7
|
-
masterAddress
|
|
7
|
+
masterAddress?: string;
|
|
8
8
|
agentPrivateKey?: string;
|
|
9
9
|
agentPublicKey?: string;
|
|
10
10
|
agentName?: string;
|
|
@@ -22,14 +22,14 @@ export declare class HyperliquidSDK {
|
|
|
22
22
|
exchange?: ExchangeClient;
|
|
23
23
|
symbolConversion: SymbolConversion;
|
|
24
24
|
readonly ws: WebSocketClient;
|
|
25
|
-
private readonly masterAddress
|
|
25
|
+
private readonly masterAddress?;
|
|
26
26
|
private readonly configParams;
|
|
27
27
|
constructor(config: HyperliquidSDKConfig);
|
|
28
28
|
/**
|
|
29
29
|
* Get wallet address (only available if private key was provided)
|
|
30
30
|
*/
|
|
31
31
|
get address(): string;
|
|
32
|
-
|
|
32
|
+
initAccount(masterAddress: string, agentPrivateKey: string, agentPublicKey: string, agentName?: string): void;
|
|
33
33
|
/**
|
|
34
34
|
* Connect to WebSocket for real-time data
|
|
35
35
|
*/
|
|
@@ -46,8 +46,4 @@ export declare class HyperliquidSDK {
|
|
|
46
46
|
* Quick helper: Get account summary with essential info
|
|
47
47
|
*/
|
|
48
48
|
getAccountSummary(): Promise<ClearinghouseState>;
|
|
49
|
-
/**
|
|
50
|
-
* Quick helper: Get market overview
|
|
51
|
-
*/
|
|
52
|
-
getMarketOverview(): Promise<any>;
|
|
53
49
|
}
|
package/dist/hyperliquid-sdk.js
CHANGED
|
@@ -21,20 +21,19 @@ const symbolConversion_1 = require("./client/symbolConversion");
|
|
|
21
21
|
*/
|
|
22
22
|
class HyperliquidSDK {
|
|
23
23
|
constructor(config) {
|
|
24
|
-
// Initialize info client (always available)
|
|
25
|
-
this.symbolConversion = new symbolConversion_1.SymbolConversion({
|
|
26
|
-
isTestnet: config.isTestnet,
|
|
27
|
-
timeout: config.timeout,
|
|
28
|
-
});
|
|
29
24
|
this.info = new info_client_1.InfoClient({
|
|
30
25
|
masterAddress: config.masterAddress,
|
|
31
26
|
isTestnet: config.isTestnet,
|
|
32
27
|
timeout: config.timeout,
|
|
33
28
|
});
|
|
29
|
+
this.symbolConversion = new symbolConversion_1.SymbolConversion({
|
|
30
|
+
isTestnet: config.isTestnet,
|
|
31
|
+
timeout: config.timeout,
|
|
32
|
+
}, this.info);
|
|
34
33
|
this.masterAddress = config.masterAddress;
|
|
35
34
|
this.configParams = config;
|
|
36
35
|
// Initialize exchange client only if private key is provided
|
|
37
|
-
if (config.
|
|
36
|
+
if (config.masterAddress) {
|
|
38
37
|
this.exchange = new exchange_client_1.ExchangeClient({
|
|
39
38
|
masterAddress: config.masterAddress,
|
|
40
39
|
agentPrivateKey: config.agentPrivateKey,
|
|
@@ -52,12 +51,25 @@ class HyperliquidSDK {
|
|
|
52
51
|
* Get wallet address (only available if private key was provided)
|
|
53
52
|
*/
|
|
54
53
|
get address() {
|
|
55
|
-
return this.masterAddress;
|
|
54
|
+
return this.masterAddress || '';
|
|
56
55
|
}
|
|
57
|
-
|
|
58
|
-
this.
|
|
59
|
-
|
|
60
|
-
|
|
56
|
+
initAccount(masterAddress, agentPrivateKey, agentPublicKey, agentName) {
|
|
57
|
+
this.info.initMasterAddress(masterAddress);
|
|
58
|
+
this.ws.initMasterAddress(masterAddress);
|
|
59
|
+
if (this.exchange) {
|
|
60
|
+
this.exchange.initAccount(masterAddress, agentPrivateKey, agentPublicKey, agentName);
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
this.exchange = new exchange_client_1.ExchangeClient({
|
|
64
|
+
masterAddress,
|
|
65
|
+
symbolConversion: this.symbolConversion,
|
|
66
|
+
agentPrivateKey,
|
|
67
|
+
agentPublicKey,
|
|
68
|
+
agentName,
|
|
69
|
+
isTestnet: this.configParams.isTestnet,
|
|
70
|
+
timeout: this.configParams.timeout,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
61
73
|
}
|
|
62
74
|
/**
|
|
63
75
|
* Connect to WebSocket for real-time data
|
|
@@ -87,18 +99,5 @@ class HyperliquidSDK {
|
|
|
87
99
|
return this.info.getClearingHouseState();
|
|
88
100
|
});
|
|
89
101
|
}
|
|
90
|
-
/**
|
|
91
|
-
* Quick helper: Get market overview
|
|
92
|
-
*/
|
|
93
|
-
getMarketOverview() {
|
|
94
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
95
|
-
const [meta, assetCtxs] = yield this.info.metaAndAssetCtxs();
|
|
96
|
-
return {
|
|
97
|
-
assets: meta.universe,
|
|
98
|
-
assetContexts: assetCtxs,
|
|
99
|
-
marginTables: meta.marginTables,
|
|
100
|
-
};
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
102
|
}
|
|
104
103
|
exports.HyperliquidSDK = HyperliquidSDK;
|
|
@@ -27,6 +27,8 @@ export declare enum ExchangeType {
|
|
|
27
27
|
}
|
|
28
28
|
export declare enum InfoType {
|
|
29
29
|
ALL_MIDS = "allMids",
|
|
30
|
+
USER_NON_FUNDING_LEDGER_UPDATES = "userNonFundingLedgerUpdates",
|
|
31
|
+
USER_HISTORICAL_ORDERS = "historicalOrders",
|
|
30
32
|
USER_OPEN_ORDERS = "openOrders",
|
|
31
33
|
USER_FILLS = "userFills",
|
|
32
34
|
USER_FILLS_BY_TIME = "userFillsByTime",
|
|
@@ -35,14 +37,13 @@ export declare enum InfoType {
|
|
|
35
37
|
CANDLES_SNAPSHOT = "candleSnapshot",
|
|
36
38
|
META_AND_ASSET_CTXS = "metaAndAssetCtxs",
|
|
37
39
|
USER_FUNDING = "userFunding",
|
|
38
|
-
USER_NON_FUNDING_LEDGER_UPDATES = "userNonFundingLedgerUpdates",
|
|
39
40
|
FUNDING_HISTORY = "fundingHistory",
|
|
40
41
|
CLEARINGHOUSE_STATE = "clearinghouseState",
|
|
41
42
|
META = "meta",
|
|
42
43
|
FRONTEND_OPEN_ORDERS = "frontendOpenOrders",
|
|
43
44
|
PREDICTED_FUNDINGS = "predictedFundings",
|
|
44
45
|
ACTIVE_ASSET_DATA = "activeAssetData",
|
|
45
|
-
|
|
46
|
+
MAX_BUILDER_FEE = "maxBuilderFee",
|
|
46
47
|
USER_FEES = "userFees",
|
|
47
48
|
USER_ROLE = "userRole",
|
|
48
49
|
EXTRA_AGENTS = "extraAgents"
|
package/dist/types/constants.js
CHANGED
|
@@ -35,6 +35,8 @@ var ExchangeType;
|
|
|
35
35
|
var InfoType;
|
|
36
36
|
(function (InfoType) {
|
|
37
37
|
InfoType["ALL_MIDS"] = "allMids";
|
|
38
|
+
InfoType["USER_NON_FUNDING_LEDGER_UPDATES"] = "userNonFundingLedgerUpdates";
|
|
39
|
+
InfoType["USER_HISTORICAL_ORDERS"] = "historicalOrders";
|
|
38
40
|
InfoType["USER_OPEN_ORDERS"] = "openOrders";
|
|
39
41
|
InfoType["USER_FILLS"] = "userFills";
|
|
40
42
|
InfoType["USER_FILLS_BY_TIME"] = "userFillsByTime";
|
|
@@ -43,14 +45,13 @@ var InfoType;
|
|
|
43
45
|
InfoType["CANDLES_SNAPSHOT"] = "candleSnapshot";
|
|
44
46
|
InfoType["META_AND_ASSET_CTXS"] = "metaAndAssetCtxs";
|
|
45
47
|
InfoType["USER_FUNDING"] = "userFunding";
|
|
46
|
-
InfoType["USER_NON_FUNDING_LEDGER_UPDATES"] = "userNonFundingLedgerUpdates";
|
|
47
48
|
InfoType["FUNDING_HISTORY"] = "fundingHistory";
|
|
48
49
|
InfoType["CLEARINGHOUSE_STATE"] = "clearinghouseState";
|
|
49
50
|
InfoType["META"] = "meta";
|
|
50
51
|
InfoType["FRONTEND_OPEN_ORDERS"] = "frontendOpenOrders";
|
|
51
52
|
InfoType["PREDICTED_FUNDINGS"] = "predictedFundings";
|
|
52
53
|
InfoType["ACTIVE_ASSET_DATA"] = "activeAssetData";
|
|
53
|
-
InfoType["
|
|
54
|
+
InfoType["MAX_BUILDER_FEE"] = "maxBuilderFee";
|
|
54
55
|
InfoType["USER_FEES"] = "userFees";
|
|
55
56
|
InfoType["USER_ROLE"] = "userRole";
|
|
56
57
|
InfoType["EXTRA_AGENTS"] = "extraAgents";
|
package/dist/types/index.d.ts
CHANGED
|
@@ -4,6 +4,33 @@ export type TriggerType = 'tp' | 'sl';
|
|
|
4
4
|
export type Side = 'A' | 'B';
|
|
5
5
|
export type AssetId = number;
|
|
6
6
|
export type OrderId = number;
|
|
7
|
+
export interface MarketOverview {
|
|
8
|
+
assets: AssetInfo[];
|
|
9
|
+
assetContexts: AssetCtx[];
|
|
10
|
+
marginTables: [number, MarginTable][];
|
|
11
|
+
}
|
|
12
|
+
export interface UserHistoricalOrders {
|
|
13
|
+
order: {
|
|
14
|
+
coin: string;
|
|
15
|
+
side: Side;
|
|
16
|
+
limitPx: string;
|
|
17
|
+
sz: string;
|
|
18
|
+
oid: number;
|
|
19
|
+
timestamp: number;
|
|
20
|
+
triggerCondition: string;
|
|
21
|
+
isTrigger: boolean;
|
|
22
|
+
triggerPx: string;
|
|
23
|
+
children: any;
|
|
24
|
+
isPositionTpsl: boolean;
|
|
25
|
+
reduceOnly: boolean;
|
|
26
|
+
orderType: string;
|
|
27
|
+
origSz: string;
|
|
28
|
+
tif: string;
|
|
29
|
+
cloid: string | null;
|
|
30
|
+
};
|
|
31
|
+
status: string;
|
|
32
|
+
statusTimestamp: number;
|
|
33
|
+
}
|
|
7
34
|
export interface OpenOrder {
|
|
8
35
|
coin: string;
|
|
9
36
|
side: Side;
|
|
@@ -52,6 +79,7 @@ export type OrderType = LimitOrderType | MarketOrderType | StopOrderType;
|
|
|
52
79
|
export interface AssetInfo {
|
|
53
80
|
name: string;
|
|
54
81
|
szDecimals: number;
|
|
82
|
+
marginTableId: number;
|
|
55
83
|
maxLeverage: number;
|
|
56
84
|
onlyIsolated?: boolean;
|
|
57
85
|
isDelisted?: boolean;
|
|
@@ -121,6 +149,24 @@ export interface UserFill {
|
|
|
121
149
|
export type UserFills = {
|
|
122
150
|
[asset: string]: UserFill[];
|
|
123
151
|
};
|
|
152
|
+
export type UserNonFundingLedgerUpdates = {
|
|
153
|
+
time: number;
|
|
154
|
+
hash: string;
|
|
155
|
+
delta: {
|
|
156
|
+
type: string;
|
|
157
|
+
usdc?: string;
|
|
158
|
+
vault?: string;
|
|
159
|
+
user?: string;
|
|
160
|
+
token?: string;
|
|
161
|
+
amount?: string;
|
|
162
|
+
requestedUsd?: string;
|
|
163
|
+
commission?: string;
|
|
164
|
+
closingCost?: string;
|
|
165
|
+
basis?: string;
|
|
166
|
+
netWithdrawnUsd?: string;
|
|
167
|
+
toPerp?: boolean;
|
|
168
|
+
};
|
|
169
|
+
};
|
|
124
170
|
export interface OrderResponse {
|
|
125
171
|
status: 'ok';
|
|
126
172
|
response: {
|
|
@@ -133,6 +179,7 @@ export interface OrderResponse {
|
|
|
133
179
|
filled?: {
|
|
134
180
|
totalSz: string;
|
|
135
181
|
avgPx: string;
|
|
182
|
+
oid: number;
|
|
136
183
|
};
|
|
137
184
|
error?: string;
|
|
138
185
|
}>;
|
|
@@ -185,6 +232,11 @@ export interface WsOrder {
|
|
|
185
232
|
children?: WsOrder[];
|
|
186
233
|
user: string;
|
|
187
234
|
}
|
|
235
|
+
export interface WsUserFills {
|
|
236
|
+
isSnapshot?: boolean;
|
|
237
|
+
user: string;
|
|
238
|
+
fills: WsFill[];
|
|
239
|
+
}
|
|
188
240
|
export interface WsFill {
|
|
189
241
|
coin: string;
|
|
190
242
|
px: string;
|
|
@@ -199,8 +251,14 @@ export interface WsFill {
|
|
|
199
251
|
crossed: boolean;
|
|
200
252
|
fee: string;
|
|
201
253
|
tid: number;
|
|
254
|
+
liquidation?: {
|
|
255
|
+
liquidatedUser: string;
|
|
256
|
+
markPx: string;
|
|
257
|
+
method: string;
|
|
258
|
+
};
|
|
202
259
|
}
|
|
203
260
|
export interface AssetCtx {
|
|
261
|
+
dayBaseVlm: string;
|
|
204
262
|
dayNtlVlm: string;
|
|
205
263
|
funding: string;
|
|
206
264
|
impactPxs: [string, string];
|
|
@@ -219,6 +277,18 @@ export interface L2Book {
|
|
|
219
277
|
levels: [WsLevel[], WsLevel[]];
|
|
220
278
|
time: number;
|
|
221
279
|
}
|
|
280
|
+
export interface WsActiveAssetCtx {
|
|
281
|
+
coin: string;
|
|
282
|
+
ctx: {
|
|
283
|
+
dayNtlVlm: string;
|
|
284
|
+
prevDayPx: string;
|
|
285
|
+
markPx: string;
|
|
286
|
+
midPx?: string;
|
|
287
|
+
funding: string;
|
|
288
|
+
openInterest: string;
|
|
289
|
+
oraclePx: string;
|
|
290
|
+
};
|
|
291
|
+
}
|
|
222
292
|
export interface Candle {
|
|
223
293
|
t: number;
|
|
224
294
|
T: number;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Removes trailing zeros from a string representation of a number.
|
|
3
|
+
* This is useful when working with price and size fields directly.
|
|
4
|
+
*
|
|
5
|
+
* Hyperliquid API requires that price ('p') and size ('s') fields do not contain trailing zeros.
|
|
6
|
+
* For example, "12345.0" should be "12345" and "0.123450" should be "0.12345".
|
|
7
|
+
* This function ensures that all numeric string values are properly formatted.
|
|
8
|
+
*
|
|
9
|
+
* @param value - The string value to normalize
|
|
10
|
+
* @returns The normalized string without trailing zeros
|
|
11
|
+
*/
|
|
12
|
+
export declare function removeTrailingZeros(value: string): string;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.removeTrailingZeros = removeTrailingZeros;
|
|
4
|
+
/**
|
|
5
|
+
* Removes trailing zeros from a string representation of a number.
|
|
6
|
+
* This is useful when working with price and size fields directly.
|
|
7
|
+
*
|
|
8
|
+
* Hyperliquid API requires that price ('p') and size ('s') fields do not contain trailing zeros.
|
|
9
|
+
* For example, "12345.0" should be "12345" and "0.123450" should be "0.12345".
|
|
10
|
+
* This function ensures that all numeric string values are properly formatted.
|
|
11
|
+
*
|
|
12
|
+
* @param value - The string value to normalize
|
|
13
|
+
* @returns The normalized string without trailing zeros
|
|
14
|
+
*/
|
|
15
|
+
function removeTrailingZeros(value) {
|
|
16
|
+
if (!value.includes('.'))
|
|
17
|
+
return value;
|
|
18
|
+
const normalized = value.replace(/\.?0+$/, '');
|
|
19
|
+
if (normalized === '-0')
|
|
20
|
+
return '0';
|
|
21
|
+
return normalized;
|
|
22
|
+
}
|
package/package.json
CHANGED