@pear-protocol/exchanges-sdk 0.0.18 → 0.1.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 +73 -137
- package/dist/client/base-ws.d.ts +30 -0
- package/dist/client/base-ws.js +113 -0
- package/dist/client/binance/exchange-ws.d.ts +19 -0
- package/dist/client/binance/exchange-ws.js +26 -0
- package/dist/{account/exchanges → client}/binance/rest.d.ts +2 -6
- package/dist/{account/exchanges → client}/binance/rest.js +4 -11
- package/dist/client/binance/types.d.ts +68 -0
- package/dist/client/binance/types.js +1 -0
- package/dist/client/binance/ws.d.ts +30 -0
- package/dist/client/binance/ws.js +54 -0
- package/dist/client/bybit/exchange-ws.d.ts +20 -0
- package/dist/client/bybit/exchange-ws.js +28 -0
- package/dist/{account/exchanges → client}/bybit/rest.js +3 -2
- package/dist/{account/exchanges → client}/bybit/types.d.ts +1 -9
- package/dist/client/bybit/types.js +1 -0
- package/dist/client/bybit/ws.d.ts +17 -0
- package/dist/client/bybit/ws.js +50 -0
- package/dist/client/exchange-ws.d.ts +12 -0
- package/dist/client/exchange-ws.js +10 -0
- package/dist/client/hyperliquid/exchange-ws.d.ts +15 -0
- package/dist/client/hyperliquid/exchange-ws.js +21 -0
- package/dist/client/hyperliquid/rest.d.ts +3 -0
- package/dist/client/hyperliquid/rest.js +12 -0
- package/dist/{account/exchanges → client}/hyperliquid/types.d.ts +18 -39
- package/dist/client/hyperliquid/types.js +1 -0
- package/dist/client/hyperliquid/ws.d.ts +10 -0
- package/dist/client/hyperliquid/ws.js +16 -0
- package/dist/client/index.d.ts +31 -0
- package/dist/client/index.js +47 -0
- package/dist/client/lighter/constants.d.ts +4 -0
- package/dist/client/lighter/constants.js +4 -0
- package/dist/client/lighter/exchange-ws.d.ts +15 -0
- package/dist/client/lighter/exchange-ws.js +21 -0
- package/dist/client/lighter/rest.d.ts +56 -0
- package/dist/client/lighter/rest.js +27 -0
- package/dist/client/lighter/types.d.ts +32 -0
- package/dist/client/lighter/types.js +1 -0
- package/dist/client/lighter/ws.d.ts +10 -0
- package/dist/client/lighter/ws.js +17 -0
- package/dist/client/okx/exchange-ws.d.ts +20 -0
- package/dist/client/okx/exchange-ws.js +28 -0
- package/dist/{account/exchanges → client}/okx/rest.js +2 -2
- package/dist/{account/exchanges → client}/okx/types.d.ts +1 -10
- package/dist/client/okx/types.js +1 -0
- package/dist/client/okx/ws.d.ts +17 -0
- package/dist/client/okx/ws.js +61 -0
- package/dist/helper/factory.d.ts +10 -0
- package/dist/helper/factory.js +12 -0
- package/dist/helper/index.d.ts +7 -0
- package/dist/helper/index.js +2 -0
- package/dist/helper/lighter/ethereum/abi.d.ts +66 -0
- package/dist/helper/lighter/ethereum/abi.js +40 -0
- package/dist/helper/lighter/ethereum/index.d.ts +8 -0
- package/dist/helper/lighter/ethereum/index.js +34 -0
- package/dist/helper/lighter/ethereum/types.d.ts +23 -0
- package/dist/helper/lighter/ethereum/types.js +1 -0
- package/dist/helper/lighter/helper.d.ts +9 -0
- package/dist/helper/lighter/helper.js +67 -0
- package/dist/helper/lighter/index.d.ts +6 -0
- package/dist/helper/lighter/index.js +2 -0
- package/dist/helper/lighter/types.d.ts +63 -0
- package/dist/helper/lighter/types.js +35 -0
- package/dist/helper/types.d.ts +11 -0
- package/dist/helper/types.js +1 -0
- package/dist/index.d.ts +37 -24
- package/dist/index.js +6 -21
- package/dist/sdk.d.ts +43 -0
- package/dist/sdk.js +52 -0
- package/dist/syncer/base.d.ts +33 -0
- package/dist/syncer/base.js +14 -0
- package/dist/syncer/index.d.ts +18 -0
- package/dist/syncer/index.js +1 -0
- package/dist/tracker/base.d.ts +79 -0
- package/dist/tracker/base.js +120 -0
- package/dist/tracker/binance/const.d.ts +4 -0
- package/dist/tracker/binance/const.js +4 -0
- package/dist/{account/exchanges → tracker}/binance/mapper.d.ts +4 -1
- package/dist/{account/exchanges → tracker}/binance/mapper.js +7 -6
- package/dist/tracker/binance/tracker.d.ts +60 -0
- package/dist/tracker/binance/tracker.js +181 -0
- package/dist/tracker/binance/types.d.ts +6 -0
- package/dist/{account/exchanges → tracker}/bybit/mapper.d.ts +5 -3
- package/dist/{account/exchanges → tracker}/bybit/mapper.js +11 -10
- package/dist/tracker/bybit/tracker.d.ts +51 -0
- package/dist/tracker/bybit/tracker.js +138 -0
- package/dist/tracker/bybit/types.d.ts +7 -0
- package/dist/{account/exchanges → tracker}/hyperliquid/mapper.d.ts +6 -4
- package/dist/{account/exchanges → tracker}/hyperliquid/mapper.js +18 -16
- package/dist/tracker/hyperliquid/tracker.d.ts +62 -0
- package/dist/tracker/hyperliquid/tracker.js +219 -0
- package/dist/tracker/hyperliquid/types.d.ts +23 -0
- package/dist/tracker/index.d.ts +38 -0
- package/dist/tracker/index.js +81 -0
- package/dist/tracker/lighter/const.d.ts +3 -0
- package/dist/tracker/lighter/const.js +3 -0
- package/dist/tracker/lighter/mapper.d.ts +16 -0
- package/dist/tracker/lighter/mapper.js +77 -0
- package/dist/tracker/lighter/tracker.d.ts +53 -0
- package/dist/tracker/lighter/tracker.js +150 -0
- package/dist/tracker/lighter/types.d.ts +16 -0
- package/dist/tracker/lighter/types.js +6 -0
- package/dist/{account/exchanges → tracker}/okx/mapper.d.ts +5 -3
- package/dist/{account/exchanges → tracker}/okx/mapper.js +11 -10
- package/dist/tracker/okx/tracker.d.ts +51 -0
- package/dist/tracker/okx/tracker.js +134 -0
- package/dist/tracker/okx/types.d.ts +8 -0
- package/dist/tracker/types.d.ts +63 -0
- package/dist/{account → tracker}/types.js +6 -4
- package/dist/tracker/utils.d.ts +11 -0
- package/dist/{account → tracker}/utils.js +0 -2
- package/dist/types.d.ts +50 -0
- package/dist/types.js +1 -0
- package/package.json +8 -4
- package/dist/account/account-manager.d.ts +0 -31
- package/dist/account/account-manager.js +0 -119
- package/dist/account/exchange-account.d.ts +0 -35
- package/dist/account/exchange-account.js +0 -158
- package/dist/account/exchanges/base.d.ts +0 -48
- package/dist/account/exchanges/base.js +0 -41
- package/dist/account/exchanges/binance/asset-tracker.d.ts +0 -26
- package/dist/account/exchanges/binance/asset-tracker.js +0 -38
- package/dist/account/exchanges/binance/const.d.ts +0 -10
- package/dist/account/exchanges/binance/const.js +0 -10
- package/dist/account/exchanges/binance/orchestrator.d.ts +0 -31
- package/dist/account/exchanges/binance/orchestrator.js +0 -91
- package/dist/account/exchanges/binance/state-handler.d.ts +0 -33
- package/dist/account/exchanges/binance/state-handler.js +0 -113
- package/dist/account/exchanges/binance/types.d.ts +0 -5
- package/dist/account/exchanges/binance/ws.d.ts +0 -23
- package/dist/account/exchanges/binance/ws.js +0 -69
- package/dist/account/exchanges/bybit/asset-tracker.d.ts +0 -26
- package/dist/account/exchanges/bybit/asset-tracker.js +0 -37
- package/dist/account/exchanges/bybit/const.d.ts +0 -7
- package/dist/account/exchanges/bybit/const.js +0 -7
- package/dist/account/exchanges/bybit/orchestrator.d.ts +0 -22
- package/dist/account/exchanges/bybit/orchestrator.js +0 -66
- package/dist/account/exchanges/bybit/state-handler.d.ts +0 -23
- package/dist/account/exchanges/bybit/state-handler.js +0 -70
- package/dist/account/exchanges/bybit/ws.d.ts +0 -19
- package/dist/account/exchanges/bybit/ws.js +0 -83
- package/dist/account/exchanges/hyperliquid/asset-tracker.d.ts +0 -35
- package/dist/account/exchanges/hyperliquid/asset-tracker.js +0 -83
- package/dist/account/exchanges/hyperliquid/orchestrator.d.ts +0 -26
- package/dist/account/exchanges/hyperliquid/orchestrator.js +0 -102
- package/dist/account/exchanges/hyperliquid/state-handler.d.ts +0 -25
- package/dist/account/exchanges/hyperliquid/state-handler.js +0 -104
- package/dist/account/exchanges/index.d.ts +0 -11
- package/dist/account/exchanges/index.js +0 -32
- package/dist/account/exchanges/okx/asset-tracker.d.ts +0 -26
- package/dist/account/exchanges/okx/asset-tracker.js +0 -34
- package/dist/account/exchanges/okx/const.d.ts +0 -7
- package/dist/account/exchanges/okx/const.js +0 -7
- package/dist/account/exchanges/okx/orchestrator.d.ts +0 -22
- package/dist/account/exchanges/okx/orchestrator.js +0 -57
- package/dist/account/exchanges/okx/state-handler.d.ts +0 -24
- package/dist/account/exchanges/okx/state-handler.js +0 -78
- package/dist/account/exchanges/okx/ws.d.ts +0 -20
- package/dist/account/exchanges/okx/ws.js +0 -103
- package/dist/account/index.d.ts +0 -11
- package/dist/account/index.js +0 -4
- package/dist/account/types.d.ts +0 -5
- package/dist/account/utils.d.ts +0 -10
- package/dist/credentials.d.ts +0 -28
- package/dist/credentials.js +0 -46
- package/dist/types-Caz2X4h0.d.ts +0 -151
- package/dist/utils/ws.d.ts +0 -10
- package/dist/utils/ws.js +0 -42
- /package/dist/{account/exchanges → client}/bybit/rest.d.ts +0 -0
- /package/dist/{utils → client}/hmac.d.ts +0 -0
- /package/dist/{utils → client}/hmac.js +0 -0
- /package/dist/{account/exchanges → client}/okx/rest.d.ts +0 -0
- /package/dist/{account/exchanges → tracker}/binance/types.js +0 -0
- /package/dist/{account/exchanges → tracker}/bybit/types.js +0 -0
- /package/dist/{account/exchanges → tracker}/hyperliquid/const.d.ts +0 -0
- /package/dist/{account/exchanges → tracker}/hyperliquid/const.js +0 -0
- /package/dist/{account/exchanges → tracker}/hyperliquid/types.js +0 -0
- /package/dist/{account/exchanges → tracker}/okx/types.js +0 -0
package/dist/sdk.d.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Connector } from '@pear-protocol/types';
|
|
2
|
+
import { ExchangeHelperExchange, ExchangeHelperMap } from './helper/types.js';
|
|
3
|
+
import { AccountPositionSyncer } from './syncer/base.js';
|
|
4
|
+
import { ExchangesSDKConfig, ExchangeConnection } from './types.js';
|
|
5
|
+
import { AccountTracker } from './tracker/base.js';
|
|
6
|
+
import './helper/lighter/types.js';
|
|
7
|
+
import './helper/lighter/ethereum/types.js';
|
|
8
|
+
import 'viem';
|
|
9
|
+
import './client/lighter/rest.js';
|
|
10
|
+
import '@pear-protocol/core-sdk';
|
|
11
|
+
import './client/index.js';
|
|
12
|
+
import './client/binance/exchange-ws.js';
|
|
13
|
+
import './client/base-ws.js';
|
|
14
|
+
import 'partysocket';
|
|
15
|
+
import './client/exchange-ws.js';
|
|
16
|
+
import './client/binance/ws.js';
|
|
17
|
+
import './client/bybit/exchange-ws.js';
|
|
18
|
+
import './client/bybit/ws.js';
|
|
19
|
+
import './client/hyperliquid/exchange-ws.js';
|
|
20
|
+
import './client/hyperliquid/ws.js';
|
|
21
|
+
import './client/lighter/exchange-ws.js';
|
|
22
|
+
import './client/lighter/ws.js';
|
|
23
|
+
import './client/okx/exchange-ws.js';
|
|
24
|
+
import './client/okx/ws.js';
|
|
25
|
+
import './tracker/types.js';
|
|
26
|
+
import './tracker/binance/types.js';
|
|
27
|
+
import './tracker/bybit/types.js';
|
|
28
|
+
import './tracker/hyperliquid/types.js';
|
|
29
|
+
import './tracker/lighter/types.js';
|
|
30
|
+
import './tracker/okx/types.js';
|
|
31
|
+
|
|
32
|
+
declare class ExchangesSDK {
|
|
33
|
+
private sdk;
|
|
34
|
+
private demo;
|
|
35
|
+
constructor(config: ExchangesSDKConfig);
|
|
36
|
+
connect(tradeAccountId: string, exchange: Connector): Promise<ExchangeConnection>;
|
|
37
|
+
createTracker(connection: ExchangeConnection): AccountTracker;
|
|
38
|
+
createHelper<E extends ExchangeHelperExchange>(exchange: E): ExchangeHelperMap[E];
|
|
39
|
+
createPositionSyncer(connection: ExchangeConnection): AccountPositionSyncer;
|
|
40
|
+
private fetchCredentials;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export { ExchangesSDK };
|
package/dist/sdk.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { createExchangeWs } from './client';
|
|
2
|
+
import './helper';
|
|
3
|
+
import { createExchangeHelper } from './helper/factory';
|
|
4
|
+
import { AccountPositionSyncer } from './syncer';
|
|
5
|
+
import { createAccountTracker } from './tracker';
|
|
6
|
+
|
|
7
|
+
class ExchangesSDK {
|
|
8
|
+
sdk;
|
|
9
|
+
demo;
|
|
10
|
+
constructor(config) {
|
|
11
|
+
this.sdk = config.sdk;
|
|
12
|
+
this.demo = config.demo ?? false;
|
|
13
|
+
}
|
|
14
|
+
async connect(tradeAccountId, exchange) {
|
|
15
|
+
const credentials = await this.fetchCredentials(tradeAccountId, exchange);
|
|
16
|
+
const ws = await createExchangeWs(exchange, { demo: this.demo, credentials });
|
|
17
|
+
return { exchange, credentials, ws };
|
|
18
|
+
}
|
|
19
|
+
createTracker(connection) {
|
|
20
|
+
return createAccountTracker(connection.exchange, {
|
|
21
|
+
demo: this.demo,
|
|
22
|
+
credentials: connection.credentials,
|
|
23
|
+
ws: connection.ws
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
createHelper(exchange) {
|
|
27
|
+
return createExchangeHelper(exchange, this.sdk);
|
|
28
|
+
}
|
|
29
|
+
createPositionSyncer(connection) {
|
|
30
|
+
return new AccountPositionSyncer({
|
|
31
|
+
sdk: this.sdk,
|
|
32
|
+
credentials: connection.credentials,
|
|
33
|
+
ws: connection.ws,
|
|
34
|
+
demo: this.demo
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
async fetchCredentials(tradeAccountId, exchange) {
|
|
38
|
+
const response = await this.sdk.core.accounts.credentials(tradeAccountId);
|
|
39
|
+
const baseCreds = response.credentials;
|
|
40
|
+
if (exchange === "hyperliquid" || exchange === "lighter") {
|
|
41
|
+
const { accounts } = await this.sdk.core.accounts.list();
|
|
42
|
+
const account = accounts.find((a) => a.id === tradeAccountId);
|
|
43
|
+
if (!account) {
|
|
44
|
+
throw new Error(`Trade account ${tradeAccountId} not found`);
|
|
45
|
+
}
|
|
46
|
+
return { ...baseCreds, accountIdentifier: account.exchangeIdentifier };
|
|
47
|
+
}
|
|
48
|
+
return baseCreds;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export { ExchangesSDK };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import PearSDK from '@pear-protocol/core-sdk';
|
|
2
|
+
import { Connector } from '@pear-protocol/types';
|
|
3
|
+
import { ExchangeWsByConnector } from '../client/index.js';
|
|
4
|
+
import { SupportedCredentials } from '../types.js';
|
|
5
|
+
import '../client/binance/exchange-ws.js';
|
|
6
|
+
import '../client/base-ws.js';
|
|
7
|
+
import 'partysocket';
|
|
8
|
+
import '../client/exchange-ws.js';
|
|
9
|
+
import '../client/binance/ws.js';
|
|
10
|
+
import '../client/bybit/exchange-ws.js';
|
|
11
|
+
import '../client/bybit/ws.js';
|
|
12
|
+
import '../client/hyperliquid/exchange-ws.js';
|
|
13
|
+
import '../client/hyperliquid/ws.js';
|
|
14
|
+
import '../client/lighter/exchange-ws.js';
|
|
15
|
+
import '../client/lighter/ws.js';
|
|
16
|
+
import '../client/okx/exchange-ws.js';
|
|
17
|
+
import '../client/okx/ws.js';
|
|
18
|
+
|
|
19
|
+
type AccountPositionSyncerConfig = {
|
|
20
|
+
sdk: PearSDK;
|
|
21
|
+
credentials: SupportedCredentials;
|
|
22
|
+
ws: ExchangeWsByConnector[Connector];
|
|
23
|
+
demo: boolean;
|
|
24
|
+
};
|
|
25
|
+
declare class AccountPositionSyncer {
|
|
26
|
+
protected sdk: PearSDK;
|
|
27
|
+
protected credentials: SupportedCredentials;
|
|
28
|
+
protected ws: ExchangeWsByConnector[Connector];
|
|
29
|
+
protected demo: boolean;
|
|
30
|
+
constructor(config: AccountPositionSyncerConfig);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export { AccountPositionSyncer, type AccountPositionSyncerConfig };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
class AccountPositionSyncer {
|
|
2
|
+
sdk;
|
|
3
|
+
credentials;
|
|
4
|
+
ws;
|
|
5
|
+
demo;
|
|
6
|
+
constructor(config) {
|
|
7
|
+
this.sdk = config.sdk;
|
|
8
|
+
this.credentials = config.credentials;
|
|
9
|
+
this.ws = config.ws;
|
|
10
|
+
this.demo = config.demo;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export { AccountPositionSyncer };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export { AccountPositionSyncer, AccountPositionSyncerConfig } from './base.js';
|
|
2
|
+
import '@pear-protocol/core-sdk';
|
|
3
|
+
import '@pear-protocol/types';
|
|
4
|
+
import '../client/index.js';
|
|
5
|
+
import '../types.js';
|
|
6
|
+
import '../client/binance/exchange-ws.js';
|
|
7
|
+
import '../client/base-ws.js';
|
|
8
|
+
import 'partysocket';
|
|
9
|
+
import '../client/exchange-ws.js';
|
|
10
|
+
import '../client/binance/ws.js';
|
|
11
|
+
import '../client/bybit/exchange-ws.js';
|
|
12
|
+
import '../client/bybit/ws.js';
|
|
13
|
+
import '../client/hyperliquid/exchange-ws.js';
|
|
14
|
+
import '../client/hyperliquid/ws.js';
|
|
15
|
+
import '../client/lighter/exchange-ws.js';
|
|
16
|
+
import '../client/lighter/ws.js';
|
|
17
|
+
import '../client/okx/exchange-ws.js';
|
|
18
|
+
import '../client/okx/ws.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './base';
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { SupportedCredentials } from '../types.js';
|
|
2
|
+
import { BalanceCallback, PositionsCallback, TrackedAssetCallback, AccountBalance, AccountPosition, TrackedAssetInfo, StateUpdate } from './types.js';
|
|
3
|
+
import '@pear-protocol/core-sdk';
|
|
4
|
+
import '@pear-protocol/types';
|
|
5
|
+
import '../client/binance/exchange-ws.js';
|
|
6
|
+
import '../client/base-ws.js';
|
|
7
|
+
import 'partysocket';
|
|
8
|
+
import '../client/exchange-ws.js';
|
|
9
|
+
import '../client/binance/ws.js';
|
|
10
|
+
import '../client/bybit/exchange-ws.js';
|
|
11
|
+
import '../client/bybit/ws.js';
|
|
12
|
+
import '../client/hyperliquid/exchange-ws.js';
|
|
13
|
+
import '../client/hyperliquid/ws.js';
|
|
14
|
+
import '../client/lighter/exchange-ws.js';
|
|
15
|
+
import '../client/lighter/ws.js';
|
|
16
|
+
import '../client/okx/exchange-ws.js';
|
|
17
|
+
import '../client/okx/ws.js';
|
|
18
|
+
import './binance/types.js';
|
|
19
|
+
import './bybit/types.js';
|
|
20
|
+
import './hyperliquid/types.js';
|
|
21
|
+
import './lighter/types.js';
|
|
22
|
+
import './okx/types.js';
|
|
23
|
+
|
|
24
|
+
type ErrorHandler = (error: Error) => void;
|
|
25
|
+
type AccountTrackerConfig = {
|
|
26
|
+
demo: boolean;
|
|
27
|
+
onError?: ErrorHandler;
|
|
28
|
+
};
|
|
29
|
+
interface AccountTracker {
|
|
30
|
+
start(): Promise<void>;
|
|
31
|
+
disconnect(): Promise<void>;
|
|
32
|
+
readonly isConnected: boolean;
|
|
33
|
+
readonly isInitialized: boolean;
|
|
34
|
+
readonly hasListeners: boolean;
|
|
35
|
+
trackBalance(cb: BalanceCallback): () => void;
|
|
36
|
+
trackPosition(cb: PositionsCallback): () => void;
|
|
37
|
+
trackAsset(asset: string, cb: TrackedAssetCallback): () => void;
|
|
38
|
+
getBalance(): AccountBalance | null;
|
|
39
|
+
getPositions(): AccountPosition[];
|
|
40
|
+
getTrackedAsset(coin: string): TrackedAssetInfo | null;
|
|
41
|
+
}
|
|
42
|
+
declare abstract class BaseAccountTracker implements AccountTracker {
|
|
43
|
+
protected onError: ErrorHandler;
|
|
44
|
+
protected demo: boolean;
|
|
45
|
+
protected credentials: SupportedCredentials | null;
|
|
46
|
+
private balance;
|
|
47
|
+
private positions;
|
|
48
|
+
private initialized;
|
|
49
|
+
private balanceListeners;
|
|
50
|
+
private positionListeners;
|
|
51
|
+
private assetEntries;
|
|
52
|
+
constructor(config: AccountTrackerConfig);
|
|
53
|
+
disconnect(): Promise<void>;
|
|
54
|
+
get isInitialized(): boolean;
|
|
55
|
+
get hasListeners(): boolean;
|
|
56
|
+
trackBalance(cb: BalanceCallback): () => void;
|
|
57
|
+
trackPosition(cb: PositionsCallback): () => void;
|
|
58
|
+
trackAsset(asset: string, cb: TrackedAssetCallback): () => void;
|
|
59
|
+
private releaseAssetListener;
|
|
60
|
+
protected get trackedCoins(): ReadonlySet<string>;
|
|
61
|
+
getBalance(): AccountBalance | null;
|
|
62
|
+
getPositions(): AccountPosition[];
|
|
63
|
+
getTrackedAsset(coin: string): TrackedAssetInfo | null;
|
|
64
|
+
protected onStateUpdate(update: StateUpdate): void;
|
|
65
|
+
private applyBalanceUpdate;
|
|
66
|
+
private applyPositionsUpdate;
|
|
67
|
+
private applyTrackedAssetsUpdate;
|
|
68
|
+
private getOrCreateAssetEntry;
|
|
69
|
+
private positionSnapshot;
|
|
70
|
+
private notify;
|
|
71
|
+
private broadcast;
|
|
72
|
+
abstract start(): Promise<void>;
|
|
73
|
+
abstract get isConnected(): boolean;
|
|
74
|
+
protected abstract ensureAssetTracked(asset: string): void;
|
|
75
|
+
protected abstract releaseAsset(asset: string): void;
|
|
76
|
+
protected abstract cleanupConnections(): void | Promise<void>;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export { type AccountTracker, type AccountTrackerConfig, BaseAccountTracker };
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
class BaseAccountTracker {
|
|
2
|
+
onError;
|
|
3
|
+
demo;
|
|
4
|
+
credentials = null;
|
|
5
|
+
balance = null;
|
|
6
|
+
positions = /* @__PURE__ */ new Map();
|
|
7
|
+
initialized = false;
|
|
8
|
+
balanceListeners = /* @__PURE__ */ new Set();
|
|
9
|
+
positionListeners = /* @__PURE__ */ new Set();
|
|
10
|
+
assetEntries = /* @__PURE__ */ new Map();
|
|
11
|
+
constructor(config) {
|
|
12
|
+
this.demo = config.demo;
|
|
13
|
+
this.onError = (error) => {
|
|
14
|
+
console.warn("[AccountTracker] error:", error.message);
|
|
15
|
+
config.onError?.(error);
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
async disconnect() {
|
|
19
|
+
this.balanceListeners.clear();
|
|
20
|
+
this.positionListeners.clear();
|
|
21
|
+
this.assetEntries.clear();
|
|
22
|
+
await this.cleanupConnections();
|
|
23
|
+
}
|
|
24
|
+
get isInitialized() {
|
|
25
|
+
return this.initialized;
|
|
26
|
+
}
|
|
27
|
+
get hasListeners() {
|
|
28
|
+
if (this.balanceListeners.size > 0 || this.positionListeners.size > 0) return true;
|
|
29
|
+
for (const entry of this.assetEntries.values()) {
|
|
30
|
+
if (entry.listeners.size > 0) return true;
|
|
31
|
+
}
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
trackBalance(cb) {
|
|
35
|
+
this.balanceListeners.add(cb);
|
|
36
|
+
if (this.balance) this.notify(cb, this.balance);
|
|
37
|
+
return () => this.balanceListeners.delete(cb);
|
|
38
|
+
}
|
|
39
|
+
trackPosition(cb) {
|
|
40
|
+
this.positionListeners.add(cb);
|
|
41
|
+
if (this.initialized) this.notify(cb, this.positionSnapshot());
|
|
42
|
+
return () => this.positionListeners.delete(cb);
|
|
43
|
+
}
|
|
44
|
+
trackAsset(asset, cb) {
|
|
45
|
+
const entry = this.getOrCreateAssetEntry(asset);
|
|
46
|
+
entry.listeners.add(cb);
|
|
47
|
+
if (this.isConnected) this.ensureAssetTracked(asset);
|
|
48
|
+
if (entry.info) this.notify(cb, entry.info);
|
|
49
|
+
return () => this.releaseAssetListener(asset, cb);
|
|
50
|
+
}
|
|
51
|
+
releaseAssetListener(asset, cb) {
|
|
52
|
+
const entry = this.assetEntries.get(asset);
|
|
53
|
+
if (!entry) return;
|
|
54
|
+
entry.listeners.delete(cb);
|
|
55
|
+
if (entry.listeners.size === 0 && this.isConnected) {
|
|
56
|
+
this.releaseAsset(asset);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
get trackedCoins() {
|
|
60
|
+
return new Set(
|
|
61
|
+
[...this.assetEntries.entries()].filter(([, entry]) => entry.listeners.size > 0).map(([coin]) => coin)
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
getBalance() {
|
|
65
|
+
return this.balance;
|
|
66
|
+
}
|
|
67
|
+
getPositions() {
|
|
68
|
+
return this.positionSnapshot();
|
|
69
|
+
}
|
|
70
|
+
getTrackedAsset(coin) {
|
|
71
|
+
return this.assetEntries.get(coin)?.info ?? null;
|
|
72
|
+
}
|
|
73
|
+
onStateUpdate(update) {
|
|
74
|
+
if (update.balance) this.applyBalanceUpdate(update.balance);
|
|
75
|
+
if (update.positions) this.applyPositionsUpdate(update.positions);
|
|
76
|
+
if (update.trackedAssets) this.applyTrackedAssetsUpdate(update.trackedAssets);
|
|
77
|
+
if (!this.initialized) this.initialized = true;
|
|
78
|
+
}
|
|
79
|
+
applyBalanceUpdate(balance) {
|
|
80
|
+
this.balance = balance;
|
|
81
|
+
this.broadcast(this.balanceListeners, balance);
|
|
82
|
+
}
|
|
83
|
+
applyPositionsUpdate(positions) {
|
|
84
|
+
for (const [key, pos] of positions) {
|
|
85
|
+
if (pos.size === "0") this.positions.delete(key);
|
|
86
|
+
else this.positions.set(key, pos);
|
|
87
|
+
}
|
|
88
|
+
this.broadcast(this.positionListeners, this.positionSnapshot());
|
|
89
|
+
}
|
|
90
|
+
applyTrackedAssetsUpdate(trackedAssets) {
|
|
91
|
+
for (const [coin, info] of trackedAssets) {
|
|
92
|
+
const entry = this.getOrCreateAssetEntry(coin);
|
|
93
|
+
entry.info = info;
|
|
94
|
+
this.broadcast(entry.listeners, info);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
getOrCreateAssetEntry(coin) {
|
|
98
|
+
let entry = this.assetEntries.get(coin);
|
|
99
|
+
if (!entry) {
|
|
100
|
+
entry = { info: null, listeners: /* @__PURE__ */ new Set() };
|
|
101
|
+
this.assetEntries.set(coin, entry);
|
|
102
|
+
}
|
|
103
|
+
return entry;
|
|
104
|
+
}
|
|
105
|
+
positionSnapshot() {
|
|
106
|
+
return Array.from(this.positions.values());
|
|
107
|
+
}
|
|
108
|
+
notify(cb, arg) {
|
|
109
|
+
try {
|
|
110
|
+
cb(arg);
|
|
111
|
+
} catch (err) {
|
|
112
|
+
this.onError(err instanceof Error ? err : new Error(String(err)));
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
broadcast(listeners, arg) {
|
|
116
|
+
for (const cb of listeners) this.notify(cb, arg);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export { BaseAccountTracker };
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BinanceRawAccountStatus, BinanceRawPositionRisk } from '../../client/binance/types.js';
|
|
2
|
+
import { AccountBalance, AccountPosition } from '../types.js';
|
|
2
3
|
import '@pear-protocol/types';
|
|
4
|
+
import './types.js';
|
|
3
5
|
import '../bybit/types.js';
|
|
4
6
|
import '../hyperliquid/types.js';
|
|
7
|
+
import '../lighter/types.js';
|
|
5
8
|
import '../okx/types.js';
|
|
6
9
|
|
|
7
10
|
declare function mapBalance(raw: BinanceRawAccountStatus): Omit<AccountBalance, 'accountType'>;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import '
|
|
2
|
-
import
|
|
1
|
+
import BigNumber from 'bignumber.js';
|
|
2
|
+
import '../types';
|
|
3
|
+
import { positionKey } from '../utils';
|
|
3
4
|
|
|
4
5
|
function mapBalance(raw) {
|
|
5
6
|
const free = {};
|
|
@@ -11,7 +12,7 @@ function mapBalance(raw) {
|
|
|
11
12
|
const ab = a.availableBalance ?? "0";
|
|
12
13
|
const mb = a.marginBalance ?? "0";
|
|
13
14
|
const im = a.initialMargin ?? "0";
|
|
14
|
-
if (
|
|
15
|
+
if (new BigNumber(wb).isZero() && new BigNumber(ab).isZero() && new BigNumber(mb).isZero()) continue;
|
|
15
16
|
free[a.asset] = ab;
|
|
16
17
|
used[a.asset] = im;
|
|
17
18
|
total[a.asset] = mb;
|
|
@@ -26,9 +27,9 @@ function mapBalance(raw) {
|
|
|
26
27
|
}
|
|
27
28
|
const totalMarginBalance = raw.totalMarginBalance ?? "0";
|
|
28
29
|
const totalMaintMargin = raw.totalMaintMargin ?? "0";
|
|
29
|
-
const
|
|
30
|
-
const
|
|
31
|
-
const marginRatio =
|
|
30
|
+
const marginBalanceBN = new BigNumber(totalMarginBalance);
|
|
31
|
+
const maintMarginBN = new BigNumber(totalMaintMargin);
|
|
32
|
+
const marginRatio = marginBalanceBN.gt(0) ? maintMarginBN.div(marginBalanceBN).toFixed(4) : "0.0000";
|
|
32
33
|
return {
|
|
33
34
|
free,
|
|
34
35
|
used,
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { BinanceUserDataWs, BinanceWsApi } from '../../client/binance/ws.js';
|
|
2
|
+
import { SupportedCredentials } from '../../types.js';
|
|
3
|
+
import { BaseAccountTracker, AccountTrackerConfig } from '../base.js';
|
|
4
|
+
import '@pear-protocol/types';
|
|
5
|
+
import '../../client/base-ws.js';
|
|
6
|
+
import 'partysocket';
|
|
7
|
+
import '@pear-protocol/core-sdk';
|
|
8
|
+
import '../../client/binance/exchange-ws.js';
|
|
9
|
+
import '../../client/exchange-ws.js';
|
|
10
|
+
import '../../client/bybit/exchange-ws.js';
|
|
11
|
+
import '../../client/bybit/ws.js';
|
|
12
|
+
import '../../client/hyperliquid/exchange-ws.js';
|
|
13
|
+
import '../../client/hyperliquid/ws.js';
|
|
14
|
+
import '../../client/lighter/exchange-ws.js';
|
|
15
|
+
import '../../client/lighter/ws.js';
|
|
16
|
+
import '../../client/okx/exchange-ws.js';
|
|
17
|
+
import '../../client/okx/ws.js';
|
|
18
|
+
import '../types.js';
|
|
19
|
+
import './types.js';
|
|
20
|
+
import '../bybit/types.js';
|
|
21
|
+
import '../hyperliquid/types.js';
|
|
22
|
+
import '../lighter/types.js';
|
|
23
|
+
import '../okx/types.js';
|
|
24
|
+
|
|
25
|
+
type BinanceAccountTrackerConfig = AccountTrackerConfig & {
|
|
26
|
+
credentials: SupportedCredentials;
|
|
27
|
+
userDataWs: BinanceUserDataWs;
|
|
28
|
+
wsApiWs: BinanceWsApi;
|
|
29
|
+
listenKeyRefreshMs?: number;
|
|
30
|
+
accountPollMs?: number;
|
|
31
|
+
};
|
|
32
|
+
declare class BinanceAccountTracker extends BaseAccountTracker {
|
|
33
|
+
private readonly creds;
|
|
34
|
+
private readonly userDataWs;
|
|
35
|
+
private readonly wsApiWs;
|
|
36
|
+
private readonly listenKeyRefreshMs;
|
|
37
|
+
private readonly accountPollMs;
|
|
38
|
+
private userDataListenerId;
|
|
39
|
+
private wsApiListenerId;
|
|
40
|
+
private listenKeyTimer;
|
|
41
|
+
private pollTimer;
|
|
42
|
+
private currentPositions;
|
|
43
|
+
private accountType;
|
|
44
|
+
private trackedAssetInfos;
|
|
45
|
+
constructor(config: BinanceAccountTrackerConfig);
|
|
46
|
+
start(): Promise<void>;
|
|
47
|
+
protected cleanupConnections(): Promise<void>;
|
|
48
|
+
get isConnected(): boolean;
|
|
49
|
+
protected ensureAssetTracked(coin: string): void;
|
|
50
|
+
protected releaseAsset(coin: string): void;
|
|
51
|
+
private pollAccountStatus;
|
|
52
|
+
private routeUserData;
|
|
53
|
+
private routeWsApi;
|
|
54
|
+
private handleAccountStatus;
|
|
55
|
+
private handlePositionRisk;
|
|
56
|
+
private handleUserDataEvent;
|
|
57
|
+
private refreshAllPositions;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export { BinanceAccountTracker, type BinanceAccountTrackerConfig };
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { fetchAccountStatus, fetchAllPositionRisk, fetchMultiAssetsMargin, keepAliveListenKey, fetchPositionRisk } from '../../client/binance/rest';
|
|
2
|
+
import { BaseAccountTracker } from '../base';
|
|
3
|
+
import { positionKey } from '../utils';
|
|
4
|
+
import { DEFAULT_LISTEN_KEY_REFRESH_MS, DEFAULT_ACCOUNT_POLL_MS } from './const';
|
|
5
|
+
import { mapBalance, mapPositions, mergePositions } from './mapper';
|
|
6
|
+
import { BinanceAccountType } from './types';
|
|
7
|
+
|
|
8
|
+
class BinanceAccountTracker extends BaseAccountTracker {
|
|
9
|
+
creds;
|
|
10
|
+
userDataWs;
|
|
11
|
+
wsApiWs;
|
|
12
|
+
listenKeyRefreshMs;
|
|
13
|
+
accountPollMs;
|
|
14
|
+
userDataListenerId = null;
|
|
15
|
+
wsApiListenerId = null;
|
|
16
|
+
listenKeyTimer = null;
|
|
17
|
+
pollTimer = null;
|
|
18
|
+
currentPositions = /* @__PURE__ */ new Map();
|
|
19
|
+
accountType = BinanceAccountType.SINGLE_ASSET;
|
|
20
|
+
trackedAssetInfos = /* @__PURE__ */ new Map();
|
|
21
|
+
constructor(config) {
|
|
22
|
+
super(config);
|
|
23
|
+
this.credentials = config.credentials;
|
|
24
|
+
this.creds = config.credentials;
|
|
25
|
+
this.userDataWs = config.userDataWs;
|
|
26
|
+
this.wsApiWs = config.wsApiWs;
|
|
27
|
+
this.listenKeyRefreshMs = config.listenKeyRefreshMs ?? DEFAULT_LISTEN_KEY_REFRESH_MS;
|
|
28
|
+
this.accountPollMs = config.accountPollMs ?? DEFAULT_ACCOUNT_POLL_MS;
|
|
29
|
+
}
|
|
30
|
+
async start() {
|
|
31
|
+
const [snapshot, positionRisk, multiAssetsMargin] = await Promise.all([
|
|
32
|
+
fetchAccountStatus(this.creds, this.demo),
|
|
33
|
+
fetchAllPositionRisk(this.creds, this.demo),
|
|
34
|
+
fetchMultiAssetsMargin(this.creds, this.demo)
|
|
35
|
+
]);
|
|
36
|
+
this.accountType = multiAssetsMargin ? BinanceAccountType.MULTI_ASSET : BinanceAccountType.SINGLE_ASSET;
|
|
37
|
+
this.handleAccountStatus(snapshot);
|
|
38
|
+
this.handlePositionRisk(positionRisk, false);
|
|
39
|
+
this.userDataListenerId = this.userDataWs.addMessageListener((raw) => this.routeUserData(raw));
|
|
40
|
+
this.wsApiListenerId = this.wsApiWs.addMessageListener((raw) => this.routeWsApi(raw));
|
|
41
|
+
this.listenKeyTimer = setInterval(() => {
|
|
42
|
+
keepAliveListenKey(this.creds.read.api_key, this.demo).catch(
|
|
43
|
+
(err) => this.onError(err instanceof Error ? err : new Error(String(err)))
|
|
44
|
+
);
|
|
45
|
+
}, this.listenKeyRefreshMs);
|
|
46
|
+
this.pollAccountStatus();
|
|
47
|
+
this.pollTimer = setInterval(() => this.pollAccountStatus(), this.accountPollMs);
|
|
48
|
+
}
|
|
49
|
+
async cleanupConnections() {
|
|
50
|
+
if (this.listenKeyTimer) clearInterval(this.listenKeyTimer);
|
|
51
|
+
this.listenKeyTimer = null;
|
|
52
|
+
if (this.pollTimer) clearInterval(this.pollTimer);
|
|
53
|
+
this.pollTimer = null;
|
|
54
|
+
if (this.userDataListenerId) {
|
|
55
|
+
this.userDataWs.removeMessageListener(this.userDataListenerId);
|
|
56
|
+
this.userDataListenerId = null;
|
|
57
|
+
}
|
|
58
|
+
if (this.wsApiListenerId) {
|
|
59
|
+
this.wsApiWs.removeMessageListener(this.wsApiListenerId);
|
|
60
|
+
this.wsApiListenerId = null;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
get isConnected() {
|
|
64
|
+
return this.userDataWs.connected && this.wsApiWs.connected;
|
|
65
|
+
}
|
|
66
|
+
ensureAssetTracked(coin) {
|
|
67
|
+
if (this.trackedAssetInfos.has(coin)) return;
|
|
68
|
+
fetchPositionRisk(this.creds, coin, this.demo).then((risk) => {
|
|
69
|
+
if (!risk) return;
|
|
70
|
+
const leverage = risk.leverage;
|
|
71
|
+
const marginType = risk.marginType;
|
|
72
|
+
const info = { coin, leverage, marginType };
|
|
73
|
+
this.trackedAssetInfos.set(coin, info);
|
|
74
|
+
const trackedAssets = /* @__PURE__ */ new Map();
|
|
75
|
+
trackedAssets.set(coin, info);
|
|
76
|
+
this.onStateUpdate({ trackedAssets });
|
|
77
|
+
}).catch((err) => {
|
|
78
|
+
this.onError(err instanceof Error ? err : new Error(String(err)));
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
releaseAsset(coin) {
|
|
82
|
+
this.trackedAssetInfos.delete(coin);
|
|
83
|
+
this.onStateUpdate({ trackedAssets: new Map(this.trackedAssetInfos) });
|
|
84
|
+
}
|
|
85
|
+
pollAccountStatus() {
|
|
86
|
+
if (!this.wsApiWs.connected) return;
|
|
87
|
+
this.wsApiWs.sendSignedRequest(this.creds, "v2/account.status").catch((err) => {
|
|
88
|
+
this.onError(err instanceof Error ? err : new Error(String(err)));
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
routeUserData(raw) {
|
|
92
|
+
try {
|
|
93
|
+
const event = JSON.parse(raw);
|
|
94
|
+
this.handleUserDataEvent(event);
|
|
95
|
+
} catch (err) {
|
|
96
|
+
this.onError(err instanceof Error ? err : new Error(String(err)));
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
routeWsApi(raw) {
|
|
100
|
+
try {
|
|
101
|
+
const msg = JSON.parse(raw);
|
|
102
|
+
if (msg.id !== void 0 && msg.result !== void 0) {
|
|
103
|
+
this.handleAccountStatus(msg.result);
|
|
104
|
+
}
|
|
105
|
+
} catch (err) {
|
|
106
|
+
this.onError(err instanceof Error ? err : new Error(String(err)));
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
handleAccountStatus(result) {
|
|
110
|
+
const balance = { ...mapBalance(result), accountType: this.accountType };
|
|
111
|
+
this.onStateUpdate({ balance });
|
|
112
|
+
}
|
|
113
|
+
handlePositionRisk(risk, merge) {
|
|
114
|
+
let positions = mapPositions(risk);
|
|
115
|
+
if (merge && this.currentPositions.size > 0) {
|
|
116
|
+
positions = mergePositions(positions, this.currentPositions);
|
|
117
|
+
}
|
|
118
|
+
this.currentPositions = positions;
|
|
119
|
+
this.onStateUpdate({ positions });
|
|
120
|
+
}
|
|
121
|
+
handleUserDataEvent(event) {
|
|
122
|
+
if (event.e === "ACCOUNT_CONFIG_UPDATE" && event.ac) {
|
|
123
|
+
const symbol = event.ac.s ?? "";
|
|
124
|
+
const leverage = event.ac.l ?? "0";
|
|
125
|
+
if (symbol && leverage !== "0") {
|
|
126
|
+
const existing = this.trackedAssetInfos.get(symbol);
|
|
127
|
+
if (existing) {
|
|
128
|
+
const updated = { ...existing, leverage };
|
|
129
|
+
this.trackedAssetInfos.set(symbol, updated);
|
|
130
|
+
const trackedAssets = /* @__PURE__ */ new Map();
|
|
131
|
+
trackedAssets.set(symbol, updated);
|
|
132
|
+
this.onStateUpdate({ trackedAssets });
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
this.refreshAllPositions();
|
|
136
|
+
}
|
|
137
|
+
if (event.e === "ACCOUNT_UPDATE") {
|
|
138
|
+
this.refreshAllPositions();
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
refreshAllPositions() {
|
|
142
|
+
const symbols = /* @__PURE__ */ new Set();
|
|
143
|
+
for (const pos of this.currentPositions.values()) symbols.add(pos.symbol);
|
|
144
|
+
for (const coin of this.trackedCoins) symbols.add(coin);
|
|
145
|
+
if (symbols.size === 0) return;
|
|
146
|
+
const promises = Array.from(symbols).map(
|
|
147
|
+
(symbol) => fetchPositionRisk(this.creds, symbol, this.demo).catch(() => void 0)
|
|
148
|
+
);
|
|
149
|
+
Promise.all(promises).then((results) => {
|
|
150
|
+
const freshPositions = /* @__PURE__ */ new Map();
|
|
151
|
+
for (const risk of results) {
|
|
152
|
+
if (!risk) continue;
|
|
153
|
+
const amt = risk.positionAmt ?? "0";
|
|
154
|
+
if (amt === "0" || amt === "") continue;
|
|
155
|
+
const symbol = risk.symbol ?? "";
|
|
156
|
+
const side = amt.startsWith("-") ? "short" : "long";
|
|
157
|
+
freshPositions.set(positionKey(symbol, side), {
|
|
158
|
+
symbol,
|
|
159
|
+
side,
|
|
160
|
+
size: amt,
|
|
161
|
+
entryPrice: risk.entryPrice ?? "0",
|
|
162
|
+
unrealizedPnl: risk.unRealizedProfit ?? "0",
|
|
163
|
+
leverage: risk.leverage ?? "0",
|
|
164
|
+
marginType: risk.marginType,
|
|
165
|
+
liquidationPrice: risk.liquidationPrice || null
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
for (const [key, pos] of this.currentPositions) {
|
|
169
|
+
if (!symbols.has(pos.symbol) && !freshPositions.has(key)) {
|
|
170
|
+
freshPositions.set(key, pos);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
this.currentPositions = freshPositions;
|
|
174
|
+
this.onStateUpdate({ positions: freshPositions });
|
|
175
|
+
}).catch((err) => {
|
|
176
|
+
this.onError(err instanceof Error ? err : new Error(String(err)));
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export { BinanceAccountTracker };
|