@gearbox-protocol/sdk 14.0.0 → 14.1.0
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.
- package/dist/cjs/abi/kyc/iDSRegistryService.js +149 -0
- package/dist/cjs/abi/kyc/iDSToken.js +71 -0
- package/dist/cjs/abi/kyc/iKYCCompressor.js +196 -0
- package/dist/cjs/abi/kyc/iKYCFactory.js +122 -0
- package/dist/cjs/abi/kyc/iKYCUnderlying.js +401 -0
- package/dist/cjs/abi/kyc/iSecuritizeDegenNFT.js +326 -0
- package/dist/cjs/abi/kyc/iSecuritizeKYCFactory.js +319 -0
- package/dist/cjs/dev/AccountOpener.js +45 -5
- package/dist/cjs/sdk/OnchainSDK.js +55 -5
- package/dist/cjs/sdk/accounts/AbstractCreditAccountsService.js +335 -21
- package/dist/cjs/sdk/accounts/CreditAccountsServiceV310.js +7 -1
- package/dist/cjs/sdk/base/TokensMeta.js +22 -42
- package/dist/cjs/sdk/base/token-types.js +9 -0
- package/dist/cjs/sdk/chain/chains.js +18 -1
- package/dist/cjs/sdk/constants/address-provider.js +3 -0
- package/dist/cjs/sdk/market/MarketRegister.js +70 -116
- package/dist/cjs/sdk/market/MarketSuite.js +3 -0
- package/dist/cjs/sdk/market/index.js +2 -0
- package/dist/cjs/sdk/market/kyc/KYCRegistry.js +269 -0
- package/dist/cjs/sdk/market/kyc/index.js +26 -0
- package/dist/cjs/sdk/market/kyc/securitize/SecuritizeKYCFactory.js +242 -0
- package/dist/cjs/sdk/market/kyc/securitize/constants.js +28 -0
- package/dist/cjs/sdk/market/kyc/securitize/index.js +26 -0
- package/dist/cjs/sdk/market/kyc/securitize/types.js +16 -0
- package/dist/cjs/sdk/{accounts/utils.js → market/kyc/types.js} +11 -15
- package/dist/cjs/sdk/market/pool/PoolSuite.js +3 -0
- package/dist/cjs/sdk/market/pool/PoolV310Contract.js +11 -2
- package/dist/cjs/sdk/market/pool/index.js +2 -0
- package/dist/cjs/sdk/market/pricefeeds/PriceFeedsRegister.js +3 -3
- package/dist/cjs/sdk/options.js +6 -0
- package/dist/cjs/sdk/pools/PoolService.js +104 -12
- package/dist/cjs/sdk/utils/viem/executeDelegatedMulticalls.js +38 -0
- package/dist/cjs/sdk/utils/viem/index.js +2 -0
- package/dist/esm/abi/kyc/iDSRegistryService.js +125 -0
- package/dist/esm/abi/kyc/iDSToken.js +47 -0
- package/dist/esm/abi/kyc/iKYCCompressor.js +172 -0
- package/dist/esm/abi/kyc/iKYCFactory.js +98 -0
- package/dist/esm/abi/kyc/iKYCUnderlying.js +377 -0
- package/dist/esm/abi/kyc/iSecuritizeDegenNFT.js +302 -0
- package/dist/esm/abi/kyc/iSecuritizeKYCFactory.js +295 -0
- package/dist/esm/dev/AccountOpener.js +47 -6
- package/dist/esm/sdk/OnchainSDK.js +57 -5
- package/dist/esm/sdk/accounts/AbstractCreditAccountsService.js +336 -22
- package/dist/esm/sdk/accounts/CreditAccountsServiceV310.js +7 -1
- package/dist/esm/sdk/base/TokensMeta.js +22 -44
- package/dist/esm/sdk/base/token-types.js +6 -0
- package/dist/esm/sdk/chain/chains.js +18 -1
- package/dist/esm/sdk/constants/address-provider.js +2 -0
- package/dist/esm/sdk/market/MarketRegister.js +74 -118
- package/dist/esm/sdk/market/MarketSuite.js +3 -0
- package/dist/esm/sdk/market/index.js +1 -0
- package/dist/esm/sdk/market/kyc/KYCRegistry.js +253 -0
- package/dist/esm/sdk/market/kyc/index.js +3 -0
- package/dist/esm/sdk/market/kyc/securitize/SecuritizeKYCFactory.js +218 -0
- package/dist/esm/sdk/market/kyc/securitize/constants.js +4 -0
- package/dist/esm/sdk/market/kyc/securitize/index.js +3 -0
- package/dist/esm/sdk/market/kyc/securitize/types.js +0 -0
- package/dist/esm/sdk/market/kyc/types.js +9 -0
- package/dist/esm/sdk/market/pool/PoolSuite.js +3 -0
- package/dist/esm/sdk/market/pool/PoolV310Contract.js +11 -2
- package/dist/esm/sdk/market/pool/index.js +1 -0
- package/dist/esm/sdk/market/pricefeeds/PriceFeedsRegister.js +3 -3
- package/dist/esm/sdk/options.js +6 -0
- package/dist/esm/sdk/pools/PoolService.js +109 -13
- package/dist/esm/sdk/utils/viem/executeDelegatedMulticalls.js +14 -0
- package/dist/esm/sdk/utils/viem/index.js +1 -0
- package/dist/types/abi/kyc/iDSRegistryService.d.ts +191 -0
- package/dist/types/abi/kyc/iDSToken.d.ts +67 -0
- package/dist/types/abi/kyc/iKYCCompressor.d.ts +228 -0
- package/dist/types/abi/kyc/iKYCFactory.d.ts +139 -0
- package/dist/types/abi/kyc/iKYCUnderlying.d.ts +548 -0
- package/dist/types/abi/kyc/iSecuritizeDegenNFT.d.ts +404 -0
- package/dist/types/abi/kyc/iSecuritizeKYCFactory.d.ts +376 -0
- package/dist/types/sdk/OnchainSDK.d.ts +19 -1
- package/dist/types/sdk/accounts/AbstractCreditAccountsService.d.ts +59 -6
- package/dist/types/sdk/accounts/CreditAccountsServiceV310.d.ts +1 -1
- package/dist/types/sdk/accounts/types.d.ts +114 -14
- package/dist/types/sdk/base/TokensMeta.d.ts +14 -3
- package/dist/types/sdk/base/token-types.d.ts +44 -4
- package/dist/types/sdk/base/types.d.ts +116 -2
- package/dist/types/sdk/chain/chains.d.ts +5 -1
- package/dist/types/sdk/constants/address-provider.d.ts +1 -0
- package/dist/types/sdk/market/MarketRegister.d.ts +6 -9
- package/dist/types/sdk/market/MarketSuite.d.ts +2 -0
- package/dist/types/sdk/market/index.d.ts +1 -0
- package/dist/types/sdk/market/kyc/KYCRegistry.d.ts +52 -0
- package/dist/types/sdk/market/kyc/index.d.ts +3 -0
- package/dist/types/sdk/market/kyc/securitize/SecuritizeKYCFactory.d.ts +429 -0
- package/dist/types/sdk/market/kyc/securitize/constants.d.ts +1 -0
- package/dist/types/sdk/market/kyc/securitize/index.d.ts +3 -0
- package/dist/types/sdk/market/kyc/securitize/types.d.ts +136 -0
- package/dist/types/sdk/market/kyc/types.d.ts +171 -0
- package/dist/types/sdk/market/oracle/PriceOracleBaseContract.d.ts +3 -2
- package/dist/types/sdk/market/oracle/types.d.ts +3 -10
- package/dist/types/sdk/market/pool/PoolSuite.d.ts +2 -0
- package/dist/types/sdk/market/pool/PoolV310Contract.d.ts +6 -2
- package/dist/types/sdk/market/pool/index.d.ts +1 -0
- package/dist/types/sdk/market/pricefeeds/PriceFeedsRegister.d.ts +1 -1
- package/dist/types/sdk/market/types.d.ts +1 -1
- package/dist/types/sdk/options.d.ts +1 -0
- package/dist/types/sdk/pools/PoolService.d.ts +8 -8
- package/dist/types/sdk/pools/types.d.ts +1 -1
- package/dist/types/sdk/types/state-human.d.ts +2 -0
- package/dist/types/sdk/types/state.d.ts +5 -0
- package/dist/types/sdk/utils/viem/executeDelegatedMulticalls.d.ts +28 -0
- package/dist/types/sdk/utils/viem/index.d.ts +1 -0
- package/package.json +1 -1
- package/dist/esm/sdk/accounts/utils.js +0 -14
- package/dist/types/sdk/accounts/utils.d.ts +0 -2
|
@@ -52,6 +52,7 @@ class AccountOpener extends import_sdk.SDKConstruct {
|
|
|
52
52
|
#minDebtMultiplier;
|
|
53
53
|
#allowMint;
|
|
54
54
|
#leverageDelta;
|
|
55
|
+
#poolService;
|
|
55
56
|
constructor(service, options_ = {}) {
|
|
56
57
|
super(service.sdk);
|
|
57
58
|
const {
|
|
@@ -77,6 +78,7 @@ class AccountOpener extends import_sdk.SDKConstruct {
|
|
|
77
78
|
this.#poolDepositMultiplier = BigInt(poolDepositMultiplier);
|
|
78
79
|
this.#minDebtMultiplier = BigInt(minDebtMultiplier);
|
|
79
80
|
this.#leverageDelta = BigInt(leverageDelta);
|
|
81
|
+
this.#poolService = new import_sdk.PoolService(service.sdk);
|
|
80
82
|
this.#logger?.info(
|
|
81
83
|
{
|
|
82
84
|
borrower: (0, import_accounts.privateKeyToAccount)(this.borrowerKey).address,
|
|
@@ -114,6 +116,10 @@ class AccountOpener extends import_sdk.SDKConstruct {
|
|
|
114
116
|
},
|
|
115
117
|
"opening credit accounts"
|
|
116
118
|
);
|
|
119
|
+
await Promise.all([
|
|
120
|
+
this.sdk.tokensMeta.loadTokenData(),
|
|
121
|
+
this.sdk.marketRegister.loadZappers()
|
|
122
|
+
]);
|
|
117
123
|
let deposits = [];
|
|
118
124
|
if (depositIntoPools) {
|
|
119
125
|
try {
|
|
@@ -465,9 +471,34 @@ class AccountOpener extends import_sdk.SDKConstruct {
|
|
|
465
471
|
this.#logger?.debug(
|
|
466
472
|
`depositor balance in underlying: ${this.sdk.tokensMeta.formatBN(pool.underlying, allowance, { symbol: true })}`
|
|
467
473
|
);
|
|
474
|
+
const tokensOut = this.#poolService.getDepositTokensOut(
|
|
475
|
+
address,
|
|
476
|
+
underlying
|
|
477
|
+
);
|
|
478
|
+
this.#logger?.debug(
|
|
479
|
+
{ tokensOut: tokensOut.map((t) => this.labelAddress(t)) },
|
|
480
|
+
"deposit tokens out"
|
|
481
|
+
);
|
|
482
|
+
if (tokensOut.length === 0) {
|
|
483
|
+
throw new Error(`no tokens out found for pool ${poolName}`);
|
|
484
|
+
}
|
|
485
|
+
const tokenOut = tokensOut[0];
|
|
486
|
+
const metadata = this.#poolService.getDepositMetadata(
|
|
487
|
+
address,
|
|
488
|
+
underlying,
|
|
489
|
+
tokenOut
|
|
490
|
+
);
|
|
491
|
+
this.logger?.debug(
|
|
492
|
+
{
|
|
493
|
+
underlying: this.labelAddress(underlying),
|
|
494
|
+
tokenOut: this.labelAddress(tokenOut),
|
|
495
|
+
...metadata
|
|
496
|
+
},
|
|
497
|
+
"pool deposit metadata"
|
|
498
|
+
);
|
|
468
499
|
txHash = await this.#anvil.writeContract({
|
|
469
500
|
account: depositor,
|
|
470
|
-
address:
|
|
501
|
+
address: metadata.approveTarget,
|
|
471
502
|
abi: import_iERC20.ierc20Abi,
|
|
472
503
|
functionName: "approve",
|
|
473
504
|
args: [address, allowance],
|
|
@@ -484,12 +515,21 @@ class AccountOpener extends import_sdk.SDKConstruct {
|
|
|
484
515
|
this.#logger?.debug(
|
|
485
516
|
`depositor approved underlying for pool ${poolName}: ${txHash}`
|
|
486
517
|
);
|
|
518
|
+
const depositCall = this.#poolService.addLiquidity({
|
|
519
|
+
collateral: { token: underlying, balance: amount },
|
|
520
|
+
pool: address,
|
|
521
|
+
wallet: depositor.address,
|
|
522
|
+
meta: metadata
|
|
523
|
+
});
|
|
524
|
+
if (!depositCall) {
|
|
525
|
+
throw new Error(`no deposit call could be created for ${poolName}`);
|
|
526
|
+
}
|
|
487
527
|
txHash = await this.#anvil.writeContract({
|
|
488
528
|
account: depositor,
|
|
489
|
-
address,
|
|
490
|
-
abi:
|
|
491
|
-
functionName:
|
|
492
|
-
args:
|
|
529
|
+
address: depositCall.target,
|
|
530
|
+
abi: depositCall.abi,
|
|
531
|
+
functionName: depositCall.functionName,
|
|
532
|
+
args: depositCall.args,
|
|
493
533
|
chain: this.#anvil.chain
|
|
494
534
|
});
|
|
495
535
|
receipt = await this.#anvil.waitForTransactionReceipt({ hash: txHash });
|
|
@@ -27,11 +27,13 @@ var import_base = require("./base/index.js");
|
|
|
27
27
|
var import_chain = require("./chain/index.js");
|
|
28
28
|
var import_constants = require("./constants/index.js");
|
|
29
29
|
var import_core = require("./core/index.js");
|
|
30
|
+
var import_market = require("./market/index.js");
|
|
30
31
|
var import_MarketRegister = require("./market/MarketRegister.js");
|
|
31
32
|
var import_pricefeeds = require("./market/pricefeeds/index.js");
|
|
32
33
|
var import_plugins = require("./plugins/index.js");
|
|
33
34
|
var import_router = require("./router/index.js");
|
|
34
35
|
var import_utils = require("./utils/index.js");
|
|
36
|
+
var import_viem2 = require("./utils/viem/index.js");
|
|
35
37
|
const STATE_VERSION = 1;
|
|
36
38
|
function createViemClient(opts, chain) {
|
|
37
39
|
if ("client" in opts) {
|
|
@@ -60,6 +62,7 @@ class OnchainSDK extends import_base.ChainContractsRegister {
|
|
|
60
62
|
#syncing = false;
|
|
61
63
|
#attached = false;
|
|
62
64
|
#addressProvider;
|
|
65
|
+
#kyc;
|
|
63
66
|
#marketRegister;
|
|
64
67
|
#priceFeeds;
|
|
65
68
|
/**
|
|
@@ -87,6 +90,7 @@ class OnchainSDK extends import_base.ChainContractsRegister {
|
|
|
87
90
|
super(client, options?.logger);
|
|
88
91
|
this.strictContractTypes = options?.strictContractTypes ?? false;
|
|
89
92
|
this.plugins = options?.plugins ?? {};
|
|
93
|
+
this.#kyc = new import_market.KYCRegistry(this);
|
|
90
94
|
for (const plugin of Object.values(this.plugins)) {
|
|
91
95
|
plugin.sdk = this;
|
|
92
96
|
}
|
|
@@ -116,6 +120,7 @@ class OnchainSDK extends import_base.ChainContractsRegister {
|
|
|
116
120
|
const marketConfigurators = mcs ?? import_utils.TypedObjectUtils.keys(
|
|
117
121
|
this.client.chain.defaultMarketConfigurators
|
|
118
122
|
);
|
|
123
|
+
const kycFactories = options?.kycFactories ?? this.client.chain.kycFactories;
|
|
119
124
|
this.logger?.info(
|
|
120
125
|
{
|
|
121
126
|
networkType: this.networkType,
|
|
@@ -153,10 +158,33 @@ class OnchainSDK extends import_base.ChainContractsRegister {
|
|
|
153
158
|
);
|
|
154
159
|
await this.#addressProvider.syncState(this.currentBlock);
|
|
155
160
|
this.#marketRegister = new import_MarketRegister.MarketRegister(this, ignoreMarkets);
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
161
|
+
if (!marketConfigurators.length) {
|
|
162
|
+
this.logger?.warn(
|
|
163
|
+
"no market configurators provided, skipping market loading"
|
|
164
|
+
);
|
|
165
|
+
} else {
|
|
166
|
+
const delegated = [
|
|
167
|
+
...this.#marketRegister.getLoadMulticalls(marketConfigurators),
|
|
168
|
+
...this.#kyc.getLoadMulticalls(marketConfigurators, kycFactories)
|
|
169
|
+
];
|
|
170
|
+
let txs = [];
|
|
171
|
+
if (!ignoreUpdateablePrices) {
|
|
172
|
+
const updatables = await this.#priceFeeds.getPartialUpdatablePriceFeeds(
|
|
173
|
+
marketConfigurators
|
|
174
|
+
);
|
|
175
|
+
const updates = await this.#priceFeeds.generatePriceFeedsUpdateTxs(updatables);
|
|
176
|
+
txs = updates.txs;
|
|
177
|
+
}
|
|
178
|
+
this.logger?.debug(
|
|
179
|
+
{ configurators: marketConfigurators },
|
|
180
|
+
`calling getMarkets with ${txs.length} price updates in block ${this.currentBlock}`
|
|
181
|
+
);
|
|
182
|
+
await (0, import_viem2.executeDelegatedMulticalls)(this.client, delegated, {
|
|
183
|
+
priceUpdates: txs,
|
|
184
|
+
blockNumber: this.currentBlock,
|
|
185
|
+
gas: this.gasLimit
|
|
186
|
+
});
|
|
187
|
+
}
|
|
160
188
|
const pluginsList = import_utils.TypedObjectUtils.entries(this.plugins);
|
|
161
189
|
const pluginResponse = await Promise.allSettled(
|
|
162
190
|
pluginsList.map(([name, plugin]) => {
|
|
@@ -209,6 +237,8 @@ class OnchainSDK extends import_base.ChainContractsRegister {
|
|
|
209
237
|
);
|
|
210
238
|
this.#marketRegister = new import_MarketRegister.MarketRegister(this, ignoreMarkets);
|
|
211
239
|
this.#marketRegister.hydrate(state.markets);
|
|
240
|
+
this.#kyc = new import_market.KYCRegistry(this);
|
|
241
|
+
this.#kyc.setState(state.kyc);
|
|
212
242
|
for (const [name, plugin] of import_utils.TypedObjectUtils.entries(this.plugins)) {
|
|
213
243
|
const pluginState = state.plugins[name];
|
|
214
244
|
if (plugin.hydrate && pluginState) {
|
|
@@ -252,6 +282,7 @@ class OnchainSDK extends import_base.ChainContractsRegister {
|
|
|
252
282
|
addressProviderV3: this.addressProvider.stateHuman(raw)
|
|
253
283
|
},
|
|
254
284
|
tokens: this.tokensMeta.values(),
|
|
285
|
+
kyc: this.#kyc.stateHuman(raw),
|
|
255
286
|
plugins: Object.fromEntries(
|
|
256
287
|
import_utils.TypedObjectUtils.entries(this.plugins).map(([name, plugin]) => [
|
|
257
288
|
name,
|
|
@@ -271,6 +302,7 @@ class OnchainSDK extends import_base.ChainContractsRegister {
|
|
|
271
302
|
timestamp: this.timestamp,
|
|
272
303
|
addressProvider: this.addressProvider.state,
|
|
273
304
|
markets: this.marketRegister.state,
|
|
305
|
+
kyc: this.#kyc.state,
|
|
274
306
|
plugins: Object.fromEntries(
|
|
275
307
|
import_utils.TypedObjectUtils.entries(this.plugins).map(([name, plugin]) => [
|
|
276
308
|
name,
|
|
@@ -438,9 +470,27 @@ class OnchainSDK extends import_base.ChainContractsRegister {
|
|
|
438
470
|
return this.#marketRegister;
|
|
439
471
|
}
|
|
440
472
|
/**
|
|
473
|
+
* KYC register for KYC-wrapped underlying tokens and factories.
|
|
474
|
+
*
|
|
475
|
+
* @throws If the SDK has not been attached or hydrated yet.
|
|
476
|
+
**/
|
|
477
|
+
get kyc() {
|
|
478
|
+
if (this.#kyc === void 0) {
|
|
479
|
+
throw new import_core.SdkNotAttachedError();
|
|
480
|
+
}
|
|
481
|
+
return this.#kyc;
|
|
482
|
+
}
|
|
483
|
+
/**
|
|
484
|
+
* @internal
|
|
441
485
|
* Resolves the appropriate router contract for a given credit manager,
|
|
442
486
|
* credit facade, or explicit version range.
|
|
443
|
-
|
|
487
|
+
*
|
|
488
|
+
* @param params - Identifies the context: a credit manager address/state,
|
|
489
|
+
* a credit facade address/state, or a {@link VersionRange}.
|
|
490
|
+
* @returns The matching router contract instance.
|
|
491
|
+
* @throws If the credit facade version is unsupported or no router is
|
|
492
|
+
* registered for the resolved version range.
|
|
493
|
+
**/
|
|
444
494
|
routerFor(params) {
|
|
445
495
|
let routerRange;
|
|
446
496
|
if (Array.isArray(params)) {
|
|
@@ -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");
|
|
@@ -29,6 +30,7 @@ var import_peripheryCompressor = require("../../abi/compressors/peripheryCompres
|
|
|
29
30
|
var import_rewardsCompressor = require("../../abi/compressors/rewardsCompressor.js");
|
|
30
31
|
var import_IWithdrawalCompressorV310 = require("../../abi/IWithdrawalCompressorV310.js");
|
|
31
32
|
var import_iBaseRewardPool = require("../../abi/iBaseRewardPool.js");
|
|
33
|
+
var import_iKYCFactory = require("../../abi/kyc/iKYCFactory.js");
|
|
32
34
|
var import_base = require("../base/index.js");
|
|
33
35
|
var import_chains = require("../chain/chains.js");
|
|
34
36
|
var import_constants = require("../constants/index.js");
|
|
@@ -76,24 +78,40 @@ class AbstractCreditAccountService extends import_base.SDKConstruct {
|
|
|
76
78
|
} catch (_e) {
|
|
77
79
|
return void 0;
|
|
78
80
|
}
|
|
81
|
+
const marketSuite = this.sdk.marketRegister.findByCreditManager(
|
|
82
|
+
raw.creditManager
|
|
83
|
+
);
|
|
84
|
+
const factory = marketSuite.kycFactory;
|
|
85
|
+
let ca;
|
|
86
|
+
let investor;
|
|
79
87
|
if (raw.success) {
|
|
80
|
-
|
|
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
|
+
});
|
|
81
113
|
}
|
|
82
|
-
|
|
83
|
-
const [cad] = await (0, import_viem2.simulateWithPriceUpdates)(this.client, {
|
|
84
|
-
priceUpdates: priceUpdateTxs,
|
|
85
|
-
contracts: [
|
|
86
|
-
{
|
|
87
|
-
abi: import_creditAccountCompressor.creditAccountCompressorAbi,
|
|
88
|
-
address: this.#compressor,
|
|
89
|
-
functionName: "getCreditAccountData",
|
|
90
|
-
args: [account]
|
|
91
|
-
}
|
|
92
|
-
],
|
|
93
|
-
blockNumber,
|
|
94
|
-
gas: this.sdk.gasLimit
|
|
95
|
-
});
|
|
96
|
-
return cad;
|
|
114
|
+
return { ...ca, investor };
|
|
97
115
|
}
|
|
98
116
|
/**
|
|
99
117
|
* {@inheritDoc ICreditAccountsService.getCreditAccounts}
|
|
@@ -149,6 +167,99 @@ class AbstractCreditAccountService extends import_base.SDKConstruct {
|
|
|
149
167
|
);
|
|
150
168
|
return allCAs.sort((a, b) => Number(a.healthFactor - b.healthFactor));
|
|
151
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
|
+
}
|
|
152
263
|
/**
|
|
153
264
|
* {@inheritDoc ICreditAccountsService.getRewards}
|
|
154
265
|
**/
|
|
@@ -358,6 +469,13 @@ class AbstractCreditAccountService extends import_base.SDKConstruct {
|
|
|
358
469
|
closePath
|
|
359
470
|
}) {
|
|
360
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
|
+
}
|
|
361
479
|
const routerCloseResult = closePath || await this.sdk.routerFor(ca).findBestClosePath({
|
|
362
480
|
creditAccount: ca,
|
|
363
481
|
creditManager: cm.creditManager,
|
|
@@ -463,8 +581,18 @@ class AbstractCreditAccountService extends import_base.SDKConstruct {
|
|
|
463
581
|
],
|
|
464
582
|
{}
|
|
465
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
|
+
}
|
|
466
593
|
const operationCalls = [
|
|
467
594
|
...addCollateralCalls,
|
|
595
|
+
...unwrapCalls,
|
|
468
596
|
this.#prepareChangeDebt(creditAccount.creditFacade, change, isDecrease)
|
|
469
597
|
];
|
|
470
598
|
const calls = await this.prependPriceUpdates(
|
|
@@ -672,6 +800,29 @@ class AbstractCreditAccountService extends import_base.SDKConstruct {
|
|
|
672
800
|
const tx = await this.multicallTx(cm, creditAccount.creditAccount, calls);
|
|
673
801
|
return { tx, calls, creditFacade: cm.creditFacade };
|
|
674
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
|
+
}
|
|
675
826
|
/**
|
|
676
827
|
* {@inheritDoc ICreditAccountsService.openCA}
|
|
677
828
|
**/
|
|
@@ -689,7 +840,8 @@ class AbstractCreditAccountService extends import_base.SDKConstruct {
|
|
|
689
840
|
calls: openPathCalls,
|
|
690
841
|
callsAfter,
|
|
691
842
|
minQuota,
|
|
692
|
-
averageQuota
|
|
843
|
+
averageQuota,
|
|
844
|
+
kycOptions
|
|
693
845
|
} = props;
|
|
694
846
|
const cmSuite = this.sdk.marketRegister.findCreditManager(creditManager);
|
|
695
847
|
const cm = cmSuite.creditManager;
|
|
@@ -723,7 +875,13 @@ class AbstractCreditAccountService extends import_base.SDKConstruct {
|
|
|
723
875
|
if (reopenCreditAccount) {
|
|
724
876
|
tx = await this.multicallTx(cmSuite, reopenCreditAccount, calls);
|
|
725
877
|
} else {
|
|
726
|
-
tx = await this.openCreditAccountTx(
|
|
878
|
+
tx = await this.openCreditAccountTx(
|
|
879
|
+
cmSuite,
|
|
880
|
+
to,
|
|
881
|
+
calls,
|
|
882
|
+
referralCode,
|
|
883
|
+
kycOptions
|
|
884
|
+
);
|
|
727
885
|
}
|
|
728
886
|
tx.value = ethAmount.toString(10);
|
|
729
887
|
return { calls, tx, creditFacade: cmSuite.creditFacade };
|
|
@@ -806,6 +964,131 @@ class AbstractCreditAccountService extends import_base.SDKConstruct {
|
|
|
806
964
|
return resp;
|
|
807
965
|
}
|
|
808
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
|
|
809
1092
|
* {@inheritDoc ICreditAccountsService.getOnDemandPriceUpdates}
|
|
810
1093
|
**/
|
|
811
1094
|
async getOnDemandPriceUpdates(account, ignoreReservePrices) {
|
|
@@ -1060,9 +1343,19 @@ class AbstractCreditAccountService extends import_base.SDKConstruct {
|
|
|
1060
1343
|
* @param to
|
|
1061
1344
|
* @param calls
|
|
1062
1345
|
* @param referralCode
|
|
1346
|
+
* @param kycOptions
|
|
1063
1347
|
* @returns
|
|
1064
1348
|
*/
|
|
1065
|
-
async openCreditAccountTx(suite, to, calls, referralCode) {
|
|
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
|
+
}
|
|
1066
1359
|
return suite.creditFacade.openCreditAccount(to, calls, referralCode ?? 0n);
|
|
1067
1360
|
}
|
|
1068
1361
|
/**
|
|
@@ -1070,9 +1363,17 @@ class AbstractCreditAccountService extends import_base.SDKConstruct {
|
|
|
1070
1363
|
* @param suite
|
|
1071
1364
|
* @param creditAccount
|
|
1072
1365
|
* @param calls
|
|
1366
|
+
* @param kycOptions
|
|
1073
1367
|
* @returns
|
|
1074
1368
|
*/
|
|
1075
|
-
async multicallTx(suite, creditAccount, calls) {
|
|
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
|
+
}
|
|
1076
1377
|
return suite.creditFacade.multicall(creditAccount, calls);
|
|
1077
1378
|
}
|
|
1078
1379
|
/**
|
|
@@ -1081,12 +1382,25 @@ class AbstractCreditAccountService extends import_base.SDKConstruct {
|
|
|
1081
1382
|
* @param creditAccount
|
|
1082
1383
|
* @param calls
|
|
1083
1384
|
* @param operation
|
|
1385
|
+
* @param kycOptions
|
|
1084
1386
|
* @returns
|
|
1085
1387
|
*/
|
|
1086
|
-
async closeCreditAccountTx(suite, creditAccount, calls, operation) {
|
|
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;
|
|
1087
1393
|
if (operation === "close") {
|
|
1394
|
+
if (factory) {
|
|
1395
|
+
throw new Error(
|
|
1396
|
+
"CloseOptions=close is not supported for KYC underlying credit accounts"
|
|
1397
|
+
);
|
|
1398
|
+
}
|
|
1088
1399
|
return suite.creditFacade.closeCreditAccount(creditAccount, calls);
|
|
1089
1400
|
}
|
|
1401
|
+
if (factory) {
|
|
1402
|
+
return factory.multicall(creditAccount, calls, kycOptions);
|
|
1403
|
+
}
|
|
1090
1404
|
return suite.creditFacade.multicall(creditAccount, calls);
|
|
1091
1405
|
}
|
|
1092
1406
|
}
|