@pear-protocol/exchanges-sdk 0.0.18 → 0.1.3

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 (190) hide show
  1. package/README.md +73 -137
  2. package/dist/client/base-ws.d.ts +30 -0
  3. package/dist/client/base-ws.js +113 -0
  4. package/dist/client/binance/exchange-ws.d.ts +19 -0
  5. package/dist/client/binance/exchange-ws.js +26 -0
  6. package/dist/{account/exchanges → client}/binance/rest.d.ts +2 -6
  7. package/dist/{account/exchanges → client}/binance/rest.js +4 -11
  8. package/dist/client/binance/types.d.ts +68 -0
  9. package/dist/client/binance/types.js +1 -0
  10. package/dist/client/binance/ws.d.ts +30 -0
  11. package/dist/client/binance/ws.js +54 -0
  12. package/dist/client/bybit/exchange-ws.d.ts +20 -0
  13. package/dist/client/bybit/exchange-ws.js +28 -0
  14. package/dist/{account/exchanges → client}/bybit/rest.js +3 -2
  15. package/dist/{account/exchanges → client}/bybit/types.d.ts +1 -9
  16. package/dist/client/bybit/types.js +1 -0
  17. package/dist/client/bybit/ws.d.ts +17 -0
  18. package/dist/client/bybit/ws.js +50 -0
  19. package/dist/client/exchange-ws.d.ts +12 -0
  20. package/dist/client/exchange-ws.js +10 -0
  21. package/dist/client/hyperliquid/exchange-ws.d.ts +15 -0
  22. package/dist/client/hyperliquid/exchange-ws.js +21 -0
  23. package/dist/client/hyperliquid/rest.d.ts +3 -0
  24. package/dist/client/hyperliquid/rest.js +12 -0
  25. package/dist/{account/exchanges → client}/hyperliquid/types.d.ts +93 -39
  26. package/dist/client/hyperliquid/types.js +1 -0
  27. package/dist/client/hyperliquid/ws.d.ts +10 -0
  28. package/dist/client/hyperliquid/ws.js +16 -0
  29. package/dist/client/index.d.ts +31 -0
  30. package/dist/client/index.js +47 -0
  31. package/dist/client/lighter/constants.d.ts +4 -0
  32. package/dist/client/lighter/constants.js +4 -0
  33. package/dist/client/lighter/exchange-ws.d.ts +15 -0
  34. package/dist/client/lighter/exchange-ws.js +21 -0
  35. package/dist/client/lighter/rest.d.ts +56 -0
  36. package/dist/client/lighter/rest.js +27 -0
  37. package/dist/client/lighter/types.d.ts +32 -0
  38. package/dist/client/lighter/types.js +1 -0
  39. package/dist/client/lighter/ws.d.ts +10 -0
  40. package/dist/client/lighter/ws.js +17 -0
  41. package/dist/client/okx/exchange-ws.d.ts +20 -0
  42. package/dist/client/okx/exchange-ws.js +28 -0
  43. package/dist/{account/exchanges → client}/okx/rest.js +2 -2
  44. package/dist/{account/exchanges → client}/okx/types.d.ts +1 -10
  45. package/dist/client/okx/types.js +1 -0
  46. package/dist/client/okx/ws.d.ts +17 -0
  47. package/dist/client/okx/ws.js +61 -0
  48. package/dist/helper/factory.d.ts +10 -0
  49. package/dist/helper/factory.js +12 -0
  50. package/dist/helper/index.d.ts +7 -0
  51. package/dist/helper/index.js +2 -0
  52. package/dist/helper/lighter/ethereum/abi.d.ts +66 -0
  53. package/dist/helper/lighter/ethereum/abi.js +40 -0
  54. package/dist/helper/lighter/ethereum/index.d.ts +8 -0
  55. package/dist/helper/lighter/ethereum/index.js +34 -0
  56. package/dist/helper/lighter/ethereum/types.d.ts +23 -0
  57. package/dist/helper/lighter/ethereum/types.js +1 -0
  58. package/dist/helper/lighter/helper.d.ts +9 -0
  59. package/dist/helper/lighter/helper.js +67 -0
  60. package/dist/helper/lighter/index.d.ts +6 -0
  61. package/dist/helper/lighter/index.js +2 -0
  62. package/dist/helper/lighter/types.d.ts +63 -0
  63. package/dist/helper/lighter/types.js +35 -0
  64. package/dist/helper/types.d.ts +11 -0
  65. package/dist/helper/types.js +1 -0
  66. package/dist/index.d.ts +43 -24
  67. package/dist/index.js +6 -21
  68. package/dist/sdk.d.ts +43 -0
  69. package/dist/sdk.js +53 -0
  70. package/dist/syncer/base.d.ts +40 -0
  71. package/dist/syncer/base.js +50 -0
  72. package/dist/syncer/binance/syncer.d.ts +24 -0
  73. package/dist/syncer/binance/syncer.js +9 -0
  74. package/dist/syncer/bybit/syncer.d.ts +24 -0
  75. package/dist/syncer/bybit/syncer.js +9 -0
  76. package/dist/syncer/factory.d.ts +22 -0
  77. package/dist/syncer/factory.js +26 -0
  78. package/dist/syncer/hyperliquid/syncer.d.ts +26 -0
  79. package/dist/syncer/hyperliquid/syncer.js +43 -0
  80. package/dist/syncer/index.d.ts +24 -0
  81. package/dist/syncer/index.js +7 -0
  82. package/dist/syncer/lighter/syncer.d.ts +24 -0
  83. package/dist/syncer/lighter/syncer.js +9 -0
  84. package/dist/syncer/okx/syncer.d.ts +24 -0
  85. package/dist/syncer/okx/syncer.js +9 -0
  86. package/dist/tracker/base.d.ts +79 -0
  87. package/dist/tracker/base.js +120 -0
  88. package/dist/tracker/binance/const.d.ts +4 -0
  89. package/dist/tracker/binance/const.js +4 -0
  90. package/dist/{account/exchanges → tracker}/binance/mapper.d.ts +4 -1
  91. package/dist/{account/exchanges → tracker}/binance/mapper.js +7 -6
  92. package/dist/tracker/binance/tracker.d.ts +60 -0
  93. package/dist/tracker/binance/tracker.js +181 -0
  94. package/dist/tracker/binance/types.d.ts +6 -0
  95. package/dist/{account/exchanges → tracker}/bybit/mapper.d.ts +5 -3
  96. package/dist/{account/exchanges → tracker}/bybit/mapper.js +11 -10
  97. package/dist/tracker/bybit/tracker.d.ts +51 -0
  98. package/dist/tracker/bybit/tracker.js +138 -0
  99. package/dist/tracker/bybit/types.d.ts +7 -0
  100. package/dist/{account/exchanges → tracker}/hyperliquid/mapper.d.ts +6 -4
  101. package/dist/{account/exchanges → tracker}/hyperliquid/mapper.js +18 -16
  102. package/dist/tracker/hyperliquid/tracker.d.ts +62 -0
  103. package/dist/tracker/hyperliquid/tracker.js +219 -0
  104. package/dist/tracker/hyperliquid/types.d.ts +23 -0
  105. package/dist/tracker/index.d.ts +38 -0
  106. package/dist/tracker/index.js +81 -0
  107. package/dist/tracker/lighter/const.d.ts +3 -0
  108. package/dist/tracker/lighter/const.js +3 -0
  109. package/dist/tracker/lighter/mapper.d.ts +16 -0
  110. package/dist/tracker/lighter/mapper.js +77 -0
  111. package/dist/tracker/lighter/tracker.d.ts +53 -0
  112. package/dist/tracker/lighter/tracker.js +150 -0
  113. package/dist/tracker/lighter/types.d.ts +16 -0
  114. package/dist/tracker/lighter/types.js +6 -0
  115. package/dist/{account/exchanges → tracker}/okx/mapper.d.ts +5 -3
  116. package/dist/{account/exchanges → tracker}/okx/mapper.js +11 -10
  117. package/dist/tracker/okx/tracker.d.ts +51 -0
  118. package/dist/tracker/okx/tracker.js +134 -0
  119. package/dist/tracker/okx/types.d.ts +8 -0
  120. package/dist/tracker/types.d.ts +63 -0
  121. package/dist/{account → tracker}/types.js +6 -4
  122. package/dist/tracker/utils.d.ts +11 -0
  123. package/dist/{account → tracker}/utils.js +0 -2
  124. package/dist/types.d.ts +50 -0
  125. package/dist/types.js +1 -0
  126. package/package.json +7 -5
  127. package/dist/account/account-manager.d.ts +0 -31
  128. package/dist/account/account-manager.js +0 -119
  129. package/dist/account/exchange-account.d.ts +0 -35
  130. package/dist/account/exchange-account.js +0 -158
  131. package/dist/account/exchanges/base.d.ts +0 -48
  132. package/dist/account/exchanges/base.js +0 -41
  133. package/dist/account/exchanges/binance/asset-tracker.d.ts +0 -26
  134. package/dist/account/exchanges/binance/asset-tracker.js +0 -38
  135. package/dist/account/exchanges/binance/const.d.ts +0 -10
  136. package/dist/account/exchanges/binance/const.js +0 -10
  137. package/dist/account/exchanges/binance/orchestrator.d.ts +0 -31
  138. package/dist/account/exchanges/binance/orchestrator.js +0 -91
  139. package/dist/account/exchanges/binance/state-handler.d.ts +0 -33
  140. package/dist/account/exchanges/binance/state-handler.js +0 -113
  141. package/dist/account/exchanges/binance/types.d.ts +0 -5
  142. package/dist/account/exchanges/binance/ws.d.ts +0 -23
  143. package/dist/account/exchanges/binance/ws.js +0 -69
  144. package/dist/account/exchanges/bybit/asset-tracker.d.ts +0 -26
  145. package/dist/account/exchanges/bybit/asset-tracker.js +0 -37
  146. package/dist/account/exchanges/bybit/const.d.ts +0 -7
  147. package/dist/account/exchanges/bybit/const.js +0 -7
  148. package/dist/account/exchanges/bybit/orchestrator.d.ts +0 -22
  149. package/dist/account/exchanges/bybit/orchestrator.js +0 -66
  150. package/dist/account/exchanges/bybit/state-handler.d.ts +0 -23
  151. package/dist/account/exchanges/bybit/state-handler.js +0 -70
  152. package/dist/account/exchanges/bybit/ws.d.ts +0 -19
  153. package/dist/account/exchanges/bybit/ws.js +0 -83
  154. package/dist/account/exchanges/hyperliquid/asset-tracker.d.ts +0 -35
  155. package/dist/account/exchanges/hyperliquid/asset-tracker.js +0 -83
  156. package/dist/account/exchanges/hyperliquid/orchestrator.d.ts +0 -26
  157. package/dist/account/exchanges/hyperliquid/orchestrator.js +0 -102
  158. package/dist/account/exchanges/hyperliquid/state-handler.d.ts +0 -25
  159. package/dist/account/exchanges/hyperliquid/state-handler.js +0 -104
  160. package/dist/account/exchanges/index.d.ts +0 -11
  161. package/dist/account/exchanges/index.js +0 -32
  162. package/dist/account/exchanges/okx/asset-tracker.d.ts +0 -26
  163. package/dist/account/exchanges/okx/asset-tracker.js +0 -34
  164. package/dist/account/exchanges/okx/const.d.ts +0 -7
  165. package/dist/account/exchanges/okx/const.js +0 -7
  166. package/dist/account/exchanges/okx/orchestrator.d.ts +0 -22
  167. package/dist/account/exchanges/okx/orchestrator.js +0 -57
  168. package/dist/account/exchanges/okx/state-handler.d.ts +0 -24
  169. package/dist/account/exchanges/okx/state-handler.js +0 -78
  170. package/dist/account/exchanges/okx/ws.d.ts +0 -20
  171. package/dist/account/exchanges/okx/ws.js +0 -103
  172. package/dist/account/index.d.ts +0 -11
  173. package/dist/account/index.js +0 -4
  174. package/dist/account/types.d.ts +0 -5
  175. package/dist/account/utils.d.ts +0 -10
  176. package/dist/credentials.d.ts +0 -28
  177. package/dist/credentials.js +0 -46
  178. package/dist/types-Caz2X4h0.d.ts +0 -151
  179. package/dist/utils/ws.d.ts +0 -10
  180. package/dist/utils/ws.js +0 -42
  181. /package/dist/{account/exchanges → client}/bybit/rest.d.ts +0 -0
  182. /package/dist/{utils → client}/hmac.d.ts +0 -0
  183. /package/dist/{utils → client}/hmac.js +0 -0
  184. /package/dist/{account/exchanges → client}/okx/rest.d.ts +0 -0
  185. /package/dist/{account/exchanges → tracker}/binance/types.js +0 -0
  186. /package/dist/{account/exchanges → tracker}/bybit/types.js +0 -0
  187. /package/dist/{account/exchanges → tracker}/hyperliquid/const.d.ts +0 -0
  188. /package/dist/{account/exchanges → tracker}/hyperliquid/const.js +0 -0
  189. /package/dist/{account/exchanges → tracker}/hyperliquid/types.js +0 -0
  190. /package/dist/{account/exchanges → tracker}/okx/types.js +0 -0
@@ -0,0 +1,138 @@
1
+ import { fetchWalletBalance, fetchPositions, fetchAccountInfo, fetchPositionLeverage } from '../../client/bybit/rest';
2
+ import { BaseAccountTracker } from '../base';
3
+ import { mergeRawCoins, buildBalance, mapPositions, mapPositionUpdates } from './mapper';
4
+ import './types';
5
+
6
+ class BybitAccountTracker extends BaseAccountTracker {
7
+ creds;
8
+ ws;
9
+ messageListenerId = null;
10
+ openListenerId = null;
11
+ rawCoins = /* @__PURE__ */ new Map();
12
+ lastWallet = null;
13
+ accountType = null;
14
+ trackedAssetInfos = /* @__PURE__ */ new Map();
15
+ constructor(config) {
16
+ super(config);
17
+ this.credentials = config.credentials;
18
+ this.creds = config.credentials;
19
+ this.ws = config.ws;
20
+ }
21
+ async start() {
22
+ const [wallet, positionsUsd, positionsUsdc, accountInfo] = await Promise.all([
23
+ fetchWalletBalance(this.creds, this.demo),
24
+ fetchPositions(this.creds, "USDT", this.demo),
25
+ fetchPositions(this.creds, "USDC", this.demo),
26
+ fetchAccountInfo(this.creds, this.demo)
27
+ ]);
28
+ this.handleInitialData(
29
+ wallet ?? null,
30
+ [positionsUsd, positionsUsdc].flat(),
31
+ accountInfo?.marginMode ?? null
32
+ );
33
+ this.messageListenerId = this.ws.main.addMessageListener((raw) => this.routeRaw(raw));
34
+ this.openListenerId = this.ws.main.addOpenListener(() => {
35
+ this.ws.authenticate().then(() => this.subscribe()).catch((err) => this.onError(err));
36
+ });
37
+ this.subscribe();
38
+ }
39
+ async cleanupConnections() {
40
+ if (this.messageListenerId) {
41
+ this.ws.main.removeMessageListener(this.messageListenerId);
42
+ this.messageListenerId = null;
43
+ }
44
+ if (this.openListenerId) {
45
+ this.ws.main.removeOpenListener(this.openListenerId);
46
+ this.openListenerId = null;
47
+ }
48
+ }
49
+ get isConnected() {
50
+ return this.ws.isConnected;
51
+ }
52
+ ensureAssetTracked(coin) {
53
+ if (this.trackedAssetInfos.has(coin)) return;
54
+ fetchPositionLeverage(this.creds, coin, this.demo).then((pos) => {
55
+ const leverage = pos?.leverage || "1";
56
+ const marginType = pos?.tradeMode === "1" ? "cross" : "isolated";
57
+ const info = { coin, leverage, marginType };
58
+ this.trackedAssetInfos.set(coin, info);
59
+ const trackedAssets = /* @__PURE__ */ new Map();
60
+ trackedAssets.set(coin, info);
61
+ this.onStateUpdate({ trackedAssets });
62
+ }).catch((err) => {
63
+ this.onError(err instanceof Error ? err : new Error(String(err)));
64
+ });
65
+ }
66
+ releaseAsset(coin) {
67
+ this.trackedAssetInfos.delete(coin);
68
+ this.onStateUpdate({ trackedAssets: new Map(this.trackedAssetInfos) });
69
+ }
70
+ subscribe() {
71
+ this.ws.main.send({ op: "subscribe", args: ["wallet", "position"] });
72
+ }
73
+ handleInitialData(wallet, positions, accountType) {
74
+ this.accountType = accountType;
75
+ if (wallet) {
76
+ this.lastWallet = wallet;
77
+ this.rawCoins = mergeRawCoins(/* @__PURE__ */ new Map(), wallet.coin ?? []);
78
+ const balance = buildBalance(wallet, this.rawCoins, this.accountType);
79
+ if (balance) this.onStateUpdate({ balance });
80
+ }
81
+ this.onStateUpdate({ positions: mapPositions(positions) });
82
+ }
83
+ routeRaw(raw) {
84
+ try {
85
+ const msg = JSON.parse(raw);
86
+ if (msg.topic && msg.data) {
87
+ this.handleMessage({ topic: msg.topic, data: msg.data });
88
+ }
89
+ } catch (err) {
90
+ this.onError(err instanceof Error ? err : new Error(String(err)));
91
+ }
92
+ }
93
+ handleMessage(msg) {
94
+ if (msg.topic === "wallet") {
95
+ const wallet = msg.data[0];
96
+ if (wallet) this.handleWalletUpdate(wallet);
97
+ } else if (msg.topic === "position") {
98
+ const rawPositions = msg.data;
99
+ const positions = mapPositionUpdates(rawPositions);
100
+ if (positions.size > 0) {
101
+ const trackedAssets = /* @__PURE__ */ new Map();
102
+ for (const pos of rawPositions) {
103
+ const existing = this.trackedAssetInfos.get(pos.symbol);
104
+ if (existing) {
105
+ const leverage = pos.leverage || existing.leverage;
106
+ const marginType = pos.tradeMode === "1" ? "isolated" : "cross";
107
+ const updated = { ...existing, leverage, marginType };
108
+ this.trackedAssetInfos.set(pos.symbol, updated);
109
+ trackedAssets.set(pos.symbol, updated);
110
+ }
111
+ }
112
+ this.onStateUpdate({
113
+ positions,
114
+ ...trackedAssets.size > 0 ? { trackedAssets } : {}
115
+ });
116
+ }
117
+ }
118
+ }
119
+ handleWalletUpdate(raw) {
120
+ this.rawCoins = mergeRawCoins(this.rawCoins, raw.coin ?? []);
121
+ const merged = this.lastWallet ? {
122
+ totalEquity: raw.totalEquity || this.lastWallet.totalEquity,
123
+ totalWalletBalance: raw.totalWalletBalance || this.lastWallet.totalWalletBalance,
124
+ totalMarginBalance: raw.totalMarginBalance || this.lastWallet.totalMarginBalance,
125
+ totalAvailableBalance: raw.totalAvailableBalance || this.lastWallet.totalAvailableBalance,
126
+ totalPerpUPL: raw.totalPerpUPL || this.lastWallet.totalPerpUPL,
127
+ totalInitialMargin: raw.totalInitialMargin || this.lastWallet.totalInitialMargin,
128
+ totalMaintenanceMargin: raw.totalMaintenanceMargin || this.lastWallet.totalMaintenanceMargin,
129
+ accountMMRate: raw.accountMMRate || this.lastWallet.accountMMRate,
130
+ coin: raw.coin ?? this.lastWallet.coin
131
+ } : raw;
132
+ this.lastWallet = merged;
133
+ const balance = buildBalance(merged, this.rawCoins, this.accountType);
134
+ if (balance) this.onStateUpdate({ balance });
135
+ }
136
+ }
137
+
138
+ export { BybitAccountTracker };
@@ -0,0 +1,7 @@
1
+ declare enum BybitAccountType {
2
+ ISOLATED_MARGIN = "ISOLATED_MARGIN",
3
+ REGULAR_MARGIN = "REGULAR_MARGIN",
4
+ PORTFOLIO_MARGIN = "PORTFOLIO_MARGIN"
5
+ }
6
+
7
+ export { BybitAccountType };
@@ -1,10 +1,12 @@
1
- import { a as AccountBalance, c as AccountPosition } from '../../../types-Caz2X4h0.js';
2
- import { AggregatedClearinghouseSummary, HyperliquidCoinBalance, HyperliquidAccountType, AssetPosition } from './types.js';
3
- import '@pear-protocol/types';
1
+ import { AssetPosition } from '../../client/hyperliquid/types.js';
2
+ import { AccountBalance, AccountPosition } from '../types.js';
3
+ import { AggregatedClearinghouseSummary, HyperliquidCoinBalance, HyperliquidAccountType } from './types.js';
4
+ import '../binance/types.js';
4
5
  import '../bybit/types.js';
6
+ import '../lighter/types.js';
5
7
  import '../okx/types.js';
6
8
 
7
- declare function mapBalance(summary: AggregatedClearinghouseSummary, spotCoinBalances: Map<string, HyperliquidCoinBalance>, accountType: HyperliquidAccountType | null, availableToTradeByCollateral: Map<string, number>): AccountBalance | null;
9
+ declare function mapBalance(summary: AggregatedClearinghouseSummary, spotCoinBalances: Map<string, HyperliquidCoinBalance>, accountType: HyperliquidAccountType | null, availableToTradeByCollateral: Map<string, string>): AccountBalance | null;
8
10
  declare function mapPositions(raw: AssetPosition[]): Map<string, AccountPosition>;
9
11
 
10
12
  export { mapBalance, mapPositions };
@@ -1,4 +1,5 @@
1
- import { positionKey } from '../../utils';
1
+ import BigNumber from 'bignumber.js';
2
+ import { positionKey } from '../utils';
2
3
  import { COLLATERAL_TOKEN_MAP } from './types';
3
4
 
4
5
  const COLLATERAL_COINS = new Set(Object.values(COLLATERAL_TOKEN_MAP));
@@ -11,9 +12,9 @@ function mapBalance(summary, spotCoinBalances, accountType, availableToTradeByCo
11
12
  for (const [, coin] of spotCoinBalances) {
12
13
  if (!COLLATERAL_COINS.has(coin.coin)) continue;
13
14
  const availableOverride = availableToTradeByCollateral.get(coin.coin);
14
- const coinFree = availableOverride !== void 0 ? availableOverride.toString() : (coin.total - coin.hold).toString();
15
- const coinUsed = coin.hold.toString();
16
- const coinTotal = coin.total.toString();
15
+ const coinFree = availableOverride !== void 0 ? availableOverride : new BigNumber(coin.total).minus(coin.hold).toFixed();
16
+ const coinUsed = coin.hold;
17
+ const coinTotal = coin.total;
17
18
  free[coin.coin] = coinFree;
18
19
  used[coin.coin] = coinUsed;
19
20
  total[coin.coin] = coinTotal;
@@ -26,19 +27,20 @@ function mapBalance(summary, spotCoinBalances, accountType, availableToTradeByCo
26
27
  usdValue: coinTotal
27
28
  });
28
29
  }
29
- const walletBalance = summary.accountValue - summary.totalUnrealizedPnl;
30
- const marginRatio = summary.accountValue > 0 ? (summary.crossMaintenanceMarginUsed / summary.accountValue).toFixed(4) : "0.0000";
30
+ const accountValueBN = new BigNumber(summary.accountValue);
31
+ const walletBalance = accountValueBN.minus(summary.totalUnrealizedPnl).toFixed();
32
+ const marginRatio = accountValueBN.gt(0) ? new BigNumber(summary.crossMaintenanceMarginUsed).div(accountValueBN).toFixed(4) : "0.0000";
31
33
  return {
32
34
  accountType,
33
35
  free,
34
36
  used,
35
37
  total,
36
- availableToTrade: summary.withdrawable.toString(),
37
- totalEquity: summary.accountValue.toString(),
38
- walletBalance: walletBalance.toString(),
39
- unrealizedPnl: summary.totalUnrealizedPnl.toString(),
40
- initialMarginUsed: summary.totalMarginUsed.toString(),
41
- maintenanceMargin: summary.crossMaintenanceMarginUsed.toString(),
38
+ availableToTrade: summary.withdrawable,
39
+ totalEquity: summary.accountValue,
40
+ walletBalance,
41
+ unrealizedPnl: summary.totalUnrealizedPnl,
42
+ initialMarginUsed: summary.totalMarginUsed,
43
+ maintenanceMargin: summary.crossMaintenanceMarginUsed,
42
44
  marginRatio,
43
45
  assets,
44
46
  timestamp: Date.now()
@@ -48,14 +50,14 @@ function mapPositions(raw) {
48
50
  const positions = /* @__PURE__ */ new Map();
49
51
  for (const ap of raw) {
50
52
  const pos = ap.position;
51
- const szi = Number.parseFloat(pos.szi || "0");
52
- if (szi === 0) continue;
53
+ const sziBN = new BigNumber(pos.szi || "0");
54
+ if (sziBN.isZero()) continue;
53
55
  const coin = pos.coin || "";
54
- const side = szi > 0 ? "long" : "short";
56
+ const side = sziBN.isPositive() ? "long" : "short";
55
57
  positions.set(positionKey(coin, side), {
56
58
  symbol: coin,
57
59
  side,
58
- size: szi.toString(),
60
+ size: sziBN.toFixed(),
59
61
  entryPrice: pos.entryPx || "0",
60
62
  unrealizedPnl: pos.unrealizedPnl || "0",
61
63
  leverage: pos.leverage.value.toString(),
@@ -0,0 +1,62 @@
1
+ import { HyperliquidWs } from '../../client/hyperliquid/ws.js';
2
+ import { SupportedCredentials } from '../../types.js';
3
+ import { BaseAccountTracker, AccountTrackerConfig } from '../base.js';
4
+ import '../../client/base-ws.js';
5
+ import 'partysocket';
6
+ import '@pear-protocol/core-sdk';
7
+ import '@pear-protocol/types';
8
+ import '../../client/binance/exchange-ws.js';
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/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 '../binance/types.js';
20
+ import '../bybit/types.js';
21
+ import './types.js';
22
+ import '../lighter/types.js';
23
+ import '../okx/types.js';
24
+
25
+ type HyperliquidAccountTrackerConfig = AccountTrackerConfig & {
26
+ credentials: SupportedCredentials;
27
+ ws: HyperliquidWs;
28
+ };
29
+ declare class HyperliquidAccountTracker extends BaseAccountTracker {
30
+ private readonly address;
31
+ private readonly ws;
32
+ private messageListenerId;
33
+ private openListenerId;
34
+ private subscribedCoins;
35
+ private lastSummary;
36
+ private spotCoinBalances;
37
+ private accountType;
38
+ private symbolToCollateralToken;
39
+ private availableToTradeByCollateral;
40
+ private trackedAssetData;
41
+ constructor(config: HyperliquidAccountTrackerConfig);
42
+ start(): Promise<void>;
43
+ protected cleanupConnections(): Promise<void>;
44
+ get isConnected(): boolean;
45
+ protected ensureAssetTracked(coin: string): void;
46
+ protected releaseAsset(coin: string): void;
47
+ private isLocked;
48
+ private addrLower;
49
+ private sendStaticSubs;
50
+ private resubscribeAll;
51
+ private routeRaw;
52
+ private handle;
53
+ private loadPerpMetas;
54
+ private onClearinghouseState;
55
+ private onActiveAssetData;
56
+ private onWebData3;
57
+ private onSpotState;
58
+ private buildBalance;
59
+ private buildTrackedAssetsMap;
60
+ }
61
+
62
+ export { HyperliquidAccountTracker, type HyperliquidAccountTrackerConfig };
@@ -0,0 +1,219 @@
1
+ import BigNumber from 'bignumber.js';
2
+ import { fetchInfo } from '../../client/hyperliquid/rest';
3
+ import { BaseAccountTracker } from '../base';
4
+ import { LOCKED_TRACKED_COINS } from './const';
5
+ import { mapPositions, mapBalance } from './mapper';
6
+ import { COLLATERAL_TOKEN_MAP } from './types';
7
+
8
+ class HyperliquidAccountTracker extends BaseAccountTracker {
9
+ address;
10
+ ws;
11
+ messageListenerId = null;
12
+ openListenerId = null;
13
+ subscribedCoins = /* @__PURE__ */ new Set();
14
+ lastSummary = {
15
+ accountValue: "0",
16
+ totalMarginUsed: "0",
17
+ totalRawUsd: "0",
18
+ crossMaintenanceMarginUsed: "0",
19
+ withdrawable: "0",
20
+ totalUnrealizedPnl: "0"
21
+ };
22
+ spotCoinBalances = /* @__PURE__ */ new Map();
23
+ accountType = null;
24
+ symbolToCollateralToken = /* @__PURE__ */ new Map();
25
+ availableToTradeByCollateral = /* @__PURE__ */ new Map();
26
+ trackedAssetData = /* @__PURE__ */ new Map();
27
+ constructor(config) {
28
+ super(config);
29
+ const creds = config.credentials;
30
+ this.credentials = config.credentials;
31
+ this.address = creds.accountIdentifier;
32
+ this.ws = config.ws;
33
+ }
34
+ async start() {
35
+ const allMetas = await fetchInfo({ type: "allPerpMetas" });
36
+ this.loadPerpMetas(allMetas);
37
+ this.messageListenerId = this.ws.addMessageListener((raw) => this.routeRaw(raw));
38
+ this.openListenerId = this.ws.addOpenListener(() => this.resubscribeAll());
39
+ this.sendStaticSubs();
40
+ for (const coin of LOCKED_TRACKED_COINS) {
41
+ this.ensureAssetTracked(coin);
42
+ }
43
+ }
44
+ async cleanupConnections() {
45
+ if (this.messageListenerId) {
46
+ this.ws.removeMessageListener(this.messageListenerId);
47
+ this.messageListenerId = null;
48
+ }
49
+ if (this.openListenerId) {
50
+ this.ws.removeOpenListener(this.openListenerId);
51
+ this.openListenerId = null;
52
+ }
53
+ this.subscribedCoins.clear();
54
+ }
55
+ get isConnected() {
56
+ return this.ws.connected;
57
+ }
58
+ ensureAssetTracked(coin) {
59
+ if (this.subscribedCoins.has(coin)) return;
60
+ this.subscribedCoins.add(coin);
61
+ this.ws.send({
62
+ method: "subscribe",
63
+ subscription: { type: "activeAssetData", coin, user: this.addrLower() }
64
+ });
65
+ }
66
+ releaseAsset(coin) {
67
+ if (this.isLocked(coin)) return;
68
+ if (!this.subscribedCoins.has(coin)) return;
69
+ this.subscribedCoins.delete(coin);
70
+ this.ws.send({
71
+ method: "unsubscribe",
72
+ subscription: { type: "activeAssetData", coin, user: this.addrLower() }
73
+ });
74
+ this.trackedAssetData.delete(coin);
75
+ this.onStateUpdate({ trackedAssets: this.buildTrackedAssetsMap() });
76
+ }
77
+ isLocked(coin) {
78
+ return LOCKED_TRACKED_COINS.includes(coin);
79
+ }
80
+ addrLower() {
81
+ return this.address.toLowerCase();
82
+ }
83
+ sendStaticSubs() {
84
+ const user = this.addrLower();
85
+ this.ws.send({ method: "subscribe", subscription: { type: "allDexsClearinghouseState", user } });
86
+ this.ws.send({ method: "subscribe", subscription: { type: "spotState", user } });
87
+ this.ws.send({ method: "subscribe", subscription: { type: "webData3", user } });
88
+ }
89
+ resubscribeAll() {
90
+ this.sendStaticSubs();
91
+ const user = this.addrLower();
92
+ for (const coin of this.subscribedCoins) {
93
+ this.ws.send({
94
+ method: "subscribe",
95
+ subscription: { type: "activeAssetData", coin, user }
96
+ });
97
+ }
98
+ }
99
+ routeRaw(raw) {
100
+ try {
101
+ const msg = JSON.parse(raw);
102
+ if (!msg.channel || !msg.data) return;
103
+ switch (msg.channel) {
104
+ case "allDexsClearinghouseState":
105
+ this.handle({ kind: "clearinghouseState", data: msg.data });
106
+ break;
107
+ case "spotState":
108
+ this.handle({ kind: "spotState", data: msg.data });
109
+ break;
110
+ case "webData3":
111
+ this.handle({ kind: "webData3", data: msg.data });
112
+ break;
113
+ case "activeAssetData":
114
+ this.handle({ kind: "activeAssetData", data: msg.data });
115
+ break;
116
+ }
117
+ } catch (err) {
118
+ this.onError(err instanceof Error ? err : new Error(String(err)));
119
+ }
120
+ }
121
+ handle(event) {
122
+ switch (event.kind) {
123
+ case "clearinghouseState":
124
+ this.onClearinghouseState(event.data);
125
+ break;
126
+ case "spotState":
127
+ this.onSpotState(event.data);
128
+ break;
129
+ case "webData3":
130
+ this.onWebData3(event.data);
131
+ break;
132
+ case "activeAssetData":
133
+ this.onActiveAssetData(event.data);
134
+ break;
135
+ }
136
+ }
137
+ loadPerpMetas(allMetas) {
138
+ allMetas.forEach((dexMeta) => {
139
+ const collateralToken = COLLATERAL_TOKEN_MAP[dexMeta.collateralToken];
140
+ dexMeta.universe.forEach((asset) => {
141
+ if (!asset.name) return;
142
+ if (collateralToken && !this.symbolToCollateralToken.has(asset.name)) {
143
+ this.symbolToCollateralToken.set(asset.name, collateralToken);
144
+ }
145
+ });
146
+ });
147
+ }
148
+ onClearinghouseState(data) {
149
+ const states = (data.clearinghouseStates || []).map(([, s]) => s).filter(Boolean);
150
+ const sumStr = (values) => values.reduce((acc, v) => acc.plus(new BigNumber(v || "0")), new BigNumber(0)).toFixed();
151
+ const allAssetPositions = states.flatMap((s) => s.assetPositions || []);
152
+ const totalUnrealizedPnl = allAssetPositions.reduce((acc, ap) => acc.plus(new BigNumber(ap.position.unrealizedPnl || "0")), new BigNumber(0)).toFixed();
153
+ this.lastSummary = {
154
+ accountValue: sumStr(states.map((s) => s.crossMarginSummary.accountValue)),
155
+ totalMarginUsed: sumStr(states.map((s) => s.crossMarginSummary.totalMarginUsed)),
156
+ totalRawUsd: sumStr(states.map((s) => s.crossMarginSummary.totalRawUsd)),
157
+ crossMaintenanceMarginUsed: sumStr(states.map((s) => s.crossMaintenanceMarginUsed)),
158
+ withdrawable: sumStr(states.map((s) => s.withdrawable)),
159
+ totalUnrealizedPnl
160
+ };
161
+ const balance = this.buildBalance();
162
+ const positions = mapPositions(allAssetPositions);
163
+ this.onStateUpdate({ balance: balance ?? void 0, positions });
164
+ }
165
+ onActiveAssetData(data) {
166
+ if (!data.coin) return;
167
+ if (!this.trackedCoins.has(data.coin)) return;
168
+ this.trackedAssetData.set(data.coin, data);
169
+ const collateral = this.symbolToCollateralToken.get(data.coin);
170
+ if (collateral && data.availableToTrade) {
171
+ const long = new BigNumber(data.availableToTrade[0] || "0");
172
+ const short = new BigNumber(data.availableToTrade[1] || "0");
173
+ const minAvailable = BigNumber.min(long, short).toFixed();
174
+ this.availableToTradeByCollateral.set(collateral, minAvailable);
175
+ const balance = this.buildBalance();
176
+ if (balance) this.onStateUpdate({ balance });
177
+ }
178
+ const trackedAssets = /* @__PURE__ */ new Map();
179
+ trackedAssets.set(data.coin, buildTrackedAssetInfo(data));
180
+ this.onStateUpdate({ trackedAssets });
181
+ }
182
+ onWebData3(data) {
183
+ this.accountType = data.userState.abstraction ?? null;
184
+ }
185
+ onSpotState(data) {
186
+ const balances = data?.spotState?.balances;
187
+ if (!balances) return;
188
+ for (const b of balances) {
189
+ const totalBN = new BigNumber(b.total || "0");
190
+ const holdBN = new BigNumber(b.hold || "0");
191
+ if (!totalBN.isZero() || !holdBN.isZero()) {
192
+ this.spotCoinBalances.set(b.coin, { coin: b.coin, total: totalBN.toFixed(), hold: holdBN.toFixed() });
193
+ } else {
194
+ this.spotCoinBalances.delete(b.coin);
195
+ }
196
+ }
197
+ const balance = this.buildBalance();
198
+ if (balance) this.onStateUpdate({ balance });
199
+ }
200
+ buildBalance() {
201
+ return mapBalance(this.lastSummary, this.spotCoinBalances, this.accountType, this.availableToTradeByCollateral);
202
+ }
203
+ buildTrackedAssetsMap() {
204
+ const result = /* @__PURE__ */ new Map();
205
+ for (const [coin, data] of this.trackedAssetData) {
206
+ result.set(coin, buildTrackedAssetInfo(data));
207
+ }
208
+ return result;
209
+ }
210
+ }
211
+ function buildTrackedAssetInfo(data) {
212
+ return {
213
+ coin: data.coin,
214
+ leverage: (data.leverage?.value ?? 1).toString(),
215
+ marginType: data.leverage?.type
216
+ };
217
+ }
218
+
219
+ export { HyperliquidAccountTracker };
@@ -0,0 +1,23 @@
1
+ declare enum HyperliquidAccountType {
2
+ DEFAULT = "default",
3
+ DEX_ABSTRACTION = "dexAbstraction",
4
+ DISABLED = "disabled",
5
+ PORTFOLIO_MARGIN = "portfolioMargin",
6
+ UNIFIED_ACCOUNT = "unifiedAccount"
7
+ }
8
+ interface HyperliquidCoinBalance {
9
+ coin: string;
10
+ total: string;
11
+ hold: string;
12
+ }
13
+ interface AggregatedClearinghouseSummary {
14
+ accountValue: string;
15
+ totalMarginUsed: string;
16
+ totalRawUsd: string;
17
+ crossMaintenanceMarginUsed: string;
18
+ withdrawable: string;
19
+ totalUnrealizedPnl: string;
20
+ }
21
+ declare const COLLATERAL_TOKEN_MAP: Record<number, string>;
22
+
23
+ export { type AggregatedClearinghouseSummary, COLLATERAL_TOKEN_MAP, HyperliquidAccountType, type HyperliquidCoinBalance };
@@ -0,0 +1,38 @@
1
+ import { Connector } from '@pear-protocol/types';
2
+ import { ExchangeWsByConnector } from '../client/index.js';
3
+ import { SupportedCredentials } from '../types.js';
4
+ import { AccountTrackerConfig, AccountTracker } from './base.js';
5
+ export { BaseAccountTracker } from './base.js';
6
+ export { BinanceAccountTracker, BinanceAccountTrackerConfig } from './binance/tracker.js';
7
+ export { BinanceAccountType } from './binance/types.js';
8
+ export { BybitAccountTracker, BybitAccountTrackerConfig } from './bybit/tracker.js';
9
+ export { BybitAccountType } from './bybit/types.js';
10
+ export { HyperliquidAccountTracker, HyperliquidAccountTrackerConfig } from './hyperliquid/tracker.js';
11
+ export { HyperliquidAccountType } from './hyperliquid/types.js';
12
+ export { LighterAccountTracker, LighterAccountTrackerConfig } from './lighter/tracker.js';
13
+ export { LighterAccountType } from './lighter/types.js';
14
+ export { OkxAccountTracker, OkxAccountTrackerConfig } from './okx/tracker.js';
15
+ export { OkxAccountType } from './okx/types.js';
16
+ export { ACCOUNT_TYPE_LABELS, AccountBalance, AccountPosition, AccountType, AssetBalance, BalanceCallback, ExchangeState, MarginMode, PositionsCallback, StateUpdate, TrackedAssetCallback, TrackedAssetInfo } from './types.js';
17
+ import '../client/binance/exchange-ws.js';
18
+ import '../client/base-ws.js';
19
+ import 'partysocket';
20
+ import '../client/exchange-ws.js';
21
+ import '../client/binance/ws.js';
22
+ import '../client/bybit/exchange-ws.js';
23
+ import '../client/bybit/ws.js';
24
+ import '../client/hyperliquid/exchange-ws.js';
25
+ import '../client/hyperliquid/ws.js';
26
+ import '../client/lighter/exchange-ws.js';
27
+ import '../client/lighter/ws.js';
28
+ import '../client/okx/exchange-ws.js';
29
+ import '../client/okx/ws.js';
30
+ import '@pear-protocol/core-sdk';
31
+
32
+ type CreateAccountTrackerConfig<E extends Connector> = AccountTrackerConfig & {
33
+ credentials: SupportedCredentials;
34
+ ws: ExchangeWsByConnector[E];
35
+ };
36
+ declare function createAccountTracker<E extends Connector>(exchange: E, config: CreateAccountTrackerConfig<E>): AccountTracker;
37
+
38
+ export { AccountTracker, AccountTrackerConfig, type CreateAccountTrackerConfig, createAccountTracker };
@@ -0,0 +1,81 @@
1
+ import { BinanceAccountTracker } from './binance/tracker';
2
+ export { BinanceAccountTracker } from './binance/tracker';
3
+ import { BybitAccountTracker } from './bybit/tracker';
4
+ export { BybitAccountTracker } from './bybit/tracker';
5
+ import { HyperliquidAccountTracker } from './hyperliquid/tracker';
6
+ export { HyperliquidAccountTracker } from './hyperliquid/tracker';
7
+ import { LighterAccountTracker } from './lighter/tracker';
8
+ export { LighterAccountTracker } from './lighter/tracker';
9
+ import { OkxAccountTracker } from './okx/tracker';
10
+ export { OkxAccountTracker } from './okx/tracker';
11
+ export { BaseAccountTracker } from './base';
12
+ export { BinanceAccountType } from './binance/types';
13
+ export { BybitAccountType } from './bybit/types';
14
+ export { HyperliquidAccountType } from './hyperliquid/types';
15
+ export { LighterAccountType } from './lighter/types';
16
+ export { OkxAccountType } from './okx/types';
17
+ export * from './types';
18
+
19
+ function createAccountTracker(exchange, config) {
20
+ let tracker;
21
+ switch (exchange) {
22
+ case "binance": {
23
+ const ws = config.ws;
24
+ tracker = new BinanceAccountTracker({
25
+ demo: config.demo,
26
+ onError: config.onError,
27
+ credentials: config.credentials,
28
+ userDataWs: ws.userData,
29
+ wsApiWs: ws.wsApi
30
+ });
31
+ break;
32
+ }
33
+ case "bybit": {
34
+ const ws = config.ws;
35
+ tracker = new BybitAccountTracker({
36
+ demo: config.demo,
37
+ onError: config.onError,
38
+ credentials: config.credentials,
39
+ ws
40
+ });
41
+ break;
42
+ }
43
+ case "okx": {
44
+ const ws = config.ws;
45
+ tracker = new OkxAccountTracker({
46
+ demo: config.demo,
47
+ onError: config.onError,
48
+ credentials: config.credentials,
49
+ ws
50
+ });
51
+ break;
52
+ }
53
+ case "hyperliquid": {
54
+ const ws = config.ws;
55
+ tracker = new HyperliquidAccountTracker({
56
+ demo: config.demo,
57
+ onError: config.onError,
58
+ credentials: config.credentials,
59
+ ws: ws.main
60
+ });
61
+ break;
62
+ }
63
+ case "lighter": {
64
+ const ws = config.ws;
65
+ tracker = new LighterAccountTracker({
66
+ demo: config.demo,
67
+ onError: config.onError,
68
+ credentials: config.credentials,
69
+ ws: ws.main
70
+ });
71
+ break;
72
+ }
73
+ default: {
74
+ const _exhaustive = exchange;
75
+ throw new Error(`Unsupported exchange: ${String(_exhaustive)}`);
76
+ }
77
+ }
78
+ return tracker;
79
+ }
80
+
81
+ export { createAccountTracker };
@@ -0,0 +1,3 @@
1
+ declare const QUOTE_ASSET = "USDC";
2
+
3
+ export { QUOTE_ASSET };
@@ -0,0 +1,3 @@
1
+ const QUOTE_ASSET = "USDC";
2
+
3
+ export { QUOTE_ASSET };