@elizaos/plugin-aave 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,2923 @@
1
+ import { Service, elizaLogger, ModelType } from '@elizaos/core';
2
+ import { Pool, UiPoolDataProvider } from '@aave/contract-helpers';
3
+ import { formatReserves, formatUserSummary } from '@aave/math-utils';
4
+ import { ethers } from 'ethers';
5
+ import BigNumber3, { BigNumber } from 'bignumber.js';
6
+ import { AaveV3BaseSepolia, AaveV3OptimismSepolia, AaveV3ArbitrumSepolia, AaveV3Fuji, AaveV3Sepolia, AaveV3ZkSync, AaveV3Scroll, AaveV3Metis, AaveV3Gnosis, AaveV3BNB, AaveV3Base, AaveV3Optimism, AaveV3Arbitrum, AaveV3Avalanche, AaveV3Polygon, AaveV3Ethereum } from '@bgd-labs/aave-address-book';
7
+
8
+ // src/services/aave-service.ts
9
+
10
+ // src/types/chains.ts
11
+ var SupportedChain = /* @__PURE__ */ ((SupportedChain2) => {
12
+ SupportedChain2["ETHEREUM"] = "ethereum";
13
+ SupportedChain2["POLYGON"] = "polygon";
14
+ SupportedChain2["AVALANCHE"] = "avalanche";
15
+ SupportedChain2["ARBITRUM"] = "arbitrum";
16
+ SupportedChain2["OPTIMISM"] = "optimism";
17
+ SupportedChain2["BASE"] = "base";
18
+ SupportedChain2["BNB"] = "bnb";
19
+ SupportedChain2["GNOSIS"] = "gnosis";
20
+ SupportedChain2["METIS"] = "metis";
21
+ SupportedChain2["SCROLL"] = "scroll";
22
+ SupportedChain2["ZKSYNC"] = "zksync";
23
+ SupportedChain2["SEPOLIA"] = "sepolia";
24
+ SupportedChain2["FUJI"] = "fuji";
25
+ SupportedChain2["ARBITRUM_SEPOLIA"] = "arbitrum-sepolia";
26
+ SupportedChain2["OPTIMISM_SEPOLIA"] = "optimism-sepolia";
27
+ SupportedChain2["BASE_SEPOLIA"] = "base-sepolia";
28
+ return SupportedChain2;
29
+ })(SupportedChain || {});
30
+ var CHAIN_CONFIGS = {
31
+ ["ethereum" /* ETHEREUM */]: {
32
+ name: "Ethereum",
33
+ chainId: 1,
34
+ nativeCurrency: "ETH",
35
+ wrappedNative: "WETH",
36
+ defaultRpcUrl: "https://eth.llamarpc.com",
37
+ isTestnet: false,
38
+ popularAssets: ["USDC", "USDT", "DAI", "WETH", "WBTC", "LINK", "AAVE"]
39
+ },
40
+ ["polygon" /* POLYGON */]: {
41
+ name: "Polygon",
42
+ chainId: 137,
43
+ nativeCurrency: "MATIC",
44
+ wrappedNative: "WMATIC",
45
+ defaultRpcUrl: "https://polygon-rpc.com",
46
+ isTestnet: false,
47
+ popularAssets: ["USDC", "USDT", "DAI", "WMATIC", "WETH", "WBTC", "AAVE"]
48
+ },
49
+ ["avalanche" /* AVALANCHE */]: {
50
+ name: "Avalanche",
51
+ chainId: 43114,
52
+ nativeCurrency: "AVAX",
53
+ wrappedNative: "WAVAX",
54
+ defaultRpcUrl: "https://api.avax.network/ext/bc/C/rpc",
55
+ isTestnet: false,
56
+ popularAssets: ["USDC", "USDT", "DAI.e", "WAVAX", "WETH.e", "WBTC.e", "AAVE.e"]
57
+ },
58
+ ["arbitrum" /* ARBITRUM */]: {
59
+ name: "Arbitrum One",
60
+ chainId: 42161,
61
+ nativeCurrency: "ETH",
62
+ wrappedNative: "WETH",
63
+ defaultRpcUrl: "https://arb1.arbitrum.io/rpc",
64
+ isTestnet: false,
65
+ popularAssets: ["USDC", "USDT", "DAI", "WETH", "WBTC", "LINK", "ARB"]
66
+ },
67
+ ["optimism" /* OPTIMISM */]: {
68
+ name: "Optimism",
69
+ chainId: 10,
70
+ nativeCurrency: "ETH",
71
+ wrappedNative: "WETH",
72
+ defaultRpcUrl: "https://mainnet.optimism.io",
73
+ isTestnet: false,
74
+ popularAssets: ["USDC", "USDT", "DAI", "WETH", "WBTC", "LINK", "OP"]
75
+ },
76
+ ["base" /* BASE */]: {
77
+ name: "Base",
78
+ chainId: 8453,
79
+ nativeCurrency: "ETH",
80
+ wrappedNative: "WETH",
81
+ defaultRpcUrl: "https://mainnet.base.org",
82
+ isTestnet: false,
83
+ popularAssets: ["USDC", "DAI", "WETH", "cbETH", "AERO"]
84
+ },
85
+ ["bnb" /* BNB */]: {
86
+ name: "BNB Chain",
87
+ chainId: 56,
88
+ nativeCurrency: "BNB",
89
+ wrappedNative: "WBNB",
90
+ defaultRpcUrl: "https://bsc-dataseed1.binance.org",
91
+ isTestnet: false,
92
+ popularAssets: ["USDC", "USDT", "WBNB", "BTCB", "ETH", "FDUSD"]
93
+ },
94
+ ["gnosis" /* GNOSIS */]: {
95
+ name: "Gnosis Chain",
96
+ chainId: 100,
97
+ nativeCurrency: "xDAI",
98
+ wrappedNative: "WXDAI",
99
+ defaultRpcUrl: "https://rpc.gnosischain.com",
100
+ isTestnet: false,
101
+ popularAssets: ["USDC", "WXDAI", "WETH", "GNO"]
102
+ },
103
+ ["metis" /* METIS */]: {
104
+ name: "Metis",
105
+ chainId: 1088,
106
+ nativeCurrency: "METIS",
107
+ wrappedNative: "WMETIS",
108
+ defaultRpcUrl: "https://andromeda.metis.io/?owner=1088",
109
+ isTestnet: false,
110
+ popularAssets: ["m.USDC", "m.USDT", "m.DAI", "WMETIS", "METIS"]
111
+ },
112
+ ["scroll" /* SCROLL */]: {
113
+ name: "Scroll",
114
+ chainId: 534352,
115
+ nativeCurrency: "ETH",
116
+ wrappedNative: "WETH",
117
+ defaultRpcUrl: "https://rpc.scroll.io",
118
+ isTestnet: false,
119
+ popularAssets: ["USDC", "USDT", "WETH", "WBTC"]
120
+ },
121
+ ["zksync" /* ZKSYNC */]: {
122
+ name: "zkSync Era",
123
+ chainId: 324,
124
+ nativeCurrency: "ETH",
125
+ wrappedNative: "WETH",
126
+ defaultRpcUrl: "https://mainnet.era.zksync.io",
127
+ isTestnet: false,
128
+ popularAssets: ["USDC", "USDT", "WETH", "WBTC"]
129
+ },
130
+ // Testnets
131
+ ["sepolia" /* SEPOLIA */]: {
132
+ name: "Ethereum Sepolia",
133
+ chainId: 11155111,
134
+ nativeCurrency: "ETH",
135
+ wrappedNative: "WETH",
136
+ defaultRpcUrl: "https://sepolia.infura.io/v3/demo",
137
+ isTestnet: true,
138
+ popularAssets: ["USDC", "USDT", "DAI", "WETH", "LINK", "AAVE"]
139
+ },
140
+ ["fuji" /* FUJI */]: {
141
+ name: "Avalanche Fuji",
142
+ chainId: 43113,
143
+ nativeCurrency: "AVAX",
144
+ wrappedNative: "WAVAX",
145
+ defaultRpcUrl: "https://api.avax-test.network/ext/bc/C/rpc",
146
+ isTestnet: true,
147
+ popularAssets: ["USDC", "WAVAX", "WETH.e"]
148
+ },
149
+ ["arbitrum-sepolia" /* ARBITRUM_SEPOLIA */]: {
150
+ name: "Arbitrum Sepolia",
151
+ chainId: 421614,
152
+ nativeCurrency: "ETH",
153
+ wrappedNative: "WETH",
154
+ defaultRpcUrl: "https://sepolia-rollup.arbitrum.io/rpc",
155
+ isTestnet: true,
156
+ popularAssets: ["USDC", "WETH"]
157
+ },
158
+ ["optimism-sepolia" /* OPTIMISM_SEPOLIA */]: {
159
+ name: "Optimism Sepolia",
160
+ chainId: 11155420,
161
+ nativeCurrency: "ETH",
162
+ wrappedNative: "WETH",
163
+ defaultRpcUrl: "https://sepolia.optimism.io",
164
+ isTestnet: true,
165
+ popularAssets: ["USDC", "WETH"]
166
+ },
167
+ ["base-sepolia" /* BASE_SEPOLIA */]: {
168
+ name: "Base Sepolia",
169
+ chainId: 84532,
170
+ nativeCurrency: "ETH",
171
+ wrappedNative: "WETH",
172
+ defaultRpcUrl: "https://sepolia.base.org",
173
+ isTestnet: true,
174
+ popularAssets: ["USDC", "WETH"]
175
+ }
176
+ };
177
+ var InterestRateMode = /* @__PURE__ */ ((InterestRateMode2) => {
178
+ InterestRateMode2[InterestRateMode2["STABLE"] = 1] = "STABLE";
179
+ InterestRateMode2[InterestRateMode2["VARIABLE"] = 2] = "VARIABLE";
180
+ return InterestRateMode2;
181
+ })(InterestRateMode || {});
182
+ var AaveErrorCode = /* @__PURE__ */ ((AaveErrorCode2) => {
183
+ AaveErrorCode2["UNKNOWN"] = "UNKNOWN";
184
+ AaveErrorCode2["INSUFFICIENT_BALANCE"] = "INSUFFICIENT_BALANCE";
185
+ AaveErrorCode2["INSUFFICIENT_COLLATERAL"] = "INSUFFICIENT_COLLATERAL";
186
+ AaveErrorCode2["ASSET_NOT_SUPPORTED"] = "ASSET_NOT_SUPPORTED";
187
+ AaveErrorCode2["BORROWING_NOT_ENABLED"] = "BORROWING_NOT_ENABLED";
188
+ AaveErrorCode2["STABLE_BORROWING_NOT_ENABLED"] = "STABLE_BORROWING_NOT_ENABLED";
189
+ AaveErrorCode2["HEALTH_FACTOR_TOO_LOW"] = "HEALTH_FACTOR_TOO_LOW";
190
+ AaveErrorCode2["TRANSACTION_FAILED"] = "TRANSACTION_FAILED";
191
+ AaveErrorCode2["INVALID_PARAMETERS"] = "INVALID_PARAMETERS";
192
+ AaveErrorCode2["USER_HAS_STABLE_RATE_LOAN"] = "USER_HAS_STABLE_RATE_LOAN";
193
+ AaveErrorCode2["AMOUNT_TOO_HIGH"] = "AMOUNT_TOO_HIGH";
194
+ AaveErrorCode2["POOL_PAUSED"] = "POOL_PAUSED";
195
+ AaveErrorCode2["RESERVE_FROZEN"] = "RESERVE_FROZEN";
196
+ AaveErrorCode2["RESERVE_INACTIVE"] = "RESERVE_INACTIVE";
197
+ AaveErrorCode2["INITIALIZATION_FAILED"] = "INITIALIZATION_FAILED";
198
+ AaveErrorCode2["CONNECTION_FAILED"] = "CONNECTION_FAILED";
199
+ AaveErrorCode2["SERVICE_NOT_INITIALIZED"] = "SERVICE_NOT_INITIALIZED";
200
+ AaveErrorCode2["WALLET_NOT_CONNECTED"] = "WALLET_NOT_CONNECTED";
201
+ AaveErrorCode2["TRANSACTION_GENERATION_FAILED"] = "TRANSACTION_GENERATION_FAILED";
202
+ AaveErrorCode2["SUPPLY_FAILED"] = "SUPPLY_FAILED";
203
+ AaveErrorCode2["WITHDRAW_FAILED"] = "WITHDRAW_FAILED";
204
+ AaveErrorCode2["BORROW_FAILED"] = "BORROW_FAILED";
205
+ AaveErrorCode2["REPAY_FAILED"] = "REPAY_FAILED";
206
+ AaveErrorCode2["DATA_FETCH_FAILED"] = "DATA_FETCH_FAILED";
207
+ AaveErrorCode2["ASSET_NOT_FOUND"] = "ASSET_NOT_FOUND";
208
+ AaveErrorCode2["UNSUPPORTED_ASSET"] = "UNSUPPORTED_ASSET";
209
+ AaveErrorCode2["NO_BORROW_CAPACITY"] = "NO_BORROW_CAPACITY";
210
+ AaveErrorCode2["UNSUPPORTED_OPERATION"] = "UNSUPPORTED_OPERATION";
211
+ return AaveErrorCode2;
212
+ })(AaveErrorCode || {});
213
+ var AaveError = class extends Error {
214
+ /** Error code for programmatic handling */
215
+ code;
216
+ /** Original error that caused this error */
217
+ cause;
218
+ /** Additional context about the error */
219
+ context;
220
+ constructor(message, code = "UNKNOWN" /* UNKNOWN */, cause, context) {
221
+ super(message);
222
+ this.name = "AaveError";
223
+ this.code = code;
224
+ this.cause = cause;
225
+ this.context = context;
226
+ }
227
+ };
228
+ var AAVE_CONSTANTS = {
229
+ /** Maximum uint256 value for unlimited approvals/withdrawals */
230
+ MAX_UINT256: new BigNumber("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
231
+ /** Number of seconds in a year for APY calculations */
232
+ SECONDS_PER_YEAR: new BigNumber(31536e3),
233
+ /** Number of ray units (1e27) used by Aave for rate calculations */
234
+ RAY: new BigNumber("1000000000000000000000000000"),
235
+ /** Number of wei units (1e18) */
236
+ WAD: new BigNumber("1000000000000000000"),
237
+ /** Percentage multiplier (100 for percentage) */
238
+ PERCENTAGE_FACTOR: new BigNumber(1e4)
239
+ };
240
+ function isAaveError(error) {
241
+ return error instanceof AaveError;
242
+ }
243
+ function isValidInterestRateMode(mode) {
244
+ return mode === 1 /* STABLE */ || mode === 2 /* VARIABLE */;
245
+ }
246
+
247
+ // src/utils/chain-resolver.ts
248
+ var CHAIN_ADDRESS_MAP = {
249
+ // Mainnets
250
+ ["ethereum" /* ETHEREUM */]: {
251
+ POOL: AaveV3Ethereum.POOL,
252
+ POOL_ADDRESSES_PROVIDER: AaveV3Ethereum.POOL_ADDRESSES_PROVIDER,
253
+ AAVE_PROTOCOL_DATA_PROVIDER: AaveV3Ethereum.AAVE_PROTOCOL_DATA_PROVIDER,
254
+ UI_POOL_DATA_PROVIDER: AaveV3Ethereum.UI_POOL_DATA_PROVIDER,
255
+ WETH_GATEWAY: AaveV3Ethereum.WETH_GATEWAY,
256
+ ACL_MANAGER: AaveV3Ethereum.ACL_MANAGER,
257
+ COLLECTOR: AaveV3Ethereum.COLLECTOR,
258
+ ORACLE: AaveV3Ethereum.ORACLE
259
+ },
260
+ ["polygon" /* POLYGON */]: {
261
+ POOL: AaveV3Polygon.POOL,
262
+ POOL_ADDRESSES_PROVIDER: AaveV3Polygon.POOL_ADDRESSES_PROVIDER,
263
+ AAVE_PROTOCOL_DATA_PROVIDER: AaveV3Polygon.AAVE_PROTOCOL_DATA_PROVIDER,
264
+ UI_POOL_DATA_PROVIDER: AaveV3Polygon.UI_POOL_DATA_PROVIDER,
265
+ WETH_GATEWAY: AaveV3Polygon.WETH_GATEWAY,
266
+ ACL_MANAGER: AaveV3Polygon.ACL_MANAGER,
267
+ COLLECTOR: AaveV3Polygon.COLLECTOR,
268
+ ORACLE: AaveV3Polygon.ORACLE
269
+ },
270
+ ["avalanche" /* AVALANCHE */]: {
271
+ POOL: AaveV3Avalanche.POOL,
272
+ POOL_ADDRESSES_PROVIDER: AaveV3Avalanche.POOL_ADDRESSES_PROVIDER,
273
+ AAVE_PROTOCOL_DATA_PROVIDER: AaveV3Avalanche.AAVE_PROTOCOL_DATA_PROVIDER,
274
+ UI_POOL_DATA_PROVIDER: AaveV3Avalanche.UI_POOL_DATA_PROVIDER,
275
+ WETH_GATEWAY: AaveV3Avalanche.WETH_GATEWAY,
276
+ ACL_MANAGER: AaveV3Avalanche.ACL_MANAGER,
277
+ COLLECTOR: AaveV3Avalanche.COLLECTOR,
278
+ ORACLE: AaveV3Avalanche.ORACLE
279
+ },
280
+ ["arbitrum" /* ARBITRUM */]: {
281
+ POOL: AaveV3Arbitrum.POOL,
282
+ POOL_ADDRESSES_PROVIDER: AaveV3Arbitrum.POOL_ADDRESSES_PROVIDER,
283
+ AAVE_PROTOCOL_DATA_PROVIDER: AaveV3Arbitrum.AAVE_PROTOCOL_DATA_PROVIDER,
284
+ UI_POOL_DATA_PROVIDER: AaveV3Arbitrum.UI_POOL_DATA_PROVIDER,
285
+ WETH_GATEWAY: AaveV3Arbitrum.WETH_GATEWAY,
286
+ ACL_MANAGER: AaveV3Arbitrum.ACL_MANAGER,
287
+ COLLECTOR: AaveV3Arbitrum.COLLECTOR,
288
+ ORACLE: AaveV3Arbitrum.ORACLE
289
+ },
290
+ ["optimism" /* OPTIMISM */]: {
291
+ POOL: AaveV3Optimism.POOL,
292
+ POOL_ADDRESSES_PROVIDER: AaveV3Optimism.POOL_ADDRESSES_PROVIDER,
293
+ AAVE_PROTOCOL_DATA_PROVIDER: AaveV3Optimism.AAVE_PROTOCOL_DATA_PROVIDER,
294
+ UI_POOL_DATA_PROVIDER: AaveV3Optimism.UI_POOL_DATA_PROVIDER,
295
+ WETH_GATEWAY: AaveV3Optimism.WETH_GATEWAY,
296
+ ACL_MANAGER: AaveV3Optimism.ACL_MANAGER,
297
+ COLLECTOR: AaveV3Optimism.COLLECTOR,
298
+ ORACLE: AaveV3Optimism.ORACLE
299
+ },
300
+ ["base" /* BASE */]: {
301
+ POOL: AaveV3Base.POOL,
302
+ POOL_ADDRESSES_PROVIDER: AaveV3Base.POOL_ADDRESSES_PROVIDER,
303
+ AAVE_PROTOCOL_DATA_PROVIDER: AaveV3Base.AAVE_PROTOCOL_DATA_PROVIDER,
304
+ UI_POOL_DATA_PROVIDER: AaveV3Base.UI_POOL_DATA_PROVIDER,
305
+ WETH_GATEWAY: AaveV3Base.WETH_GATEWAY,
306
+ ACL_MANAGER: AaveV3Base.ACL_MANAGER,
307
+ COLLECTOR: AaveV3Base.COLLECTOR,
308
+ ORACLE: AaveV3Base.ORACLE
309
+ },
310
+ ["bnb" /* BNB */]: {
311
+ POOL: AaveV3BNB.POOL,
312
+ POOL_ADDRESSES_PROVIDER: AaveV3BNB.POOL_ADDRESSES_PROVIDER,
313
+ AAVE_PROTOCOL_DATA_PROVIDER: AaveV3BNB.AAVE_PROTOCOL_DATA_PROVIDER,
314
+ UI_POOL_DATA_PROVIDER: AaveV3BNB.UI_POOL_DATA_PROVIDER,
315
+ WETH_GATEWAY: AaveV3BNB.WETH_GATEWAY,
316
+ ACL_MANAGER: AaveV3BNB.ACL_MANAGER,
317
+ COLLECTOR: AaveV3BNB.COLLECTOR,
318
+ ORACLE: AaveV3BNB.ORACLE
319
+ },
320
+ ["gnosis" /* GNOSIS */]: {
321
+ POOL: AaveV3Gnosis.POOL,
322
+ POOL_ADDRESSES_PROVIDER: AaveV3Gnosis.POOL_ADDRESSES_PROVIDER,
323
+ AAVE_PROTOCOL_DATA_PROVIDER: AaveV3Gnosis.AAVE_PROTOCOL_DATA_PROVIDER,
324
+ UI_POOL_DATA_PROVIDER: AaveV3Gnosis.UI_POOL_DATA_PROVIDER,
325
+ WETH_GATEWAY: AaveV3Gnosis.WETH_GATEWAY,
326
+ ACL_MANAGER: AaveV3Gnosis.ACL_MANAGER,
327
+ COLLECTOR: AaveV3Gnosis.COLLECTOR,
328
+ ORACLE: AaveV3Gnosis.ORACLE
329
+ },
330
+ ["metis" /* METIS */]: {
331
+ POOL: AaveV3Metis.POOL,
332
+ POOL_ADDRESSES_PROVIDER: AaveV3Metis.POOL_ADDRESSES_PROVIDER,
333
+ AAVE_PROTOCOL_DATA_PROVIDER: AaveV3Metis.AAVE_PROTOCOL_DATA_PROVIDER,
334
+ UI_POOL_DATA_PROVIDER: AaveV3Metis.UI_POOL_DATA_PROVIDER,
335
+ // WETH_GATEWAY: Not available on Metis
336
+ ACL_MANAGER: AaveV3Metis.ACL_MANAGER,
337
+ COLLECTOR: AaveV3Metis.COLLECTOR,
338
+ ORACLE: AaveV3Metis.ORACLE
339
+ },
340
+ ["scroll" /* SCROLL */]: {
341
+ POOL: AaveV3Scroll.POOL,
342
+ POOL_ADDRESSES_PROVIDER: AaveV3Scroll.POOL_ADDRESSES_PROVIDER,
343
+ AAVE_PROTOCOL_DATA_PROVIDER: AaveV3Scroll.AAVE_PROTOCOL_DATA_PROVIDER,
344
+ UI_POOL_DATA_PROVIDER: AaveV3Scroll.UI_POOL_DATA_PROVIDER,
345
+ WETH_GATEWAY: AaveV3Scroll.WETH_GATEWAY,
346
+ ACL_MANAGER: AaveV3Scroll.ACL_MANAGER,
347
+ COLLECTOR: AaveV3Scroll.COLLECTOR,
348
+ ORACLE: AaveV3Scroll.ORACLE
349
+ },
350
+ ["zksync" /* ZKSYNC */]: {
351
+ POOL: AaveV3ZkSync.POOL,
352
+ POOL_ADDRESSES_PROVIDER: AaveV3ZkSync.POOL_ADDRESSES_PROVIDER,
353
+ AAVE_PROTOCOL_DATA_PROVIDER: AaveV3ZkSync.AAVE_PROTOCOL_DATA_PROVIDER,
354
+ UI_POOL_DATA_PROVIDER: AaveV3ZkSync.UI_POOL_DATA_PROVIDER,
355
+ WETH_GATEWAY: AaveV3ZkSync.WETH_GATEWAY,
356
+ ACL_MANAGER: AaveV3ZkSync.ACL_MANAGER,
357
+ COLLECTOR: AaveV3ZkSync.COLLECTOR,
358
+ ORACLE: AaveV3ZkSync.ORACLE
359
+ },
360
+ // Testnets
361
+ ["sepolia" /* SEPOLIA */]: {
362
+ POOL: AaveV3Sepolia.POOL,
363
+ POOL_ADDRESSES_PROVIDER: AaveV3Sepolia.POOL_ADDRESSES_PROVIDER,
364
+ AAVE_PROTOCOL_DATA_PROVIDER: AaveV3Sepolia.AAVE_PROTOCOL_DATA_PROVIDER,
365
+ UI_POOL_DATA_PROVIDER: AaveV3Sepolia.UI_POOL_DATA_PROVIDER,
366
+ WETH_GATEWAY: AaveV3Sepolia.WETH_GATEWAY,
367
+ ACL_MANAGER: AaveV3Sepolia.ACL_MANAGER,
368
+ COLLECTOR: AaveV3Sepolia.COLLECTOR,
369
+ ORACLE: AaveV3Sepolia.ORACLE
370
+ },
371
+ ["fuji" /* FUJI */]: {
372
+ POOL: AaveV3Fuji.POOL,
373
+ POOL_ADDRESSES_PROVIDER: AaveV3Fuji.POOL_ADDRESSES_PROVIDER,
374
+ AAVE_PROTOCOL_DATA_PROVIDER: AaveV3Fuji.AAVE_PROTOCOL_DATA_PROVIDER,
375
+ // UI_POOL_DATA_PROVIDER: Not available on Fuji
376
+ WETH_GATEWAY: AaveV3Fuji.WETH_GATEWAY,
377
+ ACL_MANAGER: AaveV3Fuji.ACL_MANAGER,
378
+ COLLECTOR: AaveV3Fuji.COLLECTOR,
379
+ ORACLE: AaveV3Fuji.ORACLE
380
+ },
381
+ ["arbitrum-sepolia" /* ARBITRUM_SEPOLIA */]: {
382
+ POOL: AaveV3ArbitrumSepolia.POOL,
383
+ POOL_ADDRESSES_PROVIDER: AaveV3ArbitrumSepolia.POOL_ADDRESSES_PROVIDER,
384
+ AAVE_PROTOCOL_DATA_PROVIDER: AaveV3ArbitrumSepolia.AAVE_PROTOCOL_DATA_PROVIDER,
385
+ UI_POOL_DATA_PROVIDER: AaveV3ArbitrumSepolia.UI_POOL_DATA_PROVIDER,
386
+ WETH_GATEWAY: AaveV3ArbitrumSepolia.WETH_GATEWAY,
387
+ ACL_MANAGER: AaveV3ArbitrumSepolia.ACL_MANAGER,
388
+ COLLECTOR: AaveV3ArbitrumSepolia.COLLECTOR,
389
+ ORACLE: AaveV3ArbitrumSepolia.ORACLE
390
+ },
391
+ ["optimism-sepolia" /* OPTIMISM_SEPOLIA */]: {
392
+ POOL: AaveV3OptimismSepolia.POOL,
393
+ POOL_ADDRESSES_PROVIDER: AaveV3OptimismSepolia.POOL_ADDRESSES_PROVIDER,
394
+ AAVE_PROTOCOL_DATA_PROVIDER: AaveV3OptimismSepolia.AAVE_PROTOCOL_DATA_PROVIDER,
395
+ UI_POOL_DATA_PROVIDER: AaveV3OptimismSepolia.UI_POOL_DATA_PROVIDER,
396
+ WETH_GATEWAY: AaveV3OptimismSepolia.WETH_GATEWAY,
397
+ ACL_MANAGER: AaveV3OptimismSepolia.ACL_MANAGER,
398
+ COLLECTOR: AaveV3OptimismSepolia.COLLECTOR,
399
+ ORACLE: AaveV3OptimismSepolia.ORACLE
400
+ },
401
+ ["base-sepolia" /* BASE_SEPOLIA */]: {
402
+ POOL: AaveV3BaseSepolia.POOL,
403
+ POOL_ADDRESSES_PROVIDER: AaveV3BaseSepolia.POOL_ADDRESSES_PROVIDER,
404
+ AAVE_PROTOCOL_DATA_PROVIDER: AaveV3BaseSepolia.AAVE_PROTOCOL_DATA_PROVIDER,
405
+ UI_POOL_DATA_PROVIDER: AaveV3BaseSepolia.UI_POOL_DATA_PROVIDER,
406
+ WETH_GATEWAY: AaveV3BaseSepolia.WETH_GATEWAY,
407
+ ACL_MANAGER: AaveV3BaseSepolia.ACL_MANAGER,
408
+ COLLECTOR: AaveV3BaseSepolia.COLLECTOR,
409
+ ORACLE: AaveV3BaseSepolia.ORACLE
410
+ }
411
+ };
412
+ function resolveChainContext(chainName) {
413
+ const normalizedChain = chainName.toLowerCase().trim();
414
+ if (!Object.values(SupportedChain).includes(normalizedChain)) {
415
+ throw new AaveError(
416
+ `Unsupported chain: ${chainName}. Supported chains: ${Object.values(SupportedChain).join(", ")}`,
417
+ "INVALID_PARAMETERS" /* INVALID_PARAMETERS */
418
+ );
419
+ }
420
+ const config = CHAIN_CONFIGS[normalizedChain];
421
+ if (!config) {
422
+ throw new AaveError(
423
+ `Chain configuration not found for: ${chainName}`,
424
+ "INVALID_PARAMETERS" /* INVALID_PARAMETERS */
425
+ );
426
+ }
427
+ const addresses = CHAIN_ADDRESS_MAP[normalizedChain];
428
+ if (!addresses) {
429
+ throw new AaveError(
430
+ `Aave V3 contracts not available on chain: ${chainName}`,
431
+ "INVALID_PARAMETERS" /* INVALID_PARAMETERS */
432
+ );
433
+ }
434
+ return {
435
+ chain: normalizedChain,
436
+ config,
437
+ addresses
438
+ };
439
+ }
440
+ function resolveRpcUrl(chainContext, userRpcUrl) {
441
+ if (userRpcUrl) {
442
+ return userRpcUrl;
443
+ }
444
+ return chainContext.config.defaultRpcUrl;
445
+ }
446
+ function isMaxAmount(amount) {
447
+ if (typeof amount === "string") {
448
+ const normalized = amount.toLowerCase().trim();
449
+ return ["max", "maximum", "all", "everything"].includes(normalized);
450
+ }
451
+ if (amount instanceof BigNumber3) {
452
+ return false;
453
+ }
454
+ return false;
455
+ }
456
+ function parseAmount(amount) {
457
+ if (amount === null || amount === void 0) {
458
+ throw new Error("Amount cannot be null or undefined");
459
+ }
460
+ if (typeof amount === "string") {
461
+ const trimmed = amount.trim();
462
+ if (!trimmed) {
463
+ throw new Error("Amount cannot be empty");
464
+ }
465
+ if (trimmed === "NaN" || trimmed === "Infinity" || trimmed === "-Infinity") {
466
+ throw new Error("Invalid amount format");
467
+ }
468
+ const num2 = new BigNumber3(trimmed);
469
+ if (num2.isNaN() || !num2.isFinite()) {
470
+ throw new Error("Invalid amount format");
471
+ }
472
+ if (num2.isLessThanOrEqualTo(0)) {
473
+ throw new Error("Amount must be greater than 0");
474
+ }
475
+ return num2;
476
+ }
477
+ if (typeof amount === "number") {
478
+ if (!isFinite(amount) || isNaN(amount)) {
479
+ throw new Error("Amount must be a finite number");
480
+ }
481
+ }
482
+ const num = new BigNumber3(amount);
483
+ if (num.isNaN() || !num.isFinite() || num.isLessThanOrEqualTo(0)) {
484
+ throw new Error("Amount must be a positive finite number");
485
+ }
486
+ return num;
487
+ }
488
+ function validateAddress(address) {
489
+ if (!address || typeof address !== "string") {
490
+ throw new Error("Address is required");
491
+ }
492
+ const trimmed = address.trim();
493
+ if (!trimmed.match(/^0x[a-fA-F0-9]{40}$/i)) {
494
+ throw new Error("Invalid address: must be a valid Ethereum address");
495
+ }
496
+ return trimmed;
497
+ }
498
+ function validateSupplyParams(params) {
499
+ if (!params.user || !params.asset || !params.amount) {
500
+ throw new Error("Missing required parameters: user, asset, amount");
501
+ }
502
+ return {
503
+ user: validateAddress(params.user),
504
+ asset: params.asset.trim(),
505
+ amount: isMaxAmount(params.amount) ? params.amount : parseAmount(params.amount).toString()
506
+ };
507
+ }
508
+ function validateWithdrawParams(params) {
509
+ if (!params.user || !params.asset || !params.amount) {
510
+ throw new Error("Missing required parameters: user, asset, amount");
511
+ }
512
+ return {
513
+ user: validateAddress(params.user),
514
+ asset: params.asset.trim(),
515
+ amount: isMaxAmount(params.amount) ? params.amount : parseAmount(params.amount).toString()
516
+ };
517
+ }
518
+ function validateBorrowParams(params) {
519
+ if (!params.user || !params.asset || !params.amount) {
520
+ throw new Error("Missing required parameters: user, asset, amount");
521
+ }
522
+ if (params.interestRateMode !== void 0) {
523
+ if (params.interestRateMode !== 1 /* STABLE */ && params.interestRateMode !== 2 /* VARIABLE */) {
524
+ throw new Error("Invalid interest rate mode: must be 1 (stable) or 2 (variable)");
525
+ }
526
+ }
527
+ return {
528
+ user: validateAddress(params.user),
529
+ asset: params.asset.trim(),
530
+ amount: parseAmount(params.amount).toString(),
531
+ interestRateMode: params.interestRateMode || 2 /* VARIABLE */
532
+ };
533
+ }
534
+ function validateRepayParams(params) {
535
+ if (!params.user || !params.asset || !params.amount) {
536
+ throw new Error("Missing required parameters: user, asset, amount");
537
+ }
538
+ return {
539
+ user: validateAddress(params.user),
540
+ asset: params.asset.trim(),
541
+ amount: isMaxAmount(params.amount) ? params.amount : parseAmount(params.amount).toString(),
542
+ interestRateMode: params.interestRateMode || 2 /* VARIABLE */
543
+ };
544
+ }
545
+
546
+ // src/utils/error-handler.ts
547
+ function getRateModeName(mode) {
548
+ switch (mode) {
549
+ case 1 /* STABLE */:
550
+ return "Stable";
551
+ case 2 /* VARIABLE */:
552
+ return "Variable";
553
+ default:
554
+ return "Unknown";
555
+ }
556
+ }
557
+ var AAVE_PROTOCOL_ERRORS = {
558
+ // Pool errors (P prefix)
559
+ "P_INVALID_FLASHLOAN_EXECUTOR_RETURN": {
560
+ code: "TRANSACTION_FAILED" /* TRANSACTION_FAILED */,
561
+ description: "Invalid flashloan executor return",
562
+ userMessage: "Flash loan execution failed. Please check your flash loan logic.",
563
+ recovery: {
564
+ action: "Review and fix your flash loan implementation",
565
+ requiresUserAction: true
566
+ }
567
+ },
568
+ "P_VT_TRANSFER_NOT_SUPPORTED": {
569
+ code: "TRANSACTION_FAILED" /* TRANSACTION_FAILED */,
570
+ description: "Variable debt token transfer not supported",
571
+ userMessage: "Cannot transfer debt tokens. Use repay and borrow operations instead.",
572
+ recovery: {
573
+ action: "Use repay() and borrow() functions for debt management",
574
+ requiresUserAction: true
575
+ }
576
+ },
577
+ "P_ASSET_NOT_LISTED": {
578
+ code: "ASSET_NOT_SUPPORTED" /* ASSET_NOT_SUPPORTED */,
579
+ description: "Asset is not listed in the pool",
580
+ userMessage: "This asset is not supported by Aave protocol.",
581
+ recovery: {
582
+ action: "Use a supported asset from the Aave markets",
583
+ requiresUserAction: true
584
+ }
585
+ },
586
+ "P_INVALID_AMOUNT": {
587
+ code: "INVALID_PARAMETERS" /* INVALID_PARAMETERS */,
588
+ description: "Invalid amount provided",
589
+ userMessage: "The amount provided is invalid. Please check the amount and try again.",
590
+ recovery: {
591
+ action: "Ensure amount is positive and within acceptable range",
592
+ requiresUserAction: true
593
+ }
594
+ },
595
+ // Reserve errors (R prefix)
596
+ "R_LIQUIDITY_INDEX_OVERFLOW": {
597
+ code: "TRANSACTION_FAILED" /* TRANSACTION_FAILED */,
598
+ description: "Liquidity index overflow",
599
+ userMessage: "Internal calculation error. Please try again later.",
600
+ recovery: {
601
+ action: "Wait and retry the operation",
602
+ requiresUserAction: false
603
+ }
604
+ },
605
+ "R_VARIABLE_BORROW_INDEX_OVERFLOW": {
606
+ code: "TRANSACTION_FAILED" /* TRANSACTION_FAILED */,
607
+ description: "Variable borrow index overflow",
608
+ userMessage: "Internal calculation error. Please try again later.",
609
+ recovery: {
610
+ action: "Wait and retry the operation",
611
+ requiresUserAction: false
612
+ }
613
+ },
614
+ "R_LIQUIDITY_RATE_OVERFLOW": {
615
+ code: "TRANSACTION_FAILED" /* TRANSACTION_FAILED */,
616
+ description: "Liquidity rate overflow",
617
+ userMessage: "Interest rate calculation error. Please try again later.",
618
+ recovery: {
619
+ action: "Wait and retry the operation",
620
+ requiresUserAction: false
621
+ }
622
+ },
623
+ "R_VARIABLE_BORROW_RATE_OVERFLOW": {
624
+ code: "TRANSACTION_FAILED" /* TRANSACTION_FAILED */,
625
+ description: "Variable borrow rate overflow",
626
+ userMessage: "Interest rate calculation error. Please try again later.",
627
+ recovery: {
628
+ action: "Wait and retry the operation",
629
+ requiresUserAction: false
630
+ }
631
+ },
632
+ // Validation errors (V prefix)
633
+ "V_INCONSISTENT_FLASHLOAN_PARAMS": {
634
+ code: "INVALID_PARAMETERS" /* INVALID_PARAMETERS */,
635
+ description: "Inconsistent flashloan parameters",
636
+ userMessage: "Flash loan parameters are inconsistent.",
637
+ recovery: {
638
+ action: "Check flash loan asset and amount parameters",
639
+ requiresUserAction: true
640
+ }
641
+ },
642
+ "V_COLLATERAL_BALANCE_IS_ZERO": {
643
+ code: "INSUFFICIENT_COLLATERAL" /* INSUFFICIENT_COLLATERAL */,
644
+ description: "Collateral balance is zero",
645
+ userMessage: "You have no collateral deposited. Please supply collateral first.",
646
+ recovery: {
647
+ action: "Supply assets as collateral before borrowing",
648
+ requiresUserAction: true
649
+ }
650
+ },
651
+ "V_HEALTH_FACTOR_LOWER_THAN_LIQUIDATION_THRESHOLD": {
652
+ code: "HEALTH_FACTOR_TOO_LOW" /* HEALTH_FACTOR_TOO_LOW */,
653
+ description: "Health factor below liquidation threshold",
654
+ userMessage: "This operation would put your position at risk of liquidation.",
655
+ recovery: {
656
+ action: "Supply more collateral or reduce borrowing amount",
657
+ requiresUserAction: true
658
+ }
659
+ },
660
+ "V_COLLATERAL_CANNOT_COVER_NEW_BORROW": {
661
+ code: "INSUFFICIENT_COLLATERAL" /* INSUFFICIENT_COLLATERAL */,
662
+ description: "Insufficient collateral for new borrow",
663
+ userMessage: "You don't have enough collateral to borrow this amount.",
664
+ recovery: {
665
+ action: "Supply more collateral or reduce borrow amount",
666
+ requiresUserAction: true
667
+ }
668
+ },
669
+ "V_STABLE_BORROWING_NOT_ENABLED": {
670
+ code: "STABLE_BORROWING_NOT_ENABLED" /* STABLE_BORROWING_NOT_ENABLED */,
671
+ description: "Stable borrowing not enabled for asset",
672
+ userMessage: "Stable rate borrowing is not available for this asset.",
673
+ recovery: {
674
+ action: "Use variable rate borrowing instead",
675
+ requiresUserAction: true
676
+ }
677
+ },
678
+ "V_NO_DEBT_OF_SELECTED_TYPE": {
679
+ code: "TRANSACTION_FAILED" /* TRANSACTION_FAILED */,
680
+ description: "No debt of selected type",
681
+ userMessage: "You don't have debt in the selected interest rate mode.",
682
+ recovery: {
683
+ action: "Check your debt positions and select the correct rate mode",
684
+ requiresUserAction: true
685
+ }
686
+ },
687
+ "V_NO_STABLE_RATE_LOAN_IN_RESERVE": {
688
+ code: "STABLE_BORROWING_NOT_ENABLED" /* STABLE_BORROWING_NOT_ENABLED */,
689
+ description: "No stable rate loan exists",
690
+ userMessage: "No stable rate loan exists for this asset.",
691
+ recovery: {
692
+ action: "Use variable rate borrowing",
693
+ requiresUserAction: true
694
+ }
695
+ },
696
+ "V_NO_VARIABLE_RATE_LOAN_IN_RESERVE": {
697
+ code: "TRANSACTION_FAILED" /* TRANSACTION_FAILED */,
698
+ description: "No variable rate loan exists",
699
+ userMessage: "No variable rate loan exists for this asset.",
700
+ recovery: {
701
+ action: "Check your borrow positions",
702
+ requiresUserAction: true
703
+ }
704
+ },
705
+ "V_UNDERLYING_BALANCE_ZERO": {
706
+ code: "INSUFFICIENT_BALANCE" /* INSUFFICIENT_BALANCE */,
707
+ description: "Underlying balance is zero",
708
+ userMessage: "You don't have any balance of this asset to supply.",
709
+ recovery: {
710
+ action: "Acquire the asset first or check your balance",
711
+ requiresUserAction: true
712
+ }
713
+ },
714
+ "V_INTEREST_RATE_REBALANCE_CONDITIONS_NOT_MET": {
715
+ code: "TRANSACTION_FAILED" /* TRANSACTION_FAILED */,
716
+ description: "Interest rate rebalance conditions not met",
717
+ userMessage: "Cannot rebalance interest rate. Conditions not met.",
718
+ recovery: {
719
+ action: "Try again later when market conditions change",
720
+ requiresUserAction: false
721
+ }
722
+ },
723
+ // Asset configuration errors (A prefix)
724
+ "A_INTEREST_RATE_REBALANCE_CONDITIONS_NOT_MET": {
725
+ code: "TRANSACTION_FAILED" /* TRANSACTION_FAILED */,
726
+ description: "Rebalance conditions not met",
727
+ userMessage: "Cannot rebalance stable rate. Market conditions not suitable.",
728
+ recovery: {
729
+ action: "Try again when utilization rate changes",
730
+ requiresUserAction: false
731
+ }
732
+ },
733
+ "A_NO_MORE_RESERVES_ALLOWED": {
734
+ code: "POOL_PAUSED" /* POOL_PAUSED */,
735
+ description: "No more reserves allowed",
736
+ userMessage: "Maximum number of assets reached in the pool.",
737
+ recovery: {
738
+ action: "Contact Aave governance to add more reserves",
739
+ requiresUserAction: true
740
+ }
741
+ },
742
+ // Supply/Withdraw specific
743
+ "S_NOT_ENOUGH_AVAILABLE_USER_BALANCE": {
744
+ code: "INSUFFICIENT_BALANCE" /* INSUFFICIENT_BALANCE */,
745
+ description: "Insufficient user balance",
746
+ userMessage: "You don't have enough balance to complete this operation.",
747
+ recovery: {
748
+ action: "Check your wallet balance and reduce the amount",
749
+ requiresUserAction: true
750
+ }
751
+ },
752
+ "W_NO_ATOKEN_BALANCE": {
753
+ code: "INSUFFICIENT_BALANCE" /* INSUFFICIENT_BALANCE */,
754
+ description: "No aToken balance to withdraw",
755
+ userMessage: "You don't have any supplied balance to withdraw.",
756
+ recovery: {
757
+ action: "Check your supplied positions",
758
+ requiresUserAction: true
759
+ }
760
+ },
761
+ // Borrow/Repay specific
762
+ "B_BORROW_CAP_EXCEEDED": {
763
+ code: "AMOUNT_TOO_HIGH" /* AMOUNT_TOO_HIGH */,
764
+ description: "Borrow cap exceeded",
765
+ userMessage: "Borrowing this amount would exceed the protocol's borrow cap.",
766
+ recovery: {
767
+ action: "Reduce the borrow amount",
768
+ requiresUserAction: true
769
+ }
770
+ },
771
+ "B_SUPPLY_CAP_EXCEEDED": {
772
+ code: "AMOUNT_TOO_HIGH" /* AMOUNT_TOO_HIGH */,
773
+ description: "Supply cap exceeded",
774
+ userMessage: "Supplying this amount would exceed the protocol's supply cap.",
775
+ recovery: {
776
+ action: "Reduce the supply amount",
777
+ requiresUserAction: true
778
+ }
779
+ },
780
+ // Reserve status errors
781
+ "RESERVE_INACTIVE": {
782
+ code: "RESERVE_INACTIVE" /* RESERVE_INACTIVE */,
783
+ description: "Reserve is inactive",
784
+ userMessage: "This asset is currently inactive in the Aave protocol.",
785
+ recovery: {
786
+ action: "Choose an active asset or wait for reactivation",
787
+ requiresUserAction: true
788
+ }
789
+ },
790
+ "RESERVE_FROZEN": {
791
+ code: "RESERVE_FROZEN" /* RESERVE_FROZEN */,
792
+ description: "Reserve is frozen",
793
+ userMessage: "This asset is currently frozen. Only repay and withdraw operations are allowed.",
794
+ recovery: {
795
+ action: "Choose an unfrozen asset or wait for unfreeze",
796
+ requiresUserAction: true
797
+ }
798
+ },
799
+ "RESERVE_PAUSED": {
800
+ code: "POOL_PAUSED" /* POOL_PAUSED */,
801
+ description: "Reserve is paused",
802
+ userMessage: "Operations on this asset are temporarily paused.",
803
+ recovery: {
804
+ action: "Wait for the asset to be unpaused",
805
+ requiresUserAction: false
806
+ }
807
+ }
808
+ };
809
+ var NETWORK_ERROR_PATTERNS = {
810
+ // RPC errors
811
+ "network timeout": {
812
+ code: "TRANSACTION_FAILED" /* TRANSACTION_FAILED */,
813
+ userMessage: "Network connection timed out. Please try again.",
814
+ isRetryable: true
815
+ },
816
+ "connection refused": {
817
+ code: "TRANSACTION_FAILED" /* TRANSACTION_FAILED */,
818
+ userMessage: "Unable to connect to the network. Please check your connection.",
819
+ isRetryable: true
820
+ },
821
+ "socket hang up": {
822
+ code: "TRANSACTION_FAILED" /* TRANSACTION_FAILED */,
823
+ userMessage: "Network connection interrupted. Please try again.",
824
+ isRetryable: true
825
+ },
826
+ "request timeout": {
827
+ code: "TRANSACTION_FAILED" /* TRANSACTION_FAILED */,
828
+ userMessage: "Request timed out. Please try again.",
829
+ isRetryable: true
830
+ },
831
+ "rate limit": {
832
+ code: "TRANSACTION_FAILED" /* TRANSACTION_FAILED */,
833
+ userMessage: "Too many requests. Please wait a moment and try again.",
834
+ isRetryable: true
835
+ },
836
+ "insufficient funds for gas": {
837
+ code: "INSUFFICIENT_BALANCE" /* INSUFFICIENT_BALANCE */,
838
+ userMessage: "Insufficient ETH for gas fees. Please add more ETH to your wallet.",
839
+ isRetryable: false
840
+ },
841
+ "gas limit exceeded": {
842
+ code: "TRANSACTION_FAILED" /* TRANSACTION_FAILED */,
843
+ userMessage: "Transaction requires too much gas. Try reducing the amount.",
844
+ isRetryable: false
845
+ },
846
+ "replacement transaction underpriced": {
847
+ code: "TRANSACTION_FAILED" /* TRANSACTION_FAILED */,
848
+ userMessage: "Transaction replacement fee too low. Increase gas price.",
849
+ isRetryable: true
850
+ },
851
+ "nonce too low": {
852
+ code: "TRANSACTION_FAILED" /* TRANSACTION_FAILED */,
853
+ userMessage: "Transaction nonce is outdated. Please refresh and try again.",
854
+ isRetryable: true
855
+ },
856
+ "already known": {
857
+ code: "TRANSACTION_FAILED" /* TRANSACTION_FAILED */,
858
+ userMessage: "Transaction already pending. Please wait for confirmation.",
859
+ isRetryable: false
860
+ }
861
+ };
862
+ var GAS_ERROR_PATTERNS = {
863
+ "execution reverted": {
864
+ code: "TRANSACTION_FAILED" /* TRANSACTION_FAILED */,
865
+ userMessage: "Transaction would fail. Please check your parameters.",
866
+ recovery: {
867
+ action: "Review transaction parameters and account balances",
868
+ requiresUserAction: true
869
+ }
870
+ },
871
+ "out of gas": {
872
+ code: "TRANSACTION_FAILED" /* TRANSACTION_FAILED */,
873
+ userMessage: "Transaction ran out of gas. Increase gas limit.",
874
+ recovery: {
875
+ action: "Increase gas limit or reduce transaction complexity",
876
+ requiresUserAction: true
877
+ }
878
+ },
879
+ "invalid opcode": {
880
+ code: "TRANSACTION_FAILED" /* TRANSACTION_FAILED */,
881
+ userMessage: "Invalid transaction. Please check your parameters.",
882
+ recovery: {
883
+ action: "Verify all transaction parameters are correct",
884
+ requiresUserAction: true
885
+ }
886
+ }
887
+ };
888
+ function mapAaveError(error, context = {}) {
889
+ const errorMessage = error.message.toLowerCase();
890
+ for (const [pattern, errorInfo] of Object.entries(AAVE_PROTOCOL_ERRORS)) {
891
+ if (errorMessage.includes(pattern.toLowerCase()) || errorMessage.includes(`execution reverted: ${pattern.toLowerCase()}`)) {
892
+ return new AaveError(
893
+ errorInfo.userMessage,
894
+ errorInfo.code,
895
+ error,
896
+ {
897
+ ...context,
898
+ protocolError: pattern,
899
+ recovery: errorInfo.recovery
900
+ }
901
+ );
902
+ }
903
+ }
904
+ for (const [pattern, errorInfo] of Object.entries(NETWORK_ERROR_PATTERNS)) {
905
+ if (errorMessage.includes(pattern)) {
906
+ return new AaveError(
907
+ errorInfo.userMessage,
908
+ errorInfo.code,
909
+ error,
910
+ {
911
+ ...context,
912
+ networkError: pattern,
913
+ isRetryable: errorInfo.isRetryable
914
+ }
915
+ );
916
+ }
917
+ }
918
+ for (const [pattern, errorInfo] of Object.entries(GAS_ERROR_PATTERNS)) {
919
+ if (errorMessage.includes(pattern)) {
920
+ return new AaveError(
921
+ errorInfo.userMessage,
922
+ errorInfo.code,
923
+ error,
924
+ {
925
+ ...context,
926
+ gasError: pattern,
927
+ recovery: errorInfo.recovery
928
+ }
929
+ );
930
+ }
931
+ }
932
+ if (errorMessage.includes("insufficient")) {
933
+ if (errorMessage.includes("balance") || errorMessage.includes("funds")) {
934
+ return new AaveError(
935
+ "Insufficient balance to complete this operation.",
936
+ "INSUFFICIENT_BALANCE" /* INSUFFICIENT_BALANCE */,
937
+ error,
938
+ context
939
+ );
940
+ }
941
+ if (errorMessage.includes("collateral")) {
942
+ return new AaveError(
943
+ "Insufficient collateral for this operation.",
944
+ "INSUFFICIENT_COLLATERAL" /* INSUFFICIENT_COLLATERAL */,
945
+ error,
946
+ context
947
+ );
948
+ }
949
+ }
950
+ if (errorMessage.includes("health factor")) {
951
+ return new AaveError(
952
+ "This operation would put your position at risk of liquidation.",
953
+ "HEALTH_FACTOR_TOO_LOW" /* HEALTH_FACTOR_TOO_LOW */,
954
+ error,
955
+ context
956
+ );
957
+ }
958
+ if (errorMessage.includes("not enabled") && errorMessage.includes("stable")) {
959
+ return new AaveError(
960
+ "Stable rate borrowing is not enabled for this asset.",
961
+ "STABLE_BORROWING_NOT_ENABLED" /* STABLE_BORROWING_NOT_ENABLED */,
962
+ error,
963
+ context
964
+ );
965
+ }
966
+ if (errorMessage.includes("paused")) {
967
+ return new AaveError(
968
+ "The pool or asset is currently paused.",
969
+ "POOL_PAUSED" /* POOL_PAUSED */,
970
+ error,
971
+ context
972
+ );
973
+ }
974
+ if (errorMessage.includes("frozen")) {
975
+ return new AaveError(
976
+ "The asset is currently frozen.",
977
+ "RESERVE_FROZEN" /* RESERVE_FROZEN */,
978
+ error,
979
+ context
980
+ );
981
+ }
982
+ return new AaveError(
983
+ "An unexpected error occurred. Please try again.",
984
+ "UNKNOWN" /* UNKNOWN */,
985
+ error,
986
+ context
987
+ );
988
+ }
989
+ function handleContractError(error, contractName, methodName, context = {}) {
990
+ const enhancedContext = {
991
+ ...context,
992
+ contractName,
993
+ methodName
994
+ };
995
+ const aaveError = mapAaveError(error, enhancedContext);
996
+ return {
997
+ originalError: error,
998
+ aaveError,
999
+ userMessage: aaveError.message,
1000
+ technicalMessage: `Contract error in ${contractName}.${methodName}: ${error.message}`,
1001
+ context: enhancedContext,
1002
+ isRetryable: determineRetryability(aaveError),
1003
+ logLevel: determineLogLevel(aaveError),
1004
+ recovery: aaveError.context?.recovery
1005
+ };
1006
+ }
1007
+ function handleTransactionError(error, transactionHash, context = {}) {
1008
+ const enhancedContext = {
1009
+ ...context,
1010
+ transactionHash
1011
+ };
1012
+ const aaveError = mapAaveError(error, enhancedContext);
1013
+ let userMessage = aaveError.message;
1014
+ let technicalMessage = error.message;
1015
+ if (aaveError.code === "INSUFFICIENT_BALANCE" /* INSUFFICIENT_BALANCE */ && context.operation) {
1016
+ const operation = context.operation;
1017
+ const asset = context.asset || "the asset";
1018
+ switch (operation) {
1019
+ case "supply":
1020
+ userMessage = `You don't have enough ${asset} to supply this amount.`;
1021
+ break;
1022
+ case "borrow":
1023
+ userMessage = `You don't have enough collateral to borrow this amount of ${asset}.`;
1024
+ break;
1025
+ case "repay":
1026
+ userMessage = `You don't have enough ${asset} to repay this amount.`;
1027
+ break;
1028
+ case "withdraw":
1029
+ userMessage = `You don't have enough supplied ${asset} to withdraw this amount.`;
1030
+ break;
1031
+ }
1032
+ }
1033
+ return {
1034
+ originalError: error,
1035
+ aaveError,
1036
+ userMessage,
1037
+ technicalMessage,
1038
+ context: enhancedContext,
1039
+ isRetryable: determineRetryability(aaveError),
1040
+ logLevel: determineLogLevel(aaveError),
1041
+ recovery: generateRecoverySuggestion(aaveError, context)
1042
+ };
1043
+ }
1044
+ function handleBigNumberError(error, context = {}) {
1045
+ const errorMessage = error.message.toLowerCase();
1046
+ let aaveError;
1047
+ let userMessage;
1048
+ if (errorMessage.includes("invalid number") || errorMessage.includes("not a number")) {
1049
+ aaveError = new AaveError(
1050
+ "Invalid number format provided.",
1051
+ "INVALID_PARAMETERS" /* INVALID_PARAMETERS */,
1052
+ error,
1053
+ context
1054
+ );
1055
+ userMessage = "Please enter a valid number.";
1056
+ } else if (errorMessage.includes("overflow") || errorMessage.includes("too large")) {
1057
+ aaveError = new AaveError(
1058
+ "Number is too large to process.",
1059
+ "AMOUNT_TOO_HIGH" /* AMOUNT_TOO_HIGH */,
1060
+ error,
1061
+ context
1062
+ );
1063
+ userMessage = "The amount is too large. Please use a smaller number.";
1064
+ } else if (errorMessage.includes("underflow") || errorMessage.includes("negative")) {
1065
+ aaveError = new AaveError(
1066
+ "Negative numbers are not allowed.",
1067
+ "INVALID_PARAMETERS" /* INVALID_PARAMETERS */,
1068
+ error,
1069
+ context
1070
+ );
1071
+ userMessage = "Please enter a positive number.";
1072
+ } else if (errorMessage.includes("division by zero")) {
1073
+ aaveError = new AaveError(
1074
+ "Division by zero error in calculation.",
1075
+ "TRANSACTION_FAILED" /* TRANSACTION_FAILED */,
1076
+ error,
1077
+ context
1078
+ );
1079
+ userMessage = "Internal calculation error. Please try again.";
1080
+ } else {
1081
+ aaveError = new AaveError(
1082
+ "Number processing error.",
1083
+ "INVALID_PARAMETERS" /* INVALID_PARAMETERS */,
1084
+ error,
1085
+ context
1086
+ );
1087
+ userMessage = "There was an error processing the numbers. Please check your input.";
1088
+ }
1089
+ return {
1090
+ originalError: error,
1091
+ aaveError,
1092
+ userMessage,
1093
+ technicalMessage: `BigNumber/ethers error: ${error.message}`,
1094
+ context,
1095
+ isRetryable: false,
1096
+ logLevel: "warn",
1097
+ recovery: {
1098
+ action: "Check input values and try again",
1099
+ requiresUserAction: true
1100
+ }
1101
+ };
1102
+ }
1103
+ function createSupplyErrorContext(params) {
1104
+ return {
1105
+ operation: "supply",
1106
+ asset: params.asset,
1107
+ amount: params.amount?.toString(),
1108
+ user: params.user
1109
+ };
1110
+ }
1111
+ function createWithdrawErrorContext(params) {
1112
+ return {
1113
+ operation: "withdraw",
1114
+ asset: params.asset,
1115
+ amount: params.amount?.toString(),
1116
+ user: params.user
1117
+ };
1118
+ }
1119
+ function createBorrowErrorContext(params) {
1120
+ return {
1121
+ operation: "borrow",
1122
+ asset: params.asset,
1123
+ amount: params.amount?.toString(),
1124
+ user: params.user,
1125
+ interestRateMode: params.interestRateMode
1126
+ };
1127
+ }
1128
+ function createRepayErrorContext(params) {
1129
+ return {
1130
+ operation: "repay",
1131
+ asset: params.asset,
1132
+ amount: params.amount?.toString(),
1133
+ user: params.user,
1134
+ interestRateMode: params.interestRateMode
1135
+ };
1136
+ }
1137
+ function determineRetryability(error) {
1138
+ const retryableCodes = [
1139
+ "UNKNOWN" /* UNKNOWN */,
1140
+ "TRANSACTION_FAILED" /* TRANSACTION_FAILED */
1141
+ ];
1142
+ if (retryableCodes.includes(error.code)) {
1143
+ if (error.context?.isRetryable !== void 0) {
1144
+ return error.context.isRetryable;
1145
+ }
1146
+ return true;
1147
+ }
1148
+ const nonRetryableCodes = [
1149
+ "INSUFFICIENT_BALANCE" /* INSUFFICIENT_BALANCE */,
1150
+ "INSUFFICIENT_COLLATERAL" /* INSUFFICIENT_COLLATERAL */,
1151
+ "ASSET_NOT_SUPPORTED" /* ASSET_NOT_SUPPORTED */,
1152
+ "INVALID_PARAMETERS" /* INVALID_PARAMETERS */,
1153
+ "HEALTH_FACTOR_TOO_LOW" /* HEALTH_FACTOR_TOO_LOW */,
1154
+ "STABLE_BORROWING_NOT_ENABLED" /* STABLE_BORROWING_NOT_ENABLED */,
1155
+ "AMOUNT_TOO_HIGH" /* AMOUNT_TOO_HIGH */
1156
+ ];
1157
+ return !nonRetryableCodes.includes(error.code);
1158
+ }
1159
+ function determineLogLevel(error) {
1160
+ switch (error.code) {
1161
+ case "INVALID_PARAMETERS" /* INVALID_PARAMETERS */:
1162
+ case "ASSET_NOT_SUPPORTED" /* ASSET_NOT_SUPPORTED */:
1163
+ return "warn";
1164
+ case "INSUFFICIENT_BALANCE" /* INSUFFICIENT_BALANCE */:
1165
+ case "INSUFFICIENT_COLLATERAL" /* INSUFFICIENT_COLLATERAL */:
1166
+ case "HEALTH_FACTOR_TOO_LOW" /* HEALTH_FACTOR_TOO_LOW */:
1167
+ return "info";
1168
+ default:
1169
+ return "error";
1170
+ }
1171
+ }
1172
+ function generateRecoverySuggestion(error, context) {
1173
+ if (error.context?.recovery) {
1174
+ return error.context.recovery;
1175
+ }
1176
+ const { operation, asset, interestRateMode } = context;
1177
+ switch (error.code) {
1178
+ case "INSUFFICIENT_BALANCE" /* INSUFFICIENT_BALANCE */:
1179
+ if (operation === "supply" || operation === "repay") {
1180
+ return {
1181
+ action: `Acquire more ${asset || "tokens"} or reduce the amount`,
1182
+ requiresUserAction: true
1183
+ };
1184
+ }
1185
+ return {
1186
+ action: "Check your wallet balance and try a smaller amount",
1187
+ requiresUserAction: true
1188
+ };
1189
+ case "INSUFFICIENT_COLLATERAL" /* INSUFFICIENT_COLLATERAL */:
1190
+ return {
1191
+ action: "Supply more collateral or reduce the borrow amount",
1192
+ details: "Your collateral is not sufficient for this borrow amount",
1193
+ requiresUserAction: true
1194
+ };
1195
+ case "HEALTH_FACTOR_TOO_LOW" /* HEALTH_FACTOR_TOO_LOW */:
1196
+ return {
1197
+ action: "Supply additional collateral or repay some debt first",
1198
+ details: "This operation would put your position at risk of liquidation",
1199
+ requiresUserAction: true
1200
+ };
1201
+ case "STABLE_BORROWING_NOT_ENABLED" /* STABLE_BORROWING_NOT_ENABLED */:
1202
+ return {
1203
+ action: "Use variable rate borrowing instead",
1204
+ details: `Stable rate is not available for ${asset || "this asset"}`,
1205
+ requiresUserAction: true
1206
+ };
1207
+ case "ASSET_NOT_SUPPORTED" /* ASSET_NOT_SUPPORTED */:
1208
+ return {
1209
+ action: "Choose a supported asset from the Aave markets",
1210
+ requiresUserAction: true
1211
+ };
1212
+ case "RESERVE_FROZEN" /* RESERVE_FROZEN */:
1213
+ return {
1214
+ action: "Only withdraw and repay operations are allowed for frozen assets",
1215
+ requiresUserAction: true
1216
+ };
1217
+ case "RESERVE_INACTIVE" /* RESERVE_INACTIVE */:
1218
+ return {
1219
+ action: "Choose an active asset or wait for this asset to be reactivated",
1220
+ requiresUserAction: true
1221
+ };
1222
+ case "POOL_PAUSED" /* POOL_PAUSED */:
1223
+ return {
1224
+ action: "Wait for the pool to be unpaused and try again",
1225
+ requiresUserAction: false
1226
+ };
1227
+ default:
1228
+ return {
1229
+ action: "Review the error details and try again",
1230
+ requiresUserAction: true
1231
+ };
1232
+ }
1233
+ }
1234
+ function formatErrorForLogging(processedError) {
1235
+ return {
1236
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1237
+ level: processedError.logLevel,
1238
+ error: {
1239
+ type: processedError.aaveError.name,
1240
+ code: processedError.aaveError.code,
1241
+ message: processedError.technicalMessage,
1242
+ userMessage: processedError.userMessage,
1243
+ stack: processedError.originalError.stack
1244
+ },
1245
+ context: processedError.context,
1246
+ recovery: processedError.recovery,
1247
+ isRetryable: processedError.isRetryable
1248
+ };
1249
+ }
1250
+ function logError(processedError, logger) {
1251
+ const logData = formatErrorForLogging(processedError);
1252
+ {
1253
+ const logPrefix = `[${processedError.logLevel.toUpperCase()}] Aave Error:`;
1254
+ console[processedError.logLevel === "error" ? "error" : "log"](
1255
+ logPrefix,
1256
+ JSON.stringify(logData, null, 2)
1257
+ );
1258
+ }
1259
+ }
1260
+ function processError(error, operation, params, transactionHash) {
1261
+ let context;
1262
+ switch (operation) {
1263
+ case "supply":
1264
+ context = createSupplyErrorContext(params || {});
1265
+ break;
1266
+ case "withdraw":
1267
+ context = createWithdrawErrorContext(params || {});
1268
+ break;
1269
+ case "borrow":
1270
+ context = createBorrowErrorContext(params || {});
1271
+ break;
1272
+ case "repay":
1273
+ context = createRepayErrorContext(params || {});
1274
+ break;
1275
+ default:
1276
+ context = { operation };
1277
+ }
1278
+ if (error.message.includes("BigNumber") || error.message.includes("invalid number")) {
1279
+ return handleBigNumberError(error, context);
1280
+ }
1281
+ if (error.message.includes("transaction")) {
1282
+ return handleTransactionError(error, transactionHash, context);
1283
+ }
1284
+ return handleContractError(error, "AavePool", operation, context);
1285
+ }
1286
+ function createUserFriendlyMessage(error) {
1287
+ const { aaveError, context } = error;
1288
+ const { operation, asset, amount, interestRateMode } = context;
1289
+ let baseMessage = aaveError.message;
1290
+ let operationContext = "";
1291
+ switch (operation) {
1292
+ case "supply":
1293
+ operationContext = `while supplying ${amount ? `${amount} ` : ""}${asset || "tokens"}`;
1294
+ break;
1295
+ case "withdraw":
1296
+ operationContext = `while withdrawing ${amount ? `${amount} ` : ""}${asset || "tokens"}`;
1297
+ break;
1298
+ case "borrow":
1299
+ const rateType = interestRateMode ? getRateModeName(interestRateMode).toLowerCase() : "";
1300
+ operationContext = `while borrowing ${amount ? `${amount} ` : ""}${asset || "tokens"}${rateType ? ` at ${rateType} rate` : ""}`;
1301
+ break;
1302
+ case "repay":
1303
+ const repayRateType = interestRateMode ? getRateModeName(interestRateMode).toLowerCase() : "";
1304
+ operationContext = `while repaying ${amount ? `${amount} ` : ""}${asset || "debt"}${repayRateType ? ` (${repayRateType} rate)` : ""}`;
1305
+ break;
1306
+ }
1307
+ if (operationContext) {
1308
+ baseMessage = `${baseMessage} This error occurred ${operationContext}.`;
1309
+ }
1310
+ if (error.recovery) {
1311
+ baseMessage += ` ${error.recovery.action}.`;
1312
+ if (error.recovery.details) {
1313
+ baseMessage += ` ${error.recovery.details}.`;
1314
+ }
1315
+ }
1316
+ return baseMessage;
1317
+ }
1318
+ function handleError(error, operation, params, transactionHash, logger) {
1319
+ const processedError = processError(error, operation, params, transactionHash);
1320
+ processedError.userMessage = createUserFriendlyMessage(processedError);
1321
+ logError(processedError);
1322
+ return processedError;
1323
+ }
1324
+
1325
+ // src/services/aave-service.ts
1326
+ var AaveService = class extends Service {
1327
+ static serviceType = "aave";
1328
+ provider;
1329
+ signer;
1330
+ poolService;
1331
+ uiPoolDataProvider;
1332
+ chainContext;
1333
+ isInitialized = false;
1334
+ constructor(runtime) {
1335
+ super(runtime);
1336
+ }
1337
+ get description() {
1338
+ return "Aave V3 Protocol service for lending, borrowing, and DeFi operations";
1339
+ }
1340
+ get capabilityDescription() {
1341
+ const currentChain = this.chainContext?.config?.name || "Multiple chains";
1342
+ return `Supports Aave V3 lending operations on ${currentChain}: supply, withdraw, borrow, repay with aTokens and variable/stable rates`;
1343
+ }
1344
+ async initialize(runtime) {
1345
+ try {
1346
+ elizaLogger.info("Initializing Aave V3 multi-chain service...");
1347
+ const targetChain = runtime.getSetting("AAVE_CHAIN") || "ethereum";
1348
+ elizaLogger.info(`Initializing for chain: ${targetChain}`);
1349
+ this.chainContext = resolveChainContext(targetChain);
1350
+ elizaLogger.info(`Chain context resolved: ${this.chainContext.config.name} (Chain ID: ${this.chainContext.config.chainId})`);
1351
+ const customRpcUrl = runtime.getSetting("AAVE_RPC_URL") || runtime.getSetting("RPC_URL");
1352
+ const rpcUrl = resolveRpcUrl(this.chainContext, customRpcUrl);
1353
+ elizaLogger.info(`Using RPC URL: ${rpcUrl.replace(/\/\/.*@/, "//***@")}`);
1354
+ const privateKey = runtime.getSetting("WALLET_PRIVATE_KEY");
1355
+ this.provider = new ethers.providers.JsonRpcProvider(rpcUrl);
1356
+ if (privateKey) {
1357
+ this.signer = new ethers.Wallet(privateKey, this.provider);
1358
+ elizaLogger.info(`Wallet connected: ${this.signer.address} on ${this.chainContext.config.name}`);
1359
+ const network = await this.provider.getNetwork();
1360
+ if (network.chainId !== this.chainContext.config.chainId) {
1361
+ elizaLogger.warn(`Network mismatch: RPC reports chain ID ${network.chainId}, expected ${this.chainContext.config.chainId}`);
1362
+ }
1363
+ }
1364
+ const poolConfig = {
1365
+ POOL: this.chainContext.addresses.POOL
1366
+ };
1367
+ if (this.chainContext.addresses.WETH_GATEWAY) {
1368
+ poolConfig.WETH_GATEWAY = this.chainContext.addresses.WETH_GATEWAY;
1369
+ }
1370
+ this.poolService = new Pool(this.provider, poolConfig);
1371
+ if (this.chainContext.addresses.UI_POOL_DATA_PROVIDER) {
1372
+ this.uiPoolDataProvider = new UiPoolDataProvider({
1373
+ uiPoolDataProviderAddress: this.chainContext.addresses.UI_POOL_DATA_PROVIDER,
1374
+ provider: this.provider,
1375
+ chainId: this.chainContext.config.chainId
1376
+ });
1377
+ }
1378
+ await this.verifyConnection();
1379
+ this.isInitialized = true;
1380
+ elizaLogger.info(`Aave V3 service initialized successfully on ${this.chainContext.config.name}`);
1381
+ elizaLogger.info(`Available assets: ${this.chainContext.config.popularAssets.join(", ")}`);
1382
+ } catch (error) {
1383
+ elizaLogger.error("Failed to initialize Aave service:", error);
1384
+ throw new AaveError(
1385
+ `Failed to initialize Aave V3 service: ${error instanceof Error ? error.message : String(error)}`,
1386
+ "INITIALIZATION_FAILED" /* INITIALIZATION_FAILED */,
1387
+ error instanceof Error ? error : new Error(String(error)),
1388
+ {
1389
+ targetChain: runtime.getSetting("AAVE_CHAIN"),
1390
+ originalError: error
1391
+ }
1392
+ );
1393
+ }
1394
+ }
1395
+ async verifyConnection() {
1396
+ try {
1397
+ if (!this.uiPoolDataProvider) {
1398
+ elizaLogger.warn(`UI Pool Data Provider not available on ${this.chainContext.config.name} - some features may be limited`);
1399
+ return;
1400
+ }
1401
+ const reservesData = await this.uiPoolDataProvider.getReservesHumanized({
1402
+ lendingPoolAddressProvider: this.chainContext.addresses.POOL_ADDRESSES_PROVIDER
1403
+ });
1404
+ if (!reservesData || reservesData.reservesData.length === 0) {
1405
+ throw new Error("No reserves data received from Aave V3 contracts");
1406
+ }
1407
+ elizaLogger.info(`Connected to Aave V3 on ${this.chainContext.config.name} - found ${reservesData.reservesData.length} reserves`);
1408
+ const availableAssets = reservesData.reservesData.map((r) => r.symbol).slice(0, 5);
1409
+ elizaLogger.info(`Sample available assets: ${availableAssets.join(", ")}`);
1410
+ } catch (error) {
1411
+ elizaLogger.error("Connection verification failed:", error);
1412
+ throw new AaveError(
1413
+ `Failed to verify Aave V3 connection on ${this.chainContext.config.name}`,
1414
+ "CONNECTION_FAILED" /* CONNECTION_FAILED */,
1415
+ error instanceof Error ? error : new Error(String(error)),
1416
+ {
1417
+ chain: this.chainContext.config.name,
1418
+ chainId: this.chainContext.config.chainId,
1419
+ poolAddress: this.chainContext.addresses.POOL
1420
+ }
1421
+ );
1422
+ }
1423
+ }
1424
+ ensureInitialized() {
1425
+ if (!this.isInitialized || !this.poolService) {
1426
+ throw new AaveError(
1427
+ "Aave service not initialized",
1428
+ "SERVICE_NOT_INITIALIZED" /* SERVICE_NOT_INITIALIZED */
1429
+ );
1430
+ }
1431
+ }
1432
+ ensureSigner() {
1433
+ if (!this.signer) {
1434
+ throw new AaveError(
1435
+ "Wallet not connected - private key required for transactions",
1436
+ "WALLET_NOT_CONNECTED" /* WALLET_NOT_CONNECTED */
1437
+ );
1438
+ }
1439
+ }
1440
+ async supply(params) {
1441
+ try {
1442
+ this.ensureInitialized();
1443
+ this.ensureSigner();
1444
+ const validatedParams = validateSupplyParams(params);
1445
+ const amount = parseAmount(validatedParams.amount).toString();
1446
+ const userAddress = validatedParams.user;
1447
+ elizaLogger.info(`Supplying ${amount} ${validatedParams.asset} for ${userAddress}`);
1448
+ const reserveData = await this.getReserveData(validatedParams.asset);
1449
+ const supplyTxs = await this.poolService.supply({
1450
+ user: userAddress,
1451
+ reserve: reserveData.underlyingAsset,
1452
+ amount,
1453
+ onBehalfOf: userAddress
1454
+ });
1455
+ if (supplyTxs.length === 0) {
1456
+ throw new AaveError(
1457
+ "Failed to generate supply transaction",
1458
+ "TRANSACTION_GENERATION_FAILED" /* TRANSACTION_GENERATION_FAILED */
1459
+ );
1460
+ }
1461
+ let approvalTxHash;
1462
+ let supplyTxHash;
1463
+ for (const tx of supplyTxs) {
1464
+ const ethersTransaction = {
1465
+ to: tx.to,
1466
+ data: tx.data,
1467
+ value: tx.value || "0",
1468
+ gasLimit: tx.gasLimit
1469
+ };
1470
+ const txResponse = await this.signer.sendTransaction(ethersTransaction);
1471
+ const receipt = await txResponse.wait();
1472
+ if (tx.txType === "ERC20_APPROVAL") {
1473
+ approvalTxHash = receipt.transactionHash;
1474
+ elizaLogger.info(`Token approval completed: ${approvalTxHash}`);
1475
+ } else {
1476
+ supplyTxHash = receipt.transactionHash;
1477
+ elizaLogger.info(`Supply transaction completed: ${supplyTxHash}`);
1478
+ }
1479
+ }
1480
+ const accountData = await this.getUserAccountData(userAddress);
1481
+ const aTokensReceived = new BigNumber3(amount);
1482
+ return {
1483
+ success: true,
1484
+ transactionHash: supplyTxHash,
1485
+ suppliedAmount: new BigNumber3(amount),
1486
+ aTokenAmount: aTokensReceived,
1487
+ newATokenBalance: aTokensReceived,
1488
+ // Simplified - would need to query actual balance
1489
+ gasUsed: new BigNumber3("0")
1490
+ // Would need to calculate from receipt
1491
+ };
1492
+ } catch (error) {
1493
+ elizaLogger.error("Supply operation failed:", error);
1494
+ const processedError = handleError(error instanceof Error ? error : new Error(String(error)), "supply", params);
1495
+ throw new AaveError(
1496
+ processedError.userMessage,
1497
+ "SUPPLY_FAILED" /* SUPPLY_FAILED */,
1498
+ error instanceof Error ? error : new Error(String(error)),
1499
+ { operation: "supply", params }
1500
+ );
1501
+ }
1502
+ }
1503
+ async withdraw(params) {
1504
+ try {
1505
+ this.ensureInitialized();
1506
+ this.ensureSigner();
1507
+ const validatedParams = validateWithdrawParams(params);
1508
+ const userAddress = validatedParams.user;
1509
+ elizaLogger.info(`Withdrawing ${validatedParams.amount} ${validatedParams.asset} for ${userAddress}`);
1510
+ const reserveData = await this.getReserveData(validatedParams.asset);
1511
+ let amount;
1512
+ if (isMaxAmount(validatedParams.amount)) {
1513
+ amount = "-1";
1514
+ } else {
1515
+ amount = parseAmount(validatedParams.amount).toString();
1516
+ }
1517
+ const withdrawTxs = await this.poolService.withdraw({
1518
+ user: userAddress,
1519
+ reserve: reserveData.underlyingAsset,
1520
+ amount,
1521
+ onBehalfOf: userAddress
1522
+ });
1523
+ if (withdrawTxs.length === 0) {
1524
+ throw new AaveError(
1525
+ "Failed to generate withdraw transaction",
1526
+ "TRANSACTION_GENERATION_FAILED" /* TRANSACTION_GENERATION_FAILED */
1527
+ );
1528
+ }
1529
+ const tx = withdrawTxs[0];
1530
+ const ethersTransaction = {
1531
+ to: tx.to,
1532
+ data: tx.data,
1533
+ value: tx.value || "0",
1534
+ gasLimit: tx.gasLimit
1535
+ };
1536
+ const txResponse = await this.signer.sendTransaction(ethersTransaction);
1537
+ const receipt = await txResponse.wait();
1538
+ const withdrawTxHash = receipt.transactionHash;
1539
+ elizaLogger.info(`Withdraw transaction completed: ${withdrawTxHash}`);
1540
+ const accountData = await this.getUserAccountData(userAddress);
1541
+ const amountWithdrawn = isMaxAmount(validatedParams.amount) ? new BigNumber3(amount) : parseAmount(validatedParams.amount);
1542
+ return {
1543
+ success: true,
1544
+ transactionHash: withdrawTxHash,
1545
+ amountWithdrawn,
1546
+ remainingATokenBalance: new BigNumber3(0),
1547
+ // Would need to query aToken contract
1548
+ newHealthFactor: accountData.healthFactor.toNumber(),
1549
+ gasUsed: new BigNumber3(receipt.gasUsed.toString())
1550
+ };
1551
+ } catch (error) {
1552
+ elizaLogger.error("Withdraw operation failed:", error);
1553
+ const processedError = handleError(error instanceof Error ? error : new Error(String(error)), "withdraw", params);
1554
+ throw new AaveError(
1555
+ processedError.userMessage,
1556
+ "WITHDRAW_FAILED" /* WITHDRAW_FAILED */,
1557
+ error instanceof Error ? error : new Error(String(error)),
1558
+ { operation: "withdraw", params }
1559
+ );
1560
+ }
1561
+ }
1562
+ async borrow(params) {
1563
+ try {
1564
+ this.ensureInitialized();
1565
+ this.ensureSigner();
1566
+ const validatedParams = validateBorrowParams(params);
1567
+ const amount = parseAmount(validatedParams.amount).toString();
1568
+ const userAddress = validatedParams.user;
1569
+ const rateMode = validatedParams.interestRateMode;
1570
+ elizaLogger.info(`Borrowing ${amount} ${validatedParams.asset} for ${userAddress}`);
1571
+ const reserveData = await this.getReserveData(validatedParams.asset);
1572
+ const borrowTxs = await this.poolService.borrow({
1573
+ user: userAddress,
1574
+ reserve: reserveData.underlyingAsset,
1575
+ amount,
1576
+ interestRateMode: rateMode === 1 /* STABLE */ ? 1 : 2,
1577
+ onBehalfOf: userAddress
1578
+ });
1579
+ if (borrowTxs.length === 0) {
1580
+ throw new AaveError(
1581
+ "Failed to generate borrow transaction",
1582
+ "TRANSACTION_GENERATION_FAILED" /* TRANSACTION_GENERATION_FAILED */
1583
+ );
1584
+ }
1585
+ const tx = borrowTxs[0];
1586
+ const ethersTransaction = {
1587
+ to: tx.to,
1588
+ data: tx.data,
1589
+ value: tx.value || "0",
1590
+ gasLimit: tx.gasLimit
1591
+ };
1592
+ const txResponse = await this.signer.sendTransaction(ethersTransaction);
1593
+ const receipt = await txResponse.wait();
1594
+ const borrowTxHash = receipt.transactionHash;
1595
+ elizaLogger.info(`Borrow transaction completed: ${borrowTxHash}`);
1596
+ const accountData = await this.getUserAccountData(userAddress);
1597
+ const borrowAPY = rateMode === 2 /* VARIABLE */ ? Number(reserveData.variableBorrowAPY) : Number(reserveData.stableBorrowAPY);
1598
+ return {
1599
+ success: true,
1600
+ transactionHash: borrowTxHash,
1601
+ amountBorrowed: new BigNumber3(amount),
1602
+ interestRateMode: rateMode,
1603
+ currentBorrowAPY: borrowAPY,
1604
+ newHealthFactor: accountData.healthFactor.toNumber(),
1605
+ gasUsed: new BigNumber3(receipt.gasUsed.toString())
1606
+ };
1607
+ } catch (error) {
1608
+ elizaLogger.error("Borrow operation failed:", error);
1609
+ const processedError = handleError(error instanceof Error ? error : new Error(String(error)), "borrow", params);
1610
+ throw new AaveError(
1611
+ processedError.userMessage,
1612
+ "BORROW_FAILED" /* BORROW_FAILED */,
1613
+ error instanceof Error ? error : new Error(String(error)),
1614
+ { operation: "borrow", params }
1615
+ );
1616
+ }
1617
+ }
1618
+ async repay(params) {
1619
+ try {
1620
+ this.ensureInitialized();
1621
+ this.ensureSigner();
1622
+ const validatedParams = validateRepayParams(params);
1623
+ const userAddress = validatedParams.user;
1624
+ const rateMode = validatedParams.interestRateMode;
1625
+ elizaLogger.info(`Repaying ${validatedParams.amount} ${validatedParams.asset} for ${userAddress}`);
1626
+ const reserveData = await this.getReserveData(validatedParams.asset);
1627
+ let amount;
1628
+ if (isMaxAmount(validatedParams.amount)) {
1629
+ amount = "-1";
1630
+ } else {
1631
+ amount = parseAmount(validatedParams.amount).toString();
1632
+ }
1633
+ const repayTxs = await this.poolService.repay({
1634
+ user: userAddress,
1635
+ reserve: reserveData.underlyingAsset,
1636
+ amount,
1637
+ interestRateMode: rateMode === 1 /* STABLE */ ? 1 : 2,
1638
+ onBehalfOf: userAddress
1639
+ });
1640
+ if (repayTxs.length === 0) {
1641
+ throw new AaveError(
1642
+ "Failed to generate repay transaction",
1643
+ "TRANSACTION_GENERATION_FAILED" /* TRANSACTION_GENERATION_FAILED */
1644
+ );
1645
+ }
1646
+ let approvalTxHash;
1647
+ let repayTxHash;
1648
+ for (const tx of repayTxs) {
1649
+ const ethersTransaction = {
1650
+ to: tx.to,
1651
+ data: tx.data,
1652
+ value: tx.value || "0",
1653
+ gasLimit: tx.gasLimit
1654
+ };
1655
+ const txResponse = await this.signer.sendTransaction(ethersTransaction);
1656
+ const receipt = await txResponse.wait();
1657
+ if (tx.txType === "ERC20_APPROVAL") {
1658
+ approvalTxHash = receipt.transactionHash;
1659
+ elizaLogger.info(`Token approval completed: ${approvalTxHash}`);
1660
+ } else {
1661
+ repayTxHash = receipt.transactionHash;
1662
+ elizaLogger.info(`Repay transaction completed: ${repayTxHash}`);
1663
+ }
1664
+ }
1665
+ const accountData = await this.getUserAccountData(userAddress);
1666
+ const amountRepaid = isMaxAmount(validatedParams.amount) ? new BigNumber3(amount === "-1" ? "0" : amount) : parseAmount(validatedParams.amount);
1667
+ return {
1668
+ success: true,
1669
+ transactionHash: repayTxHash,
1670
+ amountRepaid,
1671
+ interestRateMode: rateMode,
1672
+ remainingDebt: accountData.totalDebtETH,
1673
+ newHealthFactor: accountData.healthFactor.toNumber(),
1674
+ gasUsed: new BigNumber3("0"),
1675
+ // Would need to calculate from receipt
1676
+ approvalTransactionHash: approvalTxHash
1677
+ };
1678
+ } catch (error) {
1679
+ elizaLogger.error("Repay operation failed:", error);
1680
+ const processedError = handleError(error instanceof Error ? error : new Error(String(error)), "repay", params);
1681
+ throw new AaveError(
1682
+ processedError.userMessage,
1683
+ "REPAY_FAILED" /* REPAY_FAILED */,
1684
+ error instanceof Error ? error : new Error(String(error)),
1685
+ { operation: "repay", params }
1686
+ );
1687
+ }
1688
+ }
1689
+ async getUserPosition(userAddress) {
1690
+ try {
1691
+ this.ensureInitialized();
1692
+ if (!this.uiPoolDataProvider) {
1693
+ throw new AaveError(
1694
+ "UI Pool Data Provider not available on this chain - cannot fetch user positions",
1695
+ "UNSUPPORTED_OPERATION" /* UNSUPPORTED_OPERATION */
1696
+ );
1697
+ }
1698
+ const validatedAddress = validateAddress(userAddress);
1699
+ const userReservesData = await this.uiPoolDataProvider.getUserReservesHumanized({
1700
+ lendingPoolAddressProvider: this.chainContext.addresses.POOL_ADDRESSES_PROVIDER,
1701
+ user: validatedAddress
1702
+ });
1703
+ const reservesData = await this.uiPoolDataProvider.getReservesHumanized({
1704
+ lendingPoolAddressProvider: this.chainContext.addresses.POOL_ADDRESSES_PROVIDER
1705
+ });
1706
+ const formattedPoolReserves = formatReserves({
1707
+ reserves: reservesData.reservesData,
1708
+ currentTimestamp: Date.now() / 1e3,
1709
+ marketReferencePriceInUsd: reservesData.baseCurrencyData.marketReferenceCurrencyPriceInUsd,
1710
+ marketReferenceCurrencyDecimals: reservesData.baseCurrencyData.marketReferenceCurrencyDecimals
1711
+ });
1712
+ const userSummary = formatUserSummary({
1713
+ currentTimestamp: Date.now() / 1e3,
1714
+ marketReferencePriceInUsd: reservesData.baseCurrencyData.marketReferenceCurrencyPriceInUsd,
1715
+ marketReferenceCurrencyDecimals: reservesData.baseCurrencyData.marketReferenceCurrencyDecimals,
1716
+ userReserves: userReservesData.userReserves,
1717
+ formattedReserves: formattedPoolReserves,
1718
+ userEmodeCategoryId: userReservesData.userEmodeCategoryId
1719
+ });
1720
+ const positions = userReservesData.userReserves.filter(
1721
+ (reserve) => reserve.scaledATokenBalance !== "0" || reserve.scaledVariableDebt !== "0" || reserve.principalStableDebt !== "0"
1722
+ ).map((reserve) => {
1723
+ const poolReserve = formattedPoolReserves.find(
1724
+ (r) => r.underlyingAsset.toLowerCase() === reserve.underlyingAsset.toLowerCase()
1725
+ );
1726
+ return {
1727
+ asset: poolReserve?.symbol || "Unknown",
1728
+ suppliedAmount: new BigNumber3(reserve.scaledATokenBalance || "0"),
1729
+ borrowedAmountVariable: new BigNumber3(reserve.scaledVariableDebt || "0"),
1730
+ borrowedAmountStable: new BigNumber3(reserve.principalStableDebt || "0"),
1731
+ supplyAPY: Number(poolReserve?.supplyAPY || "0"),
1732
+ variableBorrowAPY: Number(poolReserve?.variableBorrowAPY || "0"),
1733
+ stableBorrowAPY: Number(poolReserve?.variableBorrowAPY || "0"),
1734
+ // Use variableBorrowAPY since stableBorrowAPY doesn't exist
1735
+ isCollateral: reserve.usageAsCollateralEnabled,
1736
+ liquidationThreshold: Number(poolReserve?.reserveLiquidationThreshold || "0") / 1e4,
1737
+ ltv: Number(poolReserve?.baseLTVasCollateral || "0") / 1e4
1738
+ };
1739
+ });
1740
+ return {
1741
+ userAddress: validatedAddress,
1742
+ totalCollateralETH: new BigNumber3(userSummary.totalCollateralUSD),
1743
+ totalDebtETH: new BigNumber3(userSummary.totalBorrowsUSD),
1744
+ availableBorrowsETH: new BigNumber3(userSummary.availableBorrowsUSD),
1745
+ currentLiquidationThreshold: Number(userSummary.currentLiquidationThreshold),
1746
+ ltv: Number(userSummary.currentLtv || userSummary.totalLTV || 0),
1747
+ healthFactor: new BigNumber3(userSummary.healthFactor),
1748
+ positions,
1749
+ lastUpdated: Date.now()
1750
+ };
1751
+ } catch (error) {
1752
+ elizaLogger.error("Failed to get user position:", error);
1753
+ throw new AaveError(
1754
+ "Failed to fetch user position",
1755
+ "DATA_FETCH_FAILED" /* DATA_FETCH_FAILED */,
1756
+ error instanceof Error ? error : new Error(String(error)),
1757
+ { userAddress }
1758
+ );
1759
+ }
1760
+ }
1761
+ async getUserAccountData(userAddress) {
1762
+ try {
1763
+ this.ensureInitialized();
1764
+ const position = await this.getUserPosition(userAddress);
1765
+ return {
1766
+ totalCollateralETH: position.totalCollateralETH,
1767
+ totalDebtETH: position.totalDebtETH,
1768
+ availableBorrowsETH: position.availableBorrowsETH,
1769
+ currentLiquidationThreshold: position.currentLiquidationThreshold,
1770
+ ltv: position.ltv,
1771
+ healthFactor: position.healthFactor
1772
+ };
1773
+ } catch (error) {
1774
+ elizaLogger.error("Failed to get user account data:", error);
1775
+ throw new AaveError(
1776
+ "Failed to fetch user account data",
1777
+ "DATA_FETCH_FAILED" /* DATA_FETCH_FAILED */,
1778
+ error instanceof Error ? error : new Error(String(error)),
1779
+ { userAddress }
1780
+ );
1781
+ }
1782
+ }
1783
+ async getMarketData() {
1784
+ this.ensureInitialized();
1785
+ try {
1786
+ if (!this.uiPoolDataProvider) {
1787
+ throw new AaveError(
1788
+ "UI Pool Data Provider not available on this chain - cannot fetch market data",
1789
+ "UNSUPPORTED_OPERATION" /* UNSUPPORTED_OPERATION */
1790
+ );
1791
+ }
1792
+ const reservesData = await this.uiPoolDataProvider.getReservesHumanized({
1793
+ lendingPoolAddressProvider: this.chainContext.addresses.POOL_ADDRESSES_PROVIDER
1794
+ });
1795
+ const formattedReserves = formatReserves({
1796
+ reserves: reservesData.reservesData,
1797
+ currentTimestamp: Date.now() / 1e3,
1798
+ marketReferencePriceInUsd: reservesData.baseCurrencyData.marketReferenceCurrencyPriceInUsd,
1799
+ marketReferenceCurrencyDecimals: reservesData.baseCurrencyData.marketReferenceCurrencyDecimals
1800
+ });
1801
+ return formattedReserves.map((reserve) => ({
1802
+ asset: reserve.symbol,
1803
+ aTokenAddress: reserve.aTokenAddress,
1804
+ stableDebtTokenAddress: reserve.stableDebtTokenAddress,
1805
+ variableDebtTokenAddress: reserve.variableDebtTokenAddress,
1806
+ underlyingAsset: reserve.underlyingAsset,
1807
+ decimals: reserve.decimals,
1808
+ supplyAPY: Number(reserve.supplyAPY),
1809
+ variableBorrowAPY: Number(reserve.variableBorrowAPY),
1810
+ stableBorrowAPY: Number(reserve.stableBorrowAPY),
1811
+ totalSupply: new BigNumber3(reserve.totalLiquidity),
1812
+ totalBorrow: new BigNumber3(reserve.totalDebt),
1813
+ utilizationRate: Number(reserve.utilizationRate),
1814
+ ltv: Number(reserve.baseLTVasCollateral) / 100,
1815
+ liquidationThreshold: Number(reserve.liquidationThreshold) / 100,
1816
+ liquidationBonus: Number(reserve.liquidationBonus) / 100,
1817
+ reserveFactor: Number(reserve.reserveFactor) / 100,
1818
+ priceInUSD: new BigNumber3(reserve.priceInUSD || "0"),
1819
+ isActive: reserve.isActive,
1820
+ isFrozen: reserve.isFrozen,
1821
+ isPaused: reserve.isPaused,
1822
+ supplyCap: new BigNumber3(reserve.supplyCap || "0"),
1823
+ borrowCap: new BigNumber3(reserve.borrowCap || "0"),
1824
+ lastUpdated: Date.now()
1825
+ }));
1826
+ } catch (error) {
1827
+ elizaLogger.error("Failed to get market data:", error);
1828
+ throw new AaveError(
1829
+ "Failed to fetch market data",
1830
+ "DATA_FETCH_FAILED" /* DATA_FETCH_FAILED */,
1831
+ error instanceof Error ? error : new Error(String(error)),
1832
+ {}
1833
+ );
1834
+ }
1835
+ }
1836
+ async getReserveData(asset) {
1837
+ const marketData = await this.getMarketData();
1838
+ const assetData = marketData.find(
1839
+ (m) => m.asset.toLowerCase() === asset.toLowerCase() || m.underlyingAsset.toLowerCase() === asset.toLowerCase()
1840
+ );
1841
+ if (!assetData) {
1842
+ throw new AaveError(
1843
+ `Asset not found in market data: ${asset}`,
1844
+ "ASSET_NOT_FOUND" /* ASSET_NOT_FOUND */,
1845
+ void 0,
1846
+ { asset }
1847
+ );
1848
+ }
1849
+ return assetData;
1850
+ }
1851
+ async stop() {
1852
+ elizaLogger.info("Stopping Aave service...");
1853
+ this.isInitialized = false;
1854
+ }
1855
+ };
1856
+ var extractionTemplate = `Given the user's request to supply/deposit assets to Aave, extract the required information.
1857
+
1858
+ User request: "{{userMessage}}"
1859
+
1860
+ Extract and return ONLY a JSON object with the following structure:
1861
+ {
1862
+ "asset": "asset symbol (e.g., USDC, WETH, DAI) or address",
1863
+ "amount": "amount to supply as string (e.g., '100', '0.5')",
1864
+ "userAddress": "user's ethereum address if mentioned, otherwise null"
1865
+ }
1866
+
1867
+ Important:
1868
+ - For ETH mentions, use "WETH" as the asset
1869
+ - Amount should be the numeric value only (no symbols)
1870
+ - If amount is "all", "max", or "everything", use "max"
1871
+ - Asset should be uppercase symbol if recognizable
1872
+
1873
+ Return only the JSON object, no other text.`;
1874
+ var supplyAction = {
1875
+ name: "SUPPLY_TO_AAVE",
1876
+ description: "Supply assets to Aave V3 to earn yield and receive aTokens",
1877
+ similes: ["DEPOSIT_TO_AAVE", "LEND_TO_AAVE", "SUPPLY_ASSET", "DEPOSIT_ASSET"],
1878
+ examples: [[
1879
+ {
1880
+ name: "User",
1881
+ content: { text: "I want to supply 1000 USDC to Aave" }
1882
+ },
1883
+ {
1884
+ name: "Assistant",
1885
+ content: {
1886
+ text: "\u{1F3E6} Supplying 1000 USDC to Aave V3...\n\n\u2705 Successfully supplied 1000 USDC\n\u{1F4C4} Transaction: 0x123...abc\n\u{1FA99} Received: 1000 aUSDC (earning yield)\n\u{1F4B0} Current APY: 3.25%",
1887
+ actions: ["SUPPLY_TO_AAVE"]
1888
+ }
1889
+ }
1890
+ ], [
1891
+ {
1892
+ name: "User",
1893
+ content: { text: "deposit 0.5 ETH to start earning yield" }
1894
+ },
1895
+ {
1896
+ name: "Assistant",
1897
+ content: {
1898
+ text: "\u{1F3E6} Supplying 0.5 WETH to Aave V3...\n\n\u2705 Successfully supplied 0.5 WETH\n\u{1F4C4} Transaction: 0x456...def\n\u{1FA99} Received: 0.5 aWETH (earning yield)\n\u{1F4B0} Current APY: 2.15%",
1899
+ actions: ["SUPPLY_TO_AAVE"]
1900
+ }
1901
+ }
1902
+ ], [
1903
+ {
1904
+ name: "User",
1905
+ content: { text: "supply all my DAI to aave for lending" }
1906
+ },
1907
+ {
1908
+ name: "Assistant",
1909
+ content: {
1910
+ text: "\u{1F3E6} Supplying all available DAI to Aave V3...\n\n\u2705 Successfully supplied 2,500 DAI\n\u{1F4C4} Transaction: 0x789...ghi\n\u{1FA99} Received: 2,500 aDAI (earning yield)\n\u{1F4B0} Current APY: 4.80%",
1911
+ actions: ["SUPPLY_TO_AAVE"]
1912
+ }
1913
+ }
1914
+ ]],
1915
+ async validate(runtime, message, _state) {
1916
+ try {
1917
+ const rpcUrl = runtime.getSetting("AAVE_RPC_URL");
1918
+ if (!rpcUrl) {
1919
+ return false;
1920
+ }
1921
+ const text = message.content.text?.toLowerCase() || "";
1922
+ const supplyKeywords = [
1923
+ "supply",
1924
+ "deposit",
1925
+ "lend",
1926
+ "provide liquidity"
1927
+ ];
1928
+ const hasSupplyKeyword = supplyKeywords.some((keyword) => text.includes(keyword));
1929
+ const hasAmount = /\d+/.test(text) || text.includes("all") || text.includes("max");
1930
+ const hasAsset = /(usdc|usdt|dai|eth|weth|btc|wbtc|aave|link)/i.test(text);
1931
+ return hasSupplyKeyword && (hasAmount || hasAsset);
1932
+ } catch {
1933
+ return false;
1934
+ }
1935
+ },
1936
+ async handler(runtime, message, _state, _options, callback) {
1937
+ const content = message.content.text;
1938
+ if (!content) {
1939
+ const errorMessage = "Please specify the asset and amount to supply to Aave.";
1940
+ await callback?.({ text: errorMessage, source: message.content.source });
1941
+ return { text: errorMessage, success: false };
1942
+ }
1943
+ let asset = "";
1944
+ let amount = "";
1945
+ let userAddress;
1946
+ try {
1947
+ const aaveService = runtime.getService("aave");
1948
+ if (!aaveService) {
1949
+ throw new Error("Aave service not available");
1950
+ }
1951
+ const prompt = extractionTemplate.replace("{{userMessage}}", content);
1952
+ const response = await runtime.useModel(ModelType.TEXT_LARGE, { prompt });
1953
+ try {
1954
+ const cleanedResponse = response.replace(/^```(?:json)?\n?/, "").replace(/\n?```$/, "").trim();
1955
+ const parsed = JSON.parse(cleanedResponse);
1956
+ asset = parsed.asset;
1957
+ amount = parsed.amount;
1958
+ userAddress = parsed.userAddress;
1959
+ if (!asset || !amount) {
1960
+ throw new Error("Missing required parameters");
1961
+ }
1962
+ } catch (parseError) {
1963
+ elizaLogger.warn("Failed to parse LLM response, falling back to regex:", parseError);
1964
+ const amountAssetMatch = content.match(/(?:supply|deposit|lend)\s+([a-zA-Z\d.,]+)\s+(\w+)/i);
1965
+ const assetAmountMatch = content.match(/(\w+)\s+([a-zA-Z\d.,]+)/i);
1966
+ if (amountAssetMatch) {
1967
+ amount = amountAssetMatch[1].replace(/,/g, "");
1968
+ asset = amountAssetMatch[2].toUpperCase();
1969
+ } else if (assetAmountMatch && assetAmountMatch[2].match(/^\d/)) {
1970
+ asset = assetAmountMatch[1].toUpperCase();
1971
+ amount = assetAmountMatch[2].replace(/,/g, "");
1972
+ } else {
1973
+ throw new Error("Could not extract asset and amount from request");
1974
+ }
1975
+ if (asset === "ETH") {
1976
+ asset = "WETH";
1977
+ }
1978
+ }
1979
+ const supplyParams = validateSupplyParams({
1980
+ asset,
1981
+ amount,
1982
+ // Let validation handle string to BigNumber conversion
1983
+ user: userAddress || runtime.getSetting("WALLET_ADDRESS")
1984
+ });
1985
+ const result = await aaveService.supply(supplyParams);
1986
+ const successMessage = `\u{1F3E6} **Successfully Supplied to Aave V3**
1987
+
1988
+ \u{1F4B0} **Amount**: ${result.suppliedAmount.toFixed(4)} ${asset}
1989
+ \u{1FA99} **Received**: ${result.aTokenAmount.toFixed(4)} a${asset}
1990
+ \u{1F4C4} **Transaction**: ${result.transactionHash}
1991
+ \u{1F4B0} **New aToken Balance**: ${result.newATokenBalance.toFixed(4)} a${asset}
1992
+
1993
+ Your a${asset} tokens will automatically earn yield! \u{1F331}`;
1994
+ await callback?.({
1995
+ text: successMessage,
1996
+ source: message.content.source
1997
+ });
1998
+ return {
1999
+ text: `Successfully supplied ${result.suppliedAmount.toFixed(4)} ${asset} to Aave`,
2000
+ success: true,
2001
+ data: {
2002
+ action: "supply",
2003
+ asset,
2004
+ amount: result.suppliedAmount.toString(),
2005
+ aTokensReceived: result.aTokenAmount.toString(),
2006
+ newBalance: result.newATokenBalance.toString(),
2007
+ transactionHash: result.transactionHash
2008
+ }
2009
+ };
2010
+ } catch (error) {
2011
+ elizaLogger.error("Supply action failed:", error);
2012
+ let errorMessage;
2013
+ if (error instanceof Error) {
2014
+ if (error.message.includes("insufficient balance")) {
2015
+ errorMessage = `\u274C Insufficient ${asset} balance. Please check your wallet balance and try again.`;
2016
+ } else if (error.message.includes("allowance")) {
2017
+ errorMessage = `\u274C Token approval required. The transaction will include approval for ${asset}.`;
2018
+ } else if (error.message.includes("reserve inactive")) {
2019
+ errorMessage = `\u274C ${asset} market is currently inactive on Aave. Please try a different asset.`;
2020
+ } else if (error.message.includes("supply cap")) {
2021
+ errorMessage = `\u274C ${asset} supply cap reached on Aave. Please try a different asset or smaller amount.`;
2022
+ } else {
2023
+ errorMessage = `\u274C Supply failed: ${error.message}`;
2024
+ }
2025
+ } else {
2026
+ errorMessage = "\u274C Supply failed due to an unknown error. Please try again.";
2027
+ }
2028
+ await callback?.({
2029
+ text: errorMessage,
2030
+ source: message.content.source
2031
+ });
2032
+ return {
2033
+ text: errorMessage,
2034
+ success: false,
2035
+ data: {
2036
+ action: "supply",
2037
+ error: error instanceof Error ? error.message : "Unknown error"
2038
+ }
2039
+ };
2040
+ }
2041
+ }
2042
+ };
2043
+ var extractionTemplate2 = `Given the user's request to withdraw/redeem assets from Aave, extract the required information.
2044
+
2045
+ User request: "{{userMessage}}"
2046
+
2047
+ Extract and return ONLY a JSON object with the following structure:
2048
+ {
2049
+ "asset": "asset symbol (e.g., USDC, WETH, DAI) or address",
2050
+ "amount": "amount to withdraw as string (e.g., '100', '0.5', 'max')",
2051
+ "userAddress": "user's ethereum address if mentioned, otherwise null"
2052
+ }
2053
+
2054
+ Important:
2055
+ - For ETH mentions, use "WETH" as the asset
2056
+ - Amount should be the numeric value only (no symbols)
2057
+ - If amount is "all", "max", "everything", or similar, use "max"
2058
+ - Asset should be uppercase symbol if recognizable
2059
+
2060
+ Return only the JSON object, no other text.`;
2061
+ var withdrawAction = {
2062
+ name: "WITHDRAW_FROM_AAVE",
2063
+ description: "Withdraw supplied assets from Aave V3 by redeeming aTokens",
2064
+ similes: ["REDEEM_FROM_AAVE", "UNSTAKE_FROM_AAVE", "WITHDRAW_ASSET", "REDEEM_ATOKEN"],
2065
+ examples: [[
2066
+ {
2067
+ name: "User",
2068
+ content: { text: "I want to withdraw 500 USDC from Aave" }
2069
+ },
2070
+ {
2071
+ name: "Assistant",
2072
+ content: {
2073
+ text: "\u{1F4B8} Withdrawing 500 USDC from Aave V3...\n\n\u2705 Successfully withdrew 500 USDC\n\u{1F4C4} Transaction: 0x123...abc\n\u{1F525} Burned: 500 aUSDC\n\u{1F4B0} Remaining balance: 1,500 aUSDC\n\u{1F4CA} Earning: 3.25% APY on remaining balance",
2074
+ actions: ["WITHDRAW_FROM_AAVE"]
2075
+ }
2076
+ }
2077
+ ], [
2078
+ {
2079
+ name: "User",
2080
+ content: { text: "redeem 0.1 ETH from my aave position" }
2081
+ },
2082
+ {
2083
+ name: "Assistant",
2084
+ content: {
2085
+ text: "\u{1F4B8} Withdrawing 0.1 WETH from Aave V3...\n\n\u2705 Successfully withdrew 0.1 WETH\n\u{1F4C4} Transaction: 0x456...def\n\u{1F525} Burned: 0.1 aWETH\n\u{1F4B0} Remaining balance: 0.9 aWETH\n\u{1F4CA} Earning: 2.15% APY on remaining balance",
2086
+ actions: ["WITHDRAW_FROM_AAVE"]
2087
+ }
2088
+ }
2089
+ ], [
2090
+ {
2091
+ name: "User",
2092
+ content: { text: "withdraw all my DAI from aave lending" }
2093
+ },
2094
+ {
2095
+ name: "Assistant",
2096
+ content: {
2097
+ text: "\u{1F4B8} Withdrawing all available DAI from Aave V3...\n\n\u2705 Successfully withdrew 2,500 DAI\n\u{1F4C4} Transaction: 0x789...ghi\n\u{1F525} Burned: 2,500 aDAI\n\u{1F4B0} Remaining balance: 0 aDAI\n\u{1F389} Position fully withdrawn!",
2098
+ actions: ["WITHDRAW_FROM_AAVE"]
2099
+ }
2100
+ }
2101
+ ], [
2102
+ {
2103
+ name: "User",
2104
+ content: { text: "can I get my 100 USDT back from aave?" }
2105
+ },
2106
+ {
2107
+ name: "Assistant",
2108
+ content: {
2109
+ text: "\u{1F4B8} Withdrawing 100 USDT from Aave V3...\n\n\u2705 Successfully withdrew 100 USDT\n\u{1F4C4} Transaction: 0xabc...xyz\n\u{1F525} Burned: 100 aUSDT\n\u{1F4B0} Remaining balance: 400 aUSDT\n\u{1F4CA} Earning: 4.10% APY on remaining balance",
2110
+ actions: ["WITHDRAW_FROM_AAVE"]
2111
+ }
2112
+ }
2113
+ ]],
2114
+ async validate(runtime, message, _state) {
2115
+ try {
2116
+ const rpcUrl = runtime.getSetting("AAVE_RPC_URL");
2117
+ if (!rpcUrl) {
2118
+ return false;
2119
+ }
2120
+ const text = message.content.text?.toLowerCase() || "";
2121
+ const withdrawKeywords = [
2122
+ "withdraw",
2123
+ "redeem",
2124
+ "unstake",
2125
+ "take out",
2126
+ "get back",
2127
+ "withdraw from aave",
2128
+ "redeem from aave",
2129
+ "unstake from aave",
2130
+ "cash out",
2131
+ "exit position"
2132
+ ];
2133
+ return withdrawKeywords.some((keyword) => text.includes(keyword));
2134
+ } catch {
2135
+ return false;
2136
+ }
2137
+ },
2138
+ async handler(runtime, message, _state, _options, callback) {
2139
+ const content = message.content.text;
2140
+ if (!content) {
2141
+ const errorMessage = "Please specify the asset and amount to withdraw from Aave.";
2142
+ await callback?.({ text: errorMessage, source: message.content.source });
2143
+ return { text: errorMessage, success: false };
2144
+ }
2145
+ let asset = "";
2146
+ let amount = "";
2147
+ let userAddress;
2148
+ try {
2149
+ const aaveService = runtime.getService("aave");
2150
+ if (!aaveService) {
2151
+ throw new Error("Aave service not available");
2152
+ }
2153
+ const prompt = extractionTemplate2.replace("{{userMessage}}", content);
2154
+ const response = await runtime.useModel(ModelType.TEXT_LARGE, { prompt });
2155
+ try {
2156
+ const cleanedResponse = response.replace(/^```(?:json)?\n?/, "").replace(/\n?```$/, "").trim();
2157
+ const parsed = JSON.parse(cleanedResponse);
2158
+ asset = parsed.asset;
2159
+ amount = parsed.amount;
2160
+ userAddress = parsed.userAddress;
2161
+ if (!asset || !amount) {
2162
+ throw new Error("Missing required parameters");
2163
+ }
2164
+ } catch (parseError) {
2165
+ elizaLogger.warn("Failed to parse LLM response, falling back to regex:", parseError);
2166
+ const amountAssetMatch = content.match(/(?:withdraw|redeem|get.*back)\s+([a-zA-Z\d.,]+)\s+(\w+)/i);
2167
+ const assetAmountMatch = content.match(/(\w+)\s+([a-zA-Z\d.,]+)/i);
2168
+ const maxPatterns = /(?:withdraw|redeem|get).*(?:all|max|everything|full)/i;
2169
+ if (amountAssetMatch) {
2170
+ amount = amountAssetMatch[1].replace(/,/g, "");
2171
+ asset = amountAssetMatch[2].toUpperCase();
2172
+ } else if (assetAmountMatch && assetAmountMatch[2].match(/^\d/)) {
2173
+ asset = assetAmountMatch[1].toUpperCase();
2174
+ amount = assetAmountMatch[2].replace(/,/g, "");
2175
+ } else if (maxPatterns.test(content)) {
2176
+ const assetMatch = content.match(/(?:withdraw|redeem).*?(USDC|WETH|ETH|DAI|USDT|WBTC|LINK|UNI|AAVE|CRV|COMP)/i);
2177
+ if (assetMatch) {
2178
+ asset = assetMatch[1].toUpperCase();
2179
+ amount = "max";
2180
+ } else {
2181
+ throw new Error("Could not extract asset from request");
2182
+ }
2183
+ } else {
2184
+ throw new Error("Could not extract asset and amount from request");
2185
+ }
2186
+ if (asset === "ETH") {
2187
+ asset = "WETH";
2188
+ }
2189
+ }
2190
+ const withdrawParams = validateWithdrawParams({
2191
+ asset,
2192
+ amount,
2193
+ // Let validation handle string to BigNumber conversion
2194
+ user: userAddress || runtime.getSetting("WALLET_ADDRESS")
2195
+ });
2196
+ const result = await aaveService.withdraw(withdrawParams);
2197
+ let successMessage;
2198
+ if (result.remainingATokenBalance.isZero()) {
2199
+ successMessage = `\u{1F4B8} **Successfully Withdrew from Aave V3**
2200
+
2201
+ \u{1F389} **Full Withdrawal Complete!**
2202
+ \u{1F4B0} **Amount**: ${result.amountWithdrawn.toFixed(4)} ${asset}
2203
+ \u{1F4C4} **Transaction**: ${result.transactionHash}
2204
+ \u{1F4B0} **Remaining Balance**: 0 a${asset}
2205
+
2206
+ Your position has been fully withdrawn! \u{1F3C1}`;
2207
+ } else {
2208
+ successMessage = `\u{1F4B8} **Successfully Withdrew from Aave V3**
2209
+
2210
+ \u{1F4B0} **Amount**: ${result.amountWithdrawn.toFixed(4)} ${asset}
2211
+ \u{1F4C4} **Transaction**: ${result.transactionHash}
2212
+ \u{1F4B0} **Remaining Balance**: ${result.remainingATokenBalance.toFixed(4)} a${asset}
2213
+
2214
+ Your remaining a${asset} tokens continue earning yield! \u{1F331}`;
2215
+ }
2216
+ await callback?.({
2217
+ text: successMessage,
2218
+ source: message.content.source
2219
+ });
2220
+ return {
2221
+ text: `Successfully withdrew ${result.amountWithdrawn.toFixed(4)} ${asset} from Aave`,
2222
+ success: true,
2223
+ data: {
2224
+ action: "withdraw",
2225
+ asset,
2226
+ amount: result.amountWithdrawn.toString(),
2227
+ remainingBalance: result.remainingATokenBalance.toString(),
2228
+ transactionHash: result.transactionHash,
2229
+ isFullWithdrawal: result.remainingATokenBalance.isZero()
2230
+ }
2231
+ };
2232
+ } catch (error) {
2233
+ elizaLogger.error("Withdraw action failed:", error);
2234
+ let errorMessage;
2235
+ if (error instanceof Error) {
2236
+ if (error.message.includes("insufficient atoken") || error.message.includes("no atoken balance")) {
2237
+ errorMessage = `\u274C Insufficient a${asset || "Token"} balance. You don't have enough supplied to withdraw this amount.`;
2238
+ } else if (error.message.includes("exceeds balance")) {
2239
+ errorMessage = `\u274C Withdrawal amount exceeds your a${asset || "Token"} balance. Check your supplied position and try a smaller amount.`;
2240
+ } else if (error.message.includes("reserve frozen")) {
2241
+ errorMessage = `\u274C ${asset || "Asset"} withdrawals are currently frozen on Aave. Only emergency withdrawals may be available.`;
2242
+ } else if (error.message.includes("reserve paused")) {
2243
+ errorMessage = `\u274C ${asset || "Asset"} operations are temporarily paused on Aave. Please try again later.`;
2244
+ } else if (error.message.includes("health factor")) {
2245
+ errorMessage = `\u274C Cannot withdraw - would leave position with insufficient collateral. Supply more collateral or reduce borrows first.`;
2246
+ } else if (error.message.includes("reserve inactive")) {
2247
+ errorMessage = `\u274C ${asset || "Asset"} market is currently inactive on Aave. Please try a different asset.`;
2248
+ } else {
2249
+ errorMessage = `\u274C Withdrawal failed: ${error.message}`;
2250
+ }
2251
+ } else {
2252
+ errorMessage = "\u274C Withdrawal failed due to an unknown error. Please try again.";
2253
+ }
2254
+ await callback?.({
2255
+ text: errorMessage,
2256
+ source: message.content.source
2257
+ });
2258
+ return {
2259
+ text: errorMessage,
2260
+ success: false,
2261
+ data: {
2262
+ action: "withdraw",
2263
+ error: error instanceof Error ? error.message : "Unknown error"
2264
+ }
2265
+ };
2266
+ }
2267
+ }
2268
+ };
2269
+ var borrowAction = {
2270
+ name: "AAVE_BORROW",
2271
+ similes: [
2272
+ "BORROW_FROM_AAVE",
2273
+ "AAVE_LOAN",
2274
+ "TAKE_LOAN",
2275
+ "BORROW_ASSET",
2276
+ "DEFI_BORROW"
2277
+ ],
2278
+ description: "Borrow assets from Aave V3 protocol with specified interest rate mode",
2279
+ validate: async (runtime, message) => {
2280
+ const content = message.content?.text?.toLowerCase();
2281
+ if (!content) return false;
2282
+ const borrowKeywords = [
2283
+ "borrow",
2284
+ "loan",
2285
+ "take loan",
2286
+ "get loan",
2287
+ "variable rate",
2288
+ "stable rate",
2289
+ "interest rate"
2290
+ ];
2291
+ const hasBorrowKeyword = borrowKeywords.some(
2292
+ (keyword) => content.includes(keyword)
2293
+ );
2294
+ if (!hasBorrowKeyword) return false;
2295
+ const hasAssetOrAmount = /\b(usdc|usdt|dai|eth|weth|btc|wbtc|\d+\.?\d*)\b/i.test(content);
2296
+ return hasAssetOrAmount;
2297
+ },
2298
+ examples: [[
2299
+ {
2300
+ name: "User",
2301
+ content: { text: "I want to borrow 1000 USDC with variable rate from Aave" }
2302
+ },
2303
+ {
2304
+ name: "Assistant",
2305
+ content: {
2306
+ text: "I'll help you borrow 1000 USDC with variable interest rate from Aave V3.",
2307
+ actions: ["AAVE_BORROW"]
2308
+ }
2309
+ }
2310
+ ], [
2311
+ {
2312
+ name: "User",
2313
+ content: { text: "Take a loan of 0.5 ETH with stable rate" }
2314
+ },
2315
+ {
2316
+ name: "Assistant",
2317
+ content: {
2318
+ text: "I'll process your loan of 0.5 ETH with stable interest rate from Aave.",
2319
+ actions: ["AAVE_BORROW"]
2320
+ }
2321
+ }
2322
+ ]],
2323
+ handler: async (runtime, message, state, options, callback) => {
2324
+ try {
2325
+ elizaLogger.info("Starting Aave borrow operation...");
2326
+ const aaveService = runtime.getService("aave");
2327
+ if (!aaveService) {
2328
+ throw new Error("Aave service not available");
2329
+ }
2330
+ const content = message.content?.text;
2331
+ if (!content) {
2332
+ throw new Error("No message content provided");
2333
+ }
2334
+ let asset = "";
2335
+ let amount = "";
2336
+ let rateMode = 2 /* VARIABLE */;
2337
+ const amountAssetMatch = content.match(/(?:borrow|loan|take loan|get loan)(?:\s+of)?\s+([a-zA-Z\d.,]+)\s+(\w+)/i);
2338
+ const assetAmountMatch = content.match(/(\w+)\s+([a-zA-Z\d.,]+)/i);
2339
+ if (amountAssetMatch) {
2340
+ amount = amountAssetMatch[1].replace(/,/g, "");
2341
+ asset = amountAssetMatch[2].toUpperCase();
2342
+ } else if (assetAmountMatch && assetAmountMatch[2].match(/^\d/)) {
2343
+ asset = assetAmountMatch[1].toUpperCase();
2344
+ amount = assetAmountMatch[2].replace(/,/g, "");
2345
+ } else {
2346
+ throw new Error('Could not extract asset and amount from request. Please specify like "borrow 1000 USDC"');
2347
+ }
2348
+ if (content.toLowerCase().includes("stable")) {
2349
+ rateMode = 1 /* STABLE */;
2350
+ }
2351
+ if (asset === "ETH") {
2352
+ asset = "WETH";
2353
+ }
2354
+ const userAddress = runtime.getSetting("WALLET_ADDRESS");
2355
+ if (!userAddress) {
2356
+ throw new Error("Wallet address not configured. Please set WALLET_ADDRESS in settings.");
2357
+ }
2358
+ const parsedAmount = parseAmount(amount);
2359
+ elizaLogger.info(`Borrowing ${parsedAmount} ${asset} with ${rateMode === 1 /* STABLE */ ? "stable" : "variable"} rate for ${userAddress}`);
2360
+ const params = {
2361
+ asset,
2362
+ amount: parsedAmount,
2363
+ interestRateMode: rateMode,
2364
+ user: userAddress
2365
+ };
2366
+ const result = await aaveService.borrow(params);
2367
+ if (!result.success) {
2368
+ throw new Error(`Borrow operation failed: ${result.error?.message}`);
2369
+ }
2370
+ const rateTypeText = rateMode === 1 /* STABLE */ ? "stable" : "variable";
2371
+ const successMessage = `\u{1F4B0} **Successfully Borrowed from Aave V3**
2372
+
2373
+ \u{1F389} **Loan Approved!**
2374
+ \u{1F4B8} **Amount**: ${result.amountBorrowed.toFixed(4)} ${asset}
2375
+ \u{1F4C8} **Interest Rate**: ${rateTypeText.charAt(0).toUpperCase() + rateTypeText.slice(1)} (${result.currentBorrowAPY.toFixed(2)}% APY)
2376
+ \u{1F4C4} **Transaction**: ${result.transactionHash}
2377
+ \u{1F3E5} **Health Factor**: ${result.newHealthFactor.toFixed(3)}
2378
+
2379
+ ${result.newHealthFactor < 1.5 ? "\u26A0\uFE0F **Warning**: Your health factor is getting low. Consider adding more collateral!" : "\u2705 Your position looks healthy! Monitor your health factor regularly."}`;
2380
+ await callback?.({
2381
+ text: successMessage,
2382
+ source: message.content.source
2383
+ });
2384
+ return {
2385
+ text: `Successfully borrowed ${result.amountBorrowed.toFixed(4)} ${asset} from Aave`,
2386
+ success: true,
2387
+ data: {
2388
+ action: "borrow",
2389
+ asset,
2390
+ amount: result.amountBorrowed.toString(),
2391
+ interestRateMode: rateTypeText,
2392
+ currentAPY: result.currentBorrowAPY,
2393
+ transactionHash: result.transactionHash,
2394
+ healthFactor: result.newHealthFactor
2395
+ }
2396
+ };
2397
+ } catch (error) {
2398
+ elizaLogger.error("Borrow action failed:", error);
2399
+ let errorMessage;
2400
+ if (error instanceof Error) {
2401
+ if (error.message.includes("insufficient collateral")) {
2402
+ errorMessage = `\u274C **Insufficient Collateral**
2403
+
2404
+ You don't have enough collateral to borrow this amount.
2405
+ \u{1F4A1} **Try this:**
2406
+ \u2022 Supply more assets as collateral first
2407
+ \u2022 Reduce the borrow amount
2408
+ \u2022 Check your health factor`;
2409
+ } else if (error.message.includes("borrowing not enabled")) {
2410
+ errorMessage = `\u274C **Borrowing Not Available**
2411
+
2412
+ This asset cannot be borrowed on Aave V3 currently.
2413
+ \u{1F4A1} **Try borrowing a different asset like USDC, USDT, or DAI**`;
2414
+ } else if (error.message.includes("health factor")) {
2415
+ errorMessage = `\u274C **Health Factor Too Low**
2416
+
2417
+ This borrow would put your position at risk of liquidation.
2418
+ \u{1F4A1} **Add more collateral or reduce borrow amount**`;
2419
+ } else {
2420
+ errorMessage = `\u274C **Borrow Failed**: ${error.message}`;
2421
+ }
2422
+ } else {
2423
+ errorMessage = "\u274C **Borrow operation failed**. Please try again or check your parameters.";
2424
+ }
2425
+ await callback?.({
2426
+ text: errorMessage,
2427
+ error: true
2428
+ });
2429
+ return {
2430
+ text: error instanceof Error ? error.message : "Borrow operation failed",
2431
+ success: false,
2432
+ error: error instanceof Error ? error : new Error(String(error))
2433
+ };
2434
+ }
2435
+ }
2436
+ };
2437
+ var repayAction = {
2438
+ name: "AAVE_REPAY",
2439
+ similes: [
2440
+ "REPAY_TO_AAVE",
2441
+ "AAVE_REPAYMENT",
2442
+ "PAY_BACK",
2443
+ "REPAY_DEBT",
2444
+ "DEFI_REPAY",
2445
+ "PAYBACK_LOAN"
2446
+ ],
2447
+ description: "Repay borrowed assets to Aave V3 protocol",
2448
+ validate: async (runtime, message) => {
2449
+ const content = message.content?.text?.toLowerCase();
2450
+ if (!content) return false;
2451
+ const repayKeywords = [
2452
+ "repay",
2453
+ "pay back",
2454
+ "payback",
2455
+ "pay off",
2456
+ "repayment",
2457
+ "debt",
2458
+ "loan repay",
2459
+ "close position"
2460
+ ];
2461
+ const hasRepayKeyword = repayKeywords.some(
2462
+ (keyword) => content.includes(keyword)
2463
+ );
2464
+ if (!hasRepayKeyword) return false;
2465
+ const hasAssetOrAmount = /\b(usdc|usdt|dai|eth|weth|btc|wbtc|\d+\.?\d*|all|everything|max|maximum)\b/i.test(content);
2466
+ return hasAssetOrAmount;
2467
+ },
2468
+ examples: [[
2469
+ {
2470
+ name: "User",
2471
+ content: { text: "I want to repay 1000 USDC variable debt to Aave" }
2472
+ },
2473
+ {
2474
+ name: "Assistant",
2475
+ content: {
2476
+ text: "I'll help you repay 1000 USDC variable debt to Aave V3.",
2477
+ actions: ["AAVE_REPAY"]
2478
+ }
2479
+ }
2480
+ ], [
2481
+ {
2482
+ name: "User",
2483
+ content: { text: "Pay back all my ETH debt with stable rate" }
2484
+ },
2485
+ {
2486
+ name: "Assistant",
2487
+ content: {
2488
+ text: "I'll process the full repayment of your ETH stable debt.",
2489
+ actions: ["AAVE_REPAY"]
2490
+ }
2491
+ }
2492
+ ]],
2493
+ handler: async (runtime, message, state, options, callback) => {
2494
+ let asset = "";
2495
+ let amount = "";
2496
+ try {
2497
+ elizaLogger.info("Starting Aave repay operation...");
2498
+ const aaveService = runtime.getService("aave");
2499
+ if (!aaveService) {
2500
+ throw new Error("Aave service not available");
2501
+ }
2502
+ const content = message.content?.text;
2503
+ if (!content) {
2504
+ throw new Error("No message content provided");
2505
+ }
2506
+ let rateMode = 2 /* VARIABLE */;
2507
+ const amountAssetMatch = content.match(/(?:repay|pay back|payback|pay off)(?:\s+(?:all|full|maximum|max))?\s+([a-zA-Z\d.,]+)\s+(\w+)/i);
2508
+ const assetAmountMatch = content.match(/(\w+)\s+([a-zA-Z\d.,]+)/i);
2509
+ const maxRepayMatch = content.match(/(?:repay|pay back|payback|pay off)\s+(?:all|full|maximum|max|everything)(?:\s+(\w+))?/i);
2510
+ if (maxRepayMatch) {
2511
+ amount = "max";
2512
+ asset = maxRepayMatch[1]?.toUpperCase() || "USDC";
2513
+ } else if (amountAssetMatch) {
2514
+ amount = amountAssetMatch[1].replace(/,/g, "");
2515
+ asset = amountAssetMatch[2].toUpperCase();
2516
+ } else if (assetAmountMatch && assetAmountMatch[2].match(/^\d/)) {
2517
+ asset = assetAmountMatch[1].toUpperCase();
2518
+ amount = assetAmountMatch[2].replace(/,/g, "");
2519
+ } else {
2520
+ throw new Error('Could not extract asset and amount from request. Please specify like "repay 1000 USDC"');
2521
+ }
2522
+ if (content.toLowerCase().includes("stable")) {
2523
+ rateMode = 1 /* STABLE */;
2524
+ }
2525
+ if (asset === "ETH") {
2526
+ asset = "WETH";
2527
+ }
2528
+ const userAddress = runtime.getSetting("WALLET_ADDRESS");
2529
+ if (!userAddress) {
2530
+ throw new Error("Wallet address not configured. Please set WALLET_ADDRESS in settings.");
2531
+ }
2532
+ const parsedAmount = parseAmount(amount);
2533
+ const isFullRepayment = isMaxAmount(parsedAmount);
2534
+ elizaLogger.info(`Repaying ${isFullRepayment ? "full" : amount} ${asset} ${rateMode === 1 /* STABLE */ ? "stable" : "variable"} debt for ${userAddress}`);
2535
+ const params = {
2536
+ asset,
2537
+ amount: parsedAmount,
2538
+ interestRateMode: rateMode,
2539
+ user: userAddress
2540
+ };
2541
+ const result = await aaveService.repay(params);
2542
+ if (!result.success) {
2543
+ throw new Error(`Repay operation failed: ${result.error?.message}`);
2544
+ }
2545
+ const rateTypeText = rateMode === 1 /* STABLE */ ? "stable" : "variable";
2546
+ let successMessage;
2547
+ if (result.remainingDebt.isZero()) {
2548
+ successMessage = `\u{1F4B8} **Successfully Repaid Debt to Aave V3**
2549
+
2550
+ \u{1F389} **Debt Fully Repaid!**
2551
+ \u{1F4B0} **Amount**: ${result.amountRepaid.toFixed(4)} ${asset}
2552
+ \u{1F4C8} **Debt Type**: ${rateTypeText.charAt(0).toUpperCase() + rateTypeText.slice(1)} rate
2553
+ \u{1F4C4} **Transaction**: ${result.transactionHash}
2554
+ ${result.approvalTransactionHash ? `\u{1F513} **Approval**: ${result.approvalTransactionHash}` : ""}
2555
+ \u{1F3E5} **Health Factor**: ${result.newHealthFactor.toFixed(3)}
2556
+ \u{1F4B0} **Remaining Debt**: $0.00
2557
+
2558
+ \u{1F38A} Congratulations! You've completely paid off your ${asset} debt!`;
2559
+ } else {
2560
+ successMessage = `\u{1F4B8} **Successfully Repaid Debt to Aave V3**
2561
+
2562
+ \u{1F4B0} **Amount**: ${result.amountRepaid.toFixed(4)} ${asset}
2563
+ \u{1F4C8} **Debt Type**: ${rateTypeText.charAt(0).toUpperCase() + rateTypeText.slice(1)} rate
2564
+ \u{1F4C4} **Transaction**: ${result.transactionHash}
2565
+ ${result.approvalTransactionHash ? `\u{1F513} **Approval**: ${result.approvalTransactionHash}` : ""}
2566
+ \u{1F3E5} **Health Factor**: ${result.newHealthFactor.toFixed(3)}
2567
+ \u{1F4B0} **Remaining Debt**: ${result.remainingDebt.toFixed(4)} ETH equivalent
2568
+
2569
+ \u2705 Your position health has improved!`;
2570
+ }
2571
+ await callback?.({
2572
+ text: successMessage,
2573
+ source: message.content.source
2574
+ });
2575
+ return {
2576
+ text: `Successfully repaid ${result.amountRepaid.toFixed(4)} ${asset} to Aave`,
2577
+ success: true,
2578
+ data: {
2579
+ action: "repay",
2580
+ asset,
2581
+ amount: result.amountRepaid.toString(),
2582
+ interestRateMode: rateTypeText,
2583
+ transactionHash: result.transactionHash,
2584
+ approvalTransactionHash: result.approvalTransactionHash,
2585
+ healthFactor: result.newHealthFactor,
2586
+ remainingDebt: result.remainingDebt.toString(),
2587
+ isFullRepayment: result.remainingDebt.isZero()
2588
+ }
2589
+ };
2590
+ } catch (error) {
2591
+ elizaLogger.error("Repay action failed:", error);
2592
+ let errorMessage;
2593
+ if (error instanceof Error) {
2594
+ if (error.message.includes("insufficient balance")) {
2595
+ errorMessage = `\u274C **Insufficient Balance**
2596
+
2597
+ You don't have enough ${asset || "tokens"} to repay this amount.
2598
+ \u{1F4A1} **Try this:**
2599
+ \u2022 Check your wallet balance
2600
+ \u2022 Reduce the repay amount
2601
+ \u2022 Get more tokens first`;
2602
+ } else if (error.message.includes("no debt")) {
2603
+ errorMessage = `\u274C **No Debt Found**
2604
+
2605
+ You don't have any debt for this asset/rate type on Aave V3.
2606
+ \u{1F4A1} **Check your position to see current debts**`;
2607
+ } else if (error.message.includes("allowance")) {
2608
+ errorMessage = `\u274C **Token Approval Failed**
2609
+
2610
+ Could not approve tokens for repayment.
2611
+ \u{1F4A1} **This might be a temporary issue - please try again**`;
2612
+ } else {
2613
+ errorMessage = `\u274C **Repay Failed**: ${error.message}`;
2614
+ }
2615
+ } else {
2616
+ errorMessage = "\u274C **Repayment operation failed**. Please try again or check your parameters.";
2617
+ }
2618
+ await callback?.({
2619
+ text: errorMessage,
2620
+ error: true
2621
+ });
2622
+ return {
2623
+ text: error instanceof Error ? error.message : "Repay operation failed",
2624
+ success: false,
2625
+ error: error instanceof Error ? error : new Error(String(error))
2626
+ };
2627
+ }
2628
+ }
2629
+ };
2630
+ var marketDataProvider = {
2631
+ name: "AAVE_MARKET_DATA",
2632
+ get: async (runtime, message, state) => {
2633
+ try {
2634
+ elizaLogger.info("Fetching Aave V3 market data...");
2635
+ const aaveService = runtime.getService("aave");
2636
+ if (!aaveService) {
2637
+ return { text: "Aave service not available - cannot fetch market data." };
2638
+ }
2639
+ const marketData = await aaveService.getMarketData();
2640
+ if (!marketData || marketData.length === 0) {
2641
+ return { text: "No market data available for Aave V3 at this time." };
2642
+ }
2643
+ const majorAssets = marketData.filter((data) => ["USDC", "USDT", "DAI", "WETH", "ETH", "WBTC", "BTC"].includes(data.asset)).sort((a, b) => {
2644
+ const comparison = b.totalSupply.comparedTo(a.totalSupply);
2645
+ return comparison === null ? 0 : comparison;
2646
+ }).slice(0, 8);
2647
+ if (majorAssets.length === 0) {
2648
+ return { text: "Market data not available for major assets." };
2649
+ }
2650
+ let marketSummary = `\u{1F4CA} **Aave V3 Market Overview** (Ethereum)
2651
+
2652
+ `;
2653
+ const totalLiquidity = majorAssets.reduce(
2654
+ (sum, asset) => sum.plus(asset.totalSupply),
2655
+ new BigNumber3(0)
2656
+ );
2657
+ const avgSupplyAPY = majorAssets.reduce(
2658
+ (sum, asset) => sum + asset.supplyAPY,
2659
+ 0
2660
+ ) / majorAssets.length;
2661
+ marketSummary += `\u{1F4B0} **Total Liquidity**: $${formatLargeNumber(totalLiquidity)} across major assets
2662
+ `;
2663
+ marketSummary += `\u{1F4C8} **Avg Supply APY**: ${avgSupplyAPY.toFixed(2)}%
2664
+
2665
+ `;
2666
+ marketSummary += `**\u{1F3E6} Lending Rates:**
2667
+ `;
2668
+ marketSummary += `\`\`\`
2669
+ `;
2670
+ marketSummary += `Asset Supply APY Borrow APY Utilization
2671
+ `;
2672
+ marketSummary += `\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
2673
+ `;
2674
+ for (const asset of majorAssets) {
2675
+ const assetSymbol = asset.asset.padEnd(6);
2676
+ const supplyRate = `${asset.supplyAPY.toFixed(2)}%`.padStart(9);
2677
+ const borrowRate = `${asset.variableBorrowAPY.toFixed(2)}%`.padStart(9);
2678
+ const utilization = `${(asset.utilizationRate * 100).toFixed(1)}%`.padStart(9);
2679
+ marketSummary += `${assetSymbol} ${supplyRate} ${borrowRate} ${utilization}
2680
+ `;
2681
+ }
2682
+ marketSummary += `\`\`\`
2683
+
2684
+ `;
2685
+ const highYieldAssets = majorAssets.filter((asset) => asset.supplyAPY > 3).sort((a, b) => b.supplyAPY - a.supplyAPY);
2686
+ const lowBorrowCostAssets = majorAssets.filter((asset) => asset.variableBorrowAPY < 5).sort((a, b) => a.variableBorrowAPY - b.variableBorrowAPY);
2687
+ if (highYieldAssets.length > 0) {
2688
+ marketSummary += `\u{1F31F} **High Yield Opportunities:**
2689
+ `;
2690
+ highYieldAssets.slice(0, 3).forEach((asset) => {
2691
+ marketSummary += `\u2022 ${asset.asset}: ${asset.supplyAPY.toFixed(2)}% APY
2692
+ `;
2693
+ });
2694
+ marketSummary += `
2695
+ `;
2696
+ }
2697
+ if (lowBorrowCostAssets.length > 0) {
2698
+ marketSummary += `\u{1F4B8} **Low Borrow Costs:**
2699
+ `;
2700
+ lowBorrowCostAssets.slice(0, 3).forEach((asset) => {
2701
+ marketSummary += `\u2022 ${asset.asset}: ${asset.variableBorrowAPY.toFixed(2)}% APY
2702
+ `;
2703
+ });
2704
+ marketSummary += `
2705
+ `;
2706
+ }
2707
+ const highUtilAssets = majorAssets.filter((asset) => asset.utilizationRate > 0.8);
2708
+ if (highUtilAssets.length > 0) {
2709
+ marketSummary += `\u26A0\uFE0F **High Utilization Warning:**
2710
+ `;
2711
+ highUtilAssets.forEach((asset) => {
2712
+ marketSummary += `\u2022 ${asset.asset}: ${(asset.utilizationRate * 100).toFixed(1)}% utilized
2713
+ `;
2714
+ });
2715
+ marketSummary += `Higher utilization may impact liquidity and rates.
2716
+
2717
+ `;
2718
+ }
2719
+ marketSummary += `\u{1F4C5} *Data updated: ${(/* @__PURE__ */ new Date()).toLocaleString()}*`;
2720
+ return { text: marketSummary };
2721
+ } catch (error) {
2722
+ elizaLogger.error("Failed to get market data:", error);
2723
+ return { text: "Unable to fetch current market data from Aave V3. Please try again later." };
2724
+ }
2725
+ }
2726
+ };
2727
+ function formatLargeNumber(num) {
2728
+ if (num.isGreaterThanOrEqualTo(1e9)) {
2729
+ return `${num.dividedBy(1e9).toFixed(1)}B`;
2730
+ } else if (num.isGreaterThanOrEqualTo(1e6)) {
2731
+ return `${num.dividedBy(1e6).toFixed(1)}M`;
2732
+ } else if (num.isGreaterThanOrEqualTo(1e3)) {
2733
+ return `${num.dividedBy(1e3).toFixed(1)}K`;
2734
+ }
2735
+ return num.toFixed(2);
2736
+ }
2737
+ var positionProvider = {
2738
+ name: "AAVE_POSITION",
2739
+ get: async (runtime, message, state) => {
2740
+ try {
2741
+ elizaLogger.info("Fetching user Aave V3 position...");
2742
+ const userAddress = runtime.getSetting("WALLET_ADDRESS");
2743
+ if (!userAddress) {
2744
+ return { text: "Wallet address not configured. Please set WALLET_ADDRESS to view your position." };
2745
+ }
2746
+ const aaveService = runtime.getService("aave");
2747
+ if (!aaveService) {
2748
+ return { text: "Aave service not available - cannot fetch position data." };
2749
+ }
2750
+ const position = await aaveService.getUserPosition(userAddress);
2751
+ if (!position) {
2752
+ return { text: "Unable to fetch your Aave V3 position at this time." };
2753
+ }
2754
+ const hasSupplyPositions = position.positions.some((p) => p.suppliedAmount.isGreaterThan(0));
2755
+ const hasBorrowPositions = position.positions.some(
2756
+ (p) => p.borrowedAmountVariable.isGreaterThan(0) || p.borrowedAmountStable.isGreaterThan(0)
2757
+ );
2758
+ if (!hasSupplyPositions && !hasBorrowPositions) {
2759
+ return { text: `\u{1F4BC} **Your Aave V3 Position**
2760
+
2761
+ \u{1F3E6} **No active positions found**
2762
+
2763
+ You don't have any supplies or borrows on Aave V3 yet.
2764
+ Ready to start your DeFi journey? Try:
2765
+ \u2022 "supply 1000 USDC" to start earning yield
2766
+ \u2022 Check current "market rates" for opportunities` };
2767
+ }
2768
+ let positionSummary = `\u{1F4BC} **Your Aave V3 Position**
2769
+
2770
+ `;
2771
+ const shortAddress = `${userAddress.slice(0, 6)}...${userAddress.slice(-4)}`;
2772
+ positionSummary += `\u{1F464} **Address**: ${shortAddress}
2773
+
2774
+ `;
2775
+ positionSummary += `\u{1F3E5} **Health Overview:**
2776
+ `;
2777
+ positionSummary += `\u2022 Health Factor: ${position.healthFactor.isFinite() ? position.healthFactor.toFixed(3) : "\u221E"}
2778
+ `;
2779
+ positionSummary += `\u2022 Total Collateral: $${position.totalCollateralETH.toFixed(2)}
2780
+ `;
2781
+ positionSummary += `\u2022 Total Debt: $${position.totalDebtETH.toFixed(2)}
2782
+ `;
2783
+ if (position.totalDebtETH.isGreaterThan(0)) {
2784
+ positionSummary += `\u2022 Available to Borrow: $${position.availableBorrowsETH.toFixed(2)}
2785
+ `;
2786
+ positionSummary += `\u2022 LTV Ratio: ${(position.ltv * 100).toFixed(1)}%
2787
+ `;
2788
+ }
2789
+ positionSummary += `
2790
+ `;
2791
+ if (position.healthFactor.isFinite() && position.healthFactor.isLessThan(1.5)) {
2792
+ positionSummary += `\u26A0\uFE0F **HEALTH FACTOR WARNING**
2793
+ `;
2794
+ if (position.healthFactor.isLessThan(1.1)) {
2795
+ positionSummary += `\u{1F6A8} **CRITICAL**: Your position is near liquidation!
2796
+ `;
2797
+ } else {
2798
+ positionSummary += `\u26A1 **CAUTION**: Consider adding collateral or reducing debt
2799
+ `;
2800
+ }
2801
+ positionSummary += `
2802
+ `;
2803
+ }
2804
+ const supplies = position.positions.filter((p) => p.suppliedAmount.isGreaterThan(0));
2805
+ if (supplies.length > 0) {
2806
+ positionSummary += `\u{1F4B0} **Supply Positions:**
2807
+ `;
2808
+ positionSummary += `\`\`\`
2809
+ `;
2810
+ positionSummary += `Asset Amount APY Collateral
2811
+ `;
2812
+ positionSummary += `\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
2813
+ `;
2814
+ for (const supply of supplies) {
2815
+ const asset = supply.asset.padEnd(6);
2816
+ const amount = formatNumber(supply.suppliedAmount).padStart(10);
2817
+ const apy = `${supply.supplyAPY.toFixed(2)}%`.padStart(6);
2818
+ const collateral = (supply.isCollateral ? "\u2705" : "\u274C").padStart(10);
2819
+ positionSummary += `${asset} ${amount} ${apy} ${collateral}
2820
+ `;
2821
+ }
2822
+ positionSummary += `\`\`\`
2823
+
2824
+ `;
2825
+ }
2826
+ const borrows = position.positions.filter(
2827
+ (p) => p.borrowedAmountVariable.isGreaterThan(0) || p.borrowedAmountStable.isGreaterThan(0)
2828
+ );
2829
+ if (borrows.length > 0) {
2830
+ positionSummary += `\u{1F4B8} **Borrow Positions:**
2831
+ `;
2832
+ positionSummary += `\`\`\`
2833
+ `;
2834
+ positionSummary += `Asset Amount APY Type
2835
+ `;
2836
+ positionSummary += `\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
2837
+ `;
2838
+ for (const borrow of borrows) {
2839
+ if (borrow.borrowedAmountVariable.isGreaterThan(0)) {
2840
+ const asset = borrow.asset.padEnd(6);
2841
+ const amount = formatNumber(borrow.borrowedAmountVariable).padStart(10);
2842
+ const apy = `${borrow.variableBorrowAPY.toFixed(2)}%`.padStart(6);
2843
+ const type = "Variable".padStart(8);
2844
+ positionSummary += `${asset} ${amount} ${apy} ${type}
2845
+ `;
2846
+ }
2847
+ if (borrow.borrowedAmountStable.isGreaterThan(0)) {
2848
+ const asset = borrow.asset.padEnd(6);
2849
+ const amount = formatNumber(borrow.borrowedAmountStable).padStart(10);
2850
+ const apy = `${borrow.stableBorrowAPY.toFixed(2)}%`.padStart(6);
2851
+ const type = "Stable".padStart(8);
2852
+ positionSummary += `${asset} ${amount} ${apy} ${type}
2853
+ `;
2854
+ }
2855
+ }
2856
+ positionSummary += `\`\`\`
2857
+
2858
+ `;
2859
+ }
2860
+ positionSummary += `\u{1F4A1} **Position Insights:**
2861
+ `;
2862
+ if (hasSupplyPositions && !hasBorrowPositions) {
2863
+ positionSummary += `\u2022 You're earning yield as a pure lender \u{1F3E6}
2864
+ `;
2865
+ positionSummary += `\u2022 Consider borrowing stablecoins for leverage or other opportunities
2866
+ `;
2867
+ } else if (hasBorrowPositions) {
2868
+ if (position.healthFactor.isGreaterThan(2)) {
2869
+ positionSummary += `\u2022 Healthy leveraged position \u{1F4AA}
2870
+ `;
2871
+ positionSummary += `\u2022 You have room to borrow more if needed
2872
+ `;
2873
+ } else if (position.healthFactor.isGreaterThan(1.5)) {
2874
+ positionSummary += `\u2022 Moderate risk leveraged position \u2696\uFE0F
2875
+ `;
2876
+ positionSummary += `\u2022 Monitor health factor closely
2877
+ `;
2878
+ }
2879
+ }
2880
+ const nonCollateralAssets = supplies.filter((s) => !s.isCollateral);
2881
+ if (nonCollateralAssets.length > 0) {
2882
+ positionSummary += `\u2022 Some assets not used as collateral - enable for more borrowing power
2883
+ `;
2884
+ }
2885
+ positionSummary += `
2886
+ \u{1F4C5} *Position updated: ${(/* @__PURE__ */ new Date()).toLocaleString()}*`;
2887
+ return { text: positionSummary };
2888
+ } catch (error) {
2889
+ elizaLogger.error("Failed to get user position:", error);
2890
+ return { text: "Unable to fetch your current position from Aave V3. Please try again later." };
2891
+ }
2892
+ }
2893
+ };
2894
+ function formatNumber(num) {
2895
+ if (num.isGreaterThanOrEqualTo(1e6)) {
2896
+ return `${num.dividedBy(1e6).toFixed(2)}M`;
2897
+ } else if (num.isGreaterThanOrEqualTo(1e3)) {
2898
+ return `${num.dividedBy(1e3).toFixed(1)}K`;
2899
+ } else if (num.isGreaterThanOrEqualTo(1)) {
2900
+ return num.toFixed(2);
2901
+ } else {
2902
+ return num.toFixed(4);
2903
+ }
2904
+ }
2905
+
2906
+ // src/index.ts
2907
+ var plugin = {
2908
+ name: "aave",
2909
+ description: "Aave V3 Protocol integration for lending and borrowing operations",
2910
+ // Core services
2911
+ services: [AaveService],
2912
+ // User actions
2913
+ actions: [supplyAction, withdrawAction, borrowAction, repayAction],
2914
+ // Context providers
2915
+ providers: [marketDataProvider, positionProvider],
2916
+ // No evaluators for now
2917
+ evaluators: []
2918
+ };
2919
+ var index_default = plugin;
2920
+
2921
+ export { AAVE_CONSTANTS, AaveError, AaveErrorCode, AaveService, InterestRateMode, borrowAction, index_default as default, isAaveError, isValidInterestRateMode, marketDataProvider, plugin, positionProvider, repayAction, supplyAction, withdrawAction };
2922
+ //# sourceMappingURL=index.js.map
2923
+ //# sourceMappingURL=index.js.map