@gearbox-protocol/sdk 16.3.1-next.1 → 16.3.2-next.1

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 (95) hide show
  1. package/dist/cjs/model/errors/index.js +1 -0
  2. package/dist/cjs/model/errors/operation-errors.js +9 -0
  3. package/dist/cjs/model/index.js +1 -0
  4. package/dist/cjs/onchain/accounts/intents/collateral-money.js +41 -0
  5. package/dist/cjs/onchain/accounts/intents/guards.js +15 -3
  6. package/dist/cjs/onchain/accounts/intents/index.js +21 -18
  7. package/dist/cjs/onchain/accounts/intents/maxWithdrawCollateral.js +12 -38
  8. package/dist/cjs/onchain/accounts/intents/realize.js +10 -2
  9. package/dist/cjs/onchain/accounts/intents/tail.js +1 -1
  10. package/dist/cjs/onchain/accounts/intents/withdraw-limits.js +97 -0
  11. package/dist/cjs/onchain/index.js +2 -0
  12. package/dist/cjs/onchain/market/adapters/abi/conctructorAbi.js +1 -1
  13. package/dist/cjs/onchain/validation/checks/checkReservePriceLimited.js +30 -0
  14. package/dist/cjs/onchain/validation/checks/index.js +2 -0
  15. package/dist/cjs/onchain/validation/index.js +2 -0
  16. package/dist/cjs/plugins/bots/BotsPlugin.js +107 -0
  17. package/dist/cjs/plugins/bots/PartialLiquidationBotV310Contract.js +47 -0
  18. package/dist/cjs/plugins/bots/abi/iPartialLiquidationBotV310.js +225 -0
  19. package/dist/cjs/plugins/bots/abi/index.js +3 -0
  20. package/dist/cjs/plugins/bots/config.js +39 -0
  21. package/dist/cjs/plugins/bots/deserializePartialLiquidationBotParams.js +39 -0
  22. package/dist/cjs/plugins/bots/index.js +17 -0
  23. package/dist/cjs/plugins/bots/package.json +1 -0
  24. package/dist/cjs/plugins/bots/types.js +28 -0
  25. package/dist/cjs/sdk/prepare/PrepareApi.js +3 -2
  26. package/dist/esm/dev/AccountOpener.js +1 -1
  27. package/dist/esm/dev/withdrawalUtils.js +1 -1
  28. package/dist/esm/history/trace/extractTransfers.js +1 -1
  29. package/dist/esm/model/errors/index.js +2 -2
  30. package/dist/esm/model/errors/operation-errors.js +9 -1
  31. package/dist/esm/model/index.js +2 -2
  32. package/dist/esm/onchain/accounts/CreditAccountsServiceV310.js +2 -2
  33. package/dist/esm/onchain/accounts/intents/collateral-money.js +40 -0
  34. package/dist/esm/onchain/accounts/intents/guards.js +15 -3
  35. package/dist/esm/onchain/accounts/intents/index.js +21 -18
  36. package/dist/esm/onchain/accounts/intents/maxWithdrawCollateral.js +12 -38
  37. package/dist/esm/onchain/accounts/intents/realize.js +10 -2
  38. package/dist/esm/onchain/accounts/intents/tail.js +1 -1
  39. package/dist/esm/onchain/accounts/intents/withdraw-limits.js +95 -0
  40. package/dist/esm/onchain/accounts/liquidations/LiquidationsService.js +1 -1
  41. package/dist/esm/onchain/accounts/withdrawal-compressor/RedemptionLoggerV310Contract.js +1 -1
  42. package/dist/esm/onchain/accounts/withdrawal-compressor/WithdrawalCompressorV310Contract.js +1 -1
  43. package/dist/esm/onchain/accounts/withdrawal-compressor/WithdrawalCompressorV311Contract.js +1 -1
  44. package/dist/esm/onchain/accounts/withdrawal-compressor/WithdrawalCompressorV313Contract.js +1 -1
  45. package/dist/esm/onchain/base/TokensMeta.js +3 -3
  46. package/dist/esm/onchain/core/createAddressProvider.js +1 -1
  47. package/dist/esm/onchain/index.js +2 -1
  48. package/dist/esm/onchain/market/adapters/abi/conctructorAbi.js +1 -1
  49. package/dist/esm/onchain/market/adapters/contracts/AccountMigratorAdapterContract.js +1 -1
  50. package/dist/esm/onchain/market/adapters/contracts/ERC4626AdapterContract.js +1 -1
  51. package/dist/esm/onchain/market/credit/CreditFacadeV310BaseContract.js +1 -1
  52. package/dist/esm/onchain/market/pool/PoolV310Contract.js +1 -1
  53. package/dist/esm/onchain/market/rwa/createDegenNFT.js +1 -1
  54. package/dist/esm/onchain/market/zapper/IETHZapperContract.js +1 -1
  55. package/dist/esm/onchain/market/zapper/ZapperContract.js +1 -1
  56. package/dist/esm/onchain/preview/preview/previewPoolPositionOperation.js +2 -2
  57. package/dist/esm/onchain/utils/viem/simulateWithPriceUpdates.js +1 -1
  58. package/dist/esm/onchain/validation/checks/checkReservePriceLimited.js +29 -0
  59. package/dist/esm/onchain/validation/checks/index.js +2 -1
  60. package/dist/esm/onchain/validation/index.js +2 -1
  61. package/dist/esm/plugins/bots/BotsPlugin.js +106 -0
  62. package/dist/esm/plugins/bots/PartialLiquidationBotV310Contract.js +46 -0
  63. package/dist/esm/plugins/bots/abi/iPartialLiquidationBotV310.js +224 -0
  64. package/dist/esm/plugins/bots/abi/index.js +2 -0
  65. package/dist/esm/plugins/bots/config.js +34 -0
  66. package/dist/esm/plugins/bots/deserializePartialLiquidationBotParams.js +35 -0
  67. package/dist/esm/plugins/bots/index.js +7 -0
  68. package/dist/esm/plugins/bots/package.json +1 -0
  69. package/dist/esm/plugins/bots/types.js +26 -0
  70. package/dist/esm/sdk/prepare/PrepareApi.js +3 -2
  71. package/dist/types/model/errors/index.d.ts +2 -2
  72. package/dist/types/model/errors/operation-errors.d.ts +41 -1
  73. package/dist/types/model/index.d.ts +2 -2
  74. package/dist/types/onchain/accounts/intents/collateral-money.d.ts +42 -0
  75. package/dist/types/onchain/accounts/intents/guards.d.ts +18 -2
  76. package/dist/types/onchain/accounts/intents/index.d.ts +23 -14
  77. package/dist/types/onchain/accounts/intents/maxWithdrawCollateral.d.ts +3 -8
  78. package/dist/types/onchain/accounts/intents/types.d.ts +26 -4
  79. package/dist/types/onchain/accounts/intents/withdraw-limits.d.ts +80 -0
  80. package/dist/types/onchain/index.d.ts +2 -1
  81. package/dist/types/onchain/validation/checks/checkReservePriceLimited.d.ts +31 -0
  82. package/dist/types/onchain/validation/checks/index.d.ts +2 -1
  83. package/dist/types/onchain/validation/index.d.ts +2 -1
  84. package/dist/types/onchain/validation/raise.d.ts +2 -2
  85. package/dist/types/plugins/bots/BotsPlugin.d.ts +18 -0
  86. package/dist/types/plugins/bots/PartialLiquidationBotV310Contract.d.ts +216 -0
  87. package/dist/types/plugins/bots/abi/iPartialLiquidationBotV310.d.ts +193 -0
  88. package/dist/types/plugins/bots/abi/index.d.ts +2 -0
  89. package/dist/types/plugins/bots/config.d.ts +12 -0
  90. package/dist/types/plugins/bots/deserializePartialLiquidationBotParams.d.ts +7 -0
  91. package/dist/types/plugins/bots/index.d.ts +7 -0
  92. package/dist/types/plugins/bots/types.d.ts +53 -0
  93. package/dist/types/sdk/prepare/PrepareApi.d.ts +1 -1
  94. package/dist/types/sdk/prepare/types.d.ts +23 -16
  95. package/package.json +1 -1
@@ -28,6 +28,7 @@ exports.poolPaused = require_model_errors_operation_errors.poolPaused;
28
28
  exports.poolSunset = require_model_errors_operation_errors.poolSunset;
29
29
  exports.quotaCountExceeded = require_model_errors_operation_errors.quotaCountExceeded;
30
30
  exports.quotaLimitReached = require_model_errors_operation_errors.quotaLimitReached;
31
+ exports.reservePriceLimited = require_model_errors_operation_errors.reservePriceLimited;
31
32
  exports.rwaOpenRequirementsNotMet = require_model_errors_operation_errors.rwaOpenRequirementsNotMet;
32
33
  exports.unexpectedFailure = require_model_errors_prepare_errors.unexpectedFailure;
33
34
  exports.unpriceableTokenError = require_model_errors_oracle_errors.unpriceableTokenError;
@@ -67,6 +67,14 @@ function insufficientCollateral(args) {
67
67
  ...args
68
68
  };
69
69
  }
70
+ /** {@inheritDoc ReservePriceLimitedError} */
71
+ function reservePriceLimited(args) {
72
+ return {
73
+ code: "reservePriceLimited",
74
+ message: `The reserve price feed values this collateral below what the operation pays out: the account covers its debt at ${args.atMainPrices} on the main feed and only ${args.healthFactor} at the reserve one, below ${args.healthFactorThreshold}.`,
75
+ ...args
76
+ };
77
+ }
70
78
  /** {@inheritDoc ForbiddenTokenError} */
71
79
  function forbiddenToken(token) {
72
80
  return {
@@ -132,4 +140,5 @@ exports.poolPaused = poolPaused;
132
140
  exports.poolSunset = poolSunset;
133
141
  exports.quotaCountExceeded = quotaCountExceeded;
134
142
  exports.quotaLimitReached = quotaLimitReached;
143
+ exports.reservePriceLimited = reservePriceLimited;
135
144
  exports.rwaOpenRequirementsNotMet = rwaOpenRequirementsNotMet;
@@ -175,6 +175,7 @@ exports.quotaLimitReached = require_model_errors_operation_errors.quotaLimitReac
175
175
  exports.rateCurvePointSchema = require_model_opportunities_schema.rateCurvePointSchema;
176
176
  exports.rateCurveSchema = require_model_opportunities_schema.rateCurveSchema;
177
177
  exports.receivedAssetSchema = require_model_liquidations_schema.receivedAssetSchema;
178
+ exports.reservePriceLimited = require_model_errors_operation_errors.reservePriceLimited;
178
179
  exports.responseMetadataSchema = require_model_response_schema.responseMetadataSchema;
179
180
  exports.responseSchema = require_model_response_schema.responseSchema;
180
181
  exports.rewardsPnLSchema = require_model_positions_schema.rewardsPnLSchema;
@@ -0,0 +1,41 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_onchain_utils_bigint_math = require("../../utils/bigint-math.js");
3
+ const require_onchain_constants_math = require("../../constants/math.js");
4
+ require("../../utils/index.js");
5
+ const require_onchain_accounts_intents_utils_common = require("./utils/common.js");
6
+ //#region src/onchain/accounts/intents/collateral-money.ts
7
+ /** {@inheritDoc CollateralMoney} */
8
+ function collateralMoney(creditAccount, sdk) {
9
+ const { market, creditManager } = sdk.marketRegister.findCreditManager(creditAccount.creditManager);
10
+ const { priceOracle } = market;
11
+ const { pqk } = market.pool;
12
+ const underlying = market.pool.underlying;
13
+ const masked = creditAccount.enabledTokensMask !== 0n;
14
+ const mainUsd = (token, amount) => {
15
+ try {
16
+ return priceOracle.convertToUSD(token, amount);
17
+ } catch {
18
+ return;
19
+ }
20
+ };
21
+ const lt = (token) => BigInt(creditManager.liquidationThresholds.get(token) ?? 0);
22
+ const checkedUsd = (holding) => require_onchain_accounts_intents_utils_common.eq(holding.token, underlying) ? mainUsd(holding.token, holding.balance) ?? 0n : priceOracle.safeConvertMinUSD(holding.token, holding.balance).value;
23
+ /** A quota is underlying-denominated, and a closed market backs nothing. */
24
+ const quotaMoney = (holding) => pqk.hasActiveQuota(holding.token) ? (mainUsd(underlying, holding.quota) ?? 0n) * require_onchain_constants_math.PERCENTAGE_FACTOR : 0n;
25
+ const weigh = (holding) => {
26
+ const weighted = checkedUsd(holding) * lt(holding.token);
27
+ if (holding.quota === 0n) return weighted;
28
+ return require_onchain_utils_bigint_math.BigIntMath.min(quotaMoney(holding), weighted);
29
+ };
30
+ return {
31
+ underlying,
32
+ counts: (holding) => holding.balance > 10n && (!masked || (holding.mask & creditAccount.enabledTokensMask) !== 0n),
33
+ weigh,
34
+ quotaMoney,
35
+ mainUsd,
36
+ checkedUsd,
37
+ lt
38
+ };
39
+ }
40
+ //#endregion
41
+ exports.collateralMoney = collateralMoney;
@@ -7,6 +7,7 @@ const require_onchain_validation_checks_checkCreditManagerPaused = require("../.
7
7
  const require_onchain_validation_checks_checkForbiddenToken = require("../../validation/checks/checkForbiddenToken.js");
8
8
  const require_onchain_validation_checks_checkMarketExpired = require("../../validation/checks/checkMarketExpired.js");
9
9
  const require_onchain_validation_checks_checkQuotaLimit = require("../../validation/checks/checkQuotaLimit.js");
10
+ const require_onchain_validation_checks_checkReservePriceLimited = require("../../validation/checks/checkReservePriceLimited.js");
10
11
  const require_onchain_validation_raise = require("../../validation/raise.js");
11
12
  require("../../validation/index.js");
12
13
  const require_onchain_accounts_intents_utils_common = require("./utils/common.js");
@@ -112,13 +113,24 @@ function assertGrowthAllowed(args) {
112
113
  * whose reserve feed the SDK cannot read keeps its main price, so a plan can
113
114
  * still be refused on-chain after passing here.
114
115
  */
115
- function assertCollateralised(healthFactorBps, safePrices) {
116
+ function assertCollateralised(healthFactorBps, safePrices, atSafePrices) {
116
117
  const healthFactorThreshold = require_onchain_validation_helpers_health_factor_limits.MIN_HEALTH_FACTOR_FACADE;
117
- require_onchain_validation_raise.raise(require_onchain_validation_checks_checkCollateralised.checkCollateralised({
118
+ const errors = require_onchain_validation_checks_checkCollateralised.checkCollateralised({
118
119
  healthFactor: healthFactorBps,
119
120
  healthFactorThreshold,
120
121
  safePrices
121
- }), `the account would end at a health factor of ${healthFactorBps}, below ${healthFactorThreshold}`);
122
+ });
123
+ if (errors.length === 0) return;
124
+ if (safePrices && atSafePrices) {
125
+ const { atMainPrices, withdrawable } = atSafePrices();
126
+ require_onchain_validation_raise.raise(require_onchain_validation_checks_checkReservePriceLimited.checkReservePriceLimited({
127
+ healthFactor: healthFactorBps,
128
+ atMainPrices,
129
+ healthFactorThreshold,
130
+ withdrawable
131
+ }), `the account covers its debt at ${atMainPrices} on the main feed and only ${healthFactorBps} at the reserve one, below ${healthFactorThreshold}`);
132
+ }
133
+ require_onchain_validation_raise.raise(errors, `the account would end at a health factor of ${healthFactorBps}, below ${healthFactorThreshold}`);
122
134
  }
123
135
  /**
124
136
  * A quota can only be raised as far as the market still has room for: past the
@@ -9,13 +9,13 @@ require("../../validation/index.js");
9
9
  const require_onchain_accounts_intents_utils_pick_token = require("./utils/pick-token.js");
10
10
  const require_onchain_accounts_intents_guards = require("./guards.js");
11
11
  const require_onchain_accounts_intents_leverage_band = require("./leverage-band.js");
12
- const require_onchain_accounts_intents_math = require("./math.js");
13
12
  const require_onchain_accounts_intents_maxWithdrawCollateral = require("./maxWithdrawCollateral.js");
14
13
  const require_onchain_accounts_intents_utils_credit_account_slice = require("./utils/credit-account-slice.js");
15
14
  const require_onchain_accounts_intents_open_strategy = require("./open-strategy.js");
16
15
  const require_onchain_accounts_intents_plan = require("./plan.js");
17
- const require_onchain_accounts_intents_realize = require("./realize.js");
18
16
  const require_onchain_accounts_intents_view = require("./view.js");
17
+ const require_onchain_accounts_intents_withdraw_limits = require("./withdraw-limits.js");
18
+ const require_onchain_accounts_intents_realize = require("./realize.js");
19
19
  const require_onchain_accounts_intents_tail = require("./tail.js");
20
20
  //#region src/onchain/accounts/intents/index.ts
21
21
  /**
@@ -51,26 +51,29 @@ var CreditAccountOperationsService = class extends require_onchain_base_SDKConst
51
51
  }
52
52
  /**
53
53
  * Both ends of what a `WITHDRAW` can take out, in underlying: the largest
54
- * partial withdrawal that keeps leverage and stays inside the facade's
55
- * `debtLimits`, and the net value an exit hands over. They are reported together
56
- * because a withdraw form needs both — the range it may offer, and the one
57
- * amount past it that is allowed — and because the distance between them is
58
- * the account's own, not a constant a caller could assume.
54
+ * partial withdrawal that keeps leverage, and the net value an exit hands
55
+ * over. They are reported together because a withdraw form needs both — the
56
+ * range it may offer, and the one amount past it that is allowed — and
57
+ * because the distance between them is the account's own, not a constant a
58
+ * caller could assume.
59
59
  *
60
- * Takes no target health factor, unlike {@link maxWithdrawCollateral}: a
61
- * proportional withdrawal leaves the factor where it found it, and the
62
- * facade's `minDebt` is what bounds it.
60
+ * Two rules bound the partial end and both are reported: the facade's
61
+ * `debtLimits` as `partial`, and the safe-price collateral check on top of
62
+ * it as `safePartial`. The second is the one to offer — see
63
+ * {@link WithdrawCeilings}.
63
64
  *
64
- * @param props - Account slice and the SDK holding its market
65
- * @returns The two ceilings, see {@link WithdrawCeilings} for the gap between
66
- * them
65
+ * Takes no target health factor, unlike {@link maxWithdrawCollateral}. A
66
+ * proportional withdrawal leaves the factor where it found it, so there is
67
+ * no room to choose: what these answer to is the facade's own threshold,
68
+ * which is also what {@link startIntent} refuses against.
69
+ *
70
+ * @param props - Account slice, the SDK holding its market, and optionally
71
+ * the collateral the withdrawal would be funded from
72
+ * @returns The three limits, see {@link WithdrawCeilings} for the gap
73
+ * between them
67
74
  */
68
75
  maxWithdraw(props) {
69
- const view = require_onchain_accounts_intents_view.accountView(props.creditAccount, props.sdk);
70
- return {
71
- partial: require_onchain_accounts_intents_math.maxProportionalWithdrawal(view, view.debtLimits),
72
- exit: view.collateral > 0n ? view.collateral : 0n
73
- };
76
+ return require_onchain_accounts_intents_withdraw_limits.withdrawLimits(props);
74
77
  }
75
78
  /**
76
79
  * Debt a `REPAY` would have to cover to settle the account, in underlying
@@ -1,22 +1,18 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_onchain_utils_bigint_math = require("../../utils/bigint-math.js");
3
- const require_onchain_constants_math = require("../../constants/math.js");
3
+ require("../../constants/math.js");
4
4
  require("../../utils/index.js");
5
5
  const require_onchain_accounts_intents_utils_common = require("./utils/common.js");
6
+ const require_onchain_accounts_intents_collateral_money = require("./collateral-money.js");
6
7
  //#region src/onchain/accounts/intents/maxWithdrawCollateral.ts
7
8
  /**
8
9
  * Largest amount of one collateral the account can withdraw while its health
9
10
  * factor stays at or above `targetHF`.
10
11
  *
11
12
  * This is the collateral check solved for one balance, and it counts what that
12
- * check counts: a holding backed by a quota contributes the lesser of the
13
- * quota and its threshold-weighted value, an unquoted one — the underlying —
14
- * its weighted value alone, and dust or a disabled balance nothing at all.
15
- * Collateral is valued at the protocol safe price (`min` of the two feeds,
16
- * 0 when there is no reserve), the way the facade values a call that hands
17
- * funds over; the underlying is exempt and is valued at the main feed, as
18
- * `CreditManagerV3._safeConvertToUSD` does. The debt is valued at the main
19
- * feed, as the check does. Zero debt frees the whole balance.
13
+ * check counts — see {@link collateralMoney} for the valuation, safe prices
14
+ * included. The debt is valued at the main feed, as the check does. Zero debt
15
+ * frees the whole balance.
20
16
  *
21
17
  * Rounding always favours the account, so the answer clears the check rather
22
18
  * than landing a wei short of it.
@@ -27,49 +23,27 @@ const require_onchain_accounts_intents_utils_common = require("./utils/common.js
27
23
  **/
28
24
  function maxWithdrawCollateral(props) {
29
25
  const { creditAccount, sdk, token, targetHF } = props;
30
- const { market, creditManager } = sdk.marketRegister.findCreditManager(creditAccount.creditManager);
31
- const { priceOracle } = market;
32
- const { pqk } = market.pool;
33
- const underlying = market.pool.underlying;
34
26
  const target = creditAccount.tokens.find((t) => require_onchain_accounts_intents_utils_common.eq(t.token, token));
35
27
  if (!target || target.balance <= 10n) return 0n;
36
28
  if (creditAccount.totalDebt === 0n) return target.balance;
37
- const masked = creditAccount.enabledTokensMask !== 0n;
38
- const counts = (t) => t.balance > 10n && (!masked || (t.mask & creditAccount.enabledTokensMask) !== 0n);
39
- /** What a holding backs, in the check's units: USD × PERCENTAGE_FACTOR. */
40
- const weigh = (t) => {
41
- const lt = BigInt(creditManager.liquidationThresholds.get(t.token) ?? 0);
42
- const weighted = (require_onchain_accounts_intents_utils_common.eq(t.token, underlying) ? usd(priceOracle, t.token, t.balance) ?? 0n : priceOracle.safeConvertMinUSD(t.token, t.balance).value) * lt;
43
- if (t.quota === 0n) return weighted;
44
- return require_onchain_utils_bigint_math.BigIntMath.min(quotaUsd(t) * require_onchain_constants_math.PERCENTAGE_FACTOR, weighted);
45
- };
46
- /** A quota is underlying-denominated, and a closed market backs nothing. */
47
- const quotaUsd = (t) => pqk.hasActiveQuota(t.token) ? usd(priceOracle, underlying, t.quota) ?? 0n : 0n;
29
+ const money = require_onchain_accounts_intents_collateral_money.collateralMoney(creditAccount, sdk);
48
30
  let otherMoney = 0n;
49
31
  for (const t of creditAccount.tokens) {
50
- if (require_onchain_accounts_intents_utils_common.eq(t.token, token) || !counts(t)) continue;
51
- otherMoney += weigh(t);
32
+ if (require_onchain_accounts_intents_utils_common.eq(t.token, token) || !money.counts(t)) continue;
33
+ otherMoney += money.weigh(t);
52
34
  }
53
- const borrowed = usd(priceOracle, underlying, creditAccount.totalDebt);
35
+ const borrowed = money.mainUsd(money.underlying, creditAccount.totalDebt);
54
36
  if (borrowed === void 0 || borrowed <= 0n) return 0n;
55
37
  const required = borrowed * targetHF;
56
38
  if (required <= otherMoney) return target.balance;
57
39
  const shortfall = required - otherMoney;
58
- if (target.quota > 0n && quotaUsd(target) * 10000n < shortfall) return 0n;
59
- const targetLt = BigInt(creditManager.liquidationThresholds.get(target.token) ?? 0);
60
- const targetUsd = require_onchain_accounts_intents_utils_common.eq(target.token, underlying) ? usd(priceOracle, target.token, target.balance) ?? 0n : priceOracle.safeConvertMinUSD(target.token, target.balance).value;
40
+ if (target.quota > 0n && money.quotaMoney(target) < shortfall) return 0n;
41
+ const targetLt = money.lt(target.token);
42
+ const targetUsd = money.checkedUsd(target);
61
43
  if (targetLt === 0n || targetUsd === 0n) return 0n;
62
44
  const keptUsd = require_onchain_utils_bigint_math.BigIntMath.ceilDiv(shortfall, targetLt);
63
45
  const kept = require_onchain_utils_bigint_math.BigIntMath.ceilDiv(target.balance * keptUsd, targetUsd);
64
46
  return kept >= target.balance ? 0n : target.balance - kept;
65
47
  }
66
- /** USD value at the main feed, or `undefined` when the token has no price. */
67
- function usd(oracle, token, amount) {
68
- try {
69
- return oracle.convertToUSD(token, amount);
70
- } catch {
71
- return;
72
- }
73
- }
74
48
  //#endregion
75
49
  exports.maxWithdrawCollateral = maxWithdrawCollateral;
@@ -12,6 +12,7 @@ const require_onchain_accounts_intents_utils_price_impact = require("./utils/pri
12
12
  const require_onchain_accounts_intents_utils_quotas_for_update = require("./utils/quotas-for-update.js");
13
13
  const require_onchain_accounts_intents_utils_router_path = require("./utils/router-path.js");
14
14
  const require_onchain_accounts_intents_operations = require("./operations.js");
15
+ const require_onchain_accounts_intents_withdraw_limits = require("./withdraw-limits.js");
15
16
  //#region src/onchain/accounts/intents/realize.ts
16
17
  /**
17
18
  * Turns a plan into operations: the one place that talks to the router, knows
@@ -320,11 +321,18 @@ async function realize(steps, props) {
320
321
  totalValue: projected.totalValue
321
322
  };
322
323
  const projection = sdk.positions.projection(snapshot, { availableLiquidityChange: creditAccount.totalDebt - debt });
323
- require_onchain_accounts_intents_guards.assertCollateralised(sdk.positions.healthFactor({
324
+ const settled = {
324
325
  ...snapshot,
325
326
  assets,
326
327
  totalValue: floor.totalValue
327
- }, { safePrices: withdrawsCollateral }), withdrawsCollateral);
328
+ };
329
+ require_onchain_accounts_intents_guards.assertCollateralised(sdk.positions.healthFactor(settled, { safePrices: withdrawsCollateral }), withdrawsCollateral, () => ({
330
+ atMainPrices: sdk.positions.healthFactor(settled, { safePrices: false }),
331
+ withdrawable: require_onchain_validation_helpers_token.toTokenAmount(sdk, underlying, require_onchain_accounts_intents_withdraw_limits.withdrawLimits({
332
+ creditAccount,
333
+ sdk
334
+ }).safePartial)
335
+ }));
328
336
  const priceImpact = await require_onchain_accounts_intents_utils_price_impact.collectPriceImpact(probes, {
329
337
  totalValue: projected.totalValue,
330
338
  netValue: projected.totalValue - debt,
@@ -8,8 +8,8 @@ const require_onchain_accounts_intents_utils_common = require("./utils/common.js
8
8
  const require_onchain_accounts_intents_utils_router_path = require("./utils/router-path.js");
9
9
  const require_onchain_accounts_intents_plan = require("./plan.js");
10
10
  const require_onchain_accounts_intents_operations = require("./operations.js");
11
- const require_onchain_accounts_intents_realize = require("./realize.js");
12
11
  const require_onchain_accounts_intents_view = require("./view.js");
12
+ const require_onchain_accounts_intents_realize = require("./realize.js");
13
13
  //#region src/onchain/accounts/intents/tail.ts
14
14
  /**
15
15
  * The second half of a delayed intent: the claim, then whatever the intent
@@ -0,0 +1,97 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_onchain_utils_bigint_math = require("../../utils/bigint-math.js");
3
+ require("../../utils/index.js");
4
+ const require_onchain_validation_helpers_health_factor_limits = require("../../validation/helpers/health-factor-limits.js");
5
+ require("../../validation/index.js");
6
+ const require_onchain_accounts_intents_utils_common = require("./utils/common.js");
7
+ const require_onchain_accounts_intents_collateral_money = require("./collateral-money.js");
8
+ const require_onchain_accounts_intents_math = require("./math.js");
9
+ const require_onchain_accounts_intents_view = require("./view.js");
10
+ //#region src/onchain/accounts/intents/withdraw-limits.ts
11
+ /**
12
+ * Every limit a `WITHDRAW` answers to, in underlying units.
13
+ *
14
+ * The one place they are assembled, so the figure a form is offered and the
15
+ * figure the collateral guard names when it turns a withdrawal down cannot
16
+ * drift apart: `CreditAccountOperationsService` reports this, and the guard
17
+ * quotes it back.
18
+ *
19
+ * @param props - Account slice, the SDK holding its market, and optionally the
20
+ * collateral the withdrawal would be funded from
21
+ * @returns The three limits, see {@link WithdrawCeilings}
22
+ **/
23
+ function withdrawLimits(props) {
24
+ const { creditAccount, sdk } = props;
25
+ const view = require_onchain_accounts_intents_view.accountView(creditAccount, sdk);
26
+ const partial = require_onchain_accounts_intents_math.maxProportionalWithdrawal(view, view.debtLimits);
27
+ const safe = maxSafeWithdrawal({
28
+ ...props,
29
+ targetHF: BigInt(require_onchain_validation_helpers_health_factor_limits.MIN_HEALTH_FACTOR_FACADE)
30
+ });
31
+ return {
32
+ partial,
33
+ safePartial: require_onchain_utils_bigint_math.BigIntMath.min(partial, safe),
34
+ exit: view.collateral > 0n ? view.collateral : 0n
35
+ };
36
+ }
37
+ /**
38
+ * Largest proportional withdrawal the safe-price collateral check still clears,
39
+ * in underlying units.
40
+ *
41
+ * A withdrawal hands funds over, so the facade weighs the account it leaves
42
+ * behind at safe prices rather than main ones — see {@link collateralMoney}.
43
+ * That is a second limit on top of the facade's `debtLimits`, and the two are
44
+ * independent: a caller wanting the amount a form may actually offer takes the
45
+ * lesser of this and `maxProportionalWithdrawal`.
46
+ *
47
+ * The arithmetic is the check solved for the amount. Taking `W` out at fixed
48
+ * leverage repays `dD = D·W/C`, so `W·TVL/C` of value is sold out of the source
49
+ * token; each dollar of that sale costs the check the source's threshold times
50
+ * its safe-to-main price ratio, while the repayment relieves `targetHF` per
51
+ * dollar of debt. Both terms are linear in `W`, which is why one division
52
+ * answers instead of a search — and why the answer is exact rather than a
53
+ * bound, as long as the plan really does fund itself from `sourceToken`.
54
+ *
55
+ * Two consequences worth stating, because they surprise:
56
+ *
57
+ * - An account whose collateral is entirely a token the reserve feed marks
58
+ * down cannot withdraw at all once it is under the threshold. A proportional
59
+ * withdrawal scales collateral and debt together, so it leaves the safe-price
60
+ * factor exactly where it found it — no amount climbs back over.
61
+ * - Leaving entirely is never refused for this reason: the exit settles the
62
+ * debt instead of shrinking it, and a check with no debt to divide by has
63
+ * nothing to refuse.
64
+ *
65
+ * @returns Amount in underlying units. The account's net value when safe prices
66
+ * do not limit the withdrawal at all, so the caller's `min` is a no-op; `0n`
67
+ * when the account already sits below `targetHF` at safe prices, and only the
68
+ * exit is left
69
+ **/
70
+ function maxSafeWithdrawal(props) {
71
+ const { creditAccount, sdk, targetHF } = props;
72
+ const view = require_onchain_accounts_intents_view.accountView(creditAccount, sdk);
73
+ if (view.collateral <= 0n) return 0n;
74
+ if (view.debt === 0n) return view.collateral;
75
+ const money = require_onchain_accounts_intents_collateral_money.collateralMoney(creditAccount, sdk);
76
+ const source = props.sourceToken ?? view.fattest();
77
+ const holding = source === void 0 ? void 0 : creditAccount.tokens.find((t) => require_onchain_accounts_intents_utils_common.eq(t.token, source));
78
+ if (!holding) return view.collateral;
79
+ let total = 0n;
80
+ for (const t of creditAccount.tokens) if (money.counts(t)) total += money.weigh(t);
81
+ const debtUsd = money.mainUsd(money.underlying, view.debt);
82
+ if (debtUsd === void 0 || debtUsd <= 0n) return view.collateral;
83
+ const slack = total - debtUsd * targetHF;
84
+ if (slack < 0n) return 0n;
85
+ const sourceMainUsd = money.mainUsd(holding.token, holding.balance);
86
+ if (sourceMainUsd === void 0 || sourceMainUsd <= 0n) return view.collateral;
87
+ const sourceRate = money.lt(holding.token) * money.checkedUsd(holding);
88
+ const tvlUsd = money.mainUsd(money.underlying, view.collateral + view.debt);
89
+ if (tvlUsd === void 0) return view.collateral;
90
+ const drain = sourceRate * tvlUsd - targetHF * debtUsd * sourceMainUsd;
91
+ if (drain <= 0n) return view.collateral;
92
+ const limit = view.collateral * slack * sourceMainUsd / drain;
93
+ return limit < view.collateral ? limit : view.collateral;
94
+ }
95
+ //#endregion
96
+ exports.maxSafeWithdrawal = maxSafeWithdrawal;
97
+ exports.withdrawLimits = withdrawLimits;
@@ -213,6 +213,7 @@ const require_onchain_validation_checks_checkPoolPaused = require("./validation/
213
213
  const require_onchain_validation_checks_checkPoolSunset = require("./validation/checks/checkPoolSunset.js");
214
214
  const require_onchain_validation_checks_checkQuotaCount = require("./validation/checks/checkQuotaCount.js");
215
215
  const require_onchain_validation_checks_checkQuotaLimit = require("./validation/checks/checkQuotaLimit.js");
216
+ const require_onchain_validation_checks_checkReservePriceLimited = require("./validation/checks/checkReservePriceLimited.js");
216
217
  const require_onchain_validation_bundles_checkAccountQuotas = require("./validation/bundles/checkAccountQuotas.js");
217
218
  const require_onchain_validation_bundles_checkWalletAllowance = require("./validation/bundles/checkWalletAllowance.js");
218
219
  const require_onchain_validation_bundles_checkWalletBalance = require("./validation/bundles/checkWalletBalance.js");
@@ -586,6 +587,7 @@ exports.checkQuotaCount = require_onchain_validation_checks_checkQuotaCount.chec
586
587
  exports.checkQuotaLimit = require_onchain_validation_checks_checkQuotaLimit.checkQuotaLimit;
587
588
  exports.checkRWAOpenRequirements = require_onchain_validation_bundles_checkRWAOpenRequirements.checkRWAOpenRequirements;
588
589
  exports.checkRWAOpening = require_onchain_validation_bundles_checkRWAOpening.checkRWAOpening;
590
+ exports.checkReservePriceLimited = require_onchain_validation_checks_checkReservePriceLimited.checkReservePriceLimited;
589
591
  exports.checkSimulation = require_onchain_validation_checkSimulation.checkSimulation;
590
592
  exports.checkWallet = require_onchain_validation_bundles_checkWallet.checkWallet;
591
593
  exports.checkWalletAllowance = require_onchain_validation_bundles_checkWalletAllowance.checkWalletAllowance;
@@ -20,7 +20,7 @@ const adapterConstructorAbi = {
20
20
  ["INFINIFI_GATEWAY"]: { 310: require_onchain_market_adapters_abi_conctructorAbiPatterns.BASIC_ADAPTER_ABI },
21
21
  ["LIDO_V1"]: { 310: require_onchain_market_adapters_abi_conctructorAbiPatterns.BASIC_ADAPTER_ABI },
22
22
  ["LIDO_WSTETH_V1"]: { 310: require_onchain_market_adapters_abi_conctructorAbiPatterns.BASIC_ADAPTER_ABI },
23
- ["MIDAS_GATEWAY"]: { 311: require_onchain_market_adapters_abi_conctructorAbiPatterns.REFERER_ID_ADAPTER_ABI },
23
+ ["MIDAS_GATEWAY"]: { 311: require_onchain_market_adapters_abi_conctructorAbiPatterns.BASIC_ADAPTER_ABI },
24
24
  ["MIDAS_REDEMPTION_VAULT"]: {
25
25
  310: require_onchain_market_adapters_abi_conctructorAbiPatterns.BASIC_ADAPTER_ABI,
26
26
  311: require_onchain_market_adapters_abi_conctructorAbiPatterns.BASIC_ADAPTER_ABI
@@ -0,0 +1,30 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_model_errors_operation_errors = require("../../../model/errors/operation-errors.js");
3
+ require("../../../model/index.js");
4
+ //#region src/onchain/validation/checks/checkReservePriceLimited.ts
5
+ /**
6
+ * Whether a failed collateral check is the reserve price feed's doing.
7
+ *
8
+ * A call that hands funds over is weighed at safe prices — `min` of a token's
9
+ * two feeds, and nothing at all where governance registered no reserve feed —
10
+ * so an account that covers its debt at the main feed can still be refused.
11
+ * The two are worth telling apart: a position that is genuinely too small is
12
+ * fixed by adding collateral or requesting less, while this one is a valuation
13
+ * the account does not control, and requesting less only helps as far as
14
+ * `withdrawable` says it does.
15
+ *
16
+ * Runs after `checkCollateralised` and answers only when that one refused, so
17
+ * the caller keeps its own threshold rather than restating it here.
18
+ */
19
+ function checkReservePriceLimited(args) {
20
+ const { healthFactor, atMainPrices, healthFactorThreshold, withdrawable } = args;
21
+ if (healthFactor >= healthFactorThreshold || atMainPrices < healthFactorThreshold) return [];
22
+ return [require_model_errors_operation_errors.reservePriceLimited({
23
+ healthFactor,
24
+ atMainPrices,
25
+ healthFactorThreshold,
26
+ withdrawable
27
+ })];
28
+ }
29
+ //#endregion
30
+ exports.checkReservePriceLimited = checkReservePriceLimited;
@@ -14,6 +14,7 @@ const require_onchain_validation_checks_checkPoolPaused = require("./checkPoolPa
14
14
  const require_onchain_validation_checks_checkPoolSunset = require("./checkPoolSunset.js");
15
15
  const require_onchain_validation_checks_checkQuotaCount = require("./checkQuotaCount.js");
16
16
  const require_onchain_validation_checks_checkQuotaLimit = require("./checkQuotaLimit.js");
17
+ const require_onchain_validation_checks_checkReservePriceLimited = require("./checkReservePriceLimited.js");
17
18
  exports.checkBorrowLimit = require_onchain_validation_checks_checkBorrowLimit.checkBorrowLimit;
18
19
  exports.checkCollateralised = require_onchain_validation_checks_checkCollateralised.checkCollateralised;
19
20
  exports.checkCreditAccountFrozen = require_onchain_validation_checks_checkCreditAccountFrozen.checkCreditAccountFrozen;
@@ -29,3 +30,4 @@ exports.checkPoolPaused = require_onchain_validation_checks_checkPoolPaused.chec
29
30
  exports.checkPoolSunset = require_onchain_validation_checks_checkPoolSunset.checkPoolSunset;
30
31
  exports.checkQuotaCount = require_onchain_validation_checks_checkQuotaCount.checkQuotaCount;
31
32
  exports.checkQuotaLimit = require_onchain_validation_checks_checkQuotaLimit.checkQuotaLimit;
33
+ exports.checkReservePriceLimited = require_onchain_validation_checks_checkReservePriceLimited.checkReservePriceLimited;
@@ -18,6 +18,7 @@ const require_onchain_validation_checks_checkPoolPaused = require("./checks/chec
18
18
  const require_onchain_validation_checks_checkPoolSunset = require("./checks/checkPoolSunset.js");
19
19
  const require_onchain_validation_checks_checkQuotaCount = require("./checks/checkQuotaCount.js");
20
20
  const require_onchain_validation_checks_checkQuotaLimit = require("./checks/checkQuotaLimit.js");
21
+ const require_onchain_validation_checks_checkReservePriceLimited = require("./checks/checkReservePriceLimited.js");
21
22
  require("./checks/index.js");
22
23
  const require_onchain_validation_bundles_checkAccountQuotas = require("./bundles/checkAccountQuotas.js");
23
24
  const require_onchain_validation_bundles_checkWalletAllowance = require("./bundles/checkWalletAllowance.js");
@@ -77,6 +78,7 @@ exports.checkQuotaCount = require_onchain_validation_checks_checkQuotaCount.chec
77
78
  exports.checkQuotaLimit = require_onchain_validation_checks_checkQuotaLimit.checkQuotaLimit;
78
79
  exports.checkRWAOpenRequirements = require_onchain_validation_bundles_checkRWAOpenRequirements.checkRWAOpenRequirements;
79
80
  exports.checkRWAOpening = require_onchain_validation_bundles_checkRWAOpening.checkRWAOpening;
81
+ exports.checkReservePriceLimited = require_onchain_validation_checks_checkReservePriceLimited.checkReservePriceLimited;
80
82
  exports.checkSimulation = require_onchain_validation_checkSimulation.checkSimulation;
81
83
  exports.checkWallet = require_onchain_validation_bundles_checkWallet.checkWallet;
82
84
  exports.checkWalletAllowance = require_onchain_validation_bundles_checkWalletAllowance.checkWalletAllowance;
@@ -0,0 +1,107 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_onchain_utils_AddressMap = require("../../onchain/utils/AddressMap.js");
3
+ const require_onchain_chain_chains = require("../../onchain/chain/chains.js");
4
+ const require_onchain_constants_address_provider = require("../../onchain/constants/address-provider.js");
5
+ const require_onchain_utils_hex = require("../../onchain/utils/hex.js");
6
+ const require_onchain_plugins_BasePlugin = require("../../onchain/plugins/BasePlugin.js");
7
+ require("../../onchain/index.js");
8
+ const require_abi_310_iBytecodeRepository = require("../../abi/310/iBytecodeRepository.js");
9
+ const require_plugins_bots_abi_iPartialLiquidationBotV310 = require("./abi/iPartialLiquidationBotV310.js");
10
+ const require_plugins_bots_config = require("./config.js");
11
+ const require_plugins_bots_types = require("./types.js");
12
+ const require_plugins_bots_PartialLiquidationBotV310Contract = require("./PartialLiquidationBotV310Contract.js");
13
+ let viem = require("viem");
14
+ //#region src/plugins/bots/BotsPlugin.ts
15
+ var BotsPlugin = class extends require_onchain_plugins_BasePlugin.BasePlugin {
16
+ #bots;
17
+ get loaded() {
18
+ return !!this.#bots;
19
+ }
20
+ get bots() {
21
+ return this.#bots?.values() ?? [];
22
+ }
23
+ async load(force) {
24
+ if (!force && this.loaded) return this.state;
25
+ const treasury = this.sdk.addressProvider.getAddress(require_onchain_constants_address_provider.AP_TREASURY);
26
+ const bcr = this.sdk.addressProvider.getAddress(require_onchain_constants_address_provider.AP_BYTECODE_REPOSITORY);
27
+ const configs = require_plugins_bots_config.PARTIAL_LIQUIDATION_BOT_CONFIGS[this.sdk.networkType] ?? [];
28
+ this.#bots = new require_onchain_utils_AddressMap.AddressMap();
29
+ if (!configs.length) return this.state;
30
+ const deployedBots = await this.client.multicall({
31
+ contracts: configs.map((config) => ({
32
+ address: bcr,
33
+ abi: require_abi_310_iBytecodeRepository.iBytecodeRepositoryAbi,
34
+ functionName: "computeAddress",
35
+ args: [
36
+ (0, viem.stringToHex)(require_plugins_bots_types.BOT_PARTIAL_LIQUIDATION, { size: 32 }),
37
+ 310,
38
+ (0, viem.encodeAbiParameters)(require_plugins_bots_types.BOT_PARAMS_ABI, [
39
+ treasury,
40
+ config.minHealthFactor,
41
+ config.maxHealthFactor,
42
+ config.premiumScaleFactor,
43
+ config.feeScaleFactor
44
+ ]),
45
+ (0, viem.stringToHex)(require_plugins_bots_config.PARTIAL_LIQUIDATION_BOT_SALT, { size: 32 }),
46
+ require_plugins_bots_config.PARTIAL_LIQUIDATION_BOT_DEPLOYER
47
+ ]
48
+ })),
49
+ allowFailure: true,
50
+ blockNumber: this.sdk.currentBlock,
51
+ batchSize: 0
52
+ });
53
+ const expectedBots = new require_onchain_utils_AddressMap.AddressMap();
54
+ for (let i = 0; i < configs.length; i++) {
55
+ const b = deployedBots[i];
56
+ const { minHealthFactor, maxHealthFactor } = configs[i];
57
+ if (b.status === "success") {
58
+ expectedBots.upsert(b.result, {
59
+ ...configs[i],
60
+ treasury
61
+ });
62
+ this.logger?.debug(`expected bot [${minHealthFactor}, ${maxHealthFactor}] at ${b.result}`);
63
+ } else this.logger?.error(`failed compute address for bot [${minHealthFactor}, ${maxHealthFactor}]`, b.error);
64
+ }
65
+ const botAddrs = expectedBots.keys();
66
+ const serializedBots = await this.client.multicall({
67
+ contracts: botAddrs.map((address) => ({
68
+ address,
69
+ abi: require_plugins_bots_abi_iPartialLiquidationBotV310.iPartialLiquidationBotV310Abi,
70
+ functionName: "serialize"
71
+ })),
72
+ allowFailure: true,
73
+ blockNumber: this.sdk.currentBlock,
74
+ batchSize: 0
75
+ });
76
+ for (let i = 0; i < botAddrs.length; i++) {
77
+ const serialized = serializedBots[i];
78
+ const expected = expectedBots.mustGet(botAddrs[i]);
79
+ if (serialized.status === "success") {
80
+ const bot = new require_plugins_bots_PartialLiquidationBotV310Contract.PartialLiquidationBotV310Contract(this.sdk, {
81
+ addr: botAddrs[i],
82
+ version: BigInt(310),
83
+ contractType: require_plugins_bots_types.BOT_PARTIAL_LIQUIDATION,
84
+ serializedParams: serialized.result
85
+ });
86
+ if (!require_onchain_utils_hex.hexEq(treasury, expected.treasury) || bot.minHealthFactor !== expected.minHealthFactor || bot.maxHealthFactor !== expected.maxHealthFactor || bot.premiumScaleFactor !== expected.premiumScaleFactor || bot.feeScaleFactor !== expected.feeScaleFactor) this.logger?.error(`serialized bot ${botAddrs[i]} does not match expected bot`, serialized.error);
87
+ else this.#bots.upsert(botAddrs[i], bot);
88
+ }
89
+ }
90
+ return this.state;
91
+ }
92
+ stateHuman(raw) {
93
+ return { bots: this.#bots?.values().map((bot) => bot.stateHuman(raw)) ?? [] };
94
+ }
95
+ get state() {
96
+ return { bots: this.#bots?.values().map((bot) => bot.state) ?? [] };
97
+ }
98
+ hydrate(state) {
99
+ this.#bots = new require_onchain_utils_AddressMap.AddressMap();
100
+ for (const botState of state.bots) this.#bots.upsert(botState.addr, new require_plugins_bots_PartialLiquidationBotV310Contract.PartialLiquidationBotV310Contract(this.sdk, botState));
101
+ }
102
+ static getMigrationBotData(chainId) {
103
+ return chainId === require_onchain_chain_chains.chains.Mainnet.id ? require_plugins_bots_config.LEGACY_MIGRATION_BOT : void 0;
104
+ }
105
+ };
106
+ //#endregion
107
+ exports.BotsPlugin = BotsPlugin;