@eulerxyz/euler-v2-sdk 1.1.0 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/dist/src/index.d.ts +1 -0
  2. package/dist/src/index.d.ts.map +1 -1
  3. package/dist/src/index.js +1 -0
  4. package/dist/src/index.js.map +1 -1
  5. package/dist/src/sdk/buildSDK.d.ts +8 -0
  6. package/dist/src/sdk/buildSDK.d.ts.map +1 -1
  7. package/dist/src/sdk/buildSDK.js +20 -1
  8. package/dist/src/sdk/buildSDK.js.map +1 -1
  9. package/dist/src/sdk/sdk.d.ts +3 -0
  10. package/dist/src/sdk/sdk.d.ts.map +1 -1
  11. package/dist/src/sdk/sdk.js +2 -0
  12. package/dist/src/sdk/sdk.js.map +1 -1
  13. package/dist/src/services/executionService/abis/swapVerifierAbi.d.ts +130 -0
  14. package/dist/src/services/executionService/abis/swapVerifierAbi.d.ts.map +1 -1
  15. package/dist/src/services/executionService/abis/swapVerifierAbi.js +69 -0
  16. package/dist/src/services/executionService/abis/swapVerifierAbi.js.map +1 -1
  17. package/dist/src/services/executionService/executionService.d.ts +2 -1
  18. package/dist/src/services/executionService/executionService.d.ts.map +1 -1
  19. package/dist/src/services/executionService/executionService.js.map +1 -1
  20. package/dist/src/services/executionService/simulate.d.ts +2 -0
  21. package/dist/src/services/executionService/simulate.d.ts.map +1 -1
  22. package/dist/src/services/executionService/simulate.js +9 -1
  23. package/dist/src/services/executionService/simulate.js.map +1 -1
  24. package/dist/src/services/positionMigrationService/connectors/aave/aaveConnector.d.ts +81 -0
  25. package/dist/src/services/positionMigrationService/connectors/aave/aaveConnector.d.ts.map +1 -0
  26. package/dist/src/services/positionMigrationService/connectors/aave/aaveConnector.js +1291 -0
  27. package/dist/src/services/positionMigrationService/connectors/aave/aaveConnector.js.map +1 -0
  28. package/dist/src/services/positionMigrationService/connectors/aave/aaveConnectorTypes.d.ts +84 -0
  29. package/dist/src/services/positionMigrationService/connectors/aave/aaveConnectorTypes.d.ts.map +1 -0
  30. package/dist/src/services/positionMigrationService/connectors/aave/aaveConnectorTypes.js +2 -0
  31. package/dist/src/services/positionMigrationService/connectors/aave/aaveConnectorTypes.js.map +1 -0
  32. package/dist/src/services/positionMigrationService/connectors/aave/abis/aaveV3Abi.d.ts +370 -0
  33. package/dist/src/services/positionMigrationService/connectors/aave/abis/aaveV3Abi.d.ts.map +1 -0
  34. package/dist/src/services/positionMigrationService/connectors/aave/abis/aaveV3Abi.js +243 -0
  35. package/dist/src/services/positionMigrationService/connectors/aave/abis/aaveV3Abi.js.map +1 -0
  36. package/dist/src/services/positionMigrationService/connectors/aave/index.d.ts +4 -0
  37. package/dist/src/services/positionMigrationService/connectors/aave/index.d.ts.map +1 -0
  38. package/dist/src/services/positionMigrationService/connectors/aave/index.js +3 -0
  39. package/dist/src/services/positionMigrationService/connectors/aave/index.js.map +1 -0
  40. package/dist/src/services/positionMigrationService/connectors/index.d.ts +4 -0
  41. package/dist/src/services/positionMigrationService/connectors/index.d.ts.map +1 -0
  42. package/dist/src/services/positionMigrationService/connectors/index.js +4 -0
  43. package/dist/src/services/positionMigrationService/connectors/index.js.map +1 -0
  44. package/dist/src/services/positionMigrationService/connectors/metamorpho/abis/metamorphoAbi.d.ts +166 -0
  45. package/dist/src/services/positionMigrationService/connectors/metamorpho/abis/metamorphoAbi.d.ts.map +1 -0
  46. package/dist/src/services/positionMigrationService/connectors/metamorpho/abis/metamorphoAbi.js +108 -0
  47. package/dist/src/services/positionMigrationService/connectors/metamorpho/abis/metamorphoAbi.js.map +1 -0
  48. package/dist/src/services/positionMigrationService/connectors/metamorpho/index.d.ts +4 -0
  49. package/dist/src/services/positionMigrationService/connectors/metamorpho/index.d.ts.map +1 -0
  50. package/dist/src/services/positionMigrationService/connectors/metamorpho/index.js +3 -0
  51. package/dist/src/services/positionMigrationService/connectors/metamorpho/index.js.map +1 -0
  52. package/dist/src/services/positionMigrationService/connectors/metamorpho/metamorphoConnector.d.ts +56 -0
  53. package/dist/src/services/positionMigrationService/connectors/metamorpho/metamorphoConnector.d.ts.map +1 -0
  54. package/dist/src/services/positionMigrationService/connectors/metamorpho/metamorphoConnector.js +426 -0
  55. package/dist/src/services/positionMigrationService/connectors/metamorpho/metamorphoConnector.js.map +1 -0
  56. package/dist/src/services/positionMigrationService/connectors/metamorpho/metamorphoConnectorTypes.d.ts +46 -0
  57. package/dist/src/services/positionMigrationService/connectors/metamorpho/metamorphoConnectorTypes.d.ts.map +1 -0
  58. package/dist/src/services/positionMigrationService/connectors/metamorpho/metamorphoConnectorTypes.js +2 -0
  59. package/dist/src/services/positionMigrationService/connectors/metamorpho/metamorphoConnectorTypes.js.map +1 -0
  60. package/dist/src/services/positionMigrationService/connectors/morpho/abis/morphoBlueAbi.d.ts +269 -0
  61. package/dist/src/services/positionMigrationService/connectors/morpho/abis/morphoBlueAbi.d.ts.map +1 -0
  62. package/dist/src/services/positionMigrationService/connectors/morpho/abis/morphoBlueAbi.js +172 -0
  63. package/dist/src/services/positionMigrationService/connectors/morpho/abis/morphoBlueAbi.js.map +1 -0
  64. package/dist/src/services/positionMigrationService/connectors/morpho/index.d.ts +4 -0
  65. package/dist/src/services/positionMigrationService/connectors/morpho/index.d.ts.map +1 -0
  66. package/dist/src/services/positionMigrationService/connectors/morpho/index.js +3 -0
  67. package/dist/src/services/positionMigrationService/connectors/morpho/index.js.map +1 -0
  68. package/dist/src/services/positionMigrationService/connectors/morpho/morphoConnector.d.ts +57 -0
  69. package/dist/src/services/positionMigrationService/connectors/morpho/morphoConnector.d.ts.map +1 -0
  70. package/dist/src/services/positionMigrationService/connectors/morpho/morphoConnector.js +856 -0
  71. package/dist/src/services/positionMigrationService/connectors/morpho/morphoConnector.js.map +1 -0
  72. package/dist/src/services/positionMigrationService/connectors/morpho/morphoConnectorTypes.d.ts +61 -0
  73. package/dist/src/services/positionMigrationService/connectors/morpho/morphoConnectorTypes.d.ts.map +1 -0
  74. package/dist/src/services/positionMigrationService/connectors/morpho/morphoConnectorTypes.js +2 -0
  75. package/dist/src/services/positionMigrationService/connectors/morpho/morphoConnectorTypes.js.map +1 -0
  76. package/dist/src/services/positionMigrationService/connectors/shared.d.ts +83 -0
  77. package/dist/src/services/positionMigrationService/connectors/shared.d.ts.map +1 -0
  78. package/dist/src/services/positionMigrationService/connectors/shared.js +214 -0
  79. package/dist/src/services/positionMigrationService/connectors/shared.js.map +1 -0
  80. package/dist/src/services/positionMigrationService/index.d.ts +4 -0
  81. package/dist/src/services/positionMigrationService/index.d.ts.map +1 -0
  82. package/dist/src/services/positionMigrationService/index.js +3 -0
  83. package/dist/src/services/positionMigrationService/index.js.map +1 -0
  84. package/dist/src/services/positionMigrationService/positionMigrationService.d.ts +30 -0
  85. package/dist/src/services/positionMigrationService/positionMigrationService.d.ts.map +1 -0
  86. package/dist/src/services/positionMigrationService/positionMigrationService.js +420 -0
  87. package/dist/src/services/positionMigrationService/positionMigrationService.js.map +1 -0
  88. package/dist/src/services/positionMigrationService/positionMigrationServiceTypes.d.ts +235 -0
  89. package/dist/src/services/positionMigrationService/positionMigrationServiceTypes.d.ts.map +1 -0
  90. package/dist/src/services/positionMigrationService/positionMigrationServiceTypes.js +2 -0
  91. package/dist/src/services/positionMigrationService/positionMigrationServiceTypes.js.map +1 -0
  92. package/dist/src/services/swapService/swapVerification.d.ts +1 -1
  93. package/dist/src/services/swapService/swapVerification.d.ts.map +1 -1
  94. package/dist/src/utils/oracle.d.ts.map +1 -1
  95. package/dist/src/utils/oracle.js +6 -2
  96. package/dist/src/utils/oracle.js.map +1 -1
  97. package/package.json +1 -1
@@ -0,0 +1,1291 @@
1
+ import { encodeFunctionData, getAddress, maxUint256, } from "viem";
2
+ import { eVaultAbi, swapperAbi, swapVerifierAbi, } from "../../../executionService/index.js";
3
+ import { applyBuffer, assertEulerSource, assertEulerTarget, assertSameAddress, assertSwapQuoteUsesSwapper, encodeDepositVerifiedSwapQuoteItem, encodeGenericSwap, encodeSwapQuoteVerificationItem, encodeVerifyAmountMinAndDepositItem, encodeVerifyDebtMaxItem, getSwapperAddress, getSwapQuoteInputAmount, getSwapQuoteSwapCalls, getSwapVerifierAddress, resolveEulerSourceAmounts, splitPermitSignature, } from "../shared.js";
4
+ import { aaveATokenAbi, aaveDebtTokenAbi, aaveV3PoolAbi, } from "./abis/aaveV3Abi.js";
5
+ export const AAVE_CONNECTOR_ID = "aave";
6
+ export const AAVE_PROTOCOL = "Aave V3";
7
+ const DEFAULT_AAVE_GRAPHQL_ENDPOINT = "https://api.v3.aave.com/graphql";
8
+ const DEFAULT_AAVE_POOL_ADDRESSES = {
9
+ 1: "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2",
10
+ 10: "0x794a61358D6845594F94dc1DB02A252b5b4814aD",
11
+ 56: "0x6807dc923806fE8Fd134338EABCA509979a7e0cB",
12
+ 100: "0xb50201558B00496A145fE76f7424749556E326D8",
13
+ 143: "0x69a5F9AD4f96ebf0a0C792dD42a01cC5C0102fef",
14
+ 146: "0x5362dBb1e601abF3a4c14c22ffEdA64042E5eAA3",
15
+ 5000: "0x458F293454fE0d67EC0655f3672301301DD51422",
16
+ 8453: "0xA238Dd80C259a72e81d7e4664a9801593F98d1c5",
17
+ 9745: "0x925a2A7214Ed92428B5b1B090F80b25700095e12",
18
+ 42161: "0x794a61358D6845594F94dc1DB02A252b5b4814aD",
19
+ 43114: "0x794a61358D6845594F94dc1DB02A252b5b4814aD",
20
+ 57073: "0x2816cf15F6d2A220E789aA011D5EE4eB6c47FEbA",
21
+ };
22
+ const DEFAULT_INTEREST_BUFFER_BPS = 100n;
23
+ const DEFAULT_ATOKEN_TRANSFER_BUFFER_BPS = 1n;
24
+ const DEFAULT_OUTBOUND_INTEREST_BUFFER_BPS = 1n;
25
+ const AAVE_VARIABLE_INTEREST_RATE_MODE = 2n;
26
+ const AAVE_ACTIVE_BIT = 56n;
27
+ const AAVE_FROZEN_BIT = 57n;
28
+ const AAVE_BORROWING_BIT = 58n;
29
+ const AAVE_PAUSED_BIT = 60n;
30
+ const AAVE_LTV_MASK = (1n << 16n) - 1n;
31
+ const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
32
+ const AAVE_MARKETS_QUERY = `
33
+ query AaveMigrationMarkets($request: MarketsRequest!) {
34
+ markets(request: $request) {
35
+ name
36
+ address
37
+ chain { chainId }
38
+ totalAvailableLiquidity
39
+ totalMarketSize
40
+ reserves {
41
+ underlyingToken { address symbol decimals }
42
+ aToken { address symbol decimals }
43
+ vToken { address symbol decimals }
44
+ isFrozen
45
+ isPaused
46
+ supplyInfo {
47
+ canBeCollateral
48
+ maxLTV { raw decimals value }
49
+ total { raw decimals value }
50
+ }
51
+ borrowInfo {
52
+ borrowingState
53
+ availableLiquidity { amount { raw decimals value } }
54
+ total { amount { raw decimals value } }
55
+ }
56
+ }
57
+ }
58
+ }
59
+ `;
60
+ export const AAVE_PERMIT_TYPES = {
61
+ Permit: [
62
+ { name: "owner", type: "address" },
63
+ { name: "spender", type: "address" },
64
+ { name: "value", type: "uint256" },
65
+ { name: "nonce", type: "uint256" },
66
+ { name: "deadline", type: "uint256" },
67
+ ],
68
+ };
69
+ export const AAVE_DELEGATION_TYPES = {
70
+ DelegationWithSig: [
71
+ { name: "delegatee", type: "address" },
72
+ { name: "value", type: "uint256" },
73
+ { name: "nonce", type: "uint256" },
74
+ { name: "deadline", type: "uint256" },
75
+ ],
76
+ };
77
+ export function getAavePositionId(positionRef) {
78
+ if (!positionRef.pool) {
79
+ throw new Error("Aave position id requires a resolved pool address");
80
+ }
81
+ if (!positionRef.debtAsset) {
82
+ return [
83
+ AAVE_CONNECTOR_ID,
84
+ getAddress(positionRef.pool),
85
+ getAddress(positionRef.collateralAsset),
86
+ "supply",
87
+ ].join(":");
88
+ }
89
+ return [
90
+ AAVE_CONNECTOR_ID,
91
+ getAddress(positionRef.pool),
92
+ getAddress(positionRef.collateralAsset),
93
+ getAddress(positionRef.debtAsset),
94
+ "variable",
95
+ ].join(":");
96
+ }
97
+ export function splitAaveSignature(signature) {
98
+ return splitPermitSignature(signature);
99
+ }
100
+ export class AavePositionMigrationConnector {
101
+ deploymentService;
102
+ providerService;
103
+ executionService;
104
+ id = AAVE_CONNECTOR_ID;
105
+ protocol = AAVE_PROTOCOL;
106
+ name = "Aave V3";
107
+ deployments;
108
+ graphqlEndpoint;
109
+ marketCache = new Map();
110
+ defaultInterestBufferBps;
111
+ defaultOutboundInterestBufferBps;
112
+ referralCode;
113
+ constructor(deploymentService, providerService, executionService, config = {}) {
114
+ this.deploymentService = deploymentService;
115
+ this.providerService = providerService;
116
+ this.executionService = executionService;
117
+ this.deployments = normalizeAaveDeployments([
118
+ ...Object.entries({
119
+ ...DEFAULT_AAVE_POOL_ADDRESSES,
120
+ ...(config.poolAddresses ?? {}),
121
+ }).map(([chainId, pool]) => ({
122
+ chainId: Number(chainId),
123
+ pool,
124
+ })),
125
+ ...(config.deployments ?? []),
126
+ ]);
127
+ this.graphqlEndpoint =
128
+ config.graphqlEndpoint === null
129
+ ? undefined
130
+ : (config.graphqlEndpoint ?? DEFAULT_AAVE_GRAPHQL_ENDPOINT);
131
+ this.defaultInterestBufferBps =
132
+ config.defaultInterestBufferBps ?? DEFAULT_INTEREST_BUFFER_BPS;
133
+ this.defaultOutboundInterestBufferBps =
134
+ config.defaultOutboundInterestBufferBps ??
135
+ DEFAULT_OUTBOUND_INTEREST_BUFFER_BPS;
136
+ this.referralCode = config.referralCode ?? 0;
137
+ }
138
+ listPositions(args) {
139
+ return Promise.all((args.positionRefs ?? []).map((positionRef) => this.getPosition({
140
+ connectorId: AAVE_CONNECTOR_ID,
141
+ chainId: args.chainId,
142
+ owner: args.owner,
143
+ positionRef,
144
+ }))).then((positions) => positions.filter((position) => position.raw.stableDebt === 0n &&
145
+ (position.debt.amount > 0n || position.collateral.amount > 0n)));
146
+ }
147
+ async listTargets(args) {
148
+ if ((args.direction ?? "euler-to-external") !== "euler-to-external") {
149
+ return [];
150
+ }
151
+ const collateralAsset = getAddress(args.collateralAsset);
152
+ const debtAsset = getAddress(args.debtAsset);
153
+ if (this.graphqlEndpoint) {
154
+ try {
155
+ return await this.listGraphqlTargets({
156
+ chainId: args.chainId,
157
+ collateralAsset,
158
+ debtAsset,
159
+ minLiquidity: args.minLiquidity,
160
+ });
161
+ }
162
+ catch {
163
+ this.marketCache.delete(args.chainId);
164
+ }
165
+ }
166
+ return this.listConfiguredDeploymentTargets({
167
+ chainId: args.chainId,
168
+ collateralAsset,
169
+ debtAsset,
170
+ minLiquidity: args.minLiquidity,
171
+ });
172
+ }
173
+ async getPosition(args) {
174
+ const owner = getAddress(args.owner);
175
+ const market = await this.resolveAaveMarket(args.chainId, args.positionRef);
176
+ const ref = normalizeAavePositionRef(args.positionRef, market?.address ??
177
+ this.getPoolAddress(args.chainId, args.positionRef.pool));
178
+ const provider = this.providerService.getProvider(args.chainId);
179
+ const reserveContracts = [
180
+ {
181
+ address: ref.pool,
182
+ abi: aaveV3PoolAbi,
183
+ functionName: "getReserveData",
184
+ args: [ref.collateralAsset],
185
+ },
186
+ ...(ref.debtAsset
187
+ ? [
188
+ {
189
+ address: ref.pool,
190
+ abi: aaveV3PoolAbi,
191
+ functionName: "getReserveData",
192
+ args: [ref.debtAsset],
193
+ },
194
+ ]
195
+ : []),
196
+ ];
197
+ const [collateralReserveResult, debtReserveResult] = (await provider.multicall({
198
+ contracts: reserveContracts,
199
+ allowFailure: false,
200
+ }));
201
+ const collateralReserve = toReserveTokens(collateralReserveResult);
202
+ const debtReserve = debtReserveResult
203
+ ? toReserveTokens(debtReserveResult)
204
+ : undefined;
205
+ const balanceContracts = [
206
+ {
207
+ address: collateralReserve.aTokenAddress,
208
+ abi: aaveATokenAbi,
209
+ functionName: "balanceOf",
210
+ args: [owner],
211
+ },
212
+ ...(debtReserve
213
+ ? [
214
+ {
215
+ address: debtReserve.variableDebtTokenAddress,
216
+ abi: aaveDebtTokenAbi,
217
+ functionName: "balanceOf",
218
+ args: [owner],
219
+ },
220
+ {
221
+ address: debtReserve.stableDebtTokenAddress,
222
+ abi: aaveDebtTokenAbi,
223
+ functionName: "balanceOf",
224
+ args: [owner],
225
+ },
226
+ ]
227
+ : []),
228
+ ];
229
+ const [aTokenBalance, variableDebtResult, stableDebtResult] = (await provider.multicall({
230
+ contracts: balanceContracts,
231
+ allowFailure: false,
232
+ }));
233
+ const variableDebt = variableDebtResult ?? 0n;
234
+ const stableDebt = stableDebtResult ?? 0n;
235
+ const raw = {
236
+ id: getAavePositionId(ref),
237
+ owner,
238
+ pool: ref.pool,
239
+ marketName: market?.name,
240
+ collateralAsset: ref.collateralAsset,
241
+ debtAsset: ref.debtAsset,
242
+ collateralReserve,
243
+ debtReserve,
244
+ aTokenBalance,
245
+ stableDebt,
246
+ variableDebt,
247
+ };
248
+ return {
249
+ connectorId: AAVE_CONNECTOR_ID,
250
+ protocol: AAVE_PROTOCOL,
251
+ id: raw.id,
252
+ chainId: args.chainId,
253
+ owner,
254
+ ref,
255
+ debt: {
256
+ asset: ref.debtAsset ?? ref.collateralAsset,
257
+ amount: variableDebt + stableDebt,
258
+ },
259
+ collateral: {
260
+ asset: ref.collateralAsset,
261
+ amount: aTokenBalance,
262
+ },
263
+ raw,
264
+ };
265
+ }
266
+ async getAuthorization(args) {
267
+ if (args.direction !== "external-to-euler" &&
268
+ args.direction !== "euler-to-external") {
269
+ throw new Error(`Unsupported migration direction: ${args.direction}`);
270
+ }
271
+ const position = assertAavePosition(args.position);
272
+ const owner = getAddress(args.owner);
273
+ if (args.direction === "external-to-euler") {
274
+ const swapVerifier = getSwapVerifierAddress(this.deploymentService, args.chainId);
275
+ const token = position.raw.collateralReserve.aTokenAddress;
276
+ const collateralAmount = position.raw.aTokenBalance;
277
+ if (collateralAmount <= 0n)
278
+ return undefined;
279
+ const collateralTransferMaxAmount = applyBuffer(collateralAmount, DEFAULT_ATOKEN_TRANSFER_BUFFER_BPS);
280
+ if (await this.hasATokenAllowance(args.chainId, token, owner, swapVerifier, collateralTransferMaxAmount)) {
281
+ return undefined;
282
+ }
283
+ return this.buildATokenPermitRequest({
284
+ chainId: args.chainId,
285
+ owner,
286
+ spender: swapVerifier,
287
+ token,
288
+ value: collateralTransferMaxAmount,
289
+ positionId: position.id,
290
+ deadline: args.deadline,
291
+ });
292
+ }
293
+ const source = assertEulerSource(args.source);
294
+ const swapVerifier = getSwapVerifierAddress(this.deploymentService, args.chainId);
295
+ const sourceAmounts = await resolveEulerSourceAmounts(source, args.account);
296
+ const value = args.externalTarget?.borrowAmount ??
297
+ applyBuffer(sourceAmounts.debtAmount, args.externalTarget?.interestBufferBps ??
298
+ this.defaultOutboundInterestBufferBps);
299
+ if (!position.raw.debtReserve) {
300
+ throw new Error("Aave debt reserve is required for Euler to Aave migration");
301
+ }
302
+ const token = position.raw.debtReserve.variableDebtTokenAddress;
303
+ if (value <= 0n)
304
+ return undefined;
305
+ if (await this.hasBorrowAllowance(args.chainId, token, owner, swapVerifier, value)) {
306
+ return undefined;
307
+ }
308
+ return this.buildDebtDelegationRequest({
309
+ chainId: args.chainId,
310
+ delegator: owner,
311
+ delegatee: swapVerifier,
312
+ token,
313
+ value,
314
+ positionId: position.id,
315
+ deadline: args.deadline,
316
+ });
317
+ }
318
+ async buildMigrationBatch(args) {
319
+ if (args.position.connectorId !== AAVE_CONNECTOR_ID) {
320
+ throw new Error(`Aave connector cannot build migration for ${args.position.connectorId}`);
321
+ }
322
+ if (args.direction === "external-to-euler") {
323
+ return this.buildExternalToEulerBatch(args);
324
+ }
325
+ if (args.direction === "euler-to-external") {
326
+ return this.buildEulerToAaveBatch(args);
327
+ }
328
+ throw new Error(`Unsupported migration direction: ${args.direction}`);
329
+ }
330
+ getProtocolAddress(chainId) {
331
+ return this.getProtocolAddresses(chainId)[0];
332
+ }
333
+ getProtocolAddresses(chainId) {
334
+ return this.deployments
335
+ .filter((deployment) => deployment.chainId === chainId)
336
+ .map((deployment) => getAddress(deployment.pool));
337
+ }
338
+ getPoolAddress(chainId, override) {
339
+ if (override)
340
+ return getAddress(override);
341
+ const pool = this.getProtocolAddresses(chainId)[0];
342
+ if (!pool) {
343
+ throw new Error(`Aave connector is not configured for chainId ${chainId}`);
344
+ }
345
+ return pool;
346
+ }
347
+ async listGraphqlTargets(args) {
348
+ const markets = await this.fetchAaveMarkets(args.chainId);
349
+ const targets = [];
350
+ for (const market of markets) {
351
+ const target = toAaveGraphqlTarget({
352
+ chainId: args.chainId,
353
+ market,
354
+ collateralAsset: args.collateralAsset,
355
+ debtAsset: args.debtAsset,
356
+ minLiquidity: args.minLiquidity,
357
+ });
358
+ if (target)
359
+ targets.push(target);
360
+ }
361
+ return targets;
362
+ }
363
+ async listConfiguredDeploymentTargets(args) {
364
+ const deployments = this.deployments.filter((deployment) => deployment.chainId === args.chainId);
365
+ if (deployments.length === 0)
366
+ return [];
367
+ const targets = await Promise.all(deployments.map((deployment) => this.getConfiguredDeploymentTarget({ ...args, deployment })));
368
+ return targets.filter((target) => target !== null);
369
+ }
370
+ async getConfiguredDeploymentTarget(args) {
371
+ const pool = getAddress(args.deployment.pool);
372
+ const provider = this.providerService.getProvider(args.chainId);
373
+ const [collateralReserveResult, debtReserveResult] = (await provider.multicall({
374
+ contracts: [
375
+ {
376
+ address: pool,
377
+ abi: aaveV3PoolAbi,
378
+ functionName: "getReserveData",
379
+ args: [args.collateralAsset],
380
+ },
381
+ {
382
+ address: pool,
383
+ abi: aaveV3PoolAbi,
384
+ functionName: "getReserveData",
385
+ args: [args.debtAsset],
386
+ },
387
+ ],
388
+ allowFailure: true,
389
+ }));
390
+ if (collateralReserveResult.status !== "success" ||
391
+ debtReserveResult.status !== "success") {
392
+ return null;
393
+ }
394
+ const collateralReserve = toReserveData(collateralReserveResult.result);
395
+ const debtReserve = toReserveData(debtReserveResult.result);
396
+ if (!isUsableCollateralReserve(collateralReserve) ||
397
+ !isUsableBorrowReserve(debtReserve)) {
398
+ return null;
399
+ }
400
+ const availableLiquidity = await readAaveAvailableLiquidity(provider, args.debtAsset, debtReserve.aTokenAddress);
401
+ if (args.minLiquidity !== undefined &&
402
+ availableLiquidity !== undefined &&
403
+ availableLiquidity < args.minLiquidity) {
404
+ return null;
405
+ }
406
+ const totalSupplied = await readAaveTotalSupplied(provider, debtReserve.aTokenAddress);
407
+ const ref = {
408
+ pool,
409
+ collateralAsset: args.collateralAsset,
410
+ debtAsset: args.debtAsset,
411
+ };
412
+ const extraData = {
413
+ marketName: args.deployment.marketName,
414
+ pool,
415
+ availableLiquidity,
416
+ totalSupplied,
417
+ };
418
+ return {
419
+ connectorId: AAVE_CONNECTOR_ID,
420
+ protocol: AAVE_PROTOCOL,
421
+ id: getAavePositionId(ref),
422
+ chainId: args.chainId,
423
+ ref,
424
+ debt: { asset: args.debtAsset },
425
+ collateral: { asset: args.collateralAsset },
426
+ ...(availableLiquidity !== undefined
427
+ ? { liquidity: { asset: args.debtAsset, amount: availableLiquidity } }
428
+ : {}),
429
+ raw: {
430
+ pool,
431
+ marketName: args.deployment.marketName,
432
+ collateralReserve,
433
+ debtReserve,
434
+ availableLiquidity,
435
+ totalSupplied,
436
+ },
437
+ extraData,
438
+ };
439
+ }
440
+ async resolveAaveMarket(chainId, positionRef) {
441
+ if (positionRef.pool || !this.graphqlEndpoint)
442
+ return undefined;
443
+ try {
444
+ const collateralAsset = getAddress(positionRef.collateralAsset);
445
+ const debtAsset = positionRef.debtAsset
446
+ ? getAddress(positionRef.debtAsset)
447
+ : undefined;
448
+ return (await this.fetchAaveMarkets(chainId)).find((market) => {
449
+ const hasCollateral = market.reserves.some((reserve) => sameAddress(reserve.underlyingToken.address, collateralAsset));
450
+ const hasDebt = !debtAsset ||
451
+ market.reserves.some((reserve) => sameAddress(reserve.underlyingToken.address, debtAsset));
452
+ return hasCollateral && hasDebt;
453
+ });
454
+ }
455
+ catch {
456
+ this.marketCache.delete(chainId);
457
+ return undefined;
458
+ }
459
+ }
460
+ fetchAaveMarkets(chainId) {
461
+ const cached = this.marketCache.get(chainId);
462
+ if (cached)
463
+ return cached;
464
+ const request = this.fetchAaveMarketsUncached(chainId);
465
+ this.marketCache.set(chainId, request);
466
+ return request;
467
+ }
468
+ async fetchAaveMarketsUncached(chainId) {
469
+ if (!this.graphqlEndpoint)
470
+ return [];
471
+ const response = await fetch(this.graphqlEndpoint, {
472
+ method: "POST",
473
+ headers: { "content-type": "application/json" },
474
+ body: JSON.stringify({
475
+ query: AAVE_MARKETS_QUERY,
476
+ variables: { request: { chainIds: [chainId] } },
477
+ }),
478
+ });
479
+ if (!response.ok) {
480
+ throw new Error(`Aave GraphQL request failed: ${response.status}`);
481
+ }
482
+ const body = (await response.json());
483
+ if (body.errors?.length) {
484
+ throw new Error(body.errors[0]?.message ?? "Aave GraphQL returned an error");
485
+ }
486
+ return (body.data?.markets ?? []).filter((market) => Number(market.chain.chainId) === chainId);
487
+ }
488
+ async buildExternalToEulerBatch(args) {
489
+ const target = assertEulerTarget(args.target);
490
+ const owner = getAddress(args.owner);
491
+ const eulerAccount = getAddress(target.eulerAccount);
492
+ const targetBorrowVault = target.borrowVault
493
+ ? getAddress(target.borrowVault)
494
+ : undefined;
495
+ const targetCollateralVault = getAddress(target.collateralVault);
496
+ const pool = args.position.raw.pool;
497
+ const swapper = getSwapperAddress(this.deploymentService, args.chainId, target.swapper);
498
+ const swapVerifier = getSwapVerifierAddress(this.deploymentService, args.chainId);
499
+ const aToken = args.position.raw.collateralReserve.aTokenAddress;
500
+ const collateralAmount = args.position.raw.aTokenBalance;
501
+ const collateralMinAmount = target.minCollateralAssets ?? collateralAmount;
502
+ const collateralTransferMaxAmount = applyBuffer(collateralAmount, DEFAULT_ATOKEN_TRANSFER_BUFFER_BPS);
503
+ const verifierDeadline = args.deadline ?? BigInt(Math.floor(Date.now() / 1000) + 60 * 60);
504
+ const variableDebt = args.position.raw.variableDebt;
505
+ const stableDebt = args.position.raw.stableDebt;
506
+ const hasDebt = variableDebt > 0n;
507
+ const debtAsset = args.position.raw.debtAsset;
508
+ const collateralSwapQuote = args.collateralSwapQuote;
509
+ const debtSwapQuote = args.debtSwapQuote;
510
+ const baseDebtRepayAmount = applyBuffer(variableDebt, target.interestBufferBps ?? this.defaultInterestBufferBps);
511
+ const borrowAmount = target.borrowAmount ??
512
+ (debtSwapQuote
513
+ ? getSwapQuoteInputAmount(debtSwapQuote)
514
+ : baseDebtRepayAmount);
515
+ const externalDebtRepayAmount = debtSwapQuote
516
+ ? baseDebtRepayAmount
517
+ : borrowAmount;
518
+ if (stableDebt > 0n) {
519
+ throw new Error("Aave stable debt migration is not supported");
520
+ }
521
+ if (collateralAmount <= 0n) {
522
+ throw new Error("Aave source position has no collateral to migrate");
523
+ }
524
+ if (hasDebt && !targetBorrowVault) {
525
+ throw new Error("Target Euler borrow vault is required");
526
+ }
527
+ if (hasDebt && !debtAsset) {
528
+ throw new Error("Aave debt asset is required when source debt is present");
529
+ }
530
+ if (!hasDebt && debtSwapQuote) {
531
+ throw new Error("Aave debt swap quote requires source debt");
532
+ }
533
+ if (hasDebt && borrowAmount <= 0n) {
534
+ throw new Error("Euler borrow amount must be greater than zero");
535
+ }
536
+ if (hasDebt && externalDebtRepayAmount <= 0n) {
537
+ throw new Error("Aave repay amount must be greater than zero");
538
+ }
539
+ if (debtSwapQuote) {
540
+ assertSwapQuoteUsesSwapper(debtSwapQuote, swapper, "Aave debt migration");
541
+ }
542
+ if (collateralSwapQuote) {
543
+ assertSwapQuoteUsesSwapper(collateralSwapQuote, swapper, "Aave collateral migration");
544
+ }
545
+ const useDepositSwapVerification = target.collateralSwapVerification === "deposit";
546
+ if (useDepositSwapVerification && hasDebt) {
547
+ throw new Error("Deposit-verified collateral swaps are only supported for supply-only migrations");
548
+ }
549
+ if (useDepositSwapVerification && !collateralSwapQuote) {
550
+ throw new Error("Deposit-verified collateral swaps require a collateral swap quote");
551
+ }
552
+ const items = [];
553
+ const needsATokenPermit = args.skipAuthorizationCheck && args.authorization
554
+ ? true
555
+ : !(await this.hasATokenAllowance(args.chainId, aToken, owner, swapVerifier, collateralTransferMaxAmount));
556
+ if (needsATokenPermit) {
557
+ if (!args.authorization) {
558
+ throw new Error("Aave aToken permit for the Euler SwapVerifier is required");
559
+ }
560
+ items.push(this.encodeATokenPermitItem({
561
+ owner,
562
+ swapVerifier,
563
+ aToken,
564
+ maxAmount: collateralTransferMaxAmount,
565
+ authorization: args.authorization,
566
+ }));
567
+ }
568
+ if (hasDebt && targetBorrowVault && (target.enableController ?? true)) {
569
+ items.push(this.executionService.encodeEnableController(args.chainId, eulerAccount, targetBorrowVault));
570
+ }
571
+ if (hasDebt && (target.enableCollateral ?? true)) {
572
+ items.push(this.executionService.encodeEnableCollateral(args.chainId, eulerAccount, targetCollateralVault));
573
+ }
574
+ if (hasDebt && targetBorrowVault) {
575
+ items.push({
576
+ targetContract: targetBorrowVault,
577
+ onBehalfOfAccount: eulerAccount,
578
+ value: 0n,
579
+ data: encodeFunctionData({
580
+ abi: eVaultAbi,
581
+ functionName: "borrow",
582
+ args: [borrowAmount, swapper],
583
+ }),
584
+ });
585
+ }
586
+ const preTransferSwapperCalls = [];
587
+ if (hasDebt && debtSwapQuote) {
588
+ preTransferSwapperCalls.push(...getSwapQuoteSwapCalls(debtSwapQuote, "Aave debt migration"));
589
+ }
590
+ if (hasDebt) {
591
+ if (!debtAsset) {
592
+ throw new Error("Aave debt asset is required when source debt is present");
593
+ }
594
+ preTransferSwapperCalls.push(encodeGenericSwap({
595
+ target: pool,
596
+ tokenIn: debtAsset,
597
+ tokenOut: debtAsset,
598
+ payload: encodeFunctionData({
599
+ abi: aaveV3PoolAbi,
600
+ functionName: "repay",
601
+ args: [
602
+ debtAsset,
603
+ externalDebtRepayAmount,
604
+ AAVE_VARIABLE_INTEREST_RATE_MODE,
605
+ owner,
606
+ ],
607
+ }),
608
+ }));
609
+ if (debtSwapQuote) {
610
+ preTransferSwapperCalls.push(encodeFunctionData({
611
+ abi: swapperAbi,
612
+ functionName: "sweep",
613
+ args: [debtAsset, 0n, owner],
614
+ }));
615
+ }
616
+ }
617
+ if (preTransferSwapperCalls.length > 0) {
618
+ items.push({
619
+ targetContract: swapper,
620
+ onBehalfOfAccount: owner,
621
+ value: 0n,
622
+ data: encodeFunctionData({
623
+ abi: swapperAbi,
624
+ functionName: "multicall",
625
+ args: [preTransferSwapperCalls],
626
+ }),
627
+ });
628
+ }
629
+ items.push({
630
+ targetContract: swapVerifier,
631
+ onBehalfOfAccount: owner,
632
+ value: 0n,
633
+ data: encodeFunctionData({
634
+ abi: swapVerifierAbi,
635
+ functionName: "transferBalanceFromSender",
636
+ args: [aToken, collateralTransferMaxAmount, swapper],
637
+ }),
638
+ });
639
+ const postDepositRepayCall = hasDebt && targetBorrowVault
640
+ ? encodeFunctionData({
641
+ abi: swapperAbi,
642
+ functionName: "repay",
643
+ args: [
644
+ debtSwapQuote
645
+ ? getAddress(debtSwapQuote.tokenIn.address)
646
+ : debtAsset,
647
+ targetBorrowVault,
648
+ borrowAmount,
649
+ eulerAccount,
650
+ ],
651
+ })
652
+ : undefined;
653
+ const postTransferSwapperCalls = [];
654
+ postTransferSwapperCalls.push(encodeGenericSwap({
655
+ target: pool,
656
+ tokenIn: aToken,
657
+ tokenOut: args.position.raw.collateralAsset,
658
+ payload: encodeFunctionData({
659
+ abi: aaveV3PoolAbi,
660
+ functionName: "withdraw",
661
+ args: [
662
+ args.position.raw.collateralAsset,
663
+ maxUint256,
664
+ collateralSwapQuote ? swapper : swapVerifier,
665
+ ],
666
+ }),
667
+ }));
668
+ if (collateralSwapQuote) {
669
+ postTransferSwapperCalls.push(collateralSwapQuote.swap.swapperData);
670
+ if (postDepositRepayCall)
671
+ postTransferSwapperCalls.push(postDepositRepayCall);
672
+ }
673
+ items.push({
674
+ targetContract: swapper,
675
+ onBehalfOfAccount: owner,
676
+ value: 0n,
677
+ data: encodeFunctionData({
678
+ abi: swapperAbi,
679
+ functionName: "multicall",
680
+ args: [postTransferSwapperCalls],
681
+ }),
682
+ });
683
+ if (collateralSwapQuote && useDepositSwapVerification) {
684
+ items.push(encodeDepositVerifiedSwapQuoteItem({
685
+ quote: collateralSwapQuote,
686
+ swapVerifier,
687
+ vault: targetCollateralVault,
688
+ account: eulerAccount,
689
+ onBehalfOfAccount: owner,
690
+ deadline: verifierDeadline,
691
+ label: "Aave collateral migration",
692
+ }));
693
+ }
694
+ else if (collateralSwapQuote) {
695
+ items.push(encodeSwapQuoteVerificationItem({
696
+ quote: collateralSwapQuote,
697
+ swapVerifier,
698
+ vault: targetCollateralVault,
699
+ account: eulerAccount,
700
+ deadline: args.deadline ?? BigInt(collateralSwapQuote.verify.deadline ?? 0),
701
+ label: "Aave collateral migration",
702
+ }));
703
+ }
704
+ else {
705
+ items.push(encodeVerifyAmountMinAndDepositItem({
706
+ swapVerifier,
707
+ onBehalfOfAccount: owner,
708
+ vault: targetCollateralVault,
709
+ receiver: eulerAccount,
710
+ amountMin: collateralMinAmount,
711
+ deadline: verifierDeadline,
712
+ }));
713
+ if (postDepositRepayCall) {
714
+ items.push({
715
+ targetContract: swapper,
716
+ onBehalfOfAccount: owner,
717
+ value: 0n,
718
+ data: postDepositRepayCall,
719
+ });
720
+ }
721
+ }
722
+ return items;
723
+ }
724
+ async buildEulerToAaveBatch(args) {
725
+ if (args.collateralSwapQuote || args.debtSwapQuote) {
726
+ throw new Error("Aave Euler to Aave migration does not support swaps");
727
+ }
728
+ const source = assertEulerSource(args.source);
729
+ const owner = getAddress(args.owner);
730
+ const eulerAccount = getAddress(source.eulerAccount);
731
+ const sourceBorrowVault = getAddress(source.borrowVault);
732
+ const sourceCollateralVault = getAddress(source.collateralVault);
733
+ const pool = args.position.raw.pool;
734
+ const swapper = getSwapperAddress(this.deploymentService, args.chainId, source.swapper);
735
+ const sourceAmounts = await resolveEulerSourceAmounts(source, args.account);
736
+ const externalTarget = args.externalTarget ?? {};
737
+ const collateralAmount = externalTarget.collateralAmount ?? sourceAmounts.collateralAmount;
738
+ const sourceCollateralAmount = collateralAmount;
739
+ const redeemCollateralShares = externalTarget.collateralAmount === undefined
740
+ ? sourceAmounts.collateralShares
741
+ : undefined;
742
+ const aaveBorrowAmount = externalTarget.borrowAmount ??
743
+ applyBuffer(sourceAmounts.debtAmount, externalTarget.interestBufferBps ??
744
+ this.defaultOutboundInterestBufferBps);
745
+ const eulerRepayAmount = externalTarget.repayAmount ?? maxUint256;
746
+ const debtAsset = args.position.raw.debtAsset;
747
+ const debtReserve = args.position.raw.debtReserve;
748
+ if (!debtAsset || !debtReserve) {
749
+ throw new Error("Aave debt reserve is required for Euler to Aave migration");
750
+ }
751
+ const variableDebtToken = debtReserve.variableDebtTokenAddress;
752
+ if (sourceAmounts.debtAmount <= 0n) {
753
+ throw new Error("Euler source position has no debt to migrate");
754
+ }
755
+ if (sourceCollateralAmount <= 0n || collateralAmount <= 0n) {
756
+ throw new Error("Euler source position has no collateral to migrate");
757
+ }
758
+ if (aaveBorrowAmount <= 0n) {
759
+ throw new Error("Aave borrow amount must be greater than zero");
760
+ }
761
+ const swapVerifier = getSwapVerifierAddress(this.deploymentService, args.chainId);
762
+ const verifierDeadline = args.deadline ?? BigInt(Math.floor(Date.now() / 1000) + 60 * 60);
763
+ const items = [];
764
+ const needsDebtDelegation = args.skipAuthorizationCheck && args.authorization
765
+ ? true
766
+ : !(await this.hasBorrowAllowance(args.chainId, variableDebtToken, owner, swapVerifier, aaveBorrowAmount));
767
+ if (needsDebtDelegation) {
768
+ if (!args.authorization) {
769
+ throw new Error("Aave variable debt delegation for the Euler SwapVerifier is required");
770
+ }
771
+ items.push(this.encodeDebtDelegationItem({
772
+ owner,
773
+ swapVerifier,
774
+ variableDebtToken,
775
+ borrowAmount: aaveBorrowAmount,
776
+ authorization: args.authorization,
777
+ }));
778
+ }
779
+ items.push({
780
+ targetContract: sourceCollateralVault,
781
+ onBehalfOfAccount: eulerAccount,
782
+ value: 0n,
783
+ data: encodeFunctionData({
784
+ abi: eVaultAbi,
785
+ functionName: redeemCollateralShares ? "redeem" : "withdraw",
786
+ args: redeemCollateralShares
787
+ ? [redeemCollateralShares, swapper, eulerAccount]
788
+ : [sourceCollateralAmount, swapper, eulerAccount],
789
+ }),
790
+ });
791
+ const collateralAsset = args.position.raw.collateralAsset;
792
+ // Multicall #1: supply exact Aave collateral before borrowing.
793
+ const preBorrowCalls = [
794
+ encodeGenericSwap({
795
+ target: pool,
796
+ tokenIn: collateralAsset,
797
+ tokenOut: collateralAsset,
798
+ payload: encodeFunctionData({
799
+ abi: aaveV3PoolAbi,
800
+ functionName: "supply",
801
+ args: [collateralAsset, collateralAmount, owner, this.referralCode],
802
+ }),
803
+ }),
804
+ ];
805
+ items.push({
806
+ targetContract: swapper,
807
+ onBehalfOfAccount: owner,
808
+ value: 0n,
809
+ data: encodeFunctionData({
810
+ abi: swapperAbi,
811
+ functionName: "multicall",
812
+ args: [preBorrowCalls],
813
+ }),
814
+ });
815
+ // Top-level EVC item: borrow from Aave on behalf of the owner through the
816
+ // SwapVerifier (the standing credit delegation is granted to it), forwarding
817
+ // the borrowed debt asset to the Swapper.
818
+ items.push({
819
+ targetContract: swapVerifier,
820
+ onBehalfOfAccount: owner,
821
+ value: 0n,
822
+ data: encodeFunctionData({
823
+ abi: swapVerifierAbi,
824
+ functionName: "aaveBorrowForSender",
825
+ args: [pool, debtAsset, aaveBorrowAmount, swapper],
826
+ }),
827
+ });
828
+ // Multicall #2: repay the Euler source borrow vault and sweep any
829
+ // remainders back to the owner.
830
+ const postBorrowCalls = [
831
+ encodeFunctionData({
832
+ abi: swapperAbi,
833
+ functionName: "repay",
834
+ args: [debtAsset, sourceBorrowVault, eulerRepayAmount, eulerAccount],
835
+ }),
836
+ ];
837
+ postBorrowCalls.push(encodeFunctionData({
838
+ abi: swapperAbi,
839
+ functionName: "sweep",
840
+ args: [debtAsset, 0n, owner],
841
+ }));
842
+ // Return collateral remainders from yield-bearing source-vault share drift
843
+ // to the owner rather than stranding them.
844
+ postBorrowCalls.push(encodeFunctionData({
845
+ abi: swapperAbi,
846
+ functionName: "sweep",
847
+ args: [collateralAsset, 0n, owner],
848
+ }));
849
+ items.push({
850
+ targetContract: swapper,
851
+ onBehalfOfAccount: owner,
852
+ value: 0n,
853
+ data: encodeFunctionData({
854
+ abi: swapperAbi,
855
+ functionName: "multicall",
856
+ args: [postBorrowCalls],
857
+ }),
858
+ });
859
+ items.push(encodeVerifyDebtMaxItem({
860
+ swapVerifier,
861
+ onBehalfOfAccount: owner,
862
+ vault: sourceBorrowVault,
863
+ account: eulerAccount,
864
+ amountMax: 0n,
865
+ deadline: verifierDeadline,
866
+ }));
867
+ return items;
868
+ }
869
+ async buildATokenPermitRequest(args) {
870
+ const provider = this.providerService.getProvider(args.chainId);
871
+ const [name, nonce] = (await provider.multicall({
872
+ contracts: [
873
+ {
874
+ address: args.token,
875
+ abi: aaveATokenAbi,
876
+ functionName: "name",
877
+ },
878
+ {
879
+ address: args.token,
880
+ abi: aaveATokenAbi,
881
+ functionName: "nonces",
882
+ args: [args.owner],
883
+ },
884
+ ],
885
+ allowFailure: false,
886
+ }));
887
+ const message = {
888
+ owner: args.owner,
889
+ spender: args.spender,
890
+ value: args.value,
891
+ nonce,
892
+ deadline: args.deadline ?? BigInt(Math.floor(Date.now() / 1000) + 60 * 60),
893
+ };
894
+ return {
895
+ kind: "typedData",
896
+ authorizationType: "aTokenPermit",
897
+ connectorId: AAVE_CONNECTOR_ID,
898
+ protocol: AAVE_PROTOCOL,
899
+ chainId: args.chainId,
900
+ owner: args.owner,
901
+ positionId: args.positionId,
902
+ token: args.token,
903
+ typedData: {
904
+ domain: {
905
+ name,
906
+ version: "1",
907
+ chainId: args.chainId,
908
+ verifyingContract: args.token,
909
+ },
910
+ types: AAVE_PERMIT_TYPES,
911
+ primaryType: "Permit",
912
+ message,
913
+ },
914
+ };
915
+ }
916
+ async buildDebtDelegationRequest(args) {
917
+ const provider = this.providerService.getProvider(args.chainId);
918
+ const [name, nonce] = (await provider.multicall({
919
+ contracts: [
920
+ {
921
+ address: args.token,
922
+ abi: aaveDebtTokenAbi,
923
+ functionName: "name",
924
+ },
925
+ {
926
+ address: args.token,
927
+ abi: aaveDebtTokenAbi,
928
+ functionName: "nonces",
929
+ args: [args.delegator],
930
+ },
931
+ ],
932
+ allowFailure: false,
933
+ }));
934
+ const message = {
935
+ delegatee: args.delegatee,
936
+ value: args.value,
937
+ nonce,
938
+ deadline: args.deadline ?? BigInt(Math.floor(Date.now() / 1000) + 60 * 60),
939
+ };
940
+ return {
941
+ kind: "typedData",
942
+ authorizationType: "variableDebtDelegation",
943
+ connectorId: AAVE_CONNECTOR_ID,
944
+ protocol: AAVE_PROTOCOL,
945
+ chainId: args.chainId,
946
+ owner: args.delegator,
947
+ positionId: args.positionId,
948
+ token: args.token,
949
+ delegator: args.delegator,
950
+ typedData: {
951
+ domain: {
952
+ name,
953
+ version: "1",
954
+ chainId: args.chainId,
955
+ verifyingContract: args.token,
956
+ },
957
+ types: AAVE_DELEGATION_TYPES,
958
+ primaryType: "DelegationWithSig",
959
+ message,
960
+ },
961
+ };
962
+ }
963
+ encodeATokenPermitItem(args) {
964
+ const request = assertAaveAuthorizationRequest(args.authorization.request, "aTokenPermit");
965
+ if (!args.authorization.signature) {
966
+ throw new Error("Aave aToken permit signature is required");
967
+ }
968
+ const message = toAavePermitMessage(request.typedData.message);
969
+ assertSameAddress(message.owner, args.owner, "Aave permit owner mismatch");
970
+ assertSameAddress(message.spender, args.swapVerifier, "Aave permit spender must be the Euler SwapVerifier");
971
+ assertSameAddress(request.token, args.aToken, "Aave permit token mismatch");
972
+ if (message.value < args.maxAmount) {
973
+ throw new Error("Aave permit value is below the capped transfer amount");
974
+ }
975
+ const signature = splitAaveSignature(args.authorization.signature);
976
+ return {
977
+ targetContract: args.aToken,
978
+ onBehalfOfAccount: args.owner,
979
+ value: 0n,
980
+ data: encodeFunctionData({
981
+ abi: aaveATokenAbi,
982
+ functionName: "permit",
983
+ args: [
984
+ message.owner,
985
+ message.spender,
986
+ message.value,
987
+ message.deadline,
988
+ signature.v,
989
+ signature.r,
990
+ signature.s,
991
+ ],
992
+ }),
993
+ };
994
+ }
995
+ encodeDebtDelegationItem(args) {
996
+ const request = assertAaveAuthorizationRequest(args.authorization.request, "variableDebtDelegation");
997
+ if (!args.authorization.signature) {
998
+ throw new Error("Aave debt delegation signature is required");
999
+ }
1000
+ const message = toAaveDelegationMessage(request.typedData.message);
1001
+ assertSameAddress(request.delegator, args.owner, "Aave delegation owner mismatch");
1002
+ assertSameAddress(message.delegatee, args.swapVerifier, "Aave delegation delegatee must be the Euler SwapVerifier");
1003
+ assertSameAddress(request.token, args.variableDebtToken, "Aave delegation token mismatch");
1004
+ if (message.value < args.borrowAmount) {
1005
+ throw new Error("Aave delegation value is below the borrow amount");
1006
+ }
1007
+ const signature = splitAaveSignature(args.authorization.signature);
1008
+ return {
1009
+ targetContract: args.variableDebtToken,
1010
+ onBehalfOfAccount: args.owner,
1011
+ value: 0n,
1012
+ data: encodeFunctionData({
1013
+ abi: aaveDebtTokenAbi,
1014
+ functionName: "delegationWithSig",
1015
+ args: [
1016
+ args.owner,
1017
+ message.delegatee,
1018
+ message.value,
1019
+ message.deadline,
1020
+ signature.v,
1021
+ signature.r,
1022
+ signature.s,
1023
+ ],
1024
+ }),
1025
+ };
1026
+ }
1027
+ async hasATokenAllowance(chainId, aToken, owner, spender, amount) {
1028
+ const provider = this.providerService.getProvider(chainId);
1029
+ const allowance = (await provider.readContract({
1030
+ address: aToken,
1031
+ abi: aaveATokenAbi,
1032
+ functionName: "allowance",
1033
+ args: [owner, spender],
1034
+ }));
1035
+ return allowance >= amount;
1036
+ }
1037
+ async hasBorrowAllowance(chainId, debtToken, owner, delegatee, amount) {
1038
+ const provider = this.providerService.getProvider(chainId);
1039
+ const allowance = (await provider.readContract({
1040
+ address: debtToken,
1041
+ abi: aaveDebtTokenAbi,
1042
+ functionName: "borrowAllowance",
1043
+ args: [owner, delegatee],
1044
+ }));
1045
+ return allowance >= amount;
1046
+ }
1047
+ }
1048
+ function normalizeAavePositionRef(positionRef, pool) {
1049
+ return {
1050
+ pool: getAddress(pool),
1051
+ collateralAsset: getAddress(positionRef.collateralAsset),
1052
+ ...(positionRef.debtAsset
1053
+ ? { debtAsset: getAddress(positionRef.debtAsset) }
1054
+ : {}),
1055
+ };
1056
+ }
1057
+ function toAaveGraphqlTarget(args) {
1058
+ const pool = getAddress(args.market.address);
1059
+ const collateralReserveRow = args.market.reserves.find((reserve) => sameAddress(reserve.underlyingToken.address, args.collateralAsset));
1060
+ const debtReserveRow = args.market.reserves.find((reserve) => sameAddress(reserve.underlyingToken.address, args.debtAsset));
1061
+ if (!collateralReserveRow || !debtReserveRow)
1062
+ return null;
1063
+ if (!isUsableGraphqlCollateralReserve(collateralReserveRow) ||
1064
+ !isUsableGraphqlBorrowReserve(debtReserveRow)) {
1065
+ return null;
1066
+ }
1067
+ const availableLiquidity = BigInt(debtReserveRow.borrowInfo?.availableLiquidity.amount.raw ?? "0");
1068
+ if (args.minLiquidity !== undefined &&
1069
+ availableLiquidity < args.minLiquidity) {
1070
+ return null;
1071
+ }
1072
+ const totalSupplied = BigInt(debtReserveRow.supplyInfo.total.raw);
1073
+ const ref = {
1074
+ pool,
1075
+ collateralAsset: args.collateralAsset,
1076
+ debtAsset: args.debtAsset,
1077
+ };
1078
+ const raw = {
1079
+ pool,
1080
+ marketName: args.market.name,
1081
+ collateralReserve: toReserveDataFromGraphql(collateralReserveRow),
1082
+ debtReserve: toReserveDataFromGraphql(debtReserveRow),
1083
+ availableLiquidity,
1084
+ totalSupplied,
1085
+ totalMarketSizeUsd: args.market.totalMarketSize,
1086
+ totalAvailableLiquidityUsd: args.market.totalAvailableLiquidity,
1087
+ };
1088
+ const extraData = {
1089
+ marketName: args.market.name,
1090
+ pool,
1091
+ availableLiquidity,
1092
+ totalSupplied,
1093
+ totalMarketSizeUsd: args.market.totalMarketSize,
1094
+ totalAvailableLiquidityUsd: args.market.totalAvailableLiquidity,
1095
+ };
1096
+ return {
1097
+ connectorId: AAVE_CONNECTOR_ID,
1098
+ protocol: AAVE_PROTOCOL,
1099
+ id: getAavePositionId(ref),
1100
+ chainId: args.chainId,
1101
+ ref,
1102
+ debt: {
1103
+ asset: args.debtAsset,
1104
+ symbol: debtReserveRow.underlyingToken.symbol,
1105
+ decimals: debtReserveRow.underlyingToken.decimals,
1106
+ },
1107
+ collateral: {
1108
+ asset: args.collateralAsset,
1109
+ symbol: collateralReserveRow.underlyingToken.symbol,
1110
+ decimals: collateralReserveRow.underlyingToken.decimals,
1111
+ },
1112
+ liquidity: { asset: args.debtAsset, amount: availableLiquidity },
1113
+ raw,
1114
+ extraData,
1115
+ };
1116
+ }
1117
+ function toReserveDataFromGraphql(reserve) {
1118
+ return {
1119
+ aTokenAddress: getAddress(reserve.aToken.address),
1120
+ stableDebtTokenAddress: ZERO_ADDRESS,
1121
+ variableDebtTokenAddress: getAddress(reserve.vToken.address),
1122
+ configurationData: toReserveConfigurationDataFromGraphql(reserve),
1123
+ };
1124
+ }
1125
+ function toReserveConfigurationDataFromGraphql(reserve) {
1126
+ let data = BigInt(reserve.supplyInfo.maxLTV.raw) & AAVE_LTV_MASK;
1127
+ data |= 1n << AAVE_ACTIVE_BIT;
1128
+ if (reserve.isFrozen)
1129
+ data |= 1n << AAVE_FROZEN_BIT;
1130
+ if (reserve.isPaused)
1131
+ data |= 1n << AAVE_PAUSED_BIT;
1132
+ if (reserve.borrowInfo?.borrowingState === "ENABLED") {
1133
+ data |= 1n << AAVE_BORROWING_BIT;
1134
+ }
1135
+ return data;
1136
+ }
1137
+ function isUsableGraphqlCollateralReserve(reserve) {
1138
+ return (isNonZeroAddress(getAddress(reserve.aToken.address)) &&
1139
+ !reserve.isFrozen &&
1140
+ !reserve.isPaused &&
1141
+ reserve.supplyInfo.canBeCollateral &&
1142
+ BigInt(reserve.supplyInfo.maxLTV.raw) > 0n);
1143
+ }
1144
+ function isUsableGraphqlBorrowReserve(reserve) {
1145
+ return (isNonZeroAddress(getAddress(reserve.vToken.address)) &&
1146
+ !reserve.isFrozen &&
1147
+ !reserve.isPaused &&
1148
+ reserve.borrowInfo?.borrowingState === "ENABLED");
1149
+ }
1150
+ async function readAaveAvailableLiquidity(provider, debtAsset, debtAToken) {
1151
+ try {
1152
+ const value = await provider.readContract({
1153
+ address: debtAsset,
1154
+ abi: aaveATokenAbi,
1155
+ functionName: "balanceOf",
1156
+ args: [debtAToken],
1157
+ });
1158
+ return typeof value === "bigint" ? value : undefined;
1159
+ }
1160
+ catch {
1161
+ return undefined;
1162
+ }
1163
+ }
1164
+ async function readAaveTotalSupplied(provider, debtAToken) {
1165
+ try {
1166
+ const value = await provider.readContract({
1167
+ address: debtAToken,
1168
+ abi: aaveATokenAbi,
1169
+ functionName: "totalSupply",
1170
+ });
1171
+ return typeof value === "bigint" ? value : undefined;
1172
+ }
1173
+ catch {
1174
+ return undefined;
1175
+ }
1176
+ }
1177
+ function toReserveTokens(result) {
1178
+ const reserve = result;
1179
+ return {
1180
+ aTokenAddress: getAddress((reserve.aTokenAddress ?? reserve[8])),
1181
+ stableDebtTokenAddress: getAddress((reserve.stableDebtTokenAddress ?? reserve[9])),
1182
+ variableDebtTokenAddress: getAddress((reserve.variableDebtTokenAddress ?? reserve[10])),
1183
+ };
1184
+ }
1185
+ function toReserveData(result) {
1186
+ return {
1187
+ ...toReserveTokens(result),
1188
+ configurationData: toReserveConfigurationData(result),
1189
+ };
1190
+ }
1191
+ function toReserveConfigurationData(result) {
1192
+ const reserve = result;
1193
+ const configuration = reserve.configuration ?? reserve[0];
1194
+ const data = configuration &&
1195
+ typeof configuration === "object" &&
1196
+ "data" in configuration
1197
+ ? configuration.data
1198
+ : configuration;
1199
+ return data === undefined || data === null
1200
+ ? 0n
1201
+ : BigInt(data);
1202
+ }
1203
+ function isUsableCollateralReserve(reserve) {
1204
+ return (isNonZeroAddress(reserve.aTokenAddress) &&
1205
+ isReserveActive(reserve.configurationData) &&
1206
+ !isReserveFrozen(reserve.configurationData) &&
1207
+ !isReservePaused(reserve.configurationData) &&
1208
+ getReserveLtv(reserve.configurationData) > 0n);
1209
+ }
1210
+ function isUsableBorrowReserve(reserve) {
1211
+ return (isNonZeroAddress(reserve.variableDebtTokenAddress) &&
1212
+ isReserveActive(reserve.configurationData) &&
1213
+ !isReserveFrozen(reserve.configurationData) &&
1214
+ !isReservePaused(reserve.configurationData) &&
1215
+ isReserveBorrowingEnabled(reserve.configurationData));
1216
+ }
1217
+ function getReserveLtv(configurationData) {
1218
+ return configurationData & AAVE_LTV_MASK;
1219
+ }
1220
+ function isReserveActive(configurationData) {
1221
+ return isBitSet(configurationData, AAVE_ACTIVE_BIT);
1222
+ }
1223
+ function isReserveFrozen(configurationData) {
1224
+ return isBitSet(configurationData, AAVE_FROZEN_BIT);
1225
+ }
1226
+ function isReserveBorrowingEnabled(configurationData) {
1227
+ return isBitSet(configurationData, AAVE_BORROWING_BIT);
1228
+ }
1229
+ function isReservePaused(configurationData) {
1230
+ return isBitSet(configurationData, AAVE_PAUSED_BIT);
1231
+ }
1232
+ function isBitSet(value, bit) {
1233
+ return ((value >> bit) & 1n) === 1n;
1234
+ }
1235
+ function isNonZeroAddress(address) {
1236
+ return getAddress(address) !== ZERO_ADDRESS;
1237
+ }
1238
+ function sameAddress(a, b) {
1239
+ return getAddress(a) === getAddress(b);
1240
+ }
1241
+ function normalizeAaveDeployments(deployments) {
1242
+ const seen = new Set();
1243
+ const normalized = [];
1244
+ for (const deployment of deployments) {
1245
+ const chainId = Number(deployment.chainId);
1246
+ const pool = getAddress(deployment.pool);
1247
+ const key = `${chainId}:${pool.toLowerCase()}`;
1248
+ if (seen.has(key))
1249
+ continue;
1250
+ seen.add(key);
1251
+ normalized.push({
1252
+ chainId,
1253
+ pool,
1254
+ ...(deployment.marketName ? { marketName: deployment.marketName } : {}),
1255
+ });
1256
+ }
1257
+ return normalized;
1258
+ }
1259
+ function assertAavePosition(position) {
1260
+ if (!position || position.connectorId !== AAVE_CONNECTOR_ID) {
1261
+ throw new Error("Aave migration position is required");
1262
+ }
1263
+ return position;
1264
+ }
1265
+ function assertAaveAuthorizationRequest(request, authorizationType) {
1266
+ const aaveRequest = request;
1267
+ if (request.kind !== "typedData" ||
1268
+ request.connectorId !== AAVE_CONNECTOR_ID ||
1269
+ aaveRequest.authorizationType !== authorizationType) {
1270
+ throw new Error(`Expected an Aave ${authorizationType} authorization request`);
1271
+ }
1272
+ return aaveRequest;
1273
+ }
1274
+ function toAavePermitMessage(message) {
1275
+ return {
1276
+ owner: getAddress(message.owner),
1277
+ spender: getAddress(message.spender),
1278
+ value: BigInt(message.value),
1279
+ nonce: BigInt(message.nonce),
1280
+ deadline: BigInt(message.deadline),
1281
+ };
1282
+ }
1283
+ function toAaveDelegationMessage(message) {
1284
+ return {
1285
+ delegatee: getAddress(message.delegatee),
1286
+ value: BigInt(message.value),
1287
+ nonce: BigInt(message.nonce),
1288
+ deadline: BigInt(message.deadline),
1289
+ };
1290
+ }
1291
+ //# sourceMappingURL=aaveConnector.js.map