@gearbox-protocol/sdk 17.13.0-next.2 → 17.13.0-next.3

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 (101) hide show
  1. package/dist/cjs/model/errors/index.js +3 -0
  2. package/dist/cjs/model/errors/operation-errors.js +27 -0
  3. package/dist/cjs/model/index.js +3 -0
  4. package/dist/cjs/onchain/accounts/intents/index.js +1 -0
  5. package/dist/cjs/onchain/accounts/intents/operations.js +1 -1
  6. package/dist/cjs/onchain/accounts/intents/plan.js +21 -0
  7. package/dist/cjs/onchain/accounts/intents/realize.js +29 -7
  8. package/dist/cjs/onchain/accounts/intents/resolveQuotaUpdate.js +146 -0
  9. package/dist/cjs/onchain/accounts/intents/tests/update-quota.fixtures.js +102 -0
  10. package/dist/cjs/onchain/accounts/intents/utils/index.js +1 -0
  11. package/dist/cjs/onchain/accounts/intents/utils/quotas-for-update.js +28 -10
  12. package/dist/cjs/onchain/constants/index.js +1 -0
  13. package/dist/cjs/onchain/constants/math.js +6 -0
  14. package/dist/cjs/onchain/index.js +9 -0
  15. package/dist/cjs/onchain/positions/calcHealthFactor.js +1 -1
  16. package/dist/cjs/onchain/preview/preview/CreditAccountState.js +4 -2
  17. package/dist/cjs/onchain/validation/bundles/checkCreditOperation.js +2 -0
  18. package/dist/cjs/onchain/validation/bundles/checkQuotaUpdates.js +45 -0
  19. package/dist/cjs/onchain/validation/bundles/index.js +2 -0
  20. package/dist/cjs/onchain/validation/checks/checkMaxQuota.js +18 -0
  21. package/dist/cjs/onchain/validation/checks/checkQuotaActive.js +10 -0
  22. package/dist/cjs/onchain/validation/checks/checkQuotaChange.js +18 -0
  23. package/dist/cjs/onchain/validation/checks/index.js +6 -0
  24. package/dist/cjs/onchain/validation/index.js +8 -0
  25. package/dist/cjs/sdk/prepare/PrepareApi.js +10 -0
  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 +25 -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/index.js +2 -1
  34. package/dist/esm/onchain/accounts/intents/operations.js +1 -1
  35. package/dist/esm/onchain/accounts/intents/plan.js +22 -2
  36. package/dist/esm/onchain/accounts/intents/realize.js +29 -7
  37. package/dist/esm/onchain/accounts/intents/resolveQuotaUpdate.js +145 -0
  38. package/dist/esm/onchain/accounts/intents/tests/update-quota.fixtures.js +92 -0
  39. package/dist/esm/onchain/accounts/intents/utils/index.js +2 -2
  40. package/dist/esm/onchain/accounts/intents/utils/quotas-for-update.js +28 -11
  41. package/dist/esm/onchain/accounts/liquidations/LiquidationsService.js +1 -1
  42. package/dist/esm/onchain/accounts/withdrawal-compressor/RedemptionLoggerV310Contract.js +1 -1
  43. package/dist/esm/onchain/accounts/withdrawal-compressor/WithdrawalCompressorV310Contract.js +1 -1
  44. package/dist/esm/onchain/accounts/withdrawal-compressor/WithdrawalCompressorV311Contract.js +1 -1
  45. package/dist/esm/onchain/accounts/withdrawal-compressor/WithdrawalCompressorV313Contract.js +1 -1
  46. package/dist/esm/onchain/base/TokensMeta.js +3 -3
  47. package/dist/esm/onchain/constants/index.js +2 -2
  48. package/dist/esm/onchain/constants/math.js +6 -1
  49. package/dist/esm/onchain/core/createAddressProvider.js +1 -1
  50. package/dist/esm/onchain/index.js +6 -2
  51. package/dist/esm/onchain/market/adapters/contracts/AccountMigratorAdapterContract.js +1 -1
  52. package/dist/esm/onchain/market/adapters/contracts/ERC4626AdapterContract.js +1 -1
  53. package/dist/esm/onchain/market/credit/CreditFacadeV310BaseContract.js +1 -1
  54. package/dist/esm/onchain/market/pool/PoolV310Contract.js +1 -1
  55. package/dist/esm/onchain/market/rwa/createDegenNFT.js +1 -1
  56. package/dist/esm/onchain/market/zapper/IETHZapperContract.js +1 -1
  57. package/dist/esm/onchain/market/zapper/ZapperContract.js +1 -1
  58. package/dist/esm/onchain/positions/calcHealthFactor.js +1 -1
  59. package/dist/esm/onchain/preview/preview/CreditAccountState.js +4 -2
  60. package/dist/esm/onchain/preview/preview/previewPoolPositionOperation.js +2 -2
  61. package/dist/esm/onchain/utils/viem/simulateWithPriceUpdates.js +1 -1
  62. package/dist/esm/onchain/validation/bundles/checkCreditOperation.js +2 -0
  63. package/dist/esm/onchain/validation/bundles/checkQuotaUpdates.js +44 -0
  64. package/dist/esm/onchain/validation/bundles/index.js +2 -1
  65. package/dist/esm/onchain/validation/checks/checkMaxQuota.js +17 -0
  66. package/dist/esm/onchain/validation/checks/checkQuotaActive.js +9 -0
  67. package/dist/esm/onchain/validation/checks/checkQuotaChange.js +17 -0
  68. package/dist/esm/onchain/validation/checks/index.js +4 -1
  69. package/dist/esm/onchain/validation/index.js +5 -1
  70. package/dist/esm/sdk/prepare/PrepareApi.js +10 -0
  71. package/dist/types/model/errors/index.d.ts +2 -2
  72. package/dist/types/model/errors/operation-errors.d.ts +39 -1
  73. package/dist/types/model/index.d.ts +2 -2
  74. package/dist/types/onchain/accounts/index.d.ts +2 -2
  75. package/dist/types/onchain/accounts/intents/index.d.ts +2 -2
  76. package/dist/types/onchain/accounts/intents/operations.d.ts +9 -3
  77. package/dist/types/onchain/accounts/intents/plan.d.ts +19 -2
  78. package/dist/types/onchain/accounts/intents/resolveQuotaUpdate.d.ts +34 -0
  79. package/dist/types/onchain/accounts/intents/tests/update-quota.fixtures.d.ts +49 -0
  80. package/dist/types/onchain/accounts/intents/types.d.ts +19 -2
  81. package/dist/types/onchain/accounts/intents/utils/index.d.ts +2 -2
  82. package/dist/types/onchain/accounts/intents/utils/quotas-for-update.d.ts +23 -5
  83. package/dist/types/onchain/constants/index.d.ts +2 -2
  84. package/dist/types/onchain/constants/math.d.ts +6 -1
  85. package/dist/types/onchain/index.d.ts +7 -3
  86. package/dist/types/onchain/preview/preview/CreditAccountState.d.ts +2 -1
  87. package/dist/types/onchain/validation/bundles/checkCreditOperation.d.ts +2 -2
  88. package/dist/types/onchain/validation/bundles/checkQuotaUpdates.d.ts +16 -0
  89. package/dist/types/onchain/validation/bundles/index.d.ts +2 -1
  90. package/dist/types/onchain/validation/checks/checkMaxQuota.d.ts +16 -0
  91. package/dist/types/onchain/validation/checks/checkQuotaActive.d.ts +13 -0
  92. package/dist/types/onchain/validation/checks/checkQuotaChange.d.ts +17 -0
  93. package/dist/types/onchain/validation/checks/index.d.ts +4 -1
  94. package/dist/types/onchain/validation/index.d.ts +5 -1
  95. package/dist/types/onchain/validation/raise.d.ts +2 -2
  96. package/dist/types/sdk/execute/types.d.ts +1 -1
  97. package/dist/types/sdk/index.d.ts +2 -2
  98. package/dist/types/sdk/prepare/PrepareApi.d.ts +6 -2
  99. package/dist/types/sdk/prepare/index.d.ts +2 -2
  100. package/dist/types/sdk/prepare/types.d.ts +22 -2
  101. package/package.json +1 -1
@@ -0,0 +1,45 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_onchain_constants_math = require("../../constants/math.js");
3
+ const require_model_errors_operation_errors = require("../../../model/errors/operation-errors.js");
4
+ require("../../../model/index.js");
5
+ const require_onchain_validation_helpers_amount = require("../helpers/amount.js");
6
+ require("../helpers/index.js");
7
+ const require_onchain_validation_checks_checkForbiddenToken = require("../checks/checkForbiddenToken.js");
8
+ const require_onchain_validation_checks_checkMaxQuota = require("../checks/checkMaxQuota.js");
9
+ require("../checks/index.js");
10
+ let viem = require("viem");
11
+ //#region src/onchain/validation/bundles/checkQuotaUpdates.ts
12
+ /**
13
+ * What the facade reverts on in each quota the operation touches: an increase
14
+ * on a forbidden token, an increase on an account that ends with zero debt, and
15
+ * a resulting quota above `MAX_QUOTA_MULTIPLIER × maxDebt`.
16
+ */
17
+ function checkQuotaUpdates(suite, preview, underlying) {
18
+ const isAdjust = preview.operation === "AdjustCreditAccount";
19
+ const changes = (isAdjust ? preview.quotasChange : preview.quotas).filter((q) => q.value !== 0n);
20
+ const increases = changes.filter((q) => q.value > 0n);
21
+ const { minDebt, maxDebt } = suite.creditFacade;
22
+ const maxQuota = require_onchain_constants_math.MAX_QUOTA_MULTIPLIER * maxDebt;
23
+ const forbidden = increases.flatMap((q) => require_onchain_validation_checks_checkForbiddenToken.checkForbiddenToken({
24
+ token: q.token,
25
+ isForbidden: suite.isForbidden(q.token.address)
26
+ }));
27
+ const isZeroDebt = isAdjust && increases.length > 0 && preview.totalDebt.value === 0n ? [require_model_errors_operation_errors.debtOutOfRange({
28
+ requested: require_onchain_validation_helpers_amount.amountOf(underlying, 0n),
29
+ minDebt: require_onchain_validation_helpers_amount.amountOf(underlying, minDebt),
30
+ maxDebt: require_onchain_validation_helpers_amount.amountOf(underlying, maxDebt)
31
+ })] : [];
32
+ const aboveMax = changes.flatMap((q) => require_onchain_validation_checks_checkMaxQuota.checkMaxQuota({
33
+ token: q.token,
34
+ requested: preview.quotas.find((r) => (0, viem.isAddressEqual)(r.token.address, q.token.address))?.value ?? 0n,
35
+ maxQuota,
36
+ underlying
37
+ }));
38
+ return [
39
+ ...forbidden,
40
+ ...isZeroDebt,
41
+ ...aboveMax
42
+ ];
43
+ }
44
+ //#endregion
45
+ exports.checkQuotaUpdates = checkQuotaUpdates;
@@ -8,6 +8,7 @@ const require_onchain_validation_bundles_checkIncreaseDebt = require("./checkInc
8
8
  const require_onchain_validation_bundles_checkIncreaseQuota = require("./checkIncreaseQuota.js");
9
9
  const require_onchain_validation_bundles_checkMarket = require("./checkMarket.js");
10
10
  const require_onchain_validation_bundles_checkObtained = require("./checkObtained.js");
11
+ const require_onchain_validation_bundles_checkQuotaUpdates = require("./checkQuotaUpdates.js");
11
12
  const require_onchain_validation_bundles_checkMidasAccountGreenlist = require("./checkMidasAccountGreenlist.js");
12
13
  const require_onchain_validation_bundles_checkRWAOpenRequirements = require("./checkRWAOpenRequirements.js");
13
14
  const require_onchain_validation_bundles_checkRWAOpening = require("./checkRWAOpening.js");
@@ -30,6 +31,7 @@ exports.checkMidasAccountGreenlist = require_onchain_validation_bundles_checkMid
30
31
  exports.checkObtained = require_onchain_validation_bundles_checkObtained.checkObtained;
31
32
  exports.checkPoolFunding = require_onchain_validation_bundles_checkPoolFunding.checkPoolFunding;
32
33
  exports.checkPoolOperation = require_onchain_validation_bundles_checkPoolOperation.checkPoolOperation;
34
+ exports.checkQuotaUpdates = require_onchain_validation_bundles_checkQuotaUpdates.checkQuotaUpdates;
33
35
  exports.checkRWAOpenRequirements = require_onchain_validation_bundles_checkRWAOpenRequirements.checkRWAOpenRequirements;
34
36
  exports.checkRWAOpening = require_onchain_validation_bundles_checkRWAOpening.checkRWAOpening;
35
37
  exports.checkWallet = require_onchain_validation_bundles_checkWallet.checkWallet;
@@ -0,0 +1,18 @@
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
+ const require_onchain_validation_helpers_amount = require("../helpers/amount.js");
5
+ require("../helpers/index.js");
6
+ //#region src/onchain/validation/checks/checkMaxQuota.ts
7
+ /** The facade's per-token quota ceiling. */
8
+ function checkMaxQuota(args) {
9
+ const { token, requested, maxQuota, underlying } = args;
10
+ if (requested <= maxQuota) return [];
11
+ return [require_model_errors_operation_errors.quotaAboveMax({
12
+ token,
13
+ requested: require_onchain_validation_helpers_amount.amountOf(underlying, requested),
14
+ maxQuota: require_onchain_validation_helpers_amount.amountOf(underlying, maxQuota)
15
+ })];
16
+ }
17
+ //#endregion
18
+ exports.checkMaxQuota = checkMaxQuota;
@@ -0,0 +1,10 @@
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/checkQuotaActive.ts
5
+ /** A token whose quota the keeper does not manage at all. */
6
+ function checkQuotaActive(args) {
7
+ return args.isActive ? [] : [require_model_errors_operation_errors.quotaInactive(args.token)];
8
+ }
9
+ //#endregion
10
+ exports.checkQuotaActive = checkQuotaActive;
@@ -0,0 +1,18 @@
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
+ const require_onchain_validation_helpers_amount = require("../helpers/amount.js");
5
+ require("../helpers/index.js");
6
+ //#region src/onchain/validation/checks/checkQuotaChange.ts
7
+ /** A quota update that rounds to nothing. */
8
+ function checkQuotaChange(args) {
9
+ const { token, current, requested, change, underlying } = args;
10
+ if (change !== 0n) return [];
11
+ return [require_model_errors_operation_errors.quotaUnchanged({
12
+ token,
13
+ current: require_onchain_validation_helpers_amount.amountOf(underlying, current),
14
+ requested: require_onchain_validation_helpers_amount.amountOf(underlying, requested)
15
+ })];
16
+ }
17
+ //#endregion
18
+ exports.checkQuotaChange = checkQuotaChange;
@@ -9,9 +9,12 @@ const require_onchain_validation_checks_checkForbiddenToken = require("./checkFo
9
9
  const require_onchain_validation_checks_checkLeverage = require("./checkLeverage.js");
10
10
  const require_onchain_validation_checks_checkLiquidatorEligible = require("./checkLiquidatorEligible.js");
11
11
  const require_onchain_validation_checks_checkMarketExpired = require("./checkMarketExpired.js");
12
+ const require_onchain_validation_checks_checkMaxQuota = require("./checkMaxQuota.js");
12
13
  const require_onchain_validation_checks_checkPoolLiquidity = require("./checkPoolLiquidity.js");
13
14
  const require_onchain_validation_checks_checkPoolPaused = require("./checkPoolPaused.js");
14
15
  const require_onchain_validation_checks_checkPoolSunset = require("./checkPoolSunset.js");
16
+ const require_onchain_validation_checks_checkQuotaActive = require("./checkQuotaActive.js");
17
+ const require_onchain_validation_checks_checkQuotaChange = require("./checkQuotaChange.js");
15
18
  const require_onchain_validation_checks_checkQuotaCount = require("./checkQuotaCount.js");
16
19
  const require_onchain_validation_checks_checkQuotaLimit = require("./checkQuotaLimit.js");
17
20
  const require_onchain_validation_checks_checkReservePriceLimited = require("./checkReservePriceLimited.js");
@@ -25,9 +28,12 @@ exports.checkForbiddenToken = require_onchain_validation_checks_checkForbiddenTo
25
28
  exports.checkLeverage = require_onchain_validation_checks_checkLeverage.checkLeverage;
26
29
  exports.checkLiquidatorEligible = require_onchain_validation_checks_checkLiquidatorEligible.checkLiquidatorEligible;
27
30
  exports.checkMarketExpired = require_onchain_validation_checks_checkMarketExpired.checkMarketExpired;
31
+ exports.checkMaxQuota = require_onchain_validation_checks_checkMaxQuota.checkMaxQuota;
28
32
  exports.checkPoolLiquidity = require_onchain_validation_checks_checkPoolLiquidity.checkPoolLiquidity;
29
33
  exports.checkPoolPaused = require_onchain_validation_checks_checkPoolPaused.checkPoolPaused;
30
34
  exports.checkPoolSunset = require_onchain_validation_checks_checkPoolSunset.checkPoolSunset;
35
+ exports.checkQuotaActive = require_onchain_validation_checks_checkQuotaActive.checkQuotaActive;
36
+ exports.checkQuotaChange = require_onchain_validation_checks_checkQuotaChange.checkQuotaChange;
31
37
  exports.checkQuotaCount = require_onchain_validation_checks_checkQuotaCount.checkQuotaCount;
32
38
  exports.checkQuotaLimit = require_onchain_validation_checks_checkQuotaLimit.checkQuotaLimit;
33
39
  exports.checkReservePriceLimited = require_onchain_validation_checks_checkReservePriceLimited.checkReservePriceLimited;
@@ -13,9 +13,12 @@ const require_onchain_validation_checks_checkForbiddenToken = require("./checks/
13
13
  const require_onchain_validation_checks_checkLeverage = require("./checks/checkLeverage.js");
14
14
  const require_onchain_validation_checks_checkLiquidatorEligible = require("./checks/checkLiquidatorEligible.js");
15
15
  const require_onchain_validation_checks_checkMarketExpired = require("./checks/checkMarketExpired.js");
16
+ const require_onchain_validation_checks_checkMaxQuota = require("./checks/checkMaxQuota.js");
16
17
  const require_onchain_validation_checks_checkPoolLiquidity = require("./checks/checkPoolLiquidity.js");
17
18
  const require_onchain_validation_checks_checkPoolPaused = require("./checks/checkPoolPaused.js");
18
19
  const require_onchain_validation_checks_checkPoolSunset = require("./checks/checkPoolSunset.js");
20
+ const require_onchain_validation_checks_checkQuotaActive = require("./checks/checkQuotaActive.js");
21
+ const require_onchain_validation_checks_checkQuotaChange = require("./checks/checkQuotaChange.js");
19
22
  const require_onchain_validation_checks_checkQuotaCount = require("./checks/checkQuotaCount.js");
20
23
  const require_onchain_validation_checks_checkQuotaLimit = require("./checks/checkQuotaLimit.js");
21
24
  const require_onchain_validation_checks_checkReservePriceLimited = require("./checks/checkReservePriceLimited.js");
@@ -29,6 +32,7 @@ const require_onchain_validation_bundles_checkIncreaseDebt = require("./bundles/
29
32
  const require_onchain_validation_bundles_checkIncreaseQuota = require("./bundles/checkIncreaseQuota.js");
30
33
  const require_onchain_validation_bundles_checkMarket = require("./bundles/checkMarket.js");
31
34
  const require_onchain_validation_bundles_checkObtained = require("./bundles/checkObtained.js");
35
+ const require_onchain_validation_bundles_checkQuotaUpdates = require("./bundles/checkQuotaUpdates.js");
32
36
  const require_onchain_validation_bundles_checkMidasAccountGreenlist = require("./bundles/checkMidasAccountGreenlist.js");
33
37
  const require_onchain_validation_bundles_checkRWAOpenRequirements = require("./bundles/checkRWAOpenRequirements.js");
34
38
  const require_onchain_validation_bundles_checkRWAOpening = require("./bundles/checkRWAOpening.js");
@@ -68,6 +72,7 @@ exports.checkLiquidationFunding = require_onchain_validation_bundles_checkLiquid
68
72
  exports.checkLiquidatorEligible = require_onchain_validation_checks_checkLiquidatorEligible.checkLiquidatorEligible;
69
73
  exports.checkMarket = require_onchain_validation_bundles_checkMarket.checkMarket;
70
74
  exports.checkMarketExpired = require_onchain_validation_checks_checkMarketExpired.checkMarketExpired;
75
+ exports.checkMaxQuota = require_onchain_validation_checks_checkMaxQuota.checkMaxQuota;
71
76
  exports.checkMidasAccountGreenlist = require_onchain_validation_bundles_checkMidasAccountGreenlist.checkMidasAccountGreenlist;
72
77
  exports.checkObtained = require_onchain_validation_bundles_checkObtained.checkObtained;
73
78
  exports.checkOperation = require_onchain_validation_checkOperation.checkOperation;
@@ -76,8 +81,11 @@ exports.checkPoolLiquidity = require_onchain_validation_checks_checkPoolLiquidit
76
81
  exports.checkPoolOperation = require_onchain_validation_bundles_checkPoolOperation.checkPoolOperation;
77
82
  exports.checkPoolPaused = require_onchain_validation_checks_checkPoolPaused.checkPoolPaused;
78
83
  exports.checkPoolSunset = require_onchain_validation_checks_checkPoolSunset.checkPoolSunset;
84
+ exports.checkQuotaActive = require_onchain_validation_checks_checkQuotaActive.checkQuotaActive;
85
+ exports.checkQuotaChange = require_onchain_validation_checks_checkQuotaChange.checkQuotaChange;
79
86
  exports.checkQuotaCount = require_onchain_validation_checks_checkQuotaCount.checkQuotaCount;
80
87
  exports.checkQuotaLimit = require_onchain_validation_checks_checkQuotaLimit.checkQuotaLimit;
88
+ exports.checkQuotaUpdates = require_onchain_validation_bundles_checkQuotaUpdates.checkQuotaUpdates;
81
89
  exports.checkRWAOpenRequirements = require_onchain_validation_bundles_checkRWAOpenRequirements.checkRWAOpenRequirements;
82
90
  exports.checkRWAOpening = require_onchain_validation_bundles_checkRWAOpening.checkRWAOpening;
83
91
  exports.checkReservePriceLimited = require_onchain_validation_checks_checkReservePriceLimited.checkReservePriceLimited;
@@ -372,6 +372,16 @@ var PrepareApi = class extends require_onchain_base_MultichainConstruct.Multicha
372
372
  });
373
373
  }
374
374
  /**
375
+ * {@inheritDoc IOpportunitiesPrepare.updateQuota}
376
+ **/
377
+ async updateQuota(position, params) {
378
+ return this.#startIntent(position, params, {
379
+ type: "UPDATE_QUOTA",
380
+ token: params.token,
381
+ quota: params.quota
382
+ });
383
+ }
384
+ /**
375
385
  * {@inheritDoc IOpportunitiesPrepare.leverageBand}
376
386
  **/
377
387
  leverageBand(strategy, collateral, targetHF, position) {
@@ -1,5 +1,5 @@
1
- import { iCreditFacadeV310Abi } from "../abi/310/generated.js";
2
1
  import { ierc20Abi } from "../abi/iERC20.js";
2
+ import { iCreditFacadeV310Abi } from "../abi/310/generated.js";
3
3
  import { AddressMap } from "../onchain/utils/AddressMap.js";
4
4
  import { AddressSet } from "../onchain/utils/AddressSet.js";
5
5
  import { AssetsMap } from "../onchain/utils/AssetsMap.js";
@@ -1,6 +1,6 @@
1
+ import { iWithdrawalCompressorV313Abi } from "../abi/IWithdrawalCompressorV313.js";
1
2
  import { getNetworkType } from "../onchain/chain/chains.js";
2
3
  import { getWithdrawalCompressorAddress } from "../onchain/accounts/withdrawal-compressor/addresses.js";
3
- import { iWithdrawalCompressorV313Abi } from "../abi/IWithdrawalCompressorV313.js";
4
4
  import "../onchain/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";
@@ -1,5 +1,5 @@
1
- import { iCreditFacadeV310Abi } from "../../abi/310/generated.js";
2
1
  import { ierc20Abi } from "../../abi/iERC20.js";
2
+ import { iCreditFacadeV310Abi } from "../../abi/310/generated.js";
3
3
  import { AddressMap } from "../../onchain/utils/AddressMap.js";
4
4
  import "../../onchain/index.js";
5
5
  import { UnexpectedFacadeEventOrderError } from "./errors.js";
@@ -1,7 +1,7 @@
1
1
  import "./base.js";
2
2
  import { creditAccountFrozen, liquidatorNotEligible, notEmergencyLiquidator } from "./liquidation-errors.js";
3
- import { accountNotMidasGreenlisted, creditManagerPaused, debtOutOfRange, forbiddenToken, insufficientAllowance, insufficientBalance, insufficientCollateral, insufficientPoolLiquidity, leverageOutOfRange, marketExpired, poolPaused, poolSunset, quotaCountExceeded, quotaLimitReached, reservePriceLimited, rwaOpenRequirementsNotMet } from "./operation-errors.js";
3
+ import { accountNotMidasGreenlisted, creditManagerPaused, debtOutOfRange, forbiddenToken, insufficientAllowance, insufficientBalance, insufficientCollateral, insufficientPoolLiquidity, leverageOutOfRange, marketExpired, poolPaused, poolSunset, quotaAboveMax, quotaCountExceeded, quotaInactive, quotaLimitReached, quotaUnchanged, reservePriceLimited, rwaOpenRequirementsNotMet } from "./operation-errors.js";
4
4
  import { unpriceableTokenError } from "./oracle-errors.js";
5
5
  import { creditAccountNotEmpty, creditAccountNotFound, multipleDelayedWithdrawals, noDelayedRoute, noRecordedIntent, noStrategyTargetCollateral, unexpectedFailure, unsupportedCollateralToken, unsupportedTokenPair, withdrawalInProgress } from "./prepare-errors.js";
6
6
  import { malformedTransaction } from "./preview-errors.js";
7
- export { accountNotMidasGreenlisted, creditAccountFrozen, creditAccountNotEmpty, creditAccountNotFound, creditManagerPaused, debtOutOfRange, forbiddenToken, insufficientAllowance, insufficientBalance, insufficientCollateral, insufficientPoolLiquidity, leverageOutOfRange, liquidatorNotEligible, malformedTransaction, marketExpired, multipleDelayedWithdrawals, noDelayedRoute, noRecordedIntent, noStrategyTargetCollateral, notEmergencyLiquidator, poolPaused, poolSunset, quotaCountExceeded, quotaLimitReached, reservePriceLimited, rwaOpenRequirementsNotMet, unexpectedFailure, unpriceableTokenError, unsupportedCollateralToken, unsupportedTokenPair, withdrawalInProgress };
7
+ export { accountNotMidasGreenlisted, creditAccountFrozen, creditAccountNotEmpty, creditAccountNotFound, creditManagerPaused, debtOutOfRange, forbiddenToken, insufficientAllowance, insufficientBalance, insufficientCollateral, insufficientPoolLiquidity, leverageOutOfRange, liquidatorNotEligible, malformedTransaction, marketExpired, multipleDelayedWithdrawals, noDelayedRoute, noRecordedIntent, noStrategyTargetCollateral, notEmergencyLiquidator, poolPaused, poolSunset, quotaAboveMax, quotaCountExceeded, quotaInactive, quotaLimitReached, quotaUnchanged, reservePriceLimited, rwaOpenRequirementsNotMet, unexpectedFailure, unpriceableTokenError, unsupportedCollateralToken, unsupportedTokenPair, withdrawalInProgress };
@@ -100,6 +100,30 @@ function quotaCountExceeded(count, max) {
100
100
  max
101
101
  };
102
102
  }
103
+ /** {@inheritDoc QuotaInactiveError} */
104
+ function quotaInactive(token) {
105
+ return {
106
+ code: "quotaInactive",
107
+ message: `${token.symbol} has no active quota in this market.`,
108
+ token
109
+ };
110
+ }
111
+ /** {@inheritDoc QuotaUnchangedError} */
112
+ function quotaUnchanged(args) {
113
+ return {
114
+ code: "quotaUnchanged",
115
+ message: `${args.token.symbol} quota of ${args.requested.value} rounds to the current ${args.current.value}.`,
116
+ ...args
117
+ };
118
+ }
119
+ /** {@inheritDoc QuotaAboveMaxError} */
120
+ function quotaAboveMax(args) {
121
+ return {
122
+ code: "quotaAboveMax",
123
+ message: `${args.token.symbol} quota of ${args.requested.value} exceeds maxQuota ${args.maxQuota.value}.`,
124
+ ...args
125
+ };
126
+ }
103
127
  /** {@inheritDoc InsufficientBalanceError} */
104
128
  function insufficientBalance(args = {}) {
105
129
  const { required, held } = args;
@@ -134,4 +158,4 @@ function accountNotMidasGreenlisted(args) {
134
158
  };
135
159
  }
136
160
  //#endregion
137
- export { accountNotMidasGreenlisted, creditManagerPaused, debtOutOfRange, forbiddenToken, insufficientAllowance, insufficientBalance, insufficientCollateral, insufficientPoolLiquidity, leverageOutOfRange, marketExpired, poolPaused, poolSunset, quotaCountExceeded, quotaLimitReached, reservePriceLimited, rwaOpenRequirementsNotMet };
161
+ export { accountNotMidasGreenlisted, creditManagerPaused, debtOutOfRange, forbiddenToken, insufficientAllowance, insufficientBalance, insufficientCollateral, insufficientPoolLiquidity, leverageOutOfRange, marketExpired, poolPaused, poolSunset, quotaAboveMax, quotaCountExceeded, quotaInactive, quotaLimitReached, quotaUnchanged, reservePriceLimited, rwaOpenRequirementsNotMet };
@@ -15,7 +15,7 @@ import { ANALYTICS_POSITIONS_DEFAULT_LIMIT, ANALYTICS_POSITIONS_MAX_LIMIT, analy
15
15
  import "./curators.js";
16
16
  import "./delayed-intents.js";
17
17
  import { creditAccountFrozen, liquidatorNotEligible, notEmergencyLiquidator } from "./errors/liquidation-errors.js";
18
- import { accountNotMidasGreenlisted, creditManagerPaused, debtOutOfRange, forbiddenToken, insufficientAllowance, insufficientBalance, insufficientCollateral, insufficientPoolLiquidity, leverageOutOfRange, marketExpired, poolPaused, poolSunset, quotaCountExceeded, quotaLimitReached, reservePriceLimited, rwaOpenRequirementsNotMet } from "./errors/operation-errors.js";
18
+ import { accountNotMidasGreenlisted, creditManagerPaused, debtOutOfRange, forbiddenToken, insufficientAllowance, insufficientBalance, insufficientCollateral, insufficientPoolLiquidity, leverageOutOfRange, marketExpired, poolPaused, poolSunset, quotaAboveMax, quotaCountExceeded, quotaInactive, quotaLimitReached, quotaUnchanged, reservePriceLimited, rwaOpenRequirementsNotMet } from "./errors/operation-errors.js";
19
19
  import { unpriceableTokenError } from "./errors/oracle-errors.js";
20
20
  import { creditAccountNotEmpty, creditAccountNotFound, multipleDelayedWithdrawals, noDelayedRoute, noRecordedIntent, noStrategyTargetCollateral, unexpectedFailure, unsupportedCollateralToken, unsupportedTokenPair, withdrawalInProgress } from "./errors/prepare-errors.js";
21
21
  import { malformedTransaction } from "./errors/preview-errors.js";
@@ -33,4 +33,4 @@ import { safeValue, sdkErr, sdkOk } from "./result.js";
33
33
  import "./rewards.js";
34
34
  import "./withdrawals.js";
35
35
  import { positionClaimableWithdrawalSchema, positionPendingWithdrawalSchema, positionWithdrawalsSchema, withdrawalOutputAmountSchema } from "./withdrawals.schema.js";
36
- export { ANALYTICS_POSITIONS_DEFAULT_LIMIT, ANALYTICS_POSITIONS_MAX_LIMIT, CHART_METRIC_UNITS, CHART_RANGES, CHART_UNAVAILABLE_CODES, FILTER_ALL, KYC_REGISTRATION_LINKS, POOL_OPPORTUNITY_CHART_METRICS, POOL_POSITION_CHART_METRICS, PROTOCOL_CHART_METRICS, RWA_FACTORY_SECURITIZE, RWA_FACTORY_TYPES, RWA_PROTOCOLS, SECURITIZE_REGISTER_VAULT_TYPES, STRATEGY_OPPORTUNITY_CHART_METRICS, STRATEGY_POSITION_CHART_METRICS, STRATEGY_POSITION_COLLATERAL_ERROR, accountNotMidasGreenlisted, amountSchema, analyticsChartQueryOptionsSchema, analyticsChartQueryParamsSchema, analyticsChartQuerySchema, analyticsPositionListOptionsSchema, analyticsPositionListQueryParamsSchema, analyticsPositionListQuerySchema, analyticsPositionPageSchema, analyticsPositionSchema, analyticsPositionSortFieldSchema, analyticsSortDirectionSchema, apyBreakdownSchema, asEstimated, assetTypeSchema, backendPreferred, booleanParamSchema, borrowRateBreakdownSchema, bpsSchema, chainFailedSchema, chainIdSchema, chainMetadataSchema, chainSucceededSchema, chartBundleSchemaFor, chartDenominationSchema, chartMetricSchema, chartQueryCodec, chartQueryParamsSchema, chartQuerySchema, chartRangeSchema, chartSeriesSchema, chartValueSchema, chartWindowSchema, compareTagOf, creditAccountFrozen, creditAccountNotEmpty, creditAccountNotFound, creditManagerPaused, curatorNameSchema, curatorSchema, dataSourceSchema, debtOutOfRange, delayedReceivedAssetSchema, encodeFlag, filterAllSchema, filterable, forbiddenToken, instantReceivedAssetSchema, insufficientAllowance, insufficientBalance, insufficientCollateral, insufficientPoolLiquidity, isFilterSet, kycRequirementSchema, leverageOutOfRange, leverageSchema, liquidatableAccountFilterSchema, liquidatableAccountSchema, liquidationApprovalSchema, liquidationDetailsSchema, liquidationPositionId, liquidationPositionSchema, liquidatorNotEligible, malformedTransaction, marketExpired, matchesLiquidatableAccountFilter, matchesOpportunityFilter, matchesPositionFilter, multipleDelayedWithdrawals, noDelayedRoute, noRecordedIntent, noStrategyTargetCollateral, notEmergencyLiquidator, noticeKindSchema, noticeSchema, offchainOnly, onchainOnly, opportunityBaseSchema, opportunityDetailSchema, opportunityFilterQueryParamsSchema, opportunityFilterQuerySchema, opportunityFilterSchema, opportunityId, opportunityKeySchema, opportunityKindSchema, opportunitySchema, opportunityTotalsSchema, pnlBreakdownSchema, pointRewardsSchema, pointsProgramPnLSchema, pointsProgramSchema, pointsRewardsPnLSchema, poolOpportunityChartMetricSchema, poolOpportunityDetailSchema, poolOpportunityId, poolOpportunityKeySchema, poolOpportunitySchema, poolPaused, poolPositionChartMetricSchema, poolPositionId, poolPositionKeySchema, poolPositionSchema, poolSunset, positionClaimableWithdrawalSchema, positionCollateralSchema, positionFilterQueryParamsSchema, positionFilterQuerySchema, positionFilterSchema, positionId, positionKeySchema, positionKindSchema, positionPendingWithdrawalSchema, positionSchema, positionTransactionKindSchema, positionTransactionSchema, positionWithdrawalsSchema, positionsTotalsSchema, priceFeedDataSchema, priceFeedSummarySchema, protocolChartMetricSchema, quotaAssetSchema, quotaCountExceeded, quotaLimitReached, rateCurvePointSchema, rateCurveSchema, receivedAssetSchema, reservePriceLimited, responseMetadataSchema, responseSchema, rewardsPnLSchema, rewardsSchema, rwaOpenRequirementsNotMet, rwaProtocolSchema, safeValue, sdkErr, sdkOk, strategyOpportunityChartMetricSchema, strategyOpportunityDetailSchema, strategyOpportunityId, strategyOpportunityKeySchema, strategyOpportunitySchema, strategyPositionChartMetricSchema, strategyPositionId, strategyPositionKeySchema, strategyPositionSchema, timestampSchema, tokenAmountSchema, tokenQuotaRateSchema, tokenRewardsPnLSchema, tokenRewardsSchema, tokenSchema, tolerance, txCallSchema, underlyingTokenSchema, unexpectedFailure, unpriceableTokenError, unsupportedCollateralToken, unsupportedTokenPair, withdrawalInProgress, withdrawalOutputAmountSchema };
36
+ export { ANALYTICS_POSITIONS_DEFAULT_LIMIT, ANALYTICS_POSITIONS_MAX_LIMIT, CHART_METRIC_UNITS, CHART_RANGES, CHART_UNAVAILABLE_CODES, FILTER_ALL, KYC_REGISTRATION_LINKS, POOL_OPPORTUNITY_CHART_METRICS, POOL_POSITION_CHART_METRICS, PROTOCOL_CHART_METRICS, RWA_FACTORY_SECURITIZE, RWA_FACTORY_TYPES, RWA_PROTOCOLS, SECURITIZE_REGISTER_VAULT_TYPES, STRATEGY_OPPORTUNITY_CHART_METRICS, STRATEGY_POSITION_CHART_METRICS, STRATEGY_POSITION_COLLATERAL_ERROR, accountNotMidasGreenlisted, amountSchema, analyticsChartQueryOptionsSchema, analyticsChartQueryParamsSchema, analyticsChartQuerySchema, analyticsPositionListOptionsSchema, analyticsPositionListQueryParamsSchema, analyticsPositionListQuerySchema, analyticsPositionPageSchema, analyticsPositionSchema, analyticsPositionSortFieldSchema, analyticsSortDirectionSchema, apyBreakdownSchema, asEstimated, assetTypeSchema, backendPreferred, booleanParamSchema, borrowRateBreakdownSchema, bpsSchema, chainFailedSchema, chainIdSchema, chainMetadataSchema, chainSucceededSchema, chartBundleSchemaFor, chartDenominationSchema, chartMetricSchema, chartQueryCodec, chartQueryParamsSchema, chartQuerySchema, chartRangeSchema, chartSeriesSchema, chartValueSchema, chartWindowSchema, compareTagOf, creditAccountFrozen, creditAccountNotEmpty, creditAccountNotFound, creditManagerPaused, curatorNameSchema, curatorSchema, dataSourceSchema, debtOutOfRange, delayedReceivedAssetSchema, encodeFlag, filterAllSchema, filterable, forbiddenToken, instantReceivedAssetSchema, insufficientAllowance, insufficientBalance, insufficientCollateral, insufficientPoolLiquidity, isFilterSet, kycRequirementSchema, leverageOutOfRange, leverageSchema, liquidatableAccountFilterSchema, liquidatableAccountSchema, liquidationApprovalSchema, liquidationDetailsSchema, liquidationPositionId, liquidationPositionSchema, liquidatorNotEligible, malformedTransaction, marketExpired, matchesLiquidatableAccountFilter, matchesOpportunityFilter, matchesPositionFilter, multipleDelayedWithdrawals, noDelayedRoute, noRecordedIntent, noStrategyTargetCollateral, notEmergencyLiquidator, noticeKindSchema, noticeSchema, offchainOnly, onchainOnly, opportunityBaseSchema, opportunityDetailSchema, opportunityFilterQueryParamsSchema, opportunityFilterQuerySchema, opportunityFilterSchema, opportunityId, opportunityKeySchema, opportunityKindSchema, opportunitySchema, opportunityTotalsSchema, pnlBreakdownSchema, pointRewardsSchema, pointsProgramPnLSchema, pointsProgramSchema, pointsRewardsPnLSchema, poolOpportunityChartMetricSchema, poolOpportunityDetailSchema, poolOpportunityId, poolOpportunityKeySchema, poolOpportunitySchema, poolPaused, poolPositionChartMetricSchema, poolPositionId, poolPositionKeySchema, poolPositionSchema, poolSunset, positionClaimableWithdrawalSchema, positionCollateralSchema, positionFilterQueryParamsSchema, positionFilterQuerySchema, positionFilterSchema, positionId, positionKeySchema, positionKindSchema, positionPendingWithdrawalSchema, positionSchema, positionTransactionKindSchema, positionTransactionSchema, positionWithdrawalsSchema, positionsTotalsSchema, priceFeedDataSchema, priceFeedSummarySchema, protocolChartMetricSchema, quotaAboveMax, quotaAssetSchema, quotaCountExceeded, quotaInactive, quotaLimitReached, quotaUnchanged, rateCurvePointSchema, rateCurveSchema, receivedAssetSchema, reservePriceLimited, responseMetadataSchema, responseSchema, rewardsPnLSchema, rewardsSchema, rwaOpenRequirementsNotMet, rwaProtocolSchema, safeValue, sdkErr, sdkOk, strategyOpportunityChartMetricSchema, strategyOpportunityDetailSchema, strategyOpportunityId, strategyOpportunityKeySchema, strategyOpportunitySchema, strategyPositionChartMetricSchema, strategyPositionId, strategyPositionKeySchema, strategyPositionSchema, timestampSchema, tokenAmountSchema, tokenQuotaRateSchema, tokenRewardsPnLSchema, tokenRewardsSchema, tokenSchema, tolerance, txCallSchema, underlyingTokenSchema, unexpectedFailure, unpriceableTokenError, unsupportedCollateralToken, unsupportedTokenPair, withdrawalInProgress, withdrawalOutputAmountSchema };
@@ -1,3 +1,5 @@
1
+ import { iBaseRewardPoolAbi } from "../../abi/iBaseRewardPool.js";
2
+ import { ierc4626AdapterAbi } from "../../abi/ierc4626Adapter.js";
1
3
  import { AP_REWARDS_COMPRESSOR } from "../constants/address-provider.js";
2
4
  import { ADDRESS_0X0 } from "../constants/addresses.js";
3
5
  import { MAX_UINT256 } from "../constants/math.js";
@@ -8,8 +10,6 @@ import "../base/index.js";
8
10
  import { AccountBotsService } from "./bots/AccountBotsService.js";
9
11
  import "./bots/index.js";
10
12
  import { rewardsCompressorAbi } from "../../abi/compressors/rewardsCompressor.js";
11
- import { iBaseRewardPoolAbi } from "../../abi/iBaseRewardPool.js";
12
- import { ierc4626AdapterAbi } from "../../abi/ierc4626Adapter.js";
13
13
  import { expectedBalanceDeltas } from "../market/credit/expectedBalanceDeltas.js";
14
14
  import "../market/index.js";
15
15
  import { CreditAccountCompressor } from "./credit-account-compressor/CreditAccountCompressor.js";
@@ -16,7 +16,7 @@ import { calcLeverageBand } from "./leverage-band.js";
16
16
  import { maxBorrow } from "./maxBorrow.js";
17
17
  import { maxWithdrawCollateral } from "./maxWithdrawCollateral.js";
18
18
  import { buildOpenStrategyState } from "./open-strategy.js";
19
- import { planAddCollateral, planAdjustLeverage, planAdjustLeverageDelayed, planDeposit, planRepay, planWithdraw, planWithdrawAsset, planWithdrawDelayed } from "./plan.js";
19
+ import { planAddCollateral, planAdjustLeverage, planAdjustLeverageDelayed, planDeposit, planRepay, planUpdateQuota, planWithdraw, planWithdrawAsset, planWithdrawDelayed } from "./plan.js";
20
20
  import { withdrawLimits } from "./withdraw-limits.js";
21
21
  import { realize } from "./realize.js";
22
22
  import { planTail, projectTail } from "./tail.js";
@@ -64,6 +64,7 @@ var CreditAccountOperationsService = class extends SDKConstruct {
64
64
  case "DEPOSIT": return planDeposit(intent, view);
65
65
  case "REPAY": return planRepay(intent, view);
66
66
  case "WITHDRAW": return planWithdraw(intent, view);
67
+ case "UPDATE_QUOTA": return planUpdateQuota(intent, view);
67
68
  default: throw new Error(`${intent.type} - not implemented`);
68
69
  }
69
70
  }, limits));
@@ -67,7 +67,7 @@ function buildQuotaUpdateOperation(input) {
67
67
  const quotaAssets = [...update.quotaIncrease, ...update.quotaDecrease];
68
68
  const calls = quotaAssets.length === 0 ? [] : sdk.accounts.prepareUpdateQuotas(creditAccount.creditFacade, {
69
69
  averageQuota: quotaAssets,
70
- minQuota: quotaAssets
70
+ minQuota: input.minQuota ?? quotaAssets
71
71
  });
72
72
  return {
73
73
  type: "changeQuota",
@@ -1,4 +1,4 @@
1
- import { MAX_UINT256, PERCENTAGE_FACTOR } from "../../constants/math.js";
1
+ import { MAX_UINT256, PERCENTAGE_FACTOR, isZeroBalance } from "../../constants/math.js";
2
2
  import "../../constants/index.js";
3
3
  import { debtOutOfRange, insufficientBalance, leverageOutOfRange } from "../../../model/errors/operation-errors.js";
4
4
  import { noDelayedRoute, unsupportedCollateralToken } from "../../../model/errors/prepare-errors.js";
@@ -86,6 +86,26 @@ function planRepay(intent, view) {
86
86
  ];
87
87
  }
88
88
  /**
89
+ * One token's quota changes; no balance moves and debt is untouched.
90
+ *
91
+ * Only a token the account holds can be quoted here, and only on an account
92
+ * that owes something: the facade refuses any quota change at zero debt.
93
+ */
94
+ function planUpdateQuota(intent, view) {
95
+ const U = view.underlying;
96
+ if (eq(intent.token, U) || isZeroBalance(view.balanceOf(intent.token))) throw new IntentPreviewError(unsupportedCollateralToken(toToken(view.sdk, intent.token)), `updateQuota: ${intent.token} is the underlying or not held by the account`);
97
+ if (view.debt <= 0n) throw new IntentPreviewError(debtOutOfRange({
98
+ requested: toTokenAmount(view.sdk, U, 0n),
99
+ minDebt: toTokenAmount(view.sdk, U, view.debtLimits.minDebt),
100
+ maxDebt: toTokenAmount(view.sdk, U, view.debtLimits.maxDebt)
101
+ }), "updateQuota: the account has zero debt");
102
+ return [{
103
+ kind: "updateQuota",
104
+ token: intent.token,
105
+ quota: intent.quota
106
+ }];
107
+ }
108
+ /**
89
109
  * Intent 2.1: `W` of value leaves, debt shrinks by `D0 · W / C0` so leverage
90
110
  * holds. Both are funded by the source `S`.
91
111
  */
@@ -407,4 +427,4 @@ function assertPositive(amount, flow) {
407
427
  if (amount <= 0n) throw new IntentPreviewError(insufficientBalance(), `${flow}: amount must be positive`);
408
428
  }
409
429
  //#endregion
410
- export { RAISED, planAddCollateral, planAdjustLeverage, planAdjustLeverageDelayed, planDeposit, planFinishClaimOnly, planFinishCloseAccount, planFinishDecreaseLeverage, planFinishWithdraw, planRepay, planWithdraw, planWithdrawAsset, planWithdrawDelayed };
430
+ export { RAISED, planAddCollateral, planAdjustLeverage, planAdjustLeverageDelayed, planDeposit, planFinishClaimOnly, planFinishCloseAccount, planFinishDecreaseLeverage, planFinishWithdraw, planRepay, planUpdateQuota, planWithdraw, planWithdrawAsset, planWithdrawDelayed };
@@ -13,6 +13,7 @@ import { collectPriceImpact } from "./utils/price-impact.js";
13
13
  import { clearedQuotas, getQuotasForUpdate, quotasAfterUpdate, withDirectTransferQuota } from "./utils/quotas-for-update.js";
14
14
  import { createRouterPaths } from "./utils/router-path.js";
15
15
  import { buildAddCollateralOperation, buildClaimDelayedWithdrawalOperation, buildCloseSwapOperation, buildDecreaseDebtOperation, buildIncreaseDebtOperation, buildQuotaUpdateOperation, buildStartDelayedWithdrawalOperation, buildSwapOperation, buildUnwrapRwaCollateralOperation, buildWithdrawCollateralOperation, buildWrapRwaCollateralOperation, instantOutput } from "./operations.js";
16
+ import { resolveQuotaUpdate } from "./resolveQuotaUpdate.js";
16
17
  import { withdrawLimits } from "./withdraw-limits.js";
17
18
  //#region src/onchain/accounts/intents/realize.ts
18
19
  /**
@@ -98,10 +99,11 @@ async function realize(steps, props) {
98
99
  traded.returnedUnd += underlyingValue(returned);
99
100
  };
100
101
  /**
101
- * Set by a `clearQuotas` step, which settles the quotas mid-walk instead of
102
- * at the end — and settles them at none, whatever the balances turn out to be.
102
+ * Set by a step that settles the quotas itself, mid-walk instead of at the
103
+ * end, whatever the balances turn out to be: `clearQuotas` at none,
104
+ * `updateQuota` at the one the intent names.
103
105
  */
104
- let cleared;
106
+ let plannedQuotas;
105
107
  /**
106
108
  * Whether anything leaves the account, which is what makes the credit manager
107
109
  * judge the closing collateral check at safe prices.
@@ -147,14 +149,34 @@ async function realize(steps, props) {
147
149
  }));
148
150
  break;
149
151
  }
150
- case "clearQuotas":
151
- cleared = clearedQuotas(creditAccount.tokens);
152
+ case "clearQuotas": {
153
+ const cleared = clearedQuotas(creditAccount.tokens);
154
+ plannedQuotas = cleared;
152
155
  if (cleared.quotaDecrease.length > 0) push(buildQuotaUpdateOperation({
153
156
  update: cleared,
154
157
  creditAccount,
155
158
  sdk
156
159
  }));
157
160
  break;
161
+ }
162
+ case "updateQuota": {
163
+ const { update, minQuota } = resolveQuotaUpdate({
164
+ sdk,
165
+ creditAccount,
166
+ token: step.token,
167
+ quota: step.quota,
168
+ quotaReserve,
169
+ limits: props.limits
170
+ });
171
+ plannedQuotas = update;
172
+ push(buildQuotaUpdateOperation({
173
+ update,
174
+ creditAccount,
175
+ sdk,
176
+ minQuota
177
+ }));
178
+ break;
179
+ }
158
180
  case "convert": {
159
181
  const amount = amountOf(step.amount);
160
182
  if (amount <= 0n) {
@@ -335,7 +357,7 @@ async function realize(steps, props) {
335
357
  const floor = ledger.snapshot();
336
358
  const { assets, debt } = floor;
337
359
  const projected = expected.snapshot();
338
- const quotas = cleared ?? withDirectTransferQuota(getQuotasForUpdate({
360
+ const quotas = plannedQuotas ?? withDirectTransferQuota(getQuotasForUpdate({
339
361
  assetsBefore: creditAccount.tokens,
340
362
  assetsAfter: assets,
341
363
  initialQuotas: creditAccount.tokens,
@@ -398,7 +420,7 @@ async function realize(steps, props) {
398
420
  after: projected.assets,
399
421
  limits: props.limits
400
422
  });
401
- if (!cleared && quotas.quotaIncrease.length + quotas.quotaDecrease.length > 0) {
423
+ if (!plannedQuotas && quotas.quotaIncrease.length + quotas.quotaDecrease.length > 0) {
402
424
  assertQuotaAvailable(sdk, market, quotas.quotaIncrease, props.limits);
403
425
  push(buildQuotaUpdateOperation({
404
426
  update: quotas,
@@ -0,0 +1,145 @@
1
+ import { BigIntMath } from "../../utils/bigint-math.js";
2
+ import { MAX_QUOTA_MULTIPLIER, MIN_INT96, PERCENTAGE_FACTOR } from "../../constants/math.js";
3
+ import { toToken } from "../../validation/helpers/token.js";
4
+ import { checkForbiddenToken } from "../../validation/checks/checkForbiddenToken.js";
5
+ import { checkMaxQuota } from "../../validation/checks/checkMaxQuota.js";
6
+ import { checkQuotaActive } from "../../validation/checks/checkQuotaActive.js";
7
+ import { checkQuotaChange } from "../../validation/checks/checkQuotaChange.js";
8
+ import { checkQuotaLimit } from "../../validation/checks/checkQuotaLimit.js";
9
+ import { raise } from "../../validation/raise.js";
10
+ import "../../validation/index.js";
11
+ import { eq } from "./utils/common.js";
12
+ import { assertQuotaAvailable } from "./guards.js";
13
+ import { roundUpQuota } from "../quota-utils.js";
14
+ import { resizedQuota } from "./utils/quotas-for-update.js";
15
+ //#region src/onchain/accounts/intents/resolveQuotaUpdate.ts
16
+ /**
17
+ * The single `updateQuota` an `UPDATE_QUOTA` intent sends, checked against
18
+ * what the facade and the quota keeper would revert on.
19
+ *
20
+ * A target is taken as named and refused when the market cannot meet it. A
21
+ * sized quota is held to what the market can give instead: an increase is capped
22
+ * at the pool's available quota, and `minQuota` accepts a partial fill so long as the
23
+ * token stays enabled.
24
+ */
25
+ function resolveQuotaUpdate(props) {
26
+ const { sdk, creditAccount, quotaReserve, limits } = props;
27
+ const suite = sdk.marketRegister.findCreditManager(creditAccount.creditManager);
28
+ const { market } = suite;
29
+ const { pqk } = market.pool;
30
+ const tokenLc = props.token.toLowerCase();
31
+ const token = toToken(sdk, tokenLc);
32
+ const underlying = toToken(sdk, market.pool.underlying);
33
+ const current = creditAccount.tokens.find((t) => eq(t.token, tokenLc))?.quota ?? 0n;
34
+ raise(checkQuotaActive({
35
+ token,
36
+ isActive: pqk.quotas.get(tokenLc)?.isActive ?? false
37
+ }), `updateQuota: ${tokenLc} has no active quota`);
38
+ let resolved;
39
+ if (props.quota === void 0) {
40
+ const price = (from, to, amount) => market.priceOracle.safeConvert(from, to, amount).value;
41
+ resolved = sizedChange(current, resizedQuota({
42
+ token: tokenLc,
43
+ assets: creditAccount.tokens,
44
+ initialQuotas: creditAccount.tokens,
45
+ quotaReserve,
46
+ underlyingToken: market.pool.underlying,
47
+ liquidationThresholds: suite.creditManager.liquidationThresholds,
48
+ quotas: pqk.quotas,
49
+ maxDebt: suite.creditFacade.maxDebt,
50
+ convert: price
51
+ }), tokenLc, roundUpQuota(pqk.quotaAvailable(tokenLc)));
52
+ if (resolved.change === 0n && resolved.requested > current) raise(checkQuotaLimit({
53
+ token,
54
+ requested: resolved.requested - current,
55
+ available: 0n,
56
+ ...limits,
57
+ underlying
58
+ }), `updateQuota: the pool has no quota left for ${tokenLc}`);
59
+ } else resolved = targetChange(current, props.quota);
60
+ const { requested, change, resulting } = resolved;
61
+ raise(checkQuotaChange({
62
+ token,
63
+ current,
64
+ requested,
65
+ change,
66
+ underlying
67
+ }), `updateQuota: ${requested} rounds to the current ${current}`);
68
+ if (change > 0n) raise(checkForbiddenToken({
69
+ token,
70
+ isForbidden: suite.isForbidden(tokenLc)
71
+ }), `updateQuota: ${tokenLc} is forbidden, its quota cannot grow`);
72
+ if (props.quota !== void 0) {
73
+ const maxQuota = MAX_QUOTA_MULTIPLIER * suite.creditFacade.maxDebt;
74
+ raise(checkMaxQuota({
75
+ token,
76
+ requested: resulting,
77
+ maxQuota,
78
+ underlying
79
+ }), `updateQuota: ${resulting} exceeds maxQuota ${maxQuota}`);
80
+ if (change > 0n) assertQuotaAvailable(sdk, market, [{
81
+ token: tokenLc,
82
+ balance: change
83
+ }], limits);
84
+ }
85
+ const entry = {
86
+ token: tokenLc,
87
+ balance: change
88
+ };
89
+ return {
90
+ update: {
91
+ desiredQuota: { [tokenLc]: {
92
+ token: tokenLc,
93
+ balance: resulting
94
+ } },
95
+ quotaIncrease: change > 0n ? [entry] : [],
96
+ quotaDecrease: change < 0n ? [entry] : []
97
+ },
98
+ minQuota: [{
99
+ token: tokenLc,
100
+ balance: resolved.minQuota
101
+ }]
102
+ };
103
+ }
104
+ function targetChange(current, quota) {
105
+ const target = BigIntMath.max(quota, 0n);
106
+ if (target === 0n) return {
107
+ requested: 0n,
108
+ change: current > 0n ? MIN_INT96 : 0n,
109
+ resulting: 0n,
110
+ minQuota: 0n
111
+ };
112
+ const change = roundUpQuota(target - current);
113
+ return {
114
+ requested: target,
115
+ change,
116
+ resulting: current + change,
117
+ minQuota: current + change
118
+ };
119
+ }
120
+ /**
121
+ * Reads the one token's change back out of {@link resizedQuota}, then caps an
122
+ * increase at `available`.
123
+ */
124
+ function sizedChange(current, sized, token, available) {
125
+ const requested = sized.desiredQuota[token]?.balance ?? current;
126
+ const decrease = sized.quotaDecrease.find((a) => a.token === token)?.balance;
127
+ if (decrease !== void 0) {
128
+ const resulting = decrease === -39614081257132168796771975168n ? 0n : current + decrease;
129
+ return {
130
+ requested,
131
+ change: decrease,
132
+ resulting,
133
+ minQuota: resulting
134
+ };
135
+ }
136
+ const increase = BigIntMath.min(sized.quotaIncrease.find((a) => a.token === token)?.balance ?? 0n, available);
137
+ return {
138
+ requested,
139
+ change: increase,
140
+ resulting: current + increase,
141
+ minQuota: increase > 0n ? BigIntMath.max(current, PERCENTAGE_FACTOR) : current
142
+ };
143
+ }
144
+ //#endregion
145
+ export { resolveQuotaUpdate };