@gearbox-protocol/sdk 13.4.0 → 13.5.0-next.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/dist/cjs/abi/310/iSecuritizeDegenNFT.js +263 -0
  2. package/dist/cjs/abi/310/iSecuritizeKYCFactory.js +278 -0
  3. package/dist/cjs/{sdk/pools/PoolServiceV310.js → abi/iStateSerializer.js} +14 -8
  4. package/dist/cjs/dev/AccountOpener.js +45 -5
  5. package/dist/cjs/sdk/accounts/AbstractCreditAccountsService.js +375 -13
  6. package/dist/cjs/sdk/accounts/CreditAccountsServiceV310.js +16 -5
  7. package/dist/cjs/sdk/base/ChainContractsRegister.js +1 -1
  8. package/dist/cjs/sdk/base/TokensMeta.js +255 -32
  9. package/dist/cjs/sdk/base/index.js +2 -0
  10. package/dist/cjs/sdk/{constants/phantom-tokens.js → base/token-types.js} +9 -3
  11. package/dist/cjs/sdk/chain/chains.js +2 -1
  12. package/dist/cjs/sdk/constants/index.js +0 -2
  13. package/dist/cjs/sdk/market/MarketRegister.js +5 -2
  14. package/dist/cjs/sdk/market/MarketSuite.js +6 -0
  15. package/dist/cjs/{plugins/zappers/extraZappers.js → sdk/market/ZapperRegister.js} +110 -6
  16. package/dist/cjs/sdk/market/index.js +3 -1
  17. package/dist/cjs/sdk/market/pool/PoolSuite.js +3 -0
  18. package/dist/cjs/sdk/market/pool/PoolV310Contract.js +17 -2
  19. package/dist/cjs/sdk/market/pool/SecuritizeKYCFactory.js +97 -0
  20. package/dist/cjs/sdk/market/pool/index.js +4 -0
  21. package/dist/cjs/sdk/pools/PoolService.js +391 -0
  22. package/dist/cjs/sdk/pools/index.js +2 -4
  23. package/dist/esm/abi/310/iSecuritizeDegenNFT.js +239 -0
  24. package/dist/esm/abi/310/iSecuritizeKYCFactory.js +254 -0
  25. package/dist/esm/abi/iStateSerializer.js +12 -0
  26. package/dist/esm/dev/AccountOpener.js +47 -6
  27. package/dist/esm/sdk/accounts/AbstractCreditAccountsService.js +375 -13
  28. package/dist/esm/sdk/accounts/CreditAccountsServiceV310.js +16 -5
  29. package/dist/esm/sdk/base/ChainContractsRegister.js +1 -1
  30. package/dist/esm/sdk/base/TokensMeta.js +261 -32
  31. package/dist/esm/sdk/base/index.js +1 -0
  32. package/dist/esm/sdk/{constants/phantom-tokens.js → base/token-types.js} +4 -0
  33. package/dist/esm/sdk/chain/chains.js +2 -1
  34. package/dist/esm/sdk/constants/index.js +0 -1
  35. package/dist/esm/sdk/market/MarketRegister.js +5 -2
  36. package/dist/esm/sdk/market/MarketSuite.js +6 -0
  37. package/dist/esm/{plugins/zappers/extraZappers.js → sdk/market/ZapperRegister.js} +109 -2
  38. package/dist/esm/sdk/market/index.js +1 -0
  39. package/dist/esm/sdk/market/pool/PoolSuite.js +3 -0
  40. package/dist/esm/sdk/market/pool/PoolV310Contract.js +17 -2
  41. package/dist/esm/sdk/market/pool/SecuritizeKYCFactory.js +73 -0
  42. package/dist/esm/sdk/market/pool/index.js +2 -0
  43. package/dist/esm/sdk/pools/PoolService.js +371 -0
  44. package/dist/esm/sdk/pools/index.js +1 -2
  45. package/dist/types/abi/310/iSecuritizeDegenNFT.d.ts +324 -0
  46. package/dist/types/abi/310/iSecuritizeKYCFactory.d.ts +322 -0
  47. package/dist/types/abi/iStateSerializer.d.ts +11 -0
  48. package/dist/types/sdk/accounts/AbstractCreditAccountsService.d.ts +114 -3
  49. package/dist/types/sdk/accounts/CreditAccountsServiceV310.d.ts +1 -1
  50. package/dist/types/sdk/accounts/types.d.ts +96 -6
  51. package/dist/types/sdk/base/TokensMeta.d.ts +34 -21
  52. package/dist/types/sdk/base/index.d.ts +1 -0
  53. package/dist/types/sdk/base/token-types.d.ts +33 -0
  54. package/dist/types/sdk/base/types.d.ts +0 -7
  55. package/dist/types/sdk/chain/chains.d.ts +1 -1
  56. package/dist/types/sdk/constants/index.d.ts +0 -1
  57. package/dist/types/sdk/market/MarketRegister.d.ts +2 -2
  58. package/dist/types/sdk/market/MarketSuite.d.ts +3 -0
  59. package/dist/types/sdk/market/ZapperRegister.d.ts +17 -0
  60. package/dist/types/sdk/market/index.d.ts +1 -0
  61. package/dist/types/sdk/market/pool/PoolSuite.d.ts +2 -0
  62. package/dist/types/sdk/market/pool/PoolV310Contract.d.ts +6 -2
  63. package/dist/types/sdk/market/pool/SecuritizeKYCFactory.d.ts +345 -0
  64. package/dist/types/sdk/market/pool/index.d.ts +2 -0
  65. package/dist/types/sdk/market/types.d.ts +10 -0
  66. package/dist/types/sdk/pools/PoolService.d.ts +14 -0
  67. package/dist/types/sdk/pools/index.d.ts +1 -2
  68. package/dist/types/sdk/pools/types.d.ts +85 -111
  69. package/package.json +1 -1
  70. package/dist/cjs/plugins/zappers/ZappersPlugin.js +0 -144
  71. package/dist/cjs/plugins/zappers/index.js +0 -26
  72. package/dist/cjs/plugins/zappers/package.json +0 -1
  73. package/dist/cjs/sdk/pools/AbstractPoolService.js +0 -143
  74. package/dist/cjs/sdk/pools/createPoolService.js +0 -35
  75. package/dist/esm/plugins/zappers/ZappersPlugin.js +0 -126
  76. package/dist/esm/plugins/zappers/index.js +0 -3
  77. package/dist/esm/plugins/zappers/package.json +0 -1
  78. package/dist/esm/sdk/pools/AbstractPoolService.js +0 -119
  79. package/dist/esm/sdk/pools/PoolServiceV310.js +0 -6
  80. package/dist/esm/sdk/pools/createPoolService.js +0 -11
  81. package/dist/types/plugins/zappers/ZappersPlugin.d.ts +0 -18
  82. package/dist/types/plugins/zappers/extraZappers.d.ts +0 -6
  83. package/dist/types/plugins/zappers/index.d.ts +0 -3
  84. package/dist/types/plugins/zappers/types.d.ts +0 -12
  85. package/dist/types/sdk/constants/phantom-tokens.d.ts +0 -2
  86. package/dist/types/sdk/pools/AbstractPoolService.d.ts +0 -21
  87. package/dist/types/sdk/pools/PoolServiceV310.d.ts +0 -4
  88. package/dist/types/sdk/pools/createPoolService.d.ts +0 -3
  89. /package/dist/cjs/{plugins/zappers → sdk/market}/types.js +0 -0
  90. /package/dist/esm/{plugins/zappers → sdk/market}/types.js +0 -0
@@ -22,6 +22,7 @@ __export(AbstractCreditAccountsService_exports, {
22
22
  getWithdrawalCompressorAddress: () => getWithdrawalCompressorAddress
23
23
  });
24
24
  module.exports = __toCommonJS(AbstractCreditAccountsService_exports);
25
+ var import_integrations_v3 = require("@gearbox-protocol/integrations-v3");
25
26
  var import_viem = require("viem");
26
27
  var import_generated = require("../../abi/310/generated.js");
27
28
  var import_creditAccountCompressor = require("../../abi/compressors/creditAccountCompressor.js");
@@ -95,6 +96,23 @@ class AbstractCreditAccountService extends import_base.SDKConstruct {
95
96
  });
96
97
  return cad;
97
98
  }
99
+ /**
100
+ * Returns credit account data for a single account with the investor address resolved.
101
+ * Loads CA via getCreditAccountData; for KYC underlyings fetches the investor from the KYC factory's getInvestor(creditAccount), otherwise uses the account owner.
102
+ * @param account - Credit account address
103
+ * @param blockNumber - Optional block number for the read
104
+ * @returns CreditAccountDataWithInvestor (CA data + investor address), or undefined if the account is not found
105
+ */
106
+ async getCreditAccountDataWithInvestor(account, blockNumber) {
107
+ const ca = await this.getCreditAccountData(account, blockNumber);
108
+ if (!ca) return ca;
109
+ const marketSuite = this.sdk.marketRegister.findByCreditManager(
110
+ ca.creditManager
111
+ );
112
+ const factory = await marketSuite.getKYCFactory();
113
+ const investor = factory ? await factory.getInvestor(ca.creditAccount, true) : void 0;
114
+ return { ...ca, investor: investor ?? ca.owner };
115
+ }
98
116
  /**
99
117
  * {@inheritDoc ICreditAccountsService.getCreditAccounts}
100
118
  **/
@@ -149,6 +167,75 @@ class AbstractCreditAccountService extends import_base.SDKConstruct {
149
167
  );
150
168
  return allCAs.sort((a, b) => Number(a.healthFactor - b.healthFactor));
151
169
  }
170
+ /**
171
+ * Returns all credit accounts matching the filter, with investor set on each item.
172
+ * Delegates to getCreditAccounts; when options.owner is set, also loads KYC credit accounts for that owner and merges them into the list. Result is sorted by health factor ascending.
173
+ * @param options - Filter options (owner, creditManager, health factor, etc.)
174
+ * @param blockNumber - Optional block number for the read
175
+ * @returns Array of credit accounts (with investor field), sorted by health factor ascending
176
+ */
177
+ async getCreditAccountsWithInvestor(options, blockNumber) {
178
+ const { owner, ignoreReservePrices = false } = options ?? {};
179
+ const priceUpdate = await this.sdk.priceFeeds.generatePriceFeedsUpdateTxs(
180
+ ignoreReservePrices ? { main: true } : void 0
181
+ );
182
+ const { txs: priceUpdateTxs } = priceUpdate;
183
+ const [common, kyc] = await Promise.all([
184
+ this.getCreditAccounts(options, blockNumber),
185
+ owner ? this.getKYCCreditAccountsOfOwner(owner, priceUpdateTxs, blockNumber) : void 0
186
+ ]);
187
+ const allCAs = common.map(
188
+ (ca) => ({
189
+ ...ca,
190
+ investor: owner || ca.owner
191
+ })
192
+ );
193
+ allCAs.push(...kyc || []);
194
+ return allCAs.sort((a, b) => Number(a.healthFactor - b.healthFactor));
195
+ }
196
+ async getKYCCreditAccountsOfOwner(owner, priceUpdateTxs, blockNumber) {
197
+ const suites = this.marketConfigurators.map((mc) => {
198
+ const suite = this.sdk.marketRegister.markets.find(
199
+ (m) => m.configurator.address === mc
200
+ );
201
+ return suite;
202
+ });
203
+ const kycCAAddresses = await this.getKYCCaOfInvestor(owner, suites);
204
+ const kycCAs = await this.loadSpecifiedAccounts(
205
+ kycCAAddresses,
206
+ priceUpdateTxs,
207
+ blockNumber
208
+ );
209
+ return kycCAs.map((ca) => ({
210
+ ...ca,
211
+ investor: owner
212
+ }));
213
+ }
214
+ /**
215
+ * Loads credit account data for the given addresses using simulateWithPriceUpdates.
216
+ * Applies the provided price update txs before reading, so returned data is consistent with up-to-date prices.
217
+ * @param accounts - Credit account addresses to load
218
+ * @param priceUpdateTxs - Price feed update txs to simulate before the read (e.g. from generatePriceFeedsUpdateTxs)
219
+ * @param blockNumber - Optional block number for the read
220
+ * @returns Array of CreditAccountData in the same order as accounts (throws if any getCreditAccountData call reverts)
221
+ */
222
+ async loadSpecifiedAccounts(accounts, priceUpdateTxs, blockNumber) {
223
+ if (accounts.length === 0) return [];
224
+ const list = await (0, import_viem2.simulateWithPriceUpdates)(this.client, {
225
+ priceUpdates: priceUpdateTxs,
226
+ contracts: accounts.map(
227
+ (account) => ({
228
+ abi: import_creditAccountCompressor.creditAccountCompressorAbi,
229
+ address: this.#compressor,
230
+ functionName: "getCreditAccountData",
231
+ args: [account]
232
+ })
233
+ ),
234
+ blockNumber,
235
+ gas: this.sdk.gasLimit
236
+ });
237
+ return list;
238
+ }
152
239
  /**
153
240
  * {@inheritDoc ICreditAccountsService.getRewards}
154
241
  **/
@@ -358,6 +445,13 @@ class AbstractCreditAccountService extends import_base.SDKConstruct {
358
445
  closePath
359
446
  }) {
360
447
  const cm = this.sdk.marketRegister.findCreditManager(ca.creditManager);
448
+ await this.sdk.tokensMeta.loadTokenData(cm.underlying);
449
+ const underlying = this.sdk.tokensMeta.mustGet(cm.underlying);
450
+ if (this.sdk.tokensMeta.isKYCUnderlying(underlying)) {
451
+ throw new Error(
452
+ "closeCreditAccount is not supported for KYC underlying credit accounts"
453
+ );
454
+ }
361
455
  const routerCloseResult = closePath || await this.sdk.routerFor(ca).findBestClosePath({
362
456
  creditAccount: ca,
363
457
  creditManager: cm.creditManager,
@@ -372,7 +466,12 @@ class AbstractCreditAccountService extends import_base.SDKConstruct {
372
466
  )
373
467
  ];
374
468
  const calls = operation === "close" ? operationCalls : await this.prependPriceUpdates(ca.creditManager, operationCalls, ca);
375
- const tx = operation === "close" ? cm.creditFacade.closeCreditAccount(ca.creditAccount, calls) : cm.creditFacade.multicall(ca.creditAccount, calls);
469
+ const tx = await this.closeCreditAccountTx(
470
+ cm,
471
+ ca.creditAccount,
472
+ calls,
473
+ operation
474
+ );
376
475
  return { tx, calls, routerCloseResult, creditFacade: cm.creditFacade };
377
476
  }
378
477
  /**
@@ -395,7 +494,7 @@ class AbstractCreditAccountService extends import_base.SDKConstruct {
395
494
  operationCalls,
396
495
  creditAccount
397
496
  );
398
- const tx = cm.creditFacade.multicall(creditAccount.creditAccount, calls);
497
+ const tx = await this.multicallTx(cm, creditAccount.creditAccount, calls);
399
498
  return { tx, calls, creditFacade: cm.creditFacade };
400
499
  }
401
500
  /**
@@ -428,7 +527,7 @@ class AbstractCreditAccountService extends import_base.SDKConstruct {
428
527
  operationCalls,
429
528
  creditAccount
430
529
  );
431
- const tx = cm.creditFacade.multicall(creditAccount.creditAccount, calls);
530
+ const tx = await this.multicallTx(cm, creditAccount.creditAccount, calls);
432
531
  tx.value = ethAmount.toString(10);
433
532
  return { tx, calls, creditFacade: cm.creditFacade };
434
533
  }
@@ -438,7 +537,7 @@ class AbstractCreditAccountService extends import_base.SDKConstruct {
438
537
  async changeDebt({
439
538
  creditAccount,
440
539
  amount,
441
- addCollateral
540
+ collateral
442
541
  }) {
443
542
  if (amount === 0n) {
444
543
  throw new Error("debt increase or decrease must be non-zero");
@@ -448,18 +547,28 @@ class AbstractCreditAccountService extends import_base.SDKConstruct {
448
547
  const cm = this.sdk.marketRegister.findCreditManager(
449
548
  creditAccount.creditManager
450
549
  );
451
- const addCollateralCalls = addCollateral && isDecrease ? this.prepareAddCollateral(
550
+ const addCollateralCalls = collateral && isDecrease ? this.prepareAddCollateral(
452
551
  creditAccount.creditFacade,
453
552
  [
454
553
  {
455
- token: creditAccount.underlying,
456
- balance: change
554
+ token: collateral[0].token,
555
+ balance: collateral[0].balance
457
556
  }
458
557
  ],
459
558
  {}
460
559
  ) : [];
560
+ const unwrapCalls = collateral && isDecrease ? await this.getKYCUnwrapCalls(
561
+ collateral[0].balance,
562
+ creditAccount.creditManager
563
+ ) || [] : [];
564
+ if (addCollateralCalls.length > 0 && unwrapCalls.length === 0 && collateral && collateral?.[0].token !== creditAccount.underlying) {
565
+ throw new Error(
566
+ "Can't use collateral other than underlying for non KYC market"
567
+ );
568
+ }
461
569
  const operationCalls = [
462
570
  ...addCollateralCalls,
571
+ ...unwrapCalls,
463
572
  this.#prepareChangeDebt(creditAccount.creditFacade, change, isDecrease)
464
573
  ];
465
574
  const calls = await this.prependPriceUpdates(
@@ -467,7 +576,7 @@ class AbstractCreditAccountService extends import_base.SDKConstruct {
467
576
  operationCalls,
468
577
  creditAccount
469
578
  );
470
- const tx = cm.creditFacade.multicall(creditAccount.creditAccount, calls);
579
+ const tx = await this.multicallTx(cm, creditAccount.creditAccount, calls);
471
580
  return { tx, calls, creditFacade: cm.creditFacade };
472
581
  }
473
582
  /**
@@ -495,7 +604,7 @@ class AbstractCreditAccountService extends import_base.SDKConstruct {
495
604
  operationCalls,
496
605
  creditAccount
497
606
  );
498
- const tx = cm.creditFacade.multicall(creditAccount.creditAccount, calls);
607
+ const tx = await this.multicallTx(cm, creditAccount.creditAccount, calls);
499
608
  return { tx, calls, creditFacade: cm.creditFacade };
500
609
  }
501
610
  /**
@@ -603,7 +712,7 @@ class AbstractCreditAccountService extends import_base.SDKConstruct {
603
712
  operationCalls,
604
713
  creditAccount
605
714
  );
606
- const tx = cm.creditFacade.multicall(creditAccount.creditAccount, calls);
715
+ const tx = await this.multicallTx(cm, creditAccount.creditAccount, calls);
607
716
  return { tx, calls, creditFacade: cm.creditFacade };
608
717
  }
609
718
  /**
@@ -664,9 +773,28 @@ class AbstractCreditAccountService extends import_base.SDKConstruct {
664
773
  operationCalls,
665
774
  creditAccount
666
775
  );
667
- const tx = cm.creditFacade.multicall(creditAccount.creditAccount, calls);
776
+ const tx = await this.multicallTx(cm, creditAccount.creditAccount, calls);
668
777
  return { tx, calls, creditFacade: cm.creditFacade };
669
778
  }
779
+ /**
780
+ * Returns address to which approval should be given on collateral token
781
+ * It's credit manager for classical markets and special wallet for KYC markets
782
+ * @param options - {@link GetApprovalAddressProps}
783
+ * @returns
784
+ **/
785
+ async getApprovalAddress(options) {
786
+ const { creditManager } = options;
787
+ const suite = this.sdk.marketRegister.findCreditManager(creditManager);
788
+ const marketSuite = this.sdk.marketRegister.findByPool(suite.pool);
789
+ const factory = await marketSuite.getKYCFactory();
790
+ if (factory) {
791
+ if ("creditAccount" in options) {
792
+ return factory.getWallet(options.creditAccount);
793
+ }
794
+ return factory.precomputeWalletAddress(creditManager, options.borrower);
795
+ }
796
+ return suite.creditManager.address;
797
+ }
670
798
  /**
671
799
  * {@inheritDoc ICreditAccountsService.openCA}
672
800
  **/
@@ -698,6 +826,7 @@ class AbstractCreditAccountService extends import_base.SDKConstruct {
698
826
  this.#prepareIncreaseDebt(cm.creditFacade, debt),
699
827
  ...this.prepareAddCollateral(cm.creditFacade, collateral, permits),
700
828
  ...openPathCalls,
829
+ // path from underlying to withdrawal token
701
830
  ...tokenToWithdraw ? [
702
831
  this.prepareWithdrawToken(
703
832
  cm.creditFacade,
@@ -715,9 +844,9 @@ class AbstractCreditAccountService extends import_base.SDKConstruct {
715
844
  const calls = await this.prependPriceUpdates(cm.address, operationCalls);
716
845
  let tx;
717
846
  if (reopenCreditAccount) {
718
- tx = await cmSuite.creditFacade.multicall(reopenCreditAccount, calls);
847
+ tx = await this.multicallTx(cmSuite, reopenCreditAccount, calls);
719
848
  } else {
720
- tx = cmSuite.creditFacade.openCreditAccount(to, calls, referralCode);
849
+ tx = await this.openCreditAccountTx(cmSuite, to, calls, referralCode);
721
850
  }
722
851
  tx.value = ethAmount.toString(10);
723
852
  return { calls, tx, creditFacade: cmSuite.creditFacade };
@@ -800,6 +929,131 @@ class AbstractCreditAccountService extends import_base.SDKConstruct {
800
929
  return resp;
801
930
  }
802
931
  /**
932
+ * Returns multicall entries to redeem (unwrap) KYC ERC-4626 vault shares into underlying for the given credit manager.
933
+ * Used when withdrawing debt from a KYC market: redeems adapter vault shares so the underlying can be withdrawn.
934
+ * Only applies when the credit manager's underlying is KYC-gated and has an ERC-4626 adapter configured.
935
+ * @param amount - Number of vault shares (adapter tokens) to redeem
936
+ * @param creditManager - Credit manager address
937
+ * @returns Array of MultiCall to pass to credit facade multicall, or undefined if underlying is not KYC or no adapter is configured
938
+ */
939
+ async getKYCUnwrapCalls(amount, creditManager) {
940
+ const suite = this.sdk.marketRegister.findCreditManager(creditManager);
941
+ const meta = this.sdk.tokensMeta.mustGet(suite.underlying);
942
+ if (!this.sdk.tokensMeta.isKYCUnderlying(meta)) {
943
+ return void 0;
944
+ }
945
+ const adapter = suite.creditManager.adapters.get(meta.addr);
946
+ const adapterAddress = adapter?.address;
947
+ if (!adapterAddress) {
948
+ return void 0;
949
+ }
950
+ const mc = [
951
+ {
952
+ target: adapterAddress,
953
+ callData: (0, import_viem.encodeFunctionData)({
954
+ abi: import_integrations_v3.ierc4626AdapterAbi,
955
+ functionName: "redeem",
956
+ args: [amount, import_constants.ADDRESS_0X0, import_constants.ADDRESS_0X0]
957
+ })
958
+ }
959
+ ];
960
+ return mc;
961
+ }
962
+ /**
963
+ * Returns multicall entries to deposit (wrap) underlying into KYC ERC-4626 vault shares for the given credit manager.
964
+ * Used when adding debt on a KYC market: deposits underlying into the adapter vault so shares are minted on the account.
965
+ * Only applies when the credit manager's underlying is KYC-gated and has an ERC-4626 adapter configured.
966
+ * @param amount - Amount of underlying assets to deposit into the vault (in underlying decimals)
967
+ * @param creditManager - Credit manager address
968
+ * @returns Array of MultiCall to pass to credit facade multicall, or undefined if underlying is not KYC or no adapter is configured
969
+ */
970
+ async getKYCWrapCalls(amount, creditManager) {
971
+ const suite = this.sdk.marketRegister.findCreditManager(creditManager);
972
+ const meta = this.sdk.tokensMeta.mustGet(suite.underlying);
973
+ if (!this.sdk.tokensMeta.isKYCUnderlying(meta)) {
974
+ return void 0;
975
+ }
976
+ const adapter = suite.creditManager.adapters.get(meta.addr);
977
+ const adapterAddress = adapter?.address;
978
+ if (!adapterAddress) {
979
+ return void 0;
980
+ }
981
+ const mc = [
982
+ {
983
+ target: adapterAddress,
984
+ callData: (0, import_viem.encodeFunctionData)({
985
+ abi: import_integrations_v3.ierc4626AdapterAbi,
986
+ functionName: "deposit",
987
+ args: [amount, import_constants.ADDRESS_0X0]
988
+ })
989
+ }
990
+ ];
991
+ return mc;
992
+ }
993
+ /**
994
+ * Returns multicall entries to call redeemDiff on the KYC ERC-4626 adapter for the given credit manager.
995
+ * Redeems the leftover vault shares (e.g. after repaying debt) so the account does not hold excess KYC vault tokens.
996
+ * Only applies when the credit manager's underlying is KYC-gated and has an ERC-4626 adapter configured.
997
+ * @param amount - Leftover vault share amount to redeem (in adapter/vault decimals)
998
+ * @param creditManager - Credit manager address
999
+ * @returns Array of MultiCall to pass to credit facade multicall, or undefined if underlying is not KYC or no adapter is configured
1000
+ */
1001
+ async getRedeemDiffCalls(amount, creditManager) {
1002
+ const suite = this.sdk.marketRegister.findCreditManager(creditManager);
1003
+ const meta = this.sdk.tokensMeta.mustGet(suite.underlying);
1004
+ if (!this.sdk.tokensMeta.isKYCUnderlying(meta)) {
1005
+ return void 0;
1006
+ }
1007
+ const adapter = suite.creditManager.adapters.get(meta.addr);
1008
+ const adapterAddress = adapter?.address;
1009
+ if (!adapterAddress) {
1010
+ return void 0;
1011
+ }
1012
+ const mc = [
1013
+ {
1014
+ target: adapterAddress,
1015
+ callData: (0, import_viem.encodeFunctionData)({
1016
+ abi: import_integrations_v3.ierc4626AdapterAbi,
1017
+ functionName: "redeemDiff",
1018
+ args: [amount]
1019
+ })
1020
+ }
1021
+ ];
1022
+ return mc;
1023
+ }
1024
+ /**
1025
+ * Returns multicall entries to call depositDiff on the KYC ERC-4626 adapter for the given credit manager.
1026
+ * Deposits the leftover underlying (e.g. after decreasing debt) into the vault so the account does not hold excess underlying.
1027
+ * Only applies when the credit manager's underlying is KYC-gated and has an ERC-4626 adapter configured.
1028
+ * @param amount - Leftover underlying amount to deposit into the vault (in underlying decimals)
1029
+ * @param creditManager - Credit manager address
1030
+ * @returns Array of MultiCall to pass to credit facade multicall, or undefined if underlying is not KYC or no adapter is configured
1031
+ */
1032
+ async getDepositDiffCalls(amount, creditManager) {
1033
+ const suite = this.sdk.marketRegister.findCreditManager(creditManager);
1034
+ const meta = this.sdk.tokensMeta.mustGet(suite.underlying);
1035
+ if (!this.sdk.tokensMeta.isKYCUnderlying(meta)) {
1036
+ return void 0;
1037
+ }
1038
+ const adapter = suite.creditManager.adapters.get(meta.addr);
1039
+ const adapterAddress = adapter?.address;
1040
+ if (!adapterAddress) {
1041
+ return void 0;
1042
+ }
1043
+ const mc = [
1044
+ {
1045
+ target: adapterAddress,
1046
+ callData: (0, import_viem.encodeFunctionData)({
1047
+ abi: import_integrations_v3.ierc4626AdapterAbi,
1048
+ functionName: "depositDiff",
1049
+ args: [amount]
1050
+ })
1051
+ }
1052
+ ];
1053
+ return mc;
1054
+ }
1055
+ /**
1056
+ * Returns raw txs that are needed to update all price feeds so that all credit accounts (possibly from different markets) compute
803
1057
  * {@inheritDoc ICreditAccountsService.getOnDemandPriceUpdates}
804
1058
  **/
805
1059
  async getOnDemandPriceUpdates(account, ignoreReservePrices) {
@@ -1060,6 +1314,114 @@ class AbstractCreditAccountService extends import_base.SDKConstruct {
1060
1314
  import_constants.VERSION_RANGE_310
1061
1315
  )[0];
1062
1316
  }
1317
+ /**
1318
+ * Wrapper that selects between credit facade and KYC factory
1319
+ * @param suite
1320
+ * @param to
1321
+ * @param calls
1322
+ * @param referralCode
1323
+ * @returns
1324
+ */
1325
+ async openCreditAccountTx(suite, to, calls, referralCode) {
1326
+ const marketSuite = this.sdk.marketRegister.findByPool(suite.pool);
1327
+ const factory = await marketSuite.getKYCFactory();
1328
+ if (factory) {
1329
+ const tokensToRegister = await factory.getDSTokens();
1330
+ return factory.openCreditAccount(
1331
+ suite.creditManager.address,
1332
+ calls,
1333
+ tokensToRegister
1334
+ );
1335
+ }
1336
+ return suite.creditFacade.openCreditAccount(to, calls, referralCode ?? 0n);
1337
+ }
1338
+ /**
1339
+ * Wrapper that selects between credit facade and KYC factory
1340
+ * @param suite
1341
+ * @param creditAccount
1342
+ * @param calls
1343
+ * @returns
1344
+ */
1345
+ async multicallTx(suite, creditAccount, calls) {
1346
+ const marketSuite = this.sdk.marketRegister.findByCreditManager(
1347
+ suite.creditManager.address
1348
+ );
1349
+ const factory = await marketSuite.getKYCFactory();
1350
+ if (factory) {
1351
+ const tokensToRegister = [];
1352
+ return factory.multicall(creditAccount, calls, tokensToRegister);
1353
+ }
1354
+ return suite.creditFacade.multicall(creditAccount, calls);
1355
+ }
1356
+ /**
1357
+ * Wrapper that selects between credit facade and KYC factory
1358
+ * @param suite
1359
+ * @param creditAccount
1360
+ * @param calls
1361
+ * @param operation
1362
+ * @returns
1363
+ */
1364
+ async closeCreditAccountTx(suite, creditAccount, calls, operation) {
1365
+ const marketSuite = this.sdk.marketRegister.findByCreditManager(
1366
+ suite.creditManager.address
1367
+ );
1368
+ const factory = await marketSuite.getKYCFactory();
1369
+ if (operation === "close") {
1370
+ if (factory) {
1371
+ throw new Error(
1372
+ "CloseOptions=close is not supported for KYC underlying credit accounts"
1373
+ );
1374
+ }
1375
+ return suite.creditFacade.closeCreditAccount(creditAccount, calls);
1376
+ }
1377
+ if (factory) {
1378
+ const tokensToRegister = [];
1379
+ return factory.multicall(creditAccount, calls, tokensToRegister);
1380
+ }
1381
+ return suite.creditFacade.multicall(creditAccount, calls);
1382
+ }
1383
+ /**
1384
+ * Returns all KYC credit account addresses for an investor across the given market suites.
1385
+ * Resolves KYC factory per suite, then multicalls each factory's getCreditAccounts(investor).
1386
+ * @param investor - Owner address to query
1387
+ * @param suites - Market suites (KYC factories are resolved for each; undefined entries are skipped)
1388
+ * @returns Flat array of credit account addresses from all KYC markets
1389
+ */
1390
+ async getKYCCaOfInvestor(investor, suites) {
1391
+ if (suites.length === 0 || investor === import_constants.ADDRESS_0X0) return [];
1392
+ const factories = await Promise.all(
1393
+ suites.map((suite) => suite ? suite.getKYCFactory() : void 0)
1394
+ );
1395
+ const safeFactories = factories.reduce(
1396
+ (acc, v) => {
1397
+ if (v) {
1398
+ acc.push(v);
1399
+ }
1400
+ return acc;
1401
+ },
1402
+ []
1403
+ );
1404
+ const allResp = await this.client.multicall({
1405
+ contracts: [
1406
+ ...safeFactories.map((factory) => {
1407
+ return {
1408
+ abi: factory.abi,
1409
+ address: factory.address,
1410
+ functionName: "getCreditAccounts",
1411
+ args: [investor]
1412
+ };
1413
+ })
1414
+ ],
1415
+ allowFailure: true,
1416
+ batchSize: 0
1417
+ });
1418
+ const caLists = safeFactories.reduce((acc, _, index) => {
1419
+ const response = allResp[index];
1420
+ acc.push(...response.result || []);
1421
+ return acc;
1422
+ }, []);
1423
+ return caLists;
1424
+ }
1063
1425
  }
1064
1426
  // Annotate the CommonJS export names for ESM import in node:
1065
1427
  0 && (module.exports = {
@@ -65,7 +65,7 @@ class CreditAccountServiceV310 extends import_AbstractCreditAccountsService.Abst
65
65
  [addBotCall],
66
66
  targetContract
67
67
  ) : [addBotCall];
68
- const tx = targetContract.type === "creditAccount" ? cm.creditFacade.multicall(targetContract.creditAccount, calls) : void 0;
68
+ const tx = targetContract.type === "creditAccount" ? await this.multicallTx(cm, targetContract.creditAccount, calls) : void 0;
69
69
  return { tx, calls, creditFacade: cm.creditFacade };
70
70
  }
71
71
  /**
@@ -100,7 +100,7 @@ class CreditAccountServiceV310 extends import_AbstractCreditAccountsService.Abst
100
100
  operationCalls,
101
101
  creditAccount
102
102
  );
103
- const tx = cm.creditFacade.multicall(creditAccount.creditAccount, calls);
103
+ const tx = await this.multicallTx(cm, creditAccount.creditAccount, calls);
104
104
  return { tx, calls, creditFacade: cm.creditFacade };
105
105
  }
106
106
  /**
@@ -113,26 +113,35 @@ class CreditAccountServiceV310 extends import_AbstractCreditAccountsService.Abst
113
113
  creditAccount: ca,
114
114
  permits,
115
115
  to,
116
- tokensToClaim
116
+ tokensToClaim,
117
+ calls: wrapCalls = []
117
118
  }) {
118
119
  const cm = this.sdk.marketRegister.findCreditManager(ca.creditManager);
119
120
  const addCollateral = collateralAssets.filter((a) => a.balance > 0);
120
121
  const router = this.sdk.routerFor(ca);
122
+ const unwrapCalls = await this.getRedeemDiffCalls(1n, ca.creditManager) ?? [];
121
123
  const claimPath = await router.findClaimAllRewards({
122
124
  tokensToClaim,
123
125
  creditAccount: ca
124
126
  });
125
127
  const operationCalls = [
126
128
  ...this.prepareAddCollateral(ca.creditFacade, addCollateral, permits),
129
+ ...wrapCalls,
127
130
  ...this.prepareDisableQuotas(ca),
128
131
  ...this.prepareDecreaseDebt(ca),
132
+ ...unwrapCalls,
129
133
  ...claimPath.calls,
130
134
  ...assetsToWithdraw.map(
131
135
  (t) => this.prepareWithdrawToken(ca.creditFacade, t.token, import_math.MAX_UINT256, to)
132
136
  )
133
137
  ];
134
138
  const calls = operation === "close" ? operationCalls : await this.prependPriceUpdates(ca.creditManager, operationCalls, ca);
135
- const tx = operation === "close" ? cm.creditFacade.closeCreditAccount(ca.creditAccount, calls) : cm.creditFacade.multicall(ca.creditAccount, calls);
139
+ const tx = await this.closeCreditAccountTx(
140
+ cm,
141
+ ca.creditAccount,
142
+ calls,
143
+ operation
144
+ );
136
145
  return { tx, calls, creditFacade: cm.creditFacade };
137
146
  }
138
147
  /**
@@ -152,10 +161,12 @@ class CreditAccountServiceV310 extends import_AbstractCreditAccountsService.Abst
152
161
  tokensToClaim,
153
162
  creditAccount: ca
154
163
  });
164
+ const wrapCalls = await this.getDepositDiffCalls(1n, ca.creditManager) ?? [];
155
165
  const addCollateral = collateralAssets.filter((a) => a.balance > 0);
156
166
  const operationCalls = [
157
167
  ...this.prepareAddCollateral(ca.creditFacade, addCollateral, permits),
158
168
  ...claimPath.calls,
169
+ ...wrapCalls,
159
170
  ...assetsToWithdraw.map(
160
171
  (t) => this.prepareWithdrawToken(ca.creditFacade, t.token, import_math.MAX_UINT256, to)
161
172
  )
@@ -203,7 +214,7 @@ class CreditAccountServiceV310 extends import_AbstractCreditAccountsService.Abst
203
214
  operationCalls,
204
215
  ca
205
216
  );
206
- const tx = cm.creditFacade.multicall(ca.creditAccount, calls);
217
+ const tx = await this.multicallTx(cm, ca.creditAccount, calls);
207
218
  return { tx, calls, creditFacade: cm.creditFacade };
208
219
  }
209
220
  async previewWithdrawLlamathenaProportionally(_) {
@@ -38,7 +38,7 @@ class ChainContractsRegister {
38
38
  logger;
39
39
  constructor(client, logger) {
40
40
  this.client = client;
41
- this.tokensMeta = new import_TokensMeta.TokensMeta(client);
41
+ this.tokensMeta = new import_TokensMeta.TokensMeta(client, logger);
42
42
  this.logger = logger;
43
43
  }
44
44
  /**