@gearbox-protocol/sdk 14.1.1 → 14.2.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 (40) hide show
  1. package/dist/cjs/dev/claimDSToken.js +208 -0
  2. package/dist/cjs/plugins/accounts/AccountsPlugin.js +1 -2
  3. package/dist/cjs/sdk/OnchainSDK.js +12 -0
  4. package/dist/cjs/sdk/accounts/CreditAccountsServiceV310.js +1448 -23
  5. package/dist/cjs/sdk/accounts/index.js +0 -4
  6. package/dist/cjs/sdk/market/credit/CreditFacadeV310Contract.js +6 -0
  7. package/dist/cjs/sdk/market/kyc/securitize/SecuritizeKYCFactory.js +19 -2
  8. package/dist/cjs/sdk/market/kyc/securitize/types.js +20 -0
  9. package/dist/cjs/sdk/market/oracle/PriceOracleV310Contract.js +26 -0
  10. package/dist/cjs/sdk/market/pricefeeds/PriceFeedsRegister.js +3 -0
  11. package/dist/esm/dev/claimDSToken.js +187 -0
  12. package/dist/esm/plugins/accounts/AccountsPlugin.js +2 -7
  13. package/dist/esm/sdk/OnchainSDK.js +14 -0
  14. package/dist/esm/sdk/accounts/CreditAccountsServiceV310.js +1466 -23
  15. package/dist/esm/sdk/accounts/index.js +0 -2
  16. package/dist/esm/sdk/accounts/multicall-utils.js +1 -5
  17. package/dist/esm/sdk/market/credit/CreditFacadeV310Contract.js +6 -0
  18. package/dist/esm/sdk/market/kyc/securitize/SecuritizeKYCFactory.js +21 -2
  19. package/dist/esm/sdk/market/kyc/securitize/types.js +12 -0
  20. package/dist/esm/sdk/market/oracle/PriceOracleV310Contract.js +26 -0
  21. package/dist/esm/sdk/market/pricefeeds/PriceFeedsRegister.js +3 -0
  22. package/dist/types/dev/claimDSToken.d.ts +34 -0
  23. package/dist/types/sdk/OnchainSDK.d.ts +10 -0
  24. package/dist/types/sdk/accounts/CreditAccountsServiceV310.d.ts +181 -3
  25. package/dist/types/sdk/accounts/index.d.ts +0 -2
  26. package/dist/types/sdk/accounts/types.d.ts +56 -0
  27. package/dist/types/sdk/market/credit/CreditFacadeV310Contract.d.ts +2 -0
  28. package/dist/types/sdk/market/kyc/securitize/SecuritizeKYCFactory.d.ts +1 -1
  29. package/dist/types/sdk/market/kyc/securitize/types.d.ts +37 -22
  30. package/dist/types/sdk/market/oracle/PriceOracleBaseContract.d.ts +5 -0
  31. package/dist/types/sdk/market/oracle/PriceOracleV310Contract.d.ts +4 -0
  32. package/dist/types/sdk/market/oracle/types.d.ts +9 -0
  33. package/dist/types/sdk/pools/types.d.ts +19 -0
  34. package/package.json +1 -1
  35. package/dist/cjs/sdk/accounts/AbstractCreditAccountsService.js +0 -1411
  36. package/dist/cjs/sdk/accounts/createCreditAccountService.js +0 -35
  37. package/dist/esm/sdk/accounts/AbstractCreditAccountsService.js +0 -1405
  38. package/dist/esm/sdk/accounts/createCreditAccountService.js +0 -11
  39. package/dist/types/sdk/accounts/AbstractCreditAccountsService.d.ts +0 -226
  40. package/dist/types/sdk/accounts/createCreditAccountService.d.ts +0 -9
@@ -1,1411 +0,0 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
- var AbstractCreditAccountsService_exports = {};
20
- __export(AbstractCreditAccountsService_exports, {
21
- AbstractCreditAccountService: () => AbstractCreditAccountService,
22
- getWithdrawalCompressorAddress: () => getWithdrawalCompressorAddress
23
- });
24
- module.exports = __toCommonJS(AbstractCreditAccountsService_exports);
25
- var import_integrations_v3 = require("@gearbox-protocol/integrations-v3");
26
- var import_viem = require("viem");
27
- var import_generated = require("../../abi/310/generated.js");
28
- var import_creditAccountCompressor = require("../../abi/compressors/creditAccountCompressor.js");
29
- var import_peripheryCompressor = require("../../abi/compressors/peripheryCompressor.js");
30
- var import_rewardsCompressor = require("../../abi/compressors/rewardsCompressor.js");
31
- var import_IWithdrawalCompressorV310 = require("../../abi/IWithdrawalCompressorV310.js");
32
- var import_iBaseRewardPool = require("../../abi/iBaseRewardPool.js");
33
- var import_iKYCFactory = require("../../abi/kyc/iKYCFactory.js");
34
- var import_base = require("../base/index.js");
35
- var import_chains = require("../chain/chains.js");
36
- var import_constants = require("../constants/index.js");
37
- var import_market = require("../market/index.js");
38
- var import_router = require("../router/index.js");
39
- var import_utils = require("../utils/index.js");
40
- var import_viem2 = require("../utils/viem/index.js");
41
- var import_multicall_utils = require("./multicall-utils.js");
42
- const COMPRESSORS = {
43
- [import_chains.chains.Mainnet.id]: "0x36F3d0Bb73CBC2E94fE24dF0f26a689409cF9023",
44
- [import_chains.chains.Monad.id]: "0x36F3d0Bb73CBC2E94fE24dF0f26a689409cF9023"
45
- };
46
- function getWithdrawalCompressorAddress(chainId) {
47
- return COMPRESSORS[chainId];
48
- }
49
- class AbstractCreditAccountService extends import_base.SDKConstruct {
50
- #compressor;
51
- #batchSize;
52
- constructor(sdk, options) {
53
- super(sdk);
54
- [this.#compressor] = sdk.addressProvider.mustGetLatest(
55
- import_constants.AP_CREDIT_ACCOUNT_COMPRESSOR,
56
- import_constants.VERSION_RANGE_310
57
- );
58
- this.#batchSize = options?.batchSize;
59
- this.logger?.debug(
60
- `credit account compressor address: ${this.#compressor}`
61
- );
62
- }
63
- /**
64
- * {@inheritDoc ICreditAccountsService.getCreditAccountData}
65
- **/
66
- async getCreditAccountData(account, blockNumber) {
67
- let raw;
68
- try {
69
- raw = await this.client.readContract({
70
- abi: import_creditAccountCompressor.creditAccountCompressorAbi,
71
- address: this.#compressor,
72
- functionName: "getCreditAccountData",
73
- args: [account],
74
- blockNumber,
75
- // @ts-expect-error
76
- gas: this.sdk.gasLimit
77
- });
78
- } catch (_e) {
79
- return void 0;
80
- }
81
- const marketSuite = this.sdk.marketRegister.findByCreditManager(
82
- raw.creditManager
83
- );
84
- const factory = marketSuite.kycFactory;
85
- let ca;
86
- let investor;
87
- if (raw.success) {
88
- ca = raw;
89
- investor = await factory?.getInvestor(raw.creditAccount, false);
90
- } else {
91
- const { txs: priceUpdateTxs } = await this.getUpdateForAccount(raw);
92
- [ca, investor] = await (0, import_viem2.simulateWithPriceUpdates)(this.client, {
93
- priceUpdates: priceUpdateTxs,
94
- contracts: [
95
- {
96
- abi: import_creditAccountCompressor.creditAccountCompressorAbi,
97
- address: this.#compressor,
98
- functionName: "getCreditAccountData",
99
- args: [account]
100
- },
101
- ...factory ? [
102
- {
103
- abi: import_iKYCFactory.iKYCFactoryAbi,
104
- address: factory.address,
105
- functionName: "getInvestor",
106
- args: [raw.creditAccount]
107
- }
108
- ] : []
109
- ],
110
- blockNumber,
111
- gas: this.sdk.gasLimit
112
- });
113
- }
114
- return { ...ca, investor };
115
- }
116
- /**
117
- * {@inheritDoc ICreditAccountsService.getCreditAccounts}
118
- **/
119
- async getCreditAccounts(options, blockNumber) {
120
- const {
121
- creditManager,
122
- includeZeroDebt = false,
123
- maxHealthFactor = import_constants.MAX_UINT256,
124
- minHealthFactor = 0n,
125
- owner = import_constants.ADDRESS_0X0,
126
- ignoreReservePrices = false
127
- } = options ?? {};
128
- const arg0 = creditManager ?? {
129
- configurators: this.marketConfigurators,
130
- creditManagers: [],
131
- pools: [],
132
- underlying: import_constants.ADDRESS_0X0
133
- };
134
- const caFilter = {
135
- owner,
136
- includeZeroDebt,
137
- minHealthFactor,
138
- maxHealthFactor,
139
- reverting: false
140
- };
141
- const { txs: priceUpdateTxs } = await this.sdk.priceFeeds.generatePriceFeedsUpdateTxs(
142
- ignoreReservePrices ? { main: true } : void 0
143
- );
144
- const allCAs = [];
145
- let revertingOffset = 0;
146
- for (const reverting of [false, true]) {
147
- let offset = 0n;
148
- revertingOffset = allCAs.length;
149
- do {
150
- const [accounts, newOffset] = await this.#getCreditAccounts(
151
- this.#batchSize ? [
152
- arg0,
153
- { ...caFilter, reverting },
154
- offset,
155
- BigInt(this.#batchSize)
156
- // limit
157
- ] : [arg0, { ...caFilter, reverting }, offset],
158
- priceUpdateTxs,
159
- blockNumber
160
- );
161
- allCAs.push(...accounts);
162
- offset = newOffset;
163
- } while (offset !== 0n);
164
- }
165
- this.logger?.debug(
166
- `loaded ${allCAs.length} credit accounts (${allCAs.length - revertingOffset} reverting)`
167
- );
168
- return allCAs.sort((a, b) => Number(a.healthFactor - b.healthFactor));
169
- }
170
- /**
171
- * {@inheritDoc ICreditAccountsService.getBorrowerCreditAccounts}
172
- **/
173
- async getBorrowerCreditAccounts(borrower, options, blockNumber) {
174
- const {
175
- creditManager,
176
- includeZeroDebt = false,
177
- maxHealthFactor = import_constants.MAX_UINT256,
178
- minHealthFactor = 0n,
179
- ignoreReservePrices = false
180
- } = options ?? {};
181
- const { txs: priceUpdateTxs } = await this.sdk.priceFeeds.generatePriceFeedsUpdateTxs(
182
- ignoreReservePrices ? { main: true } : void 0
183
- );
184
- const investorDataList = await this.sdk.kyc.getInvestorData(borrower);
185
- const kycAccountAddresses = investorDataList.flatMap(
186
- (d) => d.creditAccounts.map((ca) => ca.creditAccount)
187
- );
188
- const cmFilter = creditManager ? {
189
- configurators: [],
190
- creditManagers: [creditManager],
191
- pools: [],
192
- underlying: import_constants.ADDRESS_0X0
193
- } : {
194
- configurators: this.marketConfigurators,
195
- creditManagers: [],
196
- pools: [],
197
- underlying: import_constants.ADDRESS_0X0
198
- };
199
- const permissiveFilter = {
200
- owner: borrower,
201
- includeZeroDebt: true,
202
- minHealthFactor: 0n,
203
- maxHealthFactor: import_constants.MAX_UINT256,
204
- reverting: false
205
- };
206
- const kycContracts = kycAccountAddresses.map(
207
- (account) => ({
208
- abi: import_creditAccountCompressor.creditAccountCompressorAbi,
209
- address: this.#compressor,
210
- functionName: "getCreditAccountData",
211
- args: [account]
212
- })
213
- );
214
- const getCreditAccountsContracts = [false, true].map(
215
- (reverting) => ({
216
- abi: import_creditAccountCompressor.creditAccountCompressorAbi,
217
- address: this.#compressor,
218
- functionName: "getCreditAccounts",
219
- args: [cmFilter, { ...permissiveFilter, reverting }, 0n]
220
- })
221
- );
222
- const allContracts = [...kycContracts, ...getCreditAccountsContracts];
223
- const results = await (0, import_viem2.simulateWithPriceUpdates)(this.client, {
224
- priceUpdates: priceUpdateTxs,
225
- contracts: allContracts,
226
- blockNumber,
227
- gas: this.sdk.gasLimit
228
- });
229
- const kycResults = results.slice(
230
- 0,
231
- kycAccountAddresses.length
232
- );
233
- const normalResults = results.slice(kycAccountAddresses.length);
234
- const seen = new import_utils.AddressSet();
235
- const allCAs = [];
236
- for (const ca of kycResults) {
237
- if (!seen.has(ca.creditAccount)) {
238
- seen.add(ca.creditAccount);
239
- allCAs.push({ ...ca, investor: borrower });
240
- }
241
- }
242
- for (const [accounts] of normalResults) {
243
- for (const ca of accounts) {
244
- if (!seen.has(ca.creditAccount)) {
245
- seen.add(ca.creditAccount);
246
- allCAs.push({ ...ca, investor: void 0 });
247
- }
248
- }
249
- }
250
- const filtered = allCAs.filter((ca) => {
251
- if (!includeZeroDebt && ca.debt === 0n) return false;
252
- if (ca.healthFactor < minHealthFactor) return false;
253
- if (ca.healthFactor > maxHealthFactor) return false;
254
- if (creditManager && !(0, import_utils.hexEq)(ca.creditManager, creditManager))
255
- return false;
256
- return true;
257
- });
258
- this.logger?.debug(
259
- `loaded ${allCAs.length} borrower credit accounts (${kycResults.length} KYC, ${filtered.length} after filter)`
260
- );
261
- return filtered.sort((a, b) => Number(a.healthFactor - b.healthFactor));
262
- }
263
- /**
264
- * {@inheritDoc ICreditAccountsService.getRewards}
265
- **/
266
- async getRewards(creditAccount) {
267
- const rewards = await this.client.readContract({
268
- abi: import_rewardsCompressor.rewardsCompressorAbi,
269
- address: this.rewardCompressor,
270
- functionName: "getRewards",
271
- args: [creditAccount]
272
- });
273
- const callData = (0, import_viem.encodeFunctionData)({
274
- abi: import_iBaseRewardPool.iBaseRewardPoolAbi,
275
- functionName: "getReward",
276
- args: []
277
- });
278
- const r = rewards.reduce((acc, r2) => {
279
- const adapter = r2.adapter.toLowerCase();
280
- const stakedPhantomToken = r2.stakedPhantomToken.toLowerCase();
281
- const rewardToken = r2.rewardToken.toLowerCase();
282
- const key = [adapter, stakedPhantomToken].join("-");
283
- if (!acc[key]) {
284
- acc[key] = {
285
- adapter,
286
- stakedPhantomToken,
287
- calls: [
288
- {
289
- target: adapter,
290
- callData
291
- }
292
- ],
293
- rewards: []
294
- };
295
- }
296
- acc[key].rewards.push({
297
- token: rewardToken,
298
- balance: r2.amount
299
- });
300
- return acc;
301
- }, {});
302
- return Object.values(r);
303
- }
304
- /**
305
- * {@inheritDoc ICreditAccountsService.getConnectedBots}
306
- **/
307
- async getConnectedBots(accountsToCheck, legacyMigrationBot, additionalBots) {
308
- const allResp = await this.client.multicall({
309
- contracts: [
310
- ...accountsToCheck.map((o) => {
311
- const pool = this.sdk.marketRegister.findByCreditManager(
312
- o.creditManager
313
- );
314
- return {
315
- abi: import_peripheryCompressor.peripheryCompressorAbi,
316
- address: this.peripheryCompressor,
317
- functionName: "getConnectedBots",
318
- args: [pool.configurator.address, o.creditAccount]
319
- };
320
- }),
321
- ...legacyMigrationBot ? accountsToCheck.map((ca) => {
322
- const cm = this.sdk.marketRegister.findCreditManager(
323
- ca.creditManager
324
- );
325
- return {
326
- abi: import_generated.iBotListV310Abi,
327
- address: cm.creditFacade.botList,
328
- functionName: "getBotStatus",
329
- args: [legacyMigrationBot, ca.creditAccount]
330
- };
331
- }) : [],
332
- ...accountsToCheck.flatMap((ca) => {
333
- const cm = this.sdk.marketRegister.findCreditManager(
334
- ca.creditManager
335
- );
336
- return additionalBots.map((bot) => {
337
- return {
338
- abi: import_generated.iBotListV310Abi,
339
- address: cm.creditFacade.botList,
340
- functionName: "getBotStatus",
341
- args: [bot, ca.creditAccount]
342
- };
343
- });
344
- })
345
- ],
346
- allowFailure: true,
347
- batchSize: 0
348
- });
349
- const legacyStart = 0;
350
- const legacyEnd = accountsToCheck.length;
351
- const legacy = allResp.slice(
352
- legacyStart,
353
- legacyEnd
354
- );
355
- const migrationStart = legacyEnd;
356
- const migrationEnd = legacyMigrationBot ? migrationStart + accountsToCheck.length : migrationStart;
357
- const migrationResp = allResp.slice(
358
- migrationStart,
359
- migrationEnd
360
- );
361
- const additionalStart = migrationEnd;
362
- const additionalResp = allResp.slice(
363
- additionalStart
364
- );
365
- return {
366
- legacy,
367
- additionalBots: this.#getActiveBots(
368
- accountsToCheck,
369
- additionalBots,
370
- additionalResp
371
- ),
372
- legacyMigration: this.#getActiveMigrationBots(
373
- accountsToCheck,
374
- legacyMigrationBot,
375
- migrationResp
376
- )
377
- };
378
- }
379
- #getActiveBots(accountsToCheck, bots, result) {
380
- if (result.length !== bots.length * accountsToCheck.length) {
381
- console.error(
382
- "result length mismatch",
383
- result.length,
384
- bots.length * accountsToCheck.length
385
- );
386
- }
387
- const botsByCAIndex = accountsToCheck.reduce((acc, _, index) => {
388
- const r = result.slice(index * bots.length, (index + 1) * bots.length);
389
- acc.push({
390
- result: r
391
- });
392
- return acc;
393
- }, []);
394
- return botsByCAIndex;
395
- }
396
- #getActiveMigrationBots(accountsToCheck, bot, result) {
397
- if (bot) {
398
- if (result.length !== accountsToCheck.length) {
399
- console.error(
400
- "result length mismatch for migration bots",
401
- result.length,
402
- accountsToCheck.length
403
- );
404
- }
405
- return { result, botAddress: bot };
406
- }
407
- return void 0;
408
- }
409
- /**
410
- * {@inheritDoc ICreditAccountsService.fullyLiquidate}
411
- **/
412
- async fullyLiquidate(props) {
413
- const {
414
- account,
415
- to,
416
- slippage = 50n,
417
- keepAssets,
418
- ignoreReservePrices,
419
- applyLossPolicy,
420
- debtOnly
421
- } = props;
422
- const cm = this.sdk.marketRegister.findCreditManager(account.creditManager);
423
- const routerCloseResult = await this.sdk.routerFor(account).findBestClosePath({
424
- creditAccount: account,
425
- creditManager: cm.creditManager,
426
- slippage,
427
- keepAssets,
428
- debtOnly
429
- });
430
- const calls = await this.prependPriceUpdates(
431
- account.creditManager,
432
- routerCloseResult.calls,
433
- account,
434
- { ignoreReservePrices }
435
- );
436
- let lossPolicyData;
437
- if (applyLossPolicy) {
438
- const market = this.sdk.marketRegister.findByCreditManager(
439
- account.creditManager
440
- );
441
- lossPolicyData = await market.lossPolicy.getLiquidationData(
442
- account.creditAccount
443
- );
444
- this.logger?.debug({ lossPolicyData }, "loss policy data");
445
- }
446
- const tx = cm.creditFacade.liquidateCreditAccount(
447
- account.creditAccount,
448
- to,
449
- calls,
450
- lossPolicyData
451
- );
452
- return {
453
- tx,
454
- calls,
455
- routerCloseResult,
456
- lossPolicyData,
457
- creditFacade: cm.creditFacade
458
- };
459
- }
460
- /**
461
- * {@inheritDoc ICreditAccountsService.closeCreditAccount}
462
- **/
463
- async closeCreditAccount({
464
- operation,
465
- assetsToWithdraw,
466
- creditAccount: ca,
467
- to,
468
- slippage = 50n,
469
- closePath
470
- }) {
471
- const cm = this.sdk.marketRegister.findCreditManager(ca.creditManager);
472
- await this.sdk.tokensMeta.loadTokenData(cm.underlying);
473
- const underlying = this.sdk.tokensMeta.mustGet(cm.underlying);
474
- if (this.sdk.tokensMeta.isKYCUnderlying(underlying)) {
475
- throw new Error(
476
- "closeCreditAccount is not supported for KYC underlying credit accounts"
477
- );
478
- }
479
- const routerCloseResult = closePath || await this.sdk.routerFor(ca).findBestClosePath({
480
- creditAccount: ca,
481
- creditManager: cm.creditManager,
482
- slippage
483
- });
484
- const operationCalls = [
485
- ...routerCloseResult.calls,
486
- ...this.prepareDisableQuotas(ca),
487
- ...this.prepareDecreaseDebt(ca),
488
- ...assetsToWithdraw.map(
489
- (t) => this.prepareWithdrawToken(ca.creditFacade, t, import_constants.MAX_UINT256, to)
490
- )
491
- ];
492
- const calls = operation === "close" ? operationCalls : await this.prependPriceUpdates(ca.creditManager, operationCalls, ca);
493
- const tx = await this.closeCreditAccountTx(
494
- cm,
495
- ca.creditAccount,
496
- calls,
497
- operation
498
- );
499
- return { tx, calls, routerCloseResult, creditFacade: cm.creditFacade };
500
- }
501
- /**
502
- * {@inheritDoc ICreditAccountsService.updateQuotas}
503
- **/
504
- async updateQuotas({
505
- minQuota,
506
- averageQuota,
507
- creditAccount
508
- }) {
509
- const cm = this.sdk.marketRegister.findCreditManager(
510
- creditAccount.creditManager
511
- );
512
- const operationCalls = this.prepareUpdateQuotas(
513
- creditAccount.creditFacade,
514
- { minQuota, averageQuota }
515
- );
516
- const calls = await this.prependPriceUpdates(
517
- creditAccount.creditManager,
518
- operationCalls,
519
- creditAccount
520
- );
521
- const tx = await this.multicallTx(cm, creditAccount.creditAccount, calls);
522
- return { tx, calls, creditFacade: cm.creditFacade };
523
- }
524
- /**
525
- * {@inheritDoc ICreditAccountsService.addCollateral}
526
- **/
527
- async addCollateral({
528
- creditAccount,
529
- asset,
530
- permit,
531
- ethAmount,
532
- minQuota,
533
- averageQuota
534
- }) {
535
- const cm = this.sdk.marketRegister.findCreditManager(
536
- creditAccount.creditManager
537
- );
538
- const operationCalls = [
539
- ...this.prepareAddCollateral(
540
- creditAccount.creditFacade,
541
- [asset],
542
- permit ? { [asset.token]: permit } : {}
543
- ),
544
- ...this.prepareUpdateQuotas(creditAccount.creditFacade, {
545
- minQuota,
546
- averageQuota
547
- })
548
- ];
549
- const calls = await this.prependPriceUpdates(
550
- creditAccount.creditManager,
551
- operationCalls,
552
- creditAccount
553
- );
554
- const tx = await this.multicallTx(cm, creditAccount.creditAccount, calls);
555
- tx.value = ethAmount.toString(10);
556
- return { tx, calls, creditFacade: cm.creditFacade };
557
- }
558
- /**
559
- * {@inheritDoc ICreditAccountsService.changeDebt}
560
- **/
561
- async changeDebt({
562
- creditAccount,
563
- amount,
564
- collateral
565
- }) {
566
- if (amount === 0n) {
567
- throw new Error("debt increase or decrease must be non-zero");
568
- }
569
- const isDecrease = amount < 0n;
570
- const change = amount > 0n ? amount : -amount;
571
- const cm = this.sdk.marketRegister.findCreditManager(
572
- creditAccount.creditManager
573
- );
574
- const addCollateralCalls = collateral && isDecrease ? this.prepareAddCollateral(
575
- creditAccount.creditFacade,
576
- [
577
- {
578
- token: collateral[0].token,
579
- balance: collateral[0].balance
580
- }
581
- ],
582
- {}
583
- ) : [];
584
- const unwrapCalls = collateral && isDecrease ? await this.getKYCUnwrapCalls(
585
- collateral[0].balance,
586
- creditAccount.creditManager
587
- ) || [] : [];
588
- if (addCollateralCalls.length > 0 && unwrapCalls.length === 0 && collateral && collateral?.[0].token !== creditAccount.underlying) {
589
- throw new Error(
590
- "Can't use collateral other than underlying for non KYC market"
591
- );
592
- }
593
- const operationCalls = [
594
- ...addCollateralCalls,
595
- ...unwrapCalls,
596
- this.#prepareChangeDebt(creditAccount.creditFacade, change, isDecrease)
597
- ];
598
- const calls = await this.prependPriceUpdates(
599
- creditAccount.creditManager,
600
- operationCalls,
601
- creditAccount
602
- );
603
- const tx = await this.multicallTx(cm, creditAccount.creditAccount, calls);
604
- return { tx, calls, creditFacade: cm.creditFacade };
605
- }
606
- /**
607
- * {@inheritDoc ICreditAccountsService.executeSwap}
608
- **/
609
- async executeSwap({
610
- creditAccount,
611
- calls: swapCalls,
612
- minQuota,
613
- averageQuota
614
- }) {
615
- if (swapCalls.length === 0) throw new Error("No path to execute");
616
- const cm = this.sdk.marketRegister.findCreditManager(
617
- creditAccount.creditManager
618
- );
619
- const operationCalls = [
620
- ...swapCalls,
621
- ...this.prepareUpdateQuotas(creditAccount.creditFacade, {
622
- minQuota,
623
- averageQuota
624
- })
625
- ];
626
- const calls = await this.prependPriceUpdates(
627
- creditAccount.creditManager,
628
- operationCalls,
629
- creditAccount
630
- );
631
- const tx = await this.multicallTx(cm, creditAccount.creditAccount, calls);
632
- return { tx, calls, creditFacade: cm.creditFacade };
633
- }
634
- /**
635
- * {@inheritDoc ICreditAccountsService.previewDelayedWithdrawal}
636
- **/
637
- async previewDelayedWithdrawal({
638
- creditAccount,
639
- amount,
640
- token
641
- }) {
642
- const compressor = getWithdrawalCompressorAddress(this.sdk.chainId);
643
- if (!compressor)
644
- throw new Error(
645
- `No compressor for current chain ${this.sdk.networkType}`
646
- );
647
- const contract = (0, import_viem.getContract)({
648
- address: compressor,
649
- abi: import_IWithdrawalCompressorV310.iWithdrawalCompressorV310Abi,
650
- client: this.client
651
- });
652
- const resp = await contract.read.getWithdrawalRequestResult([
653
- creditAccount,
654
- token,
655
- amount
656
- ]);
657
- return resp;
658
- }
659
- /**
660
- * {@inheritDoc ICreditAccountsService.getPendingWithdrawals}
661
- **/
662
- async getPendingWithdrawals({
663
- creditAccount
664
- }) {
665
- const compressor = getWithdrawalCompressorAddress(this.sdk.chainId);
666
- if (!compressor)
667
- throw new Error(
668
- `No compressor for current chain ${this.sdk.networkType}`
669
- );
670
- const contract = (0, import_viem.getContract)({
671
- address: compressor,
672
- abi: import_IWithdrawalCompressorV310.iWithdrawalCompressorV310Abi,
673
- client: this.client
674
- });
675
- const resp = await contract.read.getCurrentWithdrawals([creditAccount]);
676
- const claimableNow = resp?.[0] || [];
677
- const pendingResult = [...resp?.[1] || []].sort(
678
- (a, b) => a.claimableAt < b.claimableAt ? -1 : 1
679
- );
680
- const respResult = {
681
- claimableNow: [...claimableNow],
682
- pending: pendingResult
683
- };
684
- return respResult;
685
- }
686
- /**
687
- * {@inheritDoc ICreditAccountsService.startDelayedWithdrawal}
688
- **/
689
- async startDelayedWithdrawal({
690
- creditAccount,
691
- minQuota,
692
- averageQuota,
693
- preview
694
- }) {
695
- const cm = this.sdk.marketRegister.findCreditManager(
696
- creditAccount.creditManager
697
- );
698
- const record = preview.outputs.reduce((acc, o) => {
699
- const token = o.token.toLowerCase();
700
- acc[token] = (acc[token] || 0n) + o.amount;
701
- return acc;
702
- }, {});
703
- const balances = Object.entries(record).filter(([, a]) => a > 10n);
704
- const storeExpectedBalances = {
705
- target: cm.creditFacade.address,
706
- callData: (0, import_viem.encodeFunctionData)({
707
- abi: import_generated.iCreditFacadeMulticallV310Abi,
708
- functionName: "storeExpectedBalances",
709
- args: [
710
- balances.map(([token, amount]) => ({
711
- token,
712
- amount: amount > 10n ? amount - 10n : 0n
713
- }))
714
- ]
715
- })
716
- };
717
- const compareBalances = {
718
- target: cm.creditFacade.address,
719
- callData: (0, import_viem.encodeFunctionData)({
720
- abi: import_generated.iCreditFacadeMulticallV310Abi,
721
- functionName: "compareBalances",
722
- args: []
723
- })
724
- };
725
- const operationCalls = [
726
- storeExpectedBalances,
727
- ...preview.requestCalls,
728
- compareBalances,
729
- ...this.prepareUpdateQuotas(creditAccount.creditFacade, {
730
- minQuota,
731
- averageQuota
732
- })
733
- ];
734
- const calls = await this.prependPriceUpdates(
735
- creditAccount.creditManager,
736
- operationCalls,
737
- creditAccount
738
- );
739
- const tx = await this.multicallTx(cm, creditAccount.creditAccount, calls);
740
- return { tx, calls, creditFacade: cm.creditFacade };
741
- }
742
- /**
743
- * {@inheritDoc ICreditAccountsService.claimDelayed}
744
- **/
745
- async claimDelayed({
746
- creditAccount,
747
- minQuota,
748
- averageQuota,
749
- claimableNow
750
- }) {
751
- const zeroDebt = creditAccount.debt === 0n;
752
- const cm = this.sdk.marketRegister.findCreditManager(
753
- creditAccount.creditManager
754
- );
755
- const record = claimableNow.outputs.reduce(
756
- (acc, o) => {
757
- const token = o.token.toLowerCase();
758
- acc[token] = (acc[token] || 0n) + o.amount;
759
- return acc;
760
- },
761
- {}
762
- );
763
- const balances = Object.entries(record).filter(([, a]) => a > 10n);
764
- const storeExpectedBalances = {
765
- target: cm.creditFacade.address,
766
- callData: (0, import_viem.encodeFunctionData)({
767
- abi: import_generated.iCreditFacadeMulticallV310Abi,
768
- functionName: "storeExpectedBalances",
769
- args: [
770
- balances.map(([token, amount]) => ({
771
- token,
772
- amount: amount > 10n ? amount - 10n : 0n
773
- }))
774
- ]
775
- })
776
- };
777
- const compareBalances = {
778
- target: cm.creditFacade.address,
779
- callData: (0, import_viem.encodeFunctionData)({
780
- abi: import_generated.iCreditFacadeMulticallV310Abi,
781
- functionName: "compareBalances",
782
- args: []
783
- })
784
- };
785
- const quotaCalls = zeroDebt ? [] : this.prepareUpdateQuotas(creditAccount.creditFacade, {
786
- minQuota,
787
- averageQuota
788
- });
789
- const operationCalls = [
790
- storeExpectedBalances,
791
- ...claimableNow.claimCalls,
792
- compareBalances,
793
- ...quotaCalls
794
- ];
795
- const calls = zeroDebt ? operationCalls : await this.prependPriceUpdates(
796
- creditAccount.creditManager,
797
- operationCalls,
798
- creditAccount
799
- );
800
- const tx = await this.multicallTx(cm, creditAccount.creditAccount, calls);
801
- return { tx, calls, creditFacade: cm.creditFacade };
802
- }
803
- /**
804
- * {@inheritDoc ICreditAccountsService.getApprovalAddress}
805
- **/
806
- async getApprovalAddress(options) {
807
- const { creditManager } = options;
808
- const suite = this.sdk.marketRegister.findCreditManager(creditManager);
809
- const marketSuite = this.sdk.marketRegister.findByPool(suite.pool);
810
- const factory = marketSuite.kycFactory;
811
- if (factory) {
812
- return factory.getApprovalAddress(options);
813
- }
814
- return suite.creditManager.address;
815
- }
816
- /**
817
- * {@inheritDoc ICreditAccountsService.getOpenAccountRequirements}
818
- */
819
- async getOpenAccountRequirements(borrower, creditManager, props) {
820
- const { kycFactory } = this.sdk.marketRegister.findByCreditManager(creditManager);
821
- if (!kycFactory) {
822
- return void 0;
823
- }
824
- return kycFactory.getOpenAccountRequirements(borrower, props);
825
- }
826
- /**
827
- * {@inheritDoc ICreditAccountsService.openCA}
828
- **/
829
- async openCA(props) {
830
- const {
831
- ethAmount,
832
- creditManager,
833
- reopenCreditAccount,
834
- collateral,
835
- permits,
836
- debt,
837
- withdrawToken,
838
- referralCode,
839
- to,
840
- calls: openPathCalls,
841
- callsAfter,
842
- minQuota,
843
- averageQuota,
844
- kycOptions
845
- } = props;
846
- const cmSuite = this.sdk.marketRegister.findCreditManager(creditManager);
847
- const cm = cmSuite.creditManager;
848
- let tokenToWithdraw;
849
- if (withdrawToken === true) {
850
- tokenToWithdraw = cm.underlying;
851
- } else if (typeof withdrawToken === "string") {
852
- tokenToWithdraw = withdrawToken;
853
- }
854
- const operationCalls = [
855
- this.#prepareIncreaseDebt(cm.creditFacade, debt),
856
- ...this.prepareAddCollateral(cm.creditFacade, collateral, permits),
857
- ...openPathCalls,
858
- // path from underlying to withdrawal token
859
- ...tokenToWithdraw ? [
860
- this.prepareWithdrawToken(
861
- cm.creditFacade,
862
- tokenToWithdraw,
863
- import_constants.MAX_UINT256,
864
- to
865
- )
866
- ] : [],
867
- ...this.prepareUpdateQuotas(cm.creditFacade, {
868
- minQuota,
869
- averageQuota
870
- }),
871
- ...callsAfter ?? []
872
- ];
873
- const calls = await this.prependPriceUpdates(cm.address, operationCalls);
874
- let tx;
875
- if (reopenCreditAccount) {
876
- tx = await this.multicallTx(cmSuite, reopenCreditAccount, calls);
877
- } else {
878
- tx = await this.openCreditAccountTx(
879
- cmSuite,
880
- to,
881
- calls,
882
- referralCode,
883
- kycOptions
884
- );
885
- }
886
- tx.value = ethAmount.toString(10);
887
- return { calls, tx, creditFacade: cmSuite.creditFacade };
888
- }
889
- /**
890
- * {@inheritDoc ICreditAccountsService.getBorrowRate}
891
- **/
892
- getBorrowRate(ca) {
893
- const { creditManager } = this.sdk.marketRegister.findCreditManager(
894
- ca.creditManager
895
- );
896
- const { pool } = this.sdk.marketRegister.findByCreditManager(
897
- ca.creditManager
898
- );
899
- const { feeInterest } = creditManager;
900
- const { baseInterestRate } = pool.pool;
901
- const baseRateWithFee = baseInterestRate * (BigInt(feeInterest) + import_constants.PERCENTAGE_FACTOR);
902
- const totalDebt = ca.debt + ca.accruedInterest + ca.accruedFees;
903
- const r = ca.debt * baseRateWithFee / (totalDebt * import_constants.RAY);
904
- const caTokens = new import_utils.AddressMap(ca.tokens.map((t) => [t.token, t]));
905
- let qr = 0n;
906
- for (const t of creditManager.collateralTokens) {
907
- const b = caTokens.get(t);
908
- if (b) {
909
- qr += b.quota * BigInt(pool.pqk.quotas.get(t)?.rate ?? 0);
910
- }
911
- }
912
- qr = qr * (BigInt(feeInterest) + import_constants.PERCENTAGE_FACTOR) / import_constants.PERCENTAGE_FACTOR;
913
- qr /= totalDebt;
914
- return r + qr;
915
- }
916
- /**
917
- * {@inheritDoc ICreditAccountsService.getOptimalHFForPartialLiquidation}
918
- **/
919
- getOptimalHFForPartialLiquidation(ca) {
920
- const borrowRate = this.getBorrowRate(ca);
921
- return import_constants.PERCENTAGE_FACTOR + (borrowRate < 100n ? borrowRate : 100n);
922
- }
923
- /**
924
- * Internal wrapper for CreditAccountCompressor.getCreditAccounts + price updates wrapped into multicall
925
- * @param args
926
- * @param priceUpdateTxs
927
- * @param blockNumber
928
- * @returns
929
- */
930
- async #getCreditAccounts(args, priceUpdateTxs, blockNumber) {
931
- let resp;
932
- if (priceUpdateTxs?.length) {
933
- [resp] = await (0, import_viem2.simulateWithPriceUpdates)(this.client, {
934
- priceUpdates: priceUpdateTxs,
935
- contracts: [
936
- {
937
- abi: import_creditAccountCompressor.creditAccountCompressorAbi,
938
- address: this.#compressor,
939
- functionName: "getCreditAccounts",
940
- args
941
- }
942
- ],
943
- blockNumber,
944
- gas: this.sdk.gasLimit
945
- });
946
- } else {
947
- resp = await this.client.readContract({
948
- abi: import_creditAccountCompressor.creditAccountCompressorAbi,
949
- address: this.#compressor,
950
- functionName: "getCreditAccounts",
951
- args,
952
- blockNumber,
953
- // @ts-expect-error
954
- gas: this.sdk.gasLimit
955
- });
956
- }
957
- this.logger?.debug(
958
- {
959
- accounts: resp[0]?.length ?? 0,
960
- nextOffset: Number(resp[1])
961
- },
962
- "got credit accounts"
963
- );
964
- return resp;
965
- }
966
- /**
967
- * Returns multicall entries to redeem (unwrap) KYC ERC-4626 vault shares into underlying for the given credit manager.
968
- * Used when withdrawing debt from a KYC market: redeems adapter vault shares so the underlying can be withdrawn.
969
- * Only applies when the credit manager's underlying is KYC-gated and has an ERC-4626 adapter configured.
970
- * @param amount - Number of vault shares (adapter tokens) to redeem
971
- * @param creditManager - Credit manager address
972
- * @returns Array of MultiCall to pass to credit facade multicall, or undefined if underlying is not KYC or no adapter is configured
973
- */
974
- async getKYCUnwrapCalls(amount, creditManager) {
975
- const suite = this.sdk.marketRegister.findCreditManager(creditManager);
976
- const meta = this.sdk.tokensMeta.mustGet(suite.underlying);
977
- if (!this.sdk.tokensMeta.isKYCUnderlying(meta)) {
978
- return void 0;
979
- }
980
- const adapter = suite.creditManager.adapters.get(meta.addr);
981
- const adapterAddress = adapter?.address;
982
- if (!adapterAddress) {
983
- return void 0;
984
- }
985
- const mc = [
986
- {
987
- target: adapterAddress,
988
- callData: (0, import_viem.encodeFunctionData)({
989
- abi: import_integrations_v3.ierc4626AdapterAbi,
990
- functionName: "redeem",
991
- args: [amount, import_constants.ADDRESS_0X0, import_constants.ADDRESS_0X0]
992
- })
993
- }
994
- ];
995
- return mc;
996
- }
997
- /**
998
- * Returns multicall entries to deposit (wrap) underlying into KYC ERC-4626 vault shares for the given credit manager.
999
- * Used when adding debt on a KYC market: deposits underlying into the adapter vault so shares are minted on the account.
1000
- * Only applies when the credit manager's underlying is KYC-gated and has an ERC-4626 adapter configured.
1001
- * @param amount - Amount of underlying assets to deposit into the vault (in underlying decimals)
1002
- * @param creditManager - Credit manager address
1003
- * @returns Array of MultiCall to pass to credit facade multicall, or undefined if underlying is not KYC or no adapter is configured
1004
- */
1005
- async getKYCWrapCalls(amount, creditManager) {
1006
- const suite = this.sdk.marketRegister.findCreditManager(creditManager);
1007
- const meta = this.sdk.tokensMeta.mustGet(suite.underlying);
1008
- if (!this.sdk.tokensMeta.isKYCUnderlying(meta)) {
1009
- return void 0;
1010
- }
1011
- const adapter = suite.creditManager.adapters.get(meta.addr);
1012
- const adapterAddress = adapter?.address;
1013
- if (!adapterAddress) {
1014
- return void 0;
1015
- }
1016
- const mc = [
1017
- {
1018
- target: adapterAddress,
1019
- callData: (0, import_viem.encodeFunctionData)({
1020
- abi: import_integrations_v3.ierc4626AdapterAbi,
1021
- functionName: "deposit",
1022
- args: [amount, import_constants.ADDRESS_0X0]
1023
- })
1024
- }
1025
- ];
1026
- return mc;
1027
- }
1028
- /**
1029
- * Returns multicall entries to call redeemDiff on the KYC ERC-4626 adapter for the given credit manager.
1030
- * Redeems the leftover vault shares (e.g. after repaying debt) so the account does not hold excess KYC vault tokens.
1031
- * Only applies when the credit manager's underlying is KYC-gated and has an ERC-4626 adapter configured.
1032
- * @param amount - Leftover vault share amount to redeem (in adapter/vault decimals)
1033
- * @param creditManager - Credit manager address
1034
- * @returns Array of MultiCall to pass to credit facade multicall, or undefined if underlying is not KYC or no adapter is configured
1035
- */
1036
- async getRedeemDiffCalls(amount, creditManager) {
1037
- const suite = this.sdk.marketRegister.findCreditManager(creditManager);
1038
- const meta = this.sdk.tokensMeta.mustGet(suite.underlying);
1039
- if (!this.sdk.tokensMeta.isKYCUnderlying(meta)) {
1040
- return void 0;
1041
- }
1042
- const adapter = suite.creditManager.adapters.get(meta.addr);
1043
- const adapterAddress = adapter?.address;
1044
- if (!adapterAddress) {
1045
- return void 0;
1046
- }
1047
- const mc = [
1048
- {
1049
- target: adapterAddress,
1050
- callData: (0, import_viem.encodeFunctionData)({
1051
- abi: import_integrations_v3.ierc4626AdapterAbi,
1052
- functionName: "redeemDiff",
1053
- args: [amount]
1054
- })
1055
- }
1056
- ];
1057
- return mc;
1058
- }
1059
- /**
1060
- * Returns multicall entries to call depositDiff on the KYC ERC-4626 adapter for the given credit manager.
1061
- * Deposits the leftover underlying (e.g. after decreasing debt) into the vault so the account does not hold excess underlying.
1062
- * Only applies when the credit manager's underlying is KYC-gated and has an ERC-4626 adapter configured.
1063
- * @param amount - Leftover underlying amount to deposit into the vault (in underlying decimals)
1064
- * @param creditManager - Credit manager address
1065
- * @returns Array of MultiCall to pass to credit facade multicall, or undefined if underlying is not KYC or no adapter is configured
1066
- */
1067
- async getDepositDiffCalls(amount, creditManager) {
1068
- const suite = this.sdk.marketRegister.findCreditManager(creditManager);
1069
- const meta = this.sdk.tokensMeta.mustGet(suite.underlying);
1070
- if (!this.sdk.tokensMeta.isKYCUnderlying(meta)) {
1071
- return void 0;
1072
- }
1073
- const adapter = suite.creditManager.adapters.get(meta.addr);
1074
- const adapterAddress = adapter?.address;
1075
- if (!adapterAddress) {
1076
- return void 0;
1077
- }
1078
- const mc = [
1079
- {
1080
- target: adapterAddress,
1081
- callData: (0, import_viem.encodeFunctionData)({
1082
- abi: import_integrations_v3.ierc4626AdapterAbi,
1083
- functionName: "depositDiff",
1084
- args: [amount]
1085
- })
1086
- }
1087
- ];
1088
- return mc;
1089
- }
1090
- /**
1091
- * Returns raw txs that are needed to update all price feeds so that all credit accounts (possibly from different markets) compute
1092
- * {@inheritDoc ICreditAccountsService.getOnDemandPriceUpdates}
1093
- **/
1094
- async getOnDemandPriceUpdates(account, ignoreReservePrices) {
1095
- const { creditManager, creditAccount } = account;
1096
- const cm = this.sdk.marketRegister.findCreditManager(creditManager);
1097
- const update = await this.getUpdateForAccount(account, ignoreReservePrices);
1098
- this.logger?.debug(
1099
- { account: creditAccount, manager: cm.name },
1100
- `getting on demand price updates from ${update.txs.length} txs`
1101
- );
1102
- return (0, import_market.getRawPriceUpdates)(update);
1103
- }
1104
- /**
1105
- * Analyzes a multicall array and prepends necessary on-demand price feed updates.
1106
- *
1107
- * Deduplicates existing `onDemandPriceUpdates` calls
1108
- *
1109
- * @param creditManager - Address of the credit manager
1110
- * @param calls - The multicall array to prepend price updates to
1111
- * @param ca - Credit account slice, undefined when opening a new account
1112
- * @param options - Optional settings for price update generation
1113
- * @returns A new array with a single consolidated price update call prepended,
1114
- * followed by the non-price-update calls in their original order
1115
- */
1116
- async prependPriceUpdates(creditManager, calls, ca, options) {
1117
- const market = this.sdk.marketRegister.findByCreditManager(creditManager);
1118
- const cm = this.sdk.marketRegister.findCreditManager(creditManager).creditManager;
1119
- const { priceUpdates: existingUpdates, remainingCalls } = (0, import_multicall_utils.extractPriceUpdates)(calls);
1120
- const tokens = new import_utils.AddressSet([
1121
- cm.underlying,
1122
- // underlying - always included
1123
- ...(0, import_multicall_utils.extractQuotaTokens)(calls)
1124
- // tokens from `updateQuota` calls
1125
- ]);
1126
- if (ca) {
1127
- for (const t of ca.tokens) {
1128
- const isEnabled = (t.mask & ca.enabledTokensMask) !== 0n;
1129
- if (t.balance > 10n && isEnabled) {
1130
- tokens.add(t.token);
1131
- }
1132
- }
1133
- }
1134
- const ignoreReservePrices = options?.ignoreReservePrices;
1135
- const priceFeeds = market.priceOracle.priceFeedsForTokens(Array.from(tokens), {
1136
- main: true,
1137
- reserve: !ignoreReservePrices
1138
- });
1139
- const tStr = tokens.map((t) => this.labelAddress(t)).join(", ");
1140
- const remark = ignoreReservePrices ? " main" : "";
1141
- this.logger?.debug(
1142
- { account: ca?.creditAccount, manager: cm.name },
1143
- `prependPriceUpdates for ${tStr} from ${priceFeeds.length}${remark} price feeds`
1144
- );
1145
- const generatedUpdates = await this.sdk.priceFeeds.generatePriceFeedsUpdates(priceFeeds);
1146
- const merged = (0, import_multicall_utils.mergePriceUpdates)(existingUpdates, generatedUpdates);
1147
- if (merged.length === 0) {
1148
- return remainingCalls;
1149
- }
1150
- return [
1151
- {
1152
- target: cm.creditFacade,
1153
- callData: (0, import_viem.encodeFunctionData)({
1154
- abi: import_generated.iCreditFacadeMulticallV310Abi,
1155
- functionName: "onDemandPriceUpdates",
1156
- args: [merged]
1157
- })
1158
- },
1159
- ...remainingCalls
1160
- ];
1161
- }
1162
- async getUpdateForAccount(account, ignoreReservePrices) {
1163
- const { creditManager, creditAccount, enabledTokensMask } = account;
1164
- const market = this.sdk.marketRegister.findByCreditManager(creditManager);
1165
- const cm = this.sdk.marketRegister.findCreditManager(creditManager).creditManager;
1166
- const tokens = new import_utils.AddressSet([cm.underlying]);
1167
- for (const t of account.tokens) {
1168
- const isEnabled = (t.mask & enabledTokensMask) !== 0n;
1169
- if (t.balance > 10n && isEnabled) {
1170
- tokens.add(t.token);
1171
- }
1172
- }
1173
- const priceFeeds = market.priceOracle.priceFeedsForTokens(Array.from(tokens), {
1174
- main: true,
1175
- reserve: !ignoreReservePrices
1176
- });
1177
- const tStr = tokens.map((t) => this.labelAddress(t)).join(", ");
1178
- const remark = ignoreReservePrices ? " main" : "";
1179
- this.logger?.debug(
1180
- { account: creditAccount, manager: cm.name },
1181
- `generating price feed updates for ${tStr} from ${priceFeeds.length}${remark} price feeds`
1182
- );
1183
- return this.sdk.priceFeeds.generatePriceFeedsUpdateTxs(priceFeeds);
1184
- }
1185
- /**
1186
- * {@inheritDoc ICreditAccountsService.multicall}
1187
- */
1188
- async multicall(creditAccount, calls, options) {
1189
- const cm = this.sdk.marketRegister.findCreditManager(
1190
- creditAccount.creditManager
1191
- );
1192
- const callsWithPrices = await this.prependPriceUpdates(
1193
- creditAccount.creditManager,
1194
- calls,
1195
- creditAccount,
1196
- options
1197
- );
1198
- return cm.creditFacade.multicall(
1199
- creditAccount.creditAccount,
1200
- callsWithPrices
1201
- );
1202
- }
1203
- /**
1204
- * {@inheritDoc ICreditAccountsService.botMulticall}
1205
- */
1206
- async botMulticall(creditAccount, calls, options) {
1207
- const cm = this.sdk.marketRegister.findCreditManager(
1208
- creditAccount.creditManager
1209
- );
1210
- const callsWithPrices = await this.prependPriceUpdates(
1211
- creditAccount.creditManager,
1212
- calls,
1213
- creditAccount,
1214
- options
1215
- );
1216
- return cm.creditFacade.botMulticall(
1217
- creditAccount.creditAccount,
1218
- callsWithPrices
1219
- );
1220
- }
1221
- prepareDisableQuotas(ca) {
1222
- const calls = [];
1223
- for (const { token, quota } of ca.tokens) {
1224
- if (quota > 0n) {
1225
- calls.push({
1226
- target: ca.creditFacade,
1227
- callData: (0, import_viem.encodeFunctionData)({
1228
- abi: import_generated.iCreditFacadeMulticallV310Abi,
1229
- functionName: "updateQuota",
1230
- args: [token, import_constants.MIN_INT96, 0n]
1231
- })
1232
- });
1233
- }
1234
- }
1235
- return calls;
1236
- }
1237
- prepareUpdateQuotas(creditFacade, { averageQuota, minQuota }) {
1238
- const minRecord = (0, import_router.assetsMap)(minQuota);
1239
- const calls = averageQuota.map((q) => {
1240
- const minAsset = minRecord.get(q.token);
1241
- const min = minAsset && minAsset?.balance > 0 ? minAsset.balance : 0n;
1242
- return {
1243
- target: creditFacade,
1244
- callData: (0, import_viem.encodeFunctionData)({
1245
- abi: import_generated.iCreditFacadeMulticallV310Abi,
1246
- functionName: "updateQuota",
1247
- args: [q.token, q.balance, min]
1248
- })
1249
- };
1250
- });
1251
- return calls;
1252
- }
1253
- prepareDecreaseDebt(ca) {
1254
- if (ca.debt > 0n) {
1255
- return [
1256
- {
1257
- target: ca.creditFacade,
1258
- callData: (0, import_viem.encodeFunctionData)({
1259
- abi: import_generated.iCreditFacadeMulticallV310Abi,
1260
- functionName: "decreaseDebt",
1261
- args: [import_constants.MAX_UINT256]
1262
- })
1263
- }
1264
- ];
1265
- }
1266
- return [];
1267
- }
1268
- prepareWithdrawToken(creditFacade, token, amount, to) {
1269
- return {
1270
- target: creditFacade,
1271
- callData: (0, import_viem.encodeFunctionData)({
1272
- abi: import_generated.iCreditFacadeMulticallV310Abi,
1273
- functionName: "withdrawCollateral",
1274
- args: [token, amount, to]
1275
- })
1276
- };
1277
- }
1278
- #prepareIncreaseDebt(creditFacade, debt) {
1279
- return {
1280
- target: creditFacade,
1281
- callData: (0, import_viem.encodeFunctionData)({
1282
- abi: import_generated.iCreditFacadeMulticallV310Abi,
1283
- functionName: "increaseDebt",
1284
- args: [debt]
1285
- })
1286
- };
1287
- }
1288
- #prepareChangeDebt(creditFacade, change, isDecrease) {
1289
- return {
1290
- target: creditFacade,
1291
- callData: (0, import_viem.encodeFunctionData)({
1292
- abi: import_generated.iCreditFacadeMulticallV310Abi,
1293
- functionName: isDecrease ? "decreaseDebt" : "increaseDebt",
1294
- args: [change]
1295
- })
1296
- };
1297
- }
1298
- prepareAddCollateral(creditFacade, assets, permits) {
1299
- const calls = assets.map(({ token, balance }) => {
1300
- const p = permits[token];
1301
- if (p) {
1302
- return {
1303
- target: creditFacade,
1304
- callData: (0, import_viem.encodeFunctionData)({
1305
- abi: import_generated.iCreditFacadeMulticallV310Abi,
1306
- functionName: "addCollateralWithPermit",
1307
- args: [token, balance, p.deadline, p.v, p.r, p.s]
1308
- })
1309
- };
1310
- }
1311
- return {
1312
- target: creditFacade,
1313
- callData: (0, import_viem.encodeFunctionData)({
1314
- abi: import_generated.iCreditFacadeMulticallV310Abi,
1315
- functionName: "addCollateral",
1316
- args: [token, balance]
1317
- })
1318
- };
1319
- });
1320
- return calls;
1321
- }
1322
- /**
1323
- * Returns addresses of market configurators
1324
- */
1325
- get marketConfigurators() {
1326
- return this.sdk.marketRegister.marketConfigurators.map((mc) => mc.address);
1327
- }
1328
- get rewardCompressor() {
1329
- return this.sdk.addressProvider.mustGetLatest(
1330
- import_constants.AP_REWARDS_COMPRESSOR,
1331
- import_constants.VERSION_RANGE_310
1332
- )[0];
1333
- }
1334
- get peripheryCompressor() {
1335
- return this.sdk.addressProvider.mustGetLatest(
1336
- import_constants.AP_PERIPHERY_COMPRESSOR,
1337
- import_constants.VERSION_RANGE_310
1338
- )[0];
1339
- }
1340
- /**
1341
- * Wrapper that selects between credit facade and KYC factory
1342
- * @param suite
1343
- * @param to
1344
- * @param calls
1345
- * @param referralCode
1346
- * @param kycOptions
1347
- * @returns
1348
- */
1349
- async openCreditAccountTx(suite, to, calls, referralCode, kycOptions) {
1350
- const marketSuite = this.sdk.marketRegister.findByPool(suite.pool);
1351
- const factory = marketSuite.kycFactory;
1352
- if (factory) {
1353
- return factory.openCreditAccount(
1354
- suite.creditManager.address,
1355
- calls,
1356
- kycOptions
1357
- );
1358
- }
1359
- return suite.creditFacade.openCreditAccount(to, calls, referralCode ?? 0n);
1360
- }
1361
- /**
1362
- * Wrapper that selects between credit facade and KYC factory
1363
- * @param suite
1364
- * @param creditAccount
1365
- * @param calls
1366
- * @param kycOptions
1367
- * @returns
1368
- */
1369
- async multicallTx(suite, creditAccount, calls, kycOptions) {
1370
- const marketSuite = this.sdk.marketRegister.findByCreditManager(
1371
- suite.creditManager.address
1372
- );
1373
- const factory = marketSuite.kycFactory;
1374
- if (factory) {
1375
- return factory.multicall(creditAccount, calls, kycOptions);
1376
- }
1377
- return suite.creditFacade.multicall(creditAccount, calls);
1378
- }
1379
- /**
1380
- * Wrapper that selects between credit facade and KYC factory
1381
- * @param suite
1382
- * @param creditAccount
1383
- * @param calls
1384
- * @param operation
1385
- * @param kycOptions
1386
- * @returns
1387
- */
1388
- async closeCreditAccountTx(suite, creditAccount, calls, operation, kycOptions) {
1389
- const marketSuite = this.sdk.marketRegister.findByCreditManager(
1390
- suite.creditManager.address
1391
- );
1392
- const factory = marketSuite.kycFactory;
1393
- if (operation === "close") {
1394
- if (factory) {
1395
- throw new Error(
1396
- "CloseOptions=close is not supported for KYC underlying credit accounts"
1397
- );
1398
- }
1399
- return suite.creditFacade.closeCreditAccount(creditAccount, calls);
1400
- }
1401
- if (factory) {
1402
- return factory.multicall(creditAccount, calls, kycOptions);
1403
- }
1404
- return suite.creditFacade.multicall(creditAccount, calls);
1405
- }
1406
- }
1407
- // Annotate the CommonJS export names for ESM import in node:
1408
- 0 && (module.exports = {
1409
- AbstractCreditAccountService,
1410
- getWithdrawalCompressorAddress
1411
- });