@pear-protocol/exchanges-sdk 0.6.6 → 0.7.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.
Files changed (41) hide show
  1. package/README.md +105 -25
  2. package/dist/client/bybit/rest.js +8 -1
  3. package/dist/client/hyperliquid/rest.js +21 -1
  4. package/dist/client/lighter/rest.js +6 -12
  5. package/dist/client/okx/rest.js +5 -1
  6. package/dist/helper/lighter/helper.js +6 -2
  7. package/dist/index.d.ts +1112 -74
  8. package/dist/sdk.js +9 -2
  9. package/dist/tracker/balance-core.js +89 -0
  10. package/dist/tracker/balance.js +25 -0
  11. package/dist/tracker/basket-size.js +194 -0
  12. package/dist/tracker/binance/balance.js +11 -0
  13. package/dist/tracker/binance/mapper.js +87 -42
  14. package/dist/tracker/binance/tracker.js +29 -14
  15. package/dist/tracker/binance/types.js +0 -6
  16. package/dist/tracker/bybit/balance.js +14 -0
  17. package/dist/tracker/bybit/mapper.js +109 -52
  18. package/dist/tracker/bybit/tracker.js +242 -33
  19. package/dist/tracker/bybit/types.js +0 -7
  20. package/dist/tracker/hyperliquid/account-mode.js +14 -0
  21. package/dist/tracker/hyperliquid/balance.js +184 -0
  22. package/dist/tracker/hyperliquid/basket-size.js +93 -0
  23. package/dist/tracker/hyperliquid/coin-name.js +18 -0
  24. package/dist/tracker/hyperliquid/collateral.js +48 -0
  25. package/dist/tracker/hyperliquid/decimal.js +28 -0
  26. package/dist/tracker/hyperliquid/mapper.js +399 -176
  27. package/dist/tracker/hyperliquid/spot-pricing.js +106 -0
  28. package/dist/tracker/hyperliquid/tracker.js +237 -78
  29. package/dist/tracker/hyperliquid/types.js +1 -7
  30. package/dist/tracker/index.js +9 -7
  31. package/dist/tracker/lighter/balance.js +87 -0
  32. package/dist/tracker/lighter/basket-size.js +74 -0
  33. package/dist/tracker/lighter/mapper.js +324 -145
  34. package/dist/tracker/lighter/tracker.js +228 -117
  35. package/dist/tracker/lighter/types.js +1 -7
  36. package/dist/tracker/okx/balance.js +17 -0
  37. package/dist/tracker/okx/mapper.js +156 -58
  38. package/dist/tracker/okx/tracker.js +228 -29
  39. package/dist/tracker/okx/types.js +0 -8
  40. package/dist/tracker/types.js +0 -24
  41. package/package.json +7 -9
@@ -0,0 +1,87 @@
1
+ import { z } from 'zod';
2
+ import { DecimalString, SignedDecimalString, AccountBalanceCore } from '../balance-core';
3
+
4
+ const lighterShared = {
5
+ /** Perpetuals + Spot. Null whenever either half is — one unknown term makes the sum unknown. */
6
+ tradingEquity: DecimalString.nullable(),
7
+ /**
8
+ * Collateral posted against perps, which is the quote asset's `margin_balance` alone.
9
+ *
10
+ * Null when the venue sends that one field unreadably or omits it: it is not a term of this
11
+ * figure, it IS the figure, so there is nothing left to report and a zero would say the account
12
+ * has posted no collateral at all.
13
+ */
14
+ perpetualsEquity: DecimalString.nullable(),
15
+ /**
16
+ * Spot holdings valued in USD.
17
+ *
18
+ * Null when a NON-ZERO holding cannot be priced — no spot book, an inactive book, or a book that
19
+ * has never traded. Lighter's spot books publish neither a mark nor an index price, so the only
20
+ * price available is the last trade, and counting an unpriceable holding as zero would report a
21
+ * number the venue never stated.
22
+ */
23
+ spotEquity: DecimalString.nullable(),
24
+ /** Null until a source is found for each — all three are UI rows with no API field. */
25
+ publicPoolsEquity: DecimalString.nullable(),
26
+ stakingEquity: DecimalString.nullable(),
27
+ creditedInLit: DecimalString.nullable(),
28
+ /**
29
+ * Open profit and loss across every position.
30
+ *
31
+ * Null when ANY position's own PnL is unreadable: the missing term could be a profit or a loss
32
+ * of any size, so the rest of the sum is not a smaller version of the answer — `+0` in
33
+ * particular would read as a flat book.
34
+ */
35
+ unrealizedPnl: SignedDecimalString.nullable(),
36
+ /**
37
+ * Cross exposure over cross equity.
38
+ *
39
+ * A MULTIPLE, not a ratio: `0.72` reads 0.72x, and the venue publishes it that way in both
40
+ * scopes. The fraction scale the two fields below carry does not reach it — a multiple is
41
+ * already the same figure on every venue.
42
+ *
43
+ * Null when either side is unreadable, and null when equity is zero against real exposure —
44
+ * that is a division by zero, and calling it `0.00` would report the safest possible account at
45
+ * the exact moment the venue can no longer measure the riskiest.
46
+ */
47
+ crossLeverage: DecimalString.nullable(),
48
+ /**
49
+ * Maintenance margin across both margin modes.
50
+ *
51
+ * Null when the venue's own cross requirement is unreadable, or when any position feeding the
52
+ * isolated half is: a requirement understated by a missing term reads as headroom that is not
53
+ * there. Null on the same terms when a position sits on a market the tracker's market read never
54
+ * listed — the market carries the maintenance fraction that prices it, so without one there is no
55
+ * term to add rather than a term worth zero.
56
+ */
57
+ maintenanceMargin: DecimalString.nullable(),
58
+ /**
59
+ * A FRACTION, not a percentage: `0.0221` is what the venue's own page badges as 2.21%.
60
+ *
61
+ * The venue publishes `margin_usage` in percent points and the mapper divides them down, because
62
+ * every venue in this SDK states a ratio at one scale — a field whose scale depended on the
63
+ * venue behind it could not be compared across two of them, which is the whole defect the model
64
+ * exists to remove. Four decimals carry the venue's two decimals of percent exactly.
65
+ *
66
+ * Verified to exceed 1 on a live account, which reads 115.22% on the venue — never clamp.
67
+ *
68
+ * Null on the same terms as `crossLeverage`: unreadable in, unknown out, and a requirement
69
+ * standing against zero equity is unmeasurable rather than full or empty. The ratio is null on
70
+ * one term more: the live path computes it from the positions, so an unlisted market leaves it
71
+ * unknown wherever it leaves `maintenanceMargin` unknown.
72
+ */
73
+ crossMarginUsage: DecimalString.nullable(),
74
+ crossMarginRatio: DecimalString.nullable()
75
+ };
76
+ const LighterClassicBalance = AccountBalanceCore.extend({
77
+ accountMode: z.literal("lighter:classic"),
78
+ ...lighterShared
79
+ });
80
+ const LighterUnifiedBalance = AccountBalanceCore.extend({
81
+ accountMode: z.literal("lighter:unified"),
82
+ ...lighterShared,
83
+ /** Null — no source in `/account` or `user_stats`. */
84
+ portfolioMargin: DecimalString.nullable()
85
+ });
86
+
87
+ export { LighterClassicBalance, LighterUnifiedBalance };
@@ -0,0 +1,74 @@
1
+ import BigNumber from 'bignumber.js';
2
+ import { QUOTE_ASSET } from './const';
3
+
4
+ var __defProp = Object.defineProperty;
5
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
6
+ const MARGIN_FRACTION_SCALE = 1e4;
7
+ const CROSS_POOL = QUOTE_ASSET;
8
+ const DECIMAL_PATTERN = /^[+-]?(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?$/;
9
+ function toLighterBasketCalculation(legs, context) {
10
+ const capped = [];
11
+ for (const leg of legs) {
12
+ const market = context.perpBySymbol.get(leg.asset);
13
+ if (!market) {
14
+ return {
15
+ budgets: {},
16
+ legs: []
17
+ };
18
+ }
19
+ capped.push(toCappedLeg(leg, market, context.settingsByMarketId.get(String(market.market_id))));
20
+ }
21
+ return {
22
+ // Every leg draws on the same pool, so one entry carries the whole basket's budget.
23
+ budgets: {
24
+ [CROSS_POOL]: context.availableBalance
25
+ },
26
+ legs: capped
27
+ };
28
+ }
29
+ __name(toLighterBasketCalculation, "toLighterBasketCalculation");
30
+ function toCappedLeg(leg, market, currentSetting) {
31
+ return {
32
+ asset: leg.asset,
33
+ pool: CROSS_POOL,
34
+ weight: leg.weight,
35
+ effectiveLeverage: effectiveLeverage(leg.leverage, market, currentSetting),
36
+ marginMode: leg.marginMode,
37
+ maxNotional: null
38
+ };
39
+ }
40
+ __name(toCappedLeg, "toCappedLeg");
41
+ function effectiveLeverage(requested, market, currentSetting) {
42
+ const accountLeverage = currentSetting === void 0 ? defaultAccountLeverage(market) : toDecimal(currentSetting.leverage);
43
+ const granted = BigNumber.min(toDecimal(requested), venueMaxLeverage(market), accountLeverage);
44
+ return granted.isFinite() && granted.isGreaterThan(0) ? granted.toFixed() : "1";
45
+ }
46
+ __name(effectiveLeverage, "effectiveLeverage");
47
+ function venueMaxLeverage(market) {
48
+ return leverageFromMarginFraction(market.min_initial_margin_fraction);
49
+ }
50
+ __name(venueMaxLeverage, "venueMaxLeverage");
51
+ function defaultAccountLeverage(market) {
52
+ return leverageFromMarginFraction(market.default_initial_margin_fraction).integerValue(BigNumber.ROUND_FLOOR);
53
+ }
54
+ __name(defaultAccountLeverage, "defaultAccountLeverage");
55
+ function leverageFromMarginFraction(marginFraction) {
56
+ const fraction = toDecimal(marginFraction);
57
+ if (!fraction.isGreaterThan(0)) {
58
+ return new BigNumber(1);
59
+ }
60
+ return new BigNumber(MARGIN_FRACTION_SCALE).div(fraction);
61
+ }
62
+ __name(leverageFromMarginFraction, "leverageFromMarginFraction");
63
+ function toDecimal(value) {
64
+ if (typeof value === "number") {
65
+ return Number.isFinite(value) ? new BigNumber(value) : new BigNumber(0);
66
+ }
67
+ if (typeof value !== "string" || !DECIMAL_PATTERN.test(value)) {
68
+ return new BigNumber(0);
69
+ }
70
+ return new BigNumber(value);
71
+ }
72
+ __name(toDecimal, "toDecimal");
73
+
74
+ export { toLighterBasketCalculation, venueMaxLeverage };