@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,77 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
export { f as BinanceAccountType, l as BinanceAssetIndex, o as BinanceMultiAssetsMarginResponse, j as BinanceRawAccountStatus, p as BinanceRawAsset, k as BinanceRawPositionRisk, m as BinanceRawUserDataEvent, n as BinanceWsHandlers } from '../../../types-D2dbAtin.js';
|
|
2
2
|
import '@pear-protocol/types';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
symbol: string;
|
|
6
|
-
leverage: string;
|
|
7
|
-
marginType: MarginMode;
|
|
8
|
-
isAutoAddMargin: string;
|
|
9
|
-
isolatedMargin: string;
|
|
10
|
-
positionAmt: string;
|
|
11
|
-
entryPrice: string;
|
|
12
|
-
breakEvenPrice: string;
|
|
13
|
-
unRealizedProfit: string;
|
|
14
|
-
liquidationPrice: string;
|
|
15
|
-
markPrice: string;
|
|
16
|
-
maxNotionalValue: string;
|
|
17
|
-
positionSide: string;
|
|
18
|
-
notional: string;
|
|
19
|
-
isolatedWallet: string;
|
|
20
|
-
updateTime: number;
|
|
21
|
-
}
|
|
22
|
-
interface BinanceRawAsset {
|
|
23
|
-
asset: string;
|
|
24
|
-
walletBalance: string;
|
|
25
|
-
availableBalance: string;
|
|
26
|
-
unrealizedProfit: string;
|
|
27
|
-
marginBalance: string;
|
|
28
|
-
initialMargin: string;
|
|
29
|
-
maintMargin: string;
|
|
30
|
-
marginAvailable: boolean;
|
|
31
|
-
}
|
|
32
|
-
interface BinanceRawAccountStatus {
|
|
33
|
-
totalWalletBalance: string;
|
|
34
|
-
totalMarginBalance: string;
|
|
35
|
-
availableBalance: string;
|
|
36
|
-
totalUnrealizedProfit: string;
|
|
37
|
-
totalInitialMargin: string;
|
|
38
|
-
totalMaintMargin: string;
|
|
39
|
-
multiAssetsMargin: boolean;
|
|
40
|
-
assets?: BinanceRawAsset[];
|
|
41
|
-
}
|
|
42
|
-
interface BinanceAssetIndex {
|
|
43
|
-
symbol: string;
|
|
44
|
-
time: number;
|
|
45
|
-
index: string;
|
|
46
|
-
bidBuffer: string;
|
|
47
|
-
askBuffer: string;
|
|
48
|
-
bidRate: string;
|
|
49
|
-
askRate: string;
|
|
50
|
-
autoExchangeBidBuffer: string;
|
|
51
|
-
autoExchangeAskBuffer: string;
|
|
52
|
-
autoExchangeBidRate: string;
|
|
53
|
-
autoExchangeAskRate: string;
|
|
54
|
-
}
|
|
55
|
-
interface BinanceRawUserDataEvent {
|
|
56
|
-
e?: string;
|
|
57
|
-
ac?: {
|
|
58
|
-
s: string;
|
|
59
|
-
l: string;
|
|
60
|
-
};
|
|
61
|
-
a?: {
|
|
62
|
-
B?: unknown[];
|
|
63
|
-
P?: unknown[];
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
interface BinanceRawLeverageResponse {
|
|
67
|
-
leverage: string;
|
|
68
|
-
maxNotionalValue: string;
|
|
69
|
-
symbol: string;
|
|
70
|
-
}
|
|
71
|
-
interface BinanceWsHandlers {
|
|
72
|
-
onUserDataEvent: (event: unknown) => void;
|
|
73
|
-
onWsApiResponse: (id: number, result: unknown) => void;
|
|
74
|
-
onClose: () => void;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
export type { BinanceAssetIndex, BinanceRawAccountStatus, BinanceRawAsset, BinanceRawLeverageResponse, BinanceRawPositionRisk, BinanceRawUserDataEvent, BinanceWsHandlers };
|
|
3
|
+
import '../bybit/types.js';
|
|
4
|
+
import '../hyperliquid/types.js';
|
|
@@ -1 +1,7 @@
|
|
|
1
|
+
var BinanceAccountType = /* @__PURE__ */ ((BinanceAccountType2) => {
|
|
2
|
+
BinanceAccountType2["MULTI_ASSET"] = "MULTI_ASSET";
|
|
3
|
+
BinanceAccountType2["SINGLE_ASSET"] = "SINGLE_ASSET";
|
|
4
|
+
return BinanceAccountType2;
|
|
5
|
+
})(BinanceAccountType || {});
|
|
1
6
|
|
|
7
|
+
export { BinanceAccountType };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { BinanceCredentialsDTO } from '@pear-protocol/types';
|
|
2
|
-
import { BinanceWsHandlers } from '
|
|
3
|
-
import '
|
|
2
|
+
import { n as BinanceWsHandlers } from '../../../types-D2dbAtin.js';
|
|
3
|
+
import '../bybit/types.js';
|
|
4
|
+
import '../hyperliquid/types.js';
|
|
4
5
|
|
|
5
6
|
declare class BinanceWs {
|
|
6
7
|
private userDataWs;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { hmacSha256Hex } from '../../../utils/hmac';
|
|
2
|
-
import {
|
|
2
|
+
import { createWs, waitForOpen, sendWs, ReconnectingWebSocket } from '../../../utils/ws';
|
|
3
3
|
import { USER_DATA_STREAM_URL_TESTNET, USER_DATA_STREAM_URL, WS_API_URL_TESTNET, WS_API_URL } from './const';
|
|
4
4
|
|
|
5
5
|
class BinanceWs {
|
|
@@ -15,26 +15,19 @@ class BinanceWs {
|
|
|
15
15
|
}
|
|
16
16
|
async connectUserDataStream(listenKey) {
|
|
17
17
|
const url = this.demo ? USER_DATA_STREAM_URL_TESTNET : USER_DATA_STREAM_URL;
|
|
18
|
-
this.userDataWs =
|
|
18
|
+
this.userDataWs = createWs(`${url}/${listenKey}`);
|
|
19
19
|
this.userDataWs.addEventListener("message", (event) => {
|
|
20
20
|
try {
|
|
21
21
|
this.handlers.onUserDataEvent(JSON.parse(event.data));
|
|
22
22
|
} catch {
|
|
23
23
|
}
|
|
24
24
|
});
|
|
25
|
-
this.userDataWs
|
|
26
|
-
if (this.userDataWs) {
|
|
27
|
-
this.userDataWs = null;
|
|
28
|
-
this.handlers.onClose();
|
|
29
|
-
}
|
|
30
|
-
};
|
|
31
|
-
this.userDataWs.onerror = () => {
|
|
32
|
-
};
|
|
25
|
+
await waitForOpen(this.userDataWs);
|
|
33
26
|
}
|
|
34
27
|
async connectWsApi(creds) {
|
|
35
28
|
this.creds = creds;
|
|
36
29
|
const url = this.demo ? WS_API_URL_TESTNET : WS_API_URL;
|
|
37
|
-
this.wsApiWs =
|
|
30
|
+
this.wsApiWs = createWs(url);
|
|
38
31
|
this.wsApiWs.addEventListener("message", (event) => {
|
|
39
32
|
try {
|
|
40
33
|
const msg = JSON.parse(event.data);
|
|
@@ -44,14 +37,7 @@ class BinanceWs {
|
|
|
44
37
|
} catch {
|
|
45
38
|
}
|
|
46
39
|
});
|
|
47
|
-
this.wsApiWs
|
|
48
|
-
if (this.wsApiWs) {
|
|
49
|
-
this.wsApiWs = null;
|
|
50
|
-
this.handlers.onClose();
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
|
-
this.wsApiWs.onerror = () => {
|
|
54
|
-
};
|
|
40
|
+
await waitForOpen(this.wsApiWs);
|
|
55
41
|
}
|
|
56
42
|
nextRequestId() {
|
|
57
43
|
return this.requestId++;
|
|
@@ -67,18 +53,16 @@ class BinanceWs {
|
|
|
67
53
|
close() {
|
|
68
54
|
this.creds = null;
|
|
69
55
|
if (this.userDataWs) {
|
|
70
|
-
this.userDataWs.onclose = null;
|
|
71
56
|
this.userDataWs.close();
|
|
72
57
|
this.userDataWs = null;
|
|
73
58
|
}
|
|
74
59
|
if (this.wsApiWs) {
|
|
75
|
-
this.wsApiWs.onclose = null;
|
|
76
60
|
this.wsApiWs.close();
|
|
77
61
|
this.wsApiWs = null;
|
|
78
62
|
}
|
|
79
63
|
}
|
|
80
64
|
get isConnected() {
|
|
81
|
-
return this.userDataWs?.readyState ===
|
|
65
|
+
return this.userDataWs?.readyState === ReconnectingWebSocket.OPEN && this.wsApiWs?.readyState === ReconnectingWebSocket.OPEN;
|
|
82
66
|
}
|
|
83
67
|
}
|
|
84
68
|
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { BybitCredentialsDTO } from '@pear-protocol/types';
|
|
2
|
+
import { S as StateUpdate, h as TrackedAssetInfo } from '../../../types-D2dbAtin.js';
|
|
3
|
+
import './types.js';
|
|
4
|
+
import '../hyperliquid/types.js';
|
|
5
|
+
|
|
6
|
+
type OnStateUpdate = (update: StateUpdate) => void;
|
|
7
|
+
type OnError = (error: Error) => void;
|
|
8
|
+
declare class BybitAssetTracker {
|
|
9
|
+
private onStateUpdate;
|
|
10
|
+
private onError;
|
|
11
|
+
private getCreds;
|
|
12
|
+
private getDemo;
|
|
13
|
+
private trackedAssetInfos;
|
|
14
|
+
constructor(deps: {
|
|
15
|
+
onStateUpdate: OnStateUpdate;
|
|
16
|
+
onError: OnError;
|
|
17
|
+
getCreds: () => BybitCredentialsDTO;
|
|
18
|
+
getDemo: () => boolean;
|
|
19
|
+
});
|
|
20
|
+
getInfos(): Map<string, TrackedAssetInfo>;
|
|
21
|
+
onAssetTracked(coin: string): void;
|
|
22
|
+
onAssetUntracked(coin: string): void;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export { BybitAssetTracker };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { fetchPositionLeverage } from './rest';
|
|
2
|
+
|
|
3
|
+
class BybitAssetTracker {
|
|
4
|
+
onStateUpdate;
|
|
5
|
+
onError;
|
|
6
|
+
getCreds;
|
|
7
|
+
getDemo;
|
|
8
|
+
trackedAssetInfos = /* @__PURE__ */ new Map();
|
|
9
|
+
constructor(deps) {
|
|
10
|
+
this.onStateUpdate = deps.onStateUpdate;
|
|
11
|
+
this.onError = deps.onError;
|
|
12
|
+
this.getCreds = deps.getCreds;
|
|
13
|
+
this.getDemo = deps.getDemo;
|
|
14
|
+
}
|
|
15
|
+
getInfos() {
|
|
16
|
+
return this.trackedAssetInfos;
|
|
17
|
+
}
|
|
18
|
+
onAssetTracked(coin) {
|
|
19
|
+
fetchPositionLeverage(this.getCreds(), coin, this.getDemo()).then((pos) => {
|
|
20
|
+
const leverage = pos?.leverage || "1";
|
|
21
|
+
const marginType = pos?.tradeMode === "1" ? "isolated" : "cross";
|
|
22
|
+
const info = { coin, leverage, marginType };
|
|
23
|
+
this.trackedAssetInfos.set(coin, info);
|
|
24
|
+
const trackedAssets = /* @__PURE__ */ new Map();
|
|
25
|
+
trackedAssets.set(coin, info);
|
|
26
|
+
this.onStateUpdate({ trackedAssets });
|
|
27
|
+
}).catch((err) => {
|
|
28
|
+
this.onError(err instanceof Error ? err : new Error(String(err)));
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
onAssetUntracked(coin) {
|
|
32
|
+
this.trackedAssetInfos.delete(coin);
|
|
33
|
+
this.onStateUpdate({ trackedAssets: new Map(this.trackedAssetInfos) });
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export { BybitAssetTracker };
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { AccountBalance, AccountPosition } from '
|
|
2
|
-
import { BybitRawWallet, BybitRawCoin, BybitRawPosition } from './types.js';
|
|
1
|
+
import { a as AccountBalance, c as AccountPosition } from '../../../types-D2dbAtin.js';
|
|
2
|
+
import { BybitRawWallet, BybitRawCoin, BybitAccountType, BybitRawPosition } from './types.js';
|
|
3
3
|
import '@pear-protocol/types';
|
|
4
|
+
import '../hyperliquid/types.js';
|
|
4
5
|
|
|
5
|
-
declare function buildBalance(raw: BybitRawWallet, coins: Map<string, BybitRawCoin>,
|
|
6
|
+
declare function buildBalance(raw: BybitRawWallet, coins: Map<string, BybitRawCoin>, accountType: BybitAccountType | null): AccountBalance | null;
|
|
6
7
|
declare function mergeRawCoins(existing: Map<string, BybitRawCoin>, incoming: BybitRawCoin[]): Map<string, BybitRawCoin>;
|
|
7
8
|
declare function mapSinglePosition(p: BybitRawPosition, size: string): AccountPosition;
|
|
8
9
|
declare function mapPositions(raw: BybitRawPosition[]): Map<string, AccountPosition>;
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import '../../types';
|
|
2
2
|
import { positionKey } from '../../utils';
|
|
3
|
+
import { BybitAccountType } from './types';
|
|
3
4
|
|
|
4
|
-
function buildBalance(raw, coins,
|
|
5
|
+
function buildBalance(raw, coins, accountType) {
|
|
6
|
+
if (!accountType) return null;
|
|
5
7
|
const free = {};
|
|
6
8
|
const used = {};
|
|
7
9
|
const total = {};
|
|
8
10
|
const assets = [];
|
|
9
|
-
const isPortfolio =
|
|
11
|
+
const isPortfolio = accountType === BybitAccountType.PORTFOLIO_MARGIN;
|
|
10
12
|
for (const [, c] of coins) {
|
|
11
13
|
const equity = c.equity ?? "0";
|
|
12
14
|
const positionInitialMargin = c.totalPositionIM === "" ? "0" : c.totalPositionIM ?? "0";
|
|
@@ -39,7 +41,7 @@ function buildBalance(raw, coins, marginMode) {
|
|
|
39
41
|
});
|
|
40
42
|
}
|
|
41
43
|
return {
|
|
42
|
-
accountType
|
|
44
|
+
accountType,
|
|
43
45
|
free,
|
|
44
46
|
used,
|
|
45
47
|
total,
|
|
@@ -1,22 +1,21 @@
|
|
|
1
|
-
import { SupportedCredentials } from '
|
|
2
|
-
import { BaseOrchestrator } from '../base.js';
|
|
1
|
+
import { g as SupportedCredentials } from '../../../types-D2dbAtin.js';
|
|
2
|
+
import { BaseOrchestrator, OrchestratorConfig } from '../base.js';
|
|
3
3
|
import '@pear-protocol/types';
|
|
4
|
+
import './types.js';
|
|
5
|
+
import '../hyperliquid/types.js';
|
|
4
6
|
|
|
5
7
|
declare class BybitOrchestrator extends BaseOrchestrator {
|
|
6
8
|
private ws;
|
|
7
|
-
private
|
|
8
|
-
private
|
|
9
|
-
private
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
private creds;
|
|
10
|
+
private stateHandler;
|
|
11
|
+
private assetTracker;
|
|
12
|
+
constructor(config: OrchestratorConfig, credentials: SupportedCredentials);
|
|
13
|
+
protected initAsync(): Promise<void>;
|
|
14
|
+
protected cleanupConnections(): void;
|
|
15
|
+
stop(): Promise<void>;
|
|
13
16
|
get isConnected(): boolean;
|
|
14
17
|
onAssetTracked(coin: string): void;
|
|
15
18
|
onAssetUntracked(coin: string): void;
|
|
16
|
-
setLeverage(symbol: string, leverage: string): Promise<void>;
|
|
17
|
-
private stopAll;
|
|
18
|
-
private handleMessage;
|
|
19
|
-
private handleWalletUpdate;
|
|
20
19
|
}
|
|
21
20
|
|
|
22
21
|
export { BybitOrchestrator };
|
|
@@ -1,151 +1,65 @@
|
|
|
1
1
|
import { BaseOrchestrator } from '../base';
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
2
|
+
import { fetchWalletBalance, fetchPositions, fetchAccountInfo } from './rest';
|
|
3
|
+
import './types';
|
|
4
4
|
import { BybitWs } from './ws';
|
|
5
|
+
import { BybitStateHandler } from './state-handler';
|
|
6
|
+
import { BybitAssetTracker } from './asset-tracker';
|
|
5
7
|
|
|
6
8
|
class BybitOrchestrator extends BaseOrchestrator {
|
|
7
9
|
ws = null;
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const gen = ++this.startGeneration;
|
|
14
|
-
this.manualClose = false;
|
|
10
|
+
creds;
|
|
11
|
+
stateHandler;
|
|
12
|
+
assetTracker;
|
|
13
|
+
constructor(config, credentials) {
|
|
14
|
+
super(config);
|
|
15
15
|
this.credentials = credentials;
|
|
16
|
-
|
|
17
|
-
this.
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
this.
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
},
|
|
50
|
-
this.demo
|
|
51
|
-
);
|
|
52
|
-
await this.ws.connect(creds);
|
|
53
|
-
this.reconnectAttempts = 0;
|
|
54
|
-
} catch (err) {
|
|
55
|
-
if (gen !== this.startGeneration) return;
|
|
56
|
-
this.stopAll();
|
|
57
|
-
this.onError(err instanceof Error ? err : new Error(String(err)));
|
|
58
|
-
this.scheduleReconnect();
|
|
59
|
-
}
|
|
16
|
+
this.creds = credentials;
|
|
17
|
+
this.assetTracker = new BybitAssetTracker({
|
|
18
|
+
onStateUpdate: (update) => this.onStateUpdate(update),
|
|
19
|
+
onError: (err) => this.onError(err),
|
|
20
|
+
getCreds: () => this.creds,
|
|
21
|
+
getDemo: () => this.demo
|
|
22
|
+
});
|
|
23
|
+
this.stateHandler = new BybitStateHandler({
|
|
24
|
+
onStateUpdate: (update) => this.onStateUpdate(update),
|
|
25
|
+
getTrackedAssetInfos: () => this.assetTracker.getInfos()
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
async initAsync() {
|
|
29
|
+
const [wallet, positionsUsd, positionsUsdc, accountInfo] = await Promise.all([
|
|
30
|
+
fetchWalletBalance(this.creds, this.demo),
|
|
31
|
+
fetchPositions(this.creds, "USDT", this.demo),
|
|
32
|
+
fetchPositions(this.creds, "USDC", this.demo),
|
|
33
|
+
fetchAccountInfo(this.creds, this.demo)
|
|
34
|
+
]);
|
|
35
|
+
this.stateHandler.handleInitialData(
|
|
36
|
+
wallet ?? null,
|
|
37
|
+
[positionsUsd, positionsUsdc].flat(),
|
|
38
|
+
accountInfo?.marginMode ?? null
|
|
39
|
+
);
|
|
40
|
+
this.ws = new BybitWs(
|
|
41
|
+
{
|
|
42
|
+
onMessage: (msg) => this.stateHandler.handleMessage(msg)
|
|
43
|
+
},
|
|
44
|
+
this.demo
|
|
45
|
+
);
|
|
46
|
+
await this.ws.connect(this.creds);
|
|
60
47
|
}
|
|
61
|
-
|
|
62
|
-
this.
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
this.
|
|
66
|
-
this.
|
|
67
|
-
this.marginMode = "cross";
|
|
68
|
-
this.credentials = null;
|
|
48
|
+
cleanupConnections() {
|
|
49
|
+
this.ws?.close();
|
|
50
|
+
}
|
|
51
|
+
async stop() {
|
|
52
|
+
this.stopped = true;
|
|
53
|
+
this.cleanupConnections();
|
|
69
54
|
}
|
|
70
55
|
get isConnected() {
|
|
71
56
|
return this.ws?.isConnected ?? false;
|
|
72
57
|
}
|
|
73
58
|
onAssetTracked(coin) {
|
|
74
|
-
|
|
75
|
-
if (!creds) return;
|
|
76
|
-
fetchPositionLeverage(creds, coin, this.demo).then((pos) => {
|
|
77
|
-
const leverage = pos?.leverage || "1";
|
|
78
|
-
const marginType = pos?.tradeMode === "1" ? "isolated" : "cross";
|
|
79
|
-
const info = {
|
|
80
|
-
coin,
|
|
81
|
-
leverage,
|
|
82
|
-
marginType
|
|
83
|
-
};
|
|
84
|
-
this.trackedAssetInfos.set(coin, info);
|
|
85
|
-
const trackedAssets = /* @__PURE__ */ new Map();
|
|
86
|
-
trackedAssets.set(coin, info);
|
|
87
|
-
this.onStateUpdate({ trackedAssets });
|
|
88
|
-
}).catch((err) => {
|
|
89
|
-
this.onError(err instanceof Error ? err : new Error(String(err)));
|
|
90
|
-
});
|
|
59
|
+
this.assetTracker.onAssetTracked(coin);
|
|
91
60
|
}
|
|
92
61
|
onAssetUntracked(coin) {
|
|
93
|
-
this.
|
|
94
|
-
this.onStateUpdate({ trackedAssets: new Map(this.trackedAssetInfos) });
|
|
95
|
-
}
|
|
96
|
-
async setLeverage(symbol, leverage) {
|
|
97
|
-
const creds = this.credentials;
|
|
98
|
-
if (!creds) throw new Error("Not connected");
|
|
99
|
-
await setLeverage(creds, symbol, leverage, this.demo);
|
|
100
|
-
}
|
|
101
|
-
stopAll() {
|
|
102
|
-
this.clearReconnectTimer();
|
|
103
|
-
this.ws?.close();
|
|
104
|
-
this.ws = null;
|
|
105
|
-
}
|
|
106
|
-
handleMessage(topic, data) {
|
|
107
|
-
if (topic === "wallet") {
|
|
108
|
-
const wallet = data[0];
|
|
109
|
-
if (wallet) this.handleWalletUpdate(wallet);
|
|
110
|
-
} else if (topic === "position") {
|
|
111
|
-
const rawPositions = data;
|
|
112
|
-
const positions = mapPositionUpdates(rawPositions);
|
|
113
|
-
if (positions.size > 0) {
|
|
114
|
-
const trackedAssets = /* @__PURE__ */ new Map();
|
|
115
|
-
for (const pos of rawPositions) {
|
|
116
|
-
const existing = this.trackedAssetInfos.get(pos.symbol);
|
|
117
|
-
if (existing) {
|
|
118
|
-
const leverage = pos.leverage || existing.leverage;
|
|
119
|
-
const marginType = pos.tradeMode === "1" ? "isolated" : "cross";
|
|
120
|
-
const updated = { ...existing, leverage, marginType };
|
|
121
|
-
this.trackedAssetInfos.set(pos.symbol, updated);
|
|
122
|
-
trackedAssets.set(pos.symbol, updated);
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
this.onStateUpdate({
|
|
126
|
-
positions,
|
|
127
|
-
...trackedAssets.size > 0 ? { trackedAssets } : {}
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
handleWalletUpdate(raw) {
|
|
133
|
-
this.rawCoins = mergeRawCoins(this.rawCoins, raw.coin ?? []);
|
|
134
|
-
const merged = this.lastWallet ? {
|
|
135
|
-
totalEquity: raw.totalEquity || this.lastWallet.totalEquity,
|
|
136
|
-
totalWalletBalance: raw.totalWalletBalance || this.lastWallet.totalWalletBalance,
|
|
137
|
-
totalMarginBalance: raw.totalMarginBalance || this.lastWallet.totalMarginBalance,
|
|
138
|
-
totalAvailableBalance: raw.totalAvailableBalance || this.lastWallet.totalAvailableBalance,
|
|
139
|
-
totalPerpUPL: raw.totalPerpUPL || this.lastWallet.totalPerpUPL,
|
|
140
|
-
totalInitialMargin: raw.totalInitialMargin || this.lastWallet.totalInitialMargin,
|
|
141
|
-
totalMaintenanceMargin: raw.totalMaintenanceMargin || this.lastWallet.totalMaintenanceMargin,
|
|
142
|
-
accountMMRate: raw.accountMMRate || this.lastWallet.accountMMRate,
|
|
143
|
-
coin: raw.coin ?? this.lastWallet.coin
|
|
144
|
-
} : raw;
|
|
145
|
-
this.lastWallet = merged;
|
|
146
|
-
this.onStateUpdate({
|
|
147
|
-
balance: buildBalance(merged, this.rawCoins, this.marginMode)
|
|
148
|
-
});
|
|
62
|
+
this.assetTracker.onAssetUntracked(coin);
|
|
149
63
|
}
|
|
150
64
|
}
|
|
151
65
|
|
|
@@ -2,10 +2,9 @@ import { BybitCredentialsDTO } from '@pear-protocol/types';
|
|
|
2
2
|
import { BybitRawAccountInfo, BybitRawPosition, BybitRawWallet } from './types.js';
|
|
3
3
|
|
|
4
4
|
declare function fetchWalletBalance(creds: BybitCredentialsDTO, demo: boolean): Promise<BybitRawWallet | undefined>;
|
|
5
|
-
declare function fetchPositions(creds: BybitCredentialsDTO, demo: boolean): Promise<BybitRawPosition[]>;
|
|
5
|
+
declare function fetchPositions(creds: BybitCredentialsDTO, settleCoin: string, demo: boolean): Promise<BybitRawPosition[]>;
|
|
6
6
|
declare function fetchPositionLeverage(creds: BybitCredentialsDTO, symbol: string, demo: boolean): Promise<BybitRawPosition | undefined>;
|
|
7
|
-
declare function setLeverage(creds: BybitCredentialsDTO, symbol: string, leverage: string, demo: boolean): Promise<void>;
|
|
8
7
|
declare function fetchAccountInfo(creds: BybitCredentialsDTO, demo: boolean): Promise<BybitRawAccountInfo>;
|
|
9
8
|
declare function fetchCollateralRatios(creds: BybitCredentialsDTO, demo: boolean): Promise<Map<string, string>>;
|
|
10
9
|
|
|
11
|
-
export { fetchAccountInfo, fetchCollateralRatios, fetchPositionLeverage, fetchPositions, fetchWalletBalance
|
|
10
|
+
export { fetchAccountInfo, fetchCollateralRatios, fetchPositionLeverage, fetchPositions, fetchWalletBalance };
|
|
@@ -1,33 +1,6 @@
|
|
|
1
1
|
import { hmacSha256Hex } from '../../../utils/hmac';
|
|
2
2
|
import { BASE_URL_DEMO, BASE_URL } from './const';
|
|
3
3
|
|
|
4
|
-
async function signedPost(creds, path, body, demo) {
|
|
5
|
-
const baseUrl = demo ? BASE_URL_DEMO : BASE_URL;
|
|
6
|
-
const timestamp = Date.now().toString();
|
|
7
|
-
const recvWindow = "5000";
|
|
8
|
-
const bodyStr = JSON.stringify(body);
|
|
9
|
-
const signPayload = `${timestamp}${creds.api_key}${recvWindow}${bodyStr}`;
|
|
10
|
-
const signature = await hmacSha256Hex(creds.api_secret, signPayload);
|
|
11
|
-
const response = await fetch(`${baseUrl}${path}`, {
|
|
12
|
-
method: "POST",
|
|
13
|
-
headers: {
|
|
14
|
-
"X-BAPI-API-KEY": creds.api_key,
|
|
15
|
-
"X-BAPI-SIGN": signature,
|
|
16
|
-
"X-BAPI-TIMESTAMP": timestamp,
|
|
17
|
-
"X-BAPI-RECV-WINDOW": recvWindow,
|
|
18
|
-
"Content-Type": "application/json"
|
|
19
|
-
},
|
|
20
|
-
body: bodyStr
|
|
21
|
-
});
|
|
22
|
-
if (!response.ok) {
|
|
23
|
-
throw new Error(`Bybit API error: ${response.status} ${response.statusText}`);
|
|
24
|
-
}
|
|
25
|
-
const result = await response.json();
|
|
26
|
-
if (result.retCode !== 0) {
|
|
27
|
-
throw new Error(`Bybit API error: ${result.retCode} ${result.retMsg}`);
|
|
28
|
-
}
|
|
29
|
-
return result.result;
|
|
30
|
-
}
|
|
31
4
|
async function signedGet(creds, path, params, demo) {
|
|
32
5
|
const baseUrl = demo ? BASE_URL_DEMO : BASE_URL;
|
|
33
6
|
const timestamp = Date.now().toString();
|
|
@@ -61,11 +34,11 @@ async function fetchWalletBalance(creds, demo) {
|
|
|
61
34
|
);
|
|
62
35
|
return result.list[0];
|
|
63
36
|
}
|
|
64
|
-
async function fetchPositions(creds, demo) {
|
|
37
|
+
async function fetchPositions(creds, settleCoin, demo) {
|
|
65
38
|
const result = await signedGet(
|
|
66
39
|
creds,
|
|
67
40
|
"/v5/position/list",
|
|
68
|
-
{ category: "linear", settleCoin
|
|
41
|
+
{ category: "linear", settleCoin },
|
|
69
42
|
demo
|
|
70
43
|
);
|
|
71
44
|
return result.list;
|
|
@@ -79,16 +52,8 @@ async function fetchPositionLeverage(creds, symbol, demo) {
|
|
|
79
52
|
);
|
|
80
53
|
return result.list[0];
|
|
81
54
|
}
|
|
82
|
-
async function setLeverage(creds, symbol, leverage, demo) {
|
|
83
|
-
await signedPost(
|
|
84
|
-
creds,
|
|
85
|
-
"/v5/position/set-leverage",
|
|
86
|
-
{ category: "linear", symbol, buyLeverage: leverage, sellLeverage: leverage },
|
|
87
|
-
demo
|
|
88
|
-
);
|
|
89
|
-
}
|
|
90
55
|
async function fetchAccountInfo(creds, demo) {
|
|
91
|
-
return signedGet(creds, "/v5/account/
|
|
56
|
+
return signedGet(creds, "/v5/account/info", {}, demo);
|
|
92
57
|
}
|
|
93
58
|
async function fetchCollateralRatios(creds, demo) {
|
|
94
59
|
const result = await signedGet(
|
|
@@ -107,4 +72,4 @@ async function fetchCollateralRatios(creds, demo) {
|
|
|
107
72
|
return ratios;
|
|
108
73
|
}
|
|
109
74
|
|
|
110
|
-
export { fetchAccountInfo, fetchCollateralRatios, fetchPositionLeverage, fetchPositions, fetchWalletBalance
|
|
75
|
+
export { fetchAccountInfo, fetchCollateralRatios, fetchPositionLeverage, fetchPositions, fetchWalletBalance };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { S as StateUpdate, h as TrackedAssetInfo } from '../../../types-D2dbAtin.js';
|
|
2
|
+
import { BybitRawWallet, BybitRawPosition, BybitAccountType, BybitWsMessage } from './types.js';
|
|
3
|
+
import '@pear-protocol/types';
|
|
4
|
+
import '../hyperliquid/types.js';
|
|
5
|
+
|
|
6
|
+
type OnStateUpdate = (update: StateUpdate) => void;
|
|
7
|
+
declare class BybitStateHandler {
|
|
8
|
+
private onStateUpdate;
|
|
9
|
+
private getTrackedAssetInfos;
|
|
10
|
+
private rawCoins;
|
|
11
|
+
private lastWallet;
|
|
12
|
+
private accountType;
|
|
13
|
+
constructor(deps: {
|
|
14
|
+
onStateUpdate: OnStateUpdate;
|
|
15
|
+
getTrackedAssetInfos: () => Map<string, TrackedAssetInfo>;
|
|
16
|
+
});
|
|
17
|
+
handleInitialData(wallet: BybitRawWallet | null, positions: BybitRawPosition[], accountType: BybitAccountType | null): void;
|
|
18
|
+
handleMessage(msg: BybitWsMessage): void;
|
|
19
|
+
private handleWalletUpdate;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export { BybitStateHandler };
|