@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.
- package/dist/cli.js +295 -5
- package/dist/index.d.mts +205 -1
- package/dist/index.d.ts +205 -1
- package/dist/index.js +460 -17
- package/dist/index.mjs +458 -16
- package/package.json +1 -1
- package/dist/cli.d.mts +0 -2
- package/dist/cli.d.ts +0 -19
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.mjs +0 -0
- package/dist/clients/AgentIdentityClient.d.ts +0 -163
- package/dist/clients/AgentIdentityClient.d.ts.map +0 -1
- package/dist/clients/AgentIdentityClient.js +0 -293
- package/dist/clients/AgetherClient.d.ts +0 -101
- package/dist/clients/AgetherClient.d.ts.map +0 -1
- package/dist/clients/AgetherClient.js +0 -272
- package/dist/clients/ScoringClient.d.ts +0 -138
- package/dist/clients/ScoringClient.d.ts.map +0 -1
- package/dist/clients/ScoringClient.js +0 -135
- package/dist/clients/VaultClient.d.ts +0 -62
- package/dist/clients/VaultClient.d.ts.map +0 -1
- package/dist/clients/VaultClient.js +0 -157
- package/dist/clients/WalletClient.d.ts +0 -73
- package/dist/clients/WalletClient.d.ts.map +0 -1
- package/dist/clients/WalletClient.js +0 -174
- package/dist/clients/X402Client.d.ts +0 -61
- package/dist/clients/X402Client.d.ts.map +0 -1
- package/dist/clients/X402Client.js +0 -303
- package/dist/index.d.ts.map +0 -1
- package/dist/types/index.d.ts +0 -220
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.js +0 -52
- package/dist/utils/abis.d.ts +0 -21
- package/dist/utils/abis.d.ts.map +0 -1
- package/dist/utils/abis.js +0 -134
- package/dist/utils/config.d.ts +0 -31
- package/dist/utils/config.d.ts.map +0 -1
- package/dist/utils/config.js +0 -117
- package/dist/utils/format.d.ts +0 -44
- package/dist/utils/format.d.ts.map +0 -1
- 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
|
|
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/
|
|
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 ||
|
|
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
|
|
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
|
|
1461
|
-
return new
|
|
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
|
|
1907
|
+
return new import_ethers6.Contract(this.factoryAddress, ACCOUNT_FACTORY_ABI, this.getFreshSigner());
|
|
1466
1908
|
}
|
|
1467
|
-
return new
|
|
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
|
|
1913
|
+
return new import_ethers6.Contract(accountAddress, AGENT_ACCOUNT_ABI, this.getFreshSigner());
|
|
1472
1914
|
}
|
|
1473
|
-
return new
|
|
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 ===
|
|
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 !==
|
|
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
|
|
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
|
|
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
|
|
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
|
|
1607
|
-
|
|
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,
|