@gearbox-protocol/sdk 14.12.0-next.73 → 14.12.0-next.75

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 (91) hide show
  1. package/dist/cjs/dev/AccountOpener.js +2 -5
  2. package/dist/cjs/plugins/accounts-counter/AccountsCounterPlugin.js +1 -1
  3. package/dist/cjs/sdk/accounts/CreditAccountsServiceV310.js +118 -974
  4. package/dist/cjs/sdk/accounts/credit-account-compressor/CreditAccountCompressor.js +280 -0
  5. package/dist/cjs/sdk/accounts/credit-account-compressor/CreditAccountCompressorV310Contract.js +141 -0
  6. package/dist/cjs/sdk/accounts/credit-account-compressor/index.js +6 -0
  7. package/dist/cjs/sdk/accounts/credit-account-compressor/types.js +1 -0
  8. package/dist/cjs/sdk/accounts/index.js +5 -4
  9. package/dist/cjs/sdk/accounts/intents/operations/unwrap-rwa-collateral/index.js +1 -1
  10. package/dist/cjs/sdk/accounts/intents/operations/wrap-rwa-collateral/index.js +1 -1
  11. package/dist/cjs/sdk/accounts/intents/testing/sdk-mock.js +2 -2
  12. package/dist/cjs/sdk/accounts/liquidations/LiquidationsService.js +3 -3
  13. package/dist/cjs/sdk/accounts/liquidations/constants.js +0 -2
  14. package/dist/cjs/sdk/accounts/liquidations/index.js +0 -2
  15. package/dist/cjs/sdk/constants/index.js +1 -0
  16. package/dist/cjs/sdk/constants/math.js +5 -0
  17. package/dist/cjs/sdk/index.js +12 -4
  18. package/dist/cjs/sdk/market/MarketRegister.js +10 -0
  19. package/dist/cjs/sdk/market/credit/CreditFacadeV310Contract.js +181 -0
  20. package/dist/cjs/sdk/market/credit/CreditSuite.js +107 -1
  21. package/dist/cjs/sdk/{accounts → market/credit}/dominantCollateral.js +18 -4
  22. package/dist/cjs/sdk/market/credit/index.js +3 -0
  23. package/dist/cjs/sdk/market/index.js +3 -0
  24. package/dist/cjs/sdk/market/math.js +59 -0
  25. package/dist/cjs/sdk/market/oracle/PriceOracleBaseContract.js +41 -1
  26. package/dist/cjs/sdk/market/oracle/PriceOracleV310Contract.js +0 -30
  27. package/dist/cjs/sdk/market/pricefeeds/PriceFeedsRegister.js +1 -1
  28. package/dist/cjs/sdk/opportunities/index.js +4 -0
  29. package/dist/esm/dev/AccountOpener.js +2 -5
  30. package/dist/esm/plugins/accounts-counter/AccountsCounterPlugin.js +1 -1
  31. package/dist/esm/sdk/accounts/CreditAccountsServiceV310.js +121 -977
  32. package/dist/esm/sdk/accounts/credit-account-compressor/CreditAccountCompressor.js +279 -0
  33. package/dist/esm/sdk/accounts/credit-account-compressor/CreditAccountCompressorV310Contract.js +141 -0
  34. package/dist/esm/sdk/accounts/credit-account-compressor/index.js +4 -0
  35. package/dist/esm/sdk/accounts/credit-account-compressor/types.js +1 -0
  36. package/dist/esm/sdk/accounts/index.js +4 -3
  37. package/dist/esm/sdk/accounts/intents/operations/unwrap-rwa-collateral/index.js +1 -1
  38. package/dist/esm/sdk/accounts/intents/operations/wrap-rwa-collateral/index.js +1 -1
  39. package/dist/esm/sdk/accounts/intents/testing/sdk-mock.js +2 -2
  40. package/dist/esm/sdk/accounts/liquidations/LiquidationsService.js +2 -2
  41. package/dist/esm/sdk/accounts/liquidations/constants.js +1 -2
  42. package/dist/esm/sdk/accounts/liquidations/index.js +1 -2
  43. package/dist/esm/sdk/constants/index.js +2 -2
  44. package/dist/esm/sdk/constants/math.js +5 -1
  45. package/dist/esm/sdk/index.js +6 -5
  46. package/dist/esm/sdk/market/MarketRegister.js +10 -0
  47. package/dist/esm/sdk/market/credit/CreditFacadeV310Contract.js +181 -0
  48. package/dist/esm/sdk/market/credit/CreditSuite.js +108 -2
  49. package/dist/esm/sdk/{accounts → market/credit}/dominantCollateral.js +18 -5
  50. package/dist/esm/sdk/market/credit/index.js +2 -1
  51. package/dist/esm/sdk/market/index.js +2 -1
  52. package/dist/esm/sdk/market/math.js +56 -1
  53. package/dist/esm/sdk/market/oracle/PriceOracleBaseContract.js +41 -1
  54. package/dist/esm/sdk/market/oracle/PriceOracleV310Contract.js +1 -31
  55. package/dist/esm/sdk/market/pricefeeds/PriceFeedsRegister.js +1 -1
  56. package/dist/esm/sdk/opportunities/index.js +2 -2
  57. package/dist/types/plugins/accounts/AccountsPlugin.d.ts +1 -1
  58. package/dist/types/sdk/OnchainSDK.d.ts +1 -1
  59. package/dist/types/sdk/accounts/CreditAccountsServiceV310.d.ts +23 -124
  60. package/dist/types/sdk/accounts/credit-account-compressor/CreditAccountCompressor.d.ts +60 -0
  61. package/dist/types/sdk/accounts/credit-account-compressor/CreditAccountCompressorV310Contract.d.ts +879 -0
  62. package/dist/types/sdk/accounts/credit-account-compressor/index.d.ts +4 -0
  63. package/dist/types/sdk/accounts/credit-account-compressor/types.d.ts +164 -0
  64. package/dist/types/sdk/accounts/index.d.ts +7 -5
  65. package/dist/types/sdk/accounts/liquidations/constants.d.ts +1 -2
  66. package/dist/types/sdk/accounts/liquidations/index.d.ts +1 -2
  67. package/dist/types/sdk/accounts/types.d.ts +46 -457
  68. package/dist/types/sdk/base/index.d.ts +2 -2
  69. package/dist/types/sdk/base/types.d.ts +6 -1
  70. package/dist/types/sdk/constants/index.d.ts +2 -2
  71. package/dist/types/sdk/constants/math.d.ts +5 -1
  72. package/dist/types/sdk/index.d.ts +16 -14
  73. package/dist/types/sdk/market/MarketRegister.d.ts +7 -0
  74. package/dist/types/sdk/market/credit/CreditFacadeV310Contract.d.ts +47 -2
  75. package/dist/types/sdk/market/credit/CreditSuite.d.ts +24 -2
  76. package/dist/types/sdk/{accounts → market/credit}/dominantCollateral.d.ts +13 -6
  77. package/dist/types/sdk/market/credit/index.d.ts +3 -2
  78. package/dist/types/sdk/market/credit/types.d.ts +112 -2
  79. package/dist/types/sdk/market/index.d.ts +4 -3
  80. package/dist/types/sdk/market/math.d.ts +60 -1
  81. package/dist/types/sdk/market/oracle/PriceOracleBaseContract.d.ts +15 -4
  82. package/dist/types/sdk/market/oracle/PriceOracleV310Contract.d.ts +0 -10
  83. package/dist/types/sdk/market/oracle/index.d.ts +2 -2
  84. package/dist/types/sdk/market/oracle/types.d.ts +30 -14
  85. package/dist/types/sdk/market/rwa/securitize/SecuritizeRWAFactory.d.ts +1 -1
  86. package/dist/types/sdk/market/rwa/types.d.ts +1 -1
  87. package/dist/types/sdk/opportunities/index.d.ts +2 -2
  88. package/package.json +1 -1
  89. package/dist/cjs/sdk/accounts/constants.js +0 -12
  90. package/dist/esm/sdk/accounts/constants.js +0 -11
  91. package/dist/types/sdk/accounts/constants.d.ts +0 -11
@@ -12,6 +12,7 @@ require("../utils/viem/index.js");
12
12
  const require_sdk_market_MarketConfiguratorContract = require("./MarketConfiguratorContract.js");
13
13
  const require_sdk_market_MarketSuite = require("./MarketSuite.js");
14
14
  const require_sdk_market_ZapperRegister = require("./ZapperRegister.js");
15
+ let viem = require("viem");
15
16
  //#region src/sdk/market/MarketRegister.ts
16
17
  /**
17
18
  * Central registry of all Gearbox markets on the current chain.
@@ -180,6 +181,15 @@ var MarketRegister = class extends require_sdk_market_ZapperRegister.ZapperRegis
180
181
  throw new Error(`cannot find credit manager ${creditManager}`);
181
182
  }
182
183
  /**
184
+ * Finds a credit facade by its on-chain address.
185
+ * @param creditFacade - Credit facade contract address.
186
+ * @throws If no loaded market contains the given credit facade.
187
+ **/
188
+ findCreditFacade(creditFacade) {
189
+ for (const cm of this.creditManagers) if ((0, viem.isAddressEqual)(cm.creditFacade.address, creditFacade)) return cm.creditFacade;
190
+ throw new Error(`cannot find credit facade ${creditFacade}`);
191
+ }
192
+ /**
183
193
  * Finds the market that contains the given credit manager.
184
194
  * @param creditManager - Credit manager contract address.
185
195
  * @throws If no loaded market contains the given credit manager.
@@ -1,9 +1,12 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_sdk_utils_AssetsMap = require("../../utils/AssetsMap.js");
2
3
  const require_sdk_constants_addresses = require("../../constants/addresses.js");
4
+ const require_sdk_constants_math = require("../../constants/math.js");
3
5
  require("../../constants/index.js");
4
6
  const require_sdk_utils_formatter = require("../../utils/formatter.js");
5
7
  require("../../utils/index.js");
6
8
  const require_sdk_market_credit_CreditFacadeV310BaseContract = require("./CreditFacadeV310BaseContract.js");
9
+ let viem = require("viem");
7
10
  //#region src/sdk/market/credit/CreditFacadeV310Contract.ts
8
11
  var CreditFacadeV310Contract = class extends require_sdk_market_credit_CreditFacadeV310BaseContract.CreditFacadeV310BaseContract {
9
12
  underlying;
@@ -108,6 +111,184 @@ var CreditFacadeV310Contract = class extends require_sdk_market_credit_CreditFac
108
111
  ]
109
112
  });
110
113
  }
114
+ /**
115
+ * {@inheritDoc ICreditFacadeContract.prepareIncreaseDebt}
116
+ */
117
+ prepareIncreaseDebt(amount) {
118
+ return {
119
+ target: this.address,
120
+ callData: (0, viem.encodeFunctionData)({
121
+ abi: this.abi,
122
+ functionName: "increaseDebt",
123
+ args: [amount]
124
+ })
125
+ };
126
+ }
127
+ /**
128
+ * {@inheritDoc ICreditFacadeContract.prepareChangeDebt}
129
+ */
130
+ prepareChangeDebt(change, isDecrease) {
131
+ return {
132
+ target: this.address,
133
+ callData: (0, viem.encodeFunctionData)({
134
+ abi: this.abi,
135
+ functionName: isDecrease ? "decreaseDebt" : "increaseDebt",
136
+ args: [change]
137
+ })
138
+ };
139
+ }
140
+ /**
141
+ * {@inheritDoc ICreditFacadeContract.prepareDecreaseDebtFull}
142
+ */
143
+ prepareDecreaseDebtFull() {
144
+ return {
145
+ target: this.address,
146
+ callData: (0, viem.encodeFunctionData)({
147
+ abi: this.abi,
148
+ functionName: "decreaseDebt",
149
+ args: [require_sdk_constants_math.MAX_UINT256]
150
+ })
151
+ };
152
+ }
153
+ /**
154
+ * {@inheritDoc ICreditFacadeContract.prepareWithdrawCollateral}
155
+ */
156
+ prepareWithdrawCollateral(token, amount, to) {
157
+ return {
158
+ target: this.address,
159
+ callData: (0, viem.encodeFunctionData)({
160
+ abi: this.abi,
161
+ functionName: "withdrawCollateral",
162
+ args: [
163
+ token,
164
+ amount,
165
+ to
166
+ ]
167
+ })
168
+ };
169
+ }
170
+ /**
171
+ * {@inheritDoc ICreditFacadeContract.prepareAddCollateral}
172
+ */
173
+ prepareAddCollateral(assets, permits) {
174
+ return assets.map(({ token, balance }) => {
175
+ const p = permits[token];
176
+ if (p) return {
177
+ target: this.address,
178
+ callData: (0, viem.encodeFunctionData)({
179
+ abi: this.abi,
180
+ functionName: "addCollateralWithPermit",
181
+ args: [
182
+ token,
183
+ balance,
184
+ p.deadline,
185
+ p.v,
186
+ p.r,
187
+ p.s
188
+ ]
189
+ })
190
+ };
191
+ return {
192
+ target: this.address,
193
+ callData: (0, viem.encodeFunctionData)({
194
+ abi: this.abi,
195
+ functionName: "addCollateral",
196
+ args: [token, balance]
197
+ })
198
+ };
199
+ });
200
+ }
201
+ /**
202
+ * {@inheritDoc ICreditFacadeContract.prepareUpdateQuotas}
203
+ */
204
+ prepareUpdateQuotas({ averageQuota, minQuota }) {
205
+ const minRecord = new require_sdk_utils_AssetsMap.AssetsMap(minQuota);
206
+ return averageQuota.map((q) => {
207
+ const minBalance = minRecord.get(q.token);
208
+ const min = minBalance && minBalance > 0n ? minBalance : 0n;
209
+ return {
210
+ target: this.address,
211
+ callData: (0, viem.encodeFunctionData)({
212
+ abi: this.abi,
213
+ functionName: "updateQuota",
214
+ args: [
215
+ q.token,
216
+ q.balance,
217
+ min
218
+ ]
219
+ })
220
+ };
221
+ });
222
+ }
223
+ /**
224
+ * {@inheritDoc ICreditFacadeContract.prepareDisableQuotas}
225
+ */
226
+ prepareDisableQuotas(tokens) {
227
+ return tokens.filter((t) => t.quota > 0n).map((t) => ({
228
+ target: this.address,
229
+ callData: (0, viem.encodeFunctionData)({
230
+ abi: this.abi,
231
+ functionName: "updateQuota",
232
+ args: [
233
+ t.token,
234
+ require_sdk_constants_math.MIN_INT96,
235
+ 0n
236
+ ]
237
+ })
238
+ }));
239
+ }
240
+ /**
241
+ * {@inheritDoc ICreditFacadeContract.prepareSetBotPermissions}
242
+ */
243
+ prepareSetBotPermissions(bot, permissions) {
244
+ return {
245
+ target: this.address,
246
+ callData: (0, viem.encodeFunctionData)({
247
+ abi: this.abi,
248
+ functionName: "setBotPermissions",
249
+ args: [bot, permissions]
250
+ })
251
+ };
252
+ }
253
+ /**
254
+ * {@inheritDoc ICreditFacadeContract.prepareOnDemandPriceUpdates}
255
+ */
256
+ prepareOnDemandPriceUpdates(updates) {
257
+ return {
258
+ target: this.address,
259
+ callData: (0, viem.encodeFunctionData)({
260
+ abi: this.abi,
261
+ functionName: "onDemandPriceUpdates",
262
+ args: [updates]
263
+ })
264
+ };
265
+ }
266
+ /**
267
+ * {@inheritDoc ICreditFacadeContract.prepareStoreExpectedBalances}
268
+ */
269
+ prepareStoreExpectedBalances(deltas) {
270
+ return {
271
+ target: this.address,
272
+ callData: (0, viem.encodeFunctionData)({
273
+ abi: this.abi,
274
+ functionName: "storeExpectedBalances",
275
+ args: [deltas]
276
+ })
277
+ };
278
+ }
279
+ /**
280
+ * {@inheritDoc ICreditFacadeContract.prepareCompareBalances}
281
+ */
282
+ prepareCompareBalances() {
283
+ return {
284
+ target: this.address,
285
+ callData: (0, viem.encodeFunctionData)({
286
+ abi: this.abi,
287
+ functionName: "compareBalances",
288
+ args: []
289
+ })
290
+ };
291
+ }
111
292
  };
112
293
  //#endregion
113
294
  exports.CreditFacadeV310Contract = CreditFacadeV310Contract;
@@ -1,14 +1,17 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_sdk_utils_AddressMap = require("../../utils/AddressMap.js");
2
3
  const require_sdk_utils_bigint_math = require("../../utils/bigint-math.js");
3
4
  const require_sdk_chain_chains = require("../../chain/chains.js");
4
- require("../../constants/math.js");
5
+ const require_sdk_constants_math = require("../../constants/math.js");
5
6
  require("../../constants/index.js");
7
+ require("../../utils/index.js");
6
8
  const require_sdk_base_SDKConstruct = require("../../base/SDKConstruct.js");
7
9
  require("../../base/index.js");
8
10
  const require_sdk_market_math = require("../math.js");
9
11
  const require_sdk_market_credit_createCreditConfigurator = require("./createCreditConfigurator.js");
10
12
  const require_sdk_market_credit_createCreditFacade = require("./createCreditFacade.js");
11
13
  const require_sdk_market_credit_createCreditManager = require("./createCreditManager.js");
14
+ const require_sdk_market_credit_dominantCollateral = require("./dominantCollateral.js");
12
15
  //#region src/sdk/market/credit/CreditSuite.ts
13
16
  /**
14
17
  * SDK aggregate for one credit-manager branch inside a market.
@@ -116,6 +119,20 @@ var CreditSuite = class extends require_sdk_base_SDKConstruct.SDKConstruct {
116
119
  return expirationDate > 0 ? expirationDate : null;
117
120
  }
118
121
  /**
122
+ * Liquidation fee pair in effect right now, resolving {@link isExpired} once
123
+ * for both.
124
+ */
125
+ liquidationFees() {
126
+ const cm = this.creditManager;
127
+ return this.isExpired ? {
128
+ feeLiquidation: cm.feeLiquidationExpired,
129
+ liquidationDiscount: cm.liquidationDiscountExpired
130
+ } : {
131
+ feeLiquidation: cm.feeLiquidation,
132
+ liquidationDiscount: cm.liquidationDiscount
133
+ };
134
+ }
135
+ /**
119
136
  * Whether this suite can be used right now. A paused pool blocks borrowing,
120
137
  * so the suite is unusable even when its own facade is live.
121
138
  */
@@ -200,6 +217,95 @@ var CreditSuite = class extends require_sdk_base_SDKConstruct.SDKConstruct {
200
217
  };
201
218
  }
202
219
  /**
220
+ * Everything a partial liquidation of credit account needs, with any parameter the
221
+ * caller pinned down taken as given and the rest derived from current state.
222
+ *
223
+ * @param ca - Credit account to partially liquidate.
224
+ * @param overrides - Parameters to use instead of the derived defaults.
225
+ * @throws If a derived `tokenOut` cannot be picked, or if the seized token is
226
+ * not a collateral token of this credit manager.
227
+ */
228
+ partialLiquidationParams(ca, overrides = {}) {
229
+ const tokenOut = overrides.tokenOut ?? this.#bestTokenOut(ca);
230
+ const optimalHF = overrides.optimalHF ?? this.optimalHFForPartialLiquidation(ca);
231
+ const repaidAmount = overrides.repaidAmount ?? this.#optimalRepaidAmount(ca, tokenOut, optimalHF);
232
+ return {
233
+ tokenOut,
234
+ optimalHF,
235
+ repaidAmount,
236
+ minSeizedAmount: overrides.minSeizedAmount ?? this.#minSeizedAmount(tokenOut, repaidAmount)
237
+ };
238
+ }
239
+ /**
240
+ * Health factor a partial liquidation of `ca` should target, in basis points.
241
+ *
242
+ * @param ca - Credit account to partially liquidate.
243
+ */
244
+ optimalHFForPartialLiquidation(ca) {
245
+ return require_sdk_market_math.optimalHFForPartialLiquidation(this.#borrowRate(ca));
246
+ }
247
+ /**
248
+ * Collateral token a partial liquidation seizes by default.
249
+ *
250
+ * Ported from solidity:
251
+ * https://github.com/Gearbox-protocol/router-v3/blob/main/contracts/liquidation/AbstractLiquidator.sol#L270
252
+ */
253
+ #bestTokenOut(ca) {
254
+ return require_sdk_market_credit_dominantCollateral.mustGetDominantCollateral(ca, this.market);
255
+ }
256
+ /**
257
+ * Minimum amount of `token` that must be seized when repaying `repaidAmount`
258
+ * of underlying.
259
+ */
260
+ #minSeizedAmount(token, repaidAmount) {
261
+ const { market } = this;
262
+ const tokenAmount = market.priceOracle.convert(market.underlying, token, repaidAmount);
263
+ return require_sdk_market_math.minSeizedAmount(tokenAmount, this.liquidationFees().liquidationDiscount);
264
+ }
265
+ /**
266
+ * Amount of underlying to repay to bring `ca`'s health factor close to
267
+ * `optimalHF` by seizing `token`.
268
+ *
269
+ * @throws If `token` is not a collateral token of this credit manager.
270
+ */
271
+ #optimalRepaidAmount(ca, token, optimalHF) {
272
+ const { creditManager: cm, market } = this;
273
+ const { feeLiquidation, liquidationDiscount } = this.liquidationFees();
274
+ const ltTokenOut = cm.liquidationThresholds.get(token);
275
+ if (ltTokenOut === void 0) throw new Error(`token ${this.labelAddress(token)} is not a collateral token in credit manager ${this.labelAddress(cm.address)}`);
276
+ return require_sdk_market_math.optimalRepaidAmount({
277
+ totalDebt: ca.debt + ca.accruedInterest + ca.accruedFees,
278
+ twvUnderlying: market.priceOracle.convertFromUSD(market.underlying, ca.twvUSD),
279
+ minDebt: this.creditFacade.minDebt,
280
+ optimalHF,
281
+ discount: BigInt(liquidationDiscount) - BigInt(feeLiquidation),
282
+ ltTokenOut: BigInt(ltTokenOut)
283
+ });
284
+ }
285
+ /**
286
+ * Blended annual cost of credit account's debt, in basis points: base interest weighted
287
+ * by the account's share of its own total debt, plus the quota rates of the
288
+ * collaterals it actually holds, both marked up by the interest fee.
289
+ */
290
+ #borrowRate(ca) {
291
+ const { creditManager } = this;
292
+ const { pool } = this.market;
293
+ const { feeInterest } = creditManager;
294
+ const { baseInterestRate } = pool.pool;
295
+ const baseRateWithFee = baseInterestRate * (BigInt(feeInterest) + require_sdk_constants_math.PERCENTAGE_FACTOR);
296
+ const totalDebt = ca.debt + ca.accruedInterest + ca.accruedFees;
297
+ const r = ca.debt * baseRateWithFee / (totalDebt * require_sdk_constants_math.RAY);
298
+ const caTokens = new require_sdk_utils_AddressMap.AddressMap(ca.tokens.map((t) => [t.token, t]));
299
+ let qr = 0n;
300
+ for (const t of creditManager.collateralTokens) {
301
+ const b = caTokens.get(t);
302
+ if (b) qr += b.quota * BigInt(pool.pqk.quotas.get(t)?.rate ?? 0);
303
+ }
304
+ qr = qr * (BigInt(feeInterest) + require_sdk_constants_math.PERCENTAGE_FACTOR) / require_sdk_constants_math.PERCENTAGE_FACTOR;
305
+ qr /= totalDebt;
306
+ return r + qr;
307
+ }
308
+ /**
203
309
  * Whether the facade, manager, or configurator has observed logs that require
204
310
  * a credit-suite resync.
205
311
  */
@@ -1,8 +1,9 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_sdk_utils_hex = require("../utils/hex.js");
3
- require("../utils/index.js");
4
- require("./constants.js");
5
- //#region src/sdk/accounts/dominantCollateral.ts
2
+ require("../../constants/math.js");
3
+ require("../../constants/index.js");
4
+ const require_sdk_utils_hex = require("../../utils/hex.js");
5
+ require("../../utils/index.js");
6
+ //#region src/sdk/market/credit/dominantCollateral.ts
6
7
  /**
7
8
  * The account's dominant collateral: the most valuable enabled non-underlying
8
9
  * token it holds above dust, by USD value.
@@ -29,5 +30,18 @@ function dominantCollateral(account, market) {
29
30
  }
30
31
  return dominant;
31
32
  }
33
+ /**
34
+ * {@link dominantCollateral}, for callers that cannot proceed without one, such
35
+ * as picking the collateral a partial liquidation seizes.
36
+ *
37
+ * @throws If the account holds no enabled non-underlying collateral the oracle
38
+ * can price.
39
+ **/
40
+ function mustGetDominantCollateral(account, market) {
41
+ const collateral = dominantCollateral(account, market);
42
+ if (!collateral) throw new Error(`cannot determine tokenOut for partial liquidation of ${market.sdk.labelAddress(account.creditAccount)}: no enabled non-underlying collateral with value`);
43
+ return collateral;
44
+ }
32
45
  //#endregion
33
46
  exports.dominantCollateral = dominantCollateral;
47
+ exports.mustGetDominantCollateral = mustGetDominantCollateral;
@@ -3,6 +3,7 @@ const require_sdk_market_credit_CreditConfiguratorV310Contract = require("./Cred
3
3
  const require_sdk_market_credit_CreditFacadeV310BaseContract = require("./CreditFacadeV310BaseContract.js");
4
4
  const require_sdk_market_credit_CreditFacadeV310Contract = require("./CreditFacadeV310Contract.js");
5
5
  const require_sdk_market_credit_CreditManagerV310Contract = require("./CreditManagerV310Contract.js");
6
+ const require_sdk_market_credit_dominantCollateral = require("./dominantCollateral.js");
6
7
  const require_sdk_market_credit_CreditSuite = require("./CreditSuite.js");
7
8
  require("./types.js");
8
9
  exports.CreditConfiguratorV310Contract = require_sdk_market_credit_CreditConfiguratorV310Contract.CreditConfiguratorV310Contract;
@@ -11,3 +12,5 @@ exports.CreditFacadeV310Contract = require_sdk_market_credit_CreditFacadeV310Con
11
12
  exports.CreditManagerV310Contract = require_sdk_market_credit_CreditManagerV310Contract.CreditManagerV310Contract;
12
13
  exports.CreditSuite = require_sdk_market_credit_CreditSuite.CreditSuite;
13
14
  exports.creditFacadeV310Abi = require_sdk_market_credit_CreditFacadeV310BaseContract.creditFacadeV310Abi;
15
+ exports.dominantCollateral = require_sdk_market_credit_dominantCollateral.dominantCollateral;
16
+ exports.mustGetDominantCollateral = require_sdk_market_credit_dominantCollateral.mustGetDominantCollateral;
@@ -6,6 +6,7 @@ const require_sdk_market_credit_CreditConfiguratorV310Contract = require("./cred
6
6
  const require_sdk_market_credit_CreditFacadeV310BaseContract = require("./credit/CreditFacadeV310BaseContract.js");
7
7
  const require_sdk_market_credit_CreditFacadeV310Contract = require("./credit/CreditFacadeV310Contract.js");
8
8
  const require_sdk_market_credit_CreditManagerV310Contract = require("./credit/CreditManagerV310Contract.js");
9
+ const require_sdk_market_credit_dominantCollateral = require("./credit/dominantCollateral.js");
9
10
  const require_sdk_market_credit_CreditSuite = require("./credit/CreditSuite.js");
10
11
  require("./credit/index.js");
11
12
  const require_sdk_market_pricefeeds_isUpdatablePriceFeed = require("./pricefeeds/isUpdatablePriceFeed.js");
@@ -112,9 +113,11 @@ exports.createAdapter = require_sdk_market_adapters_createAdapter.createAdapter;
112
113
  exports.createPriceOracle = require_sdk_market_oracle_createPriceOracle.createPriceOracle;
113
114
  exports.createZapper = require_sdk_market_zapper_createZapper.createZapper;
114
115
  exports.creditFacadeV310Abi = require_sdk_market_credit_CreditFacadeV310BaseContract.creditFacadeV310Abi;
116
+ exports.dominantCollateral = require_sdk_market_credit_dominantCollateral.dominantCollateral;
115
117
  exports.fetchPythPayloads = require_sdk_market_pricefeeds_updates_fetchPythPayloads.fetchPythPayloads;
116
118
  exports.fetchRedstonePayloads = require_sdk_market_pricefeeds_updates_fetchRedstonePayloads.fetchRedstonePayloads;
117
119
  exports.getRawPriceUpdates = require_sdk_market_pricefeeds_getRawPriceUpdates.getRawPriceUpdates;
118
120
  exports.isLPPriceFeed = require_sdk_market_pricefeeds_AbstractLPPriceFeed.isLPPriceFeed;
119
121
  exports.isRWAFactory = require_sdk_market_rwa_types.isRWAFactory;
120
122
  exports.isUpdatablePriceFeed = require_sdk_market_pricefeeds_isUpdatablePriceFeed.isUpdatablePriceFeed;
123
+ exports.mustGetDominantCollateral = require_sdk_market_credit_dominantCollateral.mustGetDominantCollateral;
@@ -130,11 +130,70 @@ function additionalBorrowApyBps(quotaRate, leverage) {
130
130
  if (!Number.isFinite(leverage)) return 0;
131
131
  return Math.round(quotaRate * Math.max(leverage - 1, 0));
132
132
  }
133
+ /**
134
+ * {@link PERCENTAGE_FACTOR} less a 0.1% safety buffer.
135
+ *
136
+ * Partial liquidation amounts are computed off prices that can drift between
137
+ * quoting and execution, so both the seized and the repaid amount are pulled
138
+ * this far away from the boundary the contracts would revert on.
139
+ **/
140
+ const PARTIAL_LIQUIDATION_BUFFER_BPS = 9990n;
141
+ /**
142
+ * Minimum collateral a partial liquidation must seize for a given repayment,
143
+ * derived from the liquidation discount and buffered by
144
+ * {@link PARTIAL_LIQUIDATION_BUFFER_BPS}.
145
+ *
146
+ * @param tokenAmount - Repaid amount converted from underlying into the seized
147
+ * token by the oracle.
148
+ * @param liquidationDiscount - Discount in effect for this account, in basis
149
+ * points (the expired variant once the credit manager has expired).
150
+ **/
151
+ function minSeizedAmount(tokenAmount, liquidationDiscount) {
152
+ return tokenAmount * PARTIAL_LIQUIDATION_BUFFER_BPS / BigInt(liquidationDiscount);
153
+ }
154
+ /**
155
+ * Amount of underlying whose repayment brings the account's health factor close
156
+ * to `optimalHF`, capped so the account keeps at least `minDebt` of debt.
157
+ *
158
+ * Ported from solidity:
159
+ * https://github.com/Gearbox-protocol/router-v3/blob/56e2d515ec6d9bb1e324e71c3708e59710779b24/contracts/liquidation/AbstractLiquidator.sol#L292
160
+ *
161
+ * @returns The repaid amount, or `0n` when the account is already healthy
162
+ * enough or carries less than the minimum debt.
163
+ * @throws If the discounted target health factor does not exceed the seized
164
+ * token's liquidation threshold, in which case no repayment improves the
165
+ * account.
166
+ **/
167
+ function optimalRepaidAmount({ totalDebt, twvUnderlying, minDebt, optimalHF, discount, ltTokenOut }) {
168
+ const denominator = discount * optimalHF / require_sdk_constants_math.PERCENTAGE_FACTOR - ltTokenOut;
169
+ if (denominator <= 0n) throw new Error("cannot compute optimal repaid amount: invalid liquidation parameters (discount * hfOptimal <= ltTokenOut)");
170
+ const numerator = totalDebt * optimalHF - twvUnderlying * require_sdk_constants_math.PERCENTAGE_FACTOR;
171
+ if (numerator <= 0n) return 0n;
172
+ const repaidAmount = numerator / denominator * discount / require_sdk_constants_math.PERCENTAGE_FACTOR;
173
+ if (totalDebt < minDebt) return 0n;
174
+ const surplusDebt = totalDebt - minDebt;
175
+ if (repaidAmount > surplusDebt) return surplusDebt * PARTIAL_LIQUIDATION_BUFFER_BPS / require_sdk_constants_math.PERCENTAGE_FACTOR;
176
+ return repaidAmount;
177
+ }
178
+ /**
179
+ * Health factor a partial liquidation should target, in basis points: just
180
+ * above 1, by enough to cover up to 1% of borrow cost so the account does not
181
+ * fall back under water immediately.
182
+ *
183
+ * @param borrowRate - Blended borrow rate of the account, in basis points.
184
+ **/
185
+ function optimalHFForPartialLiquidation(borrowRate) {
186
+ return require_sdk_constants_math.PERCENTAGE_FACTOR + (borrowRate < 100n ? borrowRate : 100n);
187
+ }
133
188
  //#endregion
189
+ exports.PARTIAL_LIQUIDATION_BUFFER_BPS = PARTIAL_LIQUIDATION_BUFFER_BPS;
134
190
  exports.additionalBorrowApyBps = additionalBorrowApyBps;
135
191
  exports.borrowApyBps = borrowApyBps;
136
192
  exports.healthFactorBps = healthFactorBps;
137
193
  exports.maxLeverage = maxLeverage;
194
+ exports.minSeizedAmount = minSeizedAmount;
195
+ exports.optimalHFForPartialLiquidation = optimalHFForPartialLiquidation;
196
+ exports.optimalRepaidAmount = optimalRepaidAmount;
138
197
  exports.positionLeverage = positionLeverage;
139
198
  exports.rayToBps = rayToBps;
140
199
  exports.usdToNumber = usdToNumber;
@@ -1,6 +1,8 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_sdk_utils_AddressMap = require("../../utils/AddressMap.js");
3
+ const require_sdk_utils_AddressSet = require("../../utils/AddressSet.js");
3
4
  const require_sdk_constants_address_provider = require("../../constants/address-provider.js");
5
+ require("../../constants/math.js");
4
6
  const require_sdk_constants_versions = require("../../constants/versions.js");
5
7
  require("../../constants/index.js");
6
8
  const require_sdk_utils_formatter = require("../../utils/formatter.js");
@@ -8,8 +10,9 @@ require("../../utils/index.js");
8
10
  const require_sdk_base_BaseContract = require("../../base/BaseContract.js");
9
11
  require("../../base/index.js");
10
12
  const require_sdk_market_math = require("../math.js");
11
- const require_sdk_market_pricefeeds_PriceFeedRef = require("../pricefeeds/PriceFeedRef.js");
12
13
  const require_abi_compressors_priceFeedCompressor = require("../../../abi/compressors/priceFeedCompressor.js");
14
+ const require_sdk_market_pricefeeds_PriceFeedRef = require("../pricefeeds/PriceFeedRef.js");
15
+ const require_sdk_market_pricefeeds_getRawPriceUpdates = require("../pricefeeds/getRawPriceUpdates.js");
13
16
  require("../pricefeeds/index.js");
14
17
  const require_sdk_market_oracle_PriceFeedAnswerMap = require("./PriceFeedAnswerMap.js");
15
18
  let viem = require("viem");
@@ -59,6 +62,31 @@ var PriceOracleBaseContract = class extends require_sdk_base_BaseContract.BaseCo
59
62
  return tokens.flatMap((t) => [main ? this.mainPriceFeeds.get(t)?.priceFeed : void 0, reserve ? this.reservePriceFeeds.get(t)?.priceFeed : void 0]).filter((f) => !!f);
60
63
  }
61
64
  /**
65
+ * {@inheritDoc IPriceOracleContract.priceUpdateTxsForAccount}
66
+ **/
67
+ async priceUpdateTxsForAccount(account, opts) {
68
+ return this.#priceUpdateTxsForTokens(getAccountTokens(account, opts?.extraTokens), opts);
69
+ }
70
+ /**
71
+ * {@inheritDoc IPriceOracleContract.priceUpdatesForAccount}
72
+ **/
73
+ async priceUpdatesForAccount(account, opts) {
74
+ return require_sdk_market_pricefeeds_getRawPriceUpdates.getRawPriceUpdates(await this.priceUpdateTxsForAccount(account, opts));
75
+ }
76
+ /**
77
+ * {@inheritDoc IPriceOracleContract.priceUpdatesForTokens}
78
+ **/
79
+ async priceUpdatesForTokens(tokens, opts) {
80
+ return require_sdk_market_pricefeeds_getRawPriceUpdates.getRawPriceUpdates(await this.#priceUpdateTxsForTokens(tokens, opts));
81
+ }
82
+ async #priceUpdateTxsForTokens(tokens, opts) {
83
+ const priceFeeds = this.priceFeedsForTokens(tokens, opts);
84
+ const tStr = tokens.map((t) => this.labelAddress(t)).join(", ");
85
+ const remark = opts?.reserve === false ? " main" : "";
86
+ this.logger?.debug(`generating price feed updates for ${tStr} from ${priceFeeds.length}${remark} price feeds`);
87
+ return this.sdk.priceFeeds.generatePriceFeedsUpdateTxs(priceFeeds);
88
+ }
89
+ /**
62
90
  * {@inheritDoc IPriceOracleContract.mainPrice}
63
91
  **/
64
92
  mainPrice(token) {
@@ -262,6 +290,18 @@ var PriceOracleBaseContract = class extends require_sdk_base_BaseContract.BaseCo
262
290
  }
263
291
  }
264
292
  };
293
+ /**
294
+ * Tokens of an account that have to be priced: its underlying, every enabled
295
+ * token it holds a non-dust balance of, and any extra tokens the caller adds.
296
+ **/
297
+ function getAccountTokens(account, extraTokens) {
298
+ const tokens = new require_sdk_utils_AddressSet.AddressSet([account.underlying, ...extraTokens ?? []]);
299
+ for (const t of account.tokens) {
300
+ const isEnabled = (t.mask & account.enabledTokensMask) !== 0n;
301
+ if (t.balance > 10n && isEnabled) tokens.add(t.token);
302
+ }
303
+ return tokens.asArray();
304
+ }
265
305
  function formatAnswer({ price, success, updatedAt }, raw = true) {
266
306
  if (!success) return "failed";
267
307
  let priceS = require_sdk_utils_formatter.formatBN(price, 8);
@@ -1,10 +1,7 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_abi_310_generated = require("../../../abi/310/generated.js");
3
3
  const require_sdk_utils_viem_simulateWithPriceUpdates = require("../../utils/viem/simulateWithPriceUpdates.js");
4
- const require_sdk_market_pricefeeds_getRawPriceUpdates = require("../pricefeeds/getRawPriceUpdates.js");
5
- require("../pricefeeds/index.js");
6
4
  const require_sdk_market_oracle_PriceOracleBaseContract = require("./PriceOracleBaseContract.js");
7
- let viem = require("viem");
8
5
  //#region src/sdk/market/oracle/PriceOracleV310Contract.ts
9
6
  const abi = require_abi_310_generated.iPriceOracleV310Abi;
10
7
  var PriceOracleV310Contract = class extends require_sdk_market_oracle_PriceOracleBaseContract.PriceOracleBaseContract {
@@ -16,33 +13,6 @@ var PriceOracleV310Contract = class extends require_sdk_market_oracle_PriceOracl
16
13
  }, data);
17
14
  }
18
15
  /**
19
- * Converts previously obtained price updates into CreditFacade multicall entry
20
- * @param creditFacade
21
- * @param updates
22
- * @returns
23
- */
24
- onDemandPriceUpdates(creditFacade, updates) {
25
- if (!updates) {
26
- this.logger?.debug("empty updates list");
27
- return {
28
- multicall: [],
29
- raw: []
30
- };
31
- }
32
- const raw = require_sdk_market_pricefeeds_getRawPriceUpdates.getRawPriceUpdates(updates);
33
- return {
34
- raw,
35
- multicall: [{
36
- target: creditFacade,
37
- callData: (0, viem.encodeFunctionData)({
38
- abi: require_abi_310_generated.iCreditFacadeMulticallV310Abi,
39
- functionName: "onDemandPriceUpdates",
40
- args: [raw]
41
- })
42
- }]
43
- };
44
- }
45
- /**
46
16
  * {@inheritDoc IPriceOracleContract.updateAndConvert}
47
17
  **/
48
18
  async updateAndConvert(from, to, amount) {
@@ -9,6 +9,7 @@ require("../../constants/index.js");
9
9
  require("../../utils/index.js");
10
10
  const require_sdk_base_SDKConstruct = require("../../base/SDKConstruct.js");
11
11
  require("../../base/index.js");
12
+ const require_abi_compressors_priceFeedCompressor = require("../../../abi/compressors/priceFeedCompressor.js");
12
13
  const require_sdk_market_pricefeeds_AbstractPriceFeed = require("./AbstractPriceFeed.js");
13
14
  const require_sdk_market_pricefeeds_BalancerStablePriceFeed = require("./BalancerStablePriceFeed.js");
14
15
  const require_sdk_market_pricefeeds_BalancerWeightedPriceFeed = require("./BalancerWeightedPriceFeed.js");
@@ -22,7 +23,6 @@ const require_sdk_market_pricefeeds_ExternalPriceFeed = require("./ExternalPrice
22
23
  const require_sdk_market_pricefeeds_getRawPriceUpdates = require("./getRawPriceUpdates.js");
23
24
  const require_sdk_market_pricefeeds_MellowLRTPriceFeed = require("./MellowLRTPriceFeed.js");
24
25
  const require_sdk_market_pricefeeds_PendleTWAPPTPriceFeed = require("./PendleTWAPPTPriceFeed.js");
25
- const require_abi_compressors_priceFeedCompressor = require("../../../abi/compressors/priceFeedCompressor.js");
26
26
  const require_sdk_utils_internal_Hooks = require("../../utils/internal/Hooks.js");
27
27
  require("../../utils/internal/index.js");
28
28
  const require_sdk_market_pricefeeds_ConstantPriceFeed = require("./ConstantPriceFeed.js");
@@ -4,10 +4,14 @@ const require_sdk_opportunities_MultichainOpportunitiesService = require("./Mult
4
4
  const require_sdk_opportunities_OpportunitiesService = require("./OpportunitiesService.js");
5
5
  exports.MultichainOpportunitiesService = require_sdk_opportunities_MultichainOpportunitiesService.MultichainOpportunitiesService;
6
6
  exports.OpportunitiesService = require_sdk_opportunities_OpportunitiesService.OpportunitiesService;
7
+ exports.PARTIAL_LIQUIDATION_BUFFER_BPS = require_sdk_market_math.PARTIAL_LIQUIDATION_BUFFER_BPS;
7
8
  exports.additionalBorrowApyBps = require_sdk_market_math.additionalBorrowApyBps;
8
9
  exports.borrowApyBps = require_sdk_market_math.borrowApyBps;
9
10
  exports.healthFactorBps = require_sdk_market_math.healthFactorBps;
10
11
  exports.maxLeverage = require_sdk_market_math.maxLeverage;
12
+ exports.minSeizedAmount = require_sdk_market_math.minSeizedAmount;
13
+ exports.optimalHFForPartialLiquidation = require_sdk_market_math.optimalHFForPartialLiquidation;
14
+ exports.optimalRepaidAmount = require_sdk_market_math.optimalRepaidAmount;
11
15
  exports.positionLeverage = require_sdk_market_math.positionLeverage;
12
16
  exports.rayToBps = require_sdk_market_math.rayToBps;
13
17
  exports.usdToNumber = require_sdk_market_math.usdToNumber;
@@ -276,7 +276,7 @@ var AccountOpener = class extends SDKConstruct {
276
276
  averageQuota,
277
277
  minQuota
278
278
  }, "calculated quotas");
279
- const { tx, calls } = await this.#service.openCA({
279
+ const tx = await this.#service.openCA({
280
280
  creditManager: cm.creditManager.address,
281
281
  averageQuota,
282
282
  minQuota,
@@ -291,10 +291,7 @@ var AccountOpener = class extends SDKConstruct {
291
291
  to: borrower.address,
292
292
  referralCode: 0n
293
293
  });
294
- for (let i = 0; i < calls.length; i++) {
295
- const call = calls[i];
296
- logger?.debug(`call #${i + 1}: ${this.sdk.parseFunctionData(call.target, call.callData)}`);
297
- }
294
+ logger?.debug(`open account tx: ${this.sdk.stringifyFunctionData(tx.to, tx.callData)}`);
298
295
  logger?.debug("prepared open account transaction");
299
296
  return {
300
297
  tx,