@rabby-wallet/hyperliquid-sdk 1.0.0-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 +138 -0
- package/dist/client/exchange-client.d.ts +89 -0
- package/dist/client/exchange-client.js +521 -0
- package/dist/client/http-client.d.ts +26 -0
- package/dist/client/http-client.js +75 -0
- package/dist/client/info-client.d.ts +49 -0
- package/dist/client/info-client.js +140 -0
- package/dist/client/symbolConversion.d.ts +14 -0
- package/dist/client/symbolConversion.js +91 -0
- package/dist/client/websocket-client.d.ts +82 -0
- package/dist/client/websocket-client.js +227 -0
- package/dist/hyperliquid-sdk.d.ts +53 -0
- package/dist/hyperliquid-sdk.js +105 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +42 -0
- package/dist/types/constants.d.ts +67 -0
- package/dist/types/constants.js +80 -0
- package/dist/types/index.d.ts +342 -0
- package/dist/types/index.js +2 -0
- package/dist/utils/signer.d.ts +35 -0
- package/dist/utils/signer.js +134 -0
- package/package.json +36 -0
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.InfoClient = void 0;
|
|
13
|
+
const http_client_1 = require("./http-client");
|
|
14
|
+
const constants_1 = require("../types/constants");
|
|
15
|
+
/**
|
|
16
|
+
* Client for querying Hyperliquid info endpoints (perpetuals only)
|
|
17
|
+
* Only includes essential APIs as specified
|
|
18
|
+
*/
|
|
19
|
+
class InfoClient {
|
|
20
|
+
constructor(config) {
|
|
21
|
+
this.masterAddress = config.masterAddress;
|
|
22
|
+
this.httpClient = new http_client_1.HttpClient({
|
|
23
|
+
isTestnet: config.isTestnet,
|
|
24
|
+
timeout: config.timeout,
|
|
25
|
+
});
|
|
26
|
+
this.symbolConversion = config.symbolConversion;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Get all mid prices for all assets
|
|
30
|
+
*/
|
|
31
|
+
getAllMids() {
|
|
32
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
33
|
+
return this.httpClient.info({
|
|
34
|
+
type: constants_1.InfoType.ALL_MIDS,
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Get metadata and asset contexts
|
|
40
|
+
*/
|
|
41
|
+
metaAndAssetCtxs() {
|
|
42
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
43
|
+
return this.httpClient.info({
|
|
44
|
+
type: constants_1.InfoType.META_AND_ASSET_CTXS,
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
getClearingHouseState() {
|
|
49
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
50
|
+
return this.httpClient.info({
|
|
51
|
+
type: constants_1.InfoType.CLEARINGHOUSE_STATE,
|
|
52
|
+
user: this.masterAddress,
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
// frontendOpenOrders
|
|
57
|
+
getFrontendOpenOrders() {
|
|
58
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
59
|
+
return this.httpClient.info({
|
|
60
|
+
type: constants_1.InfoType.FRONTEND_OPEN_ORDERS,
|
|
61
|
+
user: this.masterAddress,
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
// need use getFrontendOpenOrders
|
|
66
|
+
// async getOpenOrders(): Promise<any> {
|
|
67
|
+
// return this.httpClient.info({
|
|
68
|
+
// type: InfoType.USER_OPEN_ORDERS,
|
|
69
|
+
// user: this.masterAddress,
|
|
70
|
+
// });
|
|
71
|
+
// }
|
|
72
|
+
/**
|
|
73
|
+
* Get user's fill history
|
|
74
|
+
*/
|
|
75
|
+
getUserFills() {
|
|
76
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
77
|
+
return this.httpClient.info({
|
|
78
|
+
type: constants_1.InfoType.USER_FILLS,
|
|
79
|
+
user: this.masterAddress,
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Get candlestick data snapshot
|
|
85
|
+
* Supported intervals: "1m", "3m", "5m", "15m", "30m", "1h", "2h", "4h", "8h", "12h", "1d", "3d", "1w", "1M"
|
|
86
|
+
*/
|
|
87
|
+
candleSnapshot(coin, interval, startTime, endTime) {
|
|
88
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
89
|
+
// if no time range is specified, default to 24 hours ago
|
|
90
|
+
const now = Date.now();
|
|
91
|
+
const defaultStartTime = now - 24 * 60 * 60 * 1000; // 24 hours ago
|
|
92
|
+
return this.httpClient.info({
|
|
93
|
+
type: constants_1.InfoType.CANDLES_SNAPSHOT,
|
|
94
|
+
req: {
|
|
95
|
+
coin,
|
|
96
|
+
interval,
|
|
97
|
+
startTime: startTime || defaultStartTime,
|
|
98
|
+
endTime: endTime || now,
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Check builder fee approval status
|
|
105
|
+
*/
|
|
106
|
+
checkBuilderFeeApproval(builder) {
|
|
107
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
108
|
+
return this.httpClient.info({
|
|
109
|
+
type: constants_1.InfoType.CHECK_BUILDER_FEE_APPROVAL,
|
|
110
|
+
user: this.masterAddress,
|
|
111
|
+
builder,
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Get user fees information
|
|
117
|
+
*/
|
|
118
|
+
getUsersFees() {
|
|
119
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
120
|
+
const res = yield this.httpClient.info({
|
|
121
|
+
type: constants_1.InfoType.USER_FEES,
|
|
122
|
+
user: this.masterAddress,
|
|
123
|
+
});
|
|
124
|
+
// const perpFee = Number(res.userCrossRate) * (1 - Number(res.activeReferralDiscount));
|
|
125
|
+
return res;
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Get user's approved persistent agents
|
|
130
|
+
*/
|
|
131
|
+
extraAgents() {
|
|
132
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
133
|
+
return this.httpClient.info({
|
|
134
|
+
type: constants_1.InfoType.EXTRA_AGENTS,
|
|
135
|
+
user: this.masterAddress,
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
exports.InfoClient = InfoClient;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { HttpClientConfig } from "./http-client";
|
|
2
|
+
export declare class SymbolConversion {
|
|
3
|
+
private assetToIndexMap;
|
|
4
|
+
private httpClient;
|
|
5
|
+
private initialized;
|
|
6
|
+
constructor(config: HttpClientConfig);
|
|
7
|
+
initialize(): Promise<void>;
|
|
8
|
+
private ensureInitialized;
|
|
9
|
+
private refreshAssetMaps;
|
|
10
|
+
getAssetIndex(assetSymbol: string): Promise<number>;
|
|
11
|
+
getAllAssets(): Promise<{
|
|
12
|
+
perp: string[];
|
|
13
|
+
}>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.SymbolConversion = void 0;
|
|
13
|
+
const constants_1 = require("../types/constants");
|
|
14
|
+
const http_client_1 = require("./http-client");
|
|
15
|
+
class SymbolConversion {
|
|
16
|
+
constructor(config) {
|
|
17
|
+
this.assetToIndexMap = new Map();
|
|
18
|
+
this.initialized = false;
|
|
19
|
+
this.httpClient = new http_client_1.HttpClient({
|
|
20
|
+
isTestnet: config.isTestnet,
|
|
21
|
+
timeout: config.timeout,
|
|
22
|
+
});
|
|
23
|
+
this.initialize();
|
|
24
|
+
}
|
|
25
|
+
initialize() {
|
|
26
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
27
|
+
if (this.initialized)
|
|
28
|
+
return;
|
|
29
|
+
try {
|
|
30
|
+
yield this.refreshAssetMaps();
|
|
31
|
+
this.initialized = true;
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
console.error('Failed to initialize SymbolConversion:', error);
|
|
35
|
+
throw error;
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
ensureInitialized() {
|
|
40
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
41
|
+
if (!this.initialized) {
|
|
42
|
+
yield this.initialize();
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
refreshAssetMaps() {
|
|
47
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
48
|
+
try {
|
|
49
|
+
const perpMeta = yield this.httpClient.info({
|
|
50
|
+
type: constants_1.InfoType.META_AND_ASSET_CTXS,
|
|
51
|
+
});
|
|
52
|
+
// Verify responses are valid before proceeding
|
|
53
|
+
if (!perpMeta ||
|
|
54
|
+
!perpMeta[0] ||
|
|
55
|
+
!perpMeta[0].universe ||
|
|
56
|
+
!Array.isArray(perpMeta[0].universe)) {
|
|
57
|
+
throw new Error('Invalid perpetual metadata response');
|
|
58
|
+
}
|
|
59
|
+
this.assetToIndexMap.clear();
|
|
60
|
+
// Handle perpetual assets
|
|
61
|
+
perpMeta[0].universe.forEach((asset, index) => {
|
|
62
|
+
this.assetToIndexMap.set(asset.name, index);
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
throw error;
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
getAssetIndex(assetSymbol) {
|
|
71
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
72
|
+
yield this.ensureInitialized();
|
|
73
|
+
const index = this.assetToIndexMap.get(assetSymbol);
|
|
74
|
+
if (index === undefined) {
|
|
75
|
+
throw new Error(`Unknown asset: ${assetSymbol}`);
|
|
76
|
+
}
|
|
77
|
+
return index;
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
getAllAssets() {
|
|
81
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
82
|
+
yield this.ensureInitialized();
|
|
83
|
+
const perp = [];
|
|
84
|
+
for (const [asset, index] of this.assetToIndexMap.entries()) {
|
|
85
|
+
perp.push(asset);
|
|
86
|
+
}
|
|
87
|
+
return { perp };
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
exports.SymbolConversion = SymbolConversion;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import type { AllMids, L2Book, Candle, WsFill, WsOrder, WebData2 } from '../types';
|
|
2
|
+
import { SymbolConversion } from './symbolConversion';
|
|
3
|
+
export interface WebSocketClientConfig {
|
|
4
|
+
masterAddress: string;
|
|
5
|
+
isTestnet?: boolean;
|
|
6
|
+
autoReconnect?: boolean;
|
|
7
|
+
reconnectDelay?: number;
|
|
8
|
+
maxReconnectAttempts?: number;
|
|
9
|
+
symbolConversion: SymbolConversion;
|
|
10
|
+
}
|
|
11
|
+
export type SubscriptionCallback<T = any> = (data: T) => void;
|
|
12
|
+
export interface Subscription {
|
|
13
|
+
unsubscribe(): void;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* WebSocket client for real-time Hyperliquid data (perpetuals only)
|
|
17
|
+
*/
|
|
18
|
+
export declare class WebSocketClient {
|
|
19
|
+
private ws;
|
|
20
|
+
private readonly url;
|
|
21
|
+
private readonly config;
|
|
22
|
+
private subscriptions;
|
|
23
|
+
private subscriptionId;
|
|
24
|
+
private reconnectAttempts;
|
|
25
|
+
private isConnecting;
|
|
26
|
+
private pendingSubscriptions;
|
|
27
|
+
private symbolConversion;
|
|
28
|
+
constructor(config: WebSocketClientConfig);
|
|
29
|
+
/**
|
|
30
|
+
* Connect to the WebSocket
|
|
31
|
+
*/
|
|
32
|
+
connect(): Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
* Disconnect from the WebSocket
|
|
35
|
+
*/
|
|
36
|
+
disconnect(): void;
|
|
37
|
+
/**
|
|
38
|
+
* Subscribe to a channel
|
|
39
|
+
*/
|
|
40
|
+
private subscribe;
|
|
41
|
+
/**
|
|
42
|
+
* Subscribe to all mid prices
|
|
43
|
+
*/
|
|
44
|
+
subscribeToAllMids(callback: SubscriptionCallback<AllMids>): Subscription;
|
|
45
|
+
/**
|
|
46
|
+
* Subscribe to L2 order book for a specific coin
|
|
47
|
+
*/
|
|
48
|
+
subscribeToL2Book(coin: string, callback: SubscriptionCallback<L2Book>): Subscription;
|
|
49
|
+
/**
|
|
50
|
+
* Subscribe to trades for a specific coin
|
|
51
|
+
*/
|
|
52
|
+
subscribeToTrades(coin: string, callback: SubscriptionCallback<any[]>): Subscription;
|
|
53
|
+
/**
|
|
54
|
+
* Subscribe to candlestick data
|
|
55
|
+
*/
|
|
56
|
+
subscribeToCandles(coin: string, interval: string, callback: SubscriptionCallback<Candle>): Subscription;
|
|
57
|
+
/**
|
|
58
|
+
* Subscribe to user fills
|
|
59
|
+
*/
|
|
60
|
+
subscribeToUserFills(callback: SubscriptionCallback<WsFill[]>): Subscription;
|
|
61
|
+
/**
|
|
62
|
+
* Subscribe to user order updates
|
|
63
|
+
*/
|
|
64
|
+
subscribeToUserOrders(callback: SubscriptionCallback<WsOrder[]>): Subscription;
|
|
65
|
+
/**
|
|
66
|
+
* Subscribe to user funding updates
|
|
67
|
+
*/
|
|
68
|
+
subscribeToUserFunding(callback: SubscriptionCallback<any>): Subscription;
|
|
69
|
+
/**
|
|
70
|
+
* Subscribe to webData2 - comprehensive user data updates
|
|
71
|
+
* Includes positions, margin summary, open orders, and other user data
|
|
72
|
+
*/
|
|
73
|
+
subscribeToWebData2(callback: SubscriptionCallback<WebData2>): Subscription;
|
|
74
|
+
/**
|
|
75
|
+
* Check if WebSocket is connected
|
|
76
|
+
*/
|
|
77
|
+
get isConnected(): boolean;
|
|
78
|
+
/**
|
|
79
|
+
* Get current connection state
|
|
80
|
+
*/
|
|
81
|
+
get readyState(): number;
|
|
82
|
+
}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.WebSocketClient = void 0;
|
|
13
|
+
const constants_1 = require("../types/constants");
|
|
14
|
+
/**
|
|
15
|
+
* WebSocket client for real-time Hyperliquid data (perpetuals only)
|
|
16
|
+
*/
|
|
17
|
+
class WebSocketClient {
|
|
18
|
+
constructor(config) {
|
|
19
|
+
this.ws = null;
|
|
20
|
+
this.subscriptions = new Map();
|
|
21
|
+
this.subscriptionId = 0;
|
|
22
|
+
this.reconnectAttempts = 0;
|
|
23
|
+
this.isConnecting = false;
|
|
24
|
+
this.pendingSubscriptions = [];
|
|
25
|
+
this.config = Object.assign({ isTestnet: false, autoReconnect: true, reconnectDelay: 3000, maxReconnectAttempts: 5 }, config);
|
|
26
|
+
this.url = this.config.isTestnet ? constants_1.WSS_URLS.TESTNET : constants_1.WSS_URLS.PRODUCTION;
|
|
27
|
+
this.symbolConversion = config.symbolConversion;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Connect to the WebSocket
|
|
31
|
+
*/
|
|
32
|
+
connect() {
|
|
33
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
34
|
+
var _a;
|
|
35
|
+
if (((_a = this.ws) === null || _a === void 0 ? void 0 : _a.readyState) === WebSocket.OPEN) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (this.isConnecting) {
|
|
39
|
+
return new Promise((resolve, reject) => {
|
|
40
|
+
const checkConnection = () => {
|
|
41
|
+
var _a;
|
|
42
|
+
if (((_a = this.ws) === null || _a === void 0 ? void 0 : _a.readyState) === WebSocket.OPEN) {
|
|
43
|
+
resolve();
|
|
44
|
+
}
|
|
45
|
+
else if (!this.isConnecting) {
|
|
46
|
+
reject(new Error('Failed to connect'));
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
setTimeout(checkConnection, 100);
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
checkConnection();
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
return new Promise((resolve, reject) => {
|
|
56
|
+
this.isConnecting = true;
|
|
57
|
+
this.ws = new WebSocket(this.url);
|
|
58
|
+
this.ws.onopen = () => {
|
|
59
|
+
this.isConnecting = false;
|
|
60
|
+
this.reconnectAttempts = 0;
|
|
61
|
+
console.log('WebSocket connected');
|
|
62
|
+
// Resubscribe to pending subscriptions
|
|
63
|
+
this.pendingSubscriptions.forEach(({ id, message, callback }) => {
|
|
64
|
+
var _a;
|
|
65
|
+
this.subscriptions.set(id, callback);
|
|
66
|
+
if (((_a = this.ws) === null || _a === void 0 ? void 0 : _a.readyState) === WebSocket.OPEN) {
|
|
67
|
+
this.ws.send(JSON.stringify(message));
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
this.pendingSubscriptions = [];
|
|
71
|
+
resolve();
|
|
72
|
+
};
|
|
73
|
+
this.ws.onmessage = (event) => {
|
|
74
|
+
try {
|
|
75
|
+
const data = JSON.parse(event.data);
|
|
76
|
+
if (data.method === 'subscription') {
|
|
77
|
+
const subscriptionId = data.subscription;
|
|
78
|
+
const callback = this.subscriptions.get(subscriptionId);
|
|
79
|
+
if (callback) {
|
|
80
|
+
callback(data.data);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
console.error('Error parsing WebSocket message:', error);
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
this.ws.onclose = () => {
|
|
89
|
+
this.isConnecting = false;
|
|
90
|
+
console.log('WebSocket disconnected');
|
|
91
|
+
if (this.config.autoReconnect && this.reconnectAttempts < this.config.maxReconnectAttempts) {
|
|
92
|
+
this.reconnectAttempts++;
|
|
93
|
+
console.log(`Reconnecting... (${this.reconnectAttempts}/${this.config.maxReconnectAttempts})`);
|
|
94
|
+
setTimeout(() => this.connect(), this.config.reconnectDelay);
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
this.ws.onerror = (error) => {
|
|
98
|
+
this.isConnecting = false;
|
|
99
|
+
console.error('WebSocket error:', error);
|
|
100
|
+
reject(error);
|
|
101
|
+
};
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Disconnect from the WebSocket
|
|
107
|
+
*/
|
|
108
|
+
disconnect() {
|
|
109
|
+
if (this.ws) {
|
|
110
|
+
this.ws.close();
|
|
111
|
+
this.ws = null;
|
|
112
|
+
}
|
|
113
|
+
this.subscriptions.clear();
|
|
114
|
+
this.pendingSubscriptions = [];
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Subscribe to a channel
|
|
118
|
+
*/
|
|
119
|
+
subscribe(message, callback) {
|
|
120
|
+
var _a;
|
|
121
|
+
const id = ++this.subscriptionId;
|
|
122
|
+
const subscriptionMessage = Object.assign(Object.assign({}, message), { id });
|
|
123
|
+
if (((_a = this.ws) === null || _a === void 0 ? void 0 : _a.readyState) === WebSocket.OPEN) {
|
|
124
|
+
this.subscriptions.set(id, callback);
|
|
125
|
+
this.ws.send(JSON.stringify(Object.assign(Object.assign({}, subscriptionMessage), { method: 'subscribe' })));
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
// Store pending subscription for when connection is established
|
|
129
|
+
this.pendingSubscriptions.push({ id, message: subscriptionMessage, callback });
|
|
130
|
+
// Auto-connect if not connected
|
|
131
|
+
if (!this.isConnecting && (!this.ws || this.ws.readyState === WebSocket.CLOSED)) {
|
|
132
|
+
this.connect().catch(console.error);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return {
|
|
136
|
+
unsubscribe: () => {
|
|
137
|
+
var _a;
|
|
138
|
+
this.subscriptions.delete(id);
|
|
139
|
+
if (((_a = this.ws) === null || _a === void 0 ? void 0 : _a.readyState) === WebSocket.OPEN) {
|
|
140
|
+
this.ws.send(JSON.stringify(Object.assign(Object.assign({}, subscriptionMessage), { method: 'unsubscribe' })));
|
|
141
|
+
}
|
|
142
|
+
// Remove from pending subscriptions
|
|
143
|
+
this.pendingSubscriptions = this.pendingSubscriptions.filter(sub => sub.id !== id);
|
|
144
|
+
},
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Subscribe to all mid prices
|
|
149
|
+
*/
|
|
150
|
+
subscribeToAllMids(callback) {
|
|
151
|
+
return this.subscribe({
|
|
152
|
+
subscription: { type: 'allMids' },
|
|
153
|
+
}, callback);
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Subscribe to L2 order book for a specific coin
|
|
157
|
+
*/
|
|
158
|
+
subscribeToL2Book(coin, callback) {
|
|
159
|
+
return this.subscribe({
|
|
160
|
+
subscription: { type: 'l2Book', coin },
|
|
161
|
+
}, callback);
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Subscribe to trades for a specific coin
|
|
165
|
+
*/
|
|
166
|
+
subscribeToTrades(coin, callback) {
|
|
167
|
+
return this.subscribe({
|
|
168
|
+
subscription: { type: 'trades', coin },
|
|
169
|
+
}, callback);
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Subscribe to candlestick data
|
|
173
|
+
*/
|
|
174
|
+
subscribeToCandles(coin, interval, callback) {
|
|
175
|
+
return this.subscribe({
|
|
176
|
+
subscription: { type: 'candle', coin, interval },
|
|
177
|
+
}, callback);
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Subscribe to user fills
|
|
181
|
+
*/
|
|
182
|
+
subscribeToUserFills(callback) {
|
|
183
|
+
return this.subscribe({
|
|
184
|
+
subscription: { type: 'userFills', user: this.config.masterAddress },
|
|
185
|
+
}, callback);
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Subscribe to user order updates
|
|
189
|
+
*/
|
|
190
|
+
subscribeToUserOrders(callback) {
|
|
191
|
+
return this.subscribe({
|
|
192
|
+
subscription: { type: 'userEvents', user: this.config.masterAddress },
|
|
193
|
+
}, callback);
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Subscribe to user funding updates
|
|
197
|
+
*/
|
|
198
|
+
subscribeToUserFunding(callback) {
|
|
199
|
+
return this.subscribe({
|
|
200
|
+
subscription: { type: 'userFundings', user: this.config.masterAddress },
|
|
201
|
+
}, callback);
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Subscribe to webData2 - comprehensive user data updates
|
|
205
|
+
* Includes positions, margin summary, open orders, and other user data
|
|
206
|
+
*/
|
|
207
|
+
subscribeToWebData2(callback) {
|
|
208
|
+
return this.subscribe({
|
|
209
|
+
subscription: { type: 'webData2', user: this.config.masterAddress },
|
|
210
|
+
}, callback);
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Check if WebSocket is connected
|
|
214
|
+
*/
|
|
215
|
+
get isConnected() {
|
|
216
|
+
var _a;
|
|
217
|
+
return ((_a = this.ws) === null || _a === void 0 ? void 0 : _a.readyState) === WebSocket.OPEN;
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Get current connection state
|
|
221
|
+
*/
|
|
222
|
+
get readyState() {
|
|
223
|
+
var _a, _b;
|
|
224
|
+
return (_b = (_a = this.ws) === null || _a === void 0 ? void 0 : _a.readyState) !== null && _b !== void 0 ? _b : WebSocket.CLOSED;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
exports.WebSocketClient = WebSocketClient;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { InfoClient } from './client/info-client';
|
|
2
|
+
import { ExchangeClient } from './client/exchange-client';
|
|
3
|
+
import type { ClearinghouseState } from './types';
|
|
4
|
+
import { WebSocketClient, WebSocketClientConfig } from './client/websocket-client';
|
|
5
|
+
import { SymbolConversion } from './client/symbolConversion';
|
|
6
|
+
export interface HyperliquidSDKConfig {
|
|
7
|
+
masterAddress: string;
|
|
8
|
+
agentPrivateKey?: string;
|
|
9
|
+
agentPublicKey?: string;
|
|
10
|
+
agentName?: string;
|
|
11
|
+
isTestnet?: boolean;
|
|
12
|
+
timeout?: number;
|
|
13
|
+
wsConfig?: WebSocketClientConfig;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Main Hyperliquid SDK class for perpetuals trading
|
|
17
|
+
* Simplified version with only essential APIs
|
|
18
|
+
* if use exchange api, must provide agentPrivateKey, agentPublicKey, agentName
|
|
19
|
+
*/
|
|
20
|
+
export declare class HyperliquidSDK {
|
|
21
|
+
readonly info: InfoClient;
|
|
22
|
+
exchange?: ExchangeClient;
|
|
23
|
+
symbolConversion: SymbolConversion;
|
|
24
|
+
readonly ws: WebSocketClient;
|
|
25
|
+
private readonly masterAddress;
|
|
26
|
+
private readonly configParams;
|
|
27
|
+
constructor(config: HyperliquidSDKConfig);
|
|
28
|
+
/**
|
|
29
|
+
* Get wallet address (only available if private key was provided)
|
|
30
|
+
*/
|
|
31
|
+
get address(): string;
|
|
32
|
+
updateExchangeAgent(agentPrivateKey: string, agentPublicKey: string, agentName: string): void;
|
|
33
|
+
/**
|
|
34
|
+
* Connect to WebSocket for real-time data
|
|
35
|
+
*/
|
|
36
|
+
connectWebSocket(): Promise<void>;
|
|
37
|
+
/**
|
|
38
|
+
* Disconnect from WebSocket
|
|
39
|
+
*/
|
|
40
|
+
disconnectWebSocket(): void;
|
|
41
|
+
/**
|
|
42
|
+
* Check if WebSocket is connected
|
|
43
|
+
*/
|
|
44
|
+
get isWebSocketConnected(): boolean;
|
|
45
|
+
/**
|
|
46
|
+
* Quick helper: Get account summary with essential info
|
|
47
|
+
*/
|
|
48
|
+
getAccountSummary(): Promise<ClearinghouseState>;
|
|
49
|
+
/**
|
|
50
|
+
* Quick helper: Get market overview
|
|
51
|
+
*/
|
|
52
|
+
getMarketOverview(): Promise<any>;
|
|
53
|
+
}
|