@gearbox-protocol/sdk 15.1.0-next.5 → 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 (130) 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 +21 -5
  20. package/dist/cjs/sdk/market/credit/CreditManagerV310Contract.js +1 -12
  21. package/dist/cjs/sdk/market/credit/CreditSuite.js +17 -26
  22. package/dist/cjs/sdk/market/credit/index.js +3 -0
  23. package/dist/cjs/sdk/market/credit/isStrategyCollateral.js +50 -0
  24. package/dist/cjs/sdk/market/index.js +17 -0
  25. package/dist/cjs/sdk/market/math.js +57 -44
  26. package/dist/cjs/sdk/market/oracle/PriceOracleBaseContract.js +10 -3
  27. package/dist/cjs/sdk/market/pool/PoolV310Contract.js +1 -1
  28. package/dist/cjs/sdk/opportunities/index.js +0 -13
  29. package/dist/cjs/sdk/positions/PositionsService.js +206 -1
  30. package/dist/cjs/sdk/positions/calcBorrowRate.js +43 -0
  31. package/dist/cjs/sdk/positions/calcHealthFactor.js +44 -0
  32. package/dist/cjs/sdk/positions/calcLiquidationPrice.js +23 -0
  33. package/dist/cjs/sdk/positions/calcLiquidationPriceForTarget.js +30 -0
  34. package/dist/cjs/sdk/positions/calcTimeToLiquidationMs.js +18 -0
  35. package/dist/cjs/sdk/positions/index.js +12 -1
  36. package/dist/cjs/sdk/positions/types.js +31 -0
  37. package/dist/esm/common-utils/utils/apy/get-single-quota-borrow-rate.js +2 -0
  38. package/dist/esm/common-utils/utils/creditAccount/calc-health-factor.js +24 -22
  39. package/dist/esm/common-utils/utils/creditAccount/calc-quota-borrow-rate.js +2 -0
  40. package/dist/esm/common-utils/utils/creditAccount/get-time-to-liquidation.js +5 -4
  41. package/dist/esm/common-utils/utils/creditAccount/liquidation-price.js +21 -11
  42. package/dist/esm/dev/AccountOpener.js +1 -1
  43. package/dist/esm/dev/withdrawalUtils.js +1 -1
  44. package/dist/esm/model/index.js +2 -2
  45. package/dist/esm/model/positions.schema.js +14 -2
  46. package/dist/esm/plugins/adapters/contracts/ERC4626AdapterContract.js +1 -1
  47. package/dist/esm/preview/preview/CreditAccountState.js +14 -1
  48. package/dist/esm/preview/preview/buildDelayedPreview.js +16 -6
  49. package/dist/esm/preview/preview/previewAdjustCreditAccount.js +9 -2
  50. package/dist/esm/preview/preview/previewOpenCreditAccount.js +11 -3
  51. package/dist/esm/preview/preview/previewOperation.js +1 -1
  52. package/dist/esm/preview/simulate/simulatePoolOperation.js +1 -1
  53. package/dist/esm/preview/trace/extractTransfers.js +1 -1
  54. package/dist/esm/sdk/accounts/CreditAccountsServiceV310.js +2 -8
  55. package/dist/esm/sdk/accounts/credit-account-compressor/CreditAccountCompressor.js +2 -90
  56. package/dist/esm/sdk/accounts/intents/testing/sdk-mock.js +31 -4
  57. package/dist/esm/sdk/accounts/intents/utils/adjust-state-to-snapshot.js +17 -0
  58. package/dist/esm/sdk/accounts/intents/utils/index.js +2 -1
  59. package/dist/esm/sdk/accounts/liquidations/LiquidationsService.js +1 -4
  60. package/dist/esm/sdk/accounts/withdrawal-compressor/RedemptionLoggerV310Contract.js +1 -1
  61. package/dist/esm/sdk/accounts/withdrawal-compressor/WithdrawalCompressorV310Contract.js +1 -1
  62. package/dist/esm/sdk/accounts/withdrawal-compressor/WithdrawalCompressorV311Contract.js +1 -1
  63. package/dist/esm/sdk/accounts/withdrawal-compressor/WithdrawalCompressorV313Contract.js +1 -1
  64. package/dist/esm/sdk/base/TokensMeta.js +3 -3
  65. package/dist/esm/sdk/chain/detectNetwork.js +1 -1
  66. package/dist/esm/sdk/core/createAddressProvider.js +1 -1
  67. package/dist/esm/sdk/index.js +9 -2
  68. package/dist/esm/sdk/market/credit/CreditFacadeV310BaseContract.js +1 -1
  69. package/dist/esm/sdk/market/credit/CreditManagerV310Contract.js +2 -13
  70. package/dist/esm/sdk/market/credit/CreditSuite.js +18 -27
  71. package/dist/esm/sdk/market/credit/index.js +2 -1
  72. package/dist/esm/sdk/market/credit/isStrategyCollateral.js +48 -0
  73. package/dist/esm/sdk/market/index.js +3 -1
  74. package/dist/esm/sdk/market/math.js +52 -40
  75. package/dist/esm/sdk/market/oracle/PriceOracleBaseContract.js +10 -3
  76. package/dist/esm/sdk/market/pool/PoolV310Contract.js +3 -3
  77. package/dist/esm/sdk/market/zapper/IETHZapperContract.js +1 -1
  78. package/dist/esm/sdk/market/zapper/ZapperContract.js +1 -1
  79. package/dist/esm/sdk/opportunities/index.js +1 -2
  80. package/dist/esm/sdk/pools/PoolService.js +1 -1
  81. package/dist/esm/sdk/positions/PositionsService.js +206 -1
  82. package/dist/esm/sdk/positions/calcBorrowRate.js +42 -0
  83. package/dist/esm/sdk/positions/calcHealthFactor.js +43 -0
  84. package/dist/esm/sdk/positions/calcLiquidationPrice.js +22 -0
  85. package/dist/esm/sdk/positions/calcLiquidationPriceForTarget.js +29 -0
  86. package/dist/esm/sdk/positions/calcTimeToLiquidationMs.js +17 -0
  87. package/dist/esm/sdk/positions/index.js +7 -2
  88. package/dist/esm/sdk/positions/types.js +31 -1
  89. package/dist/esm/sdk/utils/viem/simulateWithPriceUpdates.js +1 -1
  90. package/dist/types/common-utils/utils/apy/get-single-quota-borrow-rate.d.ts +2 -0
  91. package/dist/types/common-utils/utils/creditAccount/calc-health-factor.d.ts +3 -0
  92. package/dist/types/common-utils/utils/creditAccount/calc-quota-borrow-rate.d.ts +2 -0
  93. package/dist/types/common-utils/utils/creditAccount/get-time-to-liquidation.d.ts +3 -0
  94. package/dist/types/common-utils/utils/creditAccount/liquidation-price.d.ts +3 -0
  95. package/dist/types/model/index.d.ts +3 -3
  96. package/dist/types/model/opportunities.d.ts +9 -9
  97. package/dist/types/model/positions.d.ts +87 -4
  98. package/dist/types/model/positions.schema.d.ts +26 -1
  99. package/dist/types/preview/preview/CreditAccountState.d.ts +6 -0
  100. package/dist/types/preview/preview/buildDelayedPreview.d.ts +5 -1
  101. package/dist/types/preview/preview/types.d.ts +4 -2
  102. package/dist/types/sdk/accounts/CreditAccountsServiceV310.d.ts +1 -7
  103. package/dist/types/sdk/accounts/credit-account-compressor/CreditAccountCompressor.d.ts +3 -12
  104. package/dist/types/sdk/accounts/credit-account-compressor/index.d.ts +2 -2
  105. package/dist/types/sdk/accounts/credit-account-compressor/types.d.ts +1 -19
  106. package/dist/types/sdk/accounts/index.d.ts +2 -2
  107. package/dist/types/sdk/accounts/intents/testing/sdk-mock.d.ts +6 -0
  108. package/dist/types/sdk/accounts/intents/utils/adjust-state-to-snapshot.d.ts +13 -0
  109. package/dist/types/sdk/accounts/intents/utils/index.d.ts +2 -1
  110. package/dist/types/sdk/accounts/types.d.ts +1 -12
  111. package/dist/types/sdk/index.d.ts +10 -4
  112. package/dist/types/sdk/market/credit/CreditManagerV310Contract.d.ts +0 -4
  113. package/dist/types/sdk/market/credit/CreditSuite.d.ts +2 -16
  114. package/dist/types/sdk/market/credit/index.d.ts +2 -1
  115. package/dist/types/sdk/market/credit/isStrategyCollateral.d.ts +74 -0
  116. package/dist/types/sdk/market/credit/types.d.ts +2 -9
  117. package/dist/types/sdk/market/index.d.ts +3 -1
  118. package/dist/types/sdk/market/math.d.ts +44 -34
  119. package/dist/types/sdk/market/oracle/PriceOracleBaseContract.d.ts +4 -0
  120. package/dist/types/sdk/market/oracle/types.d.ts +8 -0
  121. package/dist/types/sdk/opportunities/index.d.ts +1 -2
  122. package/dist/types/sdk/positions/PositionsService.d.ts +31 -2
  123. package/dist/types/sdk/positions/calcBorrowRate.d.ts +40 -0
  124. package/dist/types/sdk/positions/calcHealthFactor.d.ts +45 -0
  125. package/dist/types/sdk/positions/calcLiquidationPrice.d.ts +12 -0
  126. package/dist/types/sdk/positions/calcLiquidationPriceForTarget.d.ts +43 -0
  127. package/dist/types/sdk/positions/calcTimeToLiquidationMs.d.ts +15 -0
  128. package/dist/types/sdk/positions/index.d.ts +7 -2
  129. package/dist/types/sdk/positions/types.d.ts +58 -1
  130. package/package.json +1 -1
@@ -8,8 +8,7 @@ import { BaseContract } from "../../base/BaseContract.js";
8
8
  import "../../base/index.js";
9
9
  import { createAdapter } from "../adapters/createAdapter.js";
10
10
  import "../adapters/index.js";
11
- import { maxLeverage } from "../math.js";
12
- import { isAddressEqual } from "viem";
11
+ import { calcMaxLeverage } from "../math.js";
13
12
  //#region src/sdk/market/credit/CreditManagerV310Contract.ts
14
13
  const abi = iCreditManagerV310Abi;
15
14
  var CreditManagerV310Contract = class extends BaseContract {
@@ -64,20 +63,10 @@ var CreditManagerV310Contract = class extends BaseContract {
64
63
  return this.liquidationThresholds.keys();
65
64
  }
66
65
  /**
67
- * {@inheritDoc ICreditManagerContract.leverageableCollaterals}
68
- */
69
- get leverageableCollaterals() {
70
- return this.collateralTokens.filter((token) => {
71
- if (isAddressEqual(token, this.underlying)) return false;
72
- const lt = this.liquidationThresholds.get(token);
73
- return !!lt && lt > 0 && lt < Number(10000n);
74
- });
75
- }
76
- /**
77
66
  * {@inheritDoc ICreditManagerContract.maxLeverage}
78
67
  */
79
68
  maxLeverage(collateral) {
80
- return maxLeverage(this.liquidationThresholds.mustGet(collateral));
69
+ return calcMaxLeverage(this.liquidationThresholds.mustGet(collateral));
81
70
  }
82
71
  /**
83
72
  * {@inheritDoc ICreditManagerContract.liquidationPremium}
@@ -6,12 +6,12 @@ import "../../constants/index.js";
6
6
  import "../../utils/index.js";
7
7
  import { SDKConstruct } from "../../base/SDKConstruct.js";
8
8
  import "../../base/index.js";
9
- import { additionalBorrowApyBps, borrowApyBps, minSeizedAmount, optimalHFForPartialLiquidation, optimalRepaidAmount } from "../math.js";
9
+ import { calcAdditionalBorrowApy, calcBorrowApy, minSeizedAmount, optimalHFForPartialLiquidation, optimalRepaidAmount } from "../math.js";
10
10
  import createCreditConfigurator from "./createCreditConfigurator.js";
11
11
  import createCreditFacade from "./createCreditFacade.js";
12
12
  import createCreditManager from "./createCreditManager.js";
13
13
  import { mustGetDominantCollateral } from "./dominantCollateral.js";
14
- import { isAddressEqual } from "viem";
14
+ import { isStrategyCollateral } from "./isStrategyCollateral.js";
15
15
  //#region src/sdk/market/credit/CreditSuite.ts
16
16
  /**
17
17
  * SDK aggregate for one credit-manager branch inside a market.
@@ -171,22 +171,8 @@ var CreditSuite = class extends SDKConstruct {
171
171
  return this.creditFacade.isPaused || this.market.pool.isPaused;
172
172
  }
173
173
  /**
174
- * Collateral tokens a leveraged position can be built around in this suite:
175
- * the ones the credit manager can lever up, narrowed to the tokens that can
176
- * still be entered. A token qualifies when it
177
- *
178
- * - has a liquidation threshold above `0` and below `100%`, and is not the
179
- * suite's underlying, see
180
- * {@link ICreditManagerContract.leverageableCollaterals};
181
- * - is not the token the market's underlying wraps, which for an RWA market
182
- * is the same exposure as the underlying itself;
183
- * - is not a phantom token, which only ever appears as the intermediate step
184
- * of a withdrawal and cannot be acquired;
185
- * - is not an expired token, e.g. a matured Pendle PT;
186
- * - has a non-zero main price in the market's oracle — a zero or failed
187
- * answer (e.g. a zero price feed) means the position cannot be valued;
188
- * - the market still accepts quota for, see
189
- * {@link PoolQuotaKeeperContract.hasActiveQuota}.
174
+ * Collateral tokens a leveraged position can be built around in this suite,
175
+ * see {@link isStrategyCollateral} for the per-token criteria.
190
176
  *
191
177
  * A suite where no debt can be drawn at all ({@link maxBorrowAmount} is `0`,
192
178
  * e.g. its debt limit is exhausted or zeroed out) offers no strategies,
@@ -196,14 +182,19 @@ var CreditSuite = class extends SDKConstruct {
196
182
  if (this.maxBorrowAmount === 0n) return [];
197
183
  const { pqk, unwrappedUnderlying } = this.market.pool;
198
184
  const { mainPrices } = this.market.priceOracle;
199
- const { tokensMeta } = this;
200
- return this.creditManager.leverageableCollaterals.filter((token) => {
201
- if (isAddressEqual(token, unwrappedUnderlying)) return false;
185
+ const { tokensMeta, creditManager } = this;
186
+ return creditManager.collateralTokens.filter((token) => {
202
187
  const meta = tokensMeta.mustGet(token);
203
- if (tokensMeta.isPhantomToken(meta) || meta.isExpired) return false;
204
- const mainPrice = mainPrices.get(token);
205
- if (!mainPrice?.success || mainPrice.price === 0n) return false;
206
- return pqk.hasActiveQuota(token);
188
+ return isStrategyCollateral({
189
+ token,
190
+ underlying: creditManager.underlying,
191
+ unwrappedUnderlying,
192
+ liquidationThreshold: creditManager.liquidationThresholds.mustGet(token),
193
+ contractType: meta.contractType,
194
+ isExpired: meta.isExpired,
195
+ mainPrice: mainPrices.get(token)?.price,
196
+ hasActiveQuota: pqk.hasActiveQuota(token)
197
+ });
207
198
  });
208
199
  }
209
200
  /**
@@ -256,8 +247,8 @@ var CreditSuite = class extends SDKConstruct {
256
247
  liquidationPremium: cm.liquidationPremium,
257
248
  liquidationFee: cm.feeLiquidation,
258
249
  expirationDate: this.expirationDate,
259
- borrowApy: borrowApyBps(pool.baseInterestRate, cm.feeInterest),
260
- additionalBorrowApy: additionalBorrowApyBps(market.pool.pqk.quotaRate(collateral), maxLeverage),
250
+ borrowApy: calcBorrowApy(pool.baseInterestRate, cm.feeInterest),
251
+ additionalBorrowApy: calcAdditionalBorrowApy(market.pool.pqk.quotaRate(collateral), cm.feeInterest, maxLeverage),
261
252
  maxBorrowAmount: oracle.toAmount(pool.underlying, this.maxBorrowAmount),
262
253
  maxLeverage
263
254
  };
@@ -3,7 +3,8 @@ import { CreditFacadeV310BaseContract, creditFacadeV310Abi as abi } from "./Cred
3
3
  import { CreditFacadeV310Contract } from "./CreditFacadeV310Contract.js";
4
4
  import { CreditManagerV310Contract } from "./CreditManagerV310Contract.js";
5
5
  import { dominantCollateral, mustGetDominantCollateral } from "./dominantCollateral.js";
6
+ import { NON_STRATEGY_PHANTOM_TOKEN_TYPES, isStrategyCollateral } from "./isStrategyCollateral.js";
6
7
  import { CreditSuite } from "./CreditSuite.js";
7
8
  import { expectedBalanceDeltas } from "./expectedBalanceDeltas.js";
8
9
  import "./types.js";
9
- export { CreditConfiguratorV310Contract, CreditFacadeV310BaseContract, CreditFacadeV310Contract, CreditManagerV310Contract, CreditSuite, abi as creditFacadeV310Abi, dominantCollateral, expectedBalanceDeltas, mustGetDominantCollateral };
10
+ export { CreditConfiguratorV310Contract, CreditFacadeV310BaseContract, CreditFacadeV310Contract, CreditManagerV310Contract, CreditSuite, NON_STRATEGY_PHANTOM_TOKEN_TYPES, abi as creditFacadeV310Abi, dominantCollateral, expectedBalanceDeltas, isStrategyCollateral, mustGetDominantCollateral };
@@ -0,0 +1,48 @@
1
+ import "../../constants/math.js";
2
+ import "../../constants/index.js";
3
+ import { isAddressEqual } from "viem";
4
+ //#region src/sdk/market/credit/isStrategyCollateral.ts
5
+ /**
6
+ * Withdrawal and redemption phantom tokens that can never be acquired as a
7
+ * strategy target. Other `PHANTOM_TOKEN::*` types (Convex, Infrared, staking
8
+ * rewards) can.
9
+ */
10
+ const NON_STRATEGY_PHANTOM_TOKEN_TYPES = [
11
+ "PHANTOM_TOKEN::INFINIFI_UNWIND",
12
+ "PHANTOM_TOKEN::MELLOW_WITHDRAWAL",
13
+ "PHANTOM_TOKEN::MIDAS_REDEMPTION",
14
+ "PHANTOM_TOKEN::SECURITIZE_RD",
15
+ "PHANTOM_TOKEN::UPSHIFT_WITHDRAW"
16
+ ];
17
+ const NON_STRATEGY_PHANTOM_TOKEN_TYPE_SET = new Set(NON_STRATEGY_PHANTOM_TOKEN_TYPES);
18
+ const RWA_UNDERLYING_PREFIX = "RWA_UNDERLYING::";
19
+ /**
20
+ * Whether a collateral token can be the target of a leveraged strategy.
21
+ *
22
+ * A token qualifies when it
23
+ *
24
+ * - has a liquidation threshold above `0` and below `100%`, and is not the
25
+ * suite's underlying — borrowing an asset against itself is not a position,
26
+ * and an LT of `0` or at least `100%` would mean unbounded leverage;
27
+ * - is not the token the market's underlying wraps, which for an RWA market
28
+ * is the same exposure as the underlying itself (also rejected when
29
+ * `contractType` starts with `"RWA_UNDERLYING::"`);
30
+ * - is not a withdrawal or redemption phantom token listed in
31
+ * {@link NON_STRATEGY_PHANTOM_TOKEN_TYPES} — those only ever appear as the
32
+ * intermediate step of a withdrawal and cannot be acquired;
33
+ * - is not an expired token, e.g. a matured Pendle PT;
34
+ * - has a non-zero main price in the market's oracle — a zero or missing
35
+ * answer (e.g. a failed or zero price feed) means the position cannot be
36
+ * valued;
37
+ * - the market still accepts quota for.
38
+ */
39
+ function isStrategyCollateral({ token, underlying, unwrappedUnderlying, liquidationThreshold, contractType, isExpired, mainPrice, hasActiveQuota }) {
40
+ if (isAddressEqual(token, underlying) || isAddressEqual(token, unwrappedUnderlying)) return false;
41
+ if (liquidationThreshold <= 0 || liquidationThreshold >= Number(10000n)) return false;
42
+ if (contractType && (NON_STRATEGY_PHANTOM_TOKEN_TYPE_SET.has(contractType) || contractType.startsWith(RWA_UNDERLYING_PREFIX))) return false;
43
+ if (isExpired) return false;
44
+ if (!mainPrice) return false;
45
+ return hasActiveQuota;
46
+ }
47
+ //#endregion
48
+ export { NON_STRATEGY_PHANTOM_TOKEN_TYPES, isStrategyCollateral };
@@ -4,8 +4,10 @@ import "./adapters/index.js";
4
4
  import { CreditConfiguratorV310Contract } from "./credit/CreditConfiguratorV310Contract.js";
5
5
  import { CreditFacadeV310BaseContract, creditFacadeV310Abi as abi } from "./credit/CreditFacadeV310BaseContract.js";
6
6
  import { CreditFacadeV310Contract } from "./credit/CreditFacadeV310Contract.js";
7
+ import { MAX_LEVERAGE_BUFFER_BPS, PARTIAL_LIQUIDATION_BUFFER_BPS, calcAdditionalBorrowApy, calcBorrowApy, calcMaxLeverage, calcPositionLeverage, calcUtilization, healthFactorBps, minSeizedAmount, optimalHFForPartialLiquidation, optimalRepaidAmount, rayToBps, usdToNumber } from "./math.js";
7
8
  import { CreditManagerV310Contract } from "./credit/CreditManagerV310Contract.js";
8
9
  import { dominantCollateral, mustGetDominantCollateral } from "./credit/dominantCollateral.js";
10
+ import { NON_STRATEGY_PHANTOM_TOKEN_TYPES, isStrategyCollateral } from "./credit/isStrategyCollateral.js";
9
11
  import { CreditSuite } from "./credit/CreditSuite.js";
10
12
  import { expectedBalanceDeltas } from "./credit/expectedBalanceDeltas.js";
11
13
  import "./credit/index.js";
@@ -59,4 +61,4 @@ import { RWARegistry } from "./rwa/RWARegistry.js";
59
61
  import { RWA_FACTORY_TYPES, isRWAFactory } from "./rwa/types.js";
60
62
  import "./rwa/index.js";
61
63
  import "./types.js";
62
- export { AbstractLPPriceFeedContract, AbstractPriceFeedContract, BalancerStablePriceFeedContract, BalancerWeightedPriceFeedContract, BoundedPriceFeedContract, CompositePriceFeedContract, CreditConfiguratorV310Contract, CreditFacadeV310BaseContract, CreditFacadeV310Contract, CreditManagerV310Contract, CreditSuite, CurveCryptoPriceFeedContract, CurveStablePriceFeedContract, CurveUSDPriceFeedContract, Erc4626PriceFeedContract, ExternalPriceFeedContract, GaugeContract, IERC20ZapperContract, IETHZapperContract, LinearInterestRateModelContract, MarketRegister, MarketSuite, MellowLRTPriceFeedContract, MidasLiquidatorContract, PHANTOM_TOKEN_MIDAS_REDEMPTION, PHANTOM_TOKEN_SECURITIZE_REDEMPTION, PartialPriceFeedInitError, PendleTWAPPTPriceFeed, PlaceholderAdapterContract, PoolSuite, PoolV310Contract, PriceFeedRef, PriceFeedRegister, PriceOracleV310Contract, PythPriceFeed, RWARegistry, RWA_FACTORY_SECURITIZE, RWA_FACTORY_TYPES, RWA_LIQUIDATOR_MIDAS, RWA_LIQUIDATOR_SECURITIZE, RedstonePriceFeedContract, SECURITIZE_REGISTER_VAULT_TYPES, SecuritizeLiquidatorContract, SecuritizeRWAFactory, UnsupportedZapperFunctionError, WstETHPriceFeedContract, YearnPriceFeedContract, ZapperContract, ZeroPriceFeedContract, createAdapter, createPriceOracle, createZapper, abi as creditFacadeV310Abi, dominantCollateral, expectedBalanceDeltas, fetchRedstonePayloads, getRawPriceUpdates, isLPPriceFeed, isRWAFactory, isUpdatablePriceFeed, mustGetDominantCollateral };
64
+ export { AbstractLPPriceFeedContract, AbstractPriceFeedContract, BalancerStablePriceFeedContract, BalancerWeightedPriceFeedContract, BoundedPriceFeedContract, CompositePriceFeedContract, CreditConfiguratorV310Contract, CreditFacadeV310BaseContract, CreditFacadeV310Contract, CreditManagerV310Contract, CreditSuite, CurveCryptoPriceFeedContract, CurveStablePriceFeedContract, CurveUSDPriceFeedContract, Erc4626PriceFeedContract, ExternalPriceFeedContract, GaugeContract, IERC20ZapperContract, IETHZapperContract, LinearInterestRateModelContract, MAX_LEVERAGE_BUFFER_BPS, MarketRegister, MarketSuite, MellowLRTPriceFeedContract, MidasLiquidatorContract, NON_STRATEGY_PHANTOM_TOKEN_TYPES, PARTIAL_LIQUIDATION_BUFFER_BPS, PHANTOM_TOKEN_MIDAS_REDEMPTION, PHANTOM_TOKEN_SECURITIZE_REDEMPTION, PartialPriceFeedInitError, PendleTWAPPTPriceFeed, PlaceholderAdapterContract, PoolSuite, PoolV310Contract, PriceFeedRef, PriceFeedRegister, PriceOracleV310Contract, PythPriceFeed, RWARegistry, RWA_FACTORY_SECURITIZE, RWA_FACTORY_TYPES, RWA_LIQUIDATOR_MIDAS, RWA_LIQUIDATOR_SECURITIZE, RedstonePriceFeedContract, SECURITIZE_REGISTER_VAULT_TYPES, SecuritizeLiquidatorContract, SecuritizeRWAFactory, UnsupportedZapperFunctionError, WstETHPriceFeedContract, YearnPriceFeedContract, ZapperContract, ZeroPriceFeedContract, calcAdditionalBorrowApy, calcBorrowApy, calcMaxLeverage, calcPositionLeverage, calcUtilization, createAdapter, createPriceOracle, createZapper, abi as creditFacadeV310Abi, dominantCollateral, expectedBalanceDeltas, fetchRedstonePayloads, getRawPriceUpdates, healthFactorBps, isLPPriceFeed, isRWAFactory, isStrategyCollateral, isUpdatablePriceFeed, minSeizedAmount, mustGetDominantCollateral, optimalHFForPartialLiquidation, optimalRepaidAmount, rayToBps, usdToNumber };
@@ -15,7 +15,8 @@ const FULL = Number(PERCENTAGE_FACTOR);
15
15
  *
16
16
  * @example
17
17
  * ```ts
18
- * rayToBps(50_000_000_000_000_000_000_000_000n) // 500, i.e. 5%
18
+ * // ray: 5% (0.05 × 10²⁷)
19
+ * rayToBps(50_000_000_000_000_000_000_000_000n) // 500 bps = 5%
19
20
  * ```
20
21
  **/
21
22
  function rayToBps(ray) {
@@ -26,6 +27,7 @@ function rayToBps(ray) {
26
27
  *
27
28
  * @example
28
29
  * ```ts
30
+ * // usd: $1500.50 in 8-decimal fixed point
29
31
  * usdToNumber(150_050_000_000n) // 1500.5
30
32
  * ```
31
33
  **/
@@ -38,56 +40,66 @@ function usdToNumber(usd) {
38
40
  *
39
41
  * @example
40
42
  * ```ts
41
- * utilizationBps(750n, 1000n) // 7500, i.e. 75%
43
+ * // borrowed: 750, total: 1000
44
+ * calcUtilization(750n, 1000n) // 750 / 1000 = 7500 bps = 75%
42
45
  * ```
43
46
  **/
44
- function utilizationBps(borrowed, total) {
47
+ function calcUtilization(borrowed, total) {
45
48
  if (total <= 0n || borrowed <= 0n) return 0;
46
49
  const utilization = Number(borrowed * PERCENTAGE_FACTOR / total);
47
50
  return Math.min(utilization, FULL);
48
51
  }
49
52
  /**
50
- * Annual cost of debt for a credit manager, in basis points: the pool's base
51
- * rate plus the protocol's cut of the accrued interest.
53
+ * Annual cost of debt for a credit manager, in basis points:
54
+ * `baseInterestRate × (1 + feeInterest)` — the pool's base rate plus the
55
+ * protocol's cut of the accrued interest.
52
56
  *
53
57
  * @param baseInterestRate - Pool base rate in ray.
54
58
  * @param feeInterest - Credit manager interest fee in basis points.
55
59
  *
56
60
  * @example
57
61
  * ```ts
58
- * // 5% base rate, 50% interest fee
59
- * borrowApyBps(50_000_000_000_000_000_000_000_000n, 5000) // 750, i.e. 7.5%
62
+ * // baseInterestRate: 5% in ray, feeInterest: 5000 bps = 50%
63
+ * calcBorrowApy(50_000_000_000_000_000_000_000_000n, 5000) // 5% × 1.5 = 750 bps = 7.5%
60
64
  * ```
61
65
  **/
62
- function borrowApyBps(baseInterestRate, feeInterest) {
66
+ function calcBorrowApy(baseInterestRate, feeInterest) {
63
67
  return rayToBps(baseInterestRate * (PERCENTAGE_FACTOR + BigInt(feeInterest)) / PERCENTAGE_FACTOR);
64
68
  }
65
69
  /**
66
- * Highest leverage a liquidation threshold allows: `1 / (1 - lt)`.
67
- *
68
- * A threshold of 100% or more would allow unbounded leverage; such tokens are
69
- * not strategies and are filtered out before this is called, so the guard here
70
- * only exists to keep the function total.
70
+ * 5% safety margin subtracted from 100% in {@link calcMaxLeverage}, so a
71
+ * maxed position opens with HF slightly above 1.
72
+ **/
73
+ const MAX_LEVERAGE_BUFFER_BPS = 500;
74
+ /**
75
+ * Highest total-value leverage a liquidation threshold allows:
76
+ * `(100% − buffer) / (100% − liquidationThreshold)`. At HF = 1, debt is
77
+ * `liquidationThreshold × totalValue`, leaving `1 − liquidationThreshold` of
78
+ * equity per unit of exposure; the {@link MAX_LEVERAGE_BUFFER_BPS} buffer
79
+ * keeps the maxed position slightly away from that boundary.
71
80
  *
72
81
  * @example
73
82
  * ```ts
74
- * maxLeverage(9000) // 10
75
- * maxLeverage(8000) // 5
83
+ * // liquidationThreshold: 9000 bps = 90%
84
+ * calcMaxLeverage(9000) // (1 − 0.05) / (1 − 0.9) = 9.5x total exposure
76
85
  * ```
77
86
  **/
78
- function maxLeverage(liquidationThreshold) {
79
- const equity = FULL - liquidationThreshold;
80
- return equity > 0 ? FULL / equity : Number.POSITIVE_INFINITY;
87
+ function calcMaxLeverage(liquidationThreshold) {
88
+ if (liquidationThreshold >= FULL) return 0;
89
+ const leverage = (FULL - 500) / (FULL - liquidationThreshold);
90
+ return Math.max(leverage, 1);
81
91
  }
82
92
  /**
83
93
  * Converts a credit account's health factor from the 18-decimal fixed point the
84
94
  * contracts store to basis points.
85
95
  *
86
- * An account with no debt return MAX_UINT256 from contract, here we return 0
96
+ * Accounts with no debt store `MAX_UINT256` on-chain; for those this
97
+ * returns `0`.
87
98
  *
88
99
  * @example
89
100
  * ```ts
90
- * healthFactorBps(1_250_000_000_000_000_000n) // 12500, i.e. 1.25
101
+ * // healthFactor: 1.25 in 18-decimal fixed point
102
+ * healthFactorBps(1_250_000_000_000_000_000n) // 12500 bps = 1.25
91
103
  * ```
92
104
  **/
93
105
  function healthFactorBps(healthFactor) {
@@ -95,39 +107,39 @@ function healthFactorBps(healthFactor) {
95
107
  return Number(healthFactor * PERCENTAGE_FACTOR / WAD);
96
108
  }
97
109
  /**
98
- * Leverage of an open position: `totalDebt / equity`, where equity is what is
99
- * left of the position's value once its debt is repaid.
100
- *
101
- * Returns `0` for a position that carries no debt and for one that is
102
- * underwater, where there is no equity to lever.
110
+ * Total-value leverage of an open position:
111
+ * `totalValue / (totalValue − totalDebt)`. `1` when unleveraged, `0` when
112
+ * underwater.
103
113
  *
104
- * @param totalDebt - Debt principal plus accrued interest and fees.
105
- * @param totalValue - Total value of the position, in the same token.
114
+ * @param totalValue - Total value of the position.
115
+ * @param totalDebt - Debt principal plus accrued interest and fees, same token.
106
116
  *
107
117
  * @example
108
118
  * ```ts
109
- * positionLeverage(800n, 1000n) // 4, i.e. 4x debt per unit of equity
119
+ * // totalValue: 100k, totalDebt: 80k → equity: 100k − 80k = 20k
120
+ * calcPositionLeverage(100_000n, 80_000n) // 100k / 20k = 5x
110
121
  * ```
111
122
  **/
112
- function positionLeverage(totalDebt, totalValue) {
123
+ function calcPositionLeverage(totalValue, totalDebt) {
113
124
  const equity = totalValue - totalDebt;
114
- if (equity <= 0n || totalDebt <= 0n) return 0;
115
- return Number(totalDebt) / Number(equity);
125
+ if (totalValue <= 0n || equity <= 0n) return 0;
126
+ if (totalDebt <= 0n) return 1;
127
+ return Number(totalValue) / Number(equity);
116
128
  }
117
129
  /**
118
- * Annual quota cost scaled to the debt a maximally leveraged position carries,
119
- * in basis points. Every unit of own capital carries `maxLeverage - 1` units of
120
- * debt, and the quota is paid on the whole quoted position.
130
+ * Annual quota cost on equity, in basis points:
131
+ * `quotaRate × (1 + feeInterest) × leverage`. Quota accrues on the whole
132
+ * quoted position, and the DAO takes `feeInterest` of it as with base interest.
121
133
  *
122
134
  * @example
123
135
  * ```ts
124
- * // 2.5% quota rate at 5x leverage
125
- * additionalBorrowApyBps(250, 5) // 1000, i.e. 10%
136
+ * // quotaRate: 200 bps = 2%, feeInterest: 2500 bps = 25%, leverage: 9.5x
137
+ * calcAdditionalBorrowApy(200, 2500, 9.5) // 2% × 1.25 × 9.5 = 2375 bps = 23.75%
126
138
  * ```
127
139
  **/
128
- function additionalBorrowApyBps(quotaRate, leverage) {
129
- if (!Number.isFinite(leverage)) return 0;
130
- return Math.round(quotaRate * Math.max(leverage - 1, 0));
140
+ function calcAdditionalBorrowApy(quotaRate, feeInterest, leverage) {
141
+ if (!Number.isFinite(leverage) || leverage <= 0) return 0;
142
+ return Math.round(quotaRate * (1 + feeInterest / FULL) * leverage);
131
143
  }
132
144
  /**
133
145
  * {@link PERCENTAGE_FACTOR} less a 0.1% safety buffer.
@@ -185,4 +197,4 @@ function optimalHFForPartialLiquidation(borrowRate) {
185
197
  return PERCENTAGE_FACTOR + (borrowRate < 100n ? borrowRate : 100n);
186
198
  }
187
199
  //#endregion
188
- export { PARTIAL_LIQUIDATION_BUFFER_BPS, additionalBorrowApyBps, borrowApyBps, healthFactorBps, maxLeverage, minSeizedAmount, optimalHFForPartialLiquidation, optimalRepaidAmount, positionLeverage, rayToBps, usdToNumber, utilizationBps };
200
+ export { MAX_LEVERAGE_BUFFER_BPS, PARTIAL_LIQUIDATION_BUFFER_BPS, calcAdditionalBorrowApy, calcBorrowApy, calcMaxLeverage, calcPositionLeverage, calcUtilization, healthFactorBps, minSeizedAmount, optimalHFForPartialLiquidation, optimalRepaidAmount, rayToBps, usdToNumber };
@@ -132,17 +132,24 @@ var PriceOracleBaseContract = class extends BaseContract {
132
132
  return amount * 10n ** BigInt(this.tokensMeta.decimals(to)) / price;
133
133
  }
134
134
  /**
135
- * {@inheritDoc IPriceOracleContract.safeUsdValue}
135
+ * {@inheritDoc IPriceOracleContract.safeConvertToUSD}
136
136
  **/
137
- safeUsdValue(token, amount) {
137
+ safeConvertToUSD(token, amount) {
138
138
  try {
139
- return usdToNumber(this.convertToUSD(token, amount));
139
+ return this.convertToUSD(token, amount);
140
140
  } catch (e) {
141
141
  this.logger?.debug(`cannot price ${this.labelAddress(token)}: ${e}`);
142
142
  return null;
143
143
  }
144
144
  }
145
145
  /**
146
+ * {@inheritDoc IPriceOracleContract.safeUsdValue}
147
+ **/
148
+ safeUsdValue(token, amount) {
149
+ const usd = this.safeConvertToUSD(token, amount);
150
+ return usd === null ? null : usdToNumber(usd);
151
+ }
152
+ /**
146
153
  * {@inheritDoc IPriceOracleContract.toAmount}
147
154
  **/
148
155
  toAmount = (token, value) => {
@@ -1,4 +1,3 @@
1
- import { iPausableAbi } from "../../../abi/iPausable.js";
2
1
  import { iPoolV310Abi } from "../../../abi/310/generated.js";
3
2
  import { AddressMap } from "../../utils/AddressMap.js";
4
3
  import { RAY } from "../../constants/math.js";
@@ -7,7 +6,8 @@ import { formatBN, formatBNvalue, percentFmt } from "../../utils/formatter.js";
7
6
  import "../../utils/index.js";
8
7
  import { BaseContract } from "../../base/BaseContract.js";
9
8
  import "../../base/index.js";
10
- import { utilizationBps } from "../math.js";
9
+ import { iPausableAbi } from "../../../abi/iPausable.js";
10
+ import { calcUtilization } from "../math.js";
11
11
  //#region src/sdk/market/pool/PoolV310Contract.ts
12
12
  const abi = [...iPoolV310Abi, ...iPausableAbi];
13
13
  var PoolV310Contract = class extends BaseContract {
@@ -50,7 +50,7 @@ var PoolV310Contract = class extends BaseContract {
50
50
  * {@inheritDoc IPoolContract.utilization}
51
51
  */
52
52
  get utilization() {
53
- return utilizationBps(this.borrowed, this.expectedLiquidity);
53
+ return calcUtilization(this.borrowed, this.expectedLiquidity);
54
54
  }
55
55
  /**
56
56
  * {@inheritDoc IPoolContract.unwrappedUnderlying}
@@ -1,5 +1,5 @@
1
- import { iethZapperAbi } from "../../../abi/iETHZapper.js";
2
1
  import { ZapperContract } from "./ZapperContract.js";
2
+ import { iethZapperAbi } from "../../../abi/iETHZapper.js";
3
3
  //#region src/sdk/market/zapper/IETHZapperContract.ts
4
4
  const abi = iethZapperAbi;
5
5
  var IETHZapperContract = class extends ZapperContract {
@@ -1,6 +1,6 @@
1
- import { iZapperAbi } from "../../../abi/iZapper.js";
2
1
  import { BaseContract } from "../../base/BaseContract.js";
3
2
  import "../../base/index.js";
3
+ import { iZapperAbi } from "../../../abi/iZapper.js";
4
4
  import { UnsupportedZapperFunctionError } from "./errors.js";
5
5
  //#region src/sdk/market/zapper/ZapperContract.ts
6
6
  /**
@@ -1,4 +1,3 @@
1
- import { PARTIAL_LIQUIDATION_BUFFER_BPS, additionalBorrowApyBps, borrowApyBps, healthFactorBps, maxLeverage, minSeizedAmount, optimalHFForPartialLiquidation, optimalRepaidAmount, positionLeverage, rayToBps, usdToNumber, utilizationBps } from "../market/math.js";
2
1
  import { MultichainOpportunitiesService } from "./MultichainOpportunitiesService.js";
3
2
  import { OpportunitiesService } from "./OpportunitiesService.js";
4
- export { MultichainOpportunitiesService, OpportunitiesService, PARTIAL_LIQUIDATION_BUFFER_BPS, additionalBorrowApyBps, borrowApyBps, healthFactorBps, maxLeverage, minSeizedAmount, optimalHFForPartialLiquidation, optimalRepaidAmount, positionLeverage, rayToBps, usdToNumber, utilizationBps };
3
+ export { MultichainOpportunitiesService, OpportunitiesService };
@@ -1,5 +1,5 @@
1
- import { ierc20Abi } from "../../abi/iERC20.js";
2
1
  import { AddressSet } from "../utils/AddressSet.js";
2
+ import { ierc20Abi } from "../../abi/iERC20.js";
3
3
  import "../constants/addresses.js";
4
4
  import { RAY } from "../constants/math.js";
5
5
  import "../constants/index.js";