@pear-protocol/exchanges-sdk 0.6.7 → 0.8.0
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 +105 -25
- package/dist/client/bybit/rest.js +8 -1
- package/dist/client/hyperliquid/rest.js +21 -1
- package/dist/client/lighter/rest.js +6 -12
- package/dist/client/okx/rest.js +5 -1
- package/dist/index.d.ts +1131 -78
- package/dist/sdk.js +9 -2
- package/dist/syncer/base.js +36 -14
- package/dist/tracker/balance-core.js +89 -0
- package/dist/tracker/balance.js +25 -0
- package/dist/tracker/basket-size.js +194 -0
- package/dist/tracker/binance/balance.js +11 -0
- package/dist/tracker/binance/mapper.js +87 -42
- package/dist/tracker/binance/tracker.js +29 -14
- package/dist/tracker/binance/types.js +0 -6
- package/dist/tracker/bybit/balance.js +14 -0
- package/dist/tracker/bybit/mapper.js +109 -52
- package/dist/tracker/bybit/tracker.js +242 -33
- package/dist/tracker/bybit/types.js +0 -7
- package/dist/tracker/hyperliquid/account-mode.js +14 -0
- package/dist/tracker/hyperliquid/balance.js +184 -0
- package/dist/tracker/hyperliquid/basket-size.js +93 -0
- package/dist/tracker/hyperliquid/coin-name.js +18 -0
- package/dist/tracker/hyperliquid/collateral.js +48 -0
- package/dist/tracker/hyperliquid/decimal.js +28 -0
- package/dist/tracker/hyperliquid/mapper.js +399 -176
- package/dist/tracker/hyperliquid/spot-pricing.js +106 -0
- package/dist/tracker/hyperliquid/tracker.js +237 -78
- package/dist/tracker/hyperliquid/types.js +1 -7
- package/dist/tracker/index.js +9 -7
- package/dist/tracker/lighter/balance.js +87 -0
- package/dist/tracker/lighter/basket-size.js +74 -0
- package/dist/tracker/lighter/mapper.js +324 -145
- package/dist/tracker/lighter/tracker.js +228 -117
- package/dist/tracker/lighter/types.js +1 -7
- package/dist/tracker/okx/balance.js +17 -0
- package/dist/tracker/okx/mapper.js +156 -58
- package/dist/tracker/okx/tracker.js +228 -29
- package/dist/tracker/okx/types.js +0 -8
- package/dist/tracker/types.js +0 -24
- package/package.json +7 -9
|
@@ -1,110 +1,79 @@
|
|
|
1
1
|
import BigNumber from 'bignumber.js';
|
|
2
2
|
import { positionKey } from '../utils';
|
|
3
3
|
import { QUOTE_ASSET } from './const';
|
|
4
|
-
import { LighterAccountType
|
|
4
|
+
import { LighterAccountType } from './types';
|
|
5
5
|
|
|
6
6
|
var __defProp = Object.defineProperty;
|
|
7
7
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
8
|
+
const USD_DECIMALS = 6;
|
|
9
|
+
const RATE_DECIMALS = 2;
|
|
10
|
+
const FRACTION_DECIMALS = 4;
|
|
11
|
+
const PERCENT_SCALE = 100;
|
|
12
|
+
const MARGIN_FRACTION_SCALE = 1e4;
|
|
13
|
+
const ACCOUNT_MODE_BY_TYPE = {
|
|
14
|
+
[LighterAccountType.CLASSIC]: "lighter:classic",
|
|
15
|
+
[LighterAccountType.UNIFIED]: "lighter:unified"
|
|
16
|
+
};
|
|
17
|
+
function mapLiveBalance(stats, assets, positions, markets, timestamp) {
|
|
18
|
+
const openPositions = Array.from(positions);
|
|
19
|
+
const heldAssets = Array.from(assets);
|
|
20
|
+
const risks = toPositionRisks(openPositions, markets.perpByMarketId);
|
|
21
|
+
const crossEquity = toDecimal(stats.cross.portfolio_value);
|
|
22
|
+
const equity = toEquitySplit(heldAssets, markets.spotPriceBySymbol);
|
|
23
|
+
const perCollateral = toCollateralRows(heldAssets, stats.total.available_balance);
|
|
24
|
+
const crossMaintenance = asMarginRequirement(sumMaintenance(risks, "cross"));
|
|
25
|
+
const isolatedMaintenance = asMarginRequirement(sumMaintenance(risks, "isolated"));
|
|
26
|
+
return toLighterBalance({
|
|
27
|
+
accountMode: ACCOUNT_MODE_BY_TYPE[stats.accountType],
|
|
28
|
+
equity,
|
|
29
|
+
perCollateral,
|
|
30
|
+
unrealizedPnl: signed(sumUnrealizedPnl(openPositions)),
|
|
31
|
+
// The venue states leverage and usage outright here and REST derives them, so each pair meets
|
|
32
|
+
// at one formatter — otherwise the paths would agree only while the venue kept its precision.
|
|
33
|
+
// Usage arrives in percent points and leaves as a fraction, which is the venue's scale changed.
|
|
34
|
+
crossLeverage: rate(toDecimal(stats.cross.leverage)),
|
|
35
|
+
crossMarginUsage: fractionOfPercent(toDecimal(stats.cross.margin_usage)),
|
|
36
|
+
crossMarginRatio: fractionOf(crossMaintenance, crossEquity),
|
|
37
|
+
maintenanceMargin: usdOrNull(sumOf([
|
|
38
|
+
crossMaintenance,
|
|
39
|
+
isolatedMaintenance
|
|
40
|
+
])),
|
|
41
|
+
availableBalance: stats.total.available_balance,
|
|
42
|
+
timestamp
|
|
43
|
+
});
|
|
37
44
|
}
|
|
38
|
-
__name(
|
|
39
|
-
function
|
|
40
|
-
const { free, used, total, assets } = buildAssetBalances(assetsByAssetId.values());
|
|
41
|
-
const portfolioValueBN = new BigNumber(summary.portfolioValue);
|
|
42
|
-
const marginUsageFrac = new BigNumber(summary.marginUsagePct).div(100);
|
|
43
|
-
const unrealizedPnl = portfolioValueBN.minus(summary.collateral).toFixed(6);
|
|
44
|
-
const initialMarginUsed = marginUsageFrac.multipliedBy(portfolioValueBN).toFixed(6);
|
|
45
|
-
const positionRisks = calculatePositionRisks(rawPositions, marketsByMarketId);
|
|
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));
|
|
48
|
-
const crossEquity = new BigNumber(summary.crossPortfolioValue ?? portfolioValueBN.minus(isolatedEquity));
|
|
49
|
-
const marginRatio = maximumMarginRatio(positionRisks, crossEquity);
|
|
50
|
-
return {
|
|
51
|
-
accountType: summary.accountType,
|
|
52
|
-
accountTier: summary.accountTier,
|
|
53
|
-
free,
|
|
54
|
-
used,
|
|
55
|
-
total,
|
|
56
|
-
availableToTrade: summary.availableToTrade,
|
|
57
|
-
totalEquity: summary.portfolioValue,
|
|
58
|
-
walletBalance: summary.collateral,
|
|
59
|
-
unrealizedPnl,
|
|
60
|
-
initialMarginUsed,
|
|
61
|
-
maintenanceMargin: maintenanceMargin.toFixed(6),
|
|
62
|
-
marginRatio,
|
|
63
|
-
assets,
|
|
64
|
-
timestamp: Date.now()
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
__name(mapBalance, "mapBalance");
|
|
68
|
-
function buildAccountBalance(account, marketsByMarketId, accountTier) {
|
|
69
|
-
const { free, used, total, assets } = buildAssetBalances(account.assets ?? []);
|
|
45
|
+
__name(mapLiveBalance, "mapLiveBalance");
|
|
46
|
+
function mapRestBalance(account, markets, timestamp) {
|
|
70
47
|
const positions = account.positions ?? [];
|
|
71
|
-
const
|
|
72
|
-
const
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
walletBalance: totalCollateral.toFixed(6),
|
|
94
|
-
unrealizedPnl,
|
|
95
|
-
initialMarginUsed: initialMargin.toFixed(6),
|
|
96
|
-
maintenanceMargin: maintenanceMarginBN.toFixed(6),
|
|
97
|
-
marginRatio,
|
|
98
|
-
assets,
|
|
99
|
-
timestamp: Date.now()
|
|
100
|
-
};
|
|
48
|
+
const assets = account.assets ?? [];
|
|
49
|
+
const risks = toPositionRisks(positions, markets.perpByMarketId);
|
|
50
|
+
const crossEquity = toDecimal(account.cross_asset_value);
|
|
51
|
+
const crossMaintenance = toDecimal(account.cross_maintenance_margin_requirement);
|
|
52
|
+
const isolatedMaintenance = asMarginRequirement(sumMaintenance(risks, "isolated"));
|
|
53
|
+
const equity = toEquitySplit(assets, markets.spotPriceBySymbol);
|
|
54
|
+
const perCollateral = toCollateralRows(assets, account.available_balance);
|
|
55
|
+
return toLighterBalance({
|
|
56
|
+
accountMode: ACCOUNT_MODE_BY_TYPE[toLighterAccountType(account.account_trading_mode)],
|
|
57
|
+
equity,
|
|
58
|
+
perCollateral,
|
|
59
|
+
unrealizedPnl: signed(sumUnrealizedPnl(positions)),
|
|
60
|
+
crossLeverage: multipleOf(sumNotional(risks, "cross"), crossEquity),
|
|
61
|
+
crossMarginUsage: fractionOf(toDecimal(account.cross_initial_margin_requirement), crossEquity),
|
|
62
|
+
crossMarginRatio: fractionOf(crossMaintenance, crossEquity),
|
|
63
|
+
maintenanceMargin: usdOrNull(sumOf([
|
|
64
|
+
crossMaintenance,
|
|
65
|
+
isolatedMaintenance
|
|
66
|
+
])),
|
|
67
|
+
availableBalance: account.available_balance,
|
|
68
|
+
timestamp
|
|
69
|
+
});
|
|
101
70
|
}
|
|
102
|
-
__name(
|
|
71
|
+
__name(mapRestBalance, "mapRestBalance");
|
|
103
72
|
function mapPositions(raw, includeZeroPositions = false) {
|
|
104
73
|
const positions = /* @__PURE__ */ new Map();
|
|
105
74
|
const trackedAssets = /* @__PURE__ */ new Map();
|
|
106
75
|
for (const rawPosition of Object.values(raw)) {
|
|
107
|
-
const unsignedSize =
|
|
76
|
+
const unsignedSize = toDecimalOrZero(rawPosition.position);
|
|
108
77
|
const side = rawPosition.sign === -1 ? "short" : "long";
|
|
109
78
|
const size = rawPosition.sign === -1 ? unsignedSize.negated() : unsignedSize;
|
|
110
79
|
const leverage = leverageFromImf(rawPosition.initial_margin_fraction);
|
|
@@ -134,7 +103,7 @@ function mapPositions(raw, includeZeroPositions = false) {
|
|
|
134
103
|
}
|
|
135
104
|
__name(mapPositions, "mapPositions");
|
|
136
105
|
function leverageFromImf(imfPct) {
|
|
137
|
-
const pct =
|
|
106
|
+
const pct = toDecimalOrZero(imfPct);
|
|
138
107
|
if (!pct.isFinite() || pct.lte(0)) return "1";
|
|
139
108
|
return new BigNumber(100).div(pct).integerValue(BigNumber.ROUND_FLOOR).toFixed();
|
|
140
109
|
}
|
|
@@ -142,76 +111,286 @@ __name(leverageFromImf, "leverageFromImf");
|
|
|
142
111
|
function mapMarketDefaultAssetInfo(market) {
|
|
143
112
|
return {
|
|
144
113
|
coin: market.symbol,
|
|
145
|
-
leverage: leverageFromImf(
|
|
114
|
+
leverage: leverageFromImf(toDecimalOrZero(market.default_initial_margin_fraction).div(100).toFixed()),
|
|
146
115
|
marginType: "cross"
|
|
147
116
|
};
|
|
148
117
|
}
|
|
149
118
|
__name(mapMarketDefaultAssetInfo, "mapMarketDefaultAssetInfo");
|
|
119
|
+
function buildSpotPriceIndex(spotMarkets) {
|
|
120
|
+
const priceBySymbol = /* @__PURE__ */ new Map([
|
|
121
|
+
[
|
|
122
|
+
QUOTE_ASSET,
|
|
123
|
+
"1"
|
|
124
|
+
]
|
|
125
|
+
]);
|
|
126
|
+
for (const market of spotMarkets) {
|
|
127
|
+
const [baseSymbol] = market.symbol.split("/");
|
|
128
|
+
const price = toDecimal(market.last_trade_price);
|
|
129
|
+
if (baseSymbol === void 0 || market.status !== "active" || price === null || !price.isGreaterThan(0)) {
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
priceBySymbol.set(baseSymbol, price.toFixed());
|
|
133
|
+
}
|
|
134
|
+
return priceBySymbol;
|
|
135
|
+
}
|
|
136
|
+
__name(buildSpotPriceIndex, "buildSpotPriceIndex");
|
|
150
137
|
function toLighterAccountType(accountTradingMode) {
|
|
151
138
|
return accountTradingMode === 1 ? LighterAccountType.UNIFIED : LighterAccountType.CLASSIC;
|
|
152
139
|
}
|
|
153
140
|
__name(toLighterAccountType, "toLighterAccountType");
|
|
154
|
-
function
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
141
|
+
function toLighterBalance(figures) {
|
|
142
|
+
const spotEquity = figures.equity.spot;
|
|
143
|
+
const perpetualsEquity = figures.equity.perpetuals;
|
|
144
|
+
const tradingEquity = sumOf([
|
|
145
|
+
perpetualsEquity,
|
|
146
|
+
spotEquity
|
|
147
|
+
]);
|
|
148
|
+
const shared = {
|
|
149
|
+
// Public pools, staking and credited LIT are the terms still missing from this sum.
|
|
150
|
+
totalEquity: usdOrNull(tradingEquity),
|
|
151
|
+
withdrawableBalance: usdOrNull(toDecimal(figures.availableBalance)),
|
|
152
|
+
availableMargin: usdOrNull(toDecimal(figures.availableBalance)),
|
|
153
|
+
// Lighter margins every position out of ONE cross pool, so the rows below are holdings inside
|
|
154
|
+
// that pool rather than budgets that could fund each other — only the scalars are spendable.
|
|
155
|
+
poolsShared: true,
|
|
156
|
+
// The rows outlive the scalars: an unpriceable holding nulls `spotEquity`, `tradingEquity` and
|
|
157
|
+
// `totalEquity` above, and still lists here in its own units, because a row needs no price.
|
|
158
|
+
perCollateral: figures.perCollateral,
|
|
159
|
+
timestamp: figures.timestamp,
|
|
160
|
+
tradingEquity: usdOrNull(tradingEquity),
|
|
161
|
+
perpetualsEquity: usdOrNull(perpetualsEquity),
|
|
162
|
+
spotEquity: usdOrNull(spotEquity),
|
|
163
|
+
// Public pool shares have no published net asset value, and staking has no field at all.
|
|
164
|
+
publicPoolsEquity: null,
|
|
165
|
+
stakingEquity: null,
|
|
166
|
+
creditedInLit: null,
|
|
167
|
+
unrealizedPnl: figures.unrealizedPnl,
|
|
168
|
+
crossLeverage: figures.crossLeverage,
|
|
169
|
+
maintenanceMargin: figures.maintenanceMargin,
|
|
170
|
+
crossMarginUsage: figures.crossMarginUsage,
|
|
171
|
+
crossMarginRatio: figures.crossMarginRatio
|
|
172
|
+
};
|
|
173
|
+
switch (figures.accountMode) {
|
|
174
|
+
case "lighter:classic":
|
|
175
|
+
return {
|
|
176
|
+
accountMode: "lighter:classic",
|
|
177
|
+
...shared
|
|
178
|
+
};
|
|
179
|
+
case "lighter:unified":
|
|
180
|
+
return {
|
|
181
|
+
accountMode: "lighter:unified",
|
|
182
|
+
...shared,
|
|
183
|
+
// Unified mode's portfolio margin figure appears in neither `/account` nor `user_stats`.
|
|
184
|
+
portfolioMargin: null
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
__name(toLighterBalance, "toLighterBalance");
|
|
189
|
+
function toEquitySplit(assets, priceBySymbol) {
|
|
190
|
+
let perpetuals = new BigNumber(0);
|
|
191
|
+
let spot = new BigNumber(0);
|
|
192
|
+
for (const asset of assets) {
|
|
193
|
+
if (asset.symbol === QUOTE_ASSET) {
|
|
194
|
+
perpetuals = sumOf([
|
|
195
|
+
perpetuals,
|
|
196
|
+
toDecimal(asset.margin_balance)
|
|
197
|
+
]);
|
|
198
|
+
}
|
|
199
|
+
const balance = toDecimal(asset.balance);
|
|
200
|
+
if (balance === null) {
|
|
201
|
+
spot = null;
|
|
173
202
|
continue;
|
|
174
203
|
}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
}
|
|
204
|
+
if (balance.isZero()) {
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
207
|
+
const price = priceBySymbol.get(asset.symbol);
|
|
208
|
+
if (price === void 0) {
|
|
209
|
+
spot = null;
|
|
210
|
+
continue;
|
|
211
|
+
}
|
|
212
|
+
spot = sumOf([
|
|
213
|
+
spot,
|
|
214
|
+
balance.times(price)
|
|
215
|
+
]);
|
|
183
216
|
}
|
|
184
|
-
return
|
|
217
|
+
return {
|
|
218
|
+
perpetuals,
|
|
219
|
+
spot
|
|
220
|
+
};
|
|
185
221
|
}
|
|
186
|
-
__name(
|
|
187
|
-
function
|
|
188
|
-
const
|
|
189
|
-
const
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
maximumRatio = BigNumber.max(maximumRatio, maintenanceRatio(positionRisk.maintenance, positionRisk.equity));
|
|
222
|
+
__name(toEquitySplit, "toEquitySplit");
|
|
223
|
+
function toCollateralRows(assets, availableBalance) {
|
|
224
|
+
const rows = [];
|
|
225
|
+
for (const asset of assets) {
|
|
226
|
+
const held = heldAmount(asset);
|
|
227
|
+
if (held === null || held.isZero()) {
|
|
228
|
+
continue;
|
|
194
229
|
}
|
|
230
|
+
rows.push(toCollateralRow(asset.symbol, held, availableBalance));
|
|
231
|
+
}
|
|
232
|
+
rows.sort(byAssetName);
|
|
233
|
+
return rows;
|
|
234
|
+
}
|
|
235
|
+
__name(toCollateralRows, "toCollateralRows");
|
|
236
|
+
function heldAmount(asset) {
|
|
237
|
+
return sumOf([
|
|
238
|
+
toDecimal(asset.balance),
|
|
239
|
+
toDecimal(asset.margin_balance)
|
|
240
|
+
]);
|
|
241
|
+
}
|
|
242
|
+
__name(heldAmount, "heldAmount");
|
|
243
|
+
function toCollateralRow(asset, held, availableBalance) {
|
|
244
|
+
if (asset !== QUOTE_ASSET) {
|
|
245
|
+
return {
|
|
246
|
+
asset,
|
|
247
|
+
equity: held.toFixed(),
|
|
248
|
+
availableMargin: null,
|
|
249
|
+
withdrawable: null
|
|
250
|
+
};
|
|
195
251
|
}
|
|
196
|
-
|
|
252
|
+
const usable = usdOrNull(toDecimal(availableBalance));
|
|
253
|
+
return {
|
|
254
|
+
asset,
|
|
255
|
+
equity: held.toFixed(),
|
|
256
|
+
availableMargin: usable,
|
|
257
|
+
withdrawable: usable
|
|
258
|
+
};
|
|
197
259
|
}
|
|
198
|
-
__name(
|
|
199
|
-
function
|
|
200
|
-
if (
|
|
201
|
-
return
|
|
260
|
+
__name(toCollateralRow, "toCollateralRow");
|
|
261
|
+
function byAssetName(left, right) {
|
|
262
|
+
if (left.asset < right.asset) {
|
|
263
|
+
return -1;
|
|
202
264
|
}
|
|
203
|
-
|
|
265
|
+
if (left.asset > right.asset) {
|
|
266
|
+
return 1;
|
|
267
|
+
}
|
|
268
|
+
return 0;
|
|
204
269
|
}
|
|
205
|
-
__name(
|
|
206
|
-
function
|
|
207
|
-
|
|
270
|
+
__name(byAssetName, "byAssetName");
|
|
271
|
+
function sumUnrealizedPnl(positions) {
|
|
272
|
+
return sumOf(Array.from(positions, (position) => toDecimal(position.unrealized_pnl)));
|
|
273
|
+
}
|
|
274
|
+
__name(sumUnrealizedPnl, "sumUnrealizedPnl");
|
|
275
|
+
function toPositionRisks(positions, perpByMarketId) {
|
|
276
|
+
const risks = [];
|
|
208
277
|
for (const position of positions) {
|
|
209
|
-
if (
|
|
210
|
-
|
|
278
|
+
if (toDecimalOrZero(position.position).isZero()) {
|
|
279
|
+
continue;
|
|
280
|
+
}
|
|
281
|
+
const positionValue = toDecimal(position.position_value);
|
|
282
|
+
const notional = positionValue === null ? null : positionValue.abs();
|
|
283
|
+
const market = perpByMarketId.get(position.market_id);
|
|
284
|
+
const maintenanceFraction = market === void 0 ? null : toDecimal(market.maintenance_margin_fraction);
|
|
285
|
+
risks.push({
|
|
286
|
+
marginMode: position.margin_mode === 1 ? "isolated" : "cross",
|
|
287
|
+
notional,
|
|
288
|
+
maintenance: notional === null || maintenanceFraction === null ? null : notional.times(maintenanceFraction).div(MARGIN_FRACTION_SCALE)
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
return risks;
|
|
292
|
+
}
|
|
293
|
+
__name(toPositionRisks, "toPositionRisks");
|
|
294
|
+
function sumMaintenance(risks, marginMode) {
|
|
295
|
+
return sumOf(risks.filter((risk) => risk.marginMode === marginMode).map((risk) => risk.maintenance));
|
|
296
|
+
}
|
|
297
|
+
__name(sumMaintenance, "sumMaintenance");
|
|
298
|
+
function sumNotional(risks, marginMode) {
|
|
299
|
+
return sumOf(risks.filter((risk) => risk.marginMode === marginMode).map((risk) => risk.notional));
|
|
300
|
+
}
|
|
301
|
+
__name(sumNotional, "sumNotional");
|
|
302
|
+
function sumOf(values) {
|
|
303
|
+
let total = new BigNumber(0);
|
|
304
|
+
for (const value of values) {
|
|
305
|
+
if (value === null) {
|
|
306
|
+
return null;
|
|
211
307
|
}
|
|
308
|
+
total = total.plus(value);
|
|
212
309
|
}
|
|
213
310
|
return total;
|
|
214
311
|
}
|
|
215
|
-
__name(
|
|
312
|
+
__name(sumOf, "sumOf");
|
|
313
|
+
function fractionOf(part, base) {
|
|
314
|
+
if (part === null || base === null) {
|
|
315
|
+
return null;
|
|
316
|
+
}
|
|
317
|
+
if (base.isGreaterThan(0)) {
|
|
318
|
+
return fraction(part.div(base));
|
|
319
|
+
}
|
|
320
|
+
return part.isZero() ? fraction(part) : null;
|
|
321
|
+
}
|
|
322
|
+
__name(fractionOf, "fractionOf");
|
|
323
|
+
function fractionOfPercent(percent) {
|
|
324
|
+
if (percent === null) {
|
|
325
|
+
return null;
|
|
326
|
+
}
|
|
327
|
+
return fraction(percent.div(PERCENT_SCALE));
|
|
328
|
+
}
|
|
329
|
+
__name(fractionOfPercent, "fractionOfPercent");
|
|
330
|
+
function multipleOf(part, base) {
|
|
331
|
+
if (part === null || base === null) {
|
|
332
|
+
return null;
|
|
333
|
+
}
|
|
334
|
+
if (base.isGreaterThan(0)) {
|
|
335
|
+
return rate(part.div(base));
|
|
336
|
+
}
|
|
337
|
+
return part.isZero() ? rate(part) : null;
|
|
338
|
+
}
|
|
339
|
+
__name(multipleOf, "multipleOf");
|
|
340
|
+
function rate(value) {
|
|
341
|
+
if (value === null) {
|
|
342
|
+
return null;
|
|
343
|
+
}
|
|
344
|
+
return value.toFixed(RATE_DECIMALS, BigNumber.ROUND_HALF_UP);
|
|
345
|
+
}
|
|
346
|
+
__name(rate, "rate");
|
|
347
|
+
function fraction(value) {
|
|
348
|
+
return value.toFixed(FRACTION_DECIMALS, BigNumber.ROUND_HALF_UP);
|
|
349
|
+
}
|
|
350
|
+
__name(fraction, "fraction");
|
|
351
|
+
function usd(value) {
|
|
352
|
+
return value.toFixed(USD_DECIMALS, BigNumber.ROUND_DOWN);
|
|
353
|
+
}
|
|
354
|
+
__name(usd, "usd");
|
|
355
|
+
function usdOrNull(value) {
|
|
356
|
+
if (value === null) {
|
|
357
|
+
return null;
|
|
358
|
+
}
|
|
359
|
+
return usd(value);
|
|
360
|
+
}
|
|
361
|
+
__name(usdOrNull, "usdOrNull");
|
|
362
|
+
function asMarginRequirement(value) {
|
|
363
|
+
if (value === null) {
|
|
364
|
+
return null;
|
|
365
|
+
}
|
|
366
|
+
return new BigNumber(value.toFixed(USD_DECIMALS, BigNumber.ROUND_HALF_UP));
|
|
367
|
+
}
|
|
368
|
+
__name(asMarginRequirement, "asMarginRequirement");
|
|
369
|
+
const DECIMAL_PATTERN = /^[+-]?(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?$/;
|
|
370
|
+
function toDecimal(value) {
|
|
371
|
+
if (typeof value === "number") {
|
|
372
|
+
return Number.isFinite(value) ? new BigNumber(value) : null;
|
|
373
|
+
}
|
|
374
|
+
if (typeof value !== "string" || !DECIMAL_PATTERN.test(value)) {
|
|
375
|
+
return null;
|
|
376
|
+
}
|
|
377
|
+
return new BigNumber(value);
|
|
378
|
+
}
|
|
379
|
+
__name(toDecimal, "toDecimal");
|
|
380
|
+
function toDecimalOrZero(value) {
|
|
381
|
+
return toDecimal(value) ?? new BigNumber(0);
|
|
382
|
+
}
|
|
383
|
+
__name(toDecimalOrZero, "toDecimalOrZero");
|
|
384
|
+
function signed(value) {
|
|
385
|
+
if (value === null) {
|
|
386
|
+
return null;
|
|
387
|
+
}
|
|
388
|
+
const fixed = usd(value);
|
|
389
|
+
if (new BigNumber(fixed).isZero()) {
|
|
390
|
+
return "+0";
|
|
391
|
+
}
|
|
392
|
+
return value.isNegative() ? fixed : `+${fixed}`;
|
|
393
|
+
}
|
|
394
|
+
__name(signed, "signed");
|
|
216
395
|
|
|
217
|
-
export {
|
|
396
|
+
export { buildSpotPriceIndex, leverageFromImf, mapLiveBalance, mapMarketDefaultAssetInfo, mapPositions, mapRestBalance, toLighterAccountType };
|