@gearbox-protocol/sdk 13.6.0 → 13.7.0-kyc.2
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 +70 -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/history/errors.js +2 -0
- package/dist/cjs/sdk/GearboxSDK.js +51 -4
- package/dist/cjs/sdk/accounts/AbstractCreditAccountsService.js +324 -16
- package/dist/cjs/sdk/accounts/CreditAccountsServiceV310.js +7 -1
- package/dist/cjs/sdk/base/TokensMeta.js +32 -43
- package/dist/cjs/sdk/base/token-types.js +9 -0
- package/dist/cjs/sdk/chain/chains.js +2 -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 +244 -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/market/kyc/types.js +34 -0
- 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 +46 -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/history/errors.js +2 -0
- package/dist/esm/sdk/GearboxSDK.js +55 -5
- package/dist/esm/sdk/accounts/AbstractCreditAccountsService.js +328 -17
- package/dist/esm/sdk/accounts/CreditAccountsServiceV310.js +7 -1
- package/dist/esm/sdk/base/TokensMeta.js +32 -45
- package/dist/esm/sdk/base/token-types.js +6 -0
- package/dist/esm/sdk/chain/chains.js +2 -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 +220 -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 +71 -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/GearboxSDK.d.ts +7 -0
- package/dist/types/sdk/accounts/AbstractCreditAccountsService.d.ts +52 -2
- package/dist/types/sdk/accounts/CreditAccountsServiceV310.d.ts +1 -1
- package/dist/types/sdk/accounts/types.d.ts +93 -13
- 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 +428 -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 +127 -0
- package/dist/types/sdk/market/kyc/types.d.ts +170 -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 +8 -7
|
@@ -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 {
|
|
@@ -24,8 +26,12 @@ import {
|
|
|
24
26
|
import {
|
|
25
27
|
getRawPriceUpdates
|
|
26
28
|
} from "../market/index.js";
|
|
29
|
+
import {
|
|
30
|
+
isKYCFactory,
|
|
31
|
+
KYC_FACTORY_SECURITIZE
|
|
32
|
+
} from "../market/kyc/index.js";
|
|
27
33
|
import { assetsMap } from "../router/index.js";
|
|
28
|
-
import { AddressMap, AddressSet } from "../utils/index.js";
|
|
34
|
+
import { AddressMap, AddressSet, hexEq } from "../utils/index.js";
|
|
29
35
|
import { simulateWithPriceUpdates } from "../utils/viem/index.js";
|
|
30
36
|
import {
|
|
31
37
|
extractPriceUpdates,
|
|
@@ -71,24 +77,40 @@ class AbstractCreditAccountService extends SDKConstruct {
|
|
|
71
77
|
} catch (_e) {
|
|
72
78
|
return void 0;
|
|
73
79
|
}
|
|
80
|
+
const marketSuite = this.sdk.marketRegister.findByCreditManager(
|
|
81
|
+
raw.creditManager
|
|
82
|
+
);
|
|
83
|
+
const factory = marketSuite.kycFactory;
|
|
84
|
+
let ca;
|
|
85
|
+
let investor;
|
|
74
86
|
if (raw.success) {
|
|
75
|
-
|
|
87
|
+
ca = raw;
|
|
88
|
+
investor = await factory?.getInvestor(raw.creditAccount, false);
|
|
89
|
+
} else {
|
|
90
|
+
const { txs: priceUpdateTxs } = await this.getUpdateForAccount(raw);
|
|
91
|
+
[ca, investor] = await simulateWithPriceUpdates(this.client, {
|
|
92
|
+
priceUpdates: priceUpdateTxs,
|
|
93
|
+
contracts: [
|
|
94
|
+
{
|
|
95
|
+
abi: creditAccountCompressorAbi,
|
|
96
|
+
address: this.#compressor,
|
|
97
|
+
functionName: "getCreditAccountData",
|
|
98
|
+
args: [account]
|
|
99
|
+
},
|
|
100
|
+
...factory ? [
|
|
101
|
+
{
|
|
102
|
+
abi: iKYCFactoryAbi,
|
|
103
|
+
address: factory.address,
|
|
104
|
+
functionName: "getInvestor",
|
|
105
|
+
args: [raw.creditAccount]
|
|
106
|
+
}
|
|
107
|
+
] : []
|
|
108
|
+
],
|
|
109
|
+
blockNumber,
|
|
110
|
+
gas: this.sdk.gasLimit
|
|
111
|
+
});
|
|
76
112
|
}
|
|
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;
|
|
113
|
+
return { ...ca, investor };
|
|
92
114
|
}
|
|
93
115
|
/**
|
|
94
116
|
* {@inheritDoc ICreditAccountsService.getCreditAccounts}
|
|
@@ -144,6 +166,99 @@ class AbstractCreditAccountService extends SDKConstruct {
|
|
|
144
166
|
);
|
|
145
167
|
return allCAs.sort((a, b) => Number(a.healthFactor - b.healthFactor));
|
|
146
168
|
}
|
|
169
|
+
/**
|
|
170
|
+
* {@inheritDoc ICreditAccountsService.getBorrowerCreditAccounts}
|
|
171
|
+
**/
|
|
172
|
+
async getBorrowerCreditAccounts(borrower, options, blockNumber) {
|
|
173
|
+
const {
|
|
174
|
+
creditManager,
|
|
175
|
+
includeZeroDebt = false,
|
|
176
|
+
maxHealthFactor = MAX_UINT256,
|
|
177
|
+
minHealthFactor = 0n,
|
|
178
|
+
ignoreReservePrices = false
|
|
179
|
+
} = options ?? {};
|
|
180
|
+
const { txs: priceUpdateTxs } = await this.sdk.priceFeeds.generatePriceFeedsUpdateTxs(
|
|
181
|
+
ignoreReservePrices ? { main: true } : void 0
|
|
182
|
+
);
|
|
183
|
+
const investorDataList = await this.sdk.kyc.getInvestorData(borrower);
|
|
184
|
+
const kycAccountAddresses = investorDataList.flatMap(
|
|
185
|
+
(d) => d.creditAccounts.map((ca) => ca.creditAccount)
|
|
186
|
+
);
|
|
187
|
+
const cmFilter = creditManager ? {
|
|
188
|
+
configurators: [],
|
|
189
|
+
creditManagers: [creditManager],
|
|
190
|
+
pools: [],
|
|
191
|
+
underlying: ADDRESS_0X0
|
|
192
|
+
} : {
|
|
193
|
+
configurators: this.marketConfigurators,
|
|
194
|
+
creditManagers: [],
|
|
195
|
+
pools: [],
|
|
196
|
+
underlying: ADDRESS_0X0
|
|
197
|
+
};
|
|
198
|
+
const permissiveFilter = {
|
|
199
|
+
owner: borrower,
|
|
200
|
+
includeZeroDebt: true,
|
|
201
|
+
minHealthFactor: 0n,
|
|
202
|
+
maxHealthFactor: MAX_UINT256,
|
|
203
|
+
reverting: false
|
|
204
|
+
};
|
|
205
|
+
const kycContracts = kycAccountAddresses.map(
|
|
206
|
+
(account) => ({
|
|
207
|
+
abi: creditAccountCompressorAbi,
|
|
208
|
+
address: this.#compressor,
|
|
209
|
+
functionName: "getCreditAccountData",
|
|
210
|
+
args: [account]
|
|
211
|
+
})
|
|
212
|
+
);
|
|
213
|
+
const getCreditAccountsContracts = [false, true].map(
|
|
214
|
+
(reverting) => ({
|
|
215
|
+
abi: creditAccountCompressorAbi,
|
|
216
|
+
address: this.#compressor,
|
|
217
|
+
functionName: "getCreditAccounts",
|
|
218
|
+
args: [cmFilter, { ...permissiveFilter, reverting }, 0n]
|
|
219
|
+
})
|
|
220
|
+
);
|
|
221
|
+
const allContracts = [...kycContracts, ...getCreditAccountsContracts];
|
|
222
|
+
const results = await simulateWithPriceUpdates(this.client, {
|
|
223
|
+
priceUpdates: priceUpdateTxs,
|
|
224
|
+
contracts: allContracts,
|
|
225
|
+
blockNumber,
|
|
226
|
+
gas: this.sdk.gasLimit
|
|
227
|
+
});
|
|
228
|
+
const kycResults = results.slice(
|
|
229
|
+
0,
|
|
230
|
+
kycAccountAddresses.length
|
|
231
|
+
);
|
|
232
|
+
const normalResults = results.slice(kycAccountAddresses.length);
|
|
233
|
+
const seen = new AddressSet();
|
|
234
|
+
const allCAs = [];
|
|
235
|
+
for (const ca of kycResults) {
|
|
236
|
+
if (!seen.has(ca.creditAccount)) {
|
|
237
|
+
seen.add(ca.creditAccount);
|
|
238
|
+
allCAs.push({ ...ca, investor: borrower });
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
for (const [accounts] of normalResults) {
|
|
242
|
+
for (const ca of accounts) {
|
|
243
|
+
if (!seen.has(ca.creditAccount)) {
|
|
244
|
+
seen.add(ca.creditAccount);
|
|
245
|
+
allCAs.push({ ...ca, investor: void 0 });
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
const filtered = allCAs.filter((ca) => {
|
|
250
|
+
if (!includeZeroDebt && ca.debt === 0n) return false;
|
|
251
|
+
if (ca.healthFactor < minHealthFactor) return false;
|
|
252
|
+
if (ca.healthFactor > maxHealthFactor) return false;
|
|
253
|
+
if (creditManager && !hexEq(ca.creditManager, creditManager))
|
|
254
|
+
return false;
|
|
255
|
+
return true;
|
|
256
|
+
});
|
|
257
|
+
this.logger?.debug(
|
|
258
|
+
`loaded ${allCAs.length} borrower credit accounts (${kycResults.length} KYC, ${filtered.length} after filter)`
|
|
259
|
+
);
|
|
260
|
+
return filtered.sort((a, b) => Number(a.healthFactor - b.healthFactor));
|
|
261
|
+
}
|
|
147
262
|
/**
|
|
148
263
|
* {@inheritDoc ICreditAccountsService.getRewards}
|
|
149
264
|
**/
|
|
@@ -353,6 +468,13 @@ class AbstractCreditAccountService extends SDKConstruct {
|
|
|
353
468
|
closePath
|
|
354
469
|
}) {
|
|
355
470
|
const cm = this.sdk.marketRegister.findCreditManager(ca.creditManager);
|
|
471
|
+
await this.sdk.tokensMeta.loadTokenData(cm.underlying);
|
|
472
|
+
const underlying = this.sdk.tokensMeta.mustGet(cm.underlying);
|
|
473
|
+
if (this.sdk.tokensMeta.isKYCUnderlying(underlying)) {
|
|
474
|
+
throw new Error(
|
|
475
|
+
"closeCreditAccount is not supported for KYC underlying credit accounts"
|
|
476
|
+
);
|
|
477
|
+
}
|
|
356
478
|
const routerCloseResult = closePath || await this.sdk.routerFor(ca).findBestClosePath({
|
|
357
479
|
creditAccount: ca,
|
|
358
480
|
creditManager: cm.creditManager,
|
|
@@ -458,8 +580,18 @@ class AbstractCreditAccountService extends SDKConstruct {
|
|
|
458
580
|
],
|
|
459
581
|
{}
|
|
460
582
|
) : [];
|
|
583
|
+
const unwrapCalls = collateral && isDecrease ? await this.getKYCUnwrapCalls(
|
|
584
|
+
collateral[0].balance,
|
|
585
|
+
creditAccount.creditManager
|
|
586
|
+
) || [] : [];
|
|
587
|
+
if (addCollateralCalls.length > 0 && unwrapCalls.length === 0 && collateral && collateral?.[0].token !== creditAccount.underlying) {
|
|
588
|
+
throw new Error(
|
|
589
|
+
"Can't use collateral other than underlying for non KYC market"
|
|
590
|
+
);
|
|
591
|
+
}
|
|
461
592
|
const operationCalls = [
|
|
462
593
|
...addCollateralCalls,
|
|
594
|
+
...unwrapCalls,
|
|
463
595
|
this.#prepareChangeDebt(creditAccount.creditFacade, change, isDecrease)
|
|
464
596
|
];
|
|
465
597
|
const calls = await this.prependPriceUpdates(
|
|
@@ -667,6 +799,30 @@ class AbstractCreditAccountService extends SDKConstruct {
|
|
|
667
799
|
const tx = await this.multicallTx(cm, creditAccount.creditAccount, calls);
|
|
668
800
|
return { tx, calls, creditFacade: cm.creditFacade };
|
|
669
801
|
}
|
|
802
|
+
/**
|
|
803
|
+
* {@inheritDoc ICreditAccountsService.getApprovalAddress}
|
|
804
|
+
**/
|
|
805
|
+
async getApprovalAddress(options) {
|
|
806
|
+
const { creditManager } = options;
|
|
807
|
+
const suite = this.sdk.marketRegister.findCreditManager(creditManager);
|
|
808
|
+
const marketSuite = this.sdk.marketRegister.findByPool(suite.pool);
|
|
809
|
+
const factory = marketSuite.kycFactory;
|
|
810
|
+
if (factory) {
|
|
811
|
+
return factory.getApprovalAddress(options);
|
|
812
|
+
}
|
|
813
|
+
return suite.creditManager.address;
|
|
814
|
+
}
|
|
815
|
+
/**
|
|
816
|
+
* {@inheritDoc ICreditAccountsService.getOpenAccountRequirements}
|
|
817
|
+
*/
|
|
818
|
+
async getOpenAccountRequirements(borrower, props) {
|
|
819
|
+
const { creditManager } = props;
|
|
820
|
+
const { kycFactory } = this.sdk.marketRegister.findByCreditManager(creditManager);
|
|
821
|
+
if (!kycFactory) {
|
|
822
|
+
return void 0;
|
|
823
|
+
}
|
|
824
|
+
return kycFactory.getOpenAccountRequirements(borrower);
|
|
825
|
+
}
|
|
670
826
|
/**
|
|
671
827
|
* {@inheritDoc ICreditAccountsService.openCA}
|
|
672
828
|
**/
|
|
@@ -801,6 +957,131 @@ class AbstractCreditAccountService extends SDKConstruct {
|
|
|
801
957
|
return resp;
|
|
802
958
|
}
|
|
803
959
|
/**
|
|
960
|
+
* Returns multicall entries to redeem (unwrap) KYC ERC-4626 vault shares into underlying for the given credit manager.
|
|
961
|
+
* Used when withdrawing debt from a KYC market: redeems adapter vault shares so the underlying can be withdrawn.
|
|
962
|
+
* Only applies when the credit manager's underlying is KYC-gated and has an ERC-4626 adapter configured.
|
|
963
|
+
* @param amount - Number of vault shares (adapter tokens) to redeem
|
|
964
|
+
* @param creditManager - Credit manager address
|
|
965
|
+
* @returns Array of MultiCall to pass to credit facade multicall, or undefined if underlying is not KYC or no adapter is configured
|
|
966
|
+
*/
|
|
967
|
+
async getKYCUnwrapCalls(amount, creditManager) {
|
|
968
|
+
const suite = this.sdk.marketRegister.findCreditManager(creditManager);
|
|
969
|
+
const meta = this.sdk.tokensMeta.mustGet(suite.underlying);
|
|
970
|
+
if (!this.sdk.tokensMeta.isKYCUnderlying(meta)) {
|
|
971
|
+
return void 0;
|
|
972
|
+
}
|
|
973
|
+
const adapter = suite.creditManager.adapters.get(meta.addr);
|
|
974
|
+
const adapterAddress = adapter?.address;
|
|
975
|
+
if (!adapterAddress) {
|
|
976
|
+
return void 0;
|
|
977
|
+
}
|
|
978
|
+
const mc = [
|
|
979
|
+
{
|
|
980
|
+
target: adapterAddress,
|
|
981
|
+
callData: encodeFunctionData({
|
|
982
|
+
abi: ierc4626AdapterAbi,
|
|
983
|
+
functionName: "redeem",
|
|
984
|
+
args: [amount, ADDRESS_0X0, ADDRESS_0X0]
|
|
985
|
+
})
|
|
986
|
+
}
|
|
987
|
+
];
|
|
988
|
+
return mc;
|
|
989
|
+
}
|
|
990
|
+
/**
|
|
991
|
+
* Returns multicall entries to deposit (wrap) underlying into KYC ERC-4626 vault shares for the given credit manager.
|
|
992
|
+
* Used when adding debt on a KYC market: deposits underlying into the adapter vault so shares are minted on the account.
|
|
993
|
+
* Only applies when the credit manager's underlying is KYC-gated and has an ERC-4626 adapter configured.
|
|
994
|
+
* @param amount - Amount of underlying assets to deposit into the vault (in underlying decimals)
|
|
995
|
+
* @param creditManager - Credit manager address
|
|
996
|
+
* @returns Array of MultiCall to pass to credit facade multicall, or undefined if underlying is not KYC or no adapter is configured
|
|
997
|
+
*/
|
|
998
|
+
async getKYCWrapCalls(amount, creditManager) {
|
|
999
|
+
const suite = this.sdk.marketRegister.findCreditManager(creditManager);
|
|
1000
|
+
const meta = this.sdk.tokensMeta.mustGet(suite.underlying);
|
|
1001
|
+
if (!this.sdk.tokensMeta.isKYCUnderlying(meta)) {
|
|
1002
|
+
return void 0;
|
|
1003
|
+
}
|
|
1004
|
+
const adapter = suite.creditManager.adapters.get(meta.addr);
|
|
1005
|
+
const adapterAddress = adapter?.address;
|
|
1006
|
+
if (!adapterAddress) {
|
|
1007
|
+
return void 0;
|
|
1008
|
+
}
|
|
1009
|
+
const mc = [
|
|
1010
|
+
{
|
|
1011
|
+
target: adapterAddress,
|
|
1012
|
+
callData: encodeFunctionData({
|
|
1013
|
+
abi: ierc4626AdapterAbi,
|
|
1014
|
+
functionName: "deposit",
|
|
1015
|
+
args: [amount, ADDRESS_0X0]
|
|
1016
|
+
})
|
|
1017
|
+
}
|
|
1018
|
+
];
|
|
1019
|
+
return mc;
|
|
1020
|
+
}
|
|
1021
|
+
/**
|
|
1022
|
+
* Returns multicall entries to call redeemDiff on the KYC ERC-4626 adapter for the given credit manager.
|
|
1023
|
+
* Redeems the leftover vault shares (e.g. after repaying debt) so the account does not hold excess KYC vault tokens.
|
|
1024
|
+
* Only applies when the credit manager's underlying is KYC-gated and has an ERC-4626 adapter configured.
|
|
1025
|
+
* @param amount - Leftover vault share amount to redeem (in adapter/vault decimals)
|
|
1026
|
+
* @param creditManager - Credit manager address
|
|
1027
|
+
* @returns Array of MultiCall to pass to credit facade multicall, or undefined if underlying is not KYC or no adapter is configured
|
|
1028
|
+
*/
|
|
1029
|
+
async getRedeemDiffCalls(amount, creditManager) {
|
|
1030
|
+
const suite = this.sdk.marketRegister.findCreditManager(creditManager);
|
|
1031
|
+
const meta = this.sdk.tokensMeta.mustGet(suite.underlying);
|
|
1032
|
+
if (!this.sdk.tokensMeta.isKYCUnderlying(meta)) {
|
|
1033
|
+
return void 0;
|
|
1034
|
+
}
|
|
1035
|
+
const adapter = suite.creditManager.adapters.get(meta.addr);
|
|
1036
|
+
const adapterAddress = adapter?.address;
|
|
1037
|
+
if (!adapterAddress) {
|
|
1038
|
+
return void 0;
|
|
1039
|
+
}
|
|
1040
|
+
const mc = [
|
|
1041
|
+
{
|
|
1042
|
+
target: adapterAddress,
|
|
1043
|
+
callData: encodeFunctionData({
|
|
1044
|
+
abi: ierc4626AdapterAbi,
|
|
1045
|
+
functionName: "redeemDiff",
|
|
1046
|
+
args: [amount]
|
|
1047
|
+
})
|
|
1048
|
+
}
|
|
1049
|
+
];
|
|
1050
|
+
return mc;
|
|
1051
|
+
}
|
|
1052
|
+
/**
|
|
1053
|
+
* Returns multicall entries to call depositDiff on the KYC ERC-4626 adapter for the given credit manager.
|
|
1054
|
+
* Deposits the leftover underlying (e.g. after decreasing debt) into the vault so the account does not hold excess underlying.
|
|
1055
|
+
* Only applies when the credit manager's underlying is KYC-gated and has an ERC-4626 adapter configured.
|
|
1056
|
+
* @param amount - Leftover underlying amount to deposit into the vault (in underlying decimals)
|
|
1057
|
+
* @param creditManager - Credit manager address
|
|
1058
|
+
* @returns Array of MultiCall to pass to credit facade multicall, or undefined if underlying is not KYC or no adapter is configured
|
|
1059
|
+
*/
|
|
1060
|
+
async getDepositDiffCalls(amount, creditManager) {
|
|
1061
|
+
const suite = this.sdk.marketRegister.findCreditManager(creditManager);
|
|
1062
|
+
const meta = this.sdk.tokensMeta.mustGet(suite.underlying);
|
|
1063
|
+
if (!this.sdk.tokensMeta.isKYCUnderlying(meta)) {
|
|
1064
|
+
return void 0;
|
|
1065
|
+
}
|
|
1066
|
+
const adapter = suite.creditManager.adapters.get(meta.addr);
|
|
1067
|
+
const adapterAddress = adapter?.address;
|
|
1068
|
+
if (!adapterAddress) {
|
|
1069
|
+
return void 0;
|
|
1070
|
+
}
|
|
1071
|
+
const mc = [
|
|
1072
|
+
{
|
|
1073
|
+
target: adapterAddress,
|
|
1074
|
+
callData: encodeFunctionData({
|
|
1075
|
+
abi: ierc4626AdapterAbi,
|
|
1076
|
+
functionName: "depositDiff",
|
|
1077
|
+
args: [amount]
|
|
1078
|
+
})
|
|
1079
|
+
}
|
|
1080
|
+
];
|
|
1081
|
+
return mc;
|
|
1082
|
+
}
|
|
1083
|
+
/**
|
|
1084
|
+
* Returns raw txs that are needed to update all price feeds so that all credit accounts (possibly from different markets) compute
|
|
804
1085
|
* {@inheritDoc ICreditAccountsService.getOnDemandPriceUpdates}
|
|
805
1086
|
**/
|
|
806
1087
|
async getOnDemandPriceUpdates(account, ignoreReservePrices) {
|
|
@@ -1058,6 +1339,17 @@ class AbstractCreditAccountService extends SDKConstruct {
|
|
|
1058
1339
|
* @returns
|
|
1059
1340
|
*/
|
|
1060
1341
|
async openCreditAccountTx(suite, to, calls, referralCode) {
|
|
1342
|
+
const marketSuite = this.sdk.marketRegister.findByPool(suite.pool);
|
|
1343
|
+
const factory = marketSuite.kycFactory;
|
|
1344
|
+
if (factory && isKYCFactory(factory, KYC_FACTORY_SECURITIZE)) {
|
|
1345
|
+
const tokensToRegister = factory.dsTokens.map(
|
|
1346
|
+
(t) => t.address
|
|
1347
|
+
);
|
|
1348
|
+
return factory.openCreditAccount(suite.creditManager.address, calls, {
|
|
1349
|
+
tokensToRegister,
|
|
1350
|
+
signaturesToCache: []
|
|
1351
|
+
});
|
|
1352
|
+
}
|
|
1061
1353
|
return suite.creditFacade.openCreditAccount(to, calls, referralCode ?? 0n);
|
|
1062
1354
|
}
|
|
1063
1355
|
/**
|
|
@@ -1068,6 +1360,13 @@ class AbstractCreditAccountService extends SDKConstruct {
|
|
|
1068
1360
|
* @returns
|
|
1069
1361
|
*/
|
|
1070
1362
|
async multicallTx(suite, creditAccount, calls) {
|
|
1363
|
+
const marketSuite = this.sdk.marketRegister.findByCreditManager(
|
|
1364
|
+
suite.creditManager.address
|
|
1365
|
+
);
|
|
1366
|
+
const factory = marketSuite.kycFactory;
|
|
1367
|
+
if (factory) {
|
|
1368
|
+
return factory.multicall(creditAccount, calls);
|
|
1369
|
+
}
|
|
1071
1370
|
return suite.creditFacade.multicall(creditAccount, calls);
|
|
1072
1371
|
}
|
|
1073
1372
|
/**
|
|
@@ -1079,9 +1378,21 @@ class AbstractCreditAccountService extends SDKConstruct {
|
|
|
1079
1378
|
* @returns
|
|
1080
1379
|
*/
|
|
1081
1380
|
async closeCreditAccountTx(suite, creditAccount, calls, operation) {
|
|
1381
|
+
const marketSuite = this.sdk.marketRegister.findByCreditManager(
|
|
1382
|
+
suite.creditManager.address
|
|
1383
|
+
);
|
|
1384
|
+
const factory = marketSuite.kycFactory;
|
|
1082
1385
|
if (operation === "close") {
|
|
1386
|
+
if (factory) {
|
|
1387
|
+
throw new Error(
|
|
1388
|
+
"CloseOptions=close is not supported for KYC underlying credit accounts"
|
|
1389
|
+
);
|
|
1390
|
+
}
|
|
1083
1391
|
return suite.creditFacade.closeCreditAccount(creditAccount, calls);
|
|
1084
1392
|
}
|
|
1393
|
+
if (factory) {
|
|
1394
|
+
return factory.multicall(creditAccount, calls);
|
|
1395
|
+
}
|
|
1085
1396
|
return suite.creditFacade.multicall(creditAccount, calls);
|
|
1086
1397
|
}
|
|
1087
1398
|
}
|
|
@@ -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
|
)
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
erc20Abi
|
|
3
|
-
} from "viem";
|
|
4
1
|
import { iStateSerializerAbi } from "../../abi/iStateSerializer.js";
|
|
5
2
|
import { iVersionAbi } from "../../abi/iVersion.js";
|
|
6
3
|
import {
|
|
@@ -65,6 +62,14 @@ class TokensMeta extends AddressMap {
|
|
|
65
62
|
}
|
|
66
63
|
return !!t.contractType?.startsWith("PHANTOM_TOKEN::");
|
|
67
64
|
}
|
|
65
|
+
/**
|
|
66
|
+
* Returns true if the token is a KYC underlying token, throws if the token data is not loaded
|
|
67
|
+
* @param t
|
|
68
|
+
* @returns
|
|
69
|
+
*/
|
|
70
|
+
isKYCUnderlying(t) {
|
|
71
|
+
return !!t.contractType?.startsWith("KYC_UNDERLYING::");
|
|
72
|
+
}
|
|
68
73
|
/**
|
|
69
74
|
* Returns a map of all phantom tokens
|
|
70
75
|
* Throws if token data is not loaded
|
|
@@ -78,6 +83,19 @@ class TokensMeta extends AddressMap {
|
|
|
78
83
|
}
|
|
79
84
|
return result;
|
|
80
85
|
}
|
|
86
|
+
/**
|
|
87
|
+
* Returns a map of all KYC underlying tokens
|
|
88
|
+
* Throws if token data is not loaded
|
|
89
|
+
*/
|
|
90
|
+
get kycUnderlyings() {
|
|
91
|
+
const result = new AddressMap();
|
|
92
|
+
for (const [token, meta] of this.entries()) {
|
|
93
|
+
if (this.isKYCUnderlying(meta)) {
|
|
94
|
+
result.upsert(token, meta);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return result;
|
|
98
|
+
}
|
|
81
99
|
formatBN(arg0, arg1, arg2) {
|
|
82
100
|
const token = typeof arg0 === "object" ? arg0.token : arg0;
|
|
83
101
|
const amount = typeof arg0 === "object" ? arg0.balance : arg1;
|
|
@@ -108,7 +126,7 @@ class TokensMeta extends AddressMap {
|
|
|
108
126
|
}
|
|
109
127
|
/**
|
|
110
128
|
* Loads token information about phantom tokens
|
|
111
|
-
*
|
|
129
|
+
* In future other custom tokens types that do not have compressors might be handled here
|
|
112
130
|
*
|
|
113
131
|
* @param tokens - tokens to load data for, defaults to all tokens
|
|
114
132
|
*/
|
|
@@ -137,10 +155,19 @@ class TokensMeta extends AddressMap {
|
|
|
137
155
|
batchSize: 0
|
|
138
156
|
});
|
|
139
157
|
this.#logger?.debug(`loaded ${resp.length} contract types`);
|
|
158
|
+
const kycFactories = new AddressSet();
|
|
140
159
|
for (let i = 0; i < tokensToLoad.length; i++) {
|
|
141
|
-
this.#overrideTokenMeta(
|
|
160
|
+
const meta = this.#overrideTokenMeta(
|
|
161
|
+
tokensToLoad[i],
|
|
162
|
+
resp[2 * i],
|
|
163
|
+
resp[2 * i + 1]
|
|
164
|
+
);
|
|
142
165
|
this.#tokenDataLoaded.add(tokensToLoad[i]);
|
|
166
|
+
if (this.isKYCUnderlying(meta)) {
|
|
167
|
+
kycFactories.add(meta.kycFactory);
|
|
168
|
+
}
|
|
143
169
|
}
|
|
170
|
+
this.#logger?.debug(`found ${kycFactories.size} KYC factories`);
|
|
144
171
|
}
|
|
145
172
|
#overrideTokenMeta(token, contractTypeResp, _serializeResp) {
|
|
146
173
|
const meta = this.mustGet(token);
|
|
@@ -154,46 +181,6 @@ class TokensMeta extends AddressMap {
|
|
|
154
181
|
}
|
|
155
182
|
return this.mustGet(token);
|
|
156
183
|
}
|
|
157
|
-
async #loadWithoutCompressor(tokens_) {
|
|
158
|
-
if (tokens_.size === 0) {
|
|
159
|
-
return;
|
|
160
|
-
}
|
|
161
|
-
const tokens = Array.from(tokens_);
|
|
162
|
-
const resp = await this.#client.multicall({
|
|
163
|
-
contracts: tokens.flatMap(
|
|
164
|
-
(t) => [
|
|
165
|
-
{
|
|
166
|
-
address: t,
|
|
167
|
-
abi: erc20Abi,
|
|
168
|
-
functionName: "symbol"
|
|
169
|
-
},
|
|
170
|
-
{
|
|
171
|
-
address: t,
|
|
172
|
-
abi: erc20Abi,
|
|
173
|
-
functionName: "name"
|
|
174
|
-
},
|
|
175
|
-
{
|
|
176
|
-
address: t,
|
|
177
|
-
abi: erc20Abi,
|
|
178
|
-
functionName: "decimals"
|
|
179
|
-
}
|
|
180
|
-
]
|
|
181
|
-
),
|
|
182
|
-
allowFailure: false,
|
|
183
|
-
batchSize: 0
|
|
184
|
-
});
|
|
185
|
-
this.#logger?.debug(
|
|
186
|
-
`loaded ${resp.length} basic metadata without compressor`
|
|
187
|
-
);
|
|
188
|
-
for (let i = 0; i < tokens.length; i++) {
|
|
189
|
-
this.upsert(tokens[i], {
|
|
190
|
-
addr: tokens[i],
|
|
191
|
-
symbol: resp[3 * i],
|
|
192
|
-
name: resp[3 * i + 1],
|
|
193
|
-
decimals: resp[3 * i + 2]
|
|
194
|
-
});
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
184
|
}
|
|
198
185
|
export {
|
|
199
186
|
TokensMeta
|
|
@@ -7,6 +7,12 @@ const PHANTOM_TOKEN_CONTRACT_TYPES = [
|
|
|
7
7
|
"PHANTOM_TOKEN::STAKING_REWARDS",
|
|
8
8
|
"PHANTOM_TOKEN::UPSHIFT_WITHDRAW"
|
|
9
9
|
];
|
|
10
|
+
const KYC_UNDERLYING_DEFAULT = "KYC_UNDERLYING::DEFAULT";
|
|
11
|
+
const KYC_UNDERLYING_ON_DEMAND = "KYC_UNDERLYING::ON_DEMAND";
|
|
12
|
+
const KYC_ON_DEMAND_LP_MONOPOLIZED = "ON_DEMAND_LP::MONOPOLIZED";
|
|
10
13
|
export {
|
|
14
|
+
KYC_ON_DEMAND_LP_MONOPOLIZED,
|
|
15
|
+
KYC_UNDERLYING_DEFAULT,
|
|
16
|
+
KYC_UNDERLYING_ON_DEMAND,
|
|
11
17
|
PHANTOM_TOKEN_CONTRACT_TYPES
|
|
12
18
|
};
|
|
@@ -65,7 +65,8 @@ const chains = {
|
|
|
65
65
|
"0x601067eba24bb5b558a184fc082525637e96a42d": "Gami Labs"
|
|
66
66
|
},
|
|
67
67
|
testMarketConfigurators: {
|
|
68
|
-
"0x99df7330bf42d596af2e9d9836d4fc2077c574aa": "M11 Credit"
|
|
68
|
+
"0x99df7330bf42d596af2e9d9836d4fc2077c574aa": "M11 Credit",
|
|
69
|
+
"0x610627d8d01a413bdd9b0a0b60070da7dd1e54ad": "Securitize"
|
|
69
70
|
},
|
|
70
71
|
isPublic: true,
|
|
71
72
|
wellKnownToken: {
|
|
@@ -31,6 +31,7 @@ const AP_WETH_GATEWAY = "WETH_GATEWAY";
|
|
|
31
31
|
const AP_WETH_TOKEN = "WETH_TOKEN";
|
|
32
32
|
const AP_ZAPPER_REGISTER = "ZAPPER_REGISTER";
|
|
33
33
|
const AP_ZERO_PRICE_FEED = "ZERO_PRICE_FEED";
|
|
34
|
+
const AP_KYC_COMPRESSOR = "GLOBAL::KYC_COMPRESSOR";
|
|
34
35
|
const ADDRESS_PROVIDER_V310 = "0xF7f0a609BfAb9a0A98786951ef10e5FE26cC1E38";
|
|
35
36
|
export {
|
|
36
37
|
ADDRESS_PROVIDER_V310,
|
|
@@ -51,6 +52,7 @@ export {
|
|
|
51
52
|
AP_GEAR_TOKEN,
|
|
52
53
|
AP_INFLATION_ATTACK_BLOCKER,
|
|
53
54
|
AP_INSOLVENCY_CHECKER,
|
|
55
|
+
AP_KYC_COMPRESSOR,
|
|
54
56
|
AP_MARKET_COMPRESSOR,
|
|
55
57
|
AP_MARKET_CONFIGURATOR,
|
|
56
58
|
AP_PARTIAL_LIQUIDATION_BOT,
|