@agether/sdk 1.2.0 → 1.3.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.
Files changed (41) hide show
  1. package/dist/cli.js +295 -5
  2. package/dist/index.d.mts +205 -1
  3. package/dist/index.d.ts +205 -1
  4. package/dist/index.js +460 -17
  5. package/dist/index.mjs +458 -16
  6. package/package.json +1 -1
  7. package/dist/cli.d.mts +0 -2
  8. package/dist/cli.d.ts +0 -19
  9. package/dist/cli.d.ts.map +0 -1
  10. package/dist/cli.mjs +0 -0
  11. package/dist/clients/AgentIdentityClient.d.ts +0 -163
  12. package/dist/clients/AgentIdentityClient.d.ts.map +0 -1
  13. package/dist/clients/AgentIdentityClient.js +0 -293
  14. package/dist/clients/AgetherClient.d.ts +0 -101
  15. package/dist/clients/AgetherClient.d.ts.map +0 -1
  16. package/dist/clients/AgetherClient.js +0 -272
  17. package/dist/clients/ScoringClient.d.ts +0 -138
  18. package/dist/clients/ScoringClient.d.ts.map +0 -1
  19. package/dist/clients/ScoringClient.js +0 -135
  20. package/dist/clients/VaultClient.d.ts +0 -62
  21. package/dist/clients/VaultClient.d.ts.map +0 -1
  22. package/dist/clients/VaultClient.js +0 -157
  23. package/dist/clients/WalletClient.d.ts +0 -73
  24. package/dist/clients/WalletClient.d.ts.map +0 -1
  25. package/dist/clients/WalletClient.js +0 -174
  26. package/dist/clients/X402Client.d.ts +0 -61
  27. package/dist/clients/X402Client.d.ts.map +0 -1
  28. package/dist/clients/X402Client.js +0 -303
  29. package/dist/index.d.ts.map +0 -1
  30. package/dist/types/index.d.ts +0 -220
  31. package/dist/types/index.d.ts.map +0 -1
  32. package/dist/types/index.js +0 -52
  33. package/dist/utils/abis.d.ts +0 -21
  34. package/dist/utils/abis.d.ts.map +0 -1
  35. package/dist/utils/abis.js +0 -134
  36. package/dist/utils/config.d.ts +0 -31
  37. package/dist/utils/config.d.ts.map +0 -1
  38. package/dist/utils/config.js +0 -117
  39. package/dist/utils/format.d.ts +0 -44
  40. package/dist/utils/format.d.ts.map +0 -1
  41. package/dist/utils/format.js +0 -75
package/dist/index.js CHANGED
@@ -45,6 +45,7 @@ __export(index_exports, {
45
45
  InsufficientCreditError: () => InsufficientCreditError,
46
46
  LP_VAULT_ABI: () => LP_VAULT_ABI,
47
47
  MORPHO_CREDIT_ABI: () => MORPHO_CREDIT_ABI,
48
+ MorphoCreditClient: () => MorphoCreditClient,
48
49
  REPUTATION_CREDIT_ABI: () => REPUTATION_CREDIT_ABI,
49
50
  ScoringClient: () => ScoringClient,
50
51
  ScoringRejectedError: () => ScoringRejectedError,
@@ -149,6 +150,7 @@ var AGENT_ACCOUNT_ABI = [
149
150
  "function balanceOf(address token) view returns (uint256)",
150
151
  "function ethBalance() view returns (uint256)",
151
152
  "function execute(address target, uint256 value, bytes data) payable returns (bytes)",
153
+ "function executeBatch(address[] targets, uint256[] values, bytes[] datas) payable returns (bytes[])",
152
154
  "function drawCredit(address creditProvider, uint256 amount)",
153
155
  "function repayCredit(address creditProvider, uint256 amount)",
154
156
  "function fund(address token, uint256 amount)",
@@ -1197,7 +1199,7 @@ function chainIdFromNetwork(network) {
1197
1199
  const m = network.match(/^eip155:(\d+)$/);
1198
1200
  return m ? Number(m[1]) : 1;
1199
1201
  }
1200
- var X402Client = class {
1202
+ var _X402Client = class _X402Client {
1201
1203
  constructor(config) {
1202
1204
  this.config = config;
1203
1205
  const provider = new import_ethers4.ethers.JsonRpcProvider(config.rpcUrl);
@@ -1246,6 +1248,9 @@ var X402Client = class {
1246
1248
  console.log(` amount : ${requirements.amount} (atomic)`);
1247
1249
  console.log(` asset : ${requirements.asset}`);
1248
1250
  console.log(` payTo : ${requirements.payTo}`);
1251
+ if (this.config.autoDraw && this.config.accountAddress && this.config.morphoCreditAddress) {
1252
+ await this.ensureBalance(BigInt(requirements.amount));
1253
+ }
1249
1254
  console.log(" [3/4] Signing EIP-3009 transferWithAuthorization\u2026");
1250
1255
  const paymentPayload = await this.buildPaymentPayload(requirements, resource, url);
1251
1256
  const paymentB64 = Buffer.from(JSON.stringify(paymentPayload)).toString("base64");
@@ -1406,6 +1411,43 @@ var X402Client = class {
1406
1411
  }
1407
1412
  };
1408
1413
  }
1414
+ async ensureBalance(requiredAmount) {
1415
+ const accountAddr = this.config.accountAddress;
1416
+ const morphoAddr = this.config.morphoCreditAddress;
1417
+ const provider = this.wallet.provider;
1418
+ const usdcAddr = USDC_DOMAINS["eip155:8453"]?.address || USDC_DOMAINS["eip155:1"].address;
1419
+ const usdc = new import_ethers4.ethers.Contract(usdcAddr, _X402Client.ERC20_BALANCE_ABI, provider);
1420
+ const balance = await usdc.balanceOf(accountAddr);
1421
+ const needed = requiredAmount + requiredAmount / 10n;
1422
+ if (balance >= needed) return;
1423
+ const deficit = needed - balance;
1424
+ const minDraw = import_ethers4.ethers.parseUnits("10", 6);
1425
+ const drawAmount = deficit > minDraw ? deficit : minDraw;
1426
+ console.log(` [auto-draw] USDC balance $${import_ethers4.ethers.formatUnits(balance, 6)} < needed $${import_ethers4.ethers.formatUnits(needed, 6)}`);
1427
+ const morpho = new import_ethers4.ethers.Contract(morphoAddr, _X402Client.MORPHO_DRAW_ABI, provider);
1428
+ let collateralAddr = null;
1429
+ for (const addr of _X402Client.AUTO_DRAW_COLLATERALS) {
1430
+ try {
1431
+ const pos = await morpho.getPosition(accountAddr, addr);
1432
+ if (pos.collateralAmount > 0n) {
1433
+ collateralAddr = addr;
1434
+ break;
1435
+ }
1436
+ } catch {
1437
+ continue;
1438
+ }
1439
+ }
1440
+ if (!collateralAddr) {
1441
+ throw new Error("autoDraw failed: no collateral deposited in Morpho. Deposit collateral first.");
1442
+ }
1443
+ const account = new import_ethers4.ethers.Contract(accountAddr, _X402Client.AGENT_ACCOUNT_EXEC_ABI, this.wallet);
1444
+ const morphoIface = new import_ethers4.ethers.Interface(_X402Client.MORPHO_DRAW_ABI);
1445
+ const calldata = morphoIface.encodeFunctionData("drawWithCollateral", [collateralAddr, drawAmount]);
1446
+ console.log(` [auto-draw] Borrowing $${import_ethers4.ethers.formatUnits(drawAmount, 6)} from Morpho...`);
1447
+ const tx = await account.execute(morphoAddr, 0, calldata);
1448
+ await tx.wait();
1449
+ console.log(` [auto-draw] \u2713 Borrowed (tx: ${tx.hash.slice(0, 14)}\u2026)`);
1450
+ }
1409
1451
  // ──────────── Risk check via our backend ────────────
1410
1452
  async riskCheck(paymentPayload, reqs) {
1411
1453
  try {
@@ -1437,17 +1479,417 @@ var X402Client = class {
1437
1479
  }
1438
1480
  }
1439
1481
  };
1482
+ // ──────────── Auto-draw (Flow 9) ────────────
1483
+ //
1484
+ // When autoDraw is enabled and the AgentAccount has insufficient USDC,
1485
+ // automatically borrow from Morpho credit line to cover the payment.
1486
+ _X402Client.MORPHO_DRAW_ABI = [
1487
+ "function drawWithCollateral(address collateralToken, uint256 amount)",
1488
+ "function getPosition(address account, address collateralToken) view returns (tuple(uint256 collateralAmount, uint256 borrowedAmount, uint256 borrowShares, bool isActive))"
1489
+ ];
1490
+ _X402Client.AGENT_ACCOUNT_EXEC_ABI = [
1491
+ "function execute(address target, uint256 value, bytes data) payable returns (bytes)"
1492
+ ];
1493
+ _X402Client.ERC20_BALANCE_ABI = [
1494
+ "function balanceOf(address) view returns (uint256)"
1495
+ ];
1496
+ _X402Client.AUTO_DRAW_COLLATERALS = [
1497
+ "0x4200000000000000000000000000000000000006",
1498
+ // WETH
1499
+ "0xc1CBa3fCea344f92D9239c08C0568f6F2F0ee452",
1500
+ // wstETH
1501
+ "0x2Ae3F1Ec7F1F5012CFEab0185bfc7aa3cf0DEc22"
1502
+ // cbETH
1503
+ ];
1504
+ var X402Client = _X402Client;
1440
1505
 
1441
- // src/clients/WalletClient.ts
1506
+ // src/clients/MorphoCreditClient.ts
1442
1507
  var import_ethers5 = require("ethers");
1508
+ var BASE_COLLATERALS = {
1509
+ WETH: { symbol: "WETH", address: "0x4200000000000000000000000000000000000006", decimals: 18 },
1510
+ wstETH: { symbol: "wstETH", address: "0xc1CBa3fCea344f92D9239c08C0568f6F2F0ee452", decimals: 18 },
1511
+ cbETH: { symbol: "cbETH", address: "0x2Ae3F1Ec7F1F5012CFEab0185bfc7aa3cf0DEc22", decimals: 18 }
1512
+ };
1513
+ var MorphoCreditClient = class {
1514
+ constructor(config, collaterals) {
1515
+ // ── Batch helper ──
1516
+ this.morphoIface = new import_ethers5.ethers.Interface(MORPHO_CREDIT_ABI);
1517
+ this.erc20Iface = new import_ethers5.ethers.Interface(ERC20_ABI);
1518
+ this.config = config;
1519
+ const provider = new import_ethers5.ethers.JsonRpcProvider(config.rpcUrl);
1520
+ this.signer = new import_ethers5.ethers.Wallet(config.privateKey, provider);
1521
+ this.morpho = new import_ethers5.Contract(config.contracts.morphoCredit, MORPHO_CREDIT_ABI, this.signer);
1522
+ this.factory = new import_ethers5.Contract(config.contracts.accountFactory, ACCOUNT_FACTORY_ABI, this.signer);
1523
+ this.collaterals = collaterals || BASE_COLLATERALS;
1524
+ }
1525
+ // ── Helpers ──
1526
+ resolveToken(tokenSymbol) {
1527
+ const token = this.collaterals[tokenSymbol];
1528
+ if (!token) {
1529
+ throw new Error(`Unsupported collateral token: ${tokenSymbol}. Supported: ${Object.keys(this.collaterals).join(", ")}`);
1530
+ }
1531
+ return token;
1532
+ }
1533
+ /**
1534
+ * Get the AgentAccount address for the configured agentId.
1535
+ */
1536
+ async getAccountAddress() {
1537
+ if (this.accountAddress) return this.accountAddress;
1538
+ const addr = await this.factory.getAccount(this.config.agentId.toString());
1539
+ if (addr === import_ethers5.ethers.ZeroAddress) {
1540
+ throw new Error("No AgentAccount found. Register first.");
1541
+ }
1542
+ this.accountAddress = addr;
1543
+ return addr;
1544
+ }
1545
+ /**
1546
+ * Get the AgentAccount address for any agentId.
1547
+ */
1548
+ async getAccountForAgent(agentId) {
1549
+ const addr = await this.factory.getAccount(agentId.toString());
1550
+ if (addr === import_ethers5.ethers.ZeroAddress) {
1551
+ throw new Error(`No AgentAccount for agent #${agentId}`);
1552
+ }
1553
+ return addr;
1554
+ }
1555
+ async ensureCreditProvider(accountAddr) {
1556
+ const account = new import_ethers5.Contract(accountAddr, AGENT_ACCOUNT_ABI, this.signer);
1557
+ try {
1558
+ const tx = await account.approveCreditProvider(this.config.contracts.morphoCredit);
1559
+ await tx.wait();
1560
+ } catch {
1561
+ }
1562
+ }
1563
+ /**
1564
+ * Approve ERC-20 token from EOA → MorphoCredit, then deposit for account.
1565
+ * This is 2 EOA txs (approve + depositCollateralFor) — cannot be batched
1566
+ * because both are called from EOA, not from AgentAccount.
1567
+ */
1568
+ async approveAndDeposit(accountAddr, tokenInfo, amount) {
1569
+ const token = new import_ethers5.Contract(tokenInfo.address, ERC20_ABI, this.signer);
1570
+ const balance = await token.balanceOf(this.signer.address);
1571
+ if (balance < amount) {
1572
+ throw new Error(
1573
+ `Insufficient ${tokenInfo.symbol}: have ${import_ethers5.ethers.formatUnits(balance, tokenInfo.decimals)}, need ${import_ethers5.ethers.formatUnits(amount, tokenInfo.decimals)}`
1574
+ );
1575
+ }
1576
+ const approveTx = await token.approve(this.config.contracts.morphoCredit, amount);
1577
+ await approveTx.wait();
1578
+ const depositTx = await this.morpho.depositCollateralFor(accountAddr, tokenInfo.address, amount);
1579
+ await depositTx.wait();
1580
+ return depositTx.hash;
1581
+ }
1582
+ /**
1583
+ * Execute multiple calls via AgentAccount.executeBatch() in a single tx.
1584
+ * Each call is { target, value, data }.
1585
+ */
1586
+ async batch(accountAddr, calls) {
1587
+ const account = new import_ethers5.Contract(accountAddr, AGENT_ACCOUNT_ABI, this.signer);
1588
+ const tx = await account.executeBatch(
1589
+ calls.map((c) => c.target),
1590
+ calls.map((c) => c.value),
1591
+ calls.map((c) => c.data)
1592
+ );
1593
+ await tx.wait();
1594
+ return tx.hash;
1595
+ }
1596
+ // ══════════════════════════════════════════
1597
+ // Flow 3: Deposit collateral only
1598
+ // ══════════════════════════════════════════
1599
+ /**
1600
+ * Deposit collateral from EOA into Morpho for own AgentAccount.
1601
+ * Does NOT borrow — use `borrow()` or `depositAndBorrow()` for that.
1602
+ *
1603
+ * @param tokenSymbol - Collateral token (WETH, wstETH, cbETH)
1604
+ * @param amount - Human-readable amount (e.g. "0.05")
1605
+ */
1606
+ async deposit(tokenSymbol, amount) {
1607
+ const tokenInfo = this.resolveToken(tokenSymbol);
1608
+ const amountWei = import_ethers5.ethers.parseUnits(amount, tokenInfo.decimals);
1609
+ const accountAddr = await this.getAccountAddress();
1610
+ const txHash = await this.approveAndDeposit(accountAddr, tokenInfo, amountWei);
1611
+ await this.ensureCreditProvider(accountAddr);
1612
+ const pos = await this.morpho.getPosition(accountAddr, tokenInfo.address);
1613
+ return {
1614
+ tx: txHash,
1615
+ amount: amountWei,
1616
+ token: tokenSymbol,
1617
+ agentAccount: accountAddr,
1618
+ totalCollateral: pos.collateralAmount
1619
+ };
1620
+ }
1621
+ // ══════════════════════════════════════════
1622
+ // Flow 2: Deposit + borrow in one call
1623
+ // ══════════════════════════════════════════
1624
+ /**
1625
+ * Deposit collateral AND borrow USDC in a single SDK call.
1626
+ * USDC lands in the AgentAccount.
1627
+ *
1628
+ * @param tokenSymbol - Collateral token (WETH, wstETH, cbETH)
1629
+ * @param collateralAmount - Human-readable collateral amount (e.g. "0.05")
1630
+ * @param borrowAmount - Human-readable USDC amount to borrow (e.g. "50")
1631
+ */
1632
+ async depositAndBorrow(tokenSymbol, collateralAmount, borrowAmount) {
1633
+ const tokenInfo = this.resolveToken(tokenSymbol);
1634
+ const collateralWei = import_ethers5.ethers.parseUnits(collateralAmount, tokenInfo.decimals);
1635
+ const borrowWei = import_ethers5.ethers.parseUnits(borrowAmount, 6);
1636
+ const accountAddr = await this.getAccountAddress();
1637
+ const depositTxHash = await this.approveAndDeposit(accountAddr, tokenInfo, collateralWei);
1638
+ await this.ensureCreditProvider(accountAddr);
1639
+ const account = new import_ethers5.Contract(accountAddr, AGENT_ACCOUNT_ABI, this.signer);
1640
+ const calldata = this.morphoIface.encodeFunctionData("drawWithCollateral", [tokenInfo.address, borrowWei]);
1641
+ const borrowTx = await account.execute(this.config.contracts.morphoCredit, 0, calldata);
1642
+ await borrowTx.wait();
1643
+ const totalDebt = await this.morpho.getTotalDebt(accountAddr);
1644
+ return {
1645
+ depositTx: depositTxHash,
1646
+ borrowTx: borrowTx.hash,
1647
+ collateral: { amount: collateralWei, token: tokenSymbol },
1648
+ borrowed: borrowWei,
1649
+ agentAccount: accountAddr,
1650
+ totalDebt
1651
+ };
1652
+ }
1653
+ // ══════════════════════════════════════════
1654
+ // Flow 8: Borrow against existing collateral
1655
+ // ══════════════════════════════════════════
1656
+ /**
1657
+ * Borrow USDC against already-deposited collateral.
1658
+ * Auto-detects which collateral token has a position.
1659
+ * USDC lands in AgentAccount — ready for x402 payments.
1660
+ *
1661
+ * @param amount - Human-readable USDC amount (e.g. "100")
1662
+ */
1663
+ async borrow(amount) {
1664
+ const borrowWei = import_ethers5.ethers.parseUnits(amount, 6);
1665
+ const accountAddr = await this.getAccountAddress();
1666
+ let activeToken = null;
1667
+ for (const info of Object.values(this.collaterals)) {
1668
+ const pos = await this.morpho.getPosition(accountAddr, info.address);
1669
+ if (pos.collateralAmount > 0n) {
1670
+ activeToken = info;
1671
+ break;
1672
+ }
1673
+ }
1674
+ if (!activeToken) {
1675
+ throw new Error("No collateral deposited. Use deposit() or depositAndBorrow() first.");
1676
+ }
1677
+ await this.ensureCreditProvider(accountAddr);
1678
+ const account = new import_ethers5.Contract(accountAddr, AGENT_ACCOUNT_ABI, this.signer);
1679
+ const calldata = this.morphoIface.encodeFunctionData("drawWithCollateral", [activeToken.address, borrowWei]);
1680
+ const tx = await account.execute(this.config.contracts.morphoCredit, 0, calldata);
1681
+ await tx.wait();
1682
+ const totalDebt = await this.morpho.getTotalDebt(accountAddr);
1683
+ return {
1684
+ tx: tx.hash,
1685
+ amount: borrowWei,
1686
+ agentAccount: accountAddr,
1687
+ totalDebt,
1688
+ collateralToken: activeToken.symbol
1689
+ };
1690
+ }
1691
+ // ══════════════════════════════════════════
1692
+ // Flows 4-7: Sponsor (deposit for another agent)
1693
+ // ══════════════════════════════════════════
1694
+ /**
1695
+ * Deposit collateral for another agent. Caller pays from their wallet.
1696
+ * Optionally borrow USDC for the agent (only works if caller owns the AgentAccount).
1697
+ *
1698
+ * Supports both agentId lookup and direct address.
1699
+ *
1700
+ * @param target - `{ agentId: "17676" }` or `{ address: "0x..." }`
1701
+ * @param tokenSymbol - Collateral token
1702
+ * @param amount - Human-readable collateral amount
1703
+ * @param borrowAmount - Optional: USDC to borrow (only if caller is owner)
1704
+ */
1705
+ async sponsor(target, tokenSymbol, amount, borrowAmount) {
1706
+ const tokenInfo = this.resolveToken(tokenSymbol);
1707
+ const collateralWei = import_ethers5.ethers.parseUnits(amount, tokenInfo.decimals);
1708
+ let accountAddr;
1709
+ let targetAgentId;
1710
+ if ("agentId" in target) {
1711
+ targetAgentId = target.agentId.toString();
1712
+ accountAddr = await this.getAccountForAgent(target.agentId);
1713
+ } else {
1714
+ accountAddr = target.address;
1715
+ }
1716
+ const depositTxHash = await this.approveAndDeposit(accountAddr, tokenInfo, collateralWei);
1717
+ const result = {
1718
+ depositTx: depositTxHash,
1719
+ targetAccount: accountAddr,
1720
+ targetAgentId,
1721
+ collateral: { amount: collateralWei, token: tokenSymbol },
1722
+ totalCollateral: 0n,
1723
+ totalDebt: 0n
1724
+ };
1725
+ if (borrowAmount) {
1726
+ const borrowWei = import_ethers5.ethers.parseUnits(borrowAmount, 6);
1727
+ try {
1728
+ await this.ensureCreditProvider(accountAddr);
1729
+ const account = new import_ethers5.Contract(accountAddr, AGENT_ACCOUNT_ABI, this.signer);
1730
+ const calldata = this.morphoIface.encodeFunctionData("drawWithCollateral", [tokenInfo.address, borrowWei]);
1731
+ const tx = await account.execute(this.config.contracts.morphoCredit, 0, calldata);
1732
+ await tx.wait();
1733
+ result.borrowTx = tx.hash;
1734
+ result.borrowed = borrowWei;
1735
+ } catch (e) {
1736
+ throw new Error(`Borrow failed (caller may not own this AgentAccount): ${e.message}`);
1737
+ }
1738
+ }
1739
+ const pos = await this.morpho.getPosition(accountAddr, tokenInfo.address);
1740
+ result.totalCollateral = pos.collateralAmount;
1741
+ result.totalDebt = pos.borrowedAmount;
1742
+ return result;
1743
+ }
1744
+ // ══════════════════════════════════════════
1745
+ // Repay & Withdraw
1746
+ // ══════════════════════════════════════════
1747
+ /**
1748
+ * Repay borrowed USDC from AgentAccount back to Morpho.
1749
+ *
1750
+ * @param amount - Human-readable USDC amount (e.g. "50")
1751
+ */
1752
+ async repay(amount) {
1753
+ const amountWei = import_ethers5.ethers.parseUnits(amount, 6);
1754
+ const accountAddr = await this.getAccountAddress();
1755
+ let collateralAddr = null;
1756
+ for (const info of Object.values(this.collaterals)) {
1757
+ const pos = await this.morpho.getPosition(accountAddr, info.address);
1758
+ if (pos.borrowedAmount > 0n) {
1759
+ collateralAddr = info.address;
1760
+ break;
1761
+ }
1762
+ }
1763
+ if (!collateralAddr) throw new Error("No Morpho debt to repay.");
1764
+ const usdc = new import_ethers5.Contract(this.config.contracts.usdc, ERC20_ABI, this.signer.provider);
1765
+ const balance = await usdc.balanceOf(accountAddr);
1766
+ if (balance < amountWei) {
1767
+ throw new Error(`Insufficient USDC in AgentAccount: $${import_ethers5.ethers.formatUnits(balance, 6)}`);
1768
+ }
1769
+ const txHash = await this.batch(accountAddr, [
1770
+ {
1771
+ target: this.config.contracts.usdc,
1772
+ value: 0n,
1773
+ data: this.erc20Iface.encodeFunctionData("approve", [this.config.contracts.morphoCredit, amountWei])
1774
+ },
1775
+ {
1776
+ target: this.config.contracts.morphoCredit,
1777
+ value: 0n,
1778
+ data: this.morphoIface.encodeFunctionData("repayWithCollateral", [collateralAddr, amountWei])
1779
+ }
1780
+ ]);
1781
+ const totalDebt = await this.morpho.getTotalDebt(accountAddr);
1782
+ return { tx: txHash, amount: amountWei, remainingDebt: totalDebt };
1783
+ }
1784
+ /**
1785
+ * Withdraw collateral from Morpho back to EOA.
1786
+ *
1787
+ * @param tokenSymbol - Collateral token
1788
+ * @param amount - Human-readable amount or "all"
1789
+ */
1790
+ async withdraw(tokenSymbol, amount) {
1791
+ const tokenInfo = this.resolveToken(tokenSymbol);
1792
+ const accountAddr = await this.getAccountAddress();
1793
+ const pos = await this.morpho.getPosition(accountAddr, tokenInfo.address);
1794
+ if (pos.collateralAmount === 0n) {
1795
+ throw new Error(`No ${tokenSymbol} collateral deposited.`);
1796
+ }
1797
+ const withdrawAmount = amount.toLowerCase() === "all" ? pos.collateralAmount : import_ethers5.ethers.parseUnits(amount, tokenInfo.decimals);
1798
+ if (withdrawAmount > pos.collateralAmount) {
1799
+ throw new Error(
1800
+ `Cannot withdraw more than deposited: max ${import_ethers5.ethers.formatUnits(pos.collateralAmount, tokenInfo.decimals)} ${tokenSymbol}`
1801
+ );
1802
+ }
1803
+ const txHash = await this.batch(accountAddr, [
1804
+ {
1805
+ target: this.config.contracts.morphoCredit,
1806
+ value: 0n,
1807
+ data: this.morphoIface.encodeFunctionData("withdrawCollateral", [tokenInfo.address, withdrawAmount])
1808
+ },
1809
+ {
1810
+ target: tokenInfo.address,
1811
+ value: 0n,
1812
+ data: this.erc20Iface.encodeFunctionData("transfer", [this.signer.address, withdrawAmount])
1813
+ }
1814
+ ]);
1815
+ const newPos = await this.morpho.getPosition(accountAddr, tokenInfo.address);
1816
+ return {
1817
+ tx: txHash,
1818
+ amount: withdrawAmount,
1819
+ token: tokenSymbol,
1820
+ destination: this.signer.address,
1821
+ remainingCollateral: newPos.collateralAmount
1822
+ };
1823
+ }
1824
+ // ══════════════════════════════════════════
1825
+ // View methods
1826
+ // ══════════════════════════════════════════
1827
+ /**
1828
+ * Get position for a specific collateral token.
1829
+ */
1830
+ async getPosition(tokenSymbol) {
1831
+ const tokenInfo = this.resolveToken(tokenSymbol);
1832
+ const accountAddr = await this.getAccountAddress();
1833
+ const pos = await this.morpho.getPosition(accountAddr, tokenInfo.address);
1834
+ return {
1835
+ token: tokenSymbol,
1836
+ collateralAmount: pos.collateralAmount,
1837
+ borrowedAmount: pos.borrowedAmount,
1838
+ borrowShares: pos.borrowShares,
1839
+ isActive: pos.isActive
1840
+ };
1841
+ }
1842
+ /**
1843
+ * Get all active positions across all collateral tokens.
1844
+ */
1845
+ async getAllPositions() {
1846
+ const accountAddr = await this.getAccountAddress();
1847
+ const positions = [];
1848
+ for (const [symbol, info] of Object.entries(this.collaterals)) {
1849
+ const pos = await this.morpho.getPosition(accountAddr, info.address);
1850
+ if (pos.isActive || pos.collateralAmount > 0n || pos.borrowedAmount > 0n) {
1851
+ positions.push({
1852
+ token: symbol,
1853
+ collateralAmount: pos.collateralAmount,
1854
+ borrowedAmount: pos.borrowedAmount,
1855
+ borrowShares: pos.borrowShares,
1856
+ isActive: pos.isActive
1857
+ });
1858
+ }
1859
+ }
1860
+ return positions;
1861
+ }
1862
+ /**
1863
+ * Get total debt across all positions.
1864
+ */
1865
+ async getTotalDebt() {
1866
+ const accountAddr = await this.getAccountAddress();
1867
+ return this.morpho.getTotalDebt(accountAddr);
1868
+ }
1869
+ /**
1870
+ * Get USDC balance in the AgentAccount.
1871
+ */
1872
+ async getAccountUSDC() {
1873
+ const accountAddr = await this.getAccountAddress();
1874
+ const usdc = new import_ethers5.Contract(this.config.contracts.usdc, ERC20_ABI, this.signer.provider);
1875
+ return usdc.balanceOf(accountAddr);
1876
+ }
1877
+ /** Get the wallet (signer) address */
1878
+ getAddress() {
1879
+ return this.signer.address;
1880
+ }
1881
+ };
1882
+
1883
+ // src/clients/WalletClient.ts
1884
+ var import_ethers6 = require("ethers");
1443
1885
  var WalletClient = class {
1444
1886
  constructor(config) {
1445
1887
  this.privateKey = null;
1446
1888
  this.factoryAddress = config.factoryAddress;
1447
- this.usdcAddress = config.usdcAddress || import_ethers5.ethers.ZeroAddress;
1889
+ this.usdcAddress = config.usdcAddress || import_ethers6.ethers.ZeroAddress;
1448
1890
  this.chainId = config.chainId;
1449
1891
  this.rpcUrl = config.rpcUrl;
1450
- this.provider = new import_ethers5.ethers.JsonRpcProvider(config.rpcUrl);
1892
+ this.provider = new import_ethers6.ethers.JsonRpcProvider(config.rpcUrl);
1451
1893
  this.privateKey = config.privateKey || null;
1452
1894
  }
1453
1895
  /**
@@ -1457,20 +1899,20 @@ var WalletClient = class {
1457
1899
  if (!this.privateKey) {
1458
1900
  throw new Error("Signer not configured - provide privateKey");
1459
1901
  }
1460
- const freshProvider = new import_ethers5.ethers.JsonRpcProvider(this.rpcUrl);
1461
- return new import_ethers5.Wallet(this.privateKey, freshProvider);
1902
+ const freshProvider = new import_ethers6.ethers.JsonRpcProvider(this.rpcUrl);
1903
+ return new import_ethers6.Wallet(this.privateKey, freshProvider);
1462
1904
  }
1463
1905
  getFactoryContract() {
1464
1906
  if (this.privateKey) {
1465
- return new import_ethers5.Contract(this.factoryAddress, ACCOUNT_FACTORY_ABI, this.getFreshSigner());
1907
+ return new import_ethers6.Contract(this.factoryAddress, ACCOUNT_FACTORY_ABI, this.getFreshSigner());
1466
1908
  }
1467
- return new import_ethers5.Contract(this.factoryAddress, ACCOUNT_FACTORY_ABI, this.provider);
1909
+ return new import_ethers6.Contract(this.factoryAddress, ACCOUNT_FACTORY_ABI, this.provider);
1468
1910
  }
1469
1911
  getAccountContract(accountAddress) {
1470
1912
  if (this.privateKey) {
1471
- return new import_ethers5.Contract(accountAddress, AGENT_ACCOUNT_ABI, this.getFreshSigner());
1913
+ return new import_ethers6.Contract(accountAddress, AGENT_ACCOUNT_ABI, this.getFreshSigner());
1472
1914
  }
1473
- return new import_ethers5.Contract(accountAddress, AGENT_ACCOUNT_ABI, this.provider);
1915
+ return new import_ethers6.Contract(accountAddress, AGENT_ACCOUNT_ABI, this.provider);
1474
1916
  }
1475
1917
  getChainId() {
1476
1918
  return this.chainId;
@@ -1483,7 +1925,7 @@ var WalletClient = class {
1483
1925
  async getAccount(agentId) {
1484
1926
  const factory = this.getFactoryContract();
1485
1927
  const address = await factory.getAccount(agentId);
1486
- if (address === import_ethers5.ethers.ZeroAddress) {
1928
+ if (address === import_ethers6.ethers.ZeroAddress) {
1487
1929
  return null;
1488
1930
  }
1489
1931
  return address;
@@ -1518,7 +1960,7 @@ var WalletClient = class {
1518
1960
  account.ethBalance()
1519
1961
  ]);
1520
1962
  let usdcBalance = 0n;
1521
- if (this.usdcAddress !== import_ethers5.ethers.ZeroAddress) {
1963
+ if (this.usdcAddress !== import_ethers6.ethers.ZeroAddress) {
1522
1964
  usdcBalance = await account.balanceOf(this.usdcAddress);
1523
1965
  }
1524
1966
  return {
@@ -1530,7 +1972,7 @@ var WalletClient = class {
1530
1972
  };
1531
1973
  }
1532
1974
  async getProviderStatus(accountAddress, creditProvider) {
1533
- const provider = new import_ethers5.Contract(
1975
+ const provider = new import_ethers6.Contract(
1534
1976
  creditProvider,
1535
1977
  CREDIT_PROVIDER_ABI,
1536
1978
  this.provider
@@ -1553,11 +1995,11 @@ var WalletClient = class {
1553
1995
  throw new Error("Signer not configured");
1554
1996
  }
1555
1997
  const signer = this.getFreshSigner();
1556
- const token = new import_ethers5.Contract(tokenAddress, ERC20_ABI, signer);
1998
+ const token = new import_ethers6.Contract(tokenAddress, ERC20_ABI, signer);
1557
1999
  const approveTx = await token.approve(accountAddress, amount);
1558
2000
  await approveTx.wait();
1559
2001
  const signer2 = this.getFreshSigner();
1560
- const account = new import_ethers5.Contract(accountAddress, AGENT_ACCOUNT_ABI, signer2);
2002
+ const account = new import_ethers6.Contract(accountAddress, AGENT_ACCOUNT_ABI, signer2);
1561
2003
  const tx = await account.fund(tokenAddress, amount);
1562
2004
  const receipt = await tx.wait();
1563
2005
  return receipt.hash;
@@ -1603,8 +2045,8 @@ var WalletClient = class {
1603
2045
  }
1604
2046
  // ============ Utility ============
1605
2047
  generatePaymentMessageHash(accountAddress, recipient, amount, nonce, deadline, chainId) {
1606
- return import_ethers5.ethers.keccak256(
1607
- import_ethers5.ethers.AbiCoder.defaultAbiCoder().encode(
2048
+ return import_ethers6.ethers.keccak256(
2049
+ import_ethers6.ethers.AbiCoder.defaultAbiCoder().encode(
1608
2050
  ["address", "uint256", "uint256", "uint256", "uint256", "address"],
1609
2051
  [recipient, amount, nonce, deadline, chainId, accountAddress]
1610
2052
  )
@@ -1671,6 +2113,7 @@ function rateToBps(rate) {
1671
2113
  InsufficientCreditError,
1672
2114
  LP_VAULT_ABI,
1673
2115
  MORPHO_CREDIT_ABI,
2116
+ MorphoCreditClient,
1674
2117
  REPUTATION_CREDIT_ABI,
1675
2118
  ScoringClient,
1676
2119
  ScoringRejectedError,