@pear-protocol/exchanges-sdk 0.0.10 → 0.0.12
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 +59 -42
- package/dist/account/account-manager.d.ts +5 -11
- package/dist/account/account-manager.js +22 -60
- package/dist/account/exchange-account.d.ts +8 -10
- package/dist/account/exchange-account.js +30 -57
- package/dist/account/exchanges/base.d.ts +13 -15
- package/dist/account/exchanges/base.js +5 -27
- package/dist/account/exchanges/binance/asset-tracker.d.ts +25 -0
- package/dist/account/exchanges/binance/asset-tracker.js +38 -0
- package/dist/account/exchanges/binance/mapper.d.ts +4 -3
- package/dist/account/exchanges/binance/mapper.js +0 -1
- package/dist/account/exchanges/binance/orchestrator.d.ts +9 -12
- package/dist/account/exchanges/binance/orchestrator.js +61 -183
- package/dist/account/exchanges/binance/rest.d.ts +5 -4
- package/dist/account/exchanges/binance/rest.js +4 -20
- package/dist/account/exchanges/binance/state-handler.d.ts +32 -0
- package/dist/account/exchanges/binance/state-handler.js +113 -0
- package/dist/account/exchanges/binance/types.d.ts +3 -76
- package/dist/account/exchanges/binance/types.js +6 -0
- package/dist/account/exchanges/binance/ws.d.ts +3 -2
- package/dist/account/exchanges/binance/ws.js +6 -22
- package/dist/account/exchanges/bybit/asset-tracker.d.ts +25 -0
- package/dist/account/exchanges/bybit/asset-tracker.js +37 -0
- package/dist/account/exchanges/bybit/mapper.d.ts +4 -3
- package/dist/account/exchanges/bybit/mapper.js +5 -3
- package/dist/account/exchanges/bybit/orchestrator.d.ts +11 -12
- package/dist/account/exchanges/bybit/orchestrator.js +48 -134
- package/dist/account/exchanges/bybit/rest.d.ts +2 -3
- package/dist/account/exchanges/bybit/rest.js +4 -39
- package/dist/account/exchanges/bybit/state-handler.d.ts +22 -0
- package/dist/account/exchanges/bybit/state-handler.js +70 -0
- package/dist/account/exchanges/bybit/types.d.ts +14 -3
- package/dist/account/exchanges/bybit/types.js +7 -0
- package/dist/account/exchanges/bybit/ws.d.ts +1 -0
- package/dist/account/exchanges/bybit/ws.js +21 -12
- package/dist/account/exchanges/hyperliquid/asset-tracker.d.ts +34 -0
- package/dist/account/exchanges/hyperliquid/asset-tracker.js +83 -0
- package/dist/account/exchanges/hyperliquid/mapper.d.ts +4 -4
- package/dist/account/exchanges/hyperliquid/mapper.js +1 -0
- package/dist/account/exchanges/hyperliquid/orchestrator.d.ts +15 -28
- package/dist/account/exchanges/hyperliquid/orchestrator.js +79 -216
- package/dist/account/exchanges/hyperliquid/state-handler.d.ts +24 -0
- package/dist/account/exchanges/hyperliquid/state-handler.js +104 -0
- package/dist/account/exchanges/hyperliquid/types.d.ts +119 -5
- package/dist/account/exchanges/hyperliquid/types.js +9 -1
- package/dist/account/exchanges/index.d.ts +7 -5
- package/dist/account/exchanges/index.js +12 -4
- package/dist/account/index.d.ts +3 -1
- package/dist/account/types.d.ts +4 -73
- package/dist/account/types.js +17 -0
- package/dist/account/utils.d.ts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/types-D2dbAtin.d.ts +150 -0
- package/dist/utils/hmac.d.ts +1 -2
- package/dist/utils/hmac.js +1 -8
- package/dist/utils/ws.d.ts +6 -3
- package/dist/utils/ws.js +24 -7
- package/package.json +5 -5
- package/dist/account/exchanges/hyperliquid/rest.d.ts +0 -6
- package/dist/account/exchanges/hyperliquid/rest.js +0 -11
|
@@ -1,238 +1,101 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createWs, waitForOpen, sendWs } from '../../../utils/ws';
|
|
2
2
|
import { BaseOrchestrator } from '../base';
|
|
3
3
|
import { LOCKED_TRACKED_COINS } from './const';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { COLLATERAL_TOKEN_MAP } from './types';
|
|
4
|
+
import { HyperliquidStateHandler } from './state-handler';
|
|
5
|
+
import { HyperliquidAssetTracker } from './asset-tracker';
|
|
7
6
|
|
|
7
|
+
const HL_WS_URL = "wss://api.hyperliquid.xyz/ws";
|
|
8
|
+
const HL_INFO_URL = "https://api.hyperliquid.xyz/info";
|
|
8
9
|
class HyperliquidOrchestrator extends BaseOrchestrator {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
infoClient = null;
|
|
16
|
-
subsClient = null;
|
|
17
|
-
subscriptions = [];
|
|
18
|
-
address = null;
|
|
19
|
-
activeAssetSubscriptions = /* @__PURE__ */ new Map();
|
|
20
|
-
trackedAssetData = /* @__PURE__ */ new Map();
|
|
21
|
-
spotCoinBalances = /* @__PURE__ */ new Map();
|
|
22
|
-
accountType = "disabled";
|
|
23
|
-
symbolToCollateralToken = /* @__PURE__ */ new Map();
|
|
24
|
-
availableToTradeByCollateral = /* @__PURE__ */ new Map();
|
|
25
|
-
lastSummary = {
|
|
26
|
-
accountValue: 0,
|
|
27
|
-
totalMarginUsed: 0,
|
|
28
|
-
totalRawUsd: 0,
|
|
29
|
-
crossMaintenanceMarginUsed: 0,
|
|
30
|
-
withdrawable: 0,
|
|
31
|
-
totalUnrealizedPnl: 0
|
|
32
|
-
};
|
|
33
|
-
async start(credentials) {
|
|
34
|
-
const gen = ++this.startGeneration;
|
|
35
|
-
this.manualClose = false;
|
|
36
|
-
this.credentials = credentials;
|
|
10
|
+
ws = null;
|
|
11
|
+
address;
|
|
12
|
+
stateHandler;
|
|
13
|
+
assetTracker;
|
|
14
|
+
constructor(config, credentials) {
|
|
15
|
+
super(config);
|
|
37
16
|
const creds = credentials;
|
|
17
|
+
this.credentials = credentials;
|
|
38
18
|
this.address = creds.address;
|
|
39
|
-
|
|
40
|
-
this.
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
await this.fetchPerpMetas();
|
|
47
|
-
if (gen !== this.startGeneration) return;
|
|
48
|
-
this.subsClient = new SubscriptionClient({ transport: HyperliquidOrchestrator.wsTransport });
|
|
49
|
-
const subs = [];
|
|
50
|
-
subs.push(
|
|
51
|
-
this.subsClient.allDexsClearinghouseState(
|
|
52
|
-
{ user: this.address },
|
|
53
|
-
(data) => this.handleClearinghouseState(data)
|
|
54
|
-
)
|
|
55
|
-
);
|
|
56
|
-
subs.push(this.subsClient.spotState({ user: this.address }, (data) => this.handleSpotState(data)));
|
|
57
|
-
subs.push(this.subsClient.webData3({ user: this.address }, (data) => this.handleWebData3(data)));
|
|
58
|
-
this.subscriptions = await Promise.all(subs);
|
|
59
|
-
if (gen !== this.startGeneration) return;
|
|
60
|
-
for (const sub of this.subscriptions) {
|
|
61
|
-
sub.failureSignal.addEventListener("abort", () => {
|
|
62
|
-
if (!this.manualClose) {
|
|
63
|
-
this.onError(new Error("Hyperliquid subscription failed after reconnect"));
|
|
64
|
-
}
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
for (const coin of LOCKED_TRACKED_COINS) {
|
|
68
|
-
this.trackAsset(coin);
|
|
69
|
-
}
|
|
70
|
-
for (const coin of this.trackedCoins) {
|
|
71
|
-
if (!LOCKED_TRACKED_COINS.includes(coin)) {
|
|
72
|
-
await this.subscribeActiveAssetData(coin);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
this.reconnectAttempts = 0;
|
|
76
|
-
} catch (err) {
|
|
77
|
-
if (gen !== this.startGeneration) return;
|
|
78
|
-
await this.stopAll();
|
|
79
|
-
this.onError(err instanceof Error ? err : new Error(String(err)));
|
|
80
|
-
this.scheduleReconnect();
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
stop() {
|
|
84
|
-
this.manualClose = true;
|
|
85
|
-
this.stopAll();
|
|
86
|
-
this.credentials = null;
|
|
87
|
-
this.address = null;
|
|
88
|
-
}
|
|
89
|
-
get isConnected() {
|
|
90
|
-
return this.subsClient !== null && !this.manualClose;
|
|
91
|
-
}
|
|
92
|
-
onAssetTracked(coin) {
|
|
93
|
-
this.subscribeActiveAssetData(coin).catch((err) => {
|
|
94
|
-
this.onError(err instanceof Error ? err : new Error(String(err)));
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
|
-
onAssetUntracked(coin) {
|
|
98
|
-
const sub = this.activeAssetSubscriptions.get(coin);
|
|
99
|
-
if (sub) {
|
|
100
|
-
sub.unsubscribe().catch(() => {
|
|
101
|
-
});
|
|
102
|
-
this.activeAssetSubscriptions.delete(coin);
|
|
103
|
-
}
|
|
104
|
-
this.trackedAssetData.delete(coin);
|
|
105
|
-
const trackedAssets = this.buildTrackedAssetsMap();
|
|
106
|
-
this.onStateUpdate({ trackedAssets });
|
|
107
|
-
}
|
|
108
|
-
async setLeverage(id, leverage) {
|
|
109
|
-
const creds = this.credentials;
|
|
110
|
-
if (!creds) throw new Error("Not connected");
|
|
111
|
-
const asset = Number.parseInt(id, 10);
|
|
112
|
-
if (Number.isNaN(asset)) throw new Error(`Invalid Hyperliquid asset index: ${id}`);
|
|
113
|
-
const tracked = this.trackedAssetData.get(id);
|
|
114
|
-
const isCross = tracked?.leverage?.type === "cross";
|
|
115
|
-
await setLeverage(creds, asset, Number.parseFloat(leverage), isCross);
|
|
116
|
-
}
|
|
117
|
-
canUntrackAsset(coin) {
|
|
118
|
-
return !LOCKED_TRACKED_COINS.includes(coin);
|
|
119
|
-
}
|
|
120
|
-
async fetchPerpMetas() {
|
|
121
|
-
if (!this.infoClient) return;
|
|
122
|
-
const allMetas = await this.infoClient.allPerpMetas();
|
|
123
|
-
allMetas.forEach((dexMeta) => {
|
|
124
|
-
const collateralToken = COLLATERAL_TOKEN_MAP[dexMeta.collateralToken];
|
|
125
|
-
dexMeta.universe.forEach((asset) => {
|
|
126
|
-
if (!asset.name) return;
|
|
127
|
-
if (collateralToken && !this.symbolToCollateralToken.has(asset.name)) {
|
|
128
|
-
this.symbolToCollateralToken.set(asset.name, collateralToken);
|
|
129
|
-
}
|
|
130
|
-
});
|
|
19
|
+
this.stateHandler = new HyperliquidStateHandler((update) => this.onStateUpdate(update));
|
|
20
|
+
this.assetTracker = new HyperliquidAssetTracker({
|
|
21
|
+
onStateUpdate: (update) => this.onStateUpdate(update),
|
|
22
|
+
onActiveAssetData: (data) => this.stateHandler.handleActiveAssetData(data),
|
|
23
|
+
getWs: () => this.ws,
|
|
24
|
+
getAddress: () => this.address,
|
|
25
|
+
isStopped: () => this.stopped
|
|
131
26
|
});
|
|
132
27
|
}
|
|
133
|
-
async
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
sub.failureSignal.addEventListener("abort", () => {
|
|
141
|
-
if (!this.manualClose) {
|
|
142
|
-
this.activeAssetSubscriptions.delete(coin);
|
|
143
|
-
}
|
|
28
|
+
async initAsync() {
|
|
29
|
+
const allMetas = await this.fetchInfo({ type: "allPerpMetas" });
|
|
30
|
+
this.stateHandler.loadPerpMetas(allMetas);
|
|
31
|
+
this.ws = createWs(HL_WS_URL);
|
|
32
|
+
await waitForOpen(this.ws);
|
|
33
|
+
this.ws.addEventListener("message", (event) => {
|
|
34
|
+
this.handleMessage(event.data);
|
|
144
35
|
});
|
|
145
|
-
this.
|
|
36
|
+
const userAddr = this.address.toLowerCase();
|
|
37
|
+
this.subscribe({ type: "allDexsClearinghouseState", user: userAddr });
|
|
38
|
+
this.subscribe({ type: "spotState", user: userAddr });
|
|
39
|
+
this.subscribe({ type: "webData3", user: userAddr });
|
|
40
|
+
for (const coin of LOCKED_TRACKED_COINS) {
|
|
41
|
+
this.trackAsset(coin);
|
|
42
|
+
}
|
|
43
|
+
this.assetTracker.subscribeAll(this.trackedCoins);
|
|
146
44
|
}
|
|
147
|
-
|
|
148
|
-
this.
|
|
149
|
-
const assetUnsubs = Array.from(this.activeAssetSubscriptions.values()).map((s) => s.unsubscribe().catch(() => {
|
|
150
|
-
}));
|
|
151
|
-
this.activeAssetSubscriptions.clear();
|
|
152
|
-
const unsubs = this.subscriptions.map((s) => s.unsubscribe().catch(() => {
|
|
153
|
-
}));
|
|
154
|
-
this.subscriptions = [];
|
|
155
|
-
await Promise.all([...unsubs, ...assetUnsubs]);
|
|
156
|
-
this.subsClient = null;
|
|
157
|
-
this.infoClient = null;
|
|
45
|
+
subscribe(subscription) {
|
|
46
|
+
sendWs(this.ws, { method: "subscribe", subscription });
|
|
158
47
|
}
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
for (const ap of allAssetPositions) {
|
|
179
|
-
const coin = ap.position.coin;
|
|
180
|
-
if (coin && ap.position.leverage?.value) {
|
|
181
|
-
leverageSettings.set(coin, ap.position.leverage.value.toString());
|
|
48
|
+
handleMessage(raw) {
|
|
49
|
+
try {
|
|
50
|
+
const text = typeof raw === "string" ? raw : void 0;
|
|
51
|
+
if (!text) return;
|
|
52
|
+
const msg = JSON.parse(text);
|
|
53
|
+
if (!msg.channel || !msg.data) return;
|
|
54
|
+
switch (msg.channel) {
|
|
55
|
+
case "allDexsClearinghouseState":
|
|
56
|
+
this.stateHandler.handleClearinghouseState(msg.data);
|
|
57
|
+
break;
|
|
58
|
+
case "spotState":
|
|
59
|
+
this.stateHandler.handleSpotState(msg.data);
|
|
60
|
+
break;
|
|
61
|
+
case "webData3":
|
|
62
|
+
this.stateHandler.handleWebData3(msg.data);
|
|
63
|
+
break;
|
|
64
|
+
case "activeAssetData":
|
|
65
|
+
this.assetTracker.handleActiveAssetDataMessage(msg.data);
|
|
66
|
+
break;
|
|
182
67
|
}
|
|
68
|
+
} catch {
|
|
183
69
|
}
|
|
184
|
-
this.onStateUpdate({ balance, positions, leverageSettings });
|
|
185
70
|
}
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
this.availableToTradeByCollateral.set(collateral, minAvailable);
|
|
195
|
-
const balance = this.buildBalance();
|
|
196
|
-
this.onStateUpdate({ balance });
|
|
197
|
-
}
|
|
198
|
-
const trackedAssets = /* @__PURE__ */ new Map();
|
|
199
|
-
trackedAssets.set(data.coin, this.buildTrackedAssetInfo(data));
|
|
200
|
-
this.onStateUpdate({ trackedAssets });
|
|
71
|
+
async fetchInfo(body) {
|
|
72
|
+
const res = await fetch(HL_INFO_URL, {
|
|
73
|
+
method: "POST",
|
|
74
|
+
headers: { "Content-Type": "application/json" },
|
|
75
|
+
body: JSON.stringify(body)
|
|
76
|
+
});
|
|
77
|
+
if (!res.ok) throw new Error(`Hyperliquid info request failed: ${res.status}`);
|
|
78
|
+
return res.json();
|
|
201
79
|
}
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
leverage: (data.leverage?.value ?? 1).toString(),
|
|
206
|
-
marginType: data.leverage?.type === "isolated" ? "isolated" : "cross"
|
|
207
|
-
};
|
|
80
|
+
cleanupConnections() {
|
|
81
|
+
this.ws?.close();
|
|
82
|
+
this.ws = null;
|
|
208
83
|
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
result.set(coin, this.buildTrackedAssetInfo(data));
|
|
213
|
-
}
|
|
214
|
-
return result;
|
|
84
|
+
async stop() {
|
|
85
|
+
this.stopped = true;
|
|
86
|
+
this.cleanupConnections();
|
|
215
87
|
}
|
|
216
|
-
|
|
217
|
-
return
|
|
88
|
+
get isConnected() {
|
|
89
|
+
return this.ws !== null && !this.stopped;
|
|
218
90
|
}
|
|
219
|
-
|
|
220
|
-
this.
|
|
91
|
+
onAssetTracked(coin) {
|
|
92
|
+
this.assetTracker.onAssetTracked(coin);
|
|
221
93
|
}
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
const hold = Number.parseFloat(b.hold || "0");
|
|
228
|
-
if (total !== 0 || hold !== 0) {
|
|
229
|
-
this.spotCoinBalances.set(b.coin, { coin: b.coin, total, hold });
|
|
230
|
-
} else {
|
|
231
|
-
this.spotCoinBalances.delete(b.coin);
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
const balance = this.buildBalance();
|
|
235
|
-
this.onStateUpdate({ balance });
|
|
94
|
+
onAssetUntracked(coin) {
|
|
95
|
+
this.assetTracker.onAssetUntracked(coin);
|
|
96
|
+
}
|
|
97
|
+
canUntrackAsset(coin) {
|
|
98
|
+
return this.assetTracker.canUntrack(coin);
|
|
236
99
|
}
|
|
237
100
|
}
|
|
238
101
|
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { S as StateUpdate, h as TrackedAssetInfo } from '../../../types-D2dbAtin.js';
|
|
2
|
+
import { AllPerpMetasResponse, AllDexsClearinghouseStateEvent, ActiveAssetDataEvent, WebData3Event, SpotStateEvent } from './types.js';
|
|
3
|
+
import '@pear-protocol/types';
|
|
4
|
+
import '../bybit/types.js';
|
|
5
|
+
|
|
6
|
+
type OnStateUpdate = (update: StateUpdate) => void;
|
|
7
|
+
declare class HyperliquidStateHandler {
|
|
8
|
+
private onStateUpdate;
|
|
9
|
+
private lastSummary;
|
|
10
|
+
private spotCoinBalances;
|
|
11
|
+
private accountType;
|
|
12
|
+
private symbolToCollateralToken;
|
|
13
|
+
private availableToTradeByCollateral;
|
|
14
|
+
constructor(onStateUpdate: OnStateUpdate);
|
|
15
|
+
loadPerpMetas(allMetas: AllPerpMetasResponse): void;
|
|
16
|
+
handleClearinghouseState(data: AllDexsClearinghouseStateEvent): void;
|
|
17
|
+
handleActiveAssetData(data: ActiveAssetDataEvent): void;
|
|
18
|
+
handleWebData3(data: WebData3Event): void;
|
|
19
|
+
handleSpotState(data: SpotStateEvent): void;
|
|
20
|
+
private buildBalance;
|
|
21
|
+
}
|
|
22
|
+
declare function buildTrackedAssetInfo(data: ActiveAssetDataEvent): TrackedAssetInfo;
|
|
23
|
+
|
|
24
|
+
export { HyperliquidStateHandler, buildTrackedAssetInfo };
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { mapPositions, mapBalance } from './mapper';
|
|
2
|
+
import { COLLATERAL_TOKEN_MAP } from './types';
|
|
3
|
+
|
|
4
|
+
class HyperliquidStateHandler {
|
|
5
|
+
onStateUpdate;
|
|
6
|
+
lastSummary = {
|
|
7
|
+
accountValue: 0,
|
|
8
|
+
totalMarginUsed: 0,
|
|
9
|
+
totalRawUsd: 0,
|
|
10
|
+
crossMaintenanceMarginUsed: 0,
|
|
11
|
+
withdrawable: 0,
|
|
12
|
+
totalUnrealizedPnl: 0
|
|
13
|
+
};
|
|
14
|
+
spotCoinBalances = /* @__PURE__ */ new Map();
|
|
15
|
+
accountType = null;
|
|
16
|
+
symbolToCollateralToken = /* @__PURE__ */ new Map();
|
|
17
|
+
availableToTradeByCollateral = /* @__PURE__ */ new Map();
|
|
18
|
+
constructor(onStateUpdate) {
|
|
19
|
+
this.onStateUpdate = onStateUpdate;
|
|
20
|
+
}
|
|
21
|
+
loadPerpMetas(allMetas) {
|
|
22
|
+
allMetas.forEach((dexMeta) => {
|
|
23
|
+
const collateralToken = COLLATERAL_TOKEN_MAP[dexMeta.collateralToken];
|
|
24
|
+
dexMeta.universe.forEach((asset) => {
|
|
25
|
+
if (!asset.name) return;
|
|
26
|
+
if (collateralToken && !this.symbolToCollateralToken.has(asset.name)) {
|
|
27
|
+
this.symbolToCollateralToken.set(asset.name, collateralToken);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
handleClearinghouseState(data) {
|
|
33
|
+
const states = (data.clearinghouseStates || []).map(([, s]) => s).filter(Boolean);
|
|
34
|
+
const sumStr = (values) => values.reduce((acc, v) => acc + (Number.parseFloat(v || "0") || 0), 0);
|
|
35
|
+
const allAssetPositions = states.flatMap((s) => s.assetPositions || []);
|
|
36
|
+
const totalUnrealizedPnl = allAssetPositions.reduce(
|
|
37
|
+
(acc, ap) => acc + (Number.parseFloat(ap.position.unrealizedPnl || "0") || 0),
|
|
38
|
+
0
|
|
39
|
+
);
|
|
40
|
+
this.lastSummary = {
|
|
41
|
+
accountValue: sumStr(states.map((s) => s.crossMarginSummary.accountValue)),
|
|
42
|
+
totalMarginUsed: sumStr(states.map((s) => s.crossMarginSummary.totalMarginUsed)),
|
|
43
|
+
totalRawUsd: sumStr(states.map((s) => s.crossMarginSummary.totalRawUsd)),
|
|
44
|
+
crossMaintenanceMarginUsed: sumStr(states.map((s) => s.crossMaintenanceMarginUsed)),
|
|
45
|
+
withdrawable: sumStr(states.map((s) => s.withdrawable)),
|
|
46
|
+
totalUnrealizedPnl
|
|
47
|
+
};
|
|
48
|
+
const balance = this.buildBalance();
|
|
49
|
+
const positions = mapPositions(allAssetPositions);
|
|
50
|
+
const leverageSettings = /* @__PURE__ */ new Map();
|
|
51
|
+
for (const ap of allAssetPositions) {
|
|
52
|
+
const coin = ap.position.coin;
|
|
53
|
+
if (coin && ap.position.leverage?.value) {
|
|
54
|
+
leverageSettings.set(coin, ap.position.leverage.value.toString());
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
this.onStateUpdate({ balance: balance ?? void 0, positions, leverageSettings });
|
|
58
|
+
}
|
|
59
|
+
handleActiveAssetData(data) {
|
|
60
|
+
if (!data.coin) return;
|
|
61
|
+
const collateral = this.symbolToCollateralToken.get(data.coin);
|
|
62
|
+
if (collateral && data.availableToTrade) {
|
|
63
|
+
const long = Number.parseFloat(data.availableToTrade[0] || "0");
|
|
64
|
+
const short = Number.parseFloat(data.availableToTrade[1] || "0");
|
|
65
|
+
const minAvailable = Math.min(long, short);
|
|
66
|
+
this.availableToTradeByCollateral.set(collateral, minAvailable);
|
|
67
|
+
const balance = this.buildBalance();
|
|
68
|
+
if (balance) this.onStateUpdate({ balance });
|
|
69
|
+
}
|
|
70
|
+
const trackedAssets = /* @__PURE__ */ new Map();
|
|
71
|
+
trackedAssets.set(data.coin, buildTrackedAssetInfo(data));
|
|
72
|
+
this.onStateUpdate({ trackedAssets });
|
|
73
|
+
}
|
|
74
|
+
handleWebData3(data) {
|
|
75
|
+
this.accountType = data.userState.abstraction ?? null;
|
|
76
|
+
}
|
|
77
|
+
handleSpotState(data) {
|
|
78
|
+
const balances = data?.spotState?.balances;
|
|
79
|
+
if (!balances) return;
|
|
80
|
+
for (const b of balances) {
|
|
81
|
+
const total = Number.parseFloat(b.total || "0");
|
|
82
|
+
const hold = Number.parseFloat(b.hold || "0");
|
|
83
|
+
if (total !== 0 || hold !== 0) {
|
|
84
|
+
this.spotCoinBalances.set(b.coin, { coin: b.coin, total, hold });
|
|
85
|
+
} else {
|
|
86
|
+
this.spotCoinBalances.delete(b.coin);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
const balance = this.buildBalance();
|
|
90
|
+
if (balance) this.onStateUpdate({ balance });
|
|
91
|
+
}
|
|
92
|
+
buildBalance() {
|
|
93
|
+
return mapBalance(this.lastSummary, this.spotCoinBalances, this.accountType, this.availableToTradeByCollateral);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
function buildTrackedAssetInfo(data) {
|
|
97
|
+
return {
|
|
98
|
+
coin: data.coin,
|
|
99
|
+
leverage: (data.leverage?.value ?? 1).toString(),
|
|
100
|
+
marginType: data.leverage?.type === "isolated" ? "isolated" : "cross"
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export { HyperliquidStateHandler, buildTrackedAssetInfo };
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
declare enum HyperliquidAccountType {
|
|
2
|
+
DEFAULT = "default",
|
|
3
|
+
DEX_ABSTRACTION = "dexAbstraction",
|
|
4
|
+
DISABLED = "disabled",
|
|
5
|
+
PORTFOLIO_MARGIN = "portfolioMargin",
|
|
6
|
+
UNIFIED_ACCOUNT = "unifiedAccount"
|
|
7
|
+
}
|
|
5
8
|
interface HyperliquidCoinBalance {
|
|
6
9
|
coin: string;
|
|
7
10
|
total: number;
|
|
@@ -16,5 +19,116 @@ interface AggregatedClearinghouseSummary {
|
|
|
16
19
|
totalUnrealizedPnl: number;
|
|
17
20
|
}
|
|
18
21
|
declare const COLLATERAL_TOKEN_MAP: Record<number, string>;
|
|
22
|
+
type MetaResponse = {
|
|
23
|
+
universe: {
|
|
24
|
+
szDecimals: number;
|
|
25
|
+
name: string;
|
|
26
|
+
maxLeverage: number;
|
|
27
|
+
marginTableId: number;
|
|
28
|
+
onlyIsolated?: true;
|
|
29
|
+
isDelisted?: true;
|
|
30
|
+
}[];
|
|
31
|
+
marginTables: [
|
|
32
|
+
id: number,
|
|
33
|
+
table: {
|
|
34
|
+
description: string;
|
|
35
|
+
marginTiers: {
|
|
36
|
+
lowerBound: string;
|
|
37
|
+
maxLeverage: number;
|
|
38
|
+
}[];
|
|
39
|
+
}
|
|
40
|
+
][];
|
|
41
|
+
collateralToken: number;
|
|
42
|
+
};
|
|
43
|
+
type AllPerpMetasResponse = MetaResponse[];
|
|
44
|
+
type LeverageInfo = {
|
|
45
|
+
type: 'isolated';
|
|
46
|
+
value: number;
|
|
47
|
+
rawUsd: string;
|
|
48
|
+
} | {
|
|
49
|
+
type: 'cross';
|
|
50
|
+
value: number;
|
|
51
|
+
};
|
|
52
|
+
type ClearinghouseStateResponse = {
|
|
53
|
+
marginSummary: {
|
|
54
|
+
accountValue: string;
|
|
55
|
+
totalNtlPos: string;
|
|
56
|
+
totalRawUsd: string;
|
|
57
|
+
totalMarginUsed: string;
|
|
58
|
+
};
|
|
59
|
+
crossMarginSummary: {
|
|
60
|
+
accountValue: string;
|
|
61
|
+
totalNtlPos: string;
|
|
62
|
+
totalRawUsd: string;
|
|
63
|
+
totalMarginUsed: string;
|
|
64
|
+
};
|
|
65
|
+
crossMaintenanceMarginUsed: string;
|
|
66
|
+
withdrawable: string;
|
|
67
|
+
assetPositions: {
|
|
68
|
+
type: 'oneWay';
|
|
69
|
+
position: {
|
|
70
|
+
coin: string;
|
|
71
|
+
szi: string;
|
|
72
|
+
leverage: LeverageInfo;
|
|
73
|
+
entryPx: string;
|
|
74
|
+
positionValue: string;
|
|
75
|
+
unrealizedPnl: string;
|
|
76
|
+
returnOnEquity: string;
|
|
77
|
+
liquidationPx: string | null;
|
|
78
|
+
marginUsed: string;
|
|
79
|
+
maxLeverage: number;
|
|
80
|
+
cumFunding: {
|
|
81
|
+
allTime: string;
|
|
82
|
+
sinceOpen: string;
|
|
83
|
+
sinceChange: string;
|
|
84
|
+
};
|
|
85
|
+
};
|
|
86
|
+
}[];
|
|
87
|
+
time: number;
|
|
88
|
+
};
|
|
89
|
+
type AssetPosition = ClearinghouseStateResponse['assetPositions'][number];
|
|
90
|
+
type AllDexsClearinghouseStateEvent = {
|
|
91
|
+
user: `0x${string}`;
|
|
92
|
+
clearinghouseStates: [dex: string, state: ClearinghouseStateResponse][];
|
|
93
|
+
};
|
|
94
|
+
type ActiveAssetDataEvent = {
|
|
95
|
+
user: `0x${string}`;
|
|
96
|
+
coin: string;
|
|
97
|
+
leverage: LeverageInfo;
|
|
98
|
+
maxTradeSzs: [min: string, max: string];
|
|
99
|
+
availableToTrade: [min: string, max: string];
|
|
100
|
+
markPx: string;
|
|
101
|
+
};
|
|
102
|
+
type SpotClearinghouseStateResponse = {
|
|
103
|
+
balances: {
|
|
104
|
+
coin: string;
|
|
105
|
+
token: number;
|
|
106
|
+
total: string;
|
|
107
|
+
hold: string;
|
|
108
|
+
entryNtl: string;
|
|
109
|
+
}[];
|
|
110
|
+
};
|
|
111
|
+
type SpotStateEvent = {
|
|
112
|
+
user: `0x${string}`;
|
|
113
|
+
spotState: SpotClearinghouseStateResponse;
|
|
114
|
+
};
|
|
115
|
+
type WebData3Event = {
|
|
116
|
+
userState: {
|
|
117
|
+
agentAddress: `0x${string}` | null;
|
|
118
|
+
agentValidUntil: number | null;
|
|
119
|
+
cumLedger: string;
|
|
120
|
+
serverTime: number;
|
|
121
|
+
isVault: boolean;
|
|
122
|
+
user: `0x${string}`;
|
|
123
|
+
optOutOfSpotDusting?: true;
|
|
124
|
+
dexAbstractionEnabled?: boolean;
|
|
125
|
+
abstraction?: 'dexAbstraction' | 'unifiedAccount' | 'portfolioMargin' | 'disabled';
|
|
126
|
+
};
|
|
127
|
+
perpDexStates: {
|
|
128
|
+
totalVaultEquity: string;
|
|
129
|
+
perpsAtOpenInterestCap?: unknown;
|
|
130
|
+
leadingVaults?: unknown;
|
|
131
|
+
}[];
|
|
132
|
+
};
|
|
19
133
|
|
|
20
|
-
export { type AggregatedClearinghouseSummary, type AssetPosition, COLLATERAL_TOKEN_MAP, type
|
|
134
|
+
export { type ActiveAssetDataEvent, type AggregatedClearinghouseSummary, type AllDexsClearinghouseStateEvent, type AllPerpMetasResponse, type AssetPosition, COLLATERAL_TOKEN_MAP, type ClearinghouseStateResponse, HyperliquidAccountType, type HyperliquidCoinBalance, type LeverageInfo, type MetaResponse, type SpotClearinghouseStateResponse, type SpotStateEvent, type WebData3Event };
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
var HyperliquidAccountType = /* @__PURE__ */ ((HyperliquidAccountType2) => {
|
|
2
|
+
HyperliquidAccountType2["DEFAULT"] = "default";
|
|
3
|
+
HyperliquidAccountType2["DEX_ABSTRACTION"] = "dexAbstraction";
|
|
4
|
+
HyperliquidAccountType2["DISABLED"] = "disabled";
|
|
5
|
+
HyperliquidAccountType2["PORTFOLIO_MARGIN"] = "portfolioMargin";
|
|
6
|
+
HyperliquidAccountType2["UNIFIED_ACCOUNT"] = "unifiedAccount";
|
|
7
|
+
return HyperliquidAccountType2;
|
|
8
|
+
})(HyperliquidAccountType || {});
|
|
1
9
|
const COLLATERAL_TOKEN_MAP = {
|
|
2
10
|
0: "USDC",
|
|
3
11
|
235: "USDE",
|
|
@@ -5,4 +13,4 @@ const COLLATERAL_TOKEN_MAP = {
|
|
|
5
13
|
360: "USDH"
|
|
6
14
|
};
|
|
7
15
|
|
|
8
|
-
export { COLLATERAL_TOKEN_MAP };
|
|
16
|
+
export { COLLATERAL_TOKEN_MAP, HyperliquidAccountType };
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { Connector } from '@pear-protocol/types';
|
|
2
|
-
import { OrchestratorConfig,
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
import { OrchestratorConfig, Orchestrator } from './base.js';
|
|
3
|
+
import { g as SupportedCredentials } from '../../types-D2dbAtin.js';
|
|
4
|
+
export { f as BinanceAccountType } from '../../types-D2dbAtin.js';
|
|
5
|
+
export { BybitAccountType } from './bybit/types.js';
|
|
6
|
+
export { HyperliquidAccountType } from './hyperliquid/types.js';
|
|
5
7
|
|
|
6
|
-
declare function createOrchestrator(exchange: Connector, config: OrchestratorConfig):
|
|
8
|
+
declare function createOrchestrator(exchange: Connector, config: OrchestratorConfig, credentials: SupportedCredentials): Orchestrator;
|
|
7
9
|
|
|
8
|
-
export { OrchestratorConfig, createOrchestrator };
|
|
10
|
+
export { Orchestrator, OrchestratorConfig, createOrchestrator };
|
|
@@ -2,18 +2,26 @@ import './base';
|
|
|
2
2
|
import { BinanceOrchestrator } from './binance/orchestrator';
|
|
3
3
|
import { BybitOrchestrator } from './bybit/orchestrator';
|
|
4
4
|
import { HyperliquidOrchestrator } from './hyperliquid/orchestrator';
|
|
5
|
+
export { BinanceAccountType } from './binance/types';
|
|
6
|
+
export { BybitAccountType } from './bybit/types';
|
|
7
|
+
export { HyperliquidAccountType } from './hyperliquid/types';
|
|
5
8
|
|
|
6
|
-
function createOrchestrator(exchange, config) {
|
|
9
|
+
function createOrchestrator(exchange, config, credentials) {
|
|
10
|
+
let orchestrator;
|
|
7
11
|
switch (exchange) {
|
|
8
12
|
case "binance":
|
|
9
|
-
|
|
13
|
+
orchestrator = new BinanceOrchestrator(config, credentials);
|
|
14
|
+
break;
|
|
10
15
|
case "bybit":
|
|
11
|
-
|
|
16
|
+
orchestrator = new BybitOrchestrator(config, credentials);
|
|
17
|
+
break;
|
|
12
18
|
case "hyperliquid":
|
|
13
|
-
|
|
19
|
+
orchestrator = new HyperliquidOrchestrator(config, credentials);
|
|
20
|
+
break;
|
|
14
21
|
default:
|
|
15
22
|
throw new Error(`Unsupported exchange: ${exchange}`);
|
|
16
23
|
}
|
|
24
|
+
return orchestrator;
|
|
17
25
|
}
|
|
18
26
|
|
|
19
27
|
export { createOrchestrator };
|
package/dist/account/index.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
export { AccountManager } from './account-manager.js';
|
|
2
2
|
export { ExchangeAccount } from './exchange-account.js';
|
|
3
3
|
export { createOrchestrator } from './exchanges/index.js';
|
|
4
|
-
export { AccountBalance, AccountConfig, AccountPosition, AssetBalance, BalanceCallback, ExchangeState, HyperliquidAccountCredentials, MarginMode, PositionsCallback, StateUpdate, SupportedCredentials, TrackedAssetCallback, TrackedAssetInfo, Tracker } from '
|
|
4
|
+
export { A as ACCOUNT_TYPE_LABELS, a as AccountBalance, b as AccountConfig, c as AccountPosition, d as AccountType, e as AssetBalance, B as BalanceCallback, f as BinanceAccountType, E as ExchangeState, H as HyperliquidAccountCredentials, M as MarginMode, P as PositionsCallback, S as StateUpdate, g as SupportedCredentials, T as TrackedAssetCallback, h as TrackedAssetInfo, i as Tracker } from '../types-D2dbAtin.js';
|
|
5
|
+
export { BybitAccountType } from './exchanges/bybit/types.js';
|
|
6
|
+
export { HyperliquidAccountType } from './exchanges/hyperliquid/types.js';
|
|
5
7
|
export { Orchestrator, OrchestratorConfig } from './exchanges/base.js';
|
|
6
8
|
import '@pear-protocol/core-sdk';
|
|
7
9
|
import '@pear-protocol/types';
|