@pear-protocol/exchanges-sdk 0.6.4 → 0.6.6
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/dist/client/base-ws.js +15 -6
- package/dist/client/binance/exchange-ws.js +22 -8
- package/dist/client/binance/rest.js +40 -27
- package/dist/client/binance/ws.js +21 -2
- package/dist/client/bybit/exchange-ws.js +13 -6
- package/dist/client/bybit/rest.js +30 -36
- package/dist/client/bybit/ws.js +16 -2
- package/dist/client/exchange-ws.js +5 -0
- package/dist/client/hmac.js +9 -1
- package/dist/client/hyperliquid/exchange-ws.js +13 -5
- package/dist/client/hyperliquid/rest.js +37 -7
- package/dist/client/hyperliquid/ws.js +10 -4
- package/dist/client/index.js +9 -2
- package/dist/client/lighter/constants.js +4 -0
- package/dist/client/lighter/exchange-ws.js +13 -5
- package/dist/client/lighter/rest.js +153 -18
- package/dist/client/lighter/ws.js +10 -4
- package/dist/client/okx/exchange-ws.js +13 -6
- package/dist/client/okx/rest.js +27 -24
- package/dist/client/okx/ws.js +5 -0
- package/dist/helper/factory.js +3 -0
- package/dist/helper/hyperliquid/helper.js +18 -23
- package/dist/helper/lighter/auth-token.helper.js +68 -0
- package/dist/helper/lighter/cctp-deposit.helper.js +297 -0
- package/dist/helper/lighter/ethereum/abi.js +55 -11
- package/dist/helper/lighter/ethereum/index.js +22 -3
- package/dist/helper/lighter/ethereum/usdc.helper.js +77 -0
- package/dist/helper/lighter/helper.js +112 -37
- package/dist/helper/lighter/index.js +1 -0
- package/dist/helper/lighter/onboarding.helper.js +28 -0
- package/dist/helper/lighter/types.js +6 -1
- package/dist/helper/subaccount.helper.js +20 -0
- package/dist/index.d.ts +200 -1
- package/dist/sdk.js +18 -7
- package/dist/status/base.js +16 -3
- package/dist/status/binance/status.js +3 -0
- package/dist/status/bybit/status.js +3 -0
- package/dist/status/factory.js +3 -0
- package/dist/status/hyperliquid/status.js +8 -6
- package/dist/status/lighter/status.js +11 -3
- package/dist/status/okx/status.js +3 -0
- package/dist/syncer/base.js +79 -24
- package/dist/syncer/binance/syncer.js +14 -13
- package/dist/syncer/bybit/syncer.js +10 -6
- package/dist/syncer/factory.js +3 -0
- package/dist/syncer/hyperliquid/funding.js +3 -0
- package/dist/syncer/hyperliquid/syncer.js +52 -66
- package/dist/syncer/lighter/funding.js +3 -0
- package/dist/syncer/lighter/syncer.js +26 -25
- package/dist/syncer/okx/syncer.js +15 -13
- package/dist/tracker/base.js +15 -5
- package/dist/tracker/binance/mapper.js +5 -1
- package/dist/tracker/binance/tracker.js +63 -23
- package/dist/tracker/binance/types.js +2 -2
- package/dist/tracker/bybit/mapper.js +7 -1
- package/dist/tracker/bybit/tracker.js +68 -24
- package/dist/tracker/bybit/types.js +2 -2
- package/dist/tracker/hyperliquid/const.js +3 -1
- package/dist/tracker/hyperliquid/mapper.js +36 -20
- package/dist/tracker/hyperliquid/tracker.js +147 -54
- package/dist/tracker/hyperliquid/types.js +2 -2
- package/dist/tracker/index.js +3 -0
- package/dist/tracker/lighter/mapper.js +41 -31
- package/dist/tracker/lighter/tracker.js +68 -27
- package/dist/tracker/lighter/types.js +4 -4
- package/dist/tracker/okx/mapper.js +8 -0
- package/dist/tracker/okx/tracker.js +69 -18
- package/dist/tracker/okx/types.js +2 -2
- package/dist/tracker/utils.js +4 -0
- package/package.json +4 -4
- package/dist/client/hyperliquid/client.test.js +0 -41
- package/dist/client/lighter/constants.test.js +0 -22
- package/dist/client/lighter/rest.test.js +0 -158
- package/dist/helper/hyperliquid/helper.test.js +0 -72
- package/dist/helper/lighter/helper.test.js +0 -289
- package/dist/sdk.test.js +0 -117
- package/dist/status/hyperliquid/status.test.js +0 -94
- package/dist/status/lighter/status.test.js +0 -86
- package/dist/syncer/base.test.js +0 -148
- package/dist/syncer/hyperliquid/funding.test.js +0 -63
- package/dist/syncer/hyperliquid/syncer.test.js +0 -271
- package/dist/syncer/lighter/funding.test.js +0 -48
- package/dist/syncer/lighter/syncer.test.js +0 -274
- package/dist/tracker/base.test.js +0 -132
- package/dist/tracker/binance/tracker.test.js +0 -138
- package/dist/tracker/bybit/tracker.test.js +0 -145
- package/dist/tracker/hyperliquid/mapper.test.js +0 -260
- package/dist/tracker/hyperliquid/tracker.test.js +0 -597
- package/dist/tracker/lighter/mapper.test.js +0 -199
- package/dist/tracker/lighter/tracker.test.js +0 -515
- package/dist/tracker/okx/tracker.test.js +0 -126
- package/dist/tracker/utils.test.js +0 -8
|
@@ -3,6 +3,8 @@ import { positionKey } from '../utils';
|
|
|
3
3
|
import { QUOTE_ASSET } from './const';
|
|
4
4
|
import { LighterAccountType, LighterAccountTier } from './types';
|
|
5
5
|
|
|
6
|
+
var __defProp = Object.defineProperty;
|
|
7
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
6
8
|
function buildAssetBalances(rawAssets) {
|
|
7
9
|
const free = {};
|
|
8
10
|
const used = {};
|
|
@@ -26,8 +28,14 @@ function buildAssetBalances(rawAssets) {
|
|
|
26
28
|
usdValue: rawAsset.symbol === QUOTE_ASSET ? totalAmount : "0"
|
|
27
29
|
});
|
|
28
30
|
}
|
|
29
|
-
return {
|
|
31
|
+
return {
|
|
32
|
+
free,
|
|
33
|
+
used,
|
|
34
|
+
total,
|
|
35
|
+
assets
|
|
36
|
+
};
|
|
30
37
|
}
|
|
38
|
+
__name(buildAssetBalances, "buildAssetBalances");
|
|
31
39
|
function mapBalance(summary, assetsByAssetId, rawPositions, marketsByMarketId) {
|
|
32
40
|
const { free, used, total, assets } = buildAssetBalances(assetsByAssetId.values());
|
|
33
41
|
const portfolioValueBN = new BigNumber(summary.portfolioValue);
|
|
@@ -35,14 +43,8 @@ function mapBalance(summary, assetsByAssetId, rawPositions, marketsByMarketId) {
|
|
|
35
43
|
const unrealizedPnl = portfolioValueBN.minus(summary.collateral).toFixed(6);
|
|
36
44
|
const initialMarginUsed = marginUsageFrac.multipliedBy(portfolioValueBN).toFixed(6);
|
|
37
45
|
const positionRisks = calculatePositionRisks(rawPositions, marketsByMarketId);
|
|
38
|
-
const maintenanceMargin = positionRisks.reduce(
|
|
39
|
-
|
|
40
|
-
new BigNumber(0)
|
|
41
|
-
);
|
|
42
|
-
const isolatedEquity = positionRisks.reduce(
|
|
43
|
-
(totalEquity, positionRisk) => positionRisk.marginMode === "isolated" ? totalEquity.plus(positionRisk.equity) : totalEquity,
|
|
44
|
-
new BigNumber(0)
|
|
45
|
-
);
|
|
46
|
+
const maintenanceMargin = positionRisks.reduce((totalMaintenance, positionRisk) => totalMaintenance.plus(positionRisk.maintenance), new BigNumber(0));
|
|
47
|
+
const isolatedEquity = positionRisks.reduce((totalEquity, positionRisk) => positionRisk.marginMode === "isolated" ? totalEquity.plus(positionRisk.equity) : totalEquity, new BigNumber(0));
|
|
46
48
|
const crossEquity = new BigNumber(summary.crossPortfolioValue ?? portfolioValueBN.minus(isolatedEquity));
|
|
47
49
|
const marginRatio = maximumMarginRatio(positionRisks, crossEquity);
|
|
48
50
|
return {
|
|
@@ -62,6 +64,7 @@ function mapBalance(summary, assetsByAssetId, rawPositions, marketsByMarketId) {
|
|
|
62
64
|
timestamp: Date.now()
|
|
63
65
|
};
|
|
64
66
|
}
|
|
67
|
+
__name(mapBalance, "mapBalance");
|
|
65
68
|
function buildAccountBalance(account, marketsByMarketId, accountTier) {
|
|
66
69
|
const { free, used, total, assets } = buildAssetBalances(account.assets ?? []);
|
|
67
70
|
const positions = account.positions ?? [];
|
|
@@ -71,24 +74,13 @@ function buildAccountBalance(account, marketsByMarketId, accountTier) {
|
|
|
71
74
|
if (position.margin_mode !== 1 || new BigNumber(position.position).isZero()) {
|
|
72
75
|
return totalInitialMargin;
|
|
73
76
|
}
|
|
74
|
-
return totalInitialMargin.plus(
|
|
75
|
-
new BigNumber(position.position_value).abs().times(position.initial_margin_fraction).div(100)
|
|
76
|
-
);
|
|
77
|
+
return totalInitialMargin.plus(new BigNumber(position.position_value).abs().times(position.initial_margin_fraction).div(100));
|
|
77
78
|
}, new BigNumber(0));
|
|
78
79
|
const initialMargin = new BigNumber(account.cross_initial_margin_requirement).plus(isolatedInitialMargin);
|
|
79
80
|
const positionRisks = calculatePositionRisks(positions, marketsByMarketId);
|
|
80
|
-
const isolatedMaintenanceMargin = positionRisks.reduce(
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
);
|
|
84
|
-
const maintenanceMarginBN = new BigNumber(account.cross_maintenance_margin_requirement).plus(
|
|
85
|
-
isolatedMaintenanceMargin
|
|
86
|
-
);
|
|
87
|
-
const marginRatio = maximumMarginRatio(
|
|
88
|
-
positionRisks.filter((positionRisk) => positionRisk.marginMode === "isolated"),
|
|
89
|
-
new BigNumber(account.cross_asset_value),
|
|
90
|
-
new BigNumber(account.cross_maintenance_margin_requirement)
|
|
91
|
-
);
|
|
81
|
+
const isolatedMaintenanceMargin = positionRisks.reduce((totalMaintenance, positionRisk) => positionRisk.marginMode === "isolated" ? totalMaintenance.plus(positionRisk.maintenance) : totalMaintenance, new BigNumber(0));
|
|
82
|
+
const maintenanceMarginBN = new BigNumber(account.cross_maintenance_margin_requirement).plus(isolatedMaintenanceMargin);
|
|
83
|
+
const marginRatio = maximumMarginRatio(positionRisks.filter((positionRisk) => positionRisk.marginMode === "isolated"), new BigNumber(account.cross_asset_value), new BigNumber(account.cross_maintenance_margin_requirement));
|
|
92
84
|
const unrealizedPnl = sumPositionField(positions, "unrealized_pnl").toFixed(6);
|
|
93
85
|
return {
|
|
94
86
|
accountType: toLighterAccountType(account.account_trading_mode),
|
|
@@ -107,6 +99,7 @@ function buildAccountBalance(account, marketsByMarketId, accountTier) {
|
|
|
107
99
|
timestamp: Date.now()
|
|
108
100
|
};
|
|
109
101
|
}
|
|
102
|
+
__name(buildAccountBalance, "buildAccountBalance");
|
|
110
103
|
function mapPositions(raw, includeZeroPositions = false) {
|
|
111
104
|
const positions = /* @__PURE__ */ new Map();
|
|
112
105
|
const trackedAssets = /* @__PURE__ */ new Map();
|
|
@@ -117,7 +110,11 @@ function mapPositions(raw, includeZeroPositions = false) {
|
|
|
117
110
|
const leverage = leverageFromImf(rawPosition.initial_margin_fraction);
|
|
118
111
|
const marginType = rawPosition.margin_mode === 1 ? "isolated" : "cross";
|
|
119
112
|
const marketId = String(rawPosition.market_id);
|
|
120
|
-
trackedAssets.set(marketId, {
|
|
113
|
+
trackedAssets.set(marketId, {
|
|
114
|
+
coin: rawPosition.symbol,
|
|
115
|
+
leverage,
|
|
116
|
+
marginType
|
|
117
|
+
});
|
|
121
118
|
if (!includeZeroPositions && unsignedSize.isZero()) continue;
|
|
122
119
|
positions.set(positionKey(rawPosition.symbol, side), {
|
|
123
120
|
symbol: rawPosition.symbol,
|
|
@@ -130,13 +127,18 @@ function mapPositions(raw, includeZeroPositions = false) {
|
|
|
130
127
|
liquidationPrice: rawPosition.liquidation_price && rawPosition.liquidation_price !== "0" ? rawPosition.liquidation_price : null
|
|
131
128
|
});
|
|
132
129
|
}
|
|
133
|
-
return {
|
|
130
|
+
return {
|
|
131
|
+
positions,
|
|
132
|
+
trackedAssets
|
|
133
|
+
};
|
|
134
134
|
}
|
|
135
|
+
__name(mapPositions, "mapPositions");
|
|
135
136
|
function leverageFromImf(imfPct) {
|
|
136
137
|
const pct = new BigNumber(imfPct);
|
|
137
138
|
if (!pct.isFinite() || pct.lte(0)) return "1";
|
|
138
139
|
return new BigNumber(100).div(pct).integerValue(BigNumber.ROUND_FLOOR).toFixed();
|
|
139
140
|
}
|
|
141
|
+
__name(leverageFromImf, "leverageFromImf");
|
|
140
142
|
function mapMarketDefaultAssetInfo(market) {
|
|
141
143
|
return {
|
|
142
144
|
coin: market.symbol,
|
|
@@ -144,9 +146,11 @@ function mapMarketDefaultAssetInfo(market) {
|
|
|
144
146
|
marginType: "cross"
|
|
145
147
|
};
|
|
146
148
|
}
|
|
149
|
+
__name(mapMarketDefaultAssetInfo, "mapMarketDefaultAssetInfo");
|
|
147
150
|
function toLighterAccountType(accountTradingMode) {
|
|
148
151
|
return accountTradingMode === 1 ? LighterAccountType.UNIFIED : LighterAccountType.CLASSIC;
|
|
149
152
|
}
|
|
153
|
+
__name(toLighterAccountType, "toLighterAccountType");
|
|
150
154
|
function toLighterAccountTier(userTier) {
|
|
151
155
|
switch (userTier?.trim().toLowerCase()) {
|
|
152
156
|
case "std":
|
|
@@ -160,6 +164,7 @@ function toLighterAccountTier(userTier) {
|
|
|
160
164
|
return void 0;
|
|
161
165
|
}
|
|
162
166
|
}
|
|
167
|
+
__name(toLighterAccountTier, "toLighterAccountTier");
|
|
163
168
|
function calculatePositionRisks(rawPositions, marketsByMarketId) {
|
|
164
169
|
const positionRisks = [];
|
|
165
170
|
for (const rawPosition of rawPositions) {
|
|
@@ -170,15 +175,17 @@ function calculatePositionRisks(rawPositions, marketsByMarketId) {
|
|
|
170
175
|
const marginMode = rawPosition.margin_mode === 1 ? "isolated" : "cross";
|
|
171
176
|
const maintenance = new BigNumber(rawPosition.position_value).abs().times(market.maintenance_margin_fraction).div(1e4);
|
|
172
177
|
const equity = marginMode === "isolated" ? new BigNumber(rawPosition.allocated_margin).plus(rawPosition.unrealized_pnl) : new BigNumber(0);
|
|
173
|
-
positionRisks.push({
|
|
178
|
+
positionRisks.push({
|
|
179
|
+
marginMode,
|
|
180
|
+
maintenance,
|
|
181
|
+
equity
|
|
182
|
+
});
|
|
174
183
|
}
|
|
175
184
|
return positionRisks;
|
|
176
185
|
}
|
|
186
|
+
__name(calculatePositionRisks, "calculatePositionRisks");
|
|
177
187
|
function maximumMarginRatio(positionRisks, crossEquity, authoritativeCrossMaintenance) {
|
|
178
|
-
const calculatedCrossMaintenance = positionRisks.reduce(
|
|
179
|
-
(totalMaintenance, positionRisk) => positionRisk.marginMode === "cross" ? totalMaintenance.plus(positionRisk.maintenance) : totalMaintenance,
|
|
180
|
-
new BigNumber(0)
|
|
181
|
-
);
|
|
188
|
+
const calculatedCrossMaintenance = positionRisks.reduce((totalMaintenance, positionRisk) => positionRisk.marginMode === "cross" ? totalMaintenance.plus(positionRisk.maintenance) : totalMaintenance, new BigNumber(0));
|
|
182
189
|
const crossMaintenance = authoritativeCrossMaintenance ?? calculatedCrossMaintenance;
|
|
183
190
|
let maximumRatio = maintenanceRatio(crossMaintenance, crossEquity);
|
|
184
191
|
for (const positionRisk of positionRisks) {
|
|
@@ -188,12 +195,14 @@ function maximumMarginRatio(positionRisks, crossEquity, authoritativeCrossMainte
|
|
|
188
195
|
}
|
|
189
196
|
return maximumRatio.toFixed(4);
|
|
190
197
|
}
|
|
198
|
+
__name(maximumMarginRatio, "maximumMarginRatio");
|
|
191
199
|
function maintenanceRatio(maintenance, equity) {
|
|
192
200
|
if (equity.gt(0)) {
|
|
193
201
|
return maintenance.div(equity);
|
|
194
202
|
}
|
|
195
203
|
return maintenance.gt(0) ? new BigNumber(1) : new BigNumber(0);
|
|
196
204
|
}
|
|
205
|
+
__name(maintenanceRatio, "maintenanceRatio");
|
|
197
206
|
function sumPositionField(positions, field, include = () => true) {
|
|
198
207
|
let total = new BigNumber(0);
|
|
199
208
|
for (const position of positions) {
|
|
@@ -203,5 +212,6 @@ function sumPositionField(positions, field, include = () => true) {
|
|
|
203
212
|
}
|
|
204
213
|
return total;
|
|
205
214
|
}
|
|
215
|
+
__name(sumPositionField, "sumPositionField");
|
|
206
216
|
|
|
207
217
|
export { buildAccountBalance, leverageFromImf, mapBalance, mapMarketDefaultAssetInfo, mapPositions, toLighterAccountTier, toLighterAccountType };
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import BigNumber from 'bignumber.js';
|
|
2
2
|
import { createExchangeWs } from '../../client';
|
|
3
3
|
import { fetchOrderBookDetails, fetchAccount, fetchAccountLimits } from '../../client/lighter/rest';
|
|
4
|
+
import { retrieveLighterAuthToken } from '../../helper/lighter/auth-token.helper';
|
|
4
5
|
import { BaseAccountTracker } from '../base';
|
|
5
6
|
import { mapPositions, buildAccountBalance, mapMarketDefaultAssetInfo, mapBalance, toLighterAccountTier } from './mapper';
|
|
6
7
|
import { LighterAccountType } from './types';
|
|
7
8
|
|
|
9
|
+
var __defProp = Object.defineProperty;
|
|
10
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
8
11
|
const ACCOUNT_TIER_REFRESH_INTERVAL_MS = 6e4;
|
|
9
12
|
function toPosRecord(positions) {
|
|
10
13
|
const posRecord = {};
|
|
@@ -13,7 +16,11 @@ function toPosRecord(positions) {
|
|
|
13
16
|
}
|
|
14
17
|
return posRecord;
|
|
15
18
|
}
|
|
19
|
+
__name(toPosRecord, "toPosRecord");
|
|
16
20
|
class LighterAccountTracker extends BaseAccountTracker {
|
|
21
|
+
static {
|
|
22
|
+
__name(this, "LighterAccountTracker");
|
|
23
|
+
}
|
|
17
24
|
accountIdentifier;
|
|
18
25
|
sdk;
|
|
19
26
|
ws = null;
|
|
@@ -43,22 +50,31 @@ class LighterAccountTracker extends BaseAccountTracker {
|
|
|
43
50
|
fetchOrderBookDetails(this.demo),
|
|
44
51
|
this.fetchAccountTier()
|
|
45
52
|
]);
|
|
46
|
-
if (!account) return {
|
|
53
|
+
if (!account) return {
|
|
54
|
+
balance: null,
|
|
55
|
+
positions: []
|
|
56
|
+
};
|
|
47
57
|
const { positions } = mapPositions(toPosRecord(account.positions ?? []));
|
|
48
|
-
const marketsByMarketId = new Map(markets.map((market) => [
|
|
58
|
+
const marketsByMarketId = new Map(markets.map((market) => [
|
|
59
|
+
market.market_id,
|
|
60
|
+
market
|
|
61
|
+
]));
|
|
49
62
|
return {
|
|
50
63
|
balance: buildAccountBalance(account, marketsByMarketId, accountTier),
|
|
51
64
|
positions: Array.from(positions.values())
|
|
52
65
|
};
|
|
53
66
|
}
|
|
54
67
|
/**
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
68
|
+
* Stateless one-shot per-asset settings read, keyed by market id (the same identifier the live
|
|
69
|
+
* trackAsset path uses). One public `GET /api/v1/account` covers every market the account holds
|
|
70
|
+
* a position row for (custom margin included, even when its size is zero); `orderBookDetails`
|
|
71
|
+
* supplies the exchange default for markets absent from the account payload.
|
|
72
|
+
*/
|
|
60
73
|
async fetchAssetSnapshots(marketIds) {
|
|
61
|
-
const [account, markets] = await Promise.all([
|
|
74
|
+
const [account, markets] = await Promise.all([
|
|
75
|
+
this.fetchPrimaryAccount(),
|
|
76
|
+
fetchOrderBookDetails(this.demo)
|
|
77
|
+
]);
|
|
62
78
|
const { trackedAssets } = mapPositions(toPosRecord(account?.positions ?? []), true);
|
|
63
79
|
const defaults = /* @__PURE__ */ new Map();
|
|
64
80
|
for (const m of markets) {
|
|
@@ -88,7 +104,10 @@ class LighterAccountTracker extends BaseAccountTracker {
|
|
|
88
104
|
/** Creates one tracker lifecycle while repeated callers share the same pending start. */
|
|
89
105
|
async performStart() {
|
|
90
106
|
const lifecycleVersion = ++this.lifecycleVersion;
|
|
91
|
-
const [markets, accountTier] = await Promise.all([
|
|
107
|
+
const [markets, accountTier] = await Promise.all([
|
|
108
|
+
fetchOrderBookDetails(this.demo),
|
|
109
|
+
this.fetchAccountTier()
|
|
110
|
+
]);
|
|
92
111
|
if (lifecycleVersion !== this.lifecycleVersion) return;
|
|
93
112
|
this.accountTier = accountTier;
|
|
94
113
|
this.lastAccountTierFetchAt = Date.now();
|
|
@@ -97,8 +116,13 @@ class LighterAccountTracker extends BaseAccountTracker {
|
|
|
97
116
|
this.marketsByMarketId.set(m.market_id, m);
|
|
98
117
|
trackedAssets.set(String(m.market_id), mapMarketDefaultAssetInfo(m));
|
|
99
118
|
}
|
|
100
|
-
this.onStateUpdate({
|
|
101
|
-
|
|
119
|
+
this.onStateUpdate({
|
|
120
|
+
trackedAssets
|
|
121
|
+
});
|
|
122
|
+
const ws = (await createExchangeWs("lighter", {
|
|
123
|
+
demo: this.demo,
|
|
124
|
+
credentials: this.credentials
|
|
125
|
+
})).main;
|
|
102
126
|
if (lifecycleVersion !== this.lifecycleVersion) {
|
|
103
127
|
ws.destroy();
|
|
104
128
|
return;
|
|
@@ -147,7 +171,9 @@ class LighterAccountTracker extends BaseAccountTracker {
|
|
|
147
171
|
for (const market of this.marketsByMarketId.values()) {
|
|
148
172
|
trackedAssets.set(String(market.market_id), mapMarketDefaultAssetInfo(market));
|
|
149
173
|
}
|
|
150
|
-
this.onStateUpdate({
|
|
174
|
+
this.onStateUpdate({
|
|
175
|
+
trackedAssets
|
|
176
|
+
});
|
|
151
177
|
this.sendStaticSubs();
|
|
152
178
|
}
|
|
153
179
|
sendStaticSubs() {
|
|
@@ -165,9 +191,15 @@ class LighterAccountTracker extends BaseAccountTracker {
|
|
|
165
191
|
const msg = JSON.parse(raw);
|
|
166
192
|
if (!msg.type) return;
|
|
167
193
|
if (msg.type === "subscribed/account_all" || msg.type === "update/account_all") {
|
|
168
|
-
this.handle({
|
|
194
|
+
this.handle({
|
|
195
|
+
kind: "account_all",
|
|
196
|
+
data: msg
|
|
197
|
+
});
|
|
169
198
|
} else if (msg.type === "subscribed/user_stats" || msg.type === "update/user_stats") {
|
|
170
|
-
this.handle({
|
|
199
|
+
this.handle({
|
|
200
|
+
kind: "user_stats",
|
|
201
|
+
data: msg
|
|
202
|
+
});
|
|
171
203
|
}
|
|
172
204
|
} catch (err) {
|
|
173
205
|
this.onError(err instanceof Error ? err : new Error(String(err)));
|
|
@@ -194,7 +226,9 @@ class LighterAccountTracker extends BaseAccountTracker {
|
|
|
194
226
|
this.hasAssets = true;
|
|
195
227
|
}
|
|
196
228
|
if (data.positions) {
|
|
197
|
-
const positionsForMapping = {
|
|
229
|
+
const positionsForMapping = {
|
|
230
|
+
...data.positions
|
|
231
|
+
};
|
|
198
232
|
if (isSnapshot) {
|
|
199
233
|
this.rawPositionsByMarketId.clear();
|
|
200
234
|
}
|
|
@@ -202,7 +236,10 @@ class LighterAccountTracker extends BaseAccountTracker {
|
|
|
202
236
|
if (new BigNumber(position.position).isZero()) {
|
|
203
237
|
const previousPosition = this.rawPositionsByMarketId.get(marketId);
|
|
204
238
|
if (previousPosition) {
|
|
205
|
-
positionsForMapping[marketId] = {
|
|
239
|
+
positionsForMapping[marketId] = {
|
|
240
|
+
...position,
|
|
241
|
+
sign: previousPosition.sign
|
|
242
|
+
};
|
|
206
243
|
}
|
|
207
244
|
this.rawPositionsByMarketId.delete(marketId);
|
|
208
245
|
} else {
|
|
@@ -231,31 +268,33 @@ class LighterAccountTracker extends BaseAccountTracker {
|
|
|
231
268
|
accountTier: this.accountTier
|
|
232
269
|
};
|
|
233
270
|
const balance = this.buildBalance();
|
|
234
|
-
if (balance) this.onStateUpdate({
|
|
271
|
+
if (balance) this.onStateUpdate({
|
|
272
|
+
balance
|
|
273
|
+
});
|
|
235
274
|
}
|
|
236
275
|
buildBalance() {
|
|
237
276
|
if (!this.summary || !this.hasAssets) return null;
|
|
238
|
-
return mapBalance(
|
|
239
|
-
|
|
240
|
-
this.
|
|
241
|
-
|
|
242
|
-
this.marketsByMarketId
|
|
243
|
-
);
|
|
277
|
+
return mapBalance({
|
|
278
|
+
...this.summary,
|
|
279
|
+
accountTier: this.accountTier
|
|
280
|
+
}, this.assetsByAssetId, this.rawPositionsByMarketId.values(), this.marketsByMarketId);
|
|
244
281
|
}
|
|
245
282
|
async fetchPrimaryAccount() {
|
|
246
283
|
const data = await fetchAccount(Number(this.accountIdentifier), this.demo);
|
|
247
284
|
return data.accounts[0];
|
|
248
285
|
}
|
|
249
286
|
async fetchAccountTier() {
|
|
250
|
-
if (!this.sdk || this.demo)
|
|
287
|
+
if (!this.sdk || this.demo) {
|
|
288
|
+
return void 0;
|
|
289
|
+
}
|
|
251
290
|
try {
|
|
252
291
|
const credentials = this.credentials;
|
|
253
292
|
const accountIndex = Number(this.accountIdentifier);
|
|
254
|
-
const
|
|
293
|
+
const token = await retrieveLighterAuthToken(this.sdk, {
|
|
255
294
|
accountIndex,
|
|
256
295
|
apiKeyIndex: credentials.api_key_index,
|
|
257
296
|
apiPrivateKey: credentials.api_private_key
|
|
258
|
-
});
|
|
297
|
+
}, this.demo);
|
|
259
298
|
const limits = await fetchAccountLimits(accountIndex, token, this.demo);
|
|
260
299
|
return toLighterAccountTier(limits.user_tier);
|
|
261
300
|
} catch (err) {
|
|
@@ -290,7 +329,9 @@ class LighterAccountTracker extends BaseAccountTracker {
|
|
|
290
329
|
this.accountTier = refreshedAccountTier;
|
|
291
330
|
const balance = this.buildBalance();
|
|
292
331
|
if (balance) {
|
|
293
|
-
this.onStateUpdate({
|
|
332
|
+
this.onStateUpdate({
|
|
333
|
+
balance
|
|
334
|
+
});
|
|
294
335
|
}
|
|
295
336
|
}
|
|
296
337
|
if (!account || stateVersion !== this.stateVersion) return;
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
var LighterAccountType = /* @__PURE__ */ ((LighterAccountType2)
|
|
1
|
+
var LighterAccountType = /* @__PURE__ */ (function(LighterAccountType2) {
|
|
2
2
|
LighterAccountType2["BASIC"] = "classic";
|
|
3
3
|
LighterAccountType2["CLASSIC"] = "classic";
|
|
4
4
|
LighterAccountType2["UNIFIED"] = "unified";
|
|
5
5
|
return LighterAccountType2;
|
|
6
|
-
})(
|
|
7
|
-
var LighterAccountTier = /* @__PURE__ */ ((LighterAccountTier2)
|
|
6
|
+
})({});
|
|
7
|
+
var LighterAccountTier = /* @__PURE__ */ (function(LighterAccountTier2) {
|
|
8
8
|
LighterAccountTier2["STANDARD"] = "standard";
|
|
9
9
|
LighterAccountTier2["PREMIUM"] = "premium";
|
|
10
10
|
LighterAccountTier2["PLUS"] = "plus";
|
|
11
11
|
return LighterAccountTier2;
|
|
12
|
-
})(
|
|
12
|
+
})({});
|
|
13
13
|
|
|
14
14
|
export { LighterAccountTier, LighterAccountType };
|
|
@@ -2,6 +2,8 @@ import BigNumber from 'bignumber.js';
|
|
|
2
2
|
import { positionKey } from '../utils';
|
|
3
3
|
import { OkxAccountType } from './types';
|
|
4
4
|
|
|
5
|
+
var __defProp = Object.defineProperty;
|
|
6
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
5
7
|
function mergeRawCoins(existing, incoming) {
|
|
6
8
|
const merged = new Map(existing);
|
|
7
9
|
for (const d of incoming) {
|
|
@@ -9,6 +11,7 @@ function mergeRawCoins(existing, incoming) {
|
|
|
9
11
|
}
|
|
10
12
|
return merged;
|
|
11
13
|
}
|
|
14
|
+
__name(mergeRawCoins, "mergeRawCoins");
|
|
12
15
|
function buildBalance(raw, coins, accountType) {
|
|
13
16
|
if (!accountType) return null;
|
|
14
17
|
const isSpot = accountType === OkxAccountType.SPOT;
|
|
@@ -54,6 +57,7 @@ function buildBalance(raw, coins, accountType) {
|
|
|
54
57
|
timestamp: Date.now()
|
|
55
58
|
};
|
|
56
59
|
}
|
|
60
|
+
__name(buildBalance, "buildBalance");
|
|
57
61
|
function mapSinglePosition(p) {
|
|
58
62
|
const posBN = new BigNumber(p.pos ?? "0");
|
|
59
63
|
let side;
|
|
@@ -81,6 +85,7 @@ function mapSinglePosition(p) {
|
|
|
81
85
|
liquidationPrice: p.liqPx || null
|
|
82
86
|
};
|
|
83
87
|
}
|
|
88
|
+
__name(mapSinglePosition, "mapSinglePosition");
|
|
84
89
|
function mapPositions(raw) {
|
|
85
90
|
const positions = /* @__PURE__ */ new Map();
|
|
86
91
|
for (const p of raw) {
|
|
@@ -91,6 +96,7 @@ function mapPositions(raw) {
|
|
|
91
96
|
}
|
|
92
97
|
return positions;
|
|
93
98
|
}
|
|
99
|
+
__name(mapPositions, "mapPositions");
|
|
94
100
|
function mapPositionUpdates(raw) {
|
|
95
101
|
const positions = /* @__PURE__ */ new Map();
|
|
96
102
|
for (const p of raw) {
|
|
@@ -99,6 +105,7 @@ function mapPositionUpdates(raw) {
|
|
|
99
105
|
}
|
|
100
106
|
return positions;
|
|
101
107
|
}
|
|
108
|
+
__name(mapPositionUpdates, "mapPositionUpdates");
|
|
102
109
|
function acctLvToAccountType(acctLv) {
|
|
103
110
|
switch (acctLv) {
|
|
104
111
|
case "1":
|
|
@@ -113,5 +120,6 @@ function acctLvToAccountType(acctLv) {
|
|
|
113
120
|
return null;
|
|
114
121
|
}
|
|
115
122
|
}
|
|
123
|
+
__name(acctLvToAccountType, "acctLvToAccountType");
|
|
116
124
|
|
|
117
125
|
export { acctLvToAccountType, buildBalance, mapPositionUpdates, mapPositions, mapSinglePosition, mergeRawCoins };
|
|
@@ -3,7 +3,12 @@ import { fetchLeverageInfos, fetchAccountConfig, fetchBalance, fetchPositions }
|
|
|
3
3
|
import { BaseAccountTracker } from '../base';
|
|
4
4
|
import { acctLvToAccountType, mergeRawCoins, mapPositions, buildBalance, mapPositionUpdates } from './mapper';
|
|
5
5
|
|
|
6
|
+
var __defProp = Object.defineProperty;
|
|
7
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
6
8
|
class OkxAccountTracker extends BaseAccountTracker {
|
|
9
|
+
static {
|
|
10
|
+
__name(this, "OkxAccountTracker");
|
|
11
|
+
}
|
|
7
12
|
creds;
|
|
8
13
|
ws = null;
|
|
9
14
|
messageListenerId = null;
|
|
@@ -26,10 +31,10 @@ class OkxAccountTracker extends BaseAccountTracker {
|
|
|
26
31
|
};
|
|
27
32
|
}
|
|
28
33
|
/**
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
34
|
+
* Stateless one-shot per-asset leverage read via `leverage-info`, which accepts up to 20 instIds
|
|
35
|
+
* per request (chunked in the client), so N assets cost ceil(N/20) calls. Cross margin only,
|
|
36
|
+
* matching the account-level assumption used everywhere else in this connector.
|
|
37
|
+
*/
|
|
33
38
|
async fetchAssetSnapshots(instIds) {
|
|
34
39
|
const infos = await fetchLeverageInfos(this.creds, instIds, this.demo);
|
|
35
40
|
const byInstId = /* @__PURE__ */ new Map();
|
|
@@ -39,7 +44,11 @@ class OkxAccountTracker extends BaseAccountTracker {
|
|
|
39
44
|
const result = {};
|
|
40
45
|
for (const instId of instIds) {
|
|
41
46
|
const info = byInstId.get(instId);
|
|
42
|
-
result[instId] = info ? {
|
|
47
|
+
result[instId] = info ? {
|
|
48
|
+
coin: instId,
|
|
49
|
+
leverage: info.lever || "0",
|
|
50
|
+
marginType: info.mgnMode
|
|
51
|
+
} : null;
|
|
43
52
|
}
|
|
44
53
|
return result;
|
|
45
54
|
}
|
|
@@ -47,7 +56,10 @@ class OkxAccountTracker extends BaseAccountTracker {
|
|
|
47
56
|
const { config, balance, positions } = await this.fetchSnapshotData();
|
|
48
57
|
this.accountType = acctLvToAccountType(config.acctLv);
|
|
49
58
|
this.handleInitialData(balance, positions);
|
|
50
|
-
this.ws = await createExchangeWs("okx", {
|
|
59
|
+
this.ws = await createExchangeWs("okx", {
|
|
60
|
+
demo: this.demo,
|
|
61
|
+
credentials: this.credentials
|
|
62
|
+
});
|
|
51
63
|
this.messageListenerId = this.ws.main.addMessageListener((raw) => this.routeRaw(raw));
|
|
52
64
|
this.openListenerId = this.ws.main.addOpenListener(() => {
|
|
53
65
|
this.ws?.login().then(() => this.subscribe()).catch((err) => this.onError(err));
|
|
@@ -75,36 +87,67 @@ class OkxAccountTracker extends BaseAccountTracker {
|
|
|
75
87
|
fetchBalance(this.creds, this.demo),
|
|
76
88
|
fetchPositions(this.creds, this.demo)
|
|
77
89
|
]);
|
|
78
|
-
return {
|
|
90
|
+
return {
|
|
91
|
+
config,
|
|
92
|
+
balance,
|
|
93
|
+
positions
|
|
94
|
+
};
|
|
79
95
|
}
|
|
80
96
|
ensureAssetTracked(instId) {
|
|
81
97
|
if (this.trackedAssetInfos.has(instId)) return;
|
|
82
|
-
fetchLeverageInfos(this.creds, [
|
|
98
|
+
fetchLeverageInfos(this.creds, [
|
|
99
|
+
instId
|
|
100
|
+
], this.demo).catch(() => []).then((infos) => {
|
|
83
101
|
const info = infos[0];
|
|
84
102
|
const leverage = info?.lever || "0";
|
|
85
103
|
const marginType = info?.mgnMode;
|
|
86
|
-
const trackedAssetInfo = {
|
|
104
|
+
const trackedAssetInfo = {
|
|
105
|
+
coin: instId,
|
|
106
|
+
leverage,
|
|
107
|
+
marginType
|
|
108
|
+
};
|
|
87
109
|
this.trackedAssetInfos.set(instId, trackedAssetInfo);
|
|
88
|
-
const trackedAssets = /* @__PURE__ */ new Map([
|
|
89
|
-
|
|
110
|
+
const trackedAssets = /* @__PURE__ */ new Map([
|
|
111
|
+
[
|
|
112
|
+
instId,
|
|
113
|
+
trackedAssetInfo
|
|
114
|
+
]
|
|
115
|
+
]);
|
|
116
|
+
this.onStateUpdate({
|
|
117
|
+
trackedAssets
|
|
118
|
+
});
|
|
90
119
|
}).catch((err) => this.onError(err instanceof Error ? err : new Error(String(err))));
|
|
91
120
|
}
|
|
92
121
|
releaseAsset(instId) {
|
|
93
122
|
this.trackedAssetInfos.delete(instId);
|
|
94
|
-
this.onStateUpdate({
|
|
123
|
+
this.onStateUpdate({
|
|
124
|
+
trackedAssets: new Map(this.trackedAssetInfos)
|
|
125
|
+
});
|
|
95
126
|
}
|
|
96
127
|
subscribe() {
|
|
97
128
|
this.ws?.main.send({
|
|
98
129
|
op: "subscribe",
|
|
99
|
-
args: [
|
|
130
|
+
args: [
|
|
131
|
+
{
|
|
132
|
+
channel: "account"
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
channel: "positions",
|
|
136
|
+
instType: "SWAP"
|
|
137
|
+
}
|
|
138
|
+
]
|
|
100
139
|
});
|
|
101
140
|
}
|
|
102
141
|
handleInitialData(balance, positions) {
|
|
103
142
|
this.lastBalance = balance;
|
|
104
143
|
this.rawCoins = mergeRawCoins(/* @__PURE__ */ new Map(), balance.details ?? []);
|
|
105
144
|
const built = buildBalance(balance, this.rawCoins, this.accountType);
|
|
106
|
-
if (built) this.onStateUpdate({
|
|
107
|
-
|
|
145
|
+
if (built) this.onStateUpdate({
|
|
146
|
+
balance: built
|
|
147
|
+
});
|
|
148
|
+
this.onStateUpdate({
|
|
149
|
+
positions: mapPositions(positions)
|
|
150
|
+
});
|
|
108
151
|
}
|
|
109
152
|
routeRaw(raw) {
|
|
110
153
|
if (raw === "pong") return;
|
|
@@ -136,14 +179,20 @@ class OkxAccountTracker extends BaseAccountTracker {
|
|
|
136
179
|
if (existing) {
|
|
137
180
|
const leverage = p.lever || existing.leverage;
|
|
138
181
|
const marginType = p.mgnMode;
|
|
139
|
-
const updated = {
|
|
182
|
+
const updated = {
|
|
183
|
+
...existing,
|
|
184
|
+
leverage,
|
|
185
|
+
marginType
|
|
186
|
+
};
|
|
140
187
|
this.trackedAssetInfos.set(p.instId, updated);
|
|
141
188
|
trackedAssets.set(p.instId, updated);
|
|
142
189
|
}
|
|
143
190
|
}
|
|
144
191
|
this.onStateUpdate({
|
|
145
192
|
positions,
|
|
146
|
-
...trackedAssets.size > 0 ? {
|
|
193
|
+
...trackedAssets.size > 0 ? {
|
|
194
|
+
trackedAssets
|
|
195
|
+
} : {}
|
|
147
196
|
});
|
|
148
197
|
}
|
|
149
198
|
}
|
|
@@ -161,7 +210,9 @@ class OkxAccountTracker extends BaseAccountTracker {
|
|
|
161
210
|
} : raw;
|
|
162
211
|
this.lastBalance = merged;
|
|
163
212
|
const built = buildBalance(merged, this.rawCoins, this.accountType);
|
|
164
|
-
if (built) this.onStateUpdate({
|
|
213
|
+
if (built) this.onStateUpdate({
|
|
214
|
+
balance: built
|
|
215
|
+
});
|
|
165
216
|
}
|
|
166
217
|
}
|
|
167
218
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
var OkxAccountType = /* @__PURE__ */ ((OkxAccountType2)
|
|
1
|
+
var OkxAccountType = /* @__PURE__ */ (function(OkxAccountType2) {
|
|
2
2
|
OkxAccountType2["SPOT"] = "OKX_SPOT";
|
|
3
3
|
OkxAccountType2["SINGLE_CURRENCY_MARGIN"] = "OKX_SINGLE";
|
|
4
4
|
OkxAccountType2["MULTI_CURRENCY_MARGIN"] = "OKX_MULTI";
|
|
5
5
|
OkxAccountType2["PORTFOLIO_MARGIN"] = "OKX_PORTFOLIO";
|
|
6
6
|
return OkxAccountType2;
|
|
7
|
-
})(
|
|
7
|
+
})({});
|
|
8
8
|
|
|
9
9
|
export { OkxAccountType };
|
package/dist/tracker/utils.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
1
3
|
function createEmptyState() {
|
|
2
4
|
return {
|
|
3
5
|
balance: null,
|
|
@@ -6,8 +8,10 @@ function createEmptyState() {
|
|
|
6
8
|
initialized: false
|
|
7
9
|
};
|
|
8
10
|
}
|
|
11
|
+
__name(createEmptyState, "createEmptyState");
|
|
9
12
|
function positionKey(symbol, side) {
|
|
10
13
|
return `${symbol}:${side}`;
|
|
11
14
|
}
|
|
15
|
+
__name(positionKey, "positionKey");
|
|
12
16
|
|
|
13
17
|
export { createEmptyState, positionKey };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pear-protocol/exchanges-sdk",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.6",
|
|
4
4
|
"description": "Pear Protocol Exchanges SDK",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|
|
@@ -27,9 +27,9 @@
|
|
|
27
27
|
"test:watch": "vitest"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@pear-protocol/core-sdk": "^1.
|
|
31
|
-
"@pear-protocol/types": "^1.
|
|
32
|
-
"@pear-protocol/utils": "^0.5.
|
|
30
|
+
"@pear-protocol/core-sdk": "^1.17.3",
|
|
31
|
+
"@pear-protocol/types": "^1.26.0",
|
|
32
|
+
"@pear-protocol/utils": "^0.5.1",
|
|
33
33
|
"bignumber.js": "^11.1.1",
|
|
34
34
|
"partysocket": "^1.0.3",
|
|
35
35
|
"viem": "^2.48.8"
|