@gearbox-protocol/sdk 14.12.0-next.73 → 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/dev/AccountOpener.js +2 -5
- package/dist/cjs/plugins/accounts-counter/AccountsCounterPlugin.js +1 -1
- package/dist/cjs/sdk/accounts/CreditAccountsServiceV310.js +118 -974
- 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 -4
- package/dist/cjs/sdk/accounts/intents/operations/unwrap-rwa-collateral/index.js +1 -1
- package/dist/cjs/sdk/accounts/intents/operations/wrap-rwa-collateral/index.js +1 -1
- package/dist/cjs/sdk/accounts/intents/testing/sdk-mock.js +2 -2
- package/dist/cjs/sdk/accounts/liquidations/LiquidationsService.js +3 -3
- package/dist/cjs/sdk/accounts/liquidations/constants.js +0 -2
- package/dist/cjs/sdk/accounts/liquidations/index.js +0 -2
- package/dist/cjs/sdk/constants/index.js +1 -0
- package/dist/cjs/sdk/constants/math.js +5 -0
- package/dist/cjs/sdk/index.js +12 -4
- package/dist/cjs/sdk/market/MarketRegister.js +10 -0
- package/dist/cjs/sdk/market/credit/CreditFacadeV310Contract.js +181 -0
- package/dist/cjs/sdk/market/credit/CreditSuite.js +107 -1
- package/dist/cjs/sdk/{accounts → market/credit}/dominantCollateral.js +18 -4
- package/dist/cjs/sdk/market/credit/index.js +3 -0
- package/dist/cjs/sdk/market/index.js +3 -0
- package/dist/cjs/sdk/market/math.js +59 -0
- package/dist/cjs/sdk/market/oracle/PriceOracleBaseContract.js +41 -1
- package/dist/cjs/sdk/market/oracle/PriceOracleV310Contract.js +0 -30
- package/dist/cjs/sdk/market/pricefeeds/PriceFeedsRegister.js +1 -1
- package/dist/cjs/sdk/opportunities/index.js +4 -0
- package/dist/esm/dev/AccountOpener.js +2 -5
- package/dist/esm/plugins/accounts-counter/AccountsCounterPlugin.js +1 -1
- package/dist/esm/sdk/accounts/CreditAccountsServiceV310.js +121 -977
- 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 -3
- package/dist/esm/sdk/accounts/intents/operations/unwrap-rwa-collateral/index.js +1 -1
- package/dist/esm/sdk/accounts/intents/operations/wrap-rwa-collateral/index.js +1 -1
- package/dist/esm/sdk/accounts/intents/testing/sdk-mock.js +2 -2
- package/dist/esm/sdk/accounts/liquidations/LiquidationsService.js +2 -2
- package/dist/esm/sdk/accounts/liquidations/constants.js +1 -2
- package/dist/esm/sdk/accounts/liquidations/index.js +1 -2
- package/dist/esm/sdk/constants/index.js +2 -2
- package/dist/esm/sdk/constants/math.js +5 -1
- package/dist/esm/sdk/index.js +6 -5
- package/dist/esm/sdk/market/MarketRegister.js +10 -0
- package/dist/esm/sdk/market/credit/CreditFacadeV310Contract.js +181 -0
- package/dist/esm/sdk/market/credit/CreditSuite.js +108 -2
- package/dist/esm/sdk/{accounts → market/credit}/dominantCollateral.js +18 -5
- package/dist/esm/sdk/market/credit/index.js +2 -1
- package/dist/esm/sdk/market/index.js +2 -1
- package/dist/esm/sdk/market/math.js +56 -1
- package/dist/esm/sdk/market/oracle/PriceOracleBaseContract.js +41 -1
- package/dist/esm/sdk/market/oracle/PriceOracleV310Contract.js +1 -31
- package/dist/esm/sdk/market/pricefeeds/PriceFeedsRegister.js +1 -1
- package/dist/esm/sdk/opportunities/index.js +2 -2
- package/dist/types/plugins/accounts/AccountsPlugin.d.ts +1 -1
- package/dist/types/sdk/OnchainSDK.d.ts +1 -1
- package/dist/types/sdk/accounts/CreditAccountsServiceV310.d.ts +23 -124
- 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 -5
- package/dist/types/sdk/accounts/liquidations/constants.d.ts +1 -2
- package/dist/types/sdk/accounts/liquidations/index.d.ts +1 -2
- package/dist/types/sdk/accounts/types.d.ts +46 -457
- package/dist/types/sdk/base/index.d.ts +2 -2
- package/dist/types/sdk/base/types.d.ts +6 -1
- package/dist/types/sdk/constants/index.d.ts +2 -2
- package/dist/types/sdk/constants/math.d.ts +5 -1
- package/dist/types/sdk/index.d.ts +16 -14
- package/dist/types/sdk/market/MarketRegister.d.ts +7 -0
- package/dist/types/sdk/market/credit/CreditFacadeV310Contract.d.ts +47 -2
- package/dist/types/sdk/market/credit/CreditSuite.d.ts +24 -2
- package/dist/types/sdk/{accounts → market/credit}/dominantCollateral.d.ts +13 -6
- package/dist/types/sdk/market/credit/index.d.ts +3 -2
- package/dist/types/sdk/market/credit/types.d.ts +112 -2
- package/dist/types/sdk/market/index.d.ts +4 -3
- package/dist/types/sdk/market/math.d.ts +60 -1
- package/dist/types/sdk/market/oracle/PriceOracleBaseContract.d.ts +15 -4
- package/dist/types/sdk/market/oracle/PriceOracleV310Contract.d.ts +0 -10
- package/dist/types/sdk/market/oracle/index.d.ts +2 -2
- package/dist/types/sdk/market/oracle/types.d.ts +30 -14
- package/dist/types/sdk/market/rwa/securitize/SecuritizeRWAFactory.d.ts +1 -1
- package/dist/types/sdk/market/rwa/types.d.ts +1 -1
- package/dist/types/sdk/opportunities/index.d.ts +2 -2
- package/package.json +1 -1
- package/dist/cjs/sdk/accounts/constants.js +0 -12
- package/dist/esm/sdk/accounts/constants.js +0 -11
- package/dist/types/sdk/accounts/constants.d.ts +0 -11
|
@@ -1,29 +1,17 @@
|
|
|
1
1
|
import { iBaseRewardPoolAbi } from "../../abi/iBaseRewardPool.js";
|
|
2
2
|
import { ierc4626AdapterAbi } from "../../abi/ierc4626Adapter.js";
|
|
3
|
-
import { iBotListV310Abi
|
|
4
|
-
import { creditAccountCompressorAbi } from "../../abi/compressors/creditAccountCompressor.js";
|
|
3
|
+
import { iBotListV310Abi } from "../../abi/310/generated.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 { AssetsMap } from "../utils/AssetsMap.js";
|
|
11
|
-
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";
|
|
12
7
|
import { ADDRESS_0X0 } from "../constants/addresses.js";
|
|
13
|
-
import { MAX_UINT256
|
|
8
|
+
import { MAX_UINT256 } from "../constants/math.js";
|
|
14
9
|
import { VERSION_RANGE_310 } from "../constants/versions.js";
|
|
15
10
|
import "../constants/index.js";
|
|
16
|
-
import { hexEq } from "../utils/hex.js";
|
|
17
|
-
import "../utils/index.js";
|
|
18
11
|
import { SDKConstruct } from "../base/SDKConstruct.js";
|
|
19
12
|
import "../base/index.js";
|
|
20
|
-
import {
|
|
21
|
-
import
|
|
22
|
-
import "../utils/viem/index.js";
|
|
23
|
-
import { getRawPriceUpdates } from "../market/pricefeeds/getRawPriceUpdates.js";
|
|
24
|
-
import "../market/index.js";
|
|
25
|
-
import "./constants.js";
|
|
26
|
-
import { dominantCollateral } from "./dominantCollateral.js";
|
|
13
|
+
import { CreditAccountCompressor } from "./credit-account-compressor/CreditAccountCompressor.js";
|
|
14
|
+
import "./credit-account-compressor/index.js";
|
|
27
15
|
import { extractPriceUpdates, extractQuotaTokens, mergePriceUpdates } from "./multicall-utils.js";
|
|
28
16
|
import { encodeFunctionData, getContract } from "viem";
|
|
29
17
|
//#region src/sdk/accounts/CreditAccountsServiceV310.ts
|
|
@@ -38,268 +26,33 @@ import { encodeFunctionData, getContract } from "viem";
|
|
|
38
26
|
**/
|
|
39
27
|
var CreditAccountsServiceV310 = class extends SDKConstruct {
|
|
40
28
|
#compressor;
|
|
41
|
-
|
|
42
|
-
constructor(sdk, options) {
|
|
29
|
+
constructor(sdk) {
|
|
43
30
|
super(sdk);
|
|
44
|
-
this.#
|
|
45
|
-
}
|
|
46
|
-
setBatchSize(batchSize) {
|
|
47
|
-
this.#batchSize = batchSize;
|
|
31
|
+
this.#compressor = new CreditAccountCompressor(sdk);
|
|
48
32
|
}
|
|
49
33
|
/**
|
|
50
34
|
* {@inheritDoc ICreditAccountsService.getCreditAccountData}
|
|
51
35
|
**/
|
|
52
36
|
async getCreditAccountData(account, blockNumber) {
|
|
53
|
-
|
|
54
|
-
try {
|
|
55
|
-
raw = await this.client.readContract({
|
|
56
|
-
abi: creditAccountCompressorAbi,
|
|
57
|
-
address: this.compressor,
|
|
58
|
-
functionName: "getCreditAccountData",
|
|
59
|
-
args: [account],
|
|
60
|
-
blockNumber,
|
|
61
|
-
gas: this.sdk.gasLimit
|
|
62
|
-
});
|
|
63
|
-
} catch (_e) {
|
|
64
|
-
return;
|
|
65
|
-
}
|
|
66
|
-
const factory = this.sdk.marketRegister.findByCreditManager(raw.creditManager).rwaFactory;
|
|
67
|
-
let ca;
|
|
68
|
-
let investor;
|
|
69
|
-
if (raw.success) {
|
|
70
|
-
ca = raw;
|
|
71
|
-
investor = await factory?.getInvestor(raw.creditAccount, false);
|
|
72
|
-
} else {
|
|
73
|
-
const { txs: priceUpdateTxs } = await this.#getUpdateForAccount(raw);
|
|
74
|
-
[ca, investor] = await simulateWithPriceUpdates(this.client, {
|
|
75
|
-
priceUpdates: priceUpdateTxs,
|
|
76
|
-
contracts: [{
|
|
77
|
-
abi: creditAccountCompressorAbi,
|
|
78
|
-
address: this.compressor,
|
|
79
|
-
functionName: "getCreditAccountData",
|
|
80
|
-
args: [account]
|
|
81
|
-
}, ...factory ? [{
|
|
82
|
-
abi: iRWAFactoryAbi,
|
|
83
|
-
address: factory.address,
|
|
84
|
-
functionName: "getInvestor",
|
|
85
|
-
args: [raw.creditAccount]
|
|
86
|
-
}] : []],
|
|
87
|
-
blockNumber,
|
|
88
|
-
gas: this.sdk.gasLimit
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
return {
|
|
92
|
-
...ca,
|
|
93
|
-
investor
|
|
94
|
-
};
|
|
37
|
+
return this.#compressor.getCreditAccountData(account, blockNumber);
|
|
95
38
|
}
|
|
96
39
|
/**
|
|
97
40
|
* {@inheritDoc ICreditAccountsService.getCreditAccounts}
|
|
98
41
|
**/
|
|
99
42
|
async getCreditAccounts(options, blockNumber) {
|
|
100
|
-
|
|
101
|
-
const arg0 = creditManager ?? {
|
|
102
|
-
configurators: this.marketConfigurators,
|
|
103
|
-
creditManagers: [],
|
|
104
|
-
pools: [],
|
|
105
|
-
underlying: "0x0000000000000000000000000000000000000000"
|
|
106
|
-
};
|
|
107
|
-
const caFilter = {
|
|
108
|
-
owner,
|
|
109
|
-
includeZeroDebt,
|
|
110
|
-
minHealthFactor,
|
|
111
|
-
maxHealthFactor,
|
|
112
|
-
reverting: false
|
|
113
|
-
};
|
|
114
|
-
const { txs: priceUpdateTxs } = await this.sdk.priceFeeds.generatePriceFeedsUpdateTxs(ignoreReservePrices ? { main: true } : void 0);
|
|
115
|
-
const allCAs = [];
|
|
116
|
-
let revertingOffset = 0;
|
|
117
|
-
for (const reverting of [false, true]) {
|
|
118
|
-
let offset = 0n;
|
|
119
|
-
revertingOffset = allCAs.length;
|
|
120
|
-
do {
|
|
121
|
-
const [accounts, newOffset] = await this.#getCreditAccounts(this.#batchSize ? [
|
|
122
|
-
arg0,
|
|
123
|
-
{
|
|
124
|
-
...caFilter,
|
|
125
|
-
reverting
|
|
126
|
-
},
|
|
127
|
-
offset,
|
|
128
|
-
BigInt(this.#batchSize)
|
|
129
|
-
] : [
|
|
130
|
-
arg0,
|
|
131
|
-
{
|
|
132
|
-
...caFilter,
|
|
133
|
-
reverting
|
|
134
|
-
},
|
|
135
|
-
offset
|
|
136
|
-
], priceUpdateTxs, blockNumber);
|
|
137
|
-
allCAs.push(...accounts);
|
|
138
|
-
offset = newOffset;
|
|
139
|
-
} while (offset !== 0n);
|
|
140
|
-
}
|
|
141
|
-
this.logger?.debug(`loaded ${allCAs.length} credit accounts (${allCAs.length - revertingOffset} reverting)`);
|
|
142
|
-
return allCAs.sort((a, b) => Number(a.healthFactor - b.healthFactor));
|
|
43
|
+
return this.#compressor.getCreditAccounts(options, blockNumber);
|
|
143
44
|
}
|
|
144
45
|
/**
|
|
145
46
|
* {@inheritDoc ICreditAccountsService.getBorrowerCreditAccounts}
|
|
146
47
|
**/
|
|
147
48
|
async getBorrowerCreditAccounts(borrower, options, blockNumber) {
|
|
148
|
-
|
|
149
|
-
const { txs: priceUpdateTxs } = await this.sdk.priceFeeds.generatePriceFeedsUpdateTxs(ignoreReservePrices ? { main: true } : void 0);
|
|
150
|
-
const rwaAccountAddresses = (await this.sdk.rwa.getInvestorData(borrower)).flatMap((d) => d.creditAccounts.map((ca) => ca.creditAccount));
|
|
151
|
-
const cmFilter = creditManager ? {
|
|
152
|
-
configurators: [],
|
|
153
|
-
creditManagers: [creditManager],
|
|
154
|
-
pools: [],
|
|
155
|
-
underlying: ADDRESS_0X0
|
|
156
|
-
} : {
|
|
157
|
-
configurators: this.marketConfigurators,
|
|
158
|
-
creditManagers: [],
|
|
159
|
-
pools: [],
|
|
160
|
-
underlying: ADDRESS_0X0
|
|
161
|
-
};
|
|
162
|
-
const permissiveFilter = {
|
|
163
|
-
owner: borrower,
|
|
164
|
-
includeZeroDebt: true,
|
|
165
|
-
minHealthFactor: 0n,
|
|
166
|
-
maxHealthFactor: MAX_UINT256,
|
|
167
|
-
reverting: false
|
|
168
|
-
};
|
|
169
|
-
const rwaContracts = rwaAccountAddresses.map((account) => ({
|
|
170
|
-
abi: creditAccountCompressorAbi,
|
|
171
|
-
address: this.compressor,
|
|
172
|
-
functionName: "getCreditAccountData",
|
|
173
|
-
args: [account]
|
|
174
|
-
}));
|
|
175
|
-
const getCreditAccountsContracts = [false, true].map((reverting) => ({
|
|
176
|
-
abi: creditAccountCompressorAbi,
|
|
177
|
-
address: this.compressor,
|
|
178
|
-
functionName: "getCreditAccounts",
|
|
179
|
-
args: [
|
|
180
|
-
cmFilter,
|
|
181
|
-
{
|
|
182
|
-
...permissiveFilter,
|
|
183
|
-
reverting
|
|
184
|
-
},
|
|
185
|
-
0n
|
|
186
|
-
]
|
|
187
|
-
}));
|
|
188
|
-
const allContracts = [...rwaContracts, ...getCreditAccountsContracts];
|
|
189
|
-
const results = await simulateWithPriceUpdates(this.client, {
|
|
190
|
-
priceUpdates: priceUpdateTxs,
|
|
191
|
-
contracts: allContracts,
|
|
192
|
-
blockNumber,
|
|
193
|
-
gas: this.sdk.gasLimit
|
|
194
|
-
});
|
|
195
|
-
const rwaResults = results.slice(0, rwaAccountAddresses.length);
|
|
196
|
-
const normalResults = results.slice(rwaAccountAddresses.length);
|
|
197
|
-
const seen = new AddressSet();
|
|
198
|
-
const allCAs = [];
|
|
199
|
-
for (const ca of rwaResults) if (!seen.has(ca.creditAccount)) {
|
|
200
|
-
seen.add(ca.creditAccount);
|
|
201
|
-
allCAs.push({
|
|
202
|
-
...ca,
|
|
203
|
-
investor: borrower
|
|
204
|
-
});
|
|
205
|
-
}
|
|
206
|
-
for (const [accounts] of normalResults) for (const ca of accounts) if (!seen.has(ca.creditAccount)) {
|
|
207
|
-
seen.add(ca.creditAccount);
|
|
208
|
-
allCAs.push({
|
|
209
|
-
...ca,
|
|
210
|
-
investor: void 0
|
|
211
|
-
});
|
|
212
|
-
}
|
|
213
|
-
const filtered = allCAs.filter((ca) => {
|
|
214
|
-
if (!includeZeroDebt && ca.debt === 0n) return false;
|
|
215
|
-
if (ca.healthFactor < minHealthFactor) return false;
|
|
216
|
-
if (ca.healthFactor > maxHealthFactor) return false;
|
|
217
|
-
if (creditManager && !hexEq(ca.creditManager, creditManager)) return false;
|
|
218
|
-
return true;
|
|
219
|
-
});
|
|
220
|
-
this.logger?.debug(`loaded ${allCAs.length} borrower credit accounts (${rwaResults.length} RWA, ${filtered.length} after filter)`);
|
|
221
|
-
return filtered.sort((a, b) => Number(a.healthFactor - b.healthFactor));
|
|
49
|
+
return this.#compressor.getBorrowerCreditAccounts(borrower, options, blockNumber);
|
|
222
50
|
}
|
|
223
51
|
/**
|
|
224
52
|
* {@inheritDoc ICreditAccountsService.listPositions}
|
|
225
53
|
**/
|
|
226
54
|
async listPositions(props) {
|
|
227
|
-
|
|
228
|
-
const [accounts] = await Promise.all([this.getBorrowerCreditAccounts(owner, { includeZeroDebt }), this.sdk.withdrawalCompressor?.loadWithdrawableAssets()]);
|
|
229
|
-
const describable = accounts.filter((ca) => {
|
|
230
|
-
if (!ca.success) this.logger?.warn(`cannot describe position of ${this.labelAddress(ca.creditAccount)}: collateral computation failed`);
|
|
231
|
-
return ca.success;
|
|
232
|
-
});
|
|
233
|
-
const withdrawals = await Promise.all(describable.map((ca) => this.#accountWithdrawals(ca)));
|
|
234
|
-
return describable.map((ca, i) => this.#strategyPosition(ca, withdrawals[i] ?? new AddressMap()));
|
|
235
|
-
}
|
|
236
|
-
/**
|
|
237
|
-
* Builds one strategy position from an account snapshot.
|
|
238
|
-
*
|
|
239
|
-
* @param withdrawals - Delayed withdrawals of the account, keyed by the
|
|
240
|
-
* phantom token that represents them on it.
|
|
241
|
-
**/
|
|
242
|
-
#strategyPosition(ca, withdrawals) {
|
|
243
|
-
const suite = this.sdk.marketRegister.findCreditManager(ca.creditManager);
|
|
244
|
-
const { market } = suite;
|
|
245
|
-
const { priceOracle } = market;
|
|
246
|
-
const { pool } = market.pool;
|
|
247
|
-
const token = this.sdk.tokensMeta.mustGetToken(market.unwrappedUnderlying);
|
|
248
|
-
const totalDebtValue = ca.debt + ca.accruedInterest + ca.accruedFees;
|
|
249
|
-
const collateral = dominantCollateral(ca, market);
|
|
250
|
-
return {
|
|
251
|
-
kind: "strategy",
|
|
252
|
-
chainId: this.sdk.chainId,
|
|
253
|
-
creditManager: ca.creditManager,
|
|
254
|
-
creditAccount: ca.creditAccount,
|
|
255
|
-
name: collateral ? suite.strategyName(collateral) : token.symbol,
|
|
256
|
-
targetCollateral: collateral ? this.sdk.tokensMeta.mustGetToken(collateral) : null,
|
|
257
|
-
leverage: positionLeverage(totalDebtValue, ca.totalValue),
|
|
258
|
-
borrowApy: borrowApyBps(pool.baseInterestRate, suite.creditManager.feeInterest),
|
|
259
|
-
totalDebt: {
|
|
260
|
-
token,
|
|
261
|
-
value: totalDebtValue,
|
|
262
|
-
valueUsd: usdToNumber(ca.totalDebtUSD)
|
|
263
|
-
},
|
|
264
|
-
totalValue: {
|
|
265
|
-
token,
|
|
266
|
-
value: ca.totalValue,
|
|
267
|
-
valueUsd: usdToNumber(ca.totalValueUSD)
|
|
268
|
-
},
|
|
269
|
-
healthFactor: healthFactorBps(ca.healthFactor),
|
|
270
|
-
collaterals: ca.tokens.flatMap((t) => {
|
|
271
|
-
if ((t.mask & ca.enabledTokensMask) === 0n || t.balance <= 10n) return [];
|
|
272
|
-
return [{
|
|
273
|
-
collateral: priceOracle.toTokenAmount(t.token, t.balance),
|
|
274
|
-
quota: priceOracle.toTokenAmount(market.underlying, t.quota),
|
|
275
|
-
withdrawals: withdrawals.get(t.token) ?? []
|
|
276
|
-
}];
|
|
277
|
-
})
|
|
278
|
-
};
|
|
279
|
-
}
|
|
280
|
-
/**
|
|
281
|
-
* Delayed withdrawals of one account, keyed by the phantom token that
|
|
282
|
-
* represents them on it, so that each collateral row can pick up its own.
|
|
283
|
-
**/
|
|
284
|
-
async #accountWithdrawals(ca) {
|
|
285
|
-
const compressor = this.sdk.withdrawalCompressor;
|
|
286
|
-
const byPhantomToken = new AddressMap(void 0, "accountWithdrawals");
|
|
287
|
-
const holdsPhantomToken = ca.tokens.some((t) => t.balance > 10n && compressor?.getWithdrawalSourceToken(t.token) !== void 0);
|
|
288
|
-
if (!compressor || !holdsPhantomToken) return byPhantomToken;
|
|
289
|
-
const { priceOracle } = this.sdk.marketRegister.findByCreditManager(ca.creditManager);
|
|
290
|
-
const { claimable, pending } = await compressor.getCurrentWithdrawals(ca.creditAccount);
|
|
291
|
-
const add = (w, outputs, claimableAt) => {
|
|
292
|
-
const assets = outputs.map((o) => ({
|
|
293
|
-
isDelayed: true,
|
|
294
|
-
...priceOracle.toTokenAmount(o.token, o.amount),
|
|
295
|
-
redeemer: w.redeemer,
|
|
296
|
-
claimableAt: claimableAt === void 0 ? void 0 : Number(claimableAt)
|
|
297
|
-
}));
|
|
298
|
-
byPhantomToken.upsert(w.withdrawalPhantomToken, [...byPhantomToken.get(w.withdrawalPhantomToken) ?? [], ...assets]);
|
|
299
|
-
};
|
|
300
|
-
for (const w of claimable) add(w, w.outputs);
|
|
301
|
-
for (const w of pending) add(w, w.expectedOutputs, w.claimableAt);
|
|
302
|
-
return byPhantomToken;
|
|
55
|
+
return this.#compressor.listPositions(props);
|
|
303
56
|
}
|
|
304
57
|
/**
|
|
305
58
|
* {@inheritDoc ICreditAccountsService.getRewards}
|
|
@@ -421,7 +174,7 @@ var CreditAccountsServiceV310 = class extends SDKConstruct {
|
|
|
421
174
|
keepAssets,
|
|
422
175
|
debtOnly
|
|
423
176
|
});
|
|
424
|
-
const calls = await this
|
|
177
|
+
const calls = await this.prependPriceUpdates(account.creditManager, routerCloseResult.calls, account, { ignoreReservePrices });
|
|
425
178
|
let lossPolicyData;
|
|
426
179
|
if (applyLossPolicy) {
|
|
427
180
|
lossPolicyData = await this.sdk.marketRegister.findByCreditManager(account.creditManager).lossPolicy.getLiquidationData(account.creditAccount);
|
|
@@ -436,210 +189,28 @@ var CreditAccountsServiceV310 = class extends SDKConstruct {
|
|
|
436
189
|
};
|
|
437
190
|
}
|
|
438
191
|
/**
|
|
439
|
-
* {@inheritDoc ICreditAccountsService.defaultPartialLiquidationParams}
|
|
440
|
-
*/
|
|
441
|
-
defaultPartialLiquidationParams(ca) {
|
|
442
|
-
const tokenOut = this.#getBestTokenOut(ca);
|
|
443
|
-
const optimalHF = this.getOptimalHFForPartialLiquidation(ca);
|
|
444
|
-
const repaidAmount = this.#calcOptimalRepaidAmount(ca, tokenOut, optimalHF);
|
|
445
|
-
return {
|
|
446
|
-
tokenOut,
|
|
447
|
-
optimalHF,
|
|
448
|
-
repaidAmount,
|
|
449
|
-
minSeizedAmount: this.#calcMinSeizedAmount(ca, tokenOut, repaidAmount)
|
|
450
|
-
};
|
|
451
|
-
}
|
|
452
|
-
/**
|
|
453
192
|
* {@inheritDoc ICreditAccountsService.partiallyLiquidate}
|
|
454
193
|
*/
|
|
455
194
|
async partiallyLiquidate(props) {
|
|
456
195
|
const { account, to } = props;
|
|
457
|
-
const tokenOut = props.tokenOut ?? this.#getBestTokenOut(account);
|
|
458
|
-
const optimalHF = props.optimalHF ?? this.getOptimalHFForPartialLiquidation(account);
|
|
459
|
-
const repaidAmount = props.repaidAmount ?? this.#calcOptimalRepaidAmount(account, tokenOut, optimalHF);
|
|
460
|
-
const minSeizedAmount = props.minSeizedAmount ?? this.#calcMinSeizedAmount(account, tokenOut, repaidAmount);
|
|
461
196
|
const cm = this.sdk.marketRegister.findCreditManager(account.creditManager);
|
|
197
|
+
const { tokenOut, repaidAmount, minSeizedAmount } = cm.partialLiquidationParams(account, props);
|
|
462
198
|
const updates = await this.getOnDemandPriceUpdates(account, true);
|
|
463
199
|
return cm.creditFacade.partiallyLiquidateCreditAccount(account.creditAccount, tokenOut, repaidAmount, minSeizedAmount, to, updates);
|
|
464
200
|
}
|
|
465
201
|
/**
|
|
466
|
-
* Picks the most valuable enabled non-underlying collateral token on the
|
|
467
|
-
* credit account (by oracle value in underlying).
|
|
468
|
-
*
|
|
469
|
-
* Ported from solidity:
|
|
470
|
-
* https://github.com/Gearbox-protocol/router-v3/blob/main/contracts/liquidation/AbstractLiquidator.sol#L270
|
|
471
|
-
*/
|
|
472
|
-
#getBestTokenOut(account) {
|
|
473
|
-
const market = this.sdk.marketRegister.findByCreditManager(account.creditManager);
|
|
474
|
-
const underlying = market.underlying;
|
|
475
|
-
let bestVal = 0n;
|
|
476
|
-
let bestToken;
|
|
477
|
-
for (const t of account.tokens) {
|
|
478
|
-
if (t.token === underlying) continue;
|
|
479
|
-
if ((t.mask & account.enabledTokensMask) === 0n) continue;
|
|
480
|
-
if (t.balance === 0n) continue;
|
|
481
|
-
const val = market.priceOracle.convert(t.token, underlying, t.balance);
|
|
482
|
-
if (val > bestVal) {
|
|
483
|
-
bestVal = val;
|
|
484
|
-
bestToken = t.token;
|
|
485
|
-
}
|
|
486
|
-
}
|
|
487
|
-
if (!bestToken) throw new Error(`cannot determine tokenOut for partial liquidation of ${this.sdk.labelAddress(account.creditAccount)}: no enabled non-underlying collateral with value`);
|
|
488
|
-
return bestToken;
|
|
489
|
-
}
|
|
490
|
-
/**
|
|
491
|
-
* Returns the minimum amount of `token` collateral that must be seized when
|
|
492
|
-
* repaying `repaidAmount` of underlying. Mirrors the on-chain liquidation
|
|
493
|
-
* discount math, expired-aware.
|
|
494
|
-
*/
|
|
495
|
-
#calcMinSeizedAmount(account, token, repaidAmount) {
|
|
496
|
-
const market = this.sdk.marketRegister.findByCreditManager(account.creditManager);
|
|
497
|
-
const suite = this.sdk.marketRegister.findCreditManager(account.creditManager);
|
|
498
|
-
const fee = suite.isExpired ? suite.creditManager.liquidationDiscountExpired : suite.creditManager.liquidationDiscount;
|
|
499
|
-
return market.priceOracle.convert(market.underlying, token, repaidAmount) * 9990n / BigInt(fee);
|
|
500
|
-
}
|
|
501
|
-
/**
|
|
502
|
-
* Computes the optimal `repaidAmount` (in underlying) that brings the credit
|
|
503
|
-
* account's health factor close to `optimalHF` after partial liquidation.
|
|
504
|
-
*
|
|
505
|
-
* Ported from solidity:
|
|
506
|
-
* https://github.com/Gearbox-protocol/router-v3/blob/56e2d515ec6d9bb1e324e71c3708e59710779b24/contracts/liquidation/AbstractLiquidator.sol#L292
|
|
507
|
-
*/
|
|
508
|
-
#calcOptimalRepaidAmount(account, token, optimalHF) {
|
|
509
|
-
const suite = this.sdk.marketRegister.findCreditManager(account.creditManager);
|
|
510
|
-
const market = this.sdk.marketRegister.findByCreditManager(account.creditManager);
|
|
511
|
-
const cm = suite.creditManager;
|
|
512
|
-
const feeLiquidation = suite.isExpired ? cm.feeLiquidationExpired : cm.feeLiquidation;
|
|
513
|
-
const liquidationDiscount = suite.isExpired ? cm.liquidationDiscountExpired : cm.liquidationDiscount;
|
|
514
|
-
const discount = BigInt(liquidationDiscount) - BigInt(feeLiquidation);
|
|
515
|
-
const ltTokenOut = cm.liquidationThresholds.get(token);
|
|
516
|
-
if (ltTokenOut === void 0) throw new Error(`token ${this.sdk.labelAddress(token)} is not a collateral token in credit manager ${this.sdk.labelAddress(account.creditManager)}`);
|
|
517
|
-
const totalDebt = account.debt + account.accruedInterest + account.accruedFees;
|
|
518
|
-
const twvUnderlying = market.priceOracle.convertFromUSD(market.underlying, account.twvUSD);
|
|
519
|
-
const denominator = discount * optimalHF / PERCENTAGE_FACTOR - BigInt(ltTokenOut);
|
|
520
|
-
if (denominator <= 0n) throw new Error("cannot compute optimal repaid amount: invalid liquidation parameters (discount * hfOptimal <= ltTokenOut)");
|
|
521
|
-
const numerator = totalDebt * optimalHF - twvUnderlying * PERCENTAGE_FACTOR;
|
|
522
|
-
if (numerator <= 0n) return 0n;
|
|
523
|
-
let repaidAmount = numerator / denominator * discount / PERCENTAGE_FACTOR;
|
|
524
|
-
const minDebt = suite.creditFacade.minDebt;
|
|
525
|
-
if (totalDebt < minDebt) return 0n;
|
|
526
|
-
const surplusDebt = totalDebt - minDebt;
|
|
527
|
-
if (repaidAmount > surplusDebt) repaidAmount = surplusDebt * 999n / 1000n;
|
|
528
|
-
return repaidAmount;
|
|
529
|
-
}
|
|
530
|
-
/**
|
|
531
|
-
* {@inheritDoc ICreditAccountsService.closeCreditAccount}
|
|
532
|
-
**/
|
|
533
|
-
async closeCreditAccount({ operation, assetsToWithdraw, creditAccount: ca, to, slippage = 50n, closePath }) {
|
|
534
|
-
const cm = this.sdk.marketRegister.findCreditManager(ca.creditManager);
|
|
535
|
-
const routerCloseResult = closePath || await this.sdk.routerFor(ca).findBestClosePath({
|
|
536
|
-
creditAccount: ca,
|
|
537
|
-
creditManager: cm.creditManager,
|
|
538
|
-
slippage
|
|
539
|
-
});
|
|
540
|
-
const operationCalls = await this.assembleCloseCreditAccountCalls({
|
|
541
|
-
creditAccount: ca,
|
|
542
|
-
routerCalls: routerCloseResult.calls,
|
|
543
|
-
assetsToWithdraw,
|
|
544
|
-
to
|
|
545
|
-
});
|
|
546
|
-
const calls = operation === "close" ? operationCalls : await this.#prependPriceUpdates(ca.creditManager, operationCalls, ca);
|
|
547
|
-
return {
|
|
548
|
-
tx: await this.#closeCreditAccountTx(cm, ca.creditAccount, calls, operation),
|
|
549
|
-
calls,
|
|
550
|
-
routerCloseResult,
|
|
551
|
-
creditFacade: cm.creditFacade
|
|
552
|
-
};
|
|
553
|
-
}
|
|
554
|
-
/**
|
|
555
202
|
* {@inheritDoc ICreditAccountsService.assembleCloseCreditAccountCalls}
|
|
556
203
|
*/
|
|
557
204
|
async assembleCloseCreditAccountCalls({ creditAccount: ca, routerCalls, assetsToWithdraw, to }) {
|
|
558
|
-
const unwrapCalls = await this.
|
|
205
|
+
const unwrapCalls = await this.assembleRedeemDiffCalls(1n, ca.creditManager) ?? [];
|
|
206
|
+
const { creditFacade } = this.sdk.marketRegister.findCreditManager(ca.creditManager);
|
|
559
207
|
return [
|
|
560
208
|
...routerCalls,
|
|
561
|
-
...
|
|
562
|
-
...
|
|
563
|
-
...unwrapCalls,
|
|
564
|
-
...assetsToWithdraw.map((t) => this.prepareWithdrawToken(ca.creditFacade, t, MAX_UINT256, to))
|
|
565
|
-
];
|
|
566
|
-
}
|
|
567
|
-
/**
|
|
568
|
-
* {@inheritDoc ICreditAccountsService.updateQuotas}
|
|
569
|
-
**/
|
|
570
|
-
async updateQuotas({ minQuota, averageQuota, creditAccount }) {
|
|
571
|
-
const cm = this.sdk.marketRegister.findCreditManager(creditAccount.creditManager);
|
|
572
|
-
const operationCalls = this.prepareUpdateQuotas(creditAccount.creditFacade, {
|
|
573
|
-
minQuota,
|
|
574
|
-
averageQuota
|
|
575
|
-
});
|
|
576
|
-
const calls = await this.#prependPriceUpdates(creditAccount.creditManager, operationCalls, creditAccount);
|
|
577
|
-
return {
|
|
578
|
-
tx: await this.#multicallTx(cm, creditAccount.creditAccount, calls),
|
|
579
|
-
calls,
|
|
580
|
-
creditFacade: cm.creditFacade
|
|
581
|
-
};
|
|
582
|
-
}
|
|
583
|
-
/**
|
|
584
|
-
* {@inheritDoc ICreditAccountsService.addCollateral}
|
|
585
|
-
**/
|
|
586
|
-
async addCollateral({ creditAccount, asset, permit, ethAmount, minQuota, averageQuota }) {
|
|
587
|
-
const cm = this.sdk.marketRegister.findCreditManager(creditAccount.creditManager);
|
|
588
|
-
const operationCalls = [...this.prepareAddCollateral(creditAccount.creditFacade, [asset], permit ? { [asset.token]: permit } : {}), ...this.prepareUpdateQuotas(creditAccount.creditFacade, {
|
|
589
|
-
minQuota,
|
|
590
|
-
averageQuota
|
|
591
|
-
})];
|
|
592
|
-
const calls = await this.#prependPriceUpdates(creditAccount.creditManager, operationCalls, creditAccount);
|
|
593
|
-
const tx = await this.#multicallTx(cm, creditAccount.creditAccount, calls);
|
|
594
|
-
tx.value = ethAmount.toString(10);
|
|
595
|
-
return {
|
|
596
|
-
tx,
|
|
597
|
-
calls,
|
|
598
|
-
creditFacade: cm.creditFacade
|
|
599
|
-
};
|
|
600
|
-
}
|
|
601
|
-
/**
|
|
602
|
-
* {@inheritDoc ICreditAccountsService.changeDebt}
|
|
603
|
-
**/
|
|
604
|
-
async changeDebt({ creditAccount, amount, collateral }) {
|
|
605
|
-
if (amount === 0n) throw new Error("debt increase or decrease must be non-zero");
|
|
606
|
-
const isDecrease = amount < 0n;
|
|
607
|
-
const change = amount > 0n ? amount : -amount;
|
|
608
|
-
const cm = this.sdk.marketRegister.findCreditManager(creditAccount.creditManager);
|
|
609
|
-
const addCollateralCalls = collateral && isDecrease ? this.prepareAddCollateral(creditAccount.creditFacade, [{
|
|
610
|
-
token: collateral[0].token,
|
|
611
|
-
balance: collateral[0].balance
|
|
612
|
-
}], {}) : [];
|
|
613
|
-
const unwrapCalls = collateral && isDecrease ? await this.getRWAUnwrapCalls(collateral[0].balance, creditAccount.creditManager) || [] : [];
|
|
614
|
-
if (addCollateralCalls.length > 0 && unwrapCalls.length === 0 && collateral && collateral?.[0].token !== creditAccount.underlying) throw new Error("Can't use collateral other than underlying for non RWA market");
|
|
615
|
-
const operationCalls = [
|
|
616
|
-
...addCollateralCalls,
|
|
209
|
+
...creditFacade.prepareDisableQuotas([...ca.tokens]),
|
|
210
|
+
...ca.debt > 0n ? [creditFacade.prepareDecreaseDebtFull()] : [],
|
|
617
211
|
...unwrapCalls,
|
|
618
|
-
|
|
212
|
+
...assetsToWithdraw.map((t) => creditFacade.prepareWithdrawCollateral(t, MAX_UINT256, to))
|
|
619
213
|
];
|
|
620
|
-
const calls = await this.#prependPriceUpdates(creditAccount.creditManager, operationCalls, creditAccount);
|
|
621
|
-
return {
|
|
622
|
-
tx: await this.#multicallTx(cm, creditAccount.creditAccount, calls),
|
|
623
|
-
calls,
|
|
624
|
-
creditFacade: cm.creditFacade
|
|
625
|
-
};
|
|
626
|
-
}
|
|
627
|
-
/**
|
|
628
|
-
* {@inheritDoc ICreditAccountsService.executeSwap}
|
|
629
|
-
**/
|
|
630
|
-
async executeSwap({ creditAccount, calls: swapCalls, minQuota, averageQuota }) {
|
|
631
|
-
if (swapCalls.length === 0) throw new Error("No path to execute");
|
|
632
|
-
const cm = this.sdk.marketRegister.findCreditManager(creditAccount.creditManager);
|
|
633
|
-
const operationCalls = [...swapCalls, ...this.prepareUpdateQuotas(creditAccount.creditFacade, {
|
|
634
|
-
minQuota,
|
|
635
|
-
averageQuota
|
|
636
|
-
})];
|
|
637
|
-
const calls = await this.#prependPriceUpdates(creditAccount.creditManager, operationCalls, creditAccount);
|
|
638
|
-
return {
|
|
639
|
-
tx: await this.#multicallTx(cm, creditAccount.creditAccount, calls),
|
|
640
|
-
calls,
|
|
641
|
-
creditFacade: cm.creditFacade
|
|
642
|
-
};
|
|
643
214
|
}
|
|
644
215
|
/**
|
|
645
216
|
* {@inheritDoc ICreditAccountsService.previewDelayedWithdrawal}
|
|
@@ -664,25 +235,6 @@ var CreditAccountsServiceV310 = class extends SDKConstruct {
|
|
|
664
235
|
};
|
|
665
236
|
}
|
|
666
237
|
/**
|
|
667
|
-
* {@inheritDoc ICreditAccountsService.startDelayedWithdrawal}
|
|
668
|
-
**/
|
|
669
|
-
async startDelayedWithdrawal({ creditAccount, minQuota, averageQuota, preview }) {
|
|
670
|
-
const cm = this.sdk.marketRegister.findCreditManager(creditAccount.creditManager);
|
|
671
|
-
const operationCalls = [...this.assembleStartDelayedWithdrawalCalls({
|
|
672
|
-
creditFacade: cm.creditFacade.address,
|
|
673
|
-
preview
|
|
674
|
-
}), ...this.prepareUpdateQuotas(cm.creditFacade.address, {
|
|
675
|
-
minQuota,
|
|
676
|
-
averageQuota
|
|
677
|
-
})];
|
|
678
|
-
const calls = await this.#prependPriceUpdates(creditAccount.creditManager, operationCalls, creditAccount);
|
|
679
|
-
return {
|
|
680
|
-
tx: await this.#multicallTx(cm, creditAccount.creditAccount, calls),
|
|
681
|
-
calls,
|
|
682
|
-
creditFacade: cm.creditFacade
|
|
683
|
-
};
|
|
684
|
-
}
|
|
685
|
-
/**
|
|
686
238
|
* {@inheritDoc ICreditAccountsService.assembleStartDelayedWithdrawalCalls}
|
|
687
239
|
**/
|
|
688
240
|
assembleStartDelayedWithdrawalCalls({ creditFacade, preview }) {
|
|
@@ -699,50 +251,14 @@ var CreditAccountsServiceV310 = class extends SDKConstruct {
|
|
|
699
251
|
token: preview.token,
|
|
700
252
|
amount: -preview.amountIn
|
|
701
253
|
});
|
|
702
|
-
const
|
|
703
|
-
target: creditFacade,
|
|
704
|
-
callData: encodeFunctionData({
|
|
705
|
-
abi: iCreditFacadeMulticallV310Abi,
|
|
706
|
-
functionName: "storeExpectedBalances",
|
|
707
|
-
args: [deltas]
|
|
708
|
-
})
|
|
709
|
-
};
|
|
710
|
-
const compareBalances = {
|
|
711
|
-
target: creditFacade,
|
|
712
|
-
callData: encodeFunctionData({
|
|
713
|
-
abi: iCreditFacadeMulticallV310Abi,
|
|
714
|
-
functionName: "compareBalances",
|
|
715
|
-
args: []
|
|
716
|
-
})
|
|
717
|
-
};
|
|
254
|
+
const facade = this.sdk.marketRegister.findCreditFacade(creditFacade);
|
|
718
255
|
return [
|
|
719
|
-
|
|
256
|
+
facade.prepareStoreExpectedBalances(deltas),
|
|
720
257
|
...preview.requestCalls,
|
|
721
|
-
|
|
258
|
+
facade.prepareCompareBalances()
|
|
722
259
|
];
|
|
723
260
|
}
|
|
724
261
|
/**
|
|
725
|
-
* {@inheritDoc ICreditAccountsService.claimDelayed}
|
|
726
|
-
**/
|
|
727
|
-
async claimDelayed({ creditAccount, minQuota, averageQuota, claimableNow }) {
|
|
728
|
-
const zeroDebt = creditAccount.debt === 0n;
|
|
729
|
-
const cm = this.sdk.marketRegister.findCreditManager(creditAccount.creditManager);
|
|
730
|
-
const quotaCalls = zeroDebt ? [] : this.prepareUpdateQuotas(cm.creditFacade.address, {
|
|
731
|
-
minQuota,
|
|
732
|
-
averageQuota
|
|
733
|
-
});
|
|
734
|
-
const operationCalls = [...this.assembleClaimDelayedCalls({
|
|
735
|
-
creditFacade: cm.creditFacade.address,
|
|
736
|
-
claimableNow
|
|
737
|
-
}), ...quotaCalls];
|
|
738
|
-
const calls = zeroDebt ? operationCalls : await this.#prependPriceUpdates(creditAccount.creditManager, operationCalls, creditAccount);
|
|
739
|
-
return {
|
|
740
|
-
tx: await this.#multicallTx(cm, creditAccount.creditAccount, calls),
|
|
741
|
-
calls,
|
|
742
|
-
creditFacade: cm.creditFacade
|
|
743
|
-
};
|
|
744
|
-
}
|
|
745
|
-
/**
|
|
746
262
|
* {@inheritDoc ICreditAccountsService.assembleClaimDelayedCalls}
|
|
747
263
|
**/
|
|
748
264
|
assembleClaimDelayedCalls({ creditFacade, claimableNow }) {
|
|
@@ -759,26 +275,11 @@ var CreditAccountsServiceV310 = class extends SDKConstruct {
|
|
|
759
275
|
token: claimableNow.withdrawalPhantomToken,
|
|
760
276
|
amount: -claimableNow.withdrawalTokenSpent
|
|
761
277
|
});
|
|
762
|
-
const
|
|
763
|
-
target: creditFacade,
|
|
764
|
-
callData: encodeFunctionData({
|
|
765
|
-
abi: iCreditFacadeMulticallV310Abi,
|
|
766
|
-
functionName: "storeExpectedBalances",
|
|
767
|
-
args: [deltas]
|
|
768
|
-
})
|
|
769
|
-
};
|
|
770
|
-
const compareBalances = {
|
|
771
|
-
target: creditFacade,
|
|
772
|
-
callData: encodeFunctionData({
|
|
773
|
-
abi: iCreditFacadeMulticallV310Abi,
|
|
774
|
-
functionName: "compareBalances",
|
|
775
|
-
args: []
|
|
776
|
-
})
|
|
777
|
-
};
|
|
278
|
+
const facade = this.sdk.marketRegister.findCreditFacade(creditFacade);
|
|
778
279
|
return [
|
|
779
|
-
|
|
280
|
+
facade.prepareStoreExpectedBalances(deltas),
|
|
780
281
|
...claimableNow.claimCalls,
|
|
781
|
-
|
|
282
|
+
facade.prepareCompareBalances()
|
|
782
283
|
];
|
|
783
284
|
}
|
|
784
285
|
/**
|
|
@@ -809,185 +310,94 @@ var CreditAccountsServiceV310 = class extends SDKConstruct {
|
|
|
809
310
|
let tokenToWithdraw;
|
|
810
311
|
if (withdrawToken === true) tokenToWithdraw = cm.underlying;
|
|
811
312
|
else if (typeof withdrawToken === "string") tokenToWithdraw = withdrawToken;
|
|
313
|
+
const { creditFacade } = cmSuite;
|
|
812
314
|
const operationCalls = [
|
|
813
|
-
|
|
814
|
-
...
|
|
315
|
+
creditFacade.prepareIncreaseDebt(debt),
|
|
316
|
+
...creditFacade.prepareAddCollateral(collateral, permits),
|
|
815
317
|
...openPathCalls,
|
|
816
|
-
...tokenToWithdraw ? [
|
|
817
|
-
...
|
|
318
|
+
...tokenToWithdraw ? [creditFacade.prepareWithdrawCollateral(tokenToWithdraw, MAX_UINT256, to)] : [],
|
|
319
|
+
...creditFacade.prepareUpdateQuotas({
|
|
818
320
|
minQuota,
|
|
819
321
|
averageQuota
|
|
820
322
|
}),
|
|
821
323
|
...callsAfter ?? []
|
|
822
324
|
];
|
|
823
|
-
const calls = await this
|
|
325
|
+
const calls = await this.prependPriceUpdates(cm.address, operationCalls);
|
|
824
326
|
let tx;
|
|
825
327
|
if (reopenCreditAccount) tx = await this.#multicallTx(cmSuite, reopenCreditAccount, calls);
|
|
826
328
|
else tx = await this.#openCreditAccountTx(cmSuite, to, calls, referralCode, rwaOptions);
|
|
827
329
|
tx.value = ethAmount.toString(10);
|
|
828
|
-
return
|
|
829
|
-
calls,
|
|
830
|
-
tx,
|
|
831
|
-
creditFacade: cmSuite.creditFacade
|
|
832
|
-
};
|
|
833
|
-
}
|
|
834
|
-
/**
|
|
835
|
-
* {@inheritDoc ICreditAccountsService.getBorrowRate}
|
|
836
|
-
**/
|
|
837
|
-
getBorrowRate(ca) {
|
|
838
|
-
const { creditManager } = this.sdk.marketRegister.findCreditManager(ca.creditManager);
|
|
839
|
-
const { pool } = this.sdk.marketRegister.findByCreditManager(ca.creditManager);
|
|
840
|
-
const { feeInterest } = creditManager;
|
|
841
|
-
const { baseInterestRate } = pool.pool;
|
|
842
|
-
const baseRateWithFee = baseInterestRate * (BigInt(feeInterest) + PERCENTAGE_FACTOR);
|
|
843
|
-
const totalDebt = ca.debt + ca.accruedInterest + ca.accruedFees;
|
|
844
|
-
const r = ca.debt * baseRateWithFee / (totalDebt * RAY);
|
|
845
|
-
const caTokens = new AddressMap(ca.tokens.map((t) => [t.token, t]));
|
|
846
|
-
let qr = 0n;
|
|
847
|
-
for (const t of creditManager.collateralTokens) {
|
|
848
|
-
const b = caTokens.get(t);
|
|
849
|
-
if (b) qr += b.quota * BigInt(pool.pqk.quotas.get(t)?.rate ?? 0);
|
|
850
|
-
}
|
|
851
|
-
qr = qr * (BigInt(feeInterest) + PERCENTAGE_FACTOR) / PERCENTAGE_FACTOR;
|
|
852
|
-
qr /= totalDebt;
|
|
853
|
-
return r + qr;
|
|
854
|
-
}
|
|
855
|
-
/**
|
|
856
|
-
* {@inheritDoc ICreditAccountsService.getOptimalHFForPartialLiquidation}
|
|
857
|
-
**/
|
|
858
|
-
getOptimalHFForPartialLiquidation(ca) {
|
|
859
|
-
const borrowRate = this.getBorrowRate(ca);
|
|
860
|
-
return PERCENTAGE_FACTOR + (borrowRate < 100n ? borrowRate : 100n);
|
|
861
|
-
}
|
|
862
|
-
/**
|
|
863
|
-
* Internal wrapper for CreditAccountCompressor.getCreditAccounts + price updates wrapped into multicall
|
|
864
|
-
* @param args
|
|
865
|
-
* @param priceUpdateTxs
|
|
866
|
-
* @param blockNumber
|
|
867
|
-
* @returns
|
|
868
|
-
*/
|
|
869
|
-
async #getCreditAccounts(args, priceUpdateTxs, blockNumber) {
|
|
870
|
-
let resp;
|
|
871
|
-
if (priceUpdateTxs?.length) [resp] = await simulateWithPriceUpdates(this.client, {
|
|
872
|
-
priceUpdates: priceUpdateTxs,
|
|
873
|
-
contracts: [{
|
|
874
|
-
abi: creditAccountCompressorAbi,
|
|
875
|
-
address: this.compressor,
|
|
876
|
-
functionName: "getCreditAccounts",
|
|
877
|
-
args
|
|
878
|
-
}],
|
|
879
|
-
blockNumber,
|
|
880
|
-
gas: this.sdk.gasLimit
|
|
881
|
-
});
|
|
882
|
-
else resp = await this.client.readContract({
|
|
883
|
-
abi: creditAccountCompressorAbi,
|
|
884
|
-
address: this.compressor,
|
|
885
|
-
functionName: "getCreditAccounts",
|
|
886
|
-
args,
|
|
887
|
-
blockNumber,
|
|
888
|
-
gas: this.sdk.gasLimit
|
|
889
|
-
});
|
|
890
|
-
this.logger?.debug({
|
|
891
|
-
accounts: resp[0]?.length ?? 0,
|
|
892
|
-
nextOffset: Number(resp[1])
|
|
893
|
-
}, "got credit accounts");
|
|
894
|
-
return resp;
|
|
330
|
+
return tx;
|
|
895
331
|
}
|
|
896
332
|
/**
|
|
897
|
-
*
|
|
898
|
-
*
|
|
899
|
-
*
|
|
900
|
-
* @param amount -
|
|
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
|
|
901
337
|
* @param creditManager - Credit manager address
|
|
902
|
-
* @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
|
|
903
340
|
*/
|
|
904
|
-
|
|
341
|
+
#rwaVaultCalls(functionName, amount, creditManager) {
|
|
905
342
|
const suite = this.sdk.marketRegister.findCreditManager(creditManager);
|
|
906
343
|
const meta = this.sdk.tokensMeta.mustGet(suite.underlying);
|
|
907
344
|
if (!this.sdk.tokensMeta.isRWAUnderlying(meta)) return;
|
|
908
|
-
const
|
|
909
|
-
if (!
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
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({
|
|
913
368
|
abi: ierc4626AdapterAbi,
|
|
914
|
-
functionName
|
|
915
|
-
args: [
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
369
|
+
functionName,
|
|
370
|
+
args: [amount]
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
return [{
|
|
374
|
+
target,
|
|
375
|
+
callData
|
|
921
376
|
}];
|
|
922
377
|
}
|
|
923
378
|
/**
|
|
924
|
-
*
|
|
925
|
-
* Used when adding debt on a RWA market: deposits underlying into the adapter vault so shares are minted on the account.
|
|
926
|
-
* Only applies when the credit manager's underlying is RWA-gated and has an ERC-4626 adapter configured.
|
|
927
|
-
* @param amount - Amount of underlying assets to deposit into the vault (in underlying decimals)
|
|
928
|
-
* @param creditManager - Credit manager address
|
|
929
|
-
* @returns Array of MultiCall to pass to credit facade multicall, or undefined if underlying is not RWA or no adapter is configured
|
|
379
|
+
* {@inheritDoc ICreditAccountsService.assembleRWAUnwrapCalls}
|
|
930
380
|
*/
|
|
931
|
-
async
|
|
932
|
-
|
|
933
|
-
const meta = this.sdk.tokensMeta.mustGet(suite.underlying);
|
|
934
|
-
if (!this.sdk.tokensMeta.isRWAUnderlying(meta)) return;
|
|
935
|
-
const adapterAddress = suite.creditManager.adapters.get(meta.addr)?.address;
|
|
936
|
-
if (!adapterAddress) return;
|
|
937
|
-
return [{
|
|
938
|
-
target: adapterAddress,
|
|
939
|
-
callData: encodeFunctionData({
|
|
940
|
-
abi: ierc4626AdapterAbi,
|
|
941
|
-
functionName: "deposit",
|
|
942
|
-
args: [amount, ADDRESS_0X0]
|
|
943
|
-
})
|
|
944
|
-
}];
|
|
381
|
+
async assembleRWAUnwrapCalls(amount, creditManager) {
|
|
382
|
+
return this.#rwaVaultCalls("redeem", amount, creditManager);
|
|
945
383
|
}
|
|
946
384
|
/**
|
|
947
|
-
*
|
|
948
|
-
* Redeems the leftover vault shares (e.g. after repaying debt) so the account does not hold excess RWA vault tokens.
|
|
949
|
-
* Only applies when the credit manager's underlying is RWA-gated and has an ERC-4626 adapter configured.
|
|
950
|
-
* @param amount - Leftover vault share amount to redeem (in adapter/vault decimals)
|
|
951
|
-
* @param creditManager - Credit manager address
|
|
952
|
-
* @returns Array of MultiCall to pass to credit facade multicall, or undefined if underlying is not RWA or no adapter is configured
|
|
385
|
+
* {@inheritDoc ICreditAccountsService.assembleRWAWrapCalls}
|
|
953
386
|
*/
|
|
954
|
-
async
|
|
955
|
-
|
|
956
|
-
const meta = this.sdk.tokensMeta.mustGet(suite.underlying);
|
|
957
|
-
if (!this.sdk.tokensMeta.isRWAUnderlying(meta)) return;
|
|
958
|
-
const adapterAddress = suite.creditManager.adapters.get(meta.addr)?.address;
|
|
959
|
-
if (!adapterAddress) return;
|
|
960
|
-
return [{
|
|
961
|
-
target: adapterAddress,
|
|
962
|
-
callData: encodeFunctionData({
|
|
963
|
-
abi: ierc4626AdapterAbi,
|
|
964
|
-
functionName: "redeemDiff",
|
|
965
|
-
args: [amount]
|
|
966
|
-
})
|
|
967
|
-
}];
|
|
387
|
+
async assembleRWAWrapCalls(amount, creditManager) {
|
|
388
|
+
return this.#rwaVaultCalls("deposit", amount, creditManager);
|
|
968
389
|
}
|
|
969
390
|
/**
|
|
970
|
-
*
|
|
971
|
-
* Deposits the leftover underlying (e.g. after decreasing debt) into the vault so the account does not hold excess underlying.
|
|
972
|
-
* Only applies when the credit manager's underlying is RWA-gated and has an ERC-4626 adapter configured.
|
|
973
|
-
* @param amount - Leftover underlying amount to deposit into the vault (in underlying decimals)
|
|
974
|
-
* @param creditManager - Credit manager address
|
|
975
|
-
* @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}
|
|
976
392
|
*/
|
|
977
|
-
async
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
callData: encodeFunctionData({
|
|
986
|
-
abi: ierc4626AdapterAbi,
|
|
987
|
-
functionName: "depositDiff",
|
|
988
|
-
args: [amount]
|
|
989
|
-
})
|
|
990
|
-
}];
|
|
393
|
+
async assembleRedeemDiffCalls(amount, creditManager) {
|
|
394
|
+
return this.#rwaVaultCalls("redeemDiff", amount, creditManager);
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* {@inheritDoc ICreditAccountsService.assembleDepositDiffCalls}
|
|
398
|
+
*/
|
|
399
|
+
async assembleDepositDiffCalls(amount, creditManager) {
|
|
400
|
+
return this.#rwaVaultCalls("depositDiff", amount, creditManager);
|
|
991
401
|
}
|
|
992
402
|
/**
|
|
993
403
|
* {@inheritDoc ICreditAccountsService.setBot}
|
|
@@ -1009,15 +419,8 @@ var CreditAccountsServiceV310 = class extends SDKConstruct {
|
|
|
1009
419
|
stateMutability: "view"
|
|
1010
420
|
}]
|
|
1011
421
|
}).read.requiredPermissions();
|
|
1012
|
-
const addBotCall =
|
|
1013
|
-
|
|
1014
|
-
callData: encodeFunctionData({
|
|
1015
|
-
abi: iCreditFacadeMulticallV310Abi,
|
|
1016
|
-
functionName: "setBotPermissions",
|
|
1017
|
-
args: [botAddress, permissions]
|
|
1018
|
-
})
|
|
1019
|
-
};
|
|
1020
|
-
const calls = targetContract.type === "creditAccount" ? await this.#prependPriceUpdates(targetContract.creditManager, [addBotCall], targetContract) : [addBotCall];
|
|
422
|
+
const addBotCall = cm.creditFacade.prepareSetBotPermissions(botAddress, permissions);
|
|
423
|
+
const calls = targetContract.type === "creditAccount" ? await this.prependPriceUpdates(targetContract.creditManager, [addBotCall], targetContract) : [addBotCall];
|
|
1021
424
|
return {
|
|
1022
425
|
tx: targetContract.type === "creditAccount" ? await this.#multicallTx(cm, targetContract.creditAccount, calls) : void 0,
|
|
1023
426
|
calls,
|
|
@@ -1025,79 +428,26 @@ var CreditAccountsServiceV310 = class extends SDKConstruct {
|
|
|
1025
428
|
};
|
|
1026
429
|
}
|
|
1027
430
|
/**
|
|
1028
|
-
* {@inheritDoc ICreditAccountsService.withdrawCollateral}
|
|
1029
|
-
*/
|
|
1030
|
-
async withdrawCollateral({ creditAccount, assetsToWithdraw, to, minQuota, averageQuota }) {
|
|
1031
|
-
const cm = this.sdk.marketRegister.findCreditManager(creditAccount.creditManager);
|
|
1032
|
-
const operationCalls = [...assetsToWithdraw.map((a) => this.prepareWithdrawToken(cm.creditFacade.address, a.token, a.balance, to)), ...this.prepareUpdateQuotas(cm.creditFacade.address, {
|
|
1033
|
-
minQuota,
|
|
1034
|
-
averageQuota
|
|
1035
|
-
})];
|
|
1036
|
-
const calls = await this.#prependPriceUpdates(creditAccount.creditManager, operationCalls, creditAccount);
|
|
1037
|
-
return {
|
|
1038
|
-
tx: await this.#multicallTx(cm, creditAccount.creditAccount, calls),
|
|
1039
|
-
calls,
|
|
1040
|
-
creditFacade: cm.creditFacade
|
|
1041
|
-
};
|
|
1042
|
-
}
|
|
1043
|
-
/**
|
|
1044
|
-
* {@inheritDoc ICreditAccountsService.repayCreditAccount}
|
|
1045
|
-
*/
|
|
1046
|
-
async repayCreditAccount(props) {
|
|
1047
|
-
const { operation, creditAccount: ca } = props;
|
|
1048
|
-
const cm = this.sdk.marketRegister.findCreditManager(ca.creditManager);
|
|
1049
|
-
const operationCalls = await this.assembleRepayCreditAccountCalls(props);
|
|
1050
|
-
const calls = operation === "close" ? operationCalls : await this.#prependPriceUpdates(ca.creditManager, operationCalls, ca);
|
|
1051
|
-
return {
|
|
1052
|
-
tx: await this.#closeCreditAccountTx(cm, ca.creditAccount, calls, operation),
|
|
1053
|
-
calls,
|
|
1054
|
-
creditFacade: cm.creditFacade
|
|
1055
|
-
};
|
|
1056
|
-
}
|
|
1057
|
-
/**
|
|
1058
431
|
* {@inheritDoc ICreditAccountsService.assembleRepayCreditAccountCalls}
|
|
1059
432
|
*/
|
|
1060
433
|
async assembleRepayCreditAccountCalls({ collateralAssets, assetsToWithdraw, creditAccount: ca, permits, to, tokensToClaim, calls: wrapCalls = [] }) {
|
|
1061
434
|
const addCollateral = collateralAssets.filter((a) => a.balance > 0);
|
|
1062
435
|
const router = this.sdk.routerFor(ca);
|
|
1063
|
-
const unwrapCalls = await this.
|
|
436
|
+
const unwrapCalls = await this.assembleRedeemDiffCalls(1n, ca.creditManager) ?? [];
|
|
1064
437
|
const claimPath = await router.findClaimAllRewards({
|
|
1065
438
|
tokensToClaim,
|
|
1066
439
|
creditAccount: ca
|
|
1067
440
|
});
|
|
441
|
+
const { creditFacade } = this.sdk.marketRegister.findCreditManager(ca.creditManager);
|
|
1068
442
|
return [
|
|
1069
|
-
...
|
|
443
|
+
...creditFacade.prepareAddCollateral(addCollateral, permits),
|
|
1070
444
|
...wrapCalls,
|
|
1071
|
-
...
|
|
1072
|
-
...
|
|
445
|
+
...creditFacade.prepareDisableQuotas([...ca.tokens]),
|
|
446
|
+
...ca.debt > 0n ? [creditFacade.prepareDecreaseDebtFull()] : [],
|
|
1073
447
|
...unwrapCalls,
|
|
1074
448
|
...claimPath.calls,
|
|
1075
|
-
...assetsToWithdraw.map((t) =>
|
|
1076
|
-
];
|
|
1077
|
-
}
|
|
1078
|
-
/**
|
|
1079
|
-
* {@inheritDoc ICreditAccountsService.repayAndLiquidateCreditAccount}
|
|
1080
|
-
*/
|
|
1081
|
-
async repayAndLiquidateCreditAccount({ collateralAssets, assetsToWithdraw, creditAccount: ca, permits, to, tokensToClaim }) {
|
|
1082
|
-
const cm = this.sdk.marketRegister.findCreditManager(ca.creditManager);
|
|
1083
|
-
const claimPath = await this.sdk.routerFor(ca).findClaimAllRewards({
|
|
1084
|
-
tokensToClaim,
|
|
1085
|
-
creditAccount: ca
|
|
1086
|
-
});
|
|
1087
|
-
const wrapCalls = await this.getDepositDiffCalls(1n, ca.creditManager) ?? [];
|
|
1088
|
-
const addCollateral = collateralAssets.filter((a) => a.balance > 0);
|
|
1089
|
-
const operationCalls = [
|
|
1090
|
-
...this.prepareAddCollateral(ca.creditFacade, addCollateral, permits),
|
|
1091
|
-
...claimPath.calls,
|
|
1092
|
-
...wrapCalls,
|
|
1093
|
-
...assetsToWithdraw.map((t) => this.prepareWithdrawToken(ca.creditFacade, t.token, MAX_UINT256, to))
|
|
449
|
+
...assetsToWithdraw.map((t) => creditFacade.prepareWithdrawCollateral(t.token, MAX_UINT256, to))
|
|
1094
450
|
];
|
|
1095
|
-
const calls = await this.#prependPriceUpdates(ca.creditManager, operationCalls, ca);
|
|
1096
|
-
return {
|
|
1097
|
-
tx: cm.creditFacade.liquidateCreditAccount(ca.creditAccount, to, calls),
|
|
1098
|
-
calls,
|
|
1099
|
-
creditFacade: cm.creditFacade
|
|
1100
|
-
};
|
|
1101
451
|
}
|
|
1102
452
|
/**
|
|
1103
453
|
* {@inheritDoc ICreditAccountsService.claimFarmRewards}
|
|
@@ -1112,138 +462,59 @@ var CreditAccountsServiceV310 = class extends SDKConstruct {
|
|
|
1112
462
|
creditAccount: ca
|
|
1113
463
|
});
|
|
1114
464
|
if (claimPath.calls.length === 0) throw new Error("No path to execute");
|
|
1115
|
-
const operationCalls = [...claimPath.calls, ...
|
|
465
|
+
const operationCalls = [...claimPath.calls, ...cm.creditFacade.prepareUpdateQuotas({
|
|
1116
466
|
minQuota,
|
|
1117
467
|
averageQuota
|
|
1118
468
|
})];
|
|
1119
|
-
const calls = await this
|
|
1120
|
-
return
|
|
1121
|
-
tx: await this.#multicallTx(cm, ca.creditAccount, calls),
|
|
1122
|
-
calls,
|
|
1123
|
-
creditFacade: cm.creditFacade
|
|
1124
|
-
};
|
|
469
|
+
const calls = await this.prependPriceUpdates(ca.creditManager, operationCalls, ca);
|
|
470
|
+
return await this.#multicallTx(cm, ca.creditAccount, calls);
|
|
1125
471
|
}
|
|
1126
472
|
/**
|
|
1127
473
|
* Returns raw txs that are needed to update all price feeds so that all credit accounts (possibly from different markets) compute
|
|
1128
474
|
* {@inheritDoc ICreditAccountsService.getOnDemandPriceUpdates}
|
|
1129
475
|
**/
|
|
1130
476
|
async getOnDemandPriceUpdates(account, ignoreReservePrices) {
|
|
1131
|
-
const {
|
|
1132
|
-
|
|
1133
|
-
const update = await this.#getUpdateForAccount(account, ignoreReservePrices);
|
|
1134
|
-
this.logger?.debug({
|
|
1135
|
-
account: creditAccount,
|
|
1136
|
-
manager: cm.name
|
|
1137
|
-
}, `getting on demand price updates from ${update.txs.length} txs`);
|
|
1138
|
-
return getRawPriceUpdates(update);
|
|
477
|
+
const { priceOracle } = this.sdk.marketRegister.findByCreditManager(account.creditManager);
|
|
478
|
+
return priceOracle.priceUpdatesForAccount(account, { reserve: !ignoreReservePrices });
|
|
1139
479
|
}
|
|
1140
480
|
/**
|
|
1141
|
-
*
|
|
1142
|
-
*
|
|
1143
|
-
* Deduplicates existing `onDemandPriceUpdates` calls
|
|
1144
|
-
*
|
|
1145
|
-
* @param creditManager - Address of the credit manager
|
|
1146
|
-
* @param calls - The multicall array to prepend price updates to
|
|
1147
|
-
* @param ca - Credit account slice, undefined when opening a new account
|
|
1148
|
-
* @param options - Optional settings for price update generation
|
|
1149
|
-
* @returns A new array with a single consolidated price update call prepended,
|
|
1150
|
-
* followed by the non-price-update calls in their original order
|
|
481
|
+
* {@inheritDoc ICreditAccountsService.prependPriceUpdates}
|
|
1151
482
|
*/
|
|
1152
|
-
async
|
|
1153
|
-
const
|
|
1154
|
-
const
|
|
483
|
+
async prependPriceUpdates(creditManager, calls, creditAccount, options) {
|
|
484
|
+
const { priceOracle } = this.sdk.marketRegister.findByCreditManager(creditManager);
|
|
485
|
+
const suite = this.sdk.marketRegister.findCreditManager(creditManager);
|
|
1155
486
|
const { priceUpdates: existingUpdates, remainingCalls } = extractPriceUpdates(calls);
|
|
1156
|
-
const
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
}
|
|
1161
|
-
const
|
|
1162
|
-
const priceFeeds = market.priceOracle.priceFeedsForTokens(Array.from(tokens), {
|
|
1163
|
-
main: true,
|
|
1164
|
-
reserve: !ignoreReservePrices
|
|
1165
|
-
});
|
|
1166
|
-
const tStr = tokens.map((t) => this.labelAddress(t)).join(", ");
|
|
1167
|
-
const remark = ignoreReservePrices ? " main" : "";
|
|
1168
|
-
this.logger?.debug({
|
|
1169
|
-
account: ca?.creditAccount,
|
|
1170
|
-
manager: cm.name
|
|
1171
|
-
}, `prependPriceUpdates for ${tStr} from ${priceFeeds.length}${remark} price feeds`);
|
|
1172
|
-
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);
|
|
1173
493
|
const merged = mergePriceUpdates(existingUpdates, generatedUpdates);
|
|
1174
494
|
if (merged.length === 0) return remainingCalls;
|
|
1175
|
-
return [
|
|
1176
|
-
target: cm.creditFacade,
|
|
1177
|
-
callData: encodeFunctionData({
|
|
1178
|
-
abi: iCreditFacadeMulticallV310Abi,
|
|
1179
|
-
functionName: "onDemandPriceUpdates",
|
|
1180
|
-
args: [merged]
|
|
1181
|
-
})
|
|
1182
|
-
}, ...remainingCalls];
|
|
1183
|
-
}
|
|
1184
|
-
async #getUpdateForAccount(account, ignoreReservePrices) {
|
|
1185
|
-
const { creditManager, creditAccount, enabledTokensMask } = account;
|
|
1186
|
-
const market = this.sdk.marketRegister.findByCreditManager(creditManager);
|
|
1187
|
-
const cm = this.sdk.marketRegister.findCreditManager(creditManager).creditManager;
|
|
1188
|
-
const tokens = new AddressSet([cm.underlying]);
|
|
1189
|
-
for (const t of account.tokens) {
|
|
1190
|
-
const isEnabled = (t.mask & enabledTokensMask) !== 0n;
|
|
1191
|
-
if (t.balance > 10n && isEnabled) tokens.add(t.token);
|
|
1192
|
-
}
|
|
1193
|
-
const priceFeeds = market.priceOracle.priceFeedsForTokens(Array.from(tokens), {
|
|
1194
|
-
main: true,
|
|
1195
|
-
reserve: !ignoreReservePrices
|
|
1196
|
-
});
|
|
1197
|
-
const tStr = tokens.map((t) => this.labelAddress(t)).join(", ");
|
|
1198
|
-
const remark = ignoreReservePrices ? " main" : "";
|
|
1199
|
-
this.logger?.debug({
|
|
1200
|
-
account: creditAccount,
|
|
1201
|
-
manager: cm.name
|
|
1202
|
-
}, `generating price feed updates for ${tStr} from ${priceFeeds.length}${remark} price feeds`);
|
|
1203
|
-
return this.sdk.priceFeeds.generatePriceFeedsUpdateTxs(priceFeeds);
|
|
1204
|
-
}
|
|
1205
|
-
/**
|
|
1206
|
-
* {@inheritDoc ICreditAccountsService.multicall}
|
|
1207
|
-
*/
|
|
1208
|
-
async multicall(creditAccount, calls, options) {
|
|
1209
|
-
const cm = this.sdk.marketRegister.findCreditManager(creditAccount.creditManager);
|
|
1210
|
-
const callsWithPrices = await this.#prependPriceUpdates(creditAccount.creditManager, calls, creditAccount, options);
|
|
1211
|
-
return cm.creditFacade.multicall(creditAccount.creditAccount, callsWithPrices);
|
|
1212
|
-
}
|
|
1213
|
-
/**
|
|
1214
|
-
* {@inheritDoc ICreditAccountsService.botMulticall}
|
|
1215
|
-
*/
|
|
1216
|
-
async botMulticall(creditAccount, calls, options) {
|
|
1217
|
-
const cm = this.sdk.marketRegister.findCreditManager(creditAccount.creditManager);
|
|
1218
|
-
const callsWithPrices = await this.#prependPriceUpdates(creditAccount.creditManager, calls, creditAccount, options);
|
|
1219
|
-
return cm.creditFacade.botMulticall(creditAccount.creditAccount, callsWithPrices);
|
|
1220
|
-
}
|
|
1221
|
-
/**
|
|
1222
|
-
* {@inheritDoc ICreditAccountsService.prependPriceUpdates}
|
|
1223
|
-
*/
|
|
1224
|
-
async prependPriceUpdates(creditManager, calls, creditAccount, options) {
|
|
1225
|
-
return this.#prependPriceUpdates(creditManager, calls, creditAccount, options);
|
|
495
|
+
return [suite.creditFacade.prepareOnDemandPriceUpdates(merged), ...remainingCalls];
|
|
1226
496
|
}
|
|
1227
497
|
/**
|
|
1228
498
|
* {@inheritDoc ICreditAccountsService.assembleCaOperations}
|
|
1229
499
|
*/
|
|
1230
500
|
assembleCaOperations({ operations, creditFacade }) {
|
|
501
|
+
const facade = this.sdk.marketRegister.findCreditFacade(creditFacade);
|
|
1231
502
|
const calls = [];
|
|
1232
503
|
for (const op of operations) switch (op.type) {
|
|
1233
504
|
case "increaseDebt":
|
|
1234
|
-
calls.push(
|
|
505
|
+
calls.push(facade.prepareIncreaseDebt(op.amount));
|
|
1235
506
|
break;
|
|
1236
507
|
case "decreaseDebt":
|
|
1237
|
-
calls.push(
|
|
508
|
+
calls.push(facade.prepareChangeDebt(op.amount, true));
|
|
1238
509
|
break;
|
|
1239
510
|
case "addCollateral":
|
|
1240
|
-
calls.push(...
|
|
511
|
+
calls.push(...facade.prepareAddCollateral([{
|
|
1241
512
|
token: op.token,
|
|
1242
513
|
balance: op.amount
|
|
1243
514
|
}], {}));
|
|
1244
515
|
break;
|
|
1245
516
|
case "withdrawCollateral":
|
|
1246
|
-
calls.push(
|
|
517
|
+
calls.push(facade.prepareWithdrawCollateral(op.token, op.amount, op.to));
|
|
1247
518
|
break;
|
|
1248
519
|
case "swap":
|
|
1249
520
|
case "wrapRwaCollateral":
|
|
@@ -1253,7 +524,7 @@ var CreditAccountsServiceV310 = class extends SDKConstruct {
|
|
|
1253
524
|
case "changeQuota": {
|
|
1254
525
|
const quotaAssets = [...op.quotaIncrease, ...op.quotaDecrease];
|
|
1255
526
|
if (quotaAssets.length === 0) break;
|
|
1256
|
-
calls.push(...
|
|
527
|
+
calls.push(...facade.prepareUpdateQuotas({
|
|
1257
528
|
averageQuota: quotaAssets,
|
|
1258
529
|
minQuota: quotaAssets
|
|
1259
530
|
}));
|
|
@@ -1268,142 +539,40 @@ var CreditAccountsServiceV310 = class extends SDKConstruct {
|
|
|
1268
539
|
*/
|
|
1269
540
|
async executeCaUpdate(creditAccount, calls, options) {
|
|
1270
541
|
const cm = this.sdk.marketRegister.findCreditManager(creditAccount.creditManager);
|
|
1271
|
-
const callsWithPrices = await this
|
|
542
|
+
const callsWithPrices = await this.prependPriceUpdates(creditAccount.creditManager, calls, creditAccount, { ignoreReservePrices: options?.ignoreReservePrices });
|
|
1272
543
|
const tx = await this.#multicallTx(cm, creditAccount.creditAccount, callsWithPrices);
|
|
1273
544
|
if (options?.ethAmount && options.ethAmount > 0n) tx.value = options.ethAmount.toString(10);
|
|
1274
|
-
return
|
|
1275
|
-
tx,
|
|
1276
|
-
calls: callsWithPrices
|
|
1277
|
-
};
|
|
1278
|
-
}
|
|
1279
|
-
#prepareDisableQuotas(ca) {
|
|
1280
|
-
const calls = [];
|
|
1281
|
-
for (const { token, quota } of ca.tokens) if (quota > 0n) calls.push({
|
|
1282
|
-
target: ca.creditFacade,
|
|
1283
|
-
callData: encodeFunctionData({
|
|
1284
|
-
abi: iCreditFacadeMulticallV310Abi,
|
|
1285
|
-
functionName: "updateQuota",
|
|
1286
|
-
args: [
|
|
1287
|
-
token,
|
|
1288
|
-
MIN_INT96,
|
|
1289
|
-
0n
|
|
1290
|
-
]
|
|
1291
|
-
})
|
|
1292
|
-
});
|
|
1293
|
-
return calls;
|
|
545
|
+
return tx;
|
|
1294
546
|
}
|
|
1295
547
|
/**
|
|
1296
548
|
* {@inheritDoc ICreditAccountsService.prepareUpdateQuotas}
|
|
1297
549
|
*/
|
|
1298
|
-
prepareUpdateQuotas(creditFacade,
|
|
1299
|
-
|
|
1300
|
-
return averageQuota.map((q) => {
|
|
1301
|
-
const minBalance = minRecord.get(q.token);
|
|
1302
|
-
const min = minBalance && minBalance > 0n ? minBalance : 0n;
|
|
1303
|
-
return {
|
|
1304
|
-
target: creditFacade,
|
|
1305
|
-
callData: encodeFunctionData({
|
|
1306
|
-
abi: iCreditFacadeMulticallV310Abi,
|
|
1307
|
-
functionName: "updateQuota",
|
|
1308
|
-
args: [
|
|
1309
|
-
q.token,
|
|
1310
|
-
q.balance,
|
|
1311
|
-
min
|
|
1312
|
-
]
|
|
1313
|
-
})
|
|
1314
|
-
};
|
|
1315
|
-
});
|
|
1316
|
-
}
|
|
1317
|
-
#prepareDecreaseDebt(ca) {
|
|
1318
|
-
if (ca.debt > 0n) return [{
|
|
1319
|
-
target: ca.creditFacade,
|
|
1320
|
-
callData: encodeFunctionData({
|
|
1321
|
-
abi: iCreditFacadeMulticallV310Abi,
|
|
1322
|
-
functionName: "decreaseDebt",
|
|
1323
|
-
args: [MAX_UINT256]
|
|
1324
|
-
})
|
|
1325
|
-
}];
|
|
1326
|
-
return [];
|
|
550
|
+
prepareUpdateQuotas(creditFacade, props) {
|
|
551
|
+
return this.sdk.marketRegister.findCreditFacade(creditFacade).prepareUpdateQuotas(props);
|
|
1327
552
|
}
|
|
1328
553
|
/**
|
|
1329
554
|
* {@inheritDoc ICreditAccountsService.prepareWithdrawToken}
|
|
1330
555
|
*/
|
|
1331
556
|
prepareWithdrawToken(creditFacade, token, amount, to) {
|
|
1332
|
-
return
|
|
1333
|
-
target: creditFacade,
|
|
1334
|
-
callData: encodeFunctionData({
|
|
1335
|
-
abi: iCreditFacadeMulticallV310Abi,
|
|
1336
|
-
functionName: "withdrawCollateral",
|
|
1337
|
-
args: [
|
|
1338
|
-
token,
|
|
1339
|
-
amount,
|
|
1340
|
-
to
|
|
1341
|
-
]
|
|
1342
|
-
})
|
|
1343
|
-
};
|
|
557
|
+
return this.sdk.marketRegister.findCreditFacade(creditFacade).prepareWithdrawCollateral(token, amount, to);
|
|
1344
558
|
}
|
|
1345
559
|
/**
|
|
1346
560
|
* {@inheritDoc ICreditAccountsService.prepareIncreaseDebt}
|
|
1347
561
|
*/
|
|
1348
562
|
prepareIncreaseDebt(creditFacade, debt) {
|
|
1349
|
-
return
|
|
1350
|
-
target: creditFacade,
|
|
1351
|
-
callData: encodeFunctionData({
|
|
1352
|
-
abi: iCreditFacadeMulticallV310Abi,
|
|
1353
|
-
functionName: "increaseDebt",
|
|
1354
|
-
args: [debt]
|
|
1355
|
-
})
|
|
1356
|
-
};
|
|
563
|
+
return this.sdk.marketRegister.findCreditFacade(creditFacade).prepareIncreaseDebt(debt);
|
|
1357
564
|
}
|
|
1358
565
|
/**
|
|
1359
566
|
* {@inheritDoc ICreditAccountsService.prepareChangeDebt}
|
|
1360
567
|
*/
|
|
1361
568
|
prepareChangeDebt(creditFacade, change, isDecrease) {
|
|
1362
|
-
return
|
|
1363
|
-
target: creditFacade,
|
|
1364
|
-
callData: encodeFunctionData({
|
|
1365
|
-
abi: iCreditFacadeMulticallV310Abi,
|
|
1366
|
-
functionName: isDecrease ? "decreaseDebt" : "increaseDebt",
|
|
1367
|
-
args: [change]
|
|
1368
|
-
})
|
|
1369
|
-
};
|
|
569
|
+
return this.sdk.marketRegister.findCreditFacade(creditFacade).prepareChangeDebt(change, isDecrease);
|
|
1370
570
|
}
|
|
1371
571
|
/**
|
|
1372
572
|
* {@inheritDoc ICreditAccountsService.prepareAddCollateral}
|
|
1373
573
|
*/
|
|
1374
574
|
prepareAddCollateral(creditFacade, assets, permits) {
|
|
1375
|
-
return
|
|
1376
|
-
const p = permits[token];
|
|
1377
|
-
if (p) return {
|
|
1378
|
-
target: creditFacade,
|
|
1379
|
-
callData: encodeFunctionData({
|
|
1380
|
-
abi: iCreditFacadeMulticallV310Abi,
|
|
1381
|
-
functionName: "addCollateralWithPermit",
|
|
1382
|
-
args: [
|
|
1383
|
-
token,
|
|
1384
|
-
balance,
|
|
1385
|
-
p.deadline,
|
|
1386
|
-
p.v,
|
|
1387
|
-
p.r,
|
|
1388
|
-
p.s
|
|
1389
|
-
]
|
|
1390
|
-
})
|
|
1391
|
-
};
|
|
1392
|
-
return {
|
|
1393
|
-
target: creditFacade,
|
|
1394
|
-
callData: encodeFunctionData({
|
|
1395
|
-
abi: iCreditFacadeMulticallV310Abi,
|
|
1396
|
-
functionName: "addCollateral",
|
|
1397
|
-
args: [token, balance]
|
|
1398
|
-
})
|
|
1399
|
-
};
|
|
1400
|
-
});
|
|
1401
|
-
}
|
|
1402
|
-
/**
|
|
1403
|
-
* Returns addresses of market configurators
|
|
1404
|
-
*/
|
|
1405
|
-
get marketConfigurators() {
|
|
1406
|
-
return this.sdk.marketRegister.marketConfigurators.map((mc) => mc.address);
|
|
575
|
+
return this.sdk.marketRegister.findCreditFacade(creditFacade).prepareAddCollateral(assets, permits);
|
|
1407
576
|
}
|
|
1408
577
|
get rewardCompressor() {
|
|
1409
578
|
return this.sdk.addressProvider.mustGetLatest(AP_REWARDS_COMPRESSOR, VERSION_RANGE_310)[0];
|
|
@@ -1411,13 +580,6 @@ var CreditAccountsServiceV310 = class extends SDKConstruct {
|
|
|
1411
580
|
get peripheryCompressor() {
|
|
1412
581
|
return this.sdk.addressProvider.mustGetLatest(AP_PERIPHERY_COMPRESSOR, VERSION_RANGE_310)[0];
|
|
1413
582
|
}
|
|
1414
|
-
get compressor() {
|
|
1415
|
-
if (!this.#compressor) {
|
|
1416
|
-
[this.#compressor] = this.sdk.addressProvider.mustGetLatest(AP_CREDIT_ACCOUNT_COMPRESSOR, VERSION_RANGE_310);
|
|
1417
|
-
this.logger?.debug(`credit account compressor address: ${this.#compressor}`);
|
|
1418
|
-
}
|
|
1419
|
-
return this.#compressor;
|
|
1420
|
-
}
|
|
1421
583
|
/**
|
|
1422
584
|
* Wrapper that selects between credit facade and RWA factory
|
|
1423
585
|
* @param suite
|
|
@@ -1446,24 +608,6 @@ var CreditAccountsServiceV310 = class extends SDKConstruct {
|
|
|
1446
608
|
return suite.creditFacade.multicall(creditAccount, calls);
|
|
1447
609
|
}
|
|
1448
610
|
/**
|
|
1449
|
-
* Wrapper that selects between credit facade and RWA factory
|
|
1450
|
-
* @param suite
|
|
1451
|
-
* @param creditAccount
|
|
1452
|
-
* @param calls
|
|
1453
|
-
* @param operation
|
|
1454
|
-
* @param rwaOptions
|
|
1455
|
-
* @returns
|
|
1456
|
-
*/
|
|
1457
|
-
async #closeCreditAccountTx(suite, creditAccount, calls, operation, rwaOptions) {
|
|
1458
|
-
const factory = this.sdk.marketRegister.findByCreditManager(suite.creditManager.address).rwaFactory;
|
|
1459
|
-
if (operation === "close") {
|
|
1460
|
-
if (factory) throw new Error("CloseOptions=close is not supported for RWA underlying credit accounts");
|
|
1461
|
-
return suite.creditFacade.closeCreditAccount(creditAccount, calls);
|
|
1462
|
-
}
|
|
1463
|
-
if (factory) return factory.multicall(creditAccount, calls, rwaOptions);
|
|
1464
|
-
return suite.creditFacade.multicall(creditAccount, calls);
|
|
1465
|
-
}
|
|
1466
|
-
/**
|
|
1467
611
|
* Withdrawal compressor of the current chain.
|
|
1468
612
|
* @throws If no withdrawal compressor is supported on the current chain.
|
|
1469
613
|
**/
|