@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.mjs
CHANGED
|
@@ -79,6 +79,7 @@ var AGENT_ACCOUNT_ABI = [
|
|
|
79
79
|
"function balanceOf(address token) view returns (uint256)",
|
|
80
80
|
"function ethBalance() view returns (uint256)",
|
|
81
81
|
"function execute(address target, uint256 value, bytes data) payable returns (bytes)",
|
|
82
|
+
"function executeBatch(address[] targets, uint256[] values, bytes[] datas) payable returns (bytes[])",
|
|
82
83
|
"function drawCredit(address creditProvider, uint256 amount)",
|
|
83
84
|
"function repayCredit(address creditProvider, uint256 amount)",
|
|
84
85
|
"function fund(address token, uint256 amount)",
|
|
@@ -1127,7 +1128,7 @@ function chainIdFromNetwork(network) {
|
|
|
1127
1128
|
const m = network.match(/^eip155:(\d+)$/);
|
|
1128
1129
|
return m ? Number(m[1]) : 1;
|
|
1129
1130
|
}
|
|
1130
|
-
var
|
|
1131
|
+
var _X402Client = class _X402Client {
|
|
1131
1132
|
constructor(config) {
|
|
1132
1133
|
this.config = config;
|
|
1133
1134
|
const provider = new ethers3.JsonRpcProvider(config.rpcUrl);
|
|
@@ -1176,6 +1177,9 @@ var X402Client = class {
|
|
|
1176
1177
|
console.log(` amount : ${requirements.amount} (atomic)`);
|
|
1177
1178
|
console.log(` asset : ${requirements.asset}`);
|
|
1178
1179
|
console.log(` payTo : ${requirements.payTo}`);
|
|
1180
|
+
if (this.config.autoDraw && this.config.accountAddress && this.config.morphoCreditAddress) {
|
|
1181
|
+
await this.ensureBalance(BigInt(requirements.amount));
|
|
1182
|
+
}
|
|
1179
1183
|
console.log(" [3/4] Signing EIP-3009 transferWithAuthorization\u2026");
|
|
1180
1184
|
const paymentPayload = await this.buildPaymentPayload(requirements, resource, url);
|
|
1181
1185
|
const paymentB64 = Buffer.from(JSON.stringify(paymentPayload)).toString("base64");
|
|
@@ -1336,6 +1340,43 @@ var X402Client = class {
|
|
|
1336
1340
|
}
|
|
1337
1341
|
};
|
|
1338
1342
|
}
|
|
1343
|
+
async ensureBalance(requiredAmount) {
|
|
1344
|
+
const accountAddr = this.config.accountAddress;
|
|
1345
|
+
const morphoAddr = this.config.morphoCreditAddress;
|
|
1346
|
+
const provider = this.wallet.provider;
|
|
1347
|
+
const usdcAddr = USDC_DOMAINS["eip155:8453"]?.address || USDC_DOMAINS["eip155:1"].address;
|
|
1348
|
+
const usdc = new ethers3.Contract(usdcAddr, _X402Client.ERC20_BALANCE_ABI, provider);
|
|
1349
|
+
const balance = await usdc.balanceOf(accountAddr);
|
|
1350
|
+
const needed = requiredAmount + requiredAmount / 10n;
|
|
1351
|
+
if (balance >= needed) return;
|
|
1352
|
+
const deficit = needed - balance;
|
|
1353
|
+
const minDraw = ethers3.parseUnits("10", 6);
|
|
1354
|
+
const drawAmount = deficit > minDraw ? deficit : minDraw;
|
|
1355
|
+
console.log(` [auto-draw] USDC balance $${ethers3.formatUnits(balance, 6)} < needed $${ethers3.formatUnits(needed, 6)}`);
|
|
1356
|
+
const morpho = new ethers3.Contract(morphoAddr, _X402Client.MORPHO_DRAW_ABI, provider);
|
|
1357
|
+
let collateralAddr = null;
|
|
1358
|
+
for (const addr of _X402Client.AUTO_DRAW_COLLATERALS) {
|
|
1359
|
+
try {
|
|
1360
|
+
const pos = await morpho.getPosition(accountAddr, addr);
|
|
1361
|
+
if (pos.collateralAmount > 0n) {
|
|
1362
|
+
collateralAddr = addr;
|
|
1363
|
+
break;
|
|
1364
|
+
}
|
|
1365
|
+
} catch {
|
|
1366
|
+
continue;
|
|
1367
|
+
}
|
|
1368
|
+
}
|
|
1369
|
+
if (!collateralAddr) {
|
|
1370
|
+
throw new Error("autoDraw failed: no collateral deposited in Morpho. Deposit collateral first.");
|
|
1371
|
+
}
|
|
1372
|
+
const account = new ethers3.Contract(accountAddr, _X402Client.AGENT_ACCOUNT_EXEC_ABI, this.wallet);
|
|
1373
|
+
const morphoIface = new ethers3.Interface(_X402Client.MORPHO_DRAW_ABI);
|
|
1374
|
+
const calldata = morphoIface.encodeFunctionData("drawWithCollateral", [collateralAddr, drawAmount]);
|
|
1375
|
+
console.log(` [auto-draw] Borrowing $${ethers3.formatUnits(drawAmount, 6)} from Morpho...`);
|
|
1376
|
+
const tx = await account.execute(morphoAddr, 0, calldata);
|
|
1377
|
+
await tx.wait();
|
|
1378
|
+
console.log(` [auto-draw] \u2713 Borrowed (tx: ${tx.hash.slice(0, 14)}\u2026)`);
|
|
1379
|
+
}
|
|
1339
1380
|
// ──────────── Risk check via our backend ────────────
|
|
1340
1381
|
async riskCheck(paymentPayload, reqs) {
|
|
1341
1382
|
try {
|
|
@@ -1367,17 +1408,417 @@ var X402Client = class {
|
|
|
1367
1408
|
}
|
|
1368
1409
|
}
|
|
1369
1410
|
};
|
|
1411
|
+
// ──────────── Auto-draw (Flow 9) ────────────
|
|
1412
|
+
//
|
|
1413
|
+
// When autoDraw is enabled and the AgentAccount has insufficient USDC,
|
|
1414
|
+
// automatically borrow from Morpho credit line to cover the payment.
|
|
1415
|
+
_X402Client.MORPHO_DRAW_ABI = [
|
|
1416
|
+
"function drawWithCollateral(address collateralToken, uint256 amount)",
|
|
1417
|
+
"function getPosition(address account, address collateralToken) view returns (tuple(uint256 collateralAmount, uint256 borrowedAmount, uint256 borrowShares, bool isActive))"
|
|
1418
|
+
];
|
|
1419
|
+
_X402Client.AGENT_ACCOUNT_EXEC_ABI = [
|
|
1420
|
+
"function execute(address target, uint256 value, bytes data) payable returns (bytes)"
|
|
1421
|
+
];
|
|
1422
|
+
_X402Client.ERC20_BALANCE_ABI = [
|
|
1423
|
+
"function balanceOf(address) view returns (uint256)"
|
|
1424
|
+
];
|
|
1425
|
+
_X402Client.AUTO_DRAW_COLLATERALS = [
|
|
1426
|
+
"0x4200000000000000000000000000000000000006",
|
|
1427
|
+
// WETH
|
|
1428
|
+
"0xc1CBa3fCea344f92D9239c08C0568f6F2F0ee452",
|
|
1429
|
+
// wstETH
|
|
1430
|
+
"0x2Ae3F1Ec7F1F5012CFEab0185bfc7aa3cf0DEc22"
|
|
1431
|
+
// cbETH
|
|
1432
|
+
];
|
|
1433
|
+
var X402Client = _X402Client;
|
|
1434
|
+
|
|
1435
|
+
// src/clients/MorphoCreditClient.ts
|
|
1436
|
+
import { ethers as ethers4, Contract as Contract3 } from "ethers";
|
|
1437
|
+
var BASE_COLLATERALS = {
|
|
1438
|
+
WETH: { symbol: "WETH", address: "0x4200000000000000000000000000000000000006", decimals: 18 },
|
|
1439
|
+
wstETH: { symbol: "wstETH", address: "0xc1CBa3fCea344f92D9239c08C0568f6F2F0ee452", decimals: 18 },
|
|
1440
|
+
cbETH: { symbol: "cbETH", address: "0x2Ae3F1Ec7F1F5012CFEab0185bfc7aa3cf0DEc22", decimals: 18 }
|
|
1441
|
+
};
|
|
1442
|
+
var MorphoCreditClient = class {
|
|
1443
|
+
constructor(config, collaterals) {
|
|
1444
|
+
// ── Batch helper ──
|
|
1445
|
+
this.morphoIface = new ethers4.Interface(MORPHO_CREDIT_ABI);
|
|
1446
|
+
this.erc20Iface = new ethers4.Interface(ERC20_ABI);
|
|
1447
|
+
this.config = config;
|
|
1448
|
+
const provider = new ethers4.JsonRpcProvider(config.rpcUrl);
|
|
1449
|
+
this.signer = new ethers4.Wallet(config.privateKey, provider);
|
|
1450
|
+
this.morpho = new Contract3(config.contracts.morphoCredit, MORPHO_CREDIT_ABI, this.signer);
|
|
1451
|
+
this.factory = new Contract3(config.contracts.accountFactory, ACCOUNT_FACTORY_ABI, this.signer);
|
|
1452
|
+
this.collaterals = collaterals || BASE_COLLATERALS;
|
|
1453
|
+
}
|
|
1454
|
+
// ── Helpers ──
|
|
1455
|
+
resolveToken(tokenSymbol) {
|
|
1456
|
+
const token = this.collaterals[tokenSymbol];
|
|
1457
|
+
if (!token) {
|
|
1458
|
+
throw new Error(`Unsupported collateral token: ${tokenSymbol}. Supported: ${Object.keys(this.collaterals).join(", ")}`);
|
|
1459
|
+
}
|
|
1460
|
+
return token;
|
|
1461
|
+
}
|
|
1462
|
+
/**
|
|
1463
|
+
* Get the AgentAccount address for the configured agentId.
|
|
1464
|
+
*/
|
|
1465
|
+
async getAccountAddress() {
|
|
1466
|
+
if (this.accountAddress) return this.accountAddress;
|
|
1467
|
+
const addr = await this.factory.getAccount(this.config.agentId.toString());
|
|
1468
|
+
if (addr === ethers4.ZeroAddress) {
|
|
1469
|
+
throw new Error("No AgentAccount found. Register first.");
|
|
1470
|
+
}
|
|
1471
|
+
this.accountAddress = addr;
|
|
1472
|
+
return addr;
|
|
1473
|
+
}
|
|
1474
|
+
/**
|
|
1475
|
+
* Get the AgentAccount address for any agentId.
|
|
1476
|
+
*/
|
|
1477
|
+
async getAccountForAgent(agentId) {
|
|
1478
|
+
const addr = await this.factory.getAccount(agentId.toString());
|
|
1479
|
+
if (addr === ethers4.ZeroAddress) {
|
|
1480
|
+
throw new Error(`No AgentAccount for agent #${agentId}`);
|
|
1481
|
+
}
|
|
1482
|
+
return addr;
|
|
1483
|
+
}
|
|
1484
|
+
async ensureCreditProvider(accountAddr) {
|
|
1485
|
+
const account = new Contract3(accountAddr, AGENT_ACCOUNT_ABI, this.signer);
|
|
1486
|
+
try {
|
|
1487
|
+
const tx = await account.approveCreditProvider(this.config.contracts.morphoCredit);
|
|
1488
|
+
await tx.wait();
|
|
1489
|
+
} catch {
|
|
1490
|
+
}
|
|
1491
|
+
}
|
|
1492
|
+
/**
|
|
1493
|
+
* Approve ERC-20 token from EOA → MorphoCredit, then deposit for account.
|
|
1494
|
+
* This is 2 EOA txs (approve + depositCollateralFor) — cannot be batched
|
|
1495
|
+
* because both are called from EOA, not from AgentAccount.
|
|
1496
|
+
*/
|
|
1497
|
+
async approveAndDeposit(accountAddr, tokenInfo, amount) {
|
|
1498
|
+
const token = new Contract3(tokenInfo.address, ERC20_ABI, this.signer);
|
|
1499
|
+
const balance = await token.balanceOf(this.signer.address);
|
|
1500
|
+
if (balance < amount) {
|
|
1501
|
+
throw new Error(
|
|
1502
|
+
`Insufficient ${tokenInfo.symbol}: have ${ethers4.formatUnits(balance, tokenInfo.decimals)}, need ${ethers4.formatUnits(amount, tokenInfo.decimals)}`
|
|
1503
|
+
);
|
|
1504
|
+
}
|
|
1505
|
+
const approveTx = await token.approve(this.config.contracts.morphoCredit, amount);
|
|
1506
|
+
await approveTx.wait();
|
|
1507
|
+
const depositTx = await this.morpho.depositCollateralFor(accountAddr, tokenInfo.address, amount);
|
|
1508
|
+
await depositTx.wait();
|
|
1509
|
+
return depositTx.hash;
|
|
1510
|
+
}
|
|
1511
|
+
/**
|
|
1512
|
+
* Execute multiple calls via AgentAccount.executeBatch() in a single tx.
|
|
1513
|
+
* Each call is { target, value, data }.
|
|
1514
|
+
*/
|
|
1515
|
+
async batch(accountAddr, calls) {
|
|
1516
|
+
const account = new Contract3(accountAddr, AGENT_ACCOUNT_ABI, this.signer);
|
|
1517
|
+
const tx = await account.executeBatch(
|
|
1518
|
+
calls.map((c) => c.target),
|
|
1519
|
+
calls.map((c) => c.value),
|
|
1520
|
+
calls.map((c) => c.data)
|
|
1521
|
+
);
|
|
1522
|
+
await tx.wait();
|
|
1523
|
+
return tx.hash;
|
|
1524
|
+
}
|
|
1525
|
+
// ══════════════════════════════════════════
|
|
1526
|
+
// Flow 3: Deposit collateral only
|
|
1527
|
+
// ══════════════════════════════════════════
|
|
1528
|
+
/**
|
|
1529
|
+
* Deposit collateral from EOA into Morpho for own AgentAccount.
|
|
1530
|
+
* Does NOT borrow — use `borrow()` or `depositAndBorrow()` for that.
|
|
1531
|
+
*
|
|
1532
|
+
* @param tokenSymbol - Collateral token (WETH, wstETH, cbETH)
|
|
1533
|
+
* @param amount - Human-readable amount (e.g. "0.05")
|
|
1534
|
+
*/
|
|
1535
|
+
async deposit(tokenSymbol, amount) {
|
|
1536
|
+
const tokenInfo = this.resolveToken(tokenSymbol);
|
|
1537
|
+
const amountWei = ethers4.parseUnits(amount, tokenInfo.decimals);
|
|
1538
|
+
const accountAddr = await this.getAccountAddress();
|
|
1539
|
+
const txHash = await this.approveAndDeposit(accountAddr, tokenInfo, amountWei);
|
|
1540
|
+
await this.ensureCreditProvider(accountAddr);
|
|
1541
|
+
const pos = await this.morpho.getPosition(accountAddr, tokenInfo.address);
|
|
1542
|
+
return {
|
|
1543
|
+
tx: txHash,
|
|
1544
|
+
amount: amountWei,
|
|
1545
|
+
token: tokenSymbol,
|
|
1546
|
+
agentAccount: accountAddr,
|
|
1547
|
+
totalCollateral: pos.collateralAmount
|
|
1548
|
+
};
|
|
1549
|
+
}
|
|
1550
|
+
// ══════════════════════════════════════════
|
|
1551
|
+
// Flow 2: Deposit + borrow in one call
|
|
1552
|
+
// ══════════════════════════════════════════
|
|
1553
|
+
/**
|
|
1554
|
+
* Deposit collateral AND borrow USDC in a single SDK call.
|
|
1555
|
+
* USDC lands in the AgentAccount.
|
|
1556
|
+
*
|
|
1557
|
+
* @param tokenSymbol - Collateral token (WETH, wstETH, cbETH)
|
|
1558
|
+
* @param collateralAmount - Human-readable collateral amount (e.g. "0.05")
|
|
1559
|
+
* @param borrowAmount - Human-readable USDC amount to borrow (e.g. "50")
|
|
1560
|
+
*/
|
|
1561
|
+
async depositAndBorrow(tokenSymbol, collateralAmount, borrowAmount) {
|
|
1562
|
+
const tokenInfo = this.resolveToken(tokenSymbol);
|
|
1563
|
+
const collateralWei = ethers4.parseUnits(collateralAmount, tokenInfo.decimals);
|
|
1564
|
+
const borrowWei = ethers4.parseUnits(borrowAmount, 6);
|
|
1565
|
+
const accountAddr = await this.getAccountAddress();
|
|
1566
|
+
const depositTxHash = await this.approveAndDeposit(accountAddr, tokenInfo, collateralWei);
|
|
1567
|
+
await this.ensureCreditProvider(accountAddr);
|
|
1568
|
+
const account = new Contract3(accountAddr, AGENT_ACCOUNT_ABI, this.signer);
|
|
1569
|
+
const calldata = this.morphoIface.encodeFunctionData("drawWithCollateral", [tokenInfo.address, borrowWei]);
|
|
1570
|
+
const borrowTx = await account.execute(this.config.contracts.morphoCredit, 0, calldata);
|
|
1571
|
+
await borrowTx.wait();
|
|
1572
|
+
const totalDebt = await this.morpho.getTotalDebt(accountAddr);
|
|
1573
|
+
return {
|
|
1574
|
+
depositTx: depositTxHash,
|
|
1575
|
+
borrowTx: borrowTx.hash,
|
|
1576
|
+
collateral: { amount: collateralWei, token: tokenSymbol },
|
|
1577
|
+
borrowed: borrowWei,
|
|
1578
|
+
agentAccount: accountAddr,
|
|
1579
|
+
totalDebt
|
|
1580
|
+
};
|
|
1581
|
+
}
|
|
1582
|
+
// ══════════════════════════════════════════
|
|
1583
|
+
// Flow 8: Borrow against existing collateral
|
|
1584
|
+
// ══════════════════════════════════════════
|
|
1585
|
+
/**
|
|
1586
|
+
* Borrow USDC against already-deposited collateral.
|
|
1587
|
+
* Auto-detects which collateral token has a position.
|
|
1588
|
+
* USDC lands in AgentAccount — ready for x402 payments.
|
|
1589
|
+
*
|
|
1590
|
+
* @param amount - Human-readable USDC amount (e.g. "100")
|
|
1591
|
+
*/
|
|
1592
|
+
async borrow(amount) {
|
|
1593
|
+
const borrowWei = ethers4.parseUnits(amount, 6);
|
|
1594
|
+
const accountAddr = await this.getAccountAddress();
|
|
1595
|
+
let activeToken = null;
|
|
1596
|
+
for (const info of Object.values(this.collaterals)) {
|
|
1597
|
+
const pos = await this.morpho.getPosition(accountAddr, info.address);
|
|
1598
|
+
if (pos.collateralAmount > 0n) {
|
|
1599
|
+
activeToken = info;
|
|
1600
|
+
break;
|
|
1601
|
+
}
|
|
1602
|
+
}
|
|
1603
|
+
if (!activeToken) {
|
|
1604
|
+
throw new Error("No collateral deposited. Use deposit() or depositAndBorrow() first.");
|
|
1605
|
+
}
|
|
1606
|
+
await this.ensureCreditProvider(accountAddr);
|
|
1607
|
+
const account = new Contract3(accountAddr, AGENT_ACCOUNT_ABI, this.signer);
|
|
1608
|
+
const calldata = this.morphoIface.encodeFunctionData("drawWithCollateral", [activeToken.address, borrowWei]);
|
|
1609
|
+
const tx = await account.execute(this.config.contracts.morphoCredit, 0, calldata);
|
|
1610
|
+
await tx.wait();
|
|
1611
|
+
const totalDebt = await this.morpho.getTotalDebt(accountAddr);
|
|
1612
|
+
return {
|
|
1613
|
+
tx: tx.hash,
|
|
1614
|
+
amount: borrowWei,
|
|
1615
|
+
agentAccount: accountAddr,
|
|
1616
|
+
totalDebt,
|
|
1617
|
+
collateralToken: activeToken.symbol
|
|
1618
|
+
};
|
|
1619
|
+
}
|
|
1620
|
+
// ══════════════════════════════════════════
|
|
1621
|
+
// Flows 4-7: Sponsor (deposit for another agent)
|
|
1622
|
+
// ══════════════════════════════════════════
|
|
1623
|
+
/**
|
|
1624
|
+
* Deposit collateral for another agent. Caller pays from their wallet.
|
|
1625
|
+
* Optionally borrow USDC for the agent (only works if caller owns the AgentAccount).
|
|
1626
|
+
*
|
|
1627
|
+
* Supports both agentId lookup and direct address.
|
|
1628
|
+
*
|
|
1629
|
+
* @param target - `{ agentId: "17676" }` or `{ address: "0x..." }`
|
|
1630
|
+
* @param tokenSymbol - Collateral token
|
|
1631
|
+
* @param amount - Human-readable collateral amount
|
|
1632
|
+
* @param borrowAmount - Optional: USDC to borrow (only if caller is owner)
|
|
1633
|
+
*/
|
|
1634
|
+
async sponsor(target, tokenSymbol, amount, borrowAmount) {
|
|
1635
|
+
const tokenInfo = this.resolveToken(tokenSymbol);
|
|
1636
|
+
const collateralWei = ethers4.parseUnits(amount, tokenInfo.decimals);
|
|
1637
|
+
let accountAddr;
|
|
1638
|
+
let targetAgentId;
|
|
1639
|
+
if ("agentId" in target) {
|
|
1640
|
+
targetAgentId = target.agentId.toString();
|
|
1641
|
+
accountAddr = await this.getAccountForAgent(target.agentId);
|
|
1642
|
+
} else {
|
|
1643
|
+
accountAddr = target.address;
|
|
1644
|
+
}
|
|
1645
|
+
const depositTxHash = await this.approveAndDeposit(accountAddr, tokenInfo, collateralWei);
|
|
1646
|
+
const result = {
|
|
1647
|
+
depositTx: depositTxHash,
|
|
1648
|
+
targetAccount: accountAddr,
|
|
1649
|
+
targetAgentId,
|
|
1650
|
+
collateral: { amount: collateralWei, token: tokenSymbol },
|
|
1651
|
+
totalCollateral: 0n,
|
|
1652
|
+
totalDebt: 0n
|
|
1653
|
+
};
|
|
1654
|
+
if (borrowAmount) {
|
|
1655
|
+
const borrowWei = ethers4.parseUnits(borrowAmount, 6);
|
|
1656
|
+
try {
|
|
1657
|
+
await this.ensureCreditProvider(accountAddr);
|
|
1658
|
+
const account = new Contract3(accountAddr, AGENT_ACCOUNT_ABI, this.signer);
|
|
1659
|
+
const calldata = this.morphoIface.encodeFunctionData("drawWithCollateral", [tokenInfo.address, borrowWei]);
|
|
1660
|
+
const tx = await account.execute(this.config.contracts.morphoCredit, 0, calldata);
|
|
1661
|
+
await tx.wait();
|
|
1662
|
+
result.borrowTx = tx.hash;
|
|
1663
|
+
result.borrowed = borrowWei;
|
|
1664
|
+
} catch (e) {
|
|
1665
|
+
throw new Error(`Borrow failed (caller may not own this AgentAccount): ${e.message}`);
|
|
1666
|
+
}
|
|
1667
|
+
}
|
|
1668
|
+
const pos = await this.morpho.getPosition(accountAddr, tokenInfo.address);
|
|
1669
|
+
result.totalCollateral = pos.collateralAmount;
|
|
1670
|
+
result.totalDebt = pos.borrowedAmount;
|
|
1671
|
+
return result;
|
|
1672
|
+
}
|
|
1673
|
+
// ══════════════════════════════════════════
|
|
1674
|
+
// Repay & Withdraw
|
|
1675
|
+
// ══════════════════════════════════════════
|
|
1676
|
+
/**
|
|
1677
|
+
* Repay borrowed USDC from AgentAccount back to Morpho.
|
|
1678
|
+
*
|
|
1679
|
+
* @param amount - Human-readable USDC amount (e.g. "50")
|
|
1680
|
+
*/
|
|
1681
|
+
async repay(amount) {
|
|
1682
|
+
const amountWei = ethers4.parseUnits(amount, 6);
|
|
1683
|
+
const accountAddr = await this.getAccountAddress();
|
|
1684
|
+
let collateralAddr = null;
|
|
1685
|
+
for (const info of Object.values(this.collaterals)) {
|
|
1686
|
+
const pos = await this.morpho.getPosition(accountAddr, info.address);
|
|
1687
|
+
if (pos.borrowedAmount > 0n) {
|
|
1688
|
+
collateralAddr = info.address;
|
|
1689
|
+
break;
|
|
1690
|
+
}
|
|
1691
|
+
}
|
|
1692
|
+
if (!collateralAddr) throw new Error("No Morpho debt to repay.");
|
|
1693
|
+
const usdc = new Contract3(this.config.contracts.usdc, ERC20_ABI, this.signer.provider);
|
|
1694
|
+
const balance = await usdc.balanceOf(accountAddr);
|
|
1695
|
+
if (balance < amountWei) {
|
|
1696
|
+
throw new Error(`Insufficient USDC in AgentAccount: $${ethers4.formatUnits(balance, 6)}`);
|
|
1697
|
+
}
|
|
1698
|
+
const txHash = await this.batch(accountAddr, [
|
|
1699
|
+
{
|
|
1700
|
+
target: this.config.contracts.usdc,
|
|
1701
|
+
value: 0n,
|
|
1702
|
+
data: this.erc20Iface.encodeFunctionData("approve", [this.config.contracts.morphoCredit, amountWei])
|
|
1703
|
+
},
|
|
1704
|
+
{
|
|
1705
|
+
target: this.config.contracts.morphoCredit,
|
|
1706
|
+
value: 0n,
|
|
1707
|
+
data: this.morphoIface.encodeFunctionData("repayWithCollateral", [collateralAddr, amountWei])
|
|
1708
|
+
}
|
|
1709
|
+
]);
|
|
1710
|
+
const totalDebt = await this.morpho.getTotalDebt(accountAddr);
|
|
1711
|
+
return { tx: txHash, amount: amountWei, remainingDebt: totalDebt };
|
|
1712
|
+
}
|
|
1713
|
+
/**
|
|
1714
|
+
* Withdraw collateral from Morpho back to EOA.
|
|
1715
|
+
*
|
|
1716
|
+
* @param tokenSymbol - Collateral token
|
|
1717
|
+
* @param amount - Human-readable amount or "all"
|
|
1718
|
+
*/
|
|
1719
|
+
async withdraw(tokenSymbol, amount) {
|
|
1720
|
+
const tokenInfo = this.resolveToken(tokenSymbol);
|
|
1721
|
+
const accountAddr = await this.getAccountAddress();
|
|
1722
|
+
const pos = await this.morpho.getPosition(accountAddr, tokenInfo.address);
|
|
1723
|
+
if (pos.collateralAmount === 0n) {
|
|
1724
|
+
throw new Error(`No ${tokenSymbol} collateral deposited.`);
|
|
1725
|
+
}
|
|
1726
|
+
const withdrawAmount = amount.toLowerCase() === "all" ? pos.collateralAmount : ethers4.parseUnits(amount, tokenInfo.decimals);
|
|
1727
|
+
if (withdrawAmount > pos.collateralAmount) {
|
|
1728
|
+
throw new Error(
|
|
1729
|
+
`Cannot withdraw more than deposited: max ${ethers4.formatUnits(pos.collateralAmount, tokenInfo.decimals)} ${tokenSymbol}`
|
|
1730
|
+
);
|
|
1731
|
+
}
|
|
1732
|
+
const txHash = await this.batch(accountAddr, [
|
|
1733
|
+
{
|
|
1734
|
+
target: this.config.contracts.morphoCredit,
|
|
1735
|
+
value: 0n,
|
|
1736
|
+
data: this.morphoIface.encodeFunctionData("withdrawCollateral", [tokenInfo.address, withdrawAmount])
|
|
1737
|
+
},
|
|
1738
|
+
{
|
|
1739
|
+
target: tokenInfo.address,
|
|
1740
|
+
value: 0n,
|
|
1741
|
+
data: this.erc20Iface.encodeFunctionData("transfer", [this.signer.address, withdrawAmount])
|
|
1742
|
+
}
|
|
1743
|
+
]);
|
|
1744
|
+
const newPos = await this.morpho.getPosition(accountAddr, tokenInfo.address);
|
|
1745
|
+
return {
|
|
1746
|
+
tx: txHash,
|
|
1747
|
+
amount: withdrawAmount,
|
|
1748
|
+
token: tokenSymbol,
|
|
1749
|
+
destination: this.signer.address,
|
|
1750
|
+
remainingCollateral: newPos.collateralAmount
|
|
1751
|
+
};
|
|
1752
|
+
}
|
|
1753
|
+
// ══════════════════════════════════════════
|
|
1754
|
+
// View methods
|
|
1755
|
+
// ══════════════════════════════════════════
|
|
1756
|
+
/**
|
|
1757
|
+
* Get position for a specific collateral token.
|
|
1758
|
+
*/
|
|
1759
|
+
async getPosition(tokenSymbol) {
|
|
1760
|
+
const tokenInfo = this.resolveToken(tokenSymbol);
|
|
1761
|
+
const accountAddr = await this.getAccountAddress();
|
|
1762
|
+
const pos = await this.morpho.getPosition(accountAddr, tokenInfo.address);
|
|
1763
|
+
return {
|
|
1764
|
+
token: tokenSymbol,
|
|
1765
|
+
collateralAmount: pos.collateralAmount,
|
|
1766
|
+
borrowedAmount: pos.borrowedAmount,
|
|
1767
|
+
borrowShares: pos.borrowShares,
|
|
1768
|
+
isActive: pos.isActive
|
|
1769
|
+
};
|
|
1770
|
+
}
|
|
1771
|
+
/**
|
|
1772
|
+
* Get all active positions across all collateral tokens.
|
|
1773
|
+
*/
|
|
1774
|
+
async getAllPositions() {
|
|
1775
|
+
const accountAddr = await this.getAccountAddress();
|
|
1776
|
+
const positions = [];
|
|
1777
|
+
for (const [symbol, info] of Object.entries(this.collaterals)) {
|
|
1778
|
+
const pos = await this.morpho.getPosition(accountAddr, info.address);
|
|
1779
|
+
if (pos.isActive || pos.collateralAmount > 0n || pos.borrowedAmount > 0n) {
|
|
1780
|
+
positions.push({
|
|
1781
|
+
token: symbol,
|
|
1782
|
+
collateralAmount: pos.collateralAmount,
|
|
1783
|
+
borrowedAmount: pos.borrowedAmount,
|
|
1784
|
+
borrowShares: pos.borrowShares,
|
|
1785
|
+
isActive: pos.isActive
|
|
1786
|
+
});
|
|
1787
|
+
}
|
|
1788
|
+
}
|
|
1789
|
+
return positions;
|
|
1790
|
+
}
|
|
1791
|
+
/**
|
|
1792
|
+
* Get total debt across all positions.
|
|
1793
|
+
*/
|
|
1794
|
+
async getTotalDebt() {
|
|
1795
|
+
const accountAddr = await this.getAccountAddress();
|
|
1796
|
+
return this.morpho.getTotalDebt(accountAddr);
|
|
1797
|
+
}
|
|
1798
|
+
/**
|
|
1799
|
+
* Get USDC balance in the AgentAccount.
|
|
1800
|
+
*/
|
|
1801
|
+
async getAccountUSDC() {
|
|
1802
|
+
const accountAddr = await this.getAccountAddress();
|
|
1803
|
+
const usdc = new Contract3(this.config.contracts.usdc, ERC20_ABI, this.signer.provider);
|
|
1804
|
+
return usdc.balanceOf(accountAddr);
|
|
1805
|
+
}
|
|
1806
|
+
/** Get the wallet (signer) address */
|
|
1807
|
+
getAddress() {
|
|
1808
|
+
return this.signer.address;
|
|
1809
|
+
}
|
|
1810
|
+
};
|
|
1370
1811
|
|
|
1371
1812
|
// src/clients/WalletClient.ts
|
|
1372
|
-
import { ethers as
|
|
1813
|
+
import { ethers as ethers5, Contract as Contract4, Wallet } from "ethers";
|
|
1373
1814
|
var WalletClient = class {
|
|
1374
1815
|
constructor(config) {
|
|
1375
1816
|
this.privateKey = null;
|
|
1376
1817
|
this.factoryAddress = config.factoryAddress;
|
|
1377
|
-
this.usdcAddress = config.usdcAddress ||
|
|
1818
|
+
this.usdcAddress = config.usdcAddress || ethers5.ZeroAddress;
|
|
1378
1819
|
this.chainId = config.chainId;
|
|
1379
1820
|
this.rpcUrl = config.rpcUrl;
|
|
1380
|
-
this.provider = new
|
|
1821
|
+
this.provider = new ethers5.JsonRpcProvider(config.rpcUrl);
|
|
1381
1822
|
this.privateKey = config.privateKey || null;
|
|
1382
1823
|
}
|
|
1383
1824
|
/**
|
|
@@ -1387,20 +1828,20 @@ var WalletClient = class {
|
|
|
1387
1828
|
if (!this.privateKey) {
|
|
1388
1829
|
throw new Error("Signer not configured - provide privateKey");
|
|
1389
1830
|
}
|
|
1390
|
-
const freshProvider = new
|
|
1831
|
+
const freshProvider = new ethers5.JsonRpcProvider(this.rpcUrl);
|
|
1391
1832
|
return new Wallet(this.privateKey, freshProvider);
|
|
1392
1833
|
}
|
|
1393
1834
|
getFactoryContract() {
|
|
1394
1835
|
if (this.privateKey) {
|
|
1395
|
-
return new
|
|
1836
|
+
return new Contract4(this.factoryAddress, ACCOUNT_FACTORY_ABI, this.getFreshSigner());
|
|
1396
1837
|
}
|
|
1397
|
-
return new
|
|
1838
|
+
return new Contract4(this.factoryAddress, ACCOUNT_FACTORY_ABI, this.provider);
|
|
1398
1839
|
}
|
|
1399
1840
|
getAccountContract(accountAddress) {
|
|
1400
1841
|
if (this.privateKey) {
|
|
1401
|
-
return new
|
|
1842
|
+
return new Contract4(accountAddress, AGENT_ACCOUNT_ABI, this.getFreshSigner());
|
|
1402
1843
|
}
|
|
1403
|
-
return new
|
|
1844
|
+
return new Contract4(accountAddress, AGENT_ACCOUNT_ABI, this.provider);
|
|
1404
1845
|
}
|
|
1405
1846
|
getChainId() {
|
|
1406
1847
|
return this.chainId;
|
|
@@ -1413,7 +1854,7 @@ var WalletClient = class {
|
|
|
1413
1854
|
async getAccount(agentId) {
|
|
1414
1855
|
const factory = this.getFactoryContract();
|
|
1415
1856
|
const address = await factory.getAccount(agentId);
|
|
1416
|
-
if (address ===
|
|
1857
|
+
if (address === ethers5.ZeroAddress) {
|
|
1417
1858
|
return null;
|
|
1418
1859
|
}
|
|
1419
1860
|
return address;
|
|
@@ -1448,7 +1889,7 @@ var WalletClient = class {
|
|
|
1448
1889
|
account.ethBalance()
|
|
1449
1890
|
]);
|
|
1450
1891
|
let usdcBalance = 0n;
|
|
1451
|
-
if (this.usdcAddress !==
|
|
1892
|
+
if (this.usdcAddress !== ethers5.ZeroAddress) {
|
|
1452
1893
|
usdcBalance = await account.balanceOf(this.usdcAddress);
|
|
1453
1894
|
}
|
|
1454
1895
|
return {
|
|
@@ -1460,7 +1901,7 @@ var WalletClient = class {
|
|
|
1460
1901
|
};
|
|
1461
1902
|
}
|
|
1462
1903
|
async getProviderStatus(accountAddress, creditProvider) {
|
|
1463
|
-
const provider = new
|
|
1904
|
+
const provider = new Contract4(
|
|
1464
1905
|
creditProvider,
|
|
1465
1906
|
CREDIT_PROVIDER_ABI,
|
|
1466
1907
|
this.provider
|
|
@@ -1483,11 +1924,11 @@ var WalletClient = class {
|
|
|
1483
1924
|
throw new Error("Signer not configured");
|
|
1484
1925
|
}
|
|
1485
1926
|
const signer = this.getFreshSigner();
|
|
1486
|
-
const token = new
|
|
1927
|
+
const token = new Contract4(tokenAddress, ERC20_ABI, signer);
|
|
1487
1928
|
const approveTx = await token.approve(accountAddress, amount);
|
|
1488
1929
|
await approveTx.wait();
|
|
1489
1930
|
const signer2 = this.getFreshSigner();
|
|
1490
|
-
const account = new
|
|
1931
|
+
const account = new Contract4(accountAddress, AGENT_ACCOUNT_ABI, signer2);
|
|
1491
1932
|
const tx = await account.fund(tokenAddress, amount);
|
|
1492
1933
|
const receipt = await tx.wait();
|
|
1493
1934
|
return receipt.hash;
|
|
@@ -1533,8 +1974,8 @@ var WalletClient = class {
|
|
|
1533
1974
|
}
|
|
1534
1975
|
// ============ Utility ============
|
|
1535
1976
|
generatePaymentMessageHash(accountAddress, recipient, amount, nonce, deadline, chainId) {
|
|
1536
|
-
return
|
|
1537
|
-
|
|
1977
|
+
return ethers5.keccak256(
|
|
1978
|
+
ethers5.AbiCoder.defaultAbiCoder().encode(
|
|
1538
1979
|
["address", "uint256", "uint256", "uint256", "uint256", "address"],
|
|
1539
1980
|
[recipient, amount, nonce, deadline, chainId, accountAddress]
|
|
1540
1981
|
)
|
|
@@ -1600,6 +2041,7 @@ export {
|
|
|
1600
2041
|
InsufficientCreditError,
|
|
1601
2042
|
LP_VAULT_ABI,
|
|
1602
2043
|
MORPHO_CREDIT_ABI,
|
|
2044
|
+
MorphoCreditClient,
|
|
1603
2045
|
REPUTATION_CREDIT_ABI,
|
|
1604
2046
|
ScoringClient,
|
|
1605
2047
|
ScoringRejectedError,
|
package/package.json
CHANGED
package/dist/cli.d.mts
DELETED
package/dist/cli.d.ts
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Agether CLI — Direct On-Chain Credit for AI Agents
|
|
4
|
-
*
|
|
5
|
-
* All commands sign transactions directly with the agent's private key.
|
|
6
|
-
* No simulation routes. No mocks. Production-grade.
|
|
7
|
-
*
|
|
8
|
-
* Usage:
|
|
9
|
-
* agether init <private-key> # Initialize with private key
|
|
10
|
-
* agether register [--name] [--code-url] # Register on real ERC-8004 + KYA
|
|
11
|
-
* agether apply --limit 10000 # Apply for $10,000 credit (on-chain)
|
|
12
|
-
* agether draw --amount 1000 # Draw $1,000 (on-chain)
|
|
13
|
-
* agether repay --amount 500 # Repay $500 (on-chain)
|
|
14
|
-
* agether status # Check credit line status (on-chain)
|
|
15
|
-
* agether score # Get credit score (backend)
|
|
16
|
-
* agether balance # Check ETH + USDC balances (on-chain)
|
|
17
|
-
*/
|
|
18
|
-
export {};
|
|
19
|
-
//# sourceMappingURL=cli.d.ts.map
|
package/dist/cli.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;GAeG"}
|
package/dist/cli.mjs
DELETED
|
File without changes
|