@pear-protocol/exchanges-sdk 0.0.10 → 0.0.11

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.
Files changed (60) hide show
  1. package/README.md +59 -42
  2. package/dist/account/account-manager.d.ts +5 -11
  3. package/dist/account/account-manager.js +22 -60
  4. package/dist/account/exchange-account.d.ts +8 -10
  5. package/dist/account/exchange-account.js +30 -57
  6. package/dist/account/exchanges/base.d.ts +13 -15
  7. package/dist/account/exchanges/base.js +5 -27
  8. package/dist/account/exchanges/binance/asset-tracker.d.ts +25 -0
  9. package/dist/account/exchanges/binance/asset-tracker.js +38 -0
  10. package/dist/account/exchanges/binance/mapper.d.ts +4 -3
  11. package/dist/account/exchanges/binance/mapper.js +0 -1
  12. package/dist/account/exchanges/binance/orchestrator.d.ts +9 -12
  13. package/dist/account/exchanges/binance/orchestrator.js +61 -183
  14. package/dist/account/exchanges/binance/rest.d.ts +5 -4
  15. package/dist/account/exchanges/binance/rest.js +4 -20
  16. package/dist/account/exchanges/binance/state-handler.d.ts +32 -0
  17. package/dist/account/exchanges/binance/state-handler.js +113 -0
  18. package/dist/account/exchanges/binance/types.d.ts +3 -76
  19. package/dist/account/exchanges/binance/types.js +6 -0
  20. package/dist/account/exchanges/binance/ws.d.ts +3 -2
  21. package/dist/account/exchanges/binance/ws.js +6 -22
  22. package/dist/account/exchanges/bybit/asset-tracker.d.ts +25 -0
  23. package/dist/account/exchanges/bybit/asset-tracker.js +37 -0
  24. package/dist/account/exchanges/bybit/mapper.d.ts +4 -3
  25. package/dist/account/exchanges/bybit/mapper.js +5 -3
  26. package/dist/account/exchanges/bybit/orchestrator.d.ts +11 -12
  27. package/dist/account/exchanges/bybit/orchestrator.js +48 -134
  28. package/dist/account/exchanges/bybit/rest.d.ts +2 -3
  29. package/dist/account/exchanges/bybit/rest.js +4 -39
  30. package/dist/account/exchanges/bybit/state-handler.d.ts +22 -0
  31. package/dist/account/exchanges/bybit/state-handler.js +70 -0
  32. package/dist/account/exchanges/bybit/types.d.ts +14 -3
  33. package/dist/account/exchanges/bybit/types.js +7 -0
  34. package/dist/account/exchanges/bybit/ws.d.ts +1 -0
  35. package/dist/account/exchanges/bybit/ws.js +21 -12
  36. package/dist/account/exchanges/hyperliquid/asset-tracker.d.ts +34 -0
  37. package/dist/account/exchanges/hyperliquid/asset-tracker.js +83 -0
  38. package/dist/account/exchanges/hyperliquid/mapper.d.ts +4 -4
  39. package/dist/account/exchanges/hyperliquid/mapper.js +1 -0
  40. package/dist/account/exchanges/hyperliquid/orchestrator.d.ts +15 -28
  41. package/dist/account/exchanges/hyperliquid/orchestrator.js +79 -216
  42. package/dist/account/exchanges/hyperliquid/state-handler.d.ts +24 -0
  43. package/dist/account/exchanges/hyperliquid/state-handler.js +104 -0
  44. package/dist/account/exchanges/hyperliquid/types.d.ts +119 -5
  45. package/dist/account/exchanges/hyperliquid/types.js +9 -1
  46. package/dist/account/exchanges/index.d.ts +7 -5
  47. package/dist/account/exchanges/index.js +12 -4
  48. package/dist/account/index.d.ts +3 -1
  49. package/dist/account/types.d.ts +4 -73
  50. package/dist/account/types.js +17 -0
  51. package/dist/account/utils.d.ts +3 -1
  52. package/dist/index.d.ts +3 -1
  53. package/dist/types-D2dbAtin.d.ts +150 -0
  54. package/dist/utils/hmac.d.ts +1 -2
  55. package/dist/utils/hmac.js +1 -8
  56. package/dist/utils/ws.d.ts +6 -3
  57. package/dist/utils/ws.js +24 -7
  58. package/package.json +3 -3
  59. package/dist/account/exchanges/hyperliquid/rest.d.ts +0 -6
  60. package/dist/account/exchanges/hyperliquid/rest.js +0 -11
@@ -0,0 +1,70 @@
1
+ import { mergeRawCoins, buildBalance, mapPositions, mapPositionUpdates } from './mapper';
2
+ import './types';
3
+
4
+ class BybitStateHandler {
5
+ onStateUpdate;
6
+ getTrackedAssetInfos;
7
+ rawCoins = /* @__PURE__ */ new Map();
8
+ lastWallet = null;
9
+ accountType = null;
10
+ constructor(deps) {
11
+ this.onStateUpdate = deps.onStateUpdate;
12
+ this.getTrackedAssetInfos = deps.getTrackedAssetInfos;
13
+ }
14
+ handleInitialData(wallet, positions, accountType) {
15
+ this.accountType = accountType;
16
+ if (wallet) {
17
+ this.lastWallet = wallet;
18
+ this.rawCoins = mergeRawCoins(/* @__PURE__ */ new Map(), wallet.coin ?? []);
19
+ const balance = buildBalance(wallet, this.rawCoins, this.accountType);
20
+ if (balance) this.onStateUpdate({ balance });
21
+ }
22
+ this.onStateUpdate({ positions: mapPositions(positions) });
23
+ }
24
+ handleMessage(msg) {
25
+ if (msg.topic === "wallet") {
26
+ const wallet = msg.data[0];
27
+ if (wallet) this.handleWalletUpdate(wallet);
28
+ } else if (msg.topic === "position") {
29
+ const rawPositions = msg.data;
30
+ const positions = mapPositionUpdates(rawPositions);
31
+ if (positions.size > 0) {
32
+ const trackedAssetInfos = this.getTrackedAssetInfos();
33
+ const trackedAssets = /* @__PURE__ */ new Map();
34
+ for (const pos of rawPositions) {
35
+ const existing = trackedAssetInfos.get(pos.symbol);
36
+ if (existing) {
37
+ const leverage = pos.leverage || existing.leverage;
38
+ const marginType = pos.tradeMode === "1" ? "isolated" : "cross";
39
+ const updated = { ...existing, leverage, marginType };
40
+ trackedAssetInfos.set(pos.symbol, updated);
41
+ trackedAssets.set(pos.symbol, updated);
42
+ }
43
+ }
44
+ this.onStateUpdate({
45
+ positions,
46
+ ...trackedAssets.size > 0 ? { trackedAssets } : {}
47
+ });
48
+ }
49
+ }
50
+ }
51
+ handleWalletUpdate(raw) {
52
+ this.rawCoins = mergeRawCoins(this.rawCoins, raw.coin ?? []);
53
+ const merged = this.lastWallet ? {
54
+ totalEquity: raw.totalEquity || this.lastWallet.totalEquity,
55
+ totalWalletBalance: raw.totalWalletBalance || this.lastWallet.totalWalletBalance,
56
+ totalMarginBalance: raw.totalMarginBalance || this.lastWallet.totalMarginBalance,
57
+ totalAvailableBalance: raw.totalAvailableBalance || this.lastWallet.totalAvailableBalance,
58
+ totalPerpUPL: raw.totalPerpUPL || this.lastWallet.totalPerpUPL,
59
+ totalInitialMargin: raw.totalInitialMargin || this.lastWallet.totalInitialMargin,
60
+ totalMaintenanceMargin: raw.totalMaintenanceMargin || this.lastWallet.totalMaintenanceMargin,
61
+ accountMMRate: raw.accountMMRate || this.lastWallet.accountMMRate,
62
+ coin: raw.coin ?? this.lastWallet.coin
63
+ } : raw;
64
+ this.lastWallet = merged;
65
+ const balance = buildBalance(merged, this.rawCoins, this.accountType);
66
+ if (balance) this.onStateUpdate({ balance });
67
+ }
68
+ }
69
+
70
+ export { BybitStateHandler };
@@ -23,6 +23,11 @@ interface BybitRawWallet {
23
23
  accountMMRate: string;
24
24
  coin: BybitRawCoin[];
25
25
  }
26
+ declare enum BybitAccountType {
27
+ ISOLATED_MARGIN = "ISOLATED_MARGIN",
28
+ REGULAR_MARGIN = "REGULAR_MARGIN",
29
+ PORTFOLIO_MARGIN = "PORTFOLIO_MARGIN"
30
+ }
26
31
  interface BybitRawAccountInfo {
27
32
  marginMode: string;
28
33
  updatedTime: string;
@@ -51,9 +56,15 @@ interface BybitResponse<T> {
51
56
  retMsg: string;
52
57
  result: T;
53
58
  }
59
+ type BybitWsMessage = {
60
+ topic: 'wallet';
61
+ data: BybitRawWallet[];
62
+ } | {
63
+ topic: 'position';
64
+ data: BybitRawPosition[];
65
+ };
54
66
  interface BybitWsHandlers {
55
- onMessage: (topic: string, data: unknown[]) => void;
56
- onClose: () => void;
67
+ onMessage: (msg: BybitWsMessage) => void;
57
68
  }
58
69
 
59
- export type { BybitRawAccountInfo, BybitRawCoin, BybitRawCollateralRatioEntry, BybitRawCollateralTier, BybitRawPosition, BybitRawWallet, BybitResponse, BybitWsHandlers };
70
+ export { BybitAccountType, type BybitRawAccountInfo, type BybitRawCoin, type BybitRawCollateralRatioEntry, type BybitRawCollateralTier, type BybitRawPosition, type BybitRawWallet, type BybitResponse, type BybitWsHandlers, type BybitWsMessage };
@@ -1 +1,8 @@
1
+ var BybitAccountType = /* @__PURE__ */ ((BybitAccountType2) => {
2
+ BybitAccountType2["ISOLATED_MARGIN"] = "ISOLATED_MARGIN";
3
+ BybitAccountType2["REGULAR_MARGIN"] = "REGULAR_MARGIN";
4
+ BybitAccountType2["PORTFOLIO_MARGIN"] = "PORTFOLIO_MARGIN";
5
+ return BybitAccountType2;
6
+ })(BybitAccountType || {});
1
7
 
8
+ export { BybitAccountType };
@@ -6,6 +6,7 @@ declare class BybitWs {
6
6
  private pingTimer;
7
7
  private handlers;
8
8
  private demo;
9
+ private creds;
9
10
  private readonly pingIntervalMs;
10
11
  constructor(handlers: BybitWsHandlers, demo: boolean, pingIntervalMs?: number);
11
12
  connect(creds: BybitCredentialsDTO): Promise<void>;
@@ -1,5 +1,5 @@
1
1
  import { hmacSha256Hex } from '../../../utils/hmac';
2
- import { connectWs, sendWs, clearIntervalTimer } from '../../../utils/ws';
2
+ import { createWs, sendWs, waitForOpen, ReconnectingWebSocket, clearIntervalTimer } from '../../../utils/ws';
3
3
  import { DEFAULT_PING_INTERVAL_MS, WS_URL_DEMO, WS_URL } from './const';
4
4
 
5
5
  class BybitWs {
@@ -7,6 +7,7 @@ class BybitWs {
7
7
  pingTimer = null;
8
8
  handlers;
9
9
  demo;
10
+ creds = null;
10
11
  pingIntervalMs;
11
12
  constructor(handlers, demo, pingIntervalMs = DEFAULT_PING_INTERVAL_MS) {
12
13
  this.handlers = handlers;
@@ -14,36 +15,44 @@ class BybitWs {
14
15
  this.pingIntervalMs = pingIntervalMs;
15
16
  }
16
17
  async connect(creds) {
17
- this.ws = await connectWs(this.demo ? WS_URL_DEMO : WS_URL);
18
- this.ws.onclose = () => {
19
- this.clearPing();
20
- this.handlers.onClose();
21
- };
22
- this.ws.onerror = () => {
23
- };
18
+ this.creds = creds;
19
+ this.ws = createWs(this.demo ? WS_URL_DEMO : WS_URL);
24
20
  this.ws.addEventListener("message", (event) => {
25
21
  try {
26
22
  const msg = JSON.parse(event.data);
27
23
  if (msg.topic && msg.data) {
28
- this.handlers.onMessage(msg.topic, msg.data);
24
+ this.handlers.onMessage({ topic: msg.topic, data: msg.data });
29
25
  }
30
26
  } catch {
31
27
  }
32
28
  });
29
+ let initialOpen = true;
30
+ this.ws.addEventListener("open", () => {
31
+ if (initialOpen) {
32
+ initialOpen = false;
33
+ return;
34
+ }
35
+ if (!this.creds) return;
36
+ this.authenticate(this.creds).then(() => {
37
+ sendWs(this.ws, { op: "subscribe", args: ["wallet", "position"] });
38
+ }).catch(() => {
39
+ });
40
+ });
41
+ await waitForOpen(this.ws);
33
42
  await this.authenticate(creds);
34
- sendWs(this.ws, { op: "subscribe", args: ["wallet", "position", "execution"] });
43
+ sendWs(this.ws, { op: "subscribe", args: ["wallet", "position"] });
35
44
  this.pingTimer = setInterval(() => sendWs(this.ws, { op: "ping" }), this.pingIntervalMs);
36
45
  }
37
46
  close() {
38
47
  this.clearPing();
48
+ this.creds = null;
39
49
  if (this.ws) {
40
- this.ws.onclose = null;
41
50
  this.ws.close();
42
51
  this.ws = null;
43
52
  }
44
53
  }
45
54
  get isConnected() {
46
- return this.ws?.readyState === WebSocket.OPEN;
55
+ return this.ws?.readyState === ReconnectingWebSocket.OPEN;
47
56
  }
48
57
  clearPing() {
49
58
  this.pingTimer = clearIntervalTimer(this.pingTimer);
@@ -0,0 +1,34 @@
1
+ import { S as StateUpdate } from '../../../types-D2dbAtin.js';
2
+ import { WebSocket } from 'partysocket';
3
+ import { ActiveAssetDataEvent } from './types.js';
4
+ import '@pear-protocol/types';
5
+ import '../bybit/types.js';
6
+
7
+ type OnStateUpdate = (update: StateUpdate) => void;
8
+ type OnActiveAssetData = (data: ActiveAssetDataEvent) => void;
9
+ declare class HyperliquidAssetTracker {
10
+ private onStateUpdate;
11
+ private onActiveAssetData;
12
+ private getWs;
13
+ private getAddress;
14
+ private isStopped;
15
+ private subscribedCoins;
16
+ private trackedAssetData;
17
+ constructor(deps: {
18
+ onStateUpdate: OnStateUpdate;
19
+ onActiveAssetData: OnActiveAssetData;
20
+ getWs: () => WebSocket | null;
21
+ getAddress: () => `0x${string}` | null;
22
+ isStopped: () => boolean;
23
+ });
24
+ onAssetTracked(coin: string): void;
25
+ onAssetUntracked(coin: string): void;
26
+ canUntrack(coin: string): boolean;
27
+ handleActiveAssetDataMessage(data: ActiveAssetDataEvent): void;
28
+ subscribeAll(coins: ReadonlySet<string>): void;
29
+ private subscribeActiveAssetData;
30
+ private unsubscribeActiveAssetData;
31
+ private buildTrackedAssetsMap;
32
+ }
33
+
34
+ export { HyperliquidAssetTracker };
@@ -0,0 +1,83 @@
1
+ import { sendWs } from '../../../utils/ws';
2
+ import { LOCKED_TRACKED_COINS } from './const';
3
+ import { buildTrackedAssetInfo } from './state-handler';
4
+
5
+ class HyperliquidAssetTracker {
6
+ onStateUpdate;
7
+ onActiveAssetData;
8
+ getWs;
9
+ getAddress;
10
+ isStopped;
11
+ subscribedCoins = /* @__PURE__ */ new Set();
12
+ trackedAssetData = /* @__PURE__ */ new Map();
13
+ constructor(deps) {
14
+ this.onStateUpdate = deps.onStateUpdate;
15
+ this.onActiveAssetData = deps.onActiveAssetData;
16
+ this.getWs = deps.getWs;
17
+ this.getAddress = deps.getAddress;
18
+ this.isStopped = deps.isStopped;
19
+ }
20
+ onAssetTracked(coin) {
21
+ this.subscribeActiveAssetData(coin);
22
+ }
23
+ onAssetUntracked(coin) {
24
+ this.unsubscribeActiveAssetData(coin);
25
+ this.trackedAssetData.delete(coin);
26
+ this.onStateUpdate({ trackedAssets: this.buildTrackedAssetsMap() });
27
+ }
28
+ canUntrack(coin) {
29
+ return !LOCKED_TRACKED_COINS.includes(coin);
30
+ }
31
+ handleActiveAssetDataMessage(data) {
32
+ if (!data.coin) return;
33
+ if (!this.subscribedCoins.has(data.coin)) return;
34
+ this.trackedAssetData.set(data.coin, data);
35
+ this.onActiveAssetData(data);
36
+ }
37
+ subscribeAll(coins) {
38
+ for (const coin of coins) {
39
+ if (!LOCKED_TRACKED_COINS.includes(coin)) {
40
+ this.subscribeActiveAssetData(coin);
41
+ }
42
+ }
43
+ }
44
+ subscribeActiveAssetData(coin) {
45
+ const ws = this.getWs();
46
+ const address = this.getAddress();
47
+ if (!ws || !address || this.isStopped()) return;
48
+ if (this.subscribedCoins.has(coin)) return;
49
+ this.subscribedCoins.add(coin);
50
+ sendWs(ws, {
51
+ method: "subscribe",
52
+ subscription: {
53
+ type: "activeAssetData",
54
+ coin,
55
+ user: address.toLowerCase()
56
+ }
57
+ });
58
+ }
59
+ unsubscribeActiveAssetData(coin) {
60
+ if (!this.subscribedCoins.has(coin)) return;
61
+ this.subscribedCoins.delete(coin);
62
+ const ws = this.getWs();
63
+ const address = this.getAddress();
64
+ if (!ws || !address) return;
65
+ sendWs(ws, {
66
+ method: "unsubscribe",
67
+ subscription: {
68
+ type: "activeAssetData",
69
+ coin,
70
+ user: address.toLowerCase()
71
+ }
72
+ });
73
+ }
74
+ buildTrackedAssetsMap() {
75
+ const result = /* @__PURE__ */ new Map();
76
+ for (const [coin, data] of this.trackedAssetData) {
77
+ result.set(coin, buildTrackedAssetInfo(data));
78
+ }
79
+ return result;
80
+ }
81
+ }
82
+
83
+ export { HyperliquidAssetTracker };
@@ -1,9 +1,9 @@
1
- import { AccountBalance, AccountPosition } from '../../types.js';
2
- import { AggregatedClearinghouseSummary, HyperliquidCoinBalance, AssetPosition } from './types.js';
1
+ import { a as AccountBalance, c as AccountPosition } from '../../../types-D2dbAtin.js';
2
+ import { AggregatedClearinghouseSummary, HyperliquidCoinBalance, HyperliquidAccountType, AssetPosition } from './types.js';
3
3
  import '@pear-protocol/types';
4
- import '@nktkas/hyperliquid/api/subscription';
4
+ import '../bybit/types.js';
5
5
 
6
- declare function mapBalance(summary: AggregatedClearinghouseSummary, spotCoinBalances: Map<string, HyperliquidCoinBalance>, accountType: string, availableToTradeByCollateral: Map<string, number>): AccountBalance;
6
+ declare function mapBalance(summary: AggregatedClearinghouseSummary, spotCoinBalances: Map<string, HyperliquidCoinBalance>, accountType: HyperliquidAccountType | null, availableToTradeByCollateral: Map<string, number>): AccountBalance | null;
7
7
  declare function mapPositions(raw: AssetPosition[]): Map<string, AccountPosition>;
8
8
 
9
9
  export { mapBalance, mapPositions };
@@ -3,6 +3,7 @@ import { COLLATERAL_TOKEN_MAP } from './types';
3
3
 
4
4
  const COLLATERAL_COINS = new Set(Object.values(COLLATERAL_TOKEN_MAP));
5
5
  function mapBalance(summary, spotCoinBalances, accountType, availableToTradeByCollateral) {
6
+ if (!accountType) return null;
6
7
  const free = {};
7
8
  const used = {};
8
9
  const total = {};
@@ -1,38 +1,25 @@
1
- import { InstrumentId } from '@pear-protocol/types';
2
- import { SupportedCredentials } from '../../types.js';
3
- import { BaseOrchestrator } from '../base.js';
1
+ import { g as SupportedCredentials } from '../../../types-D2dbAtin.js';
2
+ import { BaseOrchestrator, OrchestratorConfig } from '../base.js';
3
+ import '@pear-protocol/types';
4
+ import '../bybit/types.js';
5
+ import './types.js';
4
6
 
5
7
  declare class HyperliquidOrchestrator extends BaseOrchestrator {
6
- private static httpTransport;
7
- private static wsTransport;
8
- private infoClient;
9
- private subsClient;
10
- private subscriptions;
8
+ private ws;
11
9
  private address;
12
- private activeAssetSubscriptions;
13
- private trackedAssetData;
14
- private spotCoinBalances;
15
- private accountType;
16
- private symbolToCollateralToken;
17
- private availableToTradeByCollateral;
18
- private lastSummary;
19
- start(credentials: SupportedCredentials): Promise<void>;
20
- stop(): void;
10
+ private stateHandler;
11
+ private assetTracker;
12
+ constructor(config: OrchestratorConfig, credentials: SupportedCredentials);
13
+ protected initAsync(): Promise<void>;
14
+ private subscribe;
15
+ private handleMessage;
16
+ private fetchInfo;
17
+ protected cleanupConnections(): void;
18
+ stop(): Promise<void>;
21
19
  get isConnected(): boolean;
22
20
  onAssetTracked(coin: string): void;
23
21
  onAssetUntracked(coin: string): void;
24
- setLeverage(id: InstrumentId, leverage: string): Promise<void>;
25
22
  protected canUntrackAsset(coin: string): boolean;
26
- private fetchPerpMetas;
27
- private subscribeActiveAssetData;
28
- private stopAll;
29
- private handleClearinghouseState;
30
- private handleActiveAssetData;
31
- private buildTrackedAssetInfo;
32
- private buildTrackedAssetsMap;
33
- private buildBalance;
34
- private handleWebData3;
35
- private handleSpotState;
36
23
  }
37
24
 
38
25
  export { HyperliquidOrchestrator };