@agether/sdk 2.17.3 → 2.18.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 CHANGED
@@ -36,6 +36,8 @@ __export(index_exports, {
36
36
  AGETHER_8004_SCORER_ABI: () => AGETHER_8004_SCORER_ABI,
37
37
  AGETHER_8004_VALIDATION_MODULE_ABI: () => AGETHER_8004_VALIDATION_MODULE_ABI,
38
38
  AGETHER_HOOK_MULTIPLEXER_ABI: () => AGETHER_HOOK_MULTIPLEXER_ABI,
39
+ AaveClient: () => AaveClient,
40
+ AgentAccountClient: () => AgentAccountClient,
39
41
  AgentIdentityClient: () => AgentIdentityClient,
40
42
  AgentNotApprovedError: () => AgentNotApprovedError,
41
43
  AgetherClient: () => AgetherClient,
@@ -79,13 +81,13 @@ var import_ethers = require("ethers");
79
81
  var import_axios = __toESM(require("axios"));
80
82
 
81
83
  // src/types/index.ts
82
- var ChainId = /* @__PURE__ */ ((ChainId3) => {
83
- ChainId3[ChainId3["Ethereum"] = 1] = "Ethereum";
84
- ChainId3[ChainId3["Base"] = 8453] = "Base";
85
- ChainId3[ChainId3["BaseSepolia"] = 84532] = "BaseSepolia";
86
- ChainId3[ChainId3["Sepolia"] = 11155111] = "Sepolia";
87
- ChainId3[ChainId3["Hardhat"] = 31337] = "Hardhat";
88
- return ChainId3;
84
+ var ChainId = /* @__PURE__ */ ((ChainId4) => {
85
+ ChainId4[ChainId4["Ethereum"] = 1] = "Ethereum";
86
+ ChainId4[ChainId4["Base"] = 8453] = "Base";
87
+ ChainId4[ChainId4["BaseSepolia"] = 84532] = "BaseSepolia";
88
+ ChainId4[ChainId4["Sepolia"] = 11155111] = "Sepolia";
89
+ ChainId4[ChainId4["Hardhat"] = 31337] = "Hardhat";
90
+ return ChainId4;
89
91
  })(ChainId || {});
90
92
  var AgetherError = class extends Error {
91
93
  constructor(message, code, details) {
@@ -1261,67 +1263,14 @@ var AgetherClient = class _AgetherClient {
1261
1263
  };
1262
1264
 
1263
1265
  // src/clients/MorphoClient.ts
1264
- var import_ethers2 = require("ethers");
1265
- var import_axios2 = __toESM(require("axios"));
1266
-
1267
- // src/utils/retry.ts
1268
- var RETRIABLE_PATTERNS = [
1269
- "ECONNRESET",
1270
- "ECONNREFUSED",
1271
- "ENOTFOUND",
1272
- "ETIMEDOUT",
1273
- "fetch failed",
1274
- "network error",
1275
- "socket hang up",
1276
- "rate limit",
1277
- "429",
1278
- "502",
1279
- "503",
1280
- "504",
1281
- "timeout"
1282
- ];
1283
- function isRetriable(error) {
1284
- const msg = error instanceof Error ? error.message.toLowerCase() : String(error).toLowerCase();
1285
- return RETRIABLE_PATTERNS.some((p) => msg.includes(p.toLowerCase()));
1286
- }
1287
- async function withRetry(fn, options = {}) {
1288
- const {
1289
- maxRetries = 3,
1290
- baseDelay = 1e3,
1291
- maxDelay = 15e3,
1292
- onRetry
1293
- } = options;
1294
- let lastError;
1295
- for (let attempt = 1; attempt <= maxRetries; attempt++) {
1296
- try {
1297
- return await fn();
1298
- } catch (error) {
1299
- lastError = error instanceof Error ? error : new Error(String(error));
1300
- if (attempt >= maxRetries || !isRetriable(error)) {
1301
- throw lastError;
1302
- }
1303
- const delay = Math.min(baseDelay * Math.pow(2, attempt - 1), maxDelay);
1304
- const jitter = delay * (0.5 + Math.random() * 0.5);
1305
- onRetry?.(attempt, lastError);
1306
- await new Promise((resolve) => setTimeout(resolve, jitter));
1307
- }
1308
- }
1309
- throw lastError;
1310
- }
1266
+ var import_ethers3 = require("ethers");
1311
1267
 
1312
- // src/clients/MorphoClient.ts
1313
- var MORPHO_API_URL2 = "https://api.morpho.org/graphql";
1268
+ // src/clients/AgentAccountClient.ts
1269
+ var import_ethers2 = require("ethers");
1314
1270
  var MODE_SINGLE2 = "0x0000000000000000000000000000000000000000000000000000000000000000";
1315
1271
  var MODE_BATCH = "0x0100000000000000000000000000000000000000000000000000000000000000";
1316
- var morphoIface = new import_ethers2.ethers.Interface(MORPHO_BLUE_ABI);
1317
- var erc20Iface2 = new import_ethers2.ethers.Interface(ERC20_ABI);
1318
- var _MorphoClient = class _MorphoClient {
1272
+ var AgentAccountClient = class {
1319
1273
  constructor(config) {
1320
- /** Market params cache: keyed by market uniqueKey (bytes32 hash) */
1321
- this._marketCache = /* @__PURE__ */ new Map();
1322
- /** Dynamic token registry: symbol (uppercase) or address (lowercase) → { address, symbol, decimals } */
1323
- this._tokenCache = /* @__PURE__ */ new Map();
1324
- this._discoveredAt = 0;
1325
1274
  if (!config.agentId) {
1326
1275
  throw new AgetherError(
1327
1276
  "agentId is required. Use AgetherClient.register() first to get an agentId.",
@@ -1356,13 +1305,10 @@ var _MorphoClient = class _MorphoClient {
1356
1305
  }
1357
1306
  const addrs = { ...defaultCfg.contracts, ...config.contracts };
1358
1307
  this.agether4337Factory = new import_ethers2.Contract(addrs.agether4337Factory, ACCOUNT_FACTORY_ABI, this._signer);
1359
- this.morphoBlue = new import_ethers2.Contract(addrs.morphoBlue, MORPHO_BLUE_ABI, this.provider);
1360
1308
  this.entryPoint = new import_ethers2.Contract(addrs.entryPoint, ENTRYPOINT_V07_ABI, this._signer);
1361
1309
  }
1362
- // ════════════════════════════════════════════════════════
1363
- // Account Management
1364
- // ════════════════════════════════════════════════════════
1365
- /** Resolve the AgentAccount address (cached, with retry for flaky RPCs). */
1310
+ // ─── Account Management ───────────────────────────────────────────────
1311
+ /** Resolve the AgentAccount (Safe) address. Cached after first call. */
1366
1312
  async getAccountAddress() {
1367
1313
  if (this._accountAddress) return this._accountAddress;
1368
1314
  const MAX_RETRIES = 3;
@@ -1388,26 +1334,260 @@ var _MorphoClient = class _MorphoClient {
1388
1334
  getAgentId() {
1389
1335
  return this.agentId;
1390
1336
  }
1391
- /**
1392
- * Get the EOA wallet address (synchronous, best-effort).
1393
- *
1394
- * For the `privateKey` path this always works. For the `signer` path
1395
- * it works if the signer exposes `.address` synchronously (e.g. ethers.Wallet).
1396
- * If the address has not been resolved yet, throws — call `getSignerAddress()` first.
1397
- */
1337
+ /** Get the EOA wallet address (synchronous). */
1398
1338
  getWalletAddress() {
1399
1339
  if (this._eoaAddress) return this._eoaAddress;
1400
1340
  const signer = this._signer;
1401
1341
  if (signer.address && typeof signer.address === "string") {
1402
- const addr = signer.address;
1403
- this._eoaAddress = addr;
1404
- return addr;
1342
+ this._eoaAddress = signer.address;
1343
+ return signer.address;
1405
1344
  }
1406
1345
  throw new AgetherError(
1407
- "EOA address not yet resolved. Call getSignerAddress() (async) first, or use a signer that exposes .address synchronously.",
1408
- "ADDRESS_NOT_RESOLVED"
1346
+ "EOA address not available synchronously. Call getSignerAddress() first.",
1347
+ "NO_EOA_ADDRESS"
1409
1348
  );
1410
1349
  }
1350
+ /** Get EOA wallet address (async, works for all signer types). */
1351
+ async getSignerAddress() {
1352
+ if (this._eoaAddress) return this._eoaAddress;
1353
+ const addr = await this._signer.getAddress();
1354
+ this._eoaAddress = addr;
1355
+ return addr;
1356
+ }
1357
+ // ─── Safe7579 Execution ───────────────────────────────────────────────
1358
+ /** Pack two uint128 values into a single bytes32. */
1359
+ _packUint128(hi, lo) {
1360
+ return import_ethers2.ethers.zeroPadValue(import_ethers2.ethers.toBeHex(hi << 128n | lo), 32);
1361
+ }
1362
+ /**
1363
+ * Build, sign and submit a PackedUserOperation through EntryPoint.handleOps.
1364
+ */
1365
+ async _submitUserOp(callData) {
1366
+ const sender = await this.getAccountAddress();
1367
+ const validatorAddr = this.config.contracts.erc8004ValidationModule;
1368
+ const nonceKey = BigInt(validatorAddr) << 32n;
1369
+ const nonce = await this.entryPoint.getNonce(sender, nonceKey);
1370
+ const feeData = await this.provider.getFeeData();
1371
+ const maxFeePerGas = feeData.maxFeePerGas ?? import_ethers2.ethers.parseUnits("0.5", "gwei");
1372
+ const maxPriorityFeePerGas = feeData.maxPriorityFeePerGas ?? import_ethers2.ethers.parseUnits("0.1", "gwei");
1373
+ const verificationGasLimit = 500000n;
1374
+ const callGasLimit = 800000n;
1375
+ const preVerificationGas = 100000n;
1376
+ const accountGasLimits = this._packUint128(verificationGasLimit, callGasLimit);
1377
+ const gasFees = this._packUint128(maxPriorityFeePerGas, maxFeePerGas);
1378
+ const requiredPrefund = (verificationGasLimit + callGasLimit + preVerificationGas) * maxFeePerGas;
1379
+ const accountBalance = await this.provider.getBalance(sender);
1380
+ if (accountBalance < requiredPrefund) {
1381
+ const topUp = requiredPrefund - accountBalance;
1382
+ const topUpWithBuffer = topUp * 120n / 100n;
1383
+ const eoaBalance = await this.provider.getBalance(
1384
+ this._eoaAddress ?? await this._signer.getAddress()
1385
+ );
1386
+ if (eoaBalance < topUpWithBuffer) {
1387
+ const needed = import_ethers2.ethers.formatEther(topUpWithBuffer);
1388
+ throw new AgetherError(
1389
+ `Insufficient ETH for gas. Need ~${needed} ETH in EOA.`,
1390
+ "INSUFFICIENT_GAS"
1391
+ );
1392
+ }
1393
+ const tx = await this._signer.sendTransaction({ to: sender, value: topUpWithBuffer });
1394
+ await tx.wait();
1395
+ }
1396
+ const packedUserOp = {
1397
+ sender,
1398
+ nonce,
1399
+ initCode: "0x",
1400
+ callData,
1401
+ accountGasLimits,
1402
+ preVerificationGas,
1403
+ gasFees,
1404
+ paymasterAndData: "0x",
1405
+ signature: "0x"
1406
+ };
1407
+ const entryPointAddr = await this.entryPoint.getAddress();
1408
+ const chainId = (await this.provider.getNetwork()).chainId;
1409
+ const userOpHash = import_ethers2.ethers.keccak256(
1410
+ import_ethers2.ethers.AbiCoder.defaultAbiCoder().encode(
1411
+ ["bytes32", "address", "uint256"],
1412
+ [
1413
+ import_ethers2.ethers.keccak256(
1414
+ import_ethers2.ethers.AbiCoder.defaultAbiCoder().encode(
1415
+ [
1416
+ "address",
1417
+ "uint256",
1418
+ "bytes32",
1419
+ "bytes32",
1420
+ "bytes32",
1421
+ "uint256",
1422
+ "bytes32",
1423
+ "bytes32"
1424
+ ],
1425
+ [
1426
+ packedUserOp.sender,
1427
+ packedUserOp.nonce,
1428
+ import_ethers2.ethers.keccak256(packedUserOp.initCode),
1429
+ import_ethers2.ethers.keccak256(packedUserOp.callData),
1430
+ packedUserOp.accountGasLimits,
1431
+ packedUserOp.preVerificationGas,
1432
+ packedUserOp.gasFees,
1433
+ import_ethers2.ethers.keccak256(packedUserOp.paymasterAndData)
1434
+ ]
1435
+ )
1436
+ ),
1437
+ entryPointAddr,
1438
+ chainId
1439
+ ]
1440
+ )
1441
+ );
1442
+ const signature = await this._signer.signMessage(import_ethers2.ethers.getBytes(userOpHash));
1443
+ packedUserOp.signature = signature;
1444
+ const handleOpsTx = await this.entryPoint.handleOps(
1445
+ [
1446
+ [
1447
+ packedUserOp.sender,
1448
+ packedUserOp.nonce,
1449
+ packedUserOp.initCode,
1450
+ packedUserOp.callData,
1451
+ packedUserOp.accountGasLimits,
1452
+ packedUserOp.preVerificationGas,
1453
+ packedUserOp.gasFees,
1454
+ packedUserOp.paymasterAndData,
1455
+ packedUserOp.signature
1456
+ ]
1457
+ ],
1458
+ this._eoaAddress ?? await this._signer.getAddress()
1459
+ );
1460
+ const receipt = await handleOpsTx.wait();
1461
+ const epIface = new import_ethers2.ethers.Interface(ENTRYPOINT_V07_ABI);
1462
+ for (const log of receipt.logs) {
1463
+ try {
1464
+ const parsed = epIface.parseLog({ topics: log.topics, data: log.data });
1465
+ if (parsed?.name === "UserOperationEvent") {
1466
+ if (!parsed.args.success) {
1467
+ let revertMsg = "UserOp inner execution reverted";
1468
+ for (const rLog of receipt.logs) {
1469
+ try {
1470
+ const rParsed = epIface.parseLog({ topics: rLog.topics, data: rLog.data });
1471
+ if (rParsed?.name === "UserOperationRevertReason") {
1472
+ const reason = rParsed.args.revertReason;
1473
+ try {
1474
+ if (reason.length >= 10 && reason.slice(0, 10) === "0x08c379a0") {
1475
+ const decoded = import_ethers2.ethers.AbiCoder.defaultAbiCoder().decode(["string"], "0x" + reason.slice(10));
1476
+ revertMsg = `UserOp reverted: ${decoded[0]}`;
1477
+ } else {
1478
+ revertMsg = `UserOp reverted with data: ${reason}`;
1479
+ }
1480
+ } catch {
1481
+ revertMsg = `UserOp reverted with data: ${reason}`;
1482
+ }
1483
+ break;
1484
+ }
1485
+ } catch {
1486
+ continue;
1487
+ }
1488
+ }
1489
+ throw new AgetherError(revertMsg, "USEROP_EXECUTION_FAILED");
1490
+ }
1491
+ }
1492
+ } catch (e) {
1493
+ if (e instanceof AgetherError) throw e;
1494
+ continue;
1495
+ }
1496
+ }
1497
+ return receipt;
1498
+ }
1499
+ /**
1500
+ * Execute a single call via Safe7579 account through ERC-4337 UserOp.
1501
+ */
1502
+ async executeSingle(target, data, value = 0n) {
1503
+ const valueHex = import_ethers2.ethers.zeroPadValue(import_ethers2.ethers.toBeHex(value), 32);
1504
+ const executionCalldata = import_ethers2.ethers.concat([target, valueHex, data]);
1505
+ const safe7579Iface = new import_ethers2.ethers.Interface(SAFE7579_ACCOUNT_ABI);
1506
+ const callData = safe7579Iface.encodeFunctionData("execute", [MODE_SINGLE2, executionCalldata]);
1507
+ return this._submitUserOp(callData);
1508
+ }
1509
+ /**
1510
+ * Execute multiple calls via Safe7579 account in one atomic batch.
1511
+ */
1512
+ async executeBatch(targets, values, datas) {
1513
+ const executions = targets.map((t, i) => [t, values[i], datas[i]]);
1514
+ const executionCalldata = import_ethers2.ethers.AbiCoder.defaultAbiCoder().encode(
1515
+ ["(address,uint256,bytes)[]"],
1516
+ [executions]
1517
+ );
1518
+ const safe7579Iface = new import_ethers2.ethers.Interface(SAFE7579_ACCOUNT_ABI);
1519
+ const callData = safe7579Iface.encodeFunctionData("execute", [MODE_BATCH, executionCalldata]);
1520
+ return this._submitUserOp(callData);
1521
+ }
1522
+ };
1523
+
1524
+ // src/clients/MorphoClient.ts
1525
+ var import_axios2 = __toESM(require("axios"));
1526
+
1527
+ // src/utils/retry.ts
1528
+ var RETRIABLE_PATTERNS = [
1529
+ "ECONNRESET",
1530
+ "ECONNREFUSED",
1531
+ "ENOTFOUND",
1532
+ "ETIMEDOUT",
1533
+ "fetch failed",
1534
+ "network error",
1535
+ "socket hang up",
1536
+ "rate limit",
1537
+ "429",
1538
+ "502",
1539
+ "503",
1540
+ "504",
1541
+ "timeout"
1542
+ ];
1543
+ function isRetriable(error) {
1544
+ const msg = error instanceof Error ? error.message.toLowerCase() : String(error).toLowerCase();
1545
+ return RETRIABLE_PATTERNS.some((p) => msg.includes(p.toLowerCase()));
1546
+ }
1547
+ async function withRetry(fn, options = {}) {
1548
+ const {
1549
+ maxRetries = 3,
1550
+ baseDelay = 1e3,
1551
+ maxDelay = 15e3,
1552
+ onRetry
1553
+ } = options;
1554
+ let lastError;
1555
+ for (let attempt = 1; attempt <= maxRetries; attempt++) {
1556
+ try {
1557
+ return await fn();
1558
+ } catch (error) {
1559
+ lastError = error instanceof Error ? error : new Error(String(error));
1560
+ if (attempt >= maxRetries || !isRetriable(error)) {
1561
+ throw lastError;
1562
+ }
1563
+ const delay = Math.min(baseDelay * Math.pow(2, attempt - 1), maxDelay);
1564
+ const jitter = delay * (0.5 + Math.random() * 0.5);
1565
+ onRetry?.(attempt, lastError);
1566
+ await new Promise((resolve) => setTimeout(resolve, jitter));
1567
+ }
1568
+ }
1569
+ throw lastError;
1570
+ }
1571
+
1572
+ // src/clients/MorphoClient.ts
1573
+ var MORPHO_API_URL2 = "https://api.morpho.org/graphql";
1574
+ var morphoIface = new import_ethers3.ethers.Interface(MORPHO_BLUE_ABI);
1575
+ var erc20Iface2 = new import_ethers3.ethers.Interface(ERC20_ABI);
1576
+ var _MorphoClient = class _MorphoClient extends AgentAccountClient {
1577
+ constructor(config) {
1578
+ super(config);
1579
+ // Cached state
1580
+ /** Market params cache: keyed by market uniqueKey (bytes32 hash) */
1581
+ this._marketCache = /* @__PURE__ */ new Map();
1582
+ /** Dynamic token registry: symbol (uppercase) or address (lowercase) → { address, symbol, decimals } */
1583
+ this._tokenCache = /* @__PURE__ */ new Map();
1584
+ this._discoveredAt = 0;
1585
+ const addrs = { ...this.config.contracts, ...config.contracts };
1586
+ this.morphoBlue = new import_ethers3.Contract(addrs.morphoBlue, MORPHO_BLUE_ABI, this.provider);
1587
+ }
1588
+ // ════════════════════════════════════════════════════════
1589
+ // Account Management
1590
+ // ════════════════════════════════════════════════════════
1411
1591
  /**
1412
1592
  * Resolve the EOA signer address (async, works with all signer types).
1413
1593
  * Result is cached after the first call.
@@ -1464,7 +1644,7 @@ var _MorphoClient = class _MorphoClient {
1464
1644
  this._discoveredMarkets = items.map((m) => ({
1465
1645
  uniqueKey: m.uniqueKey,
1466
1646
  loanAsset: m.loanAsset,
1467
- collateralAsset: m.collateralAsset ?? { address: import_ethers2.ethers.ZeroAddress, symbol: "N/A", decimals: 0 },
1647
+ collateralAsset: m.collateralAsset ?? { address: import_ethers3.ethers.ZeroAddress, symbol: "N/A", decimals: 0 },
1468
1648
  oracle: m.oracleAddress,
1469
1649
  irm: m.irmAddress,
1470
1650
  lltv: BigInt(m.lltv),
@@ -1481,7 +1661,7 @@ var _MorphoClient = class _MorphoClient {
1481
1661
  irm: mi.irm,
1482
1662
  lltv: mi.lltv
1483
1663
  });
1484
- if (mi.collateralAsset.address !== import_ethers2.ethers.ZeroAddress) {
1664
+ if (mi.collateralAsset.address !== import_ethers3.ethers.ZeroAddress) {
1485
1665
  this._tokenCache.set(mi.collateralAsset.symbol.toUpperCase(), {
1486
1666
  address: mi.collateralAsset.address,
1487
1667
  symbol: mi.collateralAsset.symbol,
@@ -1493,7 +1673,7 @@ var _MorphoClient = class _MorphoClient {
1493
1673
  decimals: mi.collateralAsset.decimals
1494
1674
  });
1495
1675
  }
1496
- if (mi.loanAsset.address !== import_ethers2.ethers.ZeroAddress) {
1676
+ if (mi.loanAsset.address !== import_ethers3.ethers.ZeroAddress) {
1497
1677
  this._tokenCache.set(mi.loanAsset.symbol.toUpperCase(), {
1498
1678
  address: mi.loanAsset.address,
1499
1679
  symbol: mi.loanAsset.symbol,
@@ -1663,7 +1843,7 @@ var _MorphoClient = class _MorphoClient {
1663
1843
  const totalBorrowShares = BigInt(mkt.totalBorrowShares);
1664
1844
  const totalBorrowAssets = BigInt(mkt.totalBorrowAssets);
1665
1845
  debt = totalBorrowShares > 0n ? (borrowShares * totalBorrowAssets + totalBorrowShares - 1n) / totalBorrowShares : 0n;
1666
- totalDebtFloat += parseFloat(import_ethers2.ethers.formatUnits(debt, loanDecimals));
1846
+ totalDebtFloat += parseFloat(import_ethers3.ethers.formatUnits(debt, loanDecimals));
1667
1847
  } catch (e) {
1668
1848
  console.warn(`[agether] debt calc failed for market ${m.uniqueKey}:`, e instanceof Error ? e.message : e);
1669
1849
  }
@@ -1672,17 +1852,17 @@ var _MorphoClient = class _MorphoClient {
1672
1852
  marketId: m.uniqueKey,
1673
1853
  collateralToken: m.collateralAsset.symbol,
1674
1854
  loanToken: m.loanAsset.symbol,
1675
- collateral: import_ethers2.ethers.formatUnits(collateral, m.collateralAsset.decimals),
1855
+ collateral: import_ethers3.ethers.formatUnits(collateral, m.collateralAsset.decimals),
1676
1856
  borrowShares: borrowShares.toString(),
1677
1857
  supplyShares: supplyShares.toString(),
1678
- debt: import_ethers2.ethers.formatUnits(debt, loanDecimals)
1858
+ debt: import_ethers3.ethers.formatUnits(debt, loanDecimals)
1679
1859
  });
1680
1860
  }
1681
1861
  } catch (e) {
1682
1862
  console.warn("[agether] marketPositions API failed, falling back to market scan:", e instanceof Error ? e.message : e);
1683
1863
  const markets = await this.getMarkets();
1684
1864
  for (const m of markets) {
1685
- if (!m.collateralAsset || m.collateralAsset.address === import_ethers2.ethers.ZeroAddress) continue;
1865
+ if (!m.collateralAsset || m.collateralAsset.address === import_ethers3.ethers.ZeroAddress) continue;
1686
1866
  try {
1687
1867
  const pos = await this.morphoBlue.position(m.uniqueKey, acctAddr);
1688
1868
  if (pos.collateral === 0n && pos.borrowShares === 0n && pos.supplyShares === 0n) continue;
@@ -1694,7 +1874,7 @@ var _MorphoClient = class _MorphoClient {
1694
1874
  const totalBorrowShares = BigInt(mkt.totalBorrowShares);
1695
1875
  const totalBorrowAssets = BigInt(mkt.totalBorrowAssets);
1696
1876
  debt = totalBorrowShares > 0n ? (BigInt(pos.borrowShares) * totalBorrowAssets + totalBorrowShares - 1n) / totalBorrowShares : 0n;
1697
- totalDebtFloat += parseFloat(import_ethers2.ethers.formatUnits(debt, loanDecimals));
1877
+ totalDebtFloat += parseFloat(import_ethers3.ethers.formatUnits(debt, loanDecimals));
1698
1878
  } catch (e2) {
1699
1879
  console.warn(`[agether] debt calc failed:`, e2 instanceof Error ? e2.message : e2);
1700
1880
  }
@@ -1703,10 +1883,10 @@ var _MorphoClient = class _MorphoClient {
1703
1883
  marketId: m.uniqueKey,
1704
1884
  collateralToken: m.collateralAsset.symbol,
1705
1885
  loanToken: m.loanAsset.symbol,
1706
- collateral: import_ethers2.ethers.formatUnits(pos.collateral, m.collateralAsset.decimals),
1886
+ collateral: import_ethers3.ethers.formatUnits(pos.collateral, m.collateralAsset.decimals),
1707
1887
  borrowShares: pos.borrowShares.toString(),
1708
1888
  supplyShares: pos.supplyShares.toString(),
1709
- debt: import_ethers2.ethers.formatUnits(debt, loanDecimals)
1889
+ debt: import_ethers3.ethers.formatUnits(debt, loanDecimals)
1710
1890
  });
1711
1891
  } catch (e2) {
1712
1892
  console.warn(`[agether] position read failed:`, e2 instanceof Error ? e2.message : e2);
@@ -1732,7 +1912,7 @@ var _MorphoClient = class _MorphoClient {
1732
1912
  async getTokenBalance(symbolOrAddress) {
1733
1913
  const acctAddr = await this.getAccountAddress();
1734
1914
  const tokenInfo = await this._resolveToken(symbolOrAddress);
1735
- const token = new import_ethers2.Contract(tokenInfo.address, ERC20_ABI, this.provider);
1915
+ const token = new import_ethers3.Contract(tokenInfo.address, ERC20_ABI, this.provider);
1736
1916
  return token.balanceOf(acctAddr);
1737
1917
  }
1738
1918
  /**
@@ -1742,7 +1922,7 @@ var _MorphoClient = class _MorphoClient {
1742
1922
  */
1743
1923
  async getUsdcBalance() {
1744
1924
  const acctAddr = await this.getAccountAddress();
1745
- const usdc = new import_ethers2.Contract(this.config.contracts.usdc, ERC20_ABI, this.provider);
1925
+ const usdc = new import_ethers3.Contract(this.config.contracts.usdc, ERC20_ABI, this.provider);
1746
1926
  return usdc.balanceOf(acctAddr);
1747
1927
  }
1748
1928
  /**
@@ -1762,7 +1942,7 @@ var _MorphoClient = class _MorphoClient {
1762
1942
  let totalAdditional = 0n;
1763
1943
  const byMarket = [];
1764
1944
  for (const m of markets) {
1765
- if (!m.collateralAsset || m.collateralAsset.address === import_ethers2.ethers.ZeroAddress) continue;
1945
+ if (!m.collateralAsset || m.collateralAsset.address === import_ethers3.ethers.ZeroAddress) continue;
1766
1946
  try {
1767
1947
  const pos = await this.morphoBlue.position(m.uniqueKey, acctAddr);
1768
1948
  if (pos.collateral === 0n) continue;
@@ -1772,7 +1952,7 @@ var _MorphoClient = class _MorphoClient {
1772
1952
  const currentDebt = totalBorrowShares > 0n ? (BigInt(pos.borrowShares) * totalBorrowAssets + totalBorrowShares - 1n) / totalBorrowShares : 0n;
1773
1953
  let collateralValueInLoan;
1774
1954
  try {
1775
- const oracleContract = new import_ethers2.Contract(m.oracle, [
1955
+ const oracleContract = new import_ethers3.Contract(m.oracle, [
1776
1956
  "function price() view returns (uint256)"
1777
1957
  ], this.provider);
1778
1958
  const oraclePrice = await oracleContract.price();
@@ -1878,7 +2058,7 @@ var _MorphoClient = class _MorphoClient {
1878
2058
  const sym = loanTokenSymbolOrAddress.toUpperCase();
1879
2059
  items = items.filter((m) => m.loanAsset?.symbol?.toUpperCase() === sym);
1880
2060
  }
1881
- return items.filter((m) => m.collateralAsset?.address && m.collateralAsset.address !== import_ethers2.ethers.ZeroAddress).map((m) => {
2061
+ return items.filter((m) => m.collateralAsset?.address && m.collateralAsset.address !== import_ethers3.ethers.ZeroAddress).map((m) => {
1882
2062
  const loanDecimals = m.loanAsset?.decimals ?? 18;
1883
2063
  return {
1884
2064
  collateralToken: m.collateralAsset.symbol,
@@ -1939,7 +2119,7 @@ var _MorphoClient = class _MorphoClient {
1939
2119
  { maxRetries: 3, onRetry: (n, e) => console.warn(`[agether] Morpho API retry ${n}:`, e.message) }
1940
2120
  );
1941
2121
  let items = resp.data?.data?.markets?.items ?? [];
1942
- items = items.filter((m) => m.collateralAsset?.address && m.collateralAsset.address !== import_ethers2.ethers.ZeroAddress);
2122
+ items = items.filter((m) => m.collateralAsset?.address && m.collateralAsset.address !== import_ethers3.ethers.ZeroAddress);
1943
2123
  const searchUpper = search.toUpperCase();
1944
2124
  if (options?.asCollateral) {
1945
2125
  items = items.filter((m) => m.collateralAsset?.symbol?.toUpperCase() === searchUpper);
@@ -1995,10 +2175,10 @@ var _MorphoClient = class _MorphoClient {
1995
2175
  if (ethBalance > 0n) {
1996
2176
  results.push({
1997
2177
  symbol: "ETH",
1998
- address: import_ethers2.ethers.ZeroAddress,
2178
+ address: import_ethers3.ethers.ZeroAddress,
1999
2179
  decimals: 18,
2000
2180
  balance: ethBalance,
2001
- balanceFormatted: import_ethers2.ethers.formatEther(ethBalance)
2181
+ balanceFormatted: import_ethers3.ethers.formatEther(ethBalance)
2002
2182
  });
2003
2183
  }
2004
2184
  } catch {
@@ -2009,7 +2189,7 @@ var _MorphoClient = class _MorphoClient {
2009
2189
  const batch = tokenEntries.slice(i, i + batchSize);
2010
2190
  const checks = batch.map(async (info) => {
2011
2191
  try {
2012
- const token = new import_ethers2.Contract(info.address, ERC20_ABI, this.provider);
2192
+ const token = new import_ethers3.Contract(info.address, ERC20_ABI, this.provider);
2013
2193
  const balance = await token.balanceOf(acctAddr);
2014
2194
  if (balance > 0n) {
2015
2195
  return {
@@ -2017,7 +2197,7 @@ var _MorphoClient = class _MorphoClient {
2017
2197
  address: info.address,
2018
2198
  decimals: info.decimals,
2019
2199
  balance,
2020
- balanceFormatted: import_ethers2.ethers.formatUnits(balance, info.decimals)
2200
+ balanceFormatted: import_ethers3.ethers.formatUnits(balance, info.decimals)
2021
2201
  };
2022
2202
  }
2023
2203
  } catch {
@@ -2049,7 +2229,7 @@ var _MorphoClient = class _MorphoClient {
2049
2229
  try {
2050
2230
  const balance = await this.getTokenBalance(collateralSymbol);
2051
2231
  const info = await this._resolveToken(collateralSymbol);
2052
- tokensToCheck = [{ symbol: collateralSymbol, balanceFormatted: import_ethers2.ethers.formatUnits(balance, info.decimals) }];
2232
+ tokensToCheck = [{ symbol: collateralSymbol, balanceFormatted: import_ethers3.ethers.formatUnits(balance, info.decimals) }];
2053
2233
  } catch {
2054
2234
  }
2055
2235
  } else {
@@ -2129,12 +2309,12 @@ var _MorphoClient = class _MorphoClient {
2129
2309
  try {
2130
2310
  const params = await this.findMarketForCollateral(collateralSymbol);
2131
2311
  const loanDecimals = await this._getLoanTokenDecimals(params);
2132
- const oracleContract = new import_ethers2.Contract(params.oracle, [
2312
+ const oracleContract = new import_ethers3.Contract(params.oracle, [
2133
2313
  "function price() view returns (uint256)"
2134
2314
  ], this.provider);
2135
2315
  const oraclePrice = await oracleContract.price();
2136
2316
  const ORACLE_PRICE_SCALE = 10n ** 36n;
2137
- const amountWei = import_ethers2.ethers.parseUnits(amount, colInfo.decimals);
2317
+ const amountWei = import_ethers3.ethers.parseUnits(amount, colInfo.decimals);
2138
2318
  const valueInLoan = amountWei * oraclePrice / ORACLE_PRICE_SCALE;
2139
2319
  collateralValueUsd = Number(valueInLoan) / 10 ** loanDecimals;
2140
2320
  } catch (e) {
@@ -2185,14 +2365,14 @@ var _MorphoClient = class _MorphoClient {
2185
2365
  }
2186
2366
  const loanDecimals = await this._getLoanTokenDecimals(params);
2187
2367
  const loanTokenAddr = params.loanToken;
2188
- const parsedAmount = import_ethers2.ethers.parseUnits(amount, loanDecimals);
2189
- const marketId = import_ethers2.ethers.keccak256(
2190
- import_ethers2.ethers.AbiCoder.defaultAbiCoder().encode(
2368
+ const parsedAmount = import_ethers3.ethers.parseUnits(amount, loanDecimals);
2369
+ const marketId = import_ethers3.ethers.keccak256(
2370
+ import_ethers3.ethers.AbiCoder.defaultAbiCoder().encode(
2191
2371
  ["address", "address", "address", "address", "uint256"],
2192
2372
  [params.loanToken, params.collateralToken, params.oracle, params.irm, params.lltv]
2193
2373
  )
2194
2374
  );
2195
- const loanContract = new import_ethers2.Contract(loanTokenAddr, ERC20_ABI, this._signer);
2375
+ const loanContract = new import_ethers3.Contract(loanTokenAddr, ERC20_ABI, this._signer);
2196
2376
  const acctBalance = await loanContract.balanceOf(acctAddr);
2197
2377
  if (acctBalance < parsedAmount) {
2198
2378
  const shortfall = parsedAmount - acctBalance;
@@ -2201,7 +2381,7 @@ var _MorphoClient = class _MorphoClient {
2201
2381
  const loanInfo = this._tokenCache.get(loanTokenAddr.toLowerCase());
2202
2382
  const loanSymbol = loanInfo?.symbol ?? "loan token";
2203
2383
  throw new AgetherError(
2204
- `Insufficient ${loanSymbol}. Need ${amount}, AgentAccount has ${import_ethers2.ethers.formatUnits(acctBalance, loanDecimals)}, EOA has ${import_ethers2.ethers.formatUnits(eoaBalance, loanDecimals)}.`,
2384
+ `Insufficient ${loanSymbol}. Need ${amount}, AgentAccount has ${import_ethers3.ethers.formatUnits(acctBalance, loanDecimals)}, EOA has ${import_ethers3.ethers.formatUnits(eoaBalance, loanDecimals)}.`,
2205
2385
  "INSUFFICIENT_BALANCE"
2206
2386
  );
2207
2387
  }
@@ -2221,7 +2401,7 @@ var _MorphoClient = class _MorphoClient {
2221
2401
  "0x"
2222
2402
  ])
2223
2403
  ];
2224
- const receipt = await this.batch(targets, values, datas);
2404
+ const receipt = await this.executeBatch(targets, values, datas);
2225
2405
  return {
2226
2406
  tx: receipt.hash,
2227
2407
  amount,
@@ -2257,8 +2437,8 @@ var _MorphoClient = class _MorphoClient {
2257
2437
  params = p;
2258
2438
  }
2259
2439
  const loanDecimals = await this._getLoanTokenDecimals(params);
2260
- const marketId = import_ethers2.ethers.keccak256(
2261
- import_ethers2.ethers.AbiCoder.defaultAbiCoder().encode(
2440
+ const marketId = import_ethers3.ethers.keccak256(
2441
+ import_ethers3.ethers.AbiCoder.defaultAbiCoder().encode(
2262
2442
  ["address", "address", "address", "address", "uint256"],
2263
2443
  [params.loanToken, params.collateralToken, params.oracle, params.irm, params.lltv]
2264
2444
  )
@@ -2271,7 +2451,7 @@ var _MorphoClient = class _MorphoClient {
2271
2451
  withdrawAssets = 0n;
2272
2452
  if (withdrawShares === 0n) throw new AgetherError("No supply position to withdraw", "NO_SUPPLY");
2273
2453
  } else {
2274
- withdrawAssets = import_ethers2.ethers.parseUnits(amount, loanDecimals);
2454
+ withdrawAssets = import_ethers3.ethers.parseUnits(amount, loanDecimals);
2275
2455
  withdrawShares = 0n;
2276
2456
  }
2277
2457
  const data = morphoIface.encodeFunctionData("withdraw", [
@@ -2281,7 +2461,7 @@ var _MorphoClient = class _MorphoClient {
2281
2461
  acctAddr,
2282
2462
  dest
2283
2463
  ]);
2284
- const receipt = await this.exec(morphoAddr, data);
2464
+ const receipt = await this.executeSingle(morphoAddr, data);
2285
2465
  let remainingSupply = "0";
2286
2466
  try {
2287
2467
  const pos = await this.morphoBlue.position(marketId, acctAddr);
@@ -2289,7 +2469,7 @@ var _MorphoClient = class _MorphoClient {
2289
2469
  const totalSupplyAssets = BigInt(mkt.totalSupplyAssets);
2290
2470
  const totalSupplyShares = BigInt(mkt.totalSupplyShares);
2291
2471
  const currentAssets = totalSupplyShares > 0n ? BigInt(pos.supplyShares) * totalSupplyAssets / totalSupplyShares : 0n;
2292
- remainingSupply = import_ethers2.ethers.formatUnits(currentAssets, loanDecimals);
2472
+ remainingSupply = import_ethers3.ethers.formatUnits(currentAssets, loanDecimals);
2293
2473
  } catch (e) {
2294
2474
  console.warn("[agether] failed to read remaining supply:", e instanceof Error ? e.message : e);
2295
2475
  }
@@ -2354,9 +2534,9 @@ var _MorphoClient = class _MorphoClient {
2354
2534
  loanToken: p.market.loanAsset.symbol,
2355
2535
  collateralToken: p.market.collateralAsset?.symbol ?? "none",
2356
2536
  supplyShares: p.state.supplyShares,
2357
- suppliedAssets: import_ethers2.ethers.formatUnits(currentAssets, p.market.loanAsset.decimals),
2358
- netDeposited: import_ethers2.ethers.formatUnits(netDeposited, p.market.loanAsset.decimals),
2359
- earnedYield: import_ethers2.ethers.formatUnits(earnedYield, p.market.loanAsset.decimals),
2537
+ suppliedAssets: import_ethers3.ethers.formatUnits(currentAssets, p.market.loanAsset.decimals),
2538
+ netDeposited: import_ethers3.ethers.formatUnits(netDeposited, p.market.loanAsset.decimals),
2539
+ earnedYield: import_ethers3.ethers.formatUnits(earnedYield, p.market.loanAsset.decimals),
2360
2540
  supplyApy: p.market.state?.supplyApy ?? 0
2361
2541
  });
2362
2542
  }
@@ -2384,8 +2564,8 @@ var _MorphoClient = class _MorphoClient {
2384
2564
  );
2385
2565
  const params = await this.findMarketForCollateral(pos.collateralToken, pos.loanToken);
2386
2566
  const loanDecimals = await this._getLoanTokenDecimals(params);
2387
- const parsedAmount = import_ethers2.ethers.parseUnits(amount, loanDecimals);
2388
- const availableYield = import_ethers2.ethers.parseUnits(pos.earnedYield, loanDecimals);
2567
+ const parsedAmount = import_ethers3.ethers.parseUnits(amount, loanDecimals);
2568
+ const availableYield = import_ethers3.ethers.parseUnits(pos.earnedYield, loanDecimals);
2389
2569
  if (parsedAmount > availableYield) {
2390
2570
  const loanSymbol = pos.loanToken;
2391
2571
  throw new AgetherError(
@@ -2400,7 +2580,7 @@ var _MorphoClient = class _MorphoClient {
2400
2580
  acctAddr,
2401
2581
  recipient
2402
2582
  ]);
2403
- const receipt = await this.exec(morphoAddr, data);
2583
+ const receipt = await this.executeSingle(morphoAddr, data);
2404
2584
  let remainingYield = "0";
2405
2585
  let remainingSupply = "0";
2406
2586
  try {
@@ -2435,16 +2615,16 @@ var _MorphoClient = class _MorphoClient {
2435
2615
  const acctAddr = await this.getAccountAddress();
2436
2616
  const colInfo = await this._resolveToken(tokenSymbol);
2437
2617
  const params = marketParams ?? await this.findMarketForCollateral(tokenSymbol);
2438
- const weiAmount = import_ethers2.ethers.parseUnits(amount, colInfo.decimals);
2618
+ const weiAmount = import_ethers3.ethers.parseUnits(amount, colInfo.decimals);
2439
2619
  const morphoAddr = this.config.contracts.morphoBlue;
2440
- const colToken = new import_ethers2.Contract(colInfo.address, ERC20_ABI, this._signer);
2620
+ const colToken = new import_ethers3.Contract(colInfo.address, ERC20_ABI, this._signer);
2441
2621
  const acctBalance = await colToken.balanceOf(acctAddr);
2442
2622
  if (acctBalance < weiAmount) {
2443
2623
  const shortfall = weiAmount - acctBalance;
2444
2624
  const eoaBalance = await colToken.balanceOf(await this.getSignerAddress());
2445
2625
  if (eoaBalance < shortfall) {
2446
2626
  throw new AgetherError(
2447
- `Insufficient ${tokenSymbol}. Need ${amount}, AgentAccount has ${import_ethers2.ethers.formatUnits(acctBalance, colInfo.decimals)}, EOA has ${import_ethers2.ethers.formatUnits(eoaBalance, colInfo.decimals)}.`,
2627
+ `Insufficient ${tokenSymbol}. Need ${amount}, AgentAccount has ${import_ethers3.ethers.formatUnits(acctBalance, colInfo.decimals)}, EOA has ${import_ethers3.ethers.formatUnits(eoaBalance, colInfo.decimals)}.`,
2448
2628
  "INSUFFICIENT_BALANCE"
2449
2629
  );
2450
2630
  }
@@ -2463,7 +2643,7 @@ var _MorphoClient = class _MorphoClient {
2463
2643
  "0x"
2464
2644
  ])
2465
2645
  ];
2466
- const receipt = await this.batch(targets, values, datas);
2646
+ const receipt = await this.executeBatch(targets, values, datas);
2467
2647
  return {
2468
2648
  tx: receipt.hash,
2469
2649
  collateralToken: tokenSymbol,
@@ -2496,10 +2676,10 @@ var _MorphoClient = class _MorphoClient {
2496
2676
  usedToken = symbol;
2497
2677
  }
2498
2678
  const loanDecimals = await this._getLoanTokenDecimals(params);
2499
- const parsedAmount = import_ethers2.ethers.parseUnits(amount, loanDecimals);
2679
+ const parsedAmount = import_ethers3.ethers.parseUnits(amount, loanDecimals);
2500
2680
  try {
2501
- const marketId = import_ethers2.ethers.keccak256(
2502
- import_ethers2.ethers.AbiCoder.defaultAbiCoder().encode(
2681
+ const marketId = import_ethers3.ethers.keccak256(
2682
+ import_ethers3.ethers.AbiCoder.defaultAbiCoder().encode(
2503
2683
  ["address", "address", "address", "address", "uint256"],
2504
2684
  [params.loanToken, params.collateralToken, params.oracle, params.irm, params.lltv]
2505
2685
  )
@@ -2511,7 +2691,7 @@ var _MorphoClient = class _MorphoClient {
2511
2691
  "NO_COLLATERAL"
2512
2692
  );
2513
2693
  }
2514
- const oracleContract = new import_ethers2.Contract(params.oracle, ["function price() view returns (uint256)"], this.provider);
2694
+ const oracleContract = new import_ethers3.Contract(params.oracle, ["function price() view returns (uint256)"], this.provider);
2515
2695
  const oraclePrice = await oracleContract.price();
2516
2696
  const collateralValueInLoan = BigInt(pos.collateral) * oraclePrice / 10n ** 36n;
2517
2697
  const maxBorrowTotal = collateralValueInLoan * params.lltv / 10n ** 18n;
@@ -2524,8 +2704,8 @@ var _MorphoClient = class _MorphoClient {
2524
2704
  const loanInfo = this._tokenCache.get(params.loanToken.toLowerCase());
2525
2705
  const loanSymbol = loanInfo?.symbol ?? "loan token";
2526
2706
  const colInfo = await this._resolveToken(usedToken);
2527
- const maxFormatted = import_ethers2.ethers.formatUnits(maxAdditional, loanDecimals);
2528
- const colFormatted = import_ethers2.ethers.formatUnits(pos.collateral, colInfo.decimals);
2707
+ const maxFormatted = import_ethers3.ethers.formatUnits(maxAdditional, loanDecimals);
2708
+ const colFormatted = import_ethers3.ethers.formatUnits(pos.collateral, colInfo.decimals);
2529
2709
  throw new AgetherError(
2530
2710
  `Borrow of ${amount} ${loanSymbol} exceeds max borrowable ${maxFormatted} ${loanSymbol} (collateral: ${colFormatted} ${usedToken}, LLTV: ${Number(params.lltv) / 1e18 * 100}%). Deposit more collateral or reduce borrow amount.`,
2531
2711
  "EXCEEDS_MAX_LTV"
@@ -2542,7 +2722,7 @@ var _MorphoClient = class _MorphoClient {
2542
2722
  acctAddr,
2543
2723
  acctAddr
2544
2724
  ]);
2545
- const receipt = await this.exec(morphoAddr, data);
2725
+ const receipt = await this.executeSingle(morphoAddr, data);
2546
2726
  return {
2547
2727
  tx: receipt.hash,
2548
2728
  amount,
@@ -2572,19 +2752,19 @@ var _MorphoClient = class _MorphoClient {
2572
2752
  const colInfo = await this._resolveToken(tokenSymbol);
2573
2753
  const params = marketParams ?? await this.findMarketForCollateral(tokenSymbol, loanTokenSymbol);
2574
2754
  const loanDecimals = await this._getLoanTokenDecimals(params);
2575
- const colWei = import_ethers2.ethers.parseUnits(collateralAmount, colInfo.decimals);
2576
- const borrowWei = import_ethers2.ethers.parseUnits(borrowAmount, loanDecimals);
2755
+ const colWei = import_ethers3.ethers.parseUnits(collateralAmount, colInfo.decimals);
2756
+ const borrowWei = import_ethers3.ethers.parseUnits(borrowAmount, loanDecimals);
2577
2757
  const morphoAddr = this.config.contracts.morphoBlue;
2578
2758
  try {
2579
- const marketId = import_ethers2.ethers.keccak256(
2580
- import_ethers2.ethers.AbiCoder.defaultAbiCoder().encode(
2759
+ const marketId = import_ethers3.ethers.keccak256(
2760
+ import_ethers3.ethers.AbiCoder.defaultAbiCoder().encode(
2581
2761
  ["address", "address", "address", "address", "uint256"],
2582
2762
  [params.loanToken, params.collateralToken, params.oracle, params.irm, params.lltv]
2583
2763
  )
2584
2764
  );
2585
2765
  const pos = await this.morphoBlue.position(marketId, acctAddr);
2586
2766
  const totalCollateral = BigInt(pos.collateral) + colWei;
2587
- const oracleContract = new import_ethers2.Contract(params.oracle, ["function price() view returns (uint256)"], this.provider);
2767
+ const oracleContract = new import_ethers3.Contract(params.oracle, ["function price() view returns (uint256)"], this.provider);
2588
2768
  const oraclePrice = await oracleContract.price();
2589
2769
  const collateralValueInLoan = totalCollateral * oraclePrice / 10n ** 36n;
2590
2770
  const maxBorrowTotal = collateralValueInLoan * params.lltv / 10n ** 18n;
@@ -2596,9 +2776,9 @@ var _MorphoClient = class _MorphoClient {
2596
2776
  if (borrowWei > maxAdditional) {
2597
2777
  const loanInfo = this._tokenCache.get(params.loanToken.toLowerCase());
2598
2778
  const loanSymbol = loanInfo?.symbol ?? "loan token";
2599
- const maxFormatted = import_ethers2.ethers.formatUnits(maxAdditional, loanDecimals);
2779
+ const maxFormatted = import_ethers3.ethers.formatUnits(maxAdditional, loanDecimals);
2600
2780
  throw new AgetherError(
2601
- `Borrow of ${borrowAmount} ${loanSymbol} exceeds max borrowable ${maxFormatted} ${loanSymbol} (total collateral: ${import_ethers2.ethers.formatUnits(totalCollateral, colInfo.decimals)} ${tokenSymbol}, LLTV: ${Number(params.lltv) / 1e18 * 100}%). Reduce borrow or increase collateral.`,
2781
+ `Borrow of ${borrowAmount} ${loanSymbol} exceeds max borrowable ${maxFormatted} ${loanSymbol} (total collateral: ${import_ethers3.ethers.formatUnits(totalCollateral, colInfo.decimals)} ${tokenSymbol}, LLTV: ${Number(params.lltv) / 1e18 * 100}%). Reduce borrow or increase collateral.`,
2602
2782
  "EXCEEDS_MAX_LTV"
2603
2783
  );
2604
2784
  }
@@ -2606,14 +2786,14 @@ var _MorphoClient = class _MorphoClient {
2606
2786
  if (e instanceof AgetherError) throw e;
2607
2787
  console.warn("[agether] depositAndBorrow pre-check failed (proceeding anyway):", e instanceof Error ? e.message : e);
2608
2788
  }
2609
- const colToken = new import_ethers2.Contract(colInfo.address, ERC20_ABI, this._signer);
2789
+ const colToken = new import_ethers3.Contract(colInfo.address, ERC20_ABI, this._signer);
2610
2790
  const acctBalance = await colToken.balanceOf(acctAddr);
2611
2791
  if (acctBalance < colWei) {
2612
2792
  const shortfall = colWei - acctBalance;
2613
2793
  const eoaBalance = await colToken.balanceOf(await this.getSignerAddress());
2614
2794
  if (eoaBalance < shortfall) {
2615
2795
  throw new AgetherError(
2616
- `Insufficient ${tokenSymbol}. Need ${collateralAmount}, AgentAccount has ${import_ethers2.ethers.formatUnits(acctBalance, colInfo.decimals)}, EOA has ${import_ethers2.ethers.formatUnits(eoaBalance, colInfo.decimals)}.`,
2796
+ `Insufficient ${tokenSymbol}. Need ${collateralAmount}, AgentAccount has ${import_ethers3.ethers.formatUnits(acctBalance, colInfo.decimals)}, EOA has ${import_ethers3.ethers.formatUnits(eoaBalance, colInfo.decimals)}.`,
2617
2797
  "INSUFFICIENT_BALANCE"
2618
2798
  );
2619
2799
  }
@@ -2639,7 +2819,7 @@ var _MorphoClient = class _MorphoClient {
2639
2819
  acctAddr
2640
2820
  ])
2641
2821
  ];
2642
- const receipt = await this.batch(targets, values, datas);
2822
+ const receipt = await this.executeBatch(targets, values, datas);
2643
2823
  return {
2644
2824
  tx: receipt.hash,
2645
2825
  collateralToken: tokenSymbol,
@@ -2689,9 +2869,9 @@ var _MorphoClient = class _MorphoClient {
2689
2869
  const totalBorrowAssets = BigInt(onChainMkt.totalBorrowAssets);
2690
2870
  const totalBorrowShares = BigInt(onChainMkt.totalBorrowShares);
2691
2871
  const estimated = totalBorrowShares > 0n ? repayShares * totalBorrowAssets / totalBorrowShares + 10n : 0n;
2692
- approveAmount = estimated > 0n ? estimated : import_ethers2.ethers.parseUnits("1", loanDecimals);
2872
+ approveAmount = estimated > 0n ? estimated : import_ethers3.ethers.parseUnits("1", loanDecimals);
2693
2873
  } else {
2694
- const marketId = import_ethers2.ethers.keccak256(import_ethers2.ethers.AbiCoder.defaultAbiCoder().encode(
2874
+ const marketId = import_ethers3.ethers.keccak256(import_ethers3.ethers.AbiCoder.defaultAbiCoder().encode(
2695
2875
  ["address", "address", "address", "address", "uint256"],
2696
2876
  [params.loanToken, params.collateralToken, params.oracle, params.irm, params.lltv]
2697
2877
  ));
@@ -2701,14 +2881,14 @@ var _MorphoClient = class _MorphoClient {
2701
2881
  const onChainMkt = await this.morphoBlue.market(marketId);
2702
2882
  const totalBorrowAssets = BigInt(onChainMkt.totalBorrowAssets);
2703
2883
  const totalBorrowShares = BigInt(onChainMkt.totalBorrowShares);
2704
- approveAmount = totalBorrowShares > 0n ? repayShares * totalBorrowAssets / totalBorrowShares + 10n : import_ethers2.ethers.parseUnits("1", loanDecimals);
2884
+ approveAmount = totalBorrowShares > 0n ? repayShares * totalBorrowAssets / totalBorrowShares + 10n : import_ethers3.ethers.parseUnits("1", loanDecimals);
2705
2885
  }
2706
2886
  } else {
2707
- repayAssets = import_ethers2.ethers.parseUnits(amount, loanDecimals);
2887
+ repayAssets = import_ethers3.ethers.parseUnits(amount, loanDecimals);
2708
2888
  repayShares = 0n;
2709
2889
  approveAmount = repayAssets;
2710
2890
  }
2711
- const loanContract = new import_ethers2.Contract(loanTokenAddr, ERC20_ABI, this._signer);
2891
+ const loanContract = new import_ethers3.Contract(loanTokenAddr, ERC20_ABI, this._signer);
2712
2892
  const acctBalance = await loanContract.balanceOf(acctAddr);
2713
2893
  const checkAmount = repayShares > 0n && repayAssets === 0n ? approveAmount * 1005n / 1000n : approveAmount;
2714
2894
  if (acctBalance < checkAmount) {
@@ -2727,7 +2907,7 @@ var _MorphoClient = class _MorphoClient {
2727
2907
  const loanInfo = this._tokenCache.get(loanTokenAddr.toLowerCase());
2728
2908
  const loanSymbol = loanInfo?.symbol ?? "loan token";
2729
2909
  throw new AgetherError(
2730
- `Insufficient ${loanSymbol} for repay. Need ~${import_ethers2.ethers.formatUnits(checkAmount, loanDecimals)}, AgentAccount has ${import_ethers2.ethers.formatUnits(acctBalance, loanDecimals)}, EOA has ${import_ethers2.ethers.formatUnits(eoaBalance, loanDecimals)}.`,
2910
+ `Insufficient ${loanSymbol} for repay. Need ~${import_ethers3.ethers.formatUnits(checkAmount, loanDecimals)}, AgentAccount has ${import_ethers3.ethers.formatUnits(acctBalance, loanDecimals)}, EOA has ${import_ethers3.ethers.formatUnits(eoaBalance, loanDecimals)}.`,
2731
2911
  "INSUFFICIENT_BALANCE"
2732
2912
  );
2733
2913
  }
@@ -2749,7 +2929,7 @@ var _MorphoClient = class _MorphoClient {
2749
2929
  "0x"
2750
2930
  ])
2751
2931
  ];
2752
- const receipt = await this.batch(targets, values, datas);
2932
+ const receipt = await this.executeBatch(targets, values, datas);
2753
2933
  let remainingDebt = "0";
2754
2934
  try {
2755
2935
  const markets = await this.getMarkets(true);
@@ -2764,7 +2944,7 @@ var _MorphoClient = class _MorphoClient {
2764
2944
  const totalAssets = BigInt(onChainMkt.totalBorrowAssets);
2765
2945
  const totalShares = BigInt(onChainMkt.totalBorrowShares);
2766
2946
  const debtWei = totalShares > 0n ? shares * totalAssets / totalShares : 0n;
2767
- remainingDebt = import_ethers2.ethers.formatUnits(debtWei, loanDecimals);
2947
+ remainingDebt = import_ethers3.ethers.formatUnits(debtWei, loanDecimals);
2768
2948
  }
2769
2949
  }
2770
2950
  } catch (e) {
@@ -2906,7 +3086,7 @@ var _MorphoClient = class _MorphoClient {
2906
3086
  weiAmount = pos.collateral;
2907
3087
  if (weiAmount === 0n) throw new AgetherError("No collateral to withdraw", "NO_COLLATERAL");
2908
3088
  } else {
2909
- weiAmount = import_ethers2.ethers.parseUnits(amount, colInfo.decimals);
3089
+ weiAmount = import_ethers3.ethers.parseUnits(amount, colInfo.decimals);
2910
3090
  }
2911
3091
  let hasDustDebt = false;
2912
3092
  let dustBorrowShares = 0n;
@@ -2921,10 +3101,10 @@ var _MorphoClient = class _MorphoClient {
2921
3101
  const totalBorrowAssets = BigInt(onChainMkt.totalBorrowAssets);
2922
3102
  const totalBorrowShares = BigInt(onChainMkt.totalBorrowShares);
2923
3103
  const estimated = totalBorrowShares > 0n ? dustBorrowShares * totalBorrowAssets / totalBorrowShares + 10n : 0n;
2924
- dustApproveAmount = estimated > 0n ? estimated : import_ethers2.ethers.parseUnits("1", loanDecimals);
3104
+ dustApproveAmount = estimated > 0n ? estimated : import_ethers3.ethers.parseUnits("1", loanDecimals);
2925
3105
  const loanInfo = this._tokenCache.get(loanTokenAddr.toLowerCase());
2926
3106
  const loanSymbol = loanInfo?.symbol ?? "loan token";
2927
- console.log(`[agether] dust borrow shares detected: ${dustBorrowShares} shares \u2248 ${import_ethers2.ethers.formatUnits(dustApproveAmount, loanDecimals)} ${loanSymbol} \u2014 auto-repaying before withdraw`);
3107
+ console.log(`[agether] dust borrow shares detected: ${dustBorrowShares} shares \u2248 ${import_ethers3.ethers.formatUnits(dustApproveAmount, loanDecimals)} ${loanSymbol} \u2014 auto-repaying before withdraw`);
2928
3108
  }
2929
3109
  } catch (e) {
2930
3110
  console.warn("[agether] failed to check borrow shares before withdraw:", e instanceof Error ? e.message : e);
@@ -2938,7 +3118,7 @@ var _MorphoClient = class _MorphoClient {
2938
3118
  ]);
2939
3119
  let receipt;
2940
3120
  if (hasDustDebt) {
2941
- const loanContract = new import_ethers2.Contract(loanTokenAddr, ERC20_ABI, this._signer);
3121
+ const loanContract = new import_ethers3.Contract(loanTokenAddr, ERC20_ABI, this._signer);
2942
3122
  const acctBalance = await loanContract.balanceOf(acctAddr);
2943
3123
  if (acctBalance < dustApproveAmount) {
2944
3124
  const shortfall = dustApproveAmount - acctBalance;
@@ -2946,7 +3126,7 @@ var _MorphoClient = class _MorphoClient {
2946
3126
  if (eoaBalance >= shortfall) {
2947
3127
  const loanInfo = this._tokenCache.get(loanTokenAddr.toLowerCase());
2948
3128
  const loanSymbol = loanInfo?.symbol ?? "loan token";
2949
- console.log(`[agether] transferring ${import_ethers2.ethers.formatUnits(shortfall, loanDecimals)} ${loanSymbol} from EOA \u2192 AgentAccount for dust repay`);
3129
+ console.log(`[agether] transferring ${import_ethers3.ethers.formatUnits(shortfall, loanDecimals)} ${loanSymbol} from EOA \u2192 AgentAccount for dust repay`);
2950
3130
  const transferTx = await loanContract.transfer(acctAddr, shortfall);
2951
3131
  await transferTx.wait();
2952
3132
  this._refreshSigner();
@@ -2965,15 +3145,15 @@ var _MorphoClient = class _MorphoClient {
2965
3145
  ]),
2966
3146
  withdrawData
2967
3147
  ];
2968
- receipt = await this.batch(targets, values, datas);
3148
+ receipt = await this.executeBatch(targets, values, datas);
2969
3149
  } else {
2970
- receipt = await this.exec(morphoAddr, withdrawData);
3150
+ receipt = await this.executeSingle(morphoAddr, withdrawData);
2971
3151
  }
2972
3152
  let remainingCollateral = "0";
2973
3153
  try {
2974
3154
  if (market) {
2975
3155
  const pos = await this.morphoBlue.position(market.uniqueKey, acctAddr);
2976
- remainingCollateral = import_ethers2.ethers.formatUnits(pos.collateral, colInfo.decimals);
3156
+ remainingCollateral = import_ethers3.ethers.formatUnits(pos.collateral, colInfo.decimals);
2977
3157
  }
2978
3158
  } catch (e) {
2979
3159
  console.warn("[agether] failed to read remaining collateral after withdraw:", e instanceof Error ? e.message : e);
@@ -2981,7 +3161,7 @@ var _MorphoClient = class _MorphoClient {
2981
3161
  return {
2982
3162
  tx: receipt.hash,
2983
3163
  token: tokenSymbol,
2984
- amount: amount === "all" ? import_ethers2.ethers.formatUnits(weiAmount, colInfo.decimals) : amount,
3164
+ amount: amount === "all" ? import_ethers3.ethers.formatUnits(weiAmount, colInfo.decimals) : amount,
2985
3165
  remainingCollateral,
2986
3166
  destination: dest
2987
3167
  };
@@ -3005,139 +3185,21 @@ var _MorphoClient = class _MorphoClient {
3005
3185
  _refreshSigner() {
3006
3186
  if (this._useExternalSigner) {
3007
3187
  const addrs = this.config.contracts;
3008
- this.agether4337Factory = new import_ethers2.Contract(addrs.agether4337Factory, ACCOUNT_FACTORY_ABI, this._signer);
3009
- this.entryPoint = new import_ethers2.Contract(addrs.entryPoint, ENTRYPOINT_V07_ABI, this._signer);
3188
+ this.agether4337Factory = new import_ethers3.Contract(addrs.agether4337Factory, ACCOUNT_FACTORY_ABI, this._signer);
3189
+ this.entryPoint = new import_ethers3.Contract(addrs.entryPoint, ENTRYPOINT_V07_ABI, this._signer);
3010
3190
  } else {
3011
- this.provider = new import_ethers2.ethers.JsonRpcProvider(this._rpcUrl);
3012
- const wallet = new import_ethers2.ethers.Wallet(this._privateKey, this.provider);
3191
+ this.provider = new import_ethers3.ethers.JsonRpcProvider(this._rpcUrl);
3192
+ const wallet = new import_ethers3.ethers.Wallet(this._privateKey, this.provider);
3013
3193
  this._signer = wallet;
3014
3194
  this._eoaAddress = wallet.address;
3015
3195
  const addrs = this.config.contracts;
3016
- this.agether4337Factory = new import_ethers2.Contract(addrs.agether4337Factory, ACCOUNT_FACTORY_ABI, this._signer);
3017
- this.entryPoint = new import_ethers2.Contract(addrs.entryPoint, ENTRYPOINT_V07_ABI, this._signer);
3196
+ this.agether4337Factory = new import_ethers3.Contract(addrs.agether4337Factory, ACCOUNT_FACTORY_ABI, this._signer);
3197
+ this.entryPoint = new import_ethers3.Contract(addrs.entryPoint, ENTRYPOINT_V07_ABI, this._signer);
3018
3198
  }
3019
3199
  }
3020
3200
  // ────────────────────────────────────────────────────────────
3021
3201
  // ERC-4337 UserOp helpers (Safe + Safe7579 + EntryPoint v0.7)
3022
3202
  // ────────────────────────────────────────────────────────────
3023
- /**
3024
- * Pack two uint128 values into a single bytes32:
3025
- * bytes32 = (hi << 128) | lo
3026
- */
3027
- _packUint128(hi, lo) {
3028
- return import_ethers2.ethers.zeroPadValue(import_ethers2.ethers.toBeHex(hi << 128n | lo), 32);
3029
- }
3030
- /**
3031
- * Build, sign and submit a PackedUserOperation through EntryPoint.handleOps.
3032
- *
3033
- * @param callData – the ABI-encoded calldata for the Safe7579 account
3034
- * (e.g. `execute(mode, executionCalldata)`)
3035
- * @returns the transaction receipt of the handleOps call
3036
- */
3037
- async _submitUserOp(callData) {
3038
- const sender = await this.getAccountAddress();
3039
- const validatorAddr = this.config.contracts.erc8004ValidationModule;
3040
- const nonceKey = BigInt(validatorAddr) << 32n;
3041
- const nonce = await this.entryPoint.getNonce(sender, nonceKey);
3042
- const feeData = await this.provider.getFeeData();
3043
- const maxFeePerGas = feeData.maxFeePerGas ?? import_ethers2.ethers.parseUnits("0.5", "gwei");
3044
- const maxPriorityFeePerGas = feeData.maxPriorityFeePerGas ?? import_ethers2.ethers.parseUnits("0.1", "gwei");
3045
- const verificationGasLimit = 500000n;
3046
- const callGasLimit = 800000n;
3047
- const preVerificationGas = 100000n;
3048
- const accountGasLimits = this._packUint128(verificationGasLimit, callGasLimit);
3049
- const gasFees = this._packUint128(maxPriorityFeePerGas, maxFeePerGas);
3050
- const requiredPrefund = (verificationGasLimit + callGasLimit + preVerificationGas) * maxFeePerGas;
3051
- const accountBalance = await this.provider.getBalance(sender);
3052
- if (accountBalance < requiredPrefund) {
3053
- const topUp = requiredPrefund - accountBalance;
3054
- const topUpWithBuffer = topUp * 120n / 100n;
3055
- const fundTx = await this._signer.sendTransaction({
3056
- to: sender,
3057
- value: topUpWithBuffer
3058
- });
3059
- await fundTx.wait();
3060
- this._refreshSigner();
3061
- }
3062
- const userOp = {
3063
- sender,
3064
- nonce,
3065
- initCode: "0x",
3066
- callData,
3067
- accountGasLimits,
3068
- preVerificationGas,
3069
- gasFees,
3070
- paymasterAndData: "0x",
3071
- signature: "0x"
3072
- // placeholder — replaced after signing
3073
- };
3074
- const userOpHash = await this.entryPoint.getUserOpHash(userOp);
3075
- const signature = await this._signer.signMessage(import_ethers2.ethers.getBytes(userOpHash));
3076
- userOp.signature = signature;
3077
- const tx = await this.entryPoint.handleOps([userOp], await this.getSignerAddress());
3078
- const receipt = await tx.wait();
3079
- this._refreshSigner();
3080
- const epIface = new import_ethers2.ethers.Interface(ENTRYPOINT_V07_ABI);
3081
- for (const log of receipt.logs) {
3082
- try {
3083
- const parsed = epIface.parseLog({ topics: log.topics, data: log.data });
3084
- if (parsed?.name === "UserOperationEvent" && !parsed.args.success) {
3085
- let revertMsg = "UserOp inner execution reverted";
3086
- for (const rLog of receipt.logs) {
3087
- try {
3088
- const rParsed = epIface.parseLog({ topics: rLog.topics, data: rLog.data });
3089
- if (rParsed?.name === "UserOperationRevertReason") {
3090
- const reason = rParsed.args.revertReason;
3091
- try {
3092
- if (reason.length >= 10 && reason.slice(0, 10) === "0x08c379a0") {
3093
- const decoded = import_ethers2.ethers.AbiCoder.defaultAbiCoder().decode(["string"], "0x" + reason.slice(10));
3094
- revertMsg = `UserOp reverted: ${decoded[0]}`;
3095
- } else {
3096
- revertMsg = `UserOp reverted with data: ${reason}`;
3097
- }
3098
- } catch {
3099
- revertMsg = `UserOp reverted with data: ${reason}`;
3100
- }
3101
- break;
3102
- }
3103
- } catch {
3104
- continue;
3105
- }
3106
- }
3107
- throw new AgetherError(revertMsg, "USEROP_EXECUTION_FAILED");
3108
- }
3109
- } catch (e) {
3110
- if (e instanceof AgetherError) throw e;
3111
- continue;
3112
- }
3113
- }
3114
- return receipt;
3115
- }
3116
- /**
3117
- * Execute a single call via Safe7579 account (ERC-7579 single mode)
3118
- * through an ERC-4337 UserOperation.
3119
- */
3120
- async exec(target, data, value = 0n) {
3121
- const valueHex = import_ethers2.ethers.zeroPadValue(import_ethers2.ethers.toBeHex(value), 32);
3122
- const executionCalldata = import_ethers2.ethers.concat([target, valueHex, data]);
3123
- const safe7579Iface = new import_ethers2.ethers.Interface(SAFE7579_ACCOUNT_ABI);
3124
- const callData = safe7579Iface.encodeFunctionData("execute", [MODE_SINGLE2, executionCalldata]);
3125
- return this._submitUserOp(callData);
3126
- }
3127
- /**
3128
- * Execute multiple calls via Safe7579 account (ERC-7579 batch mode)
3129
- * through an ERC-4337 UserOperation.
3130
- */
3131
- async batch(targets, values, datas) {
3132
- const executions = targets.map((t, i) => [t, values[i], datas[i]]);
3133
- const executionCalldata = import_ethers2.ethers.AbiCoder.defaultAbiCoder().encode(
3134
- ["(address,uint256,bytes)[]"],
3135
- [executions]
3136
- );
3137
- const safe7579Iface = new import_ethers2.ethers.Interface(SAFE7579_ACCOUNT_ABI);
3138
- const callData = safe7579Iface.encodeFunctionData("execute", [MODE_BATCH, executionCalldata]);
3139
- return this._submitUserOp(callData);
3140
- }
3141
3203
  /** Convert MorphoMarketParams to Solidity tuple. */
3142
3204
  _toTuple(p) {
3143
3205
  return [p.loanToken, p.collateralToken, p.oracle, p.irm, p.lltv];
@@ -3187,7 +3249,7 @@ var _MorphoClient = class _MorphoClient {
3187
3249
  }
3188
3250
  const markets = await this.getMarkets();
3189
3251
  for (const m of markets) {
3190
- if (!m.collateralAsset || m.collateralAsset.address === import_ethers2.ethers.ZeroAddress) continue;
3252
+ if (!m.collateralAsset || m.collateralAsset.address === import_ethers3.ethers.ZeroAddress) continue;
3191
3253
  try {
3192
3254
  const pos = await this.morphoBlue.position(m.uniqueKey, acctAddr);
3193
3255
  if (pos.collateral > 0n) {
@@ -3255,7 +3317,7 @@ var _MorphoClient = class _MorphoClient {
3255
3317
  }
3256
3318
  const markets = await this.getMarkets();
3257
3319
  for (const m of markets) {
3258
- if (!m.collateralAsset || m.collateralAsset.address === import_ethers2.ethers.ZeroAddress) continue;
3320
+ if (!m.collateralAsset || m.collateralAsset.address === import_ethers3.ethers.ZeroAddress) continue;
3259
3321
  try {
3260
3322
  const pos = await this.morphoBlue.position(m.uniqueKey, acctAddr);
3261
3323
  if (BigInt(pos.supplyShares) > 0n) {
@@ -3434,6 +3496,316 @@ _MorphoClient._lstYieldCache = null;
3434
3496
  _MorphoClient.LST_CACHE_TTL = 30 * 60 * 1e3;
3435
3497
  var MorphoClient = _MorphoClient;
3436
3498
 
3499
+ // src/clients/AaveClient.ts
3500
+ var import_ethers4 = require("ethers");
3501
+ var POOL_ABI = [
3502
+ "function getUserAccountData(address user) view returns (uint256 totalCollateralBase, uint256 totalDebtBase, uint256 availableBorrowsBase, uint256 currentLiquidationThreshold, uint256 currentLtv, uint256 healthFactor)",
3503
+ "function getReserveData(address asset) view returns (tuple(uint256 configuration, uint128 liquidityIndex, uint128 currentLiquidityRate, uint128 variableBorrowIndex, uint128 currentVariableBorrowRate, uint128 currentStableBorrowRate, uint40 lastUpdateTimestamp, uint16 id, address aTokenAddress, address stableDebtTokenAddress, address variableDebtTokenAddress, address interestRateStrategyAddress, uint128 accruedToTreasury, uint128 unbacked, uint128 isolationModeTotalDebt))",
3504
+ "function getReservesList() view returns (address[])",
3505
+ "function supply(address asset, uint256 amount, address onBehalfOf, uint16 referralCode)",
3506
+ "function withdraw(address asset, uint256 amount, address to) returns (uint256)",
3507
+ "function borrow(address asset, uint256 amount, uint256 interestRateMode, uint16 referralCode, address onBehalfOf)",
3508
+ "function repay(address asset, uint256 amount, uint256 interestRateMode, address onBehalfOf) returns (uint256)",
3509
+ "function setUserUseReserveAsCollateral(address asset, bool useAsCollateral)"
3510
+ ];
3511
+ var ERC20_ABI2 = [
3512
+ "function approve(address spender, uint256 amount) returns (bool)",
3513
+ "function allowance(address owner, address spender) view returns (uint256)",
3514
+ "function balanceOf(address account) view returns (uint256)",
3515
+ "function decimals() view returns (uint8)",
3516
+ "function symbol() view returns (string)"
3517
+ ];
3518
+ var ORACLE_ABI = [
3519
+ "function getAssetsPrices(address[] assets) view returns (uint256[])",
3520
+ "function BASE_CURRENCY_UNIT() view returns (uint256)"
3521
+ ];
3522
+ var POOL_DATA_PROVIDER_ABI = [
3523
+ "function getReserveConfigurationData(address asset) view returns (uint256 decimals, uint256 ltv, uint256 liquidationThreshold, uint256 liquidationBonus, uint256 reserveFactor, bool usageAsCollateralEnabled, bool borrowingEnabled, bool stableBorrowRateEnabled, bool isActive, bool isFrozen)",
3524
+ "function getUserReserveData(address asset, address user) view returns (uint256 currentATokenBalance, uint256 currentStableDebt, uint256 currentVariableDebt, uint256 principalStableDebt, uint256 scaledVariableDebt, uint256 stableBorrowRate, uint256 liquidityRate, uint40 stableRateLastUpdated, bool usageAsCollateralEnabled)",
3525
+ "function getReserveTokensAddresses(address asset) view returns (address aTokenAddress, address stableDebtTokenAddress, address variableDebtTokenAddress)",
3526
+ "function getAllReservesTokens() view returns (tuple(string symbol, address tokenAddress)[])"
3527
+ ];
3528
+ var AAVE_ADDRESSES = {
3529
+ [1 /* Ethereum */]: {
3530
+ pool: "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2",
3531
+ oracle: "0x54586bE62E3c3580375aE3723C145253060Ca0C2",
3532
+ dataProvider: "0x0a16f2FCC0D44FaE41cc54e079281D84A363bECD"
3533
+ },
3534
+ [8453 /* Base */]: {
3535
+ pool: "0xA238Dd80C259a72e81d7e4664a9801593F98d1c5",
3536
+ oracle: "0x2Cc0Fc26eD4563A5ce5e8bdcfe1A2878676Ae156",
3537
+ dataProvider: "0x0F43731EB8d45A581f4a36DD74F5f358bc90C73A"
3538
+ }
3539
+ };
3540
+ var KNOWN_RESERVES = {
3541
+ [1 /* Ethereum */]: [
3542
+ { symbol: "WETH", address: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", decimals: 18 },
3543
+ { symbol: "wstETH", address: "0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0", decimals: 18 },
3544
+ { symbol: "USDC", address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", decimals: 6 },
3545
+ { symbol: "USDT", address: "0xdAC17F958D2ee523a2206206994597C13D831ec7", decimals: 6 },
3546
+ { symbol: "DAI", address: "0x6B175474E89094C44Da98b954EedeAC495271d0F", decimals: 18 },
3547
+ { symbol: "cbETH", address: "0xBe9895146f7AF43049ca1c1AE358B0541Ea49704", decimals: 18 },
3548
+ { symbol: "rETH", address: "0xae78736Cd615f374D3085123A210448E74Fc6393", decimals: 18 },
3549
+ { symbol: "weETH", address: "0xCd5fE23C85820F7B72D0926FC9b05b43E359b7ee", decimals: 18 }
3550
+ ],
3551
+ [8453 /* Base */]: [
3552
+ { symbol: "WETH", address: "0x4200000000000000000000000000000000000006", decimals: 18 },
3553
+ { symbol: "wstETH", address: "0xc1CBa3fCea344f92D9239c08C0568f6F2F0ee452", decimals: 18 },
3554
+ { symbol: "cbETH", address: "0x2Ae3F1Ec7F1F5012CFEab0185bfc7aa3cf0DEc22", decimals: 18 },
3555
+ { symbol: "USDC", address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", decimals: 6 },
3556
+ { symbol: "USDbC", address: "0xd9aAEc86B65D86f6A7B5B1b0c42FFA531710b6CA", decimals: 6 }
3557
+ ]
3558
+ };
3559
+ var _AaveClient = class _AaveClient extends AgentAccountClient {
3560
+ /**
3561
+ * Create an AaveClient. Takes the same config as MorphoClient — the agent's
3562
+ * Safe account is used for all Aave operations.
3563
+ */
3564
+ constructor(config) {
3565
+ super(config);
3566
+ // Cache
3567
+ this._reserveCache = /* @__PURE__ */ new Map();
3568
+ this._reserveCacheTs = 0;
3569
+ const chainId = config.chainId ?? 1 /* Ethereum */;
3570
+ const addrs = AAVE_ADDRESSES[chainId];
3571
+ if (!addrs) {
3572
+ throw new AgetherError(`Aave V3 not supported on chain ${chainId}`, "UNSUPPORTED_CHAIN");
3573
+ }
3574
+ this._aaveChainId = chainId;
3575
+ this._pool = new import_ethers4.Contract(addrs.pool, POOL_ABI, this.provider);
3576
+ this._oracle = new import_ethers4.Contract(addrs.oracle, ORACLE_ABI, this.provider);
3577
+ this._dataProvider = new import_ethers4.Contract(addrs.dataProvider, POOL_DATA_PROVIDER_ABI, this.provider);
3578
+ this._poolIface = new import_ethers4.ethers.Interface(POOL_ABI);
3579
+ this._erc20Iface = new import_ethers4.ethers.Interface(ERC20_ABI2);
3580
+ }
3581
+ /** Get the Agent's Safe account address. */
3582
+ async getAccountAddress() {
3583
+ return super.getAccountAddress();
3584
+ }
3585
+ /** Get chainId. */
3586
+ get aaveChainId() {
3587
+ return this._aaveChainId;
3588
+ }
3589
+ // ─── Market Data (read-only, no Safe needed) ─────────────────────────
3590
+ async getReserves(forceRefresh = false) {
3591
+ if (!forceRefresh && this._reserveCache.size > 0 && Date.now() - this._reserveCacheTs < _AaveClient.CACHE_TTL) {
3592
+ return Array.from(this._reserveCache.values());
3593
+ }
3594
+ const reserves = KNOWN_RESERVES[this._aaveChainId] ?? [];
3595
+ if (reserves.length === 0) return [];
3596
+ const addresses = reserves.map((r) => r.address);
3597
+ const prices = await this._oracle.getAssetsPrices(addresses);
3598
+ let baseCurrencyUnit;
3599
+ try {
3600
+ baseCurrencyUnit = await this._oracle.BASE_CURRENCY_UNIT();
3601
+ } catch {
3602
+ baseCurrencyUnit = 100000000n;
3603
+ }
3604
+ const results = [];
3605
+ const reserveDataPromises = reserves.map(async (reserve, i) => {
3606
+ try {
3607
+ const [reserveData, configData] = await Promise.all([
3608
+ this._pool.getReserveData(reserve.address),
3609
+ this._dataProvider.getReserveConfigurationData(reserve.address)
3610
+ ]);
3611
+ const RAY = 10n ** 27n;
3612
+ const liquidityRate = reserveData[2];
3613
+ const borrowRate = reserveData[4];
3614
+ const supplyApy = Number(liquidityRate) / Number(RAY) * 100;
3615
+ const borrowApy = Number(borrowRate) / Number(RAY) * 100;
3616
+ const priceUsd = Number(prices[i]) / Number(baseCurrencyUnit);
3617
+ const ltv = Number(configData[1]) / 100;
3618
+ const liqThreshold = Number(configData[2]) / 100;
3619
+ const borrowingEnabled = configData[6];
3620
+ const isActive = configData[8];
3621
+ const info = {
3622
+ symbol: reserve.symbol,
3623
+ address: reserve.address,
3624
+ decimals: reserve.decimals,
3625
+ supplyApy,
3626
+ borrowApy,
3627
+ totalSupply: 0,
3628
+ totalBorrow: 0,
3629
+ ltv,
3630
+ liquidationThreshold: liqThreshold,
3631
+ borrowingEnabled,
3632
+ isActive,
3633
+ priceUsd
3634
+ };
3635
+ this._reserveCache.set(reserve.symbol, info);
3636
+ return info;
3637
+ } catch (err) {
3638
+ console.warn(`[aave] Failed to fetch reserve ${reserve.symbol}:`, err instanceof Error ? err.message : err);
3639
+ return null;
3640
+ }
3641
+ });
3642
+ const settled = await Promise.all(reserveDataPromises);
3643
+ for (const r of settled) {
3644
+ if (r) results.push(r);
3645
+ }
3646
+ this._reserveCacheTs = Date.now();
3647
+ return results;
3648
+ }
3649
+ // ─── Account Data (reads from Safe account) ──────────────────────────
3650
+ async getAccountData() {
3651
+ const safeAddr = await this.getAccountAddress();
3652
+ const [totalCollateralBase, totalDebtBase, availableBorrowsBase, currentLtv, liqThreshold, healthFactor] = await this._pool.getUserAccountData(safeAddr);
3653
+ let baseCurrencyUnit;
3654
+ try {
3655
+ baseCurrencyUnit = await this._oracle.BASE_CURRENCY_UNIT();
3656
+ } catch {
3657
+ baseCurrencyUnit = 100000000n;
3658
+ }
3659
+ const totalCollateralUsd = Number(totalCollateralBase) / Number(baseCurrencyUnit);
3660
+ const totalDebtUsd = Number(totalDebtBase) / Number(baseCurrencyUnit);
3661
+ const availableBorrowUsd = Number(availableBorrowsBase) / Number(baseCurrencyUnit);
3662
+ const hf = Number(healthFactor) / 1e18;
3663
+ const reserves = KNOWN_RESERVES[this._aaveChainId] ?? [];
3664
+ const reserveInfos = await this.getReserves();
3665
+ const positions = [];
3666
+ const posPromises = reserves.map(async (reserve) => {
3667
+ try {
3668
+ const userData = await this._dataProvider.getUserReserveData(reserve.address, safeAddr);
3669
+ const aTokenBal = userData[0];
3670
+ const stableDebt = userData[1];
3671
+ const variableDebt = userData[2];
3672
+ const usedAsCollateral = userData[8];
3673
+ const totalDebt = stableDebt + variableDebt;
3674
+ if (aTokenBal === 0n && totalDebt === 0n) return null;
3675
+ const reserveInfo = reserveInfos.find((r) => r.symbol === reserve.symbol);
3676
+ const priceUsd = reserveInfo?.priceUsd ?? 0;
3677
+ const divisor = 10 ** reserve.decimals;
3678
+ return {
3679
+ asset: reserve.symbol,
3680
+ address: reserve.address,
3681
+ supplied: Number(aTokenBal) / divisor,
3682
+ suppliedUsd: Number(aTokenBal) / divisor * priceUsd,
3683
+ borrowed: Number(totalDebt) / divisor,
3684
+ borrowedUsd: Number(totalDebt) / divisor * priceUsd,
3685
+ usedAsCollateral,
3686
+ supplyApy: reserveInfo?.supplyApy ?? 0,
3687
+ borrowApy: reserveInfo?.borrowApy ?? 0
3688
+ };
3689
+ } catch {
3690
+ return null;
3691
+ }
3692
+ });
3693
+ const settled = await Promise.all(posPromises);
3694
+ for (const p of settled) {
3695
+ if (p) positions.push(p);
3696
+ }
3697
+ return {
3698
+ totalCollateralUsd,
3699
+ totalDebtUsd,
3700
+ availableBorrowUsd,
3701
+ currentLtv: Number(currentLtv) / 100,
3702
+ liquidationThreshold: Number(liqThreshold) / 100,
3703
+ healthFactor: hf > 1e10 ? Infinity : hf,
3704
+ positions
3705
+ };
3706
+ }
3707
+ // ─── Write Operations (through Safe account) ─────────────────────────
3708
+ /**
3709
+ * Supply an asset to Aave V3 from the Agent's Safe account.
3710
+ * Batch: approve + supply in one UserOp.
3711
+ */
3712
+ async supply(asset, amount) {
3713
+ const reserve = this._resolveReserve(asset);
3714
+ const amountWei = import_ethers4.ethers.parseUnits(amount, reserve.decimals);
3715
+ const safeAddr = await this.getAccountAddress();
3716
+ const poolAddr = await this._pool.getAddress();
3717
+ const approveData = this._erc20Iface.encodeFunctionData("approve", [poolAddr, amountWei]);
3718
+ const supplyData = this._poolIface.encodeFunctionData("supply", [reserve.address, amountWei, safeAddr, 0]);
3719
+ return this.executeBatch(
3720
+ [reserve.address, poolAddr],
3721
+ [0n, 0n],
3722
+ [approveData, supplyData]
3723
+ );
3724
+ }
3725
+ /**
3726
+ * Withdraw a supplied asset from Aave V3 to the Safe account.
3727
+ */
3728
+ async withdraw(asset, amount, to) {
3729
+ const reserve = this._resolveReserve(asset);
3730
+ const amountWei = amount === "all" ? import_ethers4.ethers.MaxUint256 : import_ethers4.ethers.parseUnits(amount, reserve.decimals);
3731
+ const recipient = to ?? await this.getAccountAddress();
3732
+ const poolAddr = await this._pool.getAddress();
3733
+ const data = this._poolIface.encodeFunctionData("withdraw", [reserve.address, amountWei, recipient]);
3734
+ return this.executeSingle(poolAddr, data);
3735
+ }
3736
+ /**
3737
+ * Borrow an asset from Aave V3 (variable rate) to the Safe account.
3738
+ */
3739
+ async borrow(asset, amount) {
3740
+ const reserve = this._resolveReserve(asset);
3741
+ const amountWei = import_ethers4.ethers.parseUnits(amount, reserve.decimals);
3742
+ const safeAddr = await this.getAccountAddress();
3743
+ const poolAddr = await this._pool.getAddress();
3744
+ const data = this._poolIface.encodeFunctionData("borrow", [reserve.address, amountWei, 2, 0, safeAddr]);
3745
+ return this.executeSingle(poolAddr, data);
3746
+ }
3747
+ /**
3748
+ * Repay borrowed asset on Aave V3 from the Safe account.
3749
+ * Batch: approve + repay in one UserOp.
3750
+ */
3751
+ async repay(asset, amount) {
3752
+ const reserve = this._resolveReserve(asset);
3753
+ const amountWei = amount === "all" ? import_ethers4.ethers.MaxUint256 : import_ethers4.ethers.parseUnits(amount, reserve.decimals);
3754
+ const safeAddr = await this.getAccountAddress();
3755
+ const poolAddr = await this._pool.getAddress();
3756
+ const approveAmount = amount === "all" ? import_ethers4.ethers.MaxUint256 : amountWei;
3757
+ const approveData = this._erc20Iface.encodeFunctionData("approve", [poolAddr, approveAmount]);
3758
+ const repayData = this._poolIface.encodeFunctionData("repay", [reserve.address, amountWei, 2, safeAddr]);
3759
+ return this.executeBatch(
3760
+ [reserve.address, poolAddr],
3761
+ [0n, 0n],
3762
+ [approveData, repayData]
3763
+ );
3764
+ }
3765
+ /**
3766
+ * Enable or disable a supplied asset as collateral.
3767
+ */
3768
+ async setCollateral(asset, useAsCollateral) {
3769
+ const reserve = this._resolveReserve(asset);
3770
+ const poolAddr = await this._pool.getAddress();
3771
+ const data = this._poolIface.encodeFunctionData("setUserUseReserveAsCollateral", [reserve.address, useAsCollateral]);
3772
+ return this.executeSingle(poolAddr, data);
3773
+ }
3774
+ /**
3775
+ * Supply an asset and borrow in one atomic batch operation.
3776
+ */
3777
+ async supplyAndBorrow(supplyAsset, supplyAmount, borrowAsset, borrowAmount) {
3778
+ const supplyReserve = this._resolveReserve(supplyAsset);
3779
+ const borrowReserve = this._resolveReserve(borrowAsset);
3780
+ const supplyWei = import_ethers4.ethers.parseUnits(supplyAmount, supplyReserve.decimals);
3781
+ const borrowWei = import_ethers4.ethers.parseUnits(borrowAmount, borrowReserve.decimals);
3782
+ const safeAddr = await this.getAccountAddress();
3783
+ const poolAddr = await this._pool.getAddress();
3784
+ const approveData = this._erc20Iface.encodeFunctionData("approve", [poolAddr, supplyWei]);
3785
+ const supplyData = this._poolIface.encodeFunctionData("supply", [supplyReserve.address, supplyWei, safeAddr, 0]);
3786
+ const borrowData = this._poolIface.encodeFunctionData("borrow", [borrowReserve.address, borrowWei, 2, 0, safeAddr]);
3787
+ return this.executeBatch(
3788
+ [supplyReserve.address, poolAddr, poolAddr],
3789
+ [0n, 0n, 0n],
3790
+ [approveData, supplyData, borrowData]
3791
+ );
3792
+ }
3793
+ // ─── Helpers ──────────────────────────────────────────────────────────
3794
+ _resolveReserve(symbolOrAddress) {
3795
+ const reserves = KNOWN_RESERVES[this._aaveChainId] ?? [];
3796
+ const bySymbol = reserves.find((r) => r.symbol.toLowerCase() === symbolOrAddress.toLowerCase());
3797
+ if (bySymbol) return bySymbol;
3798
+ const byAddr = reserves.find((r) => r.address.toLowerCase() === symbolOrAddress.toLowerCase());
3799
+ if (byAddr) return byAddr;
3800
+ throw new AgetherError(
3801
+ `Unknown Aave reserve: ${symbolOrAddress}. Known: ${reserves.map((r) => r.symbol).join(", ")}`,
3802
+ "UNKNOWN_RESERVE"
3803
+ );
3804
+ }
3805
+ };
3806
+ _AaveClient.CACHE_TTL = 6e4;
3807
+ var AaveClient = _AaveClient;
3808
+
3437
3809
  // src/clients/ScoringClient.ts
3438
3810
  var import_axios3 = __toESM(require("axios"));
3439
3811
 
@@ -3899,7 +4271,7 @@ var ScoringClient = class {
3899
4271
  };
3900
4272
 
3901
4273
  // src/clients/AgentIdentityClient.ts
3902
- var import_ethers3 = require("ethers");
4274
+ var import_ethers5 = require("ethers");
3903
4275
  var ERC8004_IDENTITY_ABI = [
3904
4276
  // Registration
3905
4277
  "function register() returns (uint256)",
@@ -3941,8 +4313,8 @@ var AgentIdentityClient = class {
3941
4313
  this.signer = options.signer;
3942
4314
  const identityAddr = options.config.contracts?.identityRegistry || ERC8004_SEPOLIA.identityRegistry;
3943
4315
  const reputationAddr = options.config.contracts?.reputationRegistry || ERC8004_SEPOLIA.reputationRegistry;
3944
- this.identityRegistry = new import_ethers3.ethers.Contract(identityAddr, ERC8004_IDENTITY_ABI, this.signer);
3945
- this.reputationRegistry = new import_ethers3.ethers.Contract(reputationAddr, ERC8004_REPUTATION_ABI, this.signer);
4316
+ this.identityRegistry = new import_ethers5.ethers.Contract(identityAddr, ERC8004_IDENTITY_ABI, this.signer);
4317
+ this.reputationRegistry = new import_ethers5.ethers.Contract(reputationAddr, ERC8004_REPUTATION_ABI, this.signer);
3946
4318
  }
3947
4319
  // ============ Identity Functions ============
3948
4320
  /**
@@ -4010,7 +4382,7 @@ var AgentIdentityClient = class {
4010
4382
  async registerWithMetadata(agentURI, metadata) {
4011
4383
  const metadataEntries = metadata.map((m) => ({
4012
4384
  key: m.key,
4013
- value: import_ethers3.ethers.toUtf8Bytes(m.value)
4385
+ value: import_ethers5.ethers.toUtf8Bytes(m.value)
4014
4386
  }));
4015
4387
  const tx = await this.identityRegistry["register(string,tuple(string,bytes)[])"](
4016
4388
  agentURI,
@@ -4047,7 +4419,7 @@ var AgentIdentityClient = class {
4047
4419
  const tx = await this.identityRegistry.setMetadata(
4048
4420
  agentId,
4049
4421
  key,
4050
- import_ethers3.ethers.toUtf8Bytes(value)
4422
+ import_ethers5.ethers.toUtf8Bytes(value)
4051
4423
  );
4052
4424
  const receipt = await tx.wait();
4053
4425
  return receipt.hash;
@@ -4057,7 +4429,7 @@ var AgentIdentityClient = class {
4057
4429
  */
4058
4430
  async getMetadata(agentId, key) {
4059
4431
  const value = await this.identityRegistry.getMetadata(agentId, key);
4060
- return import_ethers3.ethers.toUtf8String(value);
4432
+ return import_ethers5.ethers.toUtf8String(value);
4061
4433
  }
4062
4434
  /**
4063
4435
  * Transfer agent to new owner
@@ -4092,8 +4464,8 @@ var AgentIdentityClient = class {
4092
4464
  * Give feedback to an agent
4093
4465
  */
4094
4466
  async giveFeedback(input) {
4095
- const feedbackHash = import_ethers3.ethers.keccak256(
4096
- import_ethers3.ethers.AbiCoder.defaultAbiCoder().encode(
4467
+ const feedbackHash = import_ethers5.ethers.keccak256(
4468
+ import_ethers5.ethers.AbiCoder.defaultAbiCoder().encode(
4097
4469
  ["uint256", "int128", "uint256"],
4098
4470
  [input.agentId, input.value, Date.now()]
4099
4471
  )
@@ -4287,6 +4659,8 @@ function rateToBps(rate) {
4287
4659
  AGETHER_8004_SCORER_ABI,
4288
4660
  AGETHER_8004_VALIDATION_MODULE_ABI,
4289
4661
  AGETHER_HOOK_MULTIPLEXER_ABI,
4662
+ AaveClient,
4663
+ AgentAccountClient,
4290
4664
  AgentIdentityClient,
4291
4665
  AgentNotApprovedError,
4292
4666
  AgetherClient,