@gearbox-protocol/sdk 15.1.0-next.6 → 15.1.0-next.7

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 (106) hide show
  1. package/dist/cjs/common-utils/utils/apy/get-single-quota-borrow-rate.js +2 -0
  2. package/dist/cjs/common-utils/utils/creditAccount/calc-health-factor.js +24 -22
  3. package/dist/cjs/common-utils/utils/creditAccount/calc-quota-borrow-rate.js +2 -0
  4. package/dist/cjs/common-utils/utils/creditAccount/get-time-to-liquidation.js +5 -4
  5. package/dist/cjs/common-utils/utils/creditAccount/liquidation-price.js +21 -11
  6. package/dist/cjs/model/index.js +1 -0
  7. package/dist/cjs/model/positions.schema.js +13 -0
  8. package/dist/cjs/preview/preview/CreditAccountState.js +14 -1
  9. package/dist/cjs/preview/preview/buildDelayedPreview.js +16 -6
  10. package/dist/cjs/preview/preview/previewAdjustCreditAccount.js +9 -2
  11. package/dist/cjs/preview/preview/previewOpenCreditAccount.js +11 -3
  12. package/dist/cjs/preview/preview/previewOperation.js +1 -1
  13. package/dist/cjs/sdk/accounts/CreditAccountsServiceV310.js +0 -6
  14. package/dist/cjs/sdk/accounts/credit-account-compressor/CreditAccountCompressor.js +2 -90
  15. package/dist/cjs/sdk/accounts/intents/testing/sdk-mock.js +31 -4
  16. package/dist/cjs/sdk/accounts/intents/utils/adjust-state-to-snapshot.js +18 -0
  17. package/dist/cjs/sdk/accounts/intents/utils/index.js +2 -0
  18. package/dist/cjs/sdk/accounts/liquidations/LiquidationsService.js +0 -3
  19. package/dist/cjs/sdk/index.js +12 -0
  20. package/dist/cjs/sdk/market/oracle/PriceOracleBaseContract.js +10 -3
  21. package/dist/cjs/sdk/positions/PositionsService.js +206 -1
  22. package/dist/cjs/sdk/positions/calcBorrowRate.js +43 -0
  23. package/dist/cjs/sdk/positions/calcHealthFactor.js +44 -0
  24. package/dist/cjs/sdk/positions/calcLiquidationPrice.js +23 -0
  25. package/dist/cjs/sdk/positions/calcLiquidationPriceForTarget.js +30 -0
  26. package/dist/cjs/sdk/positions/calcTimeToLiquidationMs.js +18 -0
  27. package/dist/cjs/sdk/positions/index.js +12 -1
  28. package/dist/cjs/sdk/positions/types.js +31 -0
  29. package/dist/esm/common-utils/utils/apy/get-single-quota-borrow-rate.js +2 -0
  30. package/dist/esm/common-utils/utils/creditAccount/calc-health-factor.js +24 -22
  31. package/dist/esm/common-utils/utils/creditAccount/calc-quota-borrow-rate.js +2 -0
  32. package/dist/esm/common-utils/utils/creditAccount/get-time-to-liquidation.js +5 -4
  33. package/dist/esm/common-utils/utils/creditAccount/liquidation-price.js +21 -11
  34. package/dist/esm/dev/AccountOpener.js +1 -1
  35. package/dist/esm/dev/withdrawalUtils.js +1 -1
  36. package/dist/esm/model/index.js +2 -2
  37. package/dist/esm/model/positions.schema.js +14 -2
  38. package/dist/esm/plugins/adapters/contracts/ERC4626AdapterContract.js +1 -1
  39. package/dist/esm/preview/preview/CreditAccountState.js +14 -1
  40. package/dist/esm/preview/preview/buildDelayedPreview.js +16 -6
  41. package/dist/esm/preview/preview/previewAdjustCreditAccount.js +9 -2
  42. package/dist/esm/preview/preview/previewOpenCreditAccount.js +11 -3
  43. package/dist/esm/preview/preview/previewOperation.js +1 -1
  44. package/dist/esm/preview/simulate/simulatePoolOperation.js +1 -1
  45. package/dist/esm/preview/trace/extractTransfers.js +1 -1
  46. package/dist/esm/sdk/accounts/CreditAccountsServiceV310.js +2 -8
  47. package/dist/esm/sdk/accounts/credit-account-compressor/CreditAccountCompressor.js +2 -90
  48. package/dist/esm/sdk/accounts/intents/testing/sdk-mock.js +31 -4
  49. package/dist/esm/sdk/accounts/intents/utils/adjust-state-to-snapshot.js +17 -0
  50. package/dist/esm/sdk/accounts/intents/utils/index.js +2 -1
  51. package/dist/esm/sdk/accounts/liquidations/LiquidationsService.js +1 -4
  52. package/dist/esm/sdk/accounts/withdrawal-compressor/RedemptionLoggerV310Contract.js +1 -1
  53. package/dist/esm/sdk/accounts/withdrawal-compressor/WithdrawalCompressorV310Contract.js +1 -1
  54. package/dist/esm/sdk/accounts/withdrawal-compressor/WithdrawalCompressorV311Contract.js +1 -1
  55. package/dist/esm/sdk/accounts/withdrawal-compressor/WithdrawalCompressorV313Contract.js +1 -1
  56. package/dist/esm/sdk/base/TokensMeta.js +3 -3
  57. package/dist/esm/sdk/chain/detectNetwork.js +1 -1
  58. package/dist/esm/sdk/core/createAddressProvider.js +1 -1
  59. package/dist/esm/sdk/index.js +7 -1
  60. package/dist/esm/sdk/market/credit/CreditFacadeV310BaseContract.js +1 -1
  61. package/dist/esm/sdk/market/oracle/PriceOracleBaseContract.js +10 -3
  62. package/dist/esm/sdk/market/pool/PoolV310Contract.js +1 -1
  63. package/dist/esm/sdk/market/zapper/IETHZapperContract.js +1 -1
  64. package/dist/esm/sdk/market/zapper/ZapperContract.js +1 -1
  65. package/dist/esm/sdk/pools/PoolService.js +1 -1
  66. package/dist/esm/sdk/positions/PositionsService.js +206 -1
  67. package/dist/esm/sdk/positions/calcBorrowRate.js +42 -0
  68. package/dist/esm/sdk/positions/calcHealthFactor.js +43 -0
  69. package/dist/esm/sdk/positions/calcLiquidationPrice.js +22 -0
  70. package/dist/esm/sdk/positions/calcLiquidationPriceForTarget.js +29 -0
  71. package/dist/esm/sdk/positions/calcTimeToLiquidationMs.js +17 -0
  72. package/dist/esm/sdk/positions/index.js +7 -2
  73. package/dist/esm/sdk/positions/types.js +31 -1
  74. package/dist/esm/sdk/utils/viem/simulateWithPriceUpdates.js +1 -1
  75. package/dist/types/common-utils/utils/apy/get-single-quota-borrow-rate.d.ts +2 -0
  76. package/dist/types/common-utils/utils/creditAccount/calc-health-factor.d.ts +3 -0
  77. package/dist/types/common-utils/utils/creditAccount/calc-quota-borrow-rate.d.ts +2 -0
  78. package/dist/types/common-utils/utils/creditAccount/get-time-to-liquidation.d.ts +3 -0
  79. package/dist/types/common-utils/utils/creditAccount/liquidation-price.d.ts +3 -0
  80. package/dist/types/model/index.d.ts +3 -3
  81. package/dist/types/model/positions.d.ts +84 -1
  82. package/dist/types/model/positions.schema.d.ts +26 -1
  83. package/dist/types/preview/preview/CreditAccountState.d.ts +6 -0
  84. package/dist/types/preview/preview/buildDelayedPreview.d.ts +5 -1
  85. package/dist/types/preview/preview/types.d.ts +4 -2
  86. package/dist/types/sdk/accounts/CreditAccountsServiceV310.d.ts +1 -7
  87. package/dist/types/sdk/accounts/credit-account-compressor/CreditAccountCompressor.d.ts +3 -12
  88. package/dist/types/sdk/accounts/credit-account-compressor/index.d.ts +2 -2
  89. package/dist/types/sdk/accounts/credit-account-compressor/types.d.ts +1 -19
  90. package/dist/types/sdk/accounts/index.d.ts +2 -2
  91. package/dist/types/sdk/accounts/intents/testing/sdk-mock.d.ts +6 -0
  92. package/dist/types/sdk/accounts/intents/utils/adjust-state-to-snapshot.d.ts +13 -0
  93. package/dist/types/sdk/accounts/intents/utils/index.d.ts +2 -1
  94. package/dist/types/sdk/accounts/types.d.ts +1 -12
  95. package/dist/types/sdk/index.d.ts +8 -3
  96. package/dist/types/sdk/market/oracle/PriceOracleBaseContract.d.ts +4 -0
  97. package/dist/types/sdk/market/oracle/types.d.ts +8 -0
  98. package/dist/types/sdk/positions/PositionsService.d.ts +31 -2
  99. package/dist/types/sdk/positions/calcBorrowRate.d.ts +40 -0
  100. package/dist/types/sdk/positions/calcHealthFactor.d.ts +45 -0
  101. package/dist/types/sdk/positions/calcLiquidationPrice.d.ts +12 -0
  102. package/dist/types/sdk/positions/calcLiquidationPriceForTarget.d.ts +43 -0
  103. package/dist/types/sdk/positions/calcTimeToLiquidationMs.d.ts +15 -0
  104. package/dist/types/sdk/positions/index.d.ts +7 -2
  105. package/dist/types/sdk/positions/types.d.ts +58 -1
  106. package/package.json +1 -1
@@ -133,17 +133,24 @@ var PriceOracleBaseContract = class extends require_sdk_base_BaseContract.BaseCo
133
133
  return amount * 10n ** BigInt(this.tokensMeta.decimals(to)) / price;
134
134
  }
135
135
  /**
136
- * {@inheritDoc IPriceOracleContract.safeUsdValue}
136
+ * {@inheritDoc IPriceOracleContract.safeConvertToUSD}
137
137
  **/
138
- safeUsdValue(token, amount) {
138
+ safeConvertToUSD(token, amount) {
139
139
  try {
140
- return require_sdk_market_math.usdToNumber(this.convertToUSD(token, amount));
140
+ return this.convertToUSD(token, amount);
141
141
  } catch (e) {
142
142
  this.logger?.debug(`cannot price ${this.labelAddress(token)}: ${e}`);
143
143
  return null;
144
144
  }
145
145
  }
146
146
  /**
147
+ * {@inheritDoc IPriceOracleContract.safeUsdValue}
148
+ **/
149
+ safeUsdValue(token, amount) {
150
+ const usd = this.safeConvertToUSD(token, amount);
151
+ return usd === null ? null : require_sdk_market_math.usdToNumber(usd);
152
+ }
153
+ /**
147
154
  * {@inheritDoc IPriceOracleContract.toAmount}
148
155
  **/
149
156
  toAmount = (token, value) => {
@@ -1,9 +1,21 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_sdk_utils_AddressMap = require("../utils/AddressMap.js");
3
+ require("../constants/math.js");
4
+ require("../constants/index.js");
5
+ require("../utils/index.js");
2
6
  const require_sdk_base_SDKConstruct = require("../base/SDKConstruct.js");
3
7
  require("../base/index.js");
8
+ const require_sdk_market_math = require("../market/math.js");
9
+ const require_sdk_market_credit_dominantCollateral = require("../market/credit/dominantCollateral.js");
4
10
  const require_model_filters = require("../../model/filters.js");
5
11
  const require_model_positions = require("../../model/positions.js");
6
12
  require("../../model/index.js");
13
+ require("../market/index.js");
14
+ const require_sdk_positions_calcBorrowRate = require("./calcBorrowRate.js");
15
+ const require_sdk_positions_calcHealthFactor = require("./calcHealthFactor.js");
16
+ const require_sdk_positions_calcLiquidationPrice = require("./calcLiquidationPrice.js");
17
+ const require_sdk_positions_calcTimeToLiquidationMs = require("./calcTimeToLiquidationMs.js");
18
+ const require_sdk_positions_types = require("./types.js");
7
19
  //#region src/sdk/positions/PositionsService.ts
8
20
  /**
9
21
  * The `positions` read model of one chain: everything a wallet holds in the
@@ -28,7 +40,7 @@ var PositionsService = class extends require_sdk_base_SDKConstruct.SDKConstruct
28
40
  wallet,
29
41
  blockNumber
30
42
  }) : Promise.resolve([]),
31
- wanted("strategy") ? this.sdk.accounts.listPositions({
43
+ wanted("strategy") ? this.listStrategyPositions({
32
44
  owner: wallet,
33
45
  includeZeroDebt: !require_model_filters.isFilterSet(isZeroDebt) || isZeroDebt,
34
46
  blockNumber
@@ -44,6 +56,199 @@ var PositionsService = class extends require_sdk_base_SDKConstruct.SDKConstruct
44
56
  ...liquidation
45
57
  ].filter((row) => require_model_positions.matchesPositionFilter(row, filter));
46
58
  }
59
+ /**
60
+ * Describes all credit accounts of a wallet as strategy positions.
61
+ *
62
+ * @param props - {@link ListStrategyPositionsProps}
63
+ **/
64
+ async listStrategyPositions(props) {
65
+ const { owner, includeZeroDebt, blockNumber } = props;
66
+ const describable = (await this.sdk.accounts.getBorrowerCreditAccounts(owner, { includeZeroDebt }, blockNumber)).filter((ca) => {
67
+ if (!ca.success) this.logger?.warn(`cannot describe position of ${this.labelAddress(ca.creditAccount)}: collateral computation failed`);
68
+ return ca.success;
69
+ });
70
+ const withdrawals = await Promise.all(describable.map((ca) => this.#accountWithdrawals(ca, blockNumber)));
71
+ return describable.map((ca, i) => this.#toStrategyPosition(ca, withdrawals[i] ?? new require_sdk_utils_AddressMap.AddressMap()));
72
+ }
73
+ /**
74
+ * Health factor of an account state, in basis points (`10000` = 1.0).
75
+ **/
76
+ healthFactor(snapshot) {
77
+ const data = this.#marketData(snapshot);
78
+ return require_sdk_positions_calcHealthFactor.calcHealthFactor({
79
+ snapshot,
80
+ underlying: data.underlying,
81
+ decimals: data.decimals,
82
+ prices: data.prices,
83
+ liquidationThresholds: data.liquidationThresholds,
84
+ activeQuotas: data.activeQuotas
85
+ });
86
+ }
87
+ /**
88
+ * Cost of an account state's debt, broken down into the pool's base rate
89
+ * and per-token quota rates.
90
+ **/
91
+ borrowRate(snapshot) {
92
+ const data = this.#marketData(snapshot);
93
+ return require_sdk_positions_calcBorrowRate.calcBorrowRate({
94
+ snapshot,
95
+ baseInterestRate: data.baseInterestRate,
96
+ feeInterest: data.feeInterest,
97
+ quotaRates: data.quotaRates
98
+ });
99
+ }
100
+ /**
101
+ * Estimated milliseconds until the account's health factor decays to
102
+ * `10000` under its current borrow rate, or `null` when the debt carries
103
+ * no rate (or the account is already liquidatable).
104
+ **/
105
+ timeToLiquidation(snapshot) {
106
+ const data = this.#marketData(snapshot);
107
+ return require_sdk_positions_calcTimeToLiquidationMs.calcTimeToLiquidationMs(require_sdk_positions_calcHealthFactor.calcHealthFactor({
108
+ snapshot,
109
+ underlying: data.underlying,
110
+ decimals: data.decimals,
111
+ prices: data.prices,
112
+ liquidationThresholds: data.liquidationThresholds,
113
+ activeQuotas: data.activeQuotas
114
+ }), BigInt(require_sdk_positions_calcBorrowRate.calcBorrowRate({
115
+ snapshot,
116
+ baseInterestRate: data.baseInterestRate,
117
+ feeInterest: data.feeInterest,
118
+ quotaRates: data.quotaRates
119
+ }).totalOnDebt));
120
+ }
121
+ /**
122
+ * Price of the single non-underlying collateral at which the account
123
+ * becomes liquidatable, or `null` when the account holds zero or several
124
+ * non-underlying assets.
125
+ **/
126
+ liquidationPrice(snapshot) {
127
+ const data = this.#marketData(snapshot);
128
+ return require_sdk_positions_calcLiquidationPrice.calcLiquidationPrice({
129
+ snapshot,
130
+ underlying: data.underlying,
131
+ decimals: data.decimals,
132
+ liquidationThresholds: data.liquidationThresholds
133
+ });
134
+ }
135
+ /**
136
+ * Builds one strategy position from an account snapshot.
137
+ *
138
+ * @param withdrawals - Delayed withdrawals of the account, keyed by the
139
+ * phantom token that represents them on it.
140
+ **/
141
+ #toStrategyPosition(ca, withdrawals) {
142
+ const suite = this.sdk.marketRegister.findCreditManager(ca.creditManager);
143
+ const { market } = suite;
144
+ const { priceOracle } = market;
145
+ const { pool } = market.pool;
146
+ const token = this.sdk.tokensMeta.mustGetToken(market.unwrappedUnderlying);
147
+ const totalDebtValue = ca.debt + ca.accruedInterest + ca.accruedFees;
148
+ const collateral = require_sdk_market_credit_dominantCollateral.dominantCollateral(ca, market);
149
+ const snapshot = require_sdk_positions_types.accountSnapshotFromCreditAccountData(ca);
150
+ const borrowRate = this.borrowRate(snapshot);
151
+ const timeToLiquidation = this.timeToLiquidation(snapshot);
152
+ const liquidationPrice = this.liquidationPrice(snapshot);
153
+ return {
154
+ kind: "strategy",
155
+ chainId: this.sdk.chainId,
156
+ creditManager: ca.creditManager,
157
+ creditAccount: ca.creditAccount,
158
+ name: collateral ? suite.strategyName(collateral) : token.symbol,
159
+ targetCollateral: collateral ? this.sdk.tokensMeta.mustGetToken(collateral) : null,
160
+ leverage: require_sdk_market_math.calcPositionLeverage(ca.totalValue, totalDebtValue),
161
+ borrowApy: require_sdk_market_math.calcBorrowApy(pool.baseInterestRate, suite.creditManager.feeInterest),
162
+ totalDebt: {
163
+ token,
164
+ value: totalDebtValue,
165
+ valueUsd: require_sdk_market_math.usdToNumber(ca.totalDebtUSD)
166
+ },
167
+ totalValue: {
168
+ token,
169
+ value: ca.totalValue,
170
+ valueUsd: require_sdk_market_math.usdToNumber(ca.totalValueUSD)
171
+ },
172
+ healthFactor: require_sdk_market_math.healthFactorBps(ca.healthFactor),
173
+ borrowRate,
174
+ timeToLiquidation,
175
+ liquidationPrice,
176
+ collaterals: ca.tokens.flatMap((t) => {
177
+ if ((t.mask & ca.enabledTokensMask) === 0n || t.balance <= 10n) return [];
178
+ return [{
179
+ collateral: priceOracle.toTokenAmount(t.token, t.balance),
180
+ quota: priceOracle.toTokenAmount(market.underlying, t.quota),
181
+ withdrawals: withdrawals.get(t.token) ?? []
182
+ }];
183
+ })
184
+ };
185
+ }
186
+ /**
187
+ * Delayed withdrawals of one account, keyed by the phantom token that
188
+ * represents them on it, so that each collateral row can pick up its own.
189
+ **/
190
+ async #accountWithdrawals(ca, blockNumber) {
191
+ const compressor = this.sdk.withdrawalCompressor;
192
+ const byPhantomToken = new require_sdk_utils_AddressMap.AddressMap(void 0, "accountWithdrawals");
193
+ const holdsPhantomToken = ca.tokens.some((t) => t.balance > 10n && compressor?.getWithdrawalSourceToken(t.token) !== void 0);
194
+ if (!compressor || !holdsPhantomToken) return byPhantomToken;
195
+ const { priceOracle } = this.sdk.marketRegister.findByCreditManager(ca.creditManager);
196
+ const { claimable, pending } = await compressor.getCurrentWithdrawals(ca.creditAccount, blockNumber);
197
+ const add = (w, outputs, claimableAt) => {
198
+ const assets = outputs.map((o) => ({
199
+ isDelayed: true,
200
+ ...priceOracle.toTokenAmount(o.token, o.amount),
201
+ redeemer: w.redeemer,
202
+ claimableAt: claimableAt === void 0 ? void 0 : Number(claimableAt)
203
+ }));
204
+ byPhantomToken.upsert(w.withdrawalPhantomToken, [...byPhantomToken.get(w.withdrawalPhantomToken) ?? [], ...assets]);
205
+ };
206
+ for (const w of claimable) add(w, w.outputs);
207
+ for (const w of pending) add(w, w.expectedOutputs, w.claimableAt);
208
+ return byPhantomToken;
209
+ }
210
+ /**
211
+ * Collects decimals, prices and thresholds for the snapshot's tokens plus
212
+ * the market underlying, even when the account holds no underlying balance.
213
+ **/
214
+ #marketData(snapshot) {
215
+ const market = this.sdk.marketRegister.findByCreditManager(snapshot.creditManager);
216
+ const cm = this.sdk.marketRegister.findCreditManager(snapshot.creditManager).creditManager;
217
+ const { priceOracle } = market;
218
+ const underlying = market.pool.underlying;
219
+ const { pqk, pool } = market.pool;
220
+ const tokens = [underlying];
221
+ for (const a of snapshot.assets) tokens.push(a.token);
222
+ for (const q of snapshot.quotas) tokens.push(q.token);
223
+ const decimals = {};
224
+ const prices = {};
225
+ const liquidationThresholds = {};
226
+ const activeQuotas = {};
227
+ const quotaRates = {};
228
+ for (const token of tokens) {
229
+ const meta = this.sdk.tokensMeta.get(token);
230
+ if (meta) decimals[token] = meta.decimals;
231
+ try {
232
+ prices[token] = priceOracle.mainPrice(token);
233
+ } catch {}
234
+ const lt = cm.liquidationThresholds.get(token);
235
+ if (lt !== void 0) liquidationThresholds[token] = lt;
236
+ if (pqk.hasActiveQuota(token)) {
237
+ activeQuotas[token] = true;
238
+ quotaRates[token] = pqk.quotaRate(token);
239
+ }
240
+ }
241
+ return {
242
+ underlying,
243
+ decimals,
244
+ prices,
245
+ liquidationThresholds,
246
+ activeQuotas,
247
+ quotaRates,
248
+ baseInterestRate: pool.baseInterestRate,
249
+ feeInterest: cm.feeInterest
250
+ };
251
+ }
47
252
  };
48
253
  //#endregion
49
254
  exports.PositionsService = PositionsService;
@@ -0,0 +1,43 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_sdk_utils_AddressMap = require("../utils/AddressMap.js");
3
+ const require_sdk_constants_math = require("../constants/math.js");
4
+ const require_sdk_market_math = require("../market/math.js");
5
+ //#region src/sdk/positions/calcBorrowRate.ts
6
+ /**
7
+ * Cost of an account state's debt, broken down into the pool's base rate and
8
+ * per-token quota rates.
9
+ *
10
+ * The base rate is the market's current borrow APY (the pool's base rate plus
11
+ * the credit manager's interest fee) — the same value `borrowApy` reports on
12
+ * a position; it is not recomputed for the projected pool liquidity. Quota
13
+ * contributions are `quotaBalance * quotaRate` with the interest fee on top,
14
+ * normalized against the total value (`total`, `quotas`) and against the
15
+ * debt (`totalOnDebt`, the rate the debt itself grows at). Formulas are in
16
+ * parity with the frontend's `BorrowRateUtils`.
17
+ **/
18
+ function calcBorrowRate(props) {
19
+ const { snapshot, baseInterestRate, feeInterest, quotaRates } = props;
20
+ const { quotas, totalDebt, totalValue } = snapshot;
21
+ const rates = new require_sdk_utils_AddressMap.AddressMap(Object.entries(quotaRates));
22
+ const base = require_sdk_market_math.calcBorrowApy(baseInterestRate, feeInterest);
23
+ const fee = require_sdk_constants_math.PERCENTAGE_FACTOR + BigInt(feeInterest);
24
+ let quotaRateSum = 0n;
25
+ const perQuota = {};
26
+ for (const q of quotas) {
27
+ if (q.balance <= 10n) continue;
28
+ const rate = rates.get(q.token);
29
+ const rateBalance = rate === void 0 ? 0n : q.balance * BigInt(rate);
30
+ quotaRateSum += rateBalance;
31
+ const withFee = rateBalance * fee / require_sdk_constants_math.PERCENTAGE_FACTOR;
32
+ perQuota[q.token] = totalValue > 0n ? Number(withFee / totalValue) : 0;
33
+ }
34
+ const quotaRateSumWithFee = quotaRateSum * fee / require_sdk_constants_math.PERCENTAGE_FACTOR;
35
+ return {
36
+ total: totalValue > 0n ? Number(totalDebt * BigInt(base) / totalValue) + Number(quotaRateSumWithFee / totalValue) : 0,
37
+ totalOnDebt: totalDebt > 0n ? base + Number(quotaRateSumWithFee / totalDebt) : 0,
38
+ base,
39
+ quotas: perQuota
40
+ };
41
+ }
42
+ //#endregion
43
+ exports.calcBorrowRate = calcBorrowRate;
@@ -0,0 +1,44 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_sdk_utils_AddressMap = require("../utils/AddressMap.js");
3
+ const require_sdk_utils_bigint_math = require("../utils/bigint-math.js");
4
+ const require_sdk_constants_math = require("../constants/math.js");
5
+ let viem = require("viem");
6
+ //#region src/sdk/positions/calcHealthFactor.ts
7
+ /**
8
+ * Health factor of an account state, in basis points (`10000` = 1.0).
9
+ *
10
+ * Collateral is valued under liquidation thresholds, with quoted tokens
11
+ * capped by their quota, and compared against the debt's value. An account
12
+ * with no debt reports `65535` (`MAX_UINT16`), the contract's own sentinel
13
+ * scaled down. Formulas are in parity with the legacy `calcHealthFactor`.
14
+ * Tokens with no price in {@link CalcHealthFactorProps.prices} contribute
15
+ * nothing.
16
+ **/
17
+ function calcHealthFactor(props) {
18
+ const { snapshot, underlying, decimals, prices, liquidationThresholds, activeQuotas } = props;
19
+ if (snapshot.totalDebt === 0n) return Number(require_sdk_constants_math.MAX_UINT16);
20
+ const decimalsByToken = new require_sdk_utils_AddressMap.AddressMap(Object.entries(decimals));
21
+ const pricesByToken = new require_sdk_utils_AddressMap.AddressMap(Object.entries(prices));
22
+ const lts = new require_sdk_utils_AddressMap.AddressMap(Object.entries(liquidationThresholds));
23
+ const active = new require_sdk_utils_AddressMap.AddressMap(Object.entries(activeQuotas));
24
+ const convertToUSD = (token, amount) => {
25
+ const price = pricesByToken.get(token);
26
+ if (price === void 0) return null;
27
+ const scale = 10n ** BigInt(decimalsByToken.get(token) ?? 18);
28
+ return amount * price / scale;
29
+ };
30
+ const assetMoney = snapshot.assets.reduce((acc, { token, balance }) => {
31
+ if (balance <= 10n) return acc;
32
+ const lt = BigInt(lts.get(token) ?? 0);
33
+ const tokenLtWeighted = (convertToUSD(token, balance) ?? 0n) * lt;
34
+ const quota = snapshot.quotas.find((q) => (0, viem.isAddressEqual)(q.token, token));
35
+ const quotaBalance = quota && (active.get(token) ?? false) ? quota.balance : 0n;
36
+ const quotaWeighted = (convertToUSD(underlying, quotaBalance) ?? 0n) * require_sdk_constants_math.PERCENTAGE_FACTOR;
37
+ return acc + (quota ? require_sdk_utils_bigint_math.BigIntMath.min(quotaWeighted, tokenLtWeighted) : tokenLtWeighted);
38
+ }, 0n);
39
+ const borrowedMoney = convertToUSD(underlying, snapshot.totalDebt) ?? 0n;
40
+ const hf = borrowedMoney > 0n ? assetMoney / borrowedMoney : 0n;
41
+ return Number(hf);
42
+ }
43
+ //#endregion
44
+ exports.calcHealthFactor = calcHealthFactor;
@@ -0,0 +1,23 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ require("../constants/math.js");
3
+ const require_sdk_positions_calcLiquidationPriceForTarget = require("./calcLiquidationPriceForTarget.js");
4
+ let viem = require("viem");
5
+ //#region src/sdk/positions/calcLiquidationPrice.ts
6
+ /**
7
+ * Liquidation price of an account state's target collateral, in the oracle's
8
+ * 8-decimal (`PRICE_DECIMALS`) fixed point.
9
+ *
10
+ * As the frontend does, a liquidation price only exists when the account
11
+ * holds exactly one non-dust non-underlying asset; otherwise `null`.
12
+ **/
13
+ function calcLiquidationPrice(props) {
14
+ const { snapshot, underlying } = props;
15
+ const targets = snapshot.assets.filter((a) => a.balance > 10n && !(0, viem.isAddressEqual)(a.token, underlying));
16
+ if (targets.length !== 1) return null;
17
+ return require_sdk_positions_calcLiquidationPriceForTarget.calcLiquidationPriceForTarget({
18
+ ...props,
19
+ targetToken: targets[0].token
20
+ });
21
+ }
22
+ //#endregion
23
+ exports.calcLiquidationPrice = calcLiquidationPrice;
@@ -0,0 +1,30 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_sdk_utils_AddressMap = require("../utils/AddressMap.js");
3
+ const require_sdk_constants_math = require("../constants/math.js");
4
+ let viem = require("viem");
5
+ //#region src/sdk/positions/calcLiquidationPriceForTarget.ts
6
+ /**
7
+ * Liquidation price of an explicitly named collateral token, in
8
+ * `PRICE_DECIMALS` fixed point; `0n` when the account holds none of it or the
9
+ * token has no liquidation threshold. Formula is in parity with the legacy
10
+ * `liquidationPrice`: the effective debt (debt less the underlying balance's
11
+ * contribution under its threshold) over the threshold-weighted target
12
+ * balance.
13
+ **/
14
+ function calcLiquidationPriceForTarget(props) {
15
+ const { snapshot, targetToken, underlying, decimals, liquidationThresholds } = props;
16
+ const decimalsByToken = new require_sdk_utils_AddressMap.AddressMap(Object.entries(decimals));
17
+ const lts = new require_sdk_utils_AddressMap.AddressMap(Object.entries(liquidationThresholds));
18
+ const underlyingDecimals = decimalsByToken.get(underlying) ?? 18;
19
+ const underlyingBalance = snapshot.assets.find((a) => (0, viem.isAddressEqual)(a.token, underlying))?.balance ?? 0n;
20
+ const ltUnderlying = BigInt(lts.get(underlying) ?? 0);
21
+ const effectiveDebt = (snapshot.totalDebt - underlyingBalance * ltUnderlying / require_sdk_constants_math.PERCENTAGE_FACTOR) * require_sdk_constants_math.WAD / 10n ** BigInt(underlyingDecimals);
22
+ const targetDecimals = decimalsByToken.get(targetToken) ?? 18;
23
+ const targetBalance = snapshot.assets.find((a) => (0, viem.isAddressEqual)(a.token, targetToken))?.balance ?? 0n;
24
+ const effectiveTargetBalance = targetBalance * require_sdk_constants_math.WAD / 10n ** BigInt(targetDecimals);
25
+ const lpLT = BigInt(lts.get(targetToken) ?? 0);
26
+ if (targetBalance <= 10n || lpLT <= 0n) return 0n;
27
+ return effectiveDebt * require_sdk_constants_math.PRICE_DECIMALS * require_sdk_constants_math.PERCENTAGE_FACTOR / (effectiveTargetBalance * lpLT);
28
+ }
29
+ //#endregion
30
+ exports.calcLiquidationPriceForTarget = calcLiquidationPriceForTarget;
@@ -0,0 +1,18 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_sdk_constants_math = require("../constants/math.js");
3
+ //#region src/sdk/positions/calcTimeToLiquidationMs.ts
4
+ /**
5
+ * Estimated milliseconds until `healthFactorBps` decays to `10000` (1.0)
6
+ * while the debt grows at `totalBorrowRateOnDebt` (basis points relative to
7
+ * the debt, as {@link BorrowRateBreakdown.totalOnDebt} reports it).
8
+ *
9
+ * `null` when the account is already at or under the liquidation threshold,
10
+ * or when the debt carries no borrow rate at all. Formula is in parity with
11
+ * the legacy `getTimeToLiquidation`.
12
+ **/
13
+ function calcTimeToLiquidationMs(healthFactorBps, totalBorrowRateOnDebt) {
14
+ if (BigInt(healthFactorBps) <= 10000n || totalBorrowRateOnDebt === 0n) return null;
15
+ return (BigInt(healthFactorBps) - require_sdk_constants_math.PERCENTAGE_FACTOR) * (BigInt(require_sdk_constants_math.SECONDS_PER_YEAR) * require_sdk_constants_math.PERCENTAGE_FACTOR * require_sdk_constants_math.PERCENTAGE_DECIMALS / totalBorrowRateOnDebt) * 1000n / require_sdk_constants_math.PERCENTAGE_FACTOR;
16
+ }
17
+ //#endregion
18
+ exports.calcTimeToLiquidationMs = calcTimeToLiquidationMs;
@@ -1,6 +1,17 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_sdk_positions_calcBorrowRate = require("./calcBorrowRate.js");
3
+ const require_sdk_positions_calcHealthFactor = require("./calcHealthFactor.js");
4
+ const require_sdk_positions_calcLiquidationPriceForTarget = require("./calcLiquidationPriceForTarget.js");
5
+ const require_sdk_positions_calcLiquidationPrice = require("./calcLiquidationPrice.js");
6
+ const require_sdk_positions_calcTimeToLiquidationMs = require("./calcTimeToLiquidationMs.js");
2
7
  const require_sdk_positions_MultichainPositionsService = require("./MultichainPositionsService.js");
8
+ const require_sdk_positions_types = require("./types.js");
3
9
  const require_sdk_positions_PositionsService = require("./PositionsService.js");
4
- require("./types.js");
5
10
  exports.MultichainPositionsService = require_sdk_positions_MultichainPositionsService.MultichainPositionsService;
6
11
  exports.PositionsService = require_sdk_positions_PositionsService.PositionsService;
12
+ exports.accountSnapshotFromCreditAccountData = require_sdk_positions_types.accountSnapshotFromCreditAccountData;
13
+ exports.calcBorrowRate = require_sdk_positions_calcBorrowRate.calcBorrowRate;
14
+ exports.calcHealthFactor = require_sdk_positions_calcHealthFactor.calcHealthFactor;
15
+ exports.calcLiquidationPrice = require_sdk_positions_calcLiquidationPrice.calcLiquidationPrice;
16
+ exports.calcLiquidationPriceForTarget = require_sdk_positions_calcLiquidationPriceForTarget.calcLiquidationPriceForTarget;
17
+ exports.calcTimeToLiquidationMs = require_sdk_positions_calcTimeToLiquidationMs.calcTimeToLiquidationMs;
@@ -1 +1,32 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ require("../constants/math.js");
3
+ //#region src/sdk/positions/types.ts
4
+ /**
5
+ * Builds an {@link AccountSnapshot} from on-chain credit account data: the
6
+ * enabled, above-dust tokens become assets and quotas, and `totalDebt` is
7
+ * principal plus accrued interest and fees.
8
+ **/
9
+ function accountSnapshotFromCreditAccountData(ca) {
10
+ const assets = [];
11
+ const quotas = [];
12
+ for (const t of ca.tokens) {
13
+ if ((t.mask & ca.enabledTokensMask) === 0n || t.balance <= 10n) continue;
14
+ assets.push({
15
+ token: t.token,
16
+ balance: t.balance
17
+ });
18
+ quotas.push({
19
+ token: t.token,
20
+ balance: t.quota
21
+ });
22
+ }
23
+ return {
24
+ creditManager: ca.creditManager,
25
+ assets,
26
+ quotas,
27
+ totalDebt: ca.debt + ca.accruedInterest + ca.accruedFees,
28
+ totalValue: ca.totalValue
29
+ };
30
+ }
31
+ //#endregion
32
+ exports.accountSnapshotFromCreditAccountData = accountSnapshotFromCreditAccountData;
@@ -4,6 +4,8 @@ import { calcQuotaBorrowRate } from "../creditAccount/calc-quota-borrow-rate.js"
4
4
  /**
5
5
  * Under the hood sums up rates for all given quotas and then multiplies them by 1+feeInterest,
6
6
  * but it is expected that the ONLY quota will be passed
7
+ *
8
+ * @deprecated Use `calcBorrowRate` from `sdk/positions` instead.
7
9
  */
8
10
  function getSingleQuotaBorrowRate(props) {
9
11
  const qr = calcQuotaBorrowRate(props);
@@ -1,9 +1,5 @@
1
- import { BigIntMath } from "../../../sdk/utils/bigint-math.js";
2
- import { PERCENTAGE_FACTOR, PRICE_DECIMALS } from "../../../sdk/constants/math.js";
3
- import "../../../sdk/index.js";
4
- import { PriceUtils } from "../price-math.js";
1
+ import { calcHealthFactor as calcHealthFactor$1 } from "../../../sdk/positions/calcHealthFactor.js";
5
2
  //#region src/common-utils/utils/creditAccount/calc-health-factor.ts
6
- const MAX_UINT16 = 65535;
7
3
  /**
8
4
  * Computes account health factor in percentage-factor units.
9
5
  *
@@ -14,25 +10,31 @@ const MAX_UINT16 = 65535;
14
10
  * @param props Credit account balances, quotas, prices, thresholds, and debt context.
15
11
  * @returns Health factor as a number in `PERCENTAGE_FACTOR` scale,
16
12
  * or `65535` when debt is zero.
13
+ *
14
+ * @deprecated Use `calcHealthFactor` from `sdk/positions` instead; this
15
+ * wrapper only maps the legacy props onto an `AccountSnapshot`.
17
16
  */
18
17
  function calcHealthFactor({ assets, quotas, quotasInfo, liquidationThresholds, underlyingToken, debt, prices, tokensList }) {
19
- if (debt === 0n) return MAX_UINT16;
20
- const underlyingDecimals = tokensList[underlyingToken]?.decimals || 18;
21
- const underlyingPrice = prices[underlyingToken] || 0n;
22
- const assetMoney = assets.reduce((acc, { token: tokenAddress, balance: amount }) => {
23
- const tokenDecimals = tokensList[tokenAddress]?.decimals || 18;
24
- const lt = liquidationThresholds[tokenAddress] || 0n;
25
- const price = prices[tokenAddress] || 0n;
26
- const tokenLtMoney = PriceUtils.calcTotalPrice(price, amount, tokenDecimals) * lt / PERCENTAGE_FACTOR;
27
- const { isActive = false } = quotasInfo?.[tokenAddress] || {};
28
- const quota = quotas[tokenAddress];
29
- const quotaBalance = isActive ? quota?.balance || 0n : 0n;
30
- const quotaMoney = PriceUtils.calcTotalPrice(underlyingPrice, quotaBalance, underlyingDecimals);
31
- return acc + (quota ? BigIntMath.min(quotaMoney, tokenLtMoney) : tokenLtMoney);
32
- }, 0n);
33
- const borrowedMoney = PriceUtils.calcTotalPrice(underlyingPrice || PRICE_DECIMALS, debt, underlyingDecimals);
34
- const hfInPercent = borrowedMoney > 0n ? assetMoney * PERCENTAGE_FACTOR / borrowedMoney : 0n;
35
- return Number(hfInPercent);
18
+ const decimals = {};
19
+ for (const [token, meta] of Object.entries(tokensList)) decimals[token] = meta.decimals;
20
+ const lts = {};
21
+ for (const [token, lt] of Object.entries(liquidationThresholds)) lts[token] = Number(lt);
22
+ const activeQuotas = {};
23
+ for (const [token, info] of Object.entries(quotasInfo)) if (info?.isActive) activeQuotas[token] = true;
24
+ return calcHealthFactor$1({
25
+ snapshot: {
26
+ creditManager: underlyingToken,
27
+ assets,
28
+ quotas: Object.values(quotas),
29
+ totalDebt: debt,
30
+ totalValue: 0n
31
+ },
32
+ underlying: underlyingToken,
33
+ decimals,
34
+ prices,
35
+ liquidationThresholds: lts,
36
+ activeQuotas
37
+ });
36
38
  }
37
39
  //#endregion
38
40
  export { calcHealthFactor };
@@ -8,6 +8,8 @@
8
8
  *
9
9
  * @param props Quota balances and per-token quota rates.
10
10
  * @returns Sum of `balance * rate` terms in percentage-factor scale.
11
+ *
12
+ * @deprecated Use `calcBorrowRate` from `sdk/positions` instead.
11
13
  */
12
14
  function calcQuotaBorrowRate({ quotas, quotaRates }) {
13
15
  return Object.values(quotas).reduce((acc, { token, balance }) => {
@@ -1,5 +1,4 @@
1
- import { PERCENTAGE_DECIMALS, PERCENTAGE_FACTOR, SECONDS_PER_YEAR } from "../../../sdk/constants/math.js";
2
- import "../../../sdk/index.js";
1
+ import { calcTimeToLiquidationMs } from "../../../sdk/positions/calcTimeToLiquidationMs.js";
3
2
  //#region src/common-utils/utils/creditAccount/get-time-to-liquidation.ts
4
3
  /**
5
4
  * Estimates time remaining until health factor reaches liquidation level.
@@ -11,10 +10,12 @@ import "../../../sdk/index.js";
11
10
  * @param props Current health factor and `totalBorrowRate * debt` term.
12
11
  * @returns Milliseconds to liquidation as `bigint`, or `null` when already at/under
13
12
  * liquidation threshold or when borrow-rate exposure is zero.
13
+ *
14
+ * @deprecated Use `calcTimeToLiquidationMs` from `sdk/positions` instead;
15
+ * this wrapper only forwards to the new implementation.
14
16
  */
15
17
  function getTimeToLiquidation({ healthFactor, totalBorrowRate_debt }) {
16
- if (healthFactor <= 10000n || totalBorrowRate_debt === 0n) return null;
17
- return (BigInt(healthFactor) - PERCENTAGE_FACTOR) * (BigInt(SECONDS_PER_YEAR) * PERCENTAGE_FACTOR * PERCENTAGE_DECIMALS / totalBorrowRate_debt) * 1000n / PERCENTAGE_FACTOR;
18
+ return calcTimeToLiquidationMs(healthFactor, totalBorrowRate_debt);
18
19
  }
19
20
  //#endregion
20
21
  export { getTimeToLiquidation };
@@ -1,5 +1,4 @@
1
- import { PERCENTAGE_FACTOR, PRICE_DECIMALS, WAD } from "../../../sdk/constants/math.js";
2
- import "../../../sdk/index.js";
1
+ import { calcLiquidationPriceForTarget } from "../../../sdk/positions/calcLiquidationPriceForTarget.js";
3
2
  //#region src/common-utils/utils/creditAccount/liquidation-price.ts
4
3
  /**
5
4
  * Calculates target token liquidation price for a credit account.
@@ -12,17 +11,28 @@ import "../../../sdk/index.js";
12
11
  * @param props Debt context, assets, thresholds, and token metadata.
13
12
  * @returns Target token price in `PRICE_DECIMALS` precision that corresponds
14
13
  * to liquidation boundary; returns `0n` when target balance or LT is non-positive.
14
+ *
15
+ * @deprecated Use `calcLiquidationPriceForTarget` from `sdk/positions`
16
+ * instead; this wrapper only maps the legacy props onto an `AccountSnapshot`.
15
17
  */
16
18
  function liquidationPrice({ liquidationThresholds, debt, underlyingToken, targetToken, assets, tokensList }) {
17
- const underlyingDecimals = tokensList[underlyingToken]?.decimals || 18;
18
- const { balance: underlyingBalance = 0n } = assets[underlyingToken] || {};
19
- const effectiveDebt = (debt - underlyingBalance * (liquidationThresholds[underlyingToken] || 0n) / PERCENTAGE_FACTOR) * WAD / 10n ** BigInt(underlyingDecimals);
20
- const targetDecimals = tokensList[targetToken]?.decimals || 18;
21
- const { balance: targetBalance = 0n } = assets[targetToken] || {};
22
- const effectiveTargetBalance = targetBalance * WAD / 10n ** BigInt(targetDecimals);
23
- const lpLT = liquidationThresholds[targetToken] || 0n;
24
- if (targetBalance <= 0n || lpLT <= 0n) return 0n;
25
- return effectiveDebt * PRICE_DECIMALS * PERCENTAGE_FACTOR / (effectiveTargetBalance * lpLT);
19
+ const decimals = {};
20
+ for (const [token, meta] of Object.entries(tokensList)) decimals[token] = meta.decimals;
21
+ const lts = {};
22
+ for (const [token, lt] of Object.entries(liquidationThresholds)) lts[token] = Number(lt);
23
+ return calcLiquidationPriceForTarget({
24
+ snapshot: {
25
+ creditManager: underlyingToken,
26
+ assets: Object.values(assets),
27
+ quotas: [],
28
+ totalDebt: debt,
29
+ totalValue: 0n
30
+ },
31
+ targetToken,
32
+ underlying: underlyingToken,
33
+ decimals,
34
+ liquidationThresholds: lts
35
+ });
26
36
  }
27
37
  //#endregion
28
38
  export { liquidationPrice };
@@ -1,9 +1,9 @@
1
- import { ierc20Abi } from "../abi/iERC20.js";
2
1
  import { iCreditFacadeV310Abi } from "../abi/310/generated.js";
3
2
  import { AddressMap } from "../sdk/utils/AddressMap.js";
4
3
  import { AddressSet } from "../sdk/utils/AddressSet.js";
5
4
  import { AssetsMap } from "../sdk/utils/AssetsMap.js";
6
5
  import { childLogger } from "../sdk/utils/childLogger.js";
6
+ import { ierc20Abi } from "../abi/iERC20.js";
7
7
  import "../sdk/constants/addresses.js";
8
8
  import { MAX_UINT256, PERCENTAGE_FACTOR } from "../sdk/constants/math.js";
9
9
  import { SDKConstruct } from "../sdk/base/SDKConstruct.js";
@@ -1,6 +1,6 @@
1
- import { iWithdrawalCompressorV313Abi } from "../abi/IWithdrawalCompressorV313.js";
2
1
  import { getNetworkType } from "../sdk/chain/chains.js";
3
2
  import { getWithdrawalCompressorAddress } from "../sdk/accounts/withdrawal-compressor/addresses.js";
3
+ import { iWithdrawalCompressorV313Abi } from "../abi/IWithdrawalCompressorV313.js";
4
4
  import "../sdk/index.js";
5
5
  import { iMidasDataFeedAbi, iMidasRedemptionVaultAbi, midasGatewayAbi, midasRedeemerAbi, midasRedemptionVaultPhantomTokenAbi, securitizeRedeemerAbi, securitizeRedemptionGatewayAbi, securitizeRedemptionPhantomTokenAbi } from "./withdrawalAbi.js";
6
6
  import { erc20Abi, hexToString, parseAbi, parseEther } from "viem";