@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
|
@@ -22,11 +22,15 @@ import {
|
|
|
22
22
|
SdkNotAttachedError,
|
|
23
23
|
SdkStateVersionMismatchError
|
|
24
24
|
} from "./core/index.js";
|
|
25
|
+
import { KYCRegistry } from "./market/index.js";
|
|
25
26
|
import { MarketRegister } from "./market/MarketRegister.js";
|
|
26
27
|
import { PriceFeedRegister } from "./market/pricefeeds/index.js";
|
|
27
28
|
import { PluginStateVersionError } from "./plugins/index.js";
|
|
28
29
|
import { createRouter } from "./router/index.js";
|
|
29
30
|
import { formatTimestamp, TypedObjectUtils, toAddress } from "./utils/index.js";
|
|
31
|
+
import {
|
|
32
|
+
executeDelegatedMulticalls
|
|
33
|
+
} from "./utils/viem/index.js";
|
|
30
34
|
const STATE_VERSION = 1;
|
|
31
35
|
function createViemClient(opts, chain) {
|
|
32
36
|
if ("client" in opts) {
|
|
@@ -55,6 +59,7 @@ class OnchainSDK extends ChainContractsRegister {
|
|
|
55
59
|
#syncing = false;
|
|
56
60
|
#attached = false;
|
|
57
61
|
#addressProvider;
|
|
62
|
+
#kyc;
|
|
58
63
|
#marketRegister;
|
|
59
64
|
#priceFeeds;
|
|
60
65
|
/**
|
|
@@ -82,6 +87,7 @@ class OnchainSDK extends ChainContractsRegister {
|
|
|
82
87
|
super(client, options?.logger);
|
|
83
88
|
this.strictContractTypes = options?.strictContractTypes ?? false;
|
|
84
89
|
this.plugins = options?.plugins ?? {};
|
|
90
|
+
this.#kyc = new KYCRegistry(this);
|
|
85
91
|
for (const plugin of Object.values(this.plugins)) {
|
|
86
92
|
plugin.sdk = this;
|
|
87
93
|
}
|
|
@@ -111,6 +117,7 @@ class OnchainSDK extends ChainContractsRegister {
|
|
|
111
117
|
const marketConfigurators = mcs ?? TypedObjectUtils.keys(
|
|
112
118
|
this.client.chain.defaultMarketConfigurators
|
|
113
119
|
);
|
|
120
|
+
const kycFactories = options?.kycFactories ?? this.client.chain.kycFactories;
|
|
114
121
|
this.logger?.info(
|
|
115
122
|
{
|
|
116
123
|
networkType: this.networkType,
|
|
@@ -148,10 +155,33 @@ class OnchainSDK extends ChainContractsRegister {
|
|
|
148
155
|
);
|
|
149
156
|
await this.#addressProvider.syncState(this.currentBlock);
|
|
150
157
|
this.#marketRegister = new MarketRegister(this, ignoreMarkets);
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
158
|
+
if (!marketConfigurators.length) {
|
|
159
|
+
this.logger?.warn(
|
|
160
|
+
"no market configurators provided, skipping market loading"
|
|
161
|
+
);
|
|
162
|
+
} else {
|
|
163
|
+
const delegated = [
|
|
164
|
+
...this.#marketRegister.getLoadMulticalls(marketConfigurators),
|
|
165
|
+
...this.#kyc.getLoadMulticalls(marketConfigurators, kycFactories)
|
|
166
|
+
];
|
|
167
|
+
let txs = [];
|
|
168
|
+
if (!ignoreUpdateablePrices) {
|
|
169
|
+
const updatables = await this.#priceFeeds.getPartialUpdatablePriceFeeds(
|
|
170
|
+
marketConfigurators
|
|
171
|
+
);
|
|
172
|
+
const updates = await this.#priceFeeds.generatePriceFeedsUpdateTxs(updatables);
|
|
173
|
+
txs = updates.txs;
|
|
174
|
+
}
|
|
175
|
+
this.logger?.debug(
|
|
176
|
+
{ configurators: marketConfigurators },
|
|
177
|
+
`calling getMarkets with ${txs.length} price updates in block ${this.currentBlock}`
|
|
178
|
+
);
|
|
179
|
+
await executeDelegatedMulticalls(this.client, delegated, {
|
|
180
|
+
priceUpdates: txs,
|
|
181
|
+
blockNumber: this.currentBlock,
|
|
182
|
+
gas: this.gasLimit
|
|
183
|
+
});
|
|
184
|
+
}
|
|
155
185
|
const pluginsList = TypedObjectUtils.entries(this.plugins);
|
|
156
186
|
const pluginResponse = await Promise.allSettled(
|
|
157
187
|
pluginsList.map(([name, plugin]) => {
|
|
@@ -204,6 +234,8 @@ class OnchainSDK extends ChainContractsRegister {
|
|
|
204
234
|
);
|
|
205
235
|
this.#marketRegister = new MarketRegister(this, ignoreMarkets);
|
|
206
236
|
this.#marketRegister.hydrate(state.markets);
|
|
237
|
+
this.#kyc = new KYCRegistry(this);
|
|
238
|
+
this.#kyc.setState(state.kyc);
|
|
207
239
|
for (const [name, plugin] of TypedObjectUtils.entries(this.plugins)) {
|
|
208
240
|
const pluginState = state.plugins[name];
|
|
209
241
|
if (plugin.hydrate && pluginState) {
|
|
@@ -247,6 +279,7 @@ class OnchainSDK extends ChainContractsRegister {
|
|
|
247
279
|
addressProviderV3: this.addressProvider.stateHuman(raw)
|
|
248
280
|
},
|
|
249
281
|
tokens: this.tokensMeta.values(),
|
|
282
|
+
kyc: this.#kyc.stateHuman(raw),
|
|
250
283
|
plugins: Object.fromEntries(
|
|
251
284
|
TypedObjectUtils.entries(this.plugins).map(([name, plugin]) => [
|
|
252
285
|
name,
|
|
@@ -266,6 +299,7 @@ class OnchainSDK extends ChainContractsRegister {
|
|
|
266
299
|
timestamp: this.timestamp,
|
|
267
300
|
addressProvider: this.addressProvider.state,
|
|
268
301
|
markets: this.marketRegister.state,
|
|
302
|
+
kyc: this.#kyc.state,
|
|
269
303
|
plugins: Object.fromEntries(
|
|
270
304
|
TypedObjectUtils.entries(this.plugins).map(([name, plugin]) => [
|
|
271
305
|
name,
|
|
@@ -433,9 +467,27 @@ class OnchainSDK extends ChainContractsRegister {
|
|
|
433
467
|
return this.#marketRegister;
|
|
434
468
|
}
|
|
435
469
|
/**
|
|
470
|
+
* KYC register for KYC-wrapped underlying tokens and factories.
|
|
471
|
+
*
|
|
472
|
+
* @throws If the SDK has not been attached or hydrated yet.
|
|
473
|
+
**/
|
|
474
|
+
get kyc() {
|
|
475
|
+
if (this.#kyc === void 0) {
|
|
476
|
+
throw new SdkNotAttachedError();
|
|
477
|
+
}
|
|
478
|
+
return this.#kyc;
|
|
479
|
+
}
|
|
480
|
+
/**
|
|
481
|
+
* @internal
|
|
436
482
|
* Resolves the appropriate router contract for a given credit manager,
|
|
437
483
|
* credit facade, or explicit version range.
|
|
438
|
-
|
|
484
|
+
*
|
|
485
|
+
* @param params - Identifies the context: a credit manager address/state,
|
|
486
|
+
* a credit facade address/state, or a {@link VersionRange}.
|
|
487
|
+
* @returns The matching router contract instance.
|
|
488
|
+
* @throws If the credit facade version is unsupported or no router is
|
|
489
|
+
* registered for the resolved version range.
|
|
490
|
+
**/
|
|
439
491
|
routerFor(params) {
|
|
440
492
|
let routerRange;
|
|
441
493
|
if (Array.isArray(params)) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ierc4626AdapterAbi } from "@gearbox-protocol/integrations-v3";
|
|
1
2
|
import { encodeFunctionData, getContract } from "viem";
|
|
2
3
|
import {
|
|
3
4
|
iBotListV310Abi,
|
|
@@ -8,6 +9,7 @@ import { peripheryCompressorAbi } from "../../abi/compressors/peripheryCompresso
|
|
|
8
9
|
import { rewardsCompressorAbi } from "../../abi/compressors/rewardsCompressor.js";
|
|
9
10
|
import { iWithdrawalCompressorV310Abi } from "../../abi/IWithdrawalCompressorV310.js";
|
|
10
11
|
import { iBaseRewardPoolAbi } from "../../abi/iBaseRewardPool.js";
|
|
12
|
+
import { iKYCFactoryAbi } from "../../abi/kyc/iKYCFactory.js";
|
|
11
13
|
import { SDKConstruct } from "../base/index.js";
|
|
12
14
|
import { chains } from "../chain/chains.js";
|
|
13
15
|
import {
|
|
@@ -25,7 +27,7 @@ import {
|
|
|
25
27
|
getRawPriceUpdates
|
|
26
28
|
} from "../market/index.js";
|
|
27
29
|
import { assetsMap } from "../router/index.js";
|
|
28
|
-
import { AddressMap, AddressSet } from "../utils/index.js";
|
|
30
|
+
import { AddressMap, AddressSet, hexEq } from "../utils/index.js";
|
|
29
31
|
import { simulateWithPriceUpdates } from "../utils/viem/index.js";
|
|
30
32
|
import {
|
|
31
33
|
extractPriceUpdates,
|
|
@@ -71,24 +73,40 @@ class AbstractCreditAccountService extends SDKConstruct {
|
|
|
71
73
|
} catch (_e) {
|
|
72
74
|
return void 0;
|
|
73
75
|
}
|
|
76
|
+
const marketSuite = this.sdk.marketRegister.findByCreditManager(
|
|
77
|
+
raw.creditManager
|
|
78
|
+
);
|
|
79
|
+
const factory = marketSuite.kycFactory;
|
|
80
|
+
let ca;
|
|
81
|
+
let investor;
|
|
74
82
|
if (raw.success) {
|
|
75
|
-
|
|
83
|
+
ca = raw;
|
|
84
|
+
investor = await factory?.getInvestor(raw.creditAccount, false);
|
|
85
|
+
} else {
|
|
86
|
+
const { txs: priceUpdateTxs } = await this.getUpdateForAccount(raw);
|
|
87
|
+
[ca, investor] = await simulateWithPriceUpdates(this.client, {
|
|
88
|
+
priceUpdates: priceUpdateTxs,
|
|
89
|
+
contracts: [
|
|
90
|
+
{
|
|
91
|
+
abi: creditAccountCompressorAbi,
|
|
92
|
+
address: this.#compressor,
|
|
93
|
+
functionName: "getCreditAccountData",
|
|
94
|
+
args: [account]
|
|
95
|
+
},
|
|
96
|
+
...factory ? [
|
|
97
|
+
{
|
|
98
|
+
abi: iKYCFactoryAbi,
|
|
99
|
+
address: factory.address,
|
|
100
|
+
functionName: "getInvestor",
|
|
101
|
+
args: [raw.creditAccount]
|
|
102
|
+
}
|
|
103
|
+
] : []
|
|
104
|
+
],
|
|
105
|
+
blockNumber,
|
|
106
|
+
gas: this.sdk.gasLimit
|
|
107
|
+
});
|
|
76
108
|
}
|
|
77
|
-
|
|
78
|
-
const [cad] = await simulateWithPriceUpdates(this.client, {
|
|
79
|
-
priceUpdates: priceUpdateTxs,
|
|
80
|
-
contracts: [
|
|
81
|
-
{
|
|
82
|
-
abi: creditAccountCompressorAbi,
|
|
83
|
-
address: this.#compressor,
|
|
84
|
-
functionName: "getCreditAccountData",
|
|
85
|
-
args: [account]
|
|
86
|
-
}
|
|
87
|
-
],
|
|
88
|
-
blockNumber,
|
|
89
|
-
gas: this.sdk.gasLimit
|
|
90
|
-
});
|
|
91
|
-
return cad;
|
|
109
|
+
return { ...ca, investor };
|
|
92
110
|
}
|
|
93
111
|
/**
|
|
94
112
|
* {@inheritDoc ICreditAccountsService.getCreditAccounts}
|
|
@@ -144,6 +162,99 @@ class AbstractCreditAccountService extends SDKConstruct {
|
|
|
144
162
|
);
|
|
145
163
|
return allCAs.sort((a, b) => Number(a.healthFactor - b.healthFactor));
|
|
146
164
|
}
|
|
165
|
+
/**
|
|
166
|
+
* {@inheritDoc ICreditAccountsService.getBorrowerCreditAccounts}
|
|
167
|
+
**/
|
|
168
|
+
async getBorrowerCreditAccounts(borrower, options, blockNumber) {
|
|
169
|
+
const {
|
|
170
|
+
creditManager,
|
|
171
|
+
includeZeroDebt = false,
|
|
172
|
+
maxHealthFactor = MAX_UINT256,
|
|
173
|
+
minHealthFactor = 0n,
|
|
174
|
+
ignoreReservePrices = false
|
|
175
|
+
} = options ?? {};
|
|
176
|
+
const { txs: priceUpdateTxs } = await this.sdk.priceFeeds.generatePriceFeedsUpdateTxs(
|
|
177
|
+
ignoreReservePrices ? { main: true } : void 0
|
|
178
|
+
);
|
|
179
|
+
const investorDataList = await this.sdk.kyc.getInvestorData(borrower);
|
|
180
|
+
const kycAccountAddresses = investorDataList.flatMap(
|
|
181
|
+
(d) => d.creditAccounts.map((ca) => ca.creditAccount)
|
|
182
|
+
);
|
|
183
|
+
const cmFilter = creditManager ? {
|
|
184
|
+
configurators: [],
|
|
185
|
+
creditManagers: [creditManager],
|
|
186
|
+
pools: [],
|
|
187
|
+
underlying: ADDRESS_0X0
|
|
188
|
+
} : {
|
|
189
|
+
configurators: this.marketConfigurators,
|
|
190
|
+
creditManagers: [],
|
|
191
|
+
pools: [],
|
|
192
|
+
underlying: ADDRESS_0X0
|
|
193
|
+
};
|
|
194
|
+
const permissiveFilter = {
|
|
195
|
+
owner: borrower,
|
|
196
|
+
includeZeroDebt: true,
|
|
197
|
+
minHealthFactor: 0n,
|
|
198
|
+
maxHealthFactor: MAX_UINT256,
|
|
199
|
+
reverting: false
|
|
200
|
+
};
|
|
201
|
+
const kycContracts = kycAccountAddresses.map(
|
|
202
|
+
(account) => ({
|
|
203
|
+
abi: creditAccountCompressorAbi,
|
|
204
|
+
address: this.#compressor,
|
|
205
|
+
functionName: "getCreditAccountData",
|
|
206
|
+
args: [account]
|
|
207
|
+
})
|
|
208
|
+
);
|
|
209
|
+
const getCreditAccountsContracts = [false, true].map(
|
|
210
|
+
(reverting) => ({
|
|
211
|
+
abi: creditAccountCompressorAbi,
|
|
212
|
+
address: this.#compressor,
|
|
213
|
+
functionName: "getCreditAccounts",
|
|
214
|
+
args: [cmFilter, { ...permissiveFilter, reverting }, 0n]
|
|
215
|
+
})
|
|
216
|
+
);
|
|
217
|
+
const allContracts = [...kycContracts, ...getCreditAccountsContracts];
|
|
218
|
+
const results = await simulateWithPriceUpdates(this.client, {
|
|
219
|
+
priceUpdates: priceUpdateTxs,
|
|
220
|
+
contracts: allContracts,
|
|
221
|
+
blockNumber,
|
|
222
|
+
gas: this.sdk.gasLimit
|
|
223
|
+
});
|
|
224
|
+
const kycResults = results.slice(
|
|
225
|
+
0,
|
|
226
|
+
kycAccountAddresses.length
|
|
227
|
+
);
|
|
228
|
+
const normalResults = results.slice(kycAccountAddresses.length);
|
|
229
|
+
const seen = new AddressSet();
|
|
230
|
+
const allCAs = [];
|
|
231
|
+
for (const ca of kycResults) {
|
|
232
|
+
if (!seen.has(ca.creditAccount)) {
|
|
233
|
+
seen.add(ca.creditAccount);
|
|
234
|
+
allCAs.push({ ...ca, investor: borrower });
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
for (const [accounts] of normalResults) {
|
|
238
|
+
for (const ca of accounts) {
|
|
239
|
+
if (!seen.has(ca.creditAccount)) {
|
|
240
|
+
seen.add(ca.creditAccount);
|
|
241
|
+
allCAs.push({ ...ca, investor: void 0 });
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
const filtered = allCAs.filter((ca) => {
|
|
246
|
+
if (!includeZeroDebt && ca.debt === 0n) return false;
|
|
247
|
+
if (ca.healthFactor < minHealthFactor) return false;
|
|
248
|
+
if (ca.healthFactor > maxHealthFactor) return false;
|
|
249
|
+
if (creditManager && !hexEq(ca.creditManager, creditManager))
|
|
250
|
+
return false;
|
|
251
|
+
return true;
|
|
252
|
+
});
|
|
253
|
+
this.logger?.debug(
|
|
254
|
+
`loaded ${allCAs.length} borrower credit accounts (${kycResults.length} KYC, ${filtered.length} after filter)`
|
|
255
|
+
);
|
|
256
|
+
return filtered.sort((a, b) => Number(a.healthFactor - b.healthFactor));
|
|
257
|
+
}
|
|
147
258
|
/**
|
|
148
259
|
* {@inheritDoc ICreditAccountsService.getRewards}
|
|
149
260
|
**/
|
|
@@ -353,6 +464,13 @@ class AbstractCreditAccountService extends SDKConstruct {
|
|
|
353
464
|
closePath
|
|
354
465
|
}) {
|
|
355
466
|
const cm = this.sdk.marketRegister.findCreditManager(ca.creditManager);
|
|
467
|
+
await this.sdk.tokensMeta.loadTokenData(cm.underlying);
|
|
468
|
+
const underlying = this.sdk.tokensMeta.mustGet(cm.underlying);
|
|
469
|
+
if (this.sdk.tokensMeta.isKYCUnderlying(underlying)) {
|
|
470
|
+
throw new Error(
|
|
471
|
+
"closeCreditAccount is not supported for KYC underlying credit accounts"
|
|
472
|
+
);
|
|
473
|
+
}
|
|
356
474
|
const routerCloseResult = closePath || await this.sdk.routerFor(ca).findBestClosePath({
|
|
357
475
|
creditAccount: ca,
|
|
358
476
|
creditManager: cm.creditManager,
|
|
@@ -458,8 +576,18 @@ class AbstractCreditAccountService extends SDKConstruct {
|
|
|
458
576
|
],
|
|
459
577
|
{}
|
|
460
578
|
) : [];
|
|
579
|
+
const unwrapCalls = collateral && isDecrease ? await this.getKYCUnwrapCalls(
|
|
580
|
+
collateral[0].balance,
|
|
581
|
+
creditAccount.creditManager
|
|
582
|
+
) || [] : [];
|
|
583
|
+
if (addCollateralCalls.length > 0 && unwrapCalls.length === 0 && collateral && collateral?.[0].token !== creditAccount.underlying) {
|
|
584
|
+
throw new Error(
|
|
585
|
+
"Can't use collateral other than underlying for non KYC market"
|
|
586
|
+
);
|
|
587
|
+
}
|
|
461
588
|
const operationCalls = [
|
|
462
589
|
...addCollateralCalls,
|
|
590
|
+
...unwrapCalls,
|
|
463
591
|
this.#prepareChangeDebt(creditAccount.creditFacade, change, isDecrease)
|
|
464
592
|
];
|
|
465
593
|
const calls = await this.prependPriceUpdates(
|
|
@@ -667,6 +795,29 @@ class AbstractCreditAccountService extends SDKConstruct {
|
|
|
667
795
|
const tx = await this.multicallTx(cm, creditAccount.creditAccount, calls);
|
|
668
796
|
return { tx, calls, creditFacade: cm.creditFacade };
|
|
669
797
|
}
|
|
798
|
+
/**
|
|
799
|
+
* {@inheritDoc ICreditAccountsService.getApprovalAddress}
|
|
800
|
+
**/
|
|
801
|
+
async getApprovalAddress(options) {
|
|
802
|
+
const { creditManager } = options;
|
|
803
|
+
const suite = this.sdk.marketRegister.findCreditManager(creditManager);
|
|
804
|
+
const marketSuite = this.sdk.marketRegister.findByPool(suite.pool);
|
|
805
|
+
const factory = marketSuite.kycFactory;
|
|
806
|
+
if (factory) {
|
|
807
|
+
return factory.getApprovalAddress(options);
|
|
808
|
+
}
|
|
809
|
+
return suite.creditManager.address;
|
|
810
|
+
}
|
|
811
|
+
/**
|
|
812
|
+
* {@inheritDoc ICreditAccountsService.getOpenAccountRequirements}
|
|
813
|
+
*/
|
|
814
|
+
async getOpenAccountRequirements(borrower, creditManager, props) {
|
|
815
|
+
const { kycFactory } = this.sdk.marketRegister.findByCreditManager(creditManager);
|
|
816
|
+
if (!kycFactory) {
|
|
817
|
+
return void 0;
|
|
818
|
+
}
|
|
819
|
+
return kycFactory.getOpenAccountRequirements(borrower, props);
|
|
820
|
+
}
|
|
670
821
|
/**
|
|
671
822
|
* {@inheritDoc ICreditAccountsService.openCA}
|
|
672
823
|
**/
|
|
@@ -684,7 +835,8 @@ class AbstractCreditAccountService extends SDKConstruct {
|
|
|
684
835
|
calls: openPathCalls,
|
|
685
836
|
callsAfter,
|
|
686
837
|
minQuota,
|
|
687
|
-
averageQuota
|
|
838
|
+
averageQuota,
|
|
839
|
+
kycOptions
|
|
688
840
|
} = props;
|
|
689
841
|
const cmSuite = this.sdk.marketRegister.findCreditManager(creditManager);
|
|
690
842
|
const cm = cmSuite.creditManager;
|
|
@@ -718,7 +870,13 @@ class AbstractCreditAccountService extends SDKConstruct {
|
|
|
718
870
|
if (reopenCreditAccount) {
|
|
719
871
|
tx = await this.multicallTx(cmSuite, reopenCreditAccount, calls);
|
|
720
872
|
} else {
|
|
721
|
-
tx = await this.openCreditAccountTx(
|
|
873
|
+
tx = await this.openCreditAccountTx(
|
|
874
|
+
cmSuite,
|
|
875
|
+
to,
|
|
876
|
+
calls,
|
|
877
|
+
referralCode,
|
|
878
|
+
kycOptions
|
|
879
|
+
);
|
|
722
880
|
}
|
|
723
881
|
tx.value = ethAmount.toString(10);
|
|
724
882
|
return { calls, tx, creditFacade: cmSuite.creditFacade };
|
|
@@ -801,6 +959,131 @@ class AbstractCreditAccountService extends SDKConstruct {
|
|
|
801
959
|
return resp;
|
|
802
960
|
}
|
|
803
961
|
/**
|
|
962
|
+
* Returns multicall entries to redeem (unwrap) KYC ERC-4626 vault shares into underlying for the given credit manager.
|
|
963
|
+
* Used when withdrawing debt from a KYC market: redeems adapter vault shares so the underlying can be withdrawn.
|
|
964
|
+
* Only applies when the credit manager's underlying is KYC-gated and has an ERC-4626 adapter configured.
|
|
965
|
+
* @param amount - Number of vault shares (adapter tokens) to redeem
|
|
966
|
+
* @param creditManager - Credit manager address
|
|
967
|
+
* @returns Array of MultiCall to pass to credit facade multicall, or undefined if underlying is not KYC or no adapter is configured
|
|
968
|
+
*/
|
|
969
|
+
async getKYCUnwrapCalls(amount, creditManager) {
|
|
970
|
+
const suite = this.sdk.marketRegister.findCreditManager(creditManager);
|
|
971
|
+
const meta = this.sdk.tokensMeta.mustGet(suite.underlying);
|
|
972
|
+
if (!this.sdk.tokensMeta.isKYCUnderlying(meta)) {
|
|
973
|
+
return void 0;
|
|
974
|
+
}
|
|
975
|
+
const adapter = suite.creditManager.adapters.get(meta.addr);
|
|
976
|
+
const adapterAddress = adapter?.address;
|
|
977
|
+
if (!adapterAddress) {
|
|
978
|
+
return void 0;
|
|
979
|
+
}
|
|
980
|
+
const mc = [
|
|
981
|
+
{
|
|
982
|
+
target: adapterAddress,
|
|
983
|
+
callData: encodeFunctionData({
|
|
984
|
+
abi: ierc4626AdapterAbi,
|
|
985
|
+
functionName: "redeem",
|
|
986
|
+
args: [amount, ADDRESS_0X0, ADDRESS_0X0]
|
|
987
|
+
})
|
|
988
|
+
}
|
|
989
|
+
];
|
|
990
|
+
return mc;
|
|
991
|
+
}
|
|
992
|
+
/**
|
|
993
|
+
* Returns multicall entries to deposit (wrap) underlying into KYC ERC-4626 vault shares for the given credit manager.
|
|
994
|
+
* Used when adding debt on a KYC market: deposits underlying into the adapter vault so shares are minted on the account.
|
|
995
|
+
* Only applies when the credit manager's underlying is KYC-gated and has an ERC-4626 adapter configured.
|
|
996
|
+
* @param amount - Amount of underlying assets to deposit into the vault (in underlying decimals)
|
|
997
|
+
* @param creditManager - Credit manager address
|
|
998
|
+
* @returns Array of MultiCall to pass to credit facade multicall, or undefined if underlying is not KYC or no adapter is configured
|
|
999
|
+
*/
|
|
1000
|
+
async getKYCWrapCalls(amount, creditManager) {
|
|
1001
|
+
const suite = this.sdk.marketRegister.findCreditManager(creditManager);
|
|
1002
|
+
const meta = this.sdk.tokensMeta.mustGet(suite.underlying);
|
|
1003
|
+
if (!this.sdk.tokensMeta.isKYCUnderlying(meta)) {
|
|
1004
|
+
return void 0;
|
|
1005
|
+
}
|
|
1006
|
+
const adapter = suite.creditManager.adapters.get(meta.addr);
|
|
1007
|
+
const adapterAddress = adapter?.address;
|
|
1008
|
+
if (!adapterAddress) {
|
|
1009
|
+
return void 0;
|
|
1010
|
+
}
|
|
1011
|
+
const mc = [
|
|
1012
|
+
{
|
|
1013
|
+
target: adapterAddress,
|
|
1014
|
+
callData: encodeFunctionData({
|
|
1015
|
+
abi: ierc4626AdapterAbi,
|
|
1016
|
+
functionName: "deposit",
|
|
1017
|
+
args: [amount, ADDRESS_0X0]
|
|
1018
|
+
})
|
|
1019
|
+
}
|
|
1020
|
+
];
|
|
1021
|
+
return mc;
|
|
1022
|
+
}
|
|
1023
|
+
/**
|
|
1024
|
+
* Returns multicall entries to call redeemDiff on the KYC ERC-4626 adapter for the given credit manager.
|
|
1025
|
+
* Redeems the leftover vault shares (e.g. after repaying debt) so the account does not hold excess KYC vault tokens.
|
|
1026
|
+
* Only applies when the credit manager's underlying is KYC-gated and has an ERC-4626 adapter configured.
|
|
1027
|
+
* @param amount - Leftover vault share amount to redeem (in adapter/vault decimals)
|
|
1028
|
+
* @param creditManager - Credit manager address
|
|
1029
|
+
* @returns Array of MultiCall to pass to credit facade multicall, or undefined if underlying is not KYC or no adapter is configured
|
|
1030
|
+
*/
|
|
1031
|
+
async getRedeemDiffCalls(amount, creditManager) {
|
|
1032
|
+
const suite = this.sdk.marketRegister.findCreditManager(creditManager);
|
|
1033
|
+
const meta = this.sdk.tokensMeta.mustGet(suite.underlying);
|
|
1034
|
+
if (!this.sdk.tokensMeta.isKYCUnderlying(meta)) {
|
|
1035
|
+
return void 0;
|
|
1036
|
+
}
|
|
1037
|
+
const adapter = suite.creditManager.adapters.get(meta.addr);
|
|
1038
|
+
const adapterAddress = adapter?.address;
|
|
1039
|
+
if (!adapterAddress) {
|
|
1040
|
+
return void 0;
|
|
1041
|
+
}
|
|
1042
|
+
const mc = [
|
|
1043
|
+
{
|
|
1044
|
+
target: adapterAddress,
|
|
1045
|
+
callData: encodeFunctionData({
|
|
1046
|
+
abi: ierc4626AdapterAbi,
|
|
1047
|
+
functionName: "redeemDiff",
|
|
1048
|
+
args: [amount]
|
|
1049
|
+
})
|
|
1050
|
+
}
|
|
1051
|
+
];
|
|
1052
|
+
return mc;
|
|
1053
|
+
}
|
|
1054
|
+
/**
|
|
1055
|
+
* Returns multicall entries to call depositDiff on the KYC ERC-4626 adapter for the given credit manager.
|
|
1056
|
+
* Deposits the leftover underlying (e.g. after decreasing debt) into the vault so the account does not hold excess underlying.
|
|
1057
|
+
* Only applies when the credit manager's underlying is KYC-gated and has an ERC-4626 adapter configured.
|
|
1058
|
+
* @param amount - Leftover underlying amount to deposit into the vault (in underlying decimals)
|
|
1059
|
+
* @param creditManager - Credit manager address
|
|
1060
|
+
* @returns Array of MultiCall to pass to credit facade multicall, or undefined if underlying is not KYC or no adapter is configured
|
|
1061
|
+
*/
|
|
1062
|
+
async getDepositDiffCalls(amount, creditManager) {
|
|
1063
|
+
const suite = this.sdk.marketRegister.findCreditManager(creditManager);
|
|
1064
|
+
const meta = this.sdk.tokensMeta.mustGet(suite.underlying);
|
|
1065
|
+
if (!this.sdk.tokensMeta.isKYCUnderlying(meta)) {
|
|
1066
|
+
return void 0;
|
|
1067
|
+
}
|
|
1068
|
+
const adapter = suite.creditManager.adapters.get(meta.addr);
|
|
1069
|
+
const adapterAddress = adapter?.address;
|
|
1070
|
+
if (!adapterAddress) {
|
|
1071
|
+
return void 0;
|
|
1072
|
+
}
|
|
1073
|
+
const mc = [
|
|
1074
|
+
{
|
|
1075
|
+
target: adapterAddress,
|
|
1076
|
+
callData: encodeFunctionData({
|
|
1077
|
+
abi: ierc4626AdapterAbi,
|
|
1078
|
+
functionName: "depositDiff",
|
|
1079
|
+
args: [amount]
|
|
1080
|
+
})
|
|
1081
|
+
}
|
|
1082
|
+
];
|
|
1083
|
+
return mc;
|
|
1084
|
+
}
|
|
1085
|
+
/**
|
|
1086
|
+
* Returns raw txs that are needed to update all price feeds so that all credit accounts (possibly from different markets) compute
|
|
804
1087
|
* {@inheritDoc ICreditAccountsService.getOnDemandPriceUpdates}
|
|
805
1088
|
**/
|
|
806
1089
|
async getOnDemandPriceUpdates(account, ignoreReservePrices) {
|
|
@@ -1055,9 +1338,19 @@ class AbstractCreditAccountService extends SDKConstruct {
|
|
|
1055
1338
|
* @param to
|
|
1056
1339
|
* @param calls
|
|
1057
1340
|
* @param referralCode
|
|
1341
|
+
* @param kycOptions
|
|
1058
1342
|
* @returns
|
|
1059
1343
|
*/
|
|
1060
|
-
async openCreditAccountTx(suite, to, calls, referralCode) {
|
|
1344
|
+
async openCreditAccountTx(suite, to, calls, referralCode, kycOptions) {
|
|
1345
|
+
const marketSuite = this.sdk.marketRegister.findByPool(suite.pool);
|
|
1346
|
+
const factory = marketSuite.kycFactory;
|
|
1347
|
+
if (factory) {
|
|
1348
|
+
return factory.openCreditAccount(
|
|
1349
|
+
suite.creditManager.address,
|
|
1350
|
+
calls,
|
|
1351
|
+
kycOptions
|
|
1352
|
+
);
|
|
1353
|
+
}
|
|
1061
1354
|
return suite.creditFacade.openCreditAccount(to, calls, referralCode ?? 0n);
|
|
1062
1355
|
}
|
|
1063
1356
|
/**
|
|
@@ -1065,9 +1358,17 @@ class AbstractCreditAccountService extends SDKConstruct {
|
|
|
1065
1358
|
* @param suite
|
|
1066
1359
|
* @param creditAccount
|
|
1067
1360
|
* @param calls
|
|
1361
|
+
* @param kycOptions
|
|
1068
1362
|
* @returns
|
|
1069
1363
|
*/
|
|
1070
|
-
async multicallTx(suite, creditAccount, calls) {
|
|
1364
|
+
async multicallTx(suite, creditAccount, calls, kycOptions) {
|
|
1365
|
+
const marketSuite = this.sdk.marketRegister.findByCreditManager(
|
|
1366
|
+
suite.creditManager.address
|
|
1367
|
+
);
|
|
1368
|
+
const factory = marketSuite.kycFactory;
|
|
1369
|
+
if (factory) {
|
|
1370
|
+
return factory.multicall(creditAccount, calls, kycOptions);
|
|
1371
|
+
}
|
|
1071
1372
|
return suite.creditFacade.multicall(creditAccount, calls);
|
|
1072
1373
|
}
|
|
1073
1374
|
/**
|
|
@@ -1076,12 +1377,25 @@ class AbstractCreditAccountService extends SDKConstruct {
|
|
|
1076
1377
|
* @param creditAccount
|
|
1077
1378
|
* @param calls
|
|
1078
1379
|
* @param operation
|
|
1380
|
+
* @param kycOptions
|
|
1079
1381
|
* @returns
|
|
1080
1382
|
*/
|
|
1081
|
-
async closeCreditAccountTx(suite, creditAccount, calls, operation) {
|
|
1383
|
+
async closeCreditAccountTx(suite, creditAccount, calls, operation, kycOptions) {
|
|
1384
|
+
const marketSuite = this.sdk.marketRegister.findByCreditManager(
|
|
1385
|
+
suite.creditManager.address
|
|
1386
|
+
);
|
|
1387
|
+
const factory = marketSuite.kycFactory;
|
|
1082
1388
|
if (operation === "close") {
|
|
1389
|
+
if (factory) {
|
|
1390
|
+
throw new Error(
|
|
1391
|
+
"CloseOptions=close is not supported for KYC underlying credit accounts"
|
|
1392
|
+
);
|
|
1393
|
+
}
|
|
1083
1394
|
return suite.creditFacade.closeCreditAccount(creditAccount, calls);
|
|
1084
1395
|
}
|
|
1396
|
+
if (factory) {
|
|
1397
|
+
return factory.multicall(creditAccount, calls, kycOptions);
|
|
1398
|
+
}
|
|
1085
1399
|
return suite.creditFacade.multicall(creditAccount, calls);
|
|
1086
1400
|
}
|
|
1087
1401
|
}
|
|
@@ -90,19 +90,23 @@ class CreditAccountServiceV310 extends AbstractCreditAccountService {
|
|
|
90
90
|
creditAccount: ca,
|
|
91
91
|
permits,
|
|
92
92
|
to,
|
|
93
|
-
tokensToClaim
|
|
93
|
+
tokensToClaim,
|
|
94
|
+
calls: wrapCalls = []
|
|
94
95
|
}) {
|
|
95
96
|
const cm = this.sdk.marketRegister.findCreditManager(ca.creditManager);
|
|
96
97
|
const addCollateral = collateralAssets.filter((a) => a.balance > 0);
|
|
97
98
|
const router = this.sdk.routerFor(ca);
|
|
99
|
+
const unwrapCalls = await this.getRedeemDiffCalls(1n, ca.creditManager) ?? [];
|
|
98
100
|
const claimPath = await router.findClaimAllRewards({
|
|
99
101
|
tokensToClaim,
|
|
100
102
|
creditAccount: ca
|
|
101
103
|
});
|
|
102
104
|
const operationCalls = [
|
|
103
105
|
...this.prepareAddCollateral(ca.creditFacade, addCollateral, permits),
|
|
106
|
+
...wrapCalls,
|
|
104
107
|
...this.prepareDisableQuotas(ca),
|
|
105
108
|
...this.prepareDecreaseDebt(ca),
|
|
109
|
+
...unwrapCalls,
|
|
106
110
|
...claimPath.calls,
|
|
107
111
|
...assetsToWithdraw.map(
|
|
108
112
|
(t) => this.prepareWithdrawToken(ca.creditFacade, t.token, MAX_UINT256, to)
|
|
@@ -134,10 +138,12 @@ class CreditAccountServiceV310 extends AbstractCreditAccountService {
|
|
|
134
138
|
tokensToClaim,
|
|
135
139
|
creditAccount: ca
|
|
136
140
|
});
|
|
141
|
+
const wrapCalls = await this.getDepositDiffCalls(1n, ca.creditManager) ?? [];
|
|
137
142
|
const addCollateral = collateralAssets.filter((a) => a.balance > 0);
|
|
138
143
|
const operationCalls = [
|
|
139
144
|
...this.prepareAddCollateral(ca.creditFacade, addCollateral, permits),
|
|
140
145
|
...claimPath.calls,
|
|
146
|
+
...wrapCalls,
|
|
141
147
|
...assetsToWithdraw.map(
|
|
142
148
|
(t) => this.prepareWithdrawToken(ca.creditFacade, t.token, MAX_UINT256, to)
|
|
143
149
|
)
|