@gearbox-protocol/sdk 14.12.0-next.74 → 14.12.0-next.75
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/plugins/accounts-counter/AccountsCounterPlugin.js +1 -1
- package/dist/cjs/sdk/accounts/CreditAccountsServiceV310.js +73 -445
- package/dist/cjs/sdk/accounts/credit-account-compressor/CreditAccountCompressor.js +280 -0
- package/dist/cjs/sdk/accounts/credit-account-compressor/CreditAccountCompressorV310Contract.js +141 -0
- package/dist/cjs/sdk/accounts/credit-account-compressor/index.js +6 -0
- package/dist/cjs/sdk/accounts/credit-account-compressor/types.js +1 -0
- package/dist/cjs/sdk/accounts/index.js +5 -0
- package/dist/cjs/sdk/index.js +4 -0
- package/dist/cjs/sdk/market/oracle/PriceOracleBaseContract.js +41 -1
- package/dist/cjs/sdk/market/oracle/PriceOracleV310Contract.js +0 -23
- package/dist/cjs/sdk/market/pricefeeds/PriceFeedsRegister.js +1 -1
- package/dist/esm/plugins/accounts-counter/AccountsCounterPlugin.js +1 -1
- package/dist/esm/sdk/accounts/CreditAccountsServiceV310.js +74 -446
- package/dist/esm/sdk/accounts/credit-account-compressor/CreditAccountCompressor.js +279 -0
- package/dist/esm/sdk/accounts/credit-account-compressor/CreditAccountCompressorV310Contract.js +141 -0
- package/dist/esm/sdk/accounts/credit-account-compressor/index.js +4 -0
- package/dist/esm/sdk/accounts/credit-account-compressor/types.js +1 -0
- package/dist/esm/sdk/accounts/index.js +4 -1
- package/dist/esm/sdk/index.js +3 -1
- package/dist/esm/sdk/market/oracle/PriceOracleBaseContract.js +41 -1
- package/dist/esm/sdk/market/oracle/PriceOracleV310Contract.js +0 -23
- package/dist/esm/sdk/market/pricefeeds/PriceFeedsRegister.js +1 -1
- package/dist/types/plugins/accounts/AccountsPlugin.d.ts +1 -1
- package/dist/types/sdk/accounts/CreditAccountsServiceV310.d.ts +10 -44
- package/dist/types/sdk/accounts/credit-account-compressor/CreditAccountCompressor.d.ts +60 -0
- package/dist/types/sdk/accounts/credit-account-compressor/CreditAccountCompressorV310Contract.d.ts +879 -0
- package/dist/types/sdk/accounts/credit-account-compressor/index.d.ts +4 -0
- package/dist/types/sdk/accounts/credit-account-compressor/types.d.ts +164 -0
- package/dist/types/sdk/accounts/index.d.ts +7 -3
- package/dist/types/sdk/accounts/types.d.ts +5 -112
- package/dist/types/sdk/base/index.d.ts +2 -2
- package/dist/types/sdk/base/types.d.ts +6 -1
- package/dist/types/sdk/index.d.ts +8 -5
- package/dist/types/sdk/market/index.d.ts +2 -2
- package/dist/types/sdk/market/oracle/PriceOracleBaseContract.d.ts +15 -4
- package/dist/types/sdk/market/oracle/PriceOracleV310Contract.d.ts +0 -11
- package/dist/types/sdk/market/oracle/index.d.ts +2 -2
- package/dist/types/sdk/market/oracle/types.d.ts +30 -14
- package/package.json +1 -1
|
@@ -1,27 +1,17 @@
|
|
|
1
1
|
import { iBaseRewardPoolAbi } from "../../abi/iBaseRewardPool.js";
|
|
2
2
|
import { ierc4626AdapterAbi } from "../../abi/ierc4626Adapter.js";
|
|
3
3
|
import { iBotListV310Abi } from "../../abi/310/generated.js";
|
|
4
|
-
import { creditAccountCompressorAbi } from "../../abi/compressors/creditAccountCompressor.js";
|
|
5
4
|
import { peripheryCompressorAbi } from "../../abi/compressors/peripheryCompressor.js";
|
|
6
5
|
import { rewardsCompressorAbi } from "../../abi/compressors/rewardsCompressor.js";
|
|
7
|
-
import {
|
|
8
|
-
import { AddressMap } from "../utils/AddressMap.js";
|
|
9
|
-
import { AddressSet } from "../utils/AddressSet.js";
|
|
10
|
-
import { AP_CREDIT_ACCOUNT_COMPRESSOR, AP_PERIPHERY_COMPRESSOR, AP_REWARDS_COMPRESSOR } from "../constants/address-provider.js";
|
|
6
|
+
import { AP_PERIPHERY_COMPRESSOR, AP_REWARDS_COMPRESSOR } from "../constants/address-provider.js";
|
|
11
7
|
import { ADDRESS_0X0 } from "../constants/addresses.js";
|
|
12
8
|
import { MAX_UINT256 } from "../constants/math.js";
|
|
13
9
|
import { VERSION_RANGE_310 } from "../constants/versions.js";
|
|
14
10
|
import "../constants/index.js";
|
|
15
|
-
import { hexEq } from "../utils/hex.js";
|
|
16
|
-
import "../utils/index.js";
|
|
17
11
|
import { SDKConstruct } from "../base/SDKConstruct.js";
|
|
18
12
|
import "../base/index.js";
|
|
19
|
-
import {
|
|
20
|
-
import
|
|
21
|
-
import { simulateWithPriceUpdates } from "../utils/viem/simulateWithPriceUpdates.js";
|
|
22
|
-
import "../utils/viem/index.js";
|
|
23
|
-
import { getRawPriceUpdates } from "../market/pricefeeds/getRawPriceUpdates.js";
|
|
24
|
-
import "../market/index.js";
|
|
13
|
+
import { CreditAccountCompressor } from "./credit-account-compressor/CreditAccountCompressor.js";
|
|
14
|
+
import "./credit-account-compressor/index.js";
|
|
25
15
|
import { extractPriceUpdates, extractQuotaTokens, mergePriceUpdates } from "./multicall-utils.js";
|
|
26
16
|
import { encodeFunctionData, getContract } from "viem";
|
|
27
17
|
//#region src/sdk/accounts/CreditAccountsServiceV310.ts
|
|
@@ -36,268 +26,33 @@ import { encodeFunctionData, getContract } from "viem";
|
|
|
36
26
|
**/
|
|
37
27
|
var CreditAccountsServiceV310 = class extends SDKConstruct {
|
|
38
28
|
#compressor;
|
|
39
|
-
|
|
40
|
-
constructor(sdk, options) {
|
|
29
|
+
constructor(sdk) {
|
|
41
30
|
super(sdk);
|
|
42
|
-
this.#
|
|
43
|
-
}
|
|
44
|
-
setBatchSize(batchSize) {
|
|
45
|
-
this.#batchSize = batchSize;
|
|
31
|
+
this.#compressor = new CreditAccountCompressor(sdk);
|
|
46
32
|
}
|
|
47
33
|
/**
|
|
48
34
|
* {@inheritDoc ICreditAccountsService.getCreditAccountData}
|
|
49
35
|
**/
|
|
50
36
|
async getCreditAccountData(account, blockNumber) {
|
|
51
|
-
|
|
52
|
-
try {
|
|
53
|
-
raw = await this.client.readContract({
|
|
54
|
-
abi: creditAccountCompressorAbi,
|
|
55
|
-
address: this.compressor,
|
|
56
|
-
functionName: "getCreditAccountData",
|
|
57
|
-
args: [account],
|
|
58
|
-
blockNumber,
|
|
59
|
-
gas: this.sdk.gasLimit
|
|
60
|
-
});
|
|
61
|
-
} catch (_e) {
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
const factory = this.sdk.marketRegister.findByCreditManager(raw.creditManager).rwaFactory;
|
|
65
|
-
let ca;
|
|
66
|
-
let investor;
|
|
67
|
-
if (raw.success) {
|
|
68
|
-
ca = raw;
|
|
69
|
-
investor = await factory?.getInvestor(raw.creditAccount, false);
|
|
70
|
-
} else {
|
|
71
|
-
const { txs: priceUpdateTxs } = await this.#getUpdateForAccount(raw);
|
|
72
|
-
[ca, investor] = await simulateWithPriceUpdates(this.client, {
|
|
73
|
-
priceUpdates: priceUpdateTxs,
|
|
74
|
-
contracts: [{
|
|
75
|
-
abi: creditAccountCompressorAbi,
|
|
76
|
-
address: this.compressor,
|
|
77
|
-
functionName: "getCreditAccountData",
|
|
78
|
-
args: [account]
|
|
79
|
-
}, ...factory ? [{
|
|
80
|
-
abi: iRWAFactoryAbi,
|
|
81
|
-
address: factory.address,
|
|
82
|
-
functionName: "getInvestor",
|
|
83
|
-
args: [raw.creditAccount]
|
|
84
|
-
}] : []],
|
|
85
|
-
blockNumber,
|
|
86
|
-
gas: this.sdk.gasLimit
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
return {
|
|
90
|
-
...ca,
|
|
91
|
-
investor
|
|
92
|
-
};
|
|
37
|
+
return this.#compressor.getCreditAccountData(account, blockNumber);
|
|
93
38
|
}
|
|
94
39
|
/**
|
|
95
40
|
* {@inheritDoc ICreditAccountsService.getCreditAccounts}
|
|
96
41
|
**/
|
|
97
42
|
async getCreditAccounts(options, blockNumber) {
|
|
98
|
-
|
|
99
|
-
const arg0 = creditManager ?? {
|
|
100
|
-
configurators: this.marketConfigurators,
|
|
101
|
-
creditManagers: [],
|
|
102
|
-
pools: [],
|
|
103
|
-
underlying: "0x0000000000000000000000000000000000000000"
|
|
104
|
-
};
|
|
105
|
-
const caFilter = {
|
|
106
|
-
owner,
|
|
107
|
-
includeZeroDebt,
|
|
108
|
-
minHealthFactor,
|
|
109
|
-
maxHealthFactor,
|
|
110
|
-
reverting: false
|
|
111
|
-
};
|
|
112
|
-
const { txs: priceUpdateTxs } = await this.sdk.priceFeeds.generatePriceFeedsUpdateTxs(ignoreReservePrices ? { main: true } : void 0);
|
|
113
|
-
const allCAs = [];
|
|
114
|
-
let revertingOffset = 0;
|
|
115
|
-
for (const reverting of [false, true]) {
|
|
116
|
-
let offset = 0n;
|
|
117
|
-
revertingOffset = allCAs.length;
|
|
118
|
-
do {
|
|
119
|
-
const [accounts, newOffset] = await this.#getCreditAccounts(this.#batchSize ? [
|
|
120
|
-
arg0,
|
|
121
|
-
{
|
|
122
|
-
...caFilter,
|
|
123
|
-
reverting
|
|
124
|
-
},
|
|
125
|
-
offset,
|
|
126
|
-
BigInt(this.#batchSize)
|
|
127
|
-
] : [
|
|
128
|
-
arg0,
|
|
129
|
-
{
|
|
130
|
-
...caFilter,
|
|
131
|
-
reverting
|
|
132
|
-
},
|
|
133
|
-
offset
|
|
134
|
-
], priceUpdateTxs, blockNumber);
|
|
135
|
-
allCAs.push(...accounts);
|
|
136
|
-
offset = newOffset;
|
|
137
|
-
} while (offset !== 0n);
|
|
138
|
-
}
|
|
139
|
-
this.logger?.debug(`loaded ${allCAs.length} credit accounts (${allCAs.length - revertingOffset} reverting)`);
|
|
140
|
-
return allCAs.sort((a, b) => Number(a.healthFactor - b.healthFactor));
|
|
43
|
+
return this.#compressor.getCreditAccounts(options, blockNumber);
|
|
141
44
|
}
|
|
142
45
|
/**
|
|
143
46
|
* {@inheritDoc ICreditAccountsService.getBorrowerCreditAccounts}
|
|
144
47
|
**/
|
|
145
48
|
async getBorrowerCreditAccounts(borrower, options, blockNumber) {
|
|
146
|
-
|
|
147
|
-
const { txs: priceUpdateTxs } = await this.sdk.priceFeeds.generatePriceFeedsUpdateTxs(ignoreReservePrices ? { main: true } : void 0);
|
|
148
|
-
const rwaAccountAddresses = (await this.sdk.rwa.getInvestorData(borrower)).flatMap((d) => d.creditAccounts.map((ca) => ca.creditAccount));
|
|
149
|
-
const cmFilter = creditManager ? {
|
|
150
|
-
configurators: [],
|
|
151
|
-
creditManagers: [creditManager],
|
|
152
|
-
pools: [],
|
|
153
|
-
underlying: ADDRESS_0X0
|
|
154
|
-
} : {
|
|
155
|
-
configurators: this.marketConfigurators,
|
|
156
|
-
creditManagers: [],
|
|
157
|
-
pools: [],
|
|
158
|
-
underlying: ADDRESS_0X0
|
|
159
|
-
};
|
|
160
|
-
const permissiveFilter = {
|
|
161
|
-
owner: borrower,
|
|
162
|
-
includeZeroDebt: true,
|
|
163
|
-
minHealthFactor: 0n,
|
|
164
|
-
maxHealthFactor: MAX_UINT256,
|
|
165
|
-
reverting: false
|
|
166
|
-
};
|
|
167
|
-
const rwaContracts = rwaAccountAddresses.map((account) => ({
|
|
168
|
-
abi: creditAccountCompressorAbi,
|
|
169
|
-
address: this.compressor,
|
|
170
|
-
functionName: "getCreditAccountData",
|
|
171
|
-
args: [account]
|
|
172
|
-
}));
|
|
173
|
-
const getCreditAccountsContracts = [false, true].map((reverting) => ({
|
|
174
|
-
abi: creditAccountCompressorAbi,
|
|
175
|
-
address: this.compressor,
|
|
176
|
-
functionName: "getCreditAccounts",
|
|
177
|
-
args: [
|
|
178
|
-
cmFilter,
|
|
179
|
-
{
|
|
180
|
-
...permissiveFilter,
|
|
181
|
-
reverting
|
|
182
|
-
},
|
|
183
|
-
0n
|
|
184
|
-
]
|
|
185
|
-
}));
|
|
186
|
-
const allContracts = [...rwaContracts, ...getCreditAccountsContracts];
|
|
187
|
-
const results = await simulateWithPriceUpdates(this.client, {
|
|
188
|
-
priceUpdates: priceUpdateTxs,
|
|
189
|
-
contracts: allContracts,
|
|
190
|
-
blockNumber,
|
|
191
|
-
gas: this.sdk.gasLimit
|
|
192
|
-
});
|
|
193
|
-
const rwaResults = results.slice(0, rwaAccountAddresses.length);
|
|
194
|
-
const normalResults = results.slice(rwaAccountAddresses.length);
|
|
195
|
-
const seen = new AddressSet();
|
|
196
|
-
const allCAs = [];
|
|
197
|
-
for (const ca of rwaResults) if (!seen.has(ca.creditAccount)) {
|
|
198
|
-
seen.add(ca.creditAccount);
|
|
199
|
-
allCAs.push({
|
|
200
|
-
...ca,
|
|
201
|
-
investor: borrower
|
|
202
|
-
});
|
|
203
|
-
}
|
|
204
|
-
for (const [accounts] of normalResults) for (const ca of accounts) if (!seen.has(ca.creditAccount)) {
|
|
205
|
-
seen.add(ca.creditAccount);
|
|
206
|
-
allCAs.push({
|
|
207
|
-
...ca,
|
|
208
|
-
investor: void 0
|
|
209
|
-
});
|
|
210
|
-
}
|
|
211
|
-
const filtered = allCAs.filter((ca) => {
|
|
212
|
-
if (!includeZeroDebt && ca.debt === 0n) return false;
|
|
213
|
-
if (ca.healthFactor < minHealthFactor) return false;
|
|
214
|
-
if (ca.healthFactor > maxHealthFactor) return false;
|
|
215
|
-
if (creditManager && !hexEq(ca.creditManager, creditManager)) return false;
|
|
216
|
-
return true;
|
|
217
|
-
});
|
|
218
|
-
this.logger?.debug(`loaded ${allCAs.length} borrower credit accounts (${rwaResults.length} RWA, ${filtered.length} after filter)`);
|
|
219
|
-
return filtered.sort((a, b) => Number(a.healthFactor - b.healthFactor));
|
|
49
|
+
return this.#compressor.getBorrowerCreditAccounts(borrower, options, blockNumber);
|
|
220
50
|
}
|
|
221
51
|
/**
|
|
222
52
|
* {@inheritDoc ICreditAccountsService.listPositions}
|
|
223
53
|
**/
|
|
224
54
|
async listPositions(props) {
|
|
225
|
-
|
|
226
|
-
const [accounts] = await Promise.all([this.getBorrowerCreditAccounts(owner, { includeZeroDebt }), this.sdk.withdrawalCompressor?.loadWithdrawableAssets()]);
|
|
227
|
-
const describable = accounts.filter((ca) => {
|
|
228
|
-
if (!ca.success) this.logger?.warn(`cannot describe position of ${this.labelAddress(ca.creditAccount)}: collateral computation failed`);
|
|
229
|
-
return ca.success;
|
|
230
|
-
});
|
|
231
|
-
const withdrawals = await Promise.all(describable.map((ca) => this.#accountWithdrawals(ca)));
|
|
232
|
-
return describable.map((ca, i) => this.#strategyPosition(ca, withdrawals[i] ?? new AddressMap()));
|
|
233
|
-
}
|
|
234
|
-
/**
|
|
235
|
-
* Builds one strategy position from an account snapshot.
|
|
236
|
-
*
|
|
237
|
-
* @param withdrawals - Delayed withdrawals of the account, keyed by the
|
|
238
|
-
* phantom token that represents them on it.
|
|
239
|
-
**/
|
|
240
|
-
#strategyPosition(ca, withdrawals) {
|
|
241
|
-
const suite = this.sdk.marketRegister.findCreditManager(ca.creditManager);
|
|
242
|
-
const { market } = suite;
|
|
243
|
-
const { priceOracle } = market;
|
|
244
|
-
const { pool } = market.pool;
|
|
245
|
-
const token = this.sdk.tokensMeta.mustGetToken(market.unwrappedUnderlying);
|
|
246
|
-
const totalDebtValue = ca.debt + ca.accruedInterest + ca.accruedFees;
|
|
247
|
-
const collateral = dominantCollateral(ca, market);
|
|
248
|
-
return {
|
|
249
|
-
kind: "strategy",
|
|
250
|
-
chainId: this.sdk.chainId,
|
|
251
|
-
creditManager: ca.creditManager,
|
|
252
|
-
creditAccount: ca.creditAccount,
|
|
253
|
-
name: collateral ? suite.strategyName(collateral) : token.symbol,
|
|
254
|
-
targetCollateral: collateral ? this.sdk.tokensMeta.mustGetToken(collateral) : null,
|
|
255
|
-
leverage: positionLeverage(totalDebtValue, ca.totalValue),
|
|
256
|
-
borrowApy: borrowApyBps(pool.baseInterestRate, suite.creditManager.feeInterest),
|
|
257
|
-
totalDebt: {
|
|
258
|
-
token,
|
|
259
|
-
value: totalDebtValue,
|
|
260
|
-
valueUsd: usdToNumber(ca.totalDebtUSD)
|
|
261
|
-
},
|
|
262
|
-
totalValue: {
|
|
263
|
-
token,
|
|
264
|
-
value: ca.totalValue,
|
|
265
|
-
valueUsd: usdToNumber(ca.totalValueUSD)
|
|
266
|
-
},
|
|
267
|
-
healthFactor: healthFactorBps(ca.healthFactor),
|
|
268
|
-
collaterals: ca.tokens.flatMap((t) => {
|
|
269
|
-
if ((t.mask & ca.enabledTokensMask) === 0n || t.balance <= 10n) return [];
|
|
270
|
-
return [{
|
|
271
|
-
collateral: priceOracle.toTokenAmount(t.token, t.balance),
|
|
272
|
-
quota: priceOracle.toTokenAmount(market.underlying, t.quota),
|
|
273
|
-
withdrawals: withdrawals.get(t.token) ?? []
|
|
274
|
-
}];
|
|
275
|
-
})
|
|
276
|
-
};
|
|
277
|
-
}
|
|
278
|
-
/**
|
|
279
|
-
* Delayed withdrawals of one account, keyed by the phantom token that
|
|
280
|
-
* represents them on it, so that each collateral row can pick up its own.
|
|
281
|
-
**/
|
|
282
|
-
async #accountWithdrawals(ca) {
|
|
283
|
-
const compressor = this.sdk.withdrawalCompressor;
|
|
284
|
-
const byPhantomToken = new AddressMap(void 0, "accountWithdrawals");
|
|
285
|
-
const holdsPhantomToken = ca.tokens.some((t) => t.balance > 10n && compressor?.getWithdrawalSourceToken(t.token) !== void 0);
|
|
286
|
-
if (!compressor || !holdsPhantomToken) return byPhantomToken;
|
|
287
|
-
const { priceOracle } = this.sdk.marketRegister.findByCreditManager(ca.creditManager);
|
|
288
|
-
const { claimable, pending } = await compressor.getCurrentWithdrawals(ca.creditAccount);
|
|
289
|
-
const add = (w, outputs, claimableAt) => {
|
|
290
|
-
const assets = outputs.map((o) => ({
|
|
291
|
-
isDelayed: true,
|
|
292
|
-
...priceOracle.toTokenAmount(o.token, o.amount),
|
|
293
|
-
redeemer: w.redeemer,
|
|
294
|
-
claimableAt: claimableAt === void 0 ? void 0 : Number(claimableAt)
|
|
295
|
-
}));
|
|
296
|
-
byPhantomToken.upsert(w.withdrawalPhantomToken, [...byPhantomToken.get(w.withdrawalPhantomToken) ?? [], ...assets]);
|
|
297
|
-
};
|
|
298
|
-
for (const w of claimable) add(w, w.outputs);
|
|
299
|
-
for (const w of pending) add(w, w.expectedOutputs, w.claimableAt);
|
|
300
|
-
return byPhantomToken;
|
|
55
|
+
return this.#compressor.listPositions(props);
|
|
301
56
|
}
|
|
302
57
|
/**
|
|
303
58
|
* {@inheritDoc ICreditAccountsService.getRewards}
|
|
@@ -419,7 +174,7 @@ var CreditAccountsServiceV310 = class extends SDKConstruct {
|
|
|
419
174
|
keepAssets,
|
|
420
175
|
debtOnly
|
|
421
176
|
});
|
|
422
|
-
const calls = await this
|
|
177
|
+
const calls = await this.prependPriceUpdates(account.creditManager, routerCloseResult.calls, account, { ignoreReservePrices });
|
|
423
178
|
let lossPolicyData;
|
|
424
179
|
if (applyLossPolicy) {
|
|
425
180
|
lossPolicyData = await this.sdk.marketRegister.findByCreditManager(account.creditManager).lossPolicy.getLiquidationData(account.creditAccount);
|
|
@@ -567,7 +322,7 @@ var CreditAccountsServiceV310 = class extends SDKConstruct {
|
|
|
567
322
|
}),
|
|
568
323
|
...callsAfter ?? []
|
|
569
324
|
];
|
|
570
|
-
const calls = await this
|
|
325
|
+
const calls = await this.prependPriceUpdates(cm.address, operationCalls);
|
|
571
326
|
let tx;
|
|
572
327
|
if (reopenCreditAccount) tx = await this.#multicallTx(cmSuite, reopenCreditAccount, calls);
|
|
573
328
|
else tx = await this.#openCreditAccountTx(cmSuite, to, calls, referralCode, rwaOptions);
|
|
@@ -575,134 +330,74 @@ var CreditAccountsServiceV310 = class extends SDKConstruct {
|
|
|
575
330
|
return tx;
|
|
576
331
|
}
|
|
577
332
|
/**
|
|
578
|
-
*
|
|
579
|
-
*
|
|
580
|
-
* @param
|
|
581
|
-
* @param
|
|
582
|
-
* @returns
|
|
583
|
-
*/
|
|
584
|
-
async #getCreditAccounts(args, priceUpdateTxs, blockNumber) {
|
|
585
|
-
let resp;
|
|
586
|
-
if (priceUpdateTxs?.length) [resp] = await simulateWithPriceUpdates(this.client, {
|
|
587
|
-
priceUpdates: priceUpdateTxs,
|
|
588
|
-
contracts: [{
|
|
589
|
-
abi: creditAccountCompressorAbi,
|
|
590
|
-
address: this.compressor,
|
|
591
|
-
functionName: "getCreditAccounts",
|
|
592
|
-
args
|
|
593
|
-
}],
|
|
594
|
-
blockNumber,
|
|
595
|
-
gas: this.sdk.gasLimit
|
|
596
|
-
});
|
|
597
|
-
else resp = await this.client.readContract({
|
|
598
|
-
abi: creditAccountCompressorAbi,
|
|
599
|
-
address: this.compressor,
|
|
600
|
-
functionName: "getCreditAccounts",
|
|
601
|
-
args,
|
|
602
|
-
blockNumber,
|
|
603
|
-
gas: this.sdk.gasLimit
|
|
604
|
-
});
|
|
605
|
-
this.logger?.debug({
|
|
606
|
-
accounts: resp[0]?.length ?? 0,
|
|
607
|
-
nextOffset: Number(resp[1])
|
|
608
|
-
}, "got credit accounts");
|
|
609
|
-
return resp;
|
|
610
|
-
}
|
|
611
|
-
/**
|
|
612
|
-
* Returns multicall entries to redeem (unwrap) RWA ERC-4626 vault shares into underlying for the given credit manager.
|
|
613
|
-
* Used when withdrawing debt from a RWA market: redeems adapter vault shares so the underlying can be withdrawn.
|
|
614
|
-
* Only applies when the credit manager's underlying is RWA-gated and has an ERC-4626 adapter configured.
|
|
615
|
-
* @param amount - Number of vault shares (adapter tokens) to redeem
|
|
333
|
+
* Encodes one ERC-4626 adapter call for an RWA market's underlying vault.
|
|
334
|
+
*
|
|
335
|
+
* @param functionName - Adapter function to call
|
|
336
|
+
* @param amount - Amount passed to the adapter, in the units the function expects
|
|
616
337
|
* @param creditManager - Credit manager address
|
|
617
|
-
* @returns Array of MultiCall to pass to credit facade multicall, or undefined
|
|
338
|
+
* @returns Array of MultiCall to pass to credit facade multicall, or undefined
|
|
339
|
+
* if the underlying is not RWA-gated or no adapter is configured for it
|
|
618
340
|
*/
|
|
619
|
-
|
|
341
|
+
#rwaVaultCalls(functionName, amount, creditManager) {
|
|
620
342
|
const suite = this.sdk.marketRegister.findCreditManager(creditManager);
|
|
621
343
|
const meta = this.sdk.tokensMeta.mustGet(suite.underlying);
|
|
622
344
|
if (!this.sdk.tokensMeta.isRWAUnderlying(meta)) return;
|
|
623
|
-
const
|
|
624
|
-
if (!
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
345
|
+
const target = suite.creditManager.adapters.get(meta.addr)?.address;
|
|
346
|
+
if (!target) return;
|
|
347
|
+
let callData;
|
|
348
|
+
switch (functionName) {
|
|
349
|
+
case "deposit":
|
|
350
|
+
callData = encodeFunctionData({
|
|
351
|
+
abi: ierc4626AdapterAbi,
|
|
352
|
+
functionName,
|
|
353
|
+
args: [amount, ADDRESS_0X0]
|
|
354
|
+
});
|
|
355
|
+
break;
|
|
356
|
+
case "redeem":
|
|
357
|
+
callData = encodeFunctionData({
|
|
358
|
+
abi: ierc4626AdapterAbi,
|
|
359
|
+
functionName,
|
|
360
|
+
args: [
|
|
361
|
+
amount,
|
|
362
|
+
ADDRESS_0X0,
|
|
363
|
+
ADDRESS_0X0
|
|
364
|
+
]
|
|
365
|
+
});
|
|
366
|
+
break;
|
|
367
|
+
default: callData = encodeFunctionData({
|
|
628
368
|
abi: ierc4626AdapterAbi,
|
|
629
|
-
functionName
|
|
630
|
-
args: [
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
369
|
+
functionName,
|
|
370
|
+
args: [amount]
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
return [{
|
|
374
|
+
target,
|
|
375
|
+
callData
|
|
636
376
|
}];
|
|
637
377
|
}
|
|
638
378
|
/**
|
|
639
|
-
*
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
379
|
+
* {@inheritDoc ICreditAccountsService.assembleRWAUnwrapCalls}
|
|
380
|
+
*/
|
|
381
|
+
async assembleRWAUnwrapCalls(amount, creditManager) {
|
|
382
|
+
return this.#rwaVaultCalls("redeem", amount, creditManager);
|
|
383
|
+
}
|
|
384
|
+
/**
|
|
385
|
+
* {@inheritDoc ICreditAccountsService.assembleRWAWrapCalls}
|
|
645
386
|
*/
|
|
646
387
|
async assembleRWAWrapCalls(amount, creditManager) {
|
|
647
|
-
|
|
648
|
-
const meta = this.sdk.tokensMeta.mustGet(suite.underlying);
|
|
649
|
-
if (!this.sdk.tokensMeta.isRWAUnderlying(meta)) return;
|
|
650
|
-
const adapterAddress = suite.creditManager.adapters.get(meta.addr)?.address;
|
|
651
|
-
if (!adapterAddress) return;
|
|
652
|
-
return [{
|
|
653
|
-
target: adapterAddress,
|
|
654
|
-
callData: encodeFunctionData({
|
|
655
|
-
abi: ierc4626AdapterAbi,
|
|
656
|
-
functionName: "deposit",
|
|
657
|
-
args: [amount, ADDRESS_0X0]
|
|
658
|
-
})
|
|
659
|
-
}];
|
|
388
|
+
return this.#rwaVaultCalls("deposit", amount, creditManager);
|
|
660
389
|
}
|
|
661
390
|
/**
|
|
662
|
-
*
|
|
663
|
-
* Redeems the leftover vault shares (e.g. after repaying debt) so the account does not hold excess RWA vault tokens.
|
|
664
|
-
* Only applies when the credit manager's underlying is RWA-gated and has an ERC-4626 adapter configured.
|
|
665
|
-
* @param amount - Leftover vault share amount to redeem (in adapter/vault decimals)
|
|
666
|
-
* @param creditManager - Credit manager address
|
|
667
|
-
* @returns Array of MultiCall to pass to credit facade multicall, or undefined if underlying is not RWA or no adapter is configured
|
|
391
|
+
* {@inheritDoc ICreditAccountsService.assembleRedeemDiffCalls}
|
|
668
392
|
*/
|
|
669
393
|
async assembleRedeemDiffCalls(amount, creditManager) {
|
|
670
|
-
|
|
671
|
-
const meta = this.sdk.tokensMeta.mustGet(suite.underlying);
|
|
672
|
-
if (!this.sdk.tokensMeta.isRWAUnderlying(meta)) return;
|
|
673
|
-
const adapterAddress = suite.creditManager.adapters.get(meta.addr)?.address;
|
|
674
|
-
if (!adapterAddress) return;
|
|
675
|
-
return [{
|
|
676
|
-
target: adapterAddress,
|
|
677
|
-
callData: encodeFunctionData({
|
|
678
|
-
abi: ierc4626AdapterAbi,
|
|
679
|
-
functionName: "redeemDiff",
|
|
680
|
-
args: [amount]
|
|
681
|
-
})
|
|
682
|
-
}];
|
|
394
|
+
return this.#rwaVaultCalls("redeemDiff", amount, creditManager);
|
|
683
395
|
}
|
|
684
396
|
/**
|
|
685
|
-
*
|
|
686
|
-
* Deposits the leftover underlying (e.g. after decreasing debt) into the vault so the account does not hold excess underlying.
|
|
687
|
-
* Only applies when the credit manager's underlying is RWA-gated and has an ERC-4626 adapter configured.
|
|
688
|
-
* @param amount - Leftover underlying amount to deposit into the vault (in underlying decimals)
|
|
689
|
-
* @param creditManager - Credit manager address
|
|
690
|
-
* @returns Array of MultiCall to pass to credit facade multicall, or undefined if underlying is not RWA or no adapter is configured
|
|
397
|
+
* {@inheritDoc ICreditAccountsService.assembleDepositDiffCalls}
|
|
691
398
|
*/
|
|
692
399
|
async assembleDepositDiffCalls(amount, creditManager) {
|
|
693
|
-
|
|
694
|
-
const meta = this.sdk.tokensMeta.mustGet(suite.underlying);
|
|
695
|
-
if (!this.sdk.tokensMeta.isRWAUnderlying(meta)) return;
|
|
696
|
-
const adapterAddress = suite.creditManager.adapters.get(meta.addr)?.address;
|
|
697
|
-
if (!adapterAddress) return;
|
|
698
|
-
return [{
|
|
699
|
-
target: adapterAddress,
|
|
700
|
-
callData: encodeFunctionData({
|
|
701
|
-
abi: ierc4626AdapterAbi,
|
|
702
|
-
functionName: "depositDiff",
|
|
703
|
-
args: [amount]
|
|
704
|
-
})
|
|
705
|
-
}];
|
|
400
|
+
return this.#rwaVaultCalls("depositDiff", amount, creditManager);
|
|
706
401
|
}
|
|
707
402
|
/**
|
|
708
403
|
* {@inheritDoc ICreditAccountsService.setBot}
|
|
@@ -725,7 +420,7 @@ var CreditAccountsServiceV310 = class extends SDKConstruct {
|
|
|
725
420
|
}]
|
|
726
421
|
}).read.requiredPermissions();
|
|
727
422
|
const addBotCall = cm.creditFacade.prepareSetBotPermissions(botAddress, permissions);
|
|
728
|
-
const calls = targetContract.type === "creditAccount" ? await this
|
|
423
|
+
const calls = targetContract.type === "creditAccount" ? await this.prependPriceUpdates(targetContract.creditManager, [addBotCall], targetContract) : [addBotCall];
|
|
729
424
|
return {
|
|
730
425
|
tx: targetContract.type === "creditAccount" ? await this.#multicallTx(cm, targetContract.creditAccount, calls) : void 0,
|
|
731
426
|
calls,
|
|
@@ -771,7 +466,7 @@ var CreditAccountsServiceV310 = class extends SDKConstruct {
|
|
|
771
466
|
minQuota,
|
|
772
467
|
averageQuota
|
|
773
468
|
})];
|
|
774
|
-
const calls = await this
|
|
469
|
+
const calls = await this.prependPriceUpdates(ca.creditManager, operationCalls, ca);
|
|
775
470
|
return await this.#multicallTx(cm, ca.creditAccount, calls);
|
|
776
471
|
}
|
|
777
472
|
/**
|
|
@@ -779,80 +474,26 @@ var CreditAccountsServiceV310 = class extends SDKConstruct {
|
|
|
779
474
|
* {@inheritDoc ICreditAccountsService.getOnDemandPriceUpdates}
|
|
780
475
|
**/
|
|
781
476
|
async getOnDemandPriceUpdates(account, ignoreReservePrices) {
|
|
782
|
-
const {
|
|
783
|
-
|
|
784
|
-
const update = await this.#getUpdateForAccount(account, ignoreReservePrices);
|
|
785
|
-
this.logger?.debug({
|
|
786
|
-
account: creditAccount,
|
|
787
|
-
manager: cm.name
|
|
788
|
-
}, `getting on demand price updates from ${update.txs.length} txs`);
|
|
789
|
-
return getRawPriceUpdates(update);
|
|
477
|
+
const { priceOracle } = this.sdk.marketRegister.findByCreditManager(account.creditManager);
|
|
478
|
+
return priceOracle.priceUpdatesForAccount(account, { reserve: !ignoreReservePrices });
|
|
790
479
|
}
|
|
791
480
|
/**
|
|
792
|
-
*
|
|
793
|
-
*
|
|
794
|
-
* Deduplicates existing `onDemandPriceUpdates` calls
|
|
795
|
-
*
|
|
796
|
-
* @param creditManager - Address of the credit manager
|
|
797
|
-
* @param calls - The multicall array to prepend price updates to
|
|
798
|
-
* @param ca - Credit account slice, undefined when opening a new account
|
|
799
|
-
* @param options - Optional settings for price update generation
|
|
800
|
-
* @returns A new array with a single consolidated price update call prepended,
|
|
801
|
-
* followed by the non-price-update calls in their original order
|
|
481
|
+
* {@inheritDoc ICreditAccountsService.prependPriceUpdates}
|
|
802
482
|
*/
|
|
803
|
-
async
|
|
804
|
-
const
|
|
483
|
+
async prependPriceUpdates(creditManager, calls, creditAccount, options) {
|
|
484
|
+
const { priceOracle } = this.sdk.marketRegister.findByCreditManager(creditManager);
|
|
805
485
|
const suite = this.sdk.marketRegister.findCreditManager(creditManager);
|
|
806
|
-
const cm = suite.creditManager;
|
|
807
486
|
const { priceUpdates: existingUpdates, remainingCalls } = extractPriceUpdates(calls);
|
|
808
|
-
const
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
}
|
|
813
|
-
const
|
|
814
|
-
const priceFeeds = market.priceOracle.priceFeedsForTokens(Array.from(tokens), {
|
|
815
|
-
main: true,
|
|
816
|
-
reserve: !ignoreReservePrices
|
|
817
|
-
});
|
|
818
|
-
const tStr = tokens.map((t) => this.labelAddress(t)).join(", ");
|
|
819
|
-
const remark = ignoreReservePrices ? " main" : "";
|
|
820
|
-
this.logger?.debug({
|
|
821
|
-
account: ca?.creditAccount,
|
|
822
|
-
manager: cm.name
|
|
823
|
-
}, `prependPriceUpdates for ${tStr} from ${priceFeeds.length}${remark} price feeds`);
|
|
824
|
-
const generatedUpdates = await this.sdk.priceFeeds.generatePriceFeedsUpdates(priceFeeds);
|
|
487
|
+
const extraTokens = extractQuotaTokens(calls).asArray();
|
|
488
|
+
const opts = {
|
|
489
|
+
reserve: !options?.ignoreReservePrices,
|
|
490
|
+
extraTokens
|
|
491
|
+
};
|
|
492
|
+
const generatedUpdates = creditAccount ? await priceOracle.priceUpdatesForAccount(creditAccount, opts) : await priceOracle.priceUpdatesForTokens([suite.creditManager.underlying, ...extraTokens], opts);
|
|
825
493
|
const merged = mergePriceUpdates(existingUpdates, generatedUpdates);
|
|
826
494
|
if (merged.length === 0) return remainingCalls;
|
|
827
495
|
return [suite.creditFacade.prepareOnDemandPriceUpdates(merged), ...remainingCalls];
|
|
828
496
|
}
|
|
829
|
-
async #getUpdateForAccount(account, ignoreReservePrices) {
|
|
830
|
-
const { creditManager, creditAccount, enabledTokensMask } = account;
|
|
831
|
-
const market = this.sdk.marketRegister.findByCreditManager(creditManager);
|
|
832
|
-
const cm = this.sdk.marketRegister.findCreditManager(creditManager).creditManager;
|
|
833
|
-
const tokens = new AddressSet([cm.underlying]);
|
|
834
|
-
for (const t of account.tokens) {
|
|
835
|
-
const isEnabled = (t.mask & enabledTokensMask) !== 0n;
|
|
836
|
-
if (t.balance > 10n && isEnabled) tokens.add(t.token);
|
|
837
|
-
}
|
|
838
|
-
const priceFeeds = market.priceOracle.priceFeedsForTokens(Array.from(tokens), {
|
|
839
|
-
main: true,
|
|
840
|
-
reserve: !ignoreReservePrices
|
|
841
|
-
});
|
|
842
|
-
const tStr = tokens.map((t) => this.labelAddress(t)).join(", ");
|
|
843
|
-
const remark = ignoreReservePrices ? " main" : "";
|
|
844
|
-
this.logger?.debug({
|
|
845
|
-
account: creditAccount,
|
|
846
|
-
manager: cm.name
|
|
847
|
-
}, `generating price feed updates for ${tStr} from ${priceFeeds.length}${remark} price feeds`);
|
|
848
|
-
return this.sdk.priceFeeds.generatePriceFeedsUpdateTxs(priceFeeds);
|
|
849
|
-
}
|
|
850
|
-
/**
|
|
851
|
-
* {@inheritDoc ICreditAccountsService.prependPriceUpdates}
|
|
852
|
-
*/
|
|
853
|
-
async prependPriceUpdates(creditManager, calls, creditAccount, options) {
|
|
854
|
-
return this.#prependPriceUpdates(creditManager, calls, creditAccount, options);
|
|
855
|
-
}
|
|
856
497
|
/**
|
|
857
498
|
* {@inheritDoc ICreditAccountsService.assembleCaOperations}
|
|
858
499
|
*/
|
|
@@ -898,7 +539,7 @@ var CreditAccountsServiceV310 = class extends SDKConstruct {
|
|
|
898
539
|
*/
|
|
899
540
|
async executeCaUpdate(creditAccount, calls, options) {
|
|
900
541
|
const cm = this.sdk.marketRegister.findCreditManager(creditAccount.creditManager);
|
|
901
|
-
const callsWithPrices = await this
|
|
542
|
+
const callsWithPrices = await this.prependPriceUpdates(creditAccount.creditManager, calls, creditAccount, { ignoreReservePrices: options?.ignoreReservePrices });
|
|
902
543
|
const tx = await this.#multicallTx(cm, creditAccount.creditAccount, callsWithPrices);
|
|
903
544
|
if (options?.ethAmount && options.ethAmount > 0n) tx.value = options.ethAmount.toString(10);
|
|
904
545
|
return tx;
|
|
@@ -933,25 +574,12 @@ var CreditAccountsServiceV310 = class extends SDKConstruct {
|
|
|
933
574
|
prepareAddCollateral(creditFacade, assets, permits) {
|
|
934
575
|
return this.sdk.marketRegister.findCreditFacade(creditFacade).prepareAddCollateral(assets, permits);
|
|
935
576
|
}
|
|
936
|
-
/**
|
|
937
|
-
* Returns addresses of market configurators
|
|
938
|
-
*/
|
|
939
|
-
get marketConfigurators() {
|
|
940
|
-
return this.sdk.marketRegister.marketConfigurators.map((mc) => mc.address);
|
|
941
|
-
}
|
|
942
577
|
get rewardCompressor() {
|
|
943
578
|
return this.sdk.addressProvider.mustGetLatest(AP_REWARDS_COMPRESSOR, VERSION_RANGE_310)[0];
|
|
944
579
|
}
|
|
945
580
|
get peripheryCompressor() {
|
|
946
581
|
return this.sdk.addressProvider.mustGetLatest(AP_PERIPHERY_COMPRESSOR, VERSION_RANGE_310)[0];
|
|
947
582
|
}
|
|
948
|
-
get compressor() {
|
|
949
|
-
if (!this.#compressor) {
|
|
950
|
-
[this.#compressor] = this.sdk.addressProvider.mustGetLatest(AP_CREDIT_ACCOUNT_COMPRESSOR, VERSION_RANGE_310);
|
|
951
|
-
this.logger?.debug(`credit account compressor address: ${this.#compressor}`);
|
|
952
|
-
}
|
|
953
|
-
return this.#compressor;
|
|
954
|
-
}
|
|
955
583
|
/**
|
|
956
584
|
* Wrapper that selects between credit facade and RWA factory
|
|
957
585
|
* @param suite
|