@agether/sdk 1.5.0 → 1.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,207 +1,26 @@
1
- // src/clients/AgetherClient.ts
2
- import { ethers, Contract } from "ethers";
3
-
4
- // src/types/index.ts
5
- var ChainId = /* @__PURE__ */ ((ChainId3) => {
6
- ChainId3[ChainId3["Ethereum"] = 1] = "Ethereum";
7
- ChainId3[ChainId3["Base"] = 8453] = "Base";
8
- ChainId3[ChainId3["BaseSepolia"] = 84532] = "BaseSepolia";
9
- ChainId3[ChainId3["Sepolia"] = 11155111] = "Sepolia";
10
- ChainId3[ChainId3["Hardhat"] = 31337] = "Hardhat";
11
- return ChainId3;
12
- })(ChainId || {});
13
- var AgetherError = class extends Error {
14
- constructor(message, code, details) {
15
- super(message);
16
- this.code = code;
17
- this.details = details;
18
- this.name = "AgetherError";
19
- }
20
- };
21
- var InsufficientBalanceError = class extends AgetherError {
22
- constructor(available, required) {
23
- super(
24
- `Insufficient balance: available ${available}, required ${required}`,
25
- "INSUFFICIENT_BALANCE",
26
- { available: available.toString(), required: required.toString() }
27
- );
28
- }
29
- };
30
- var ScoringRejectedError = class extends AgetherError {
31
- constructor(riskScore, reason) {
32
- super(
33
- `Scoring rejected: risk score ${riskScore}${reason ? `, ${reason}` : ""}`,
34
- "SCORING_REJECTED",
35
- { riskScore, reason }
36
- );
37
- }
38
- };
39
- var AgentNotApprovedError = class extends AgetherError {
40
- constructor(agentId) {
41
- super(
42
- `Agent ${agentId} is not KYA-approved. Submit code for validation first.`,
43
- "AGENT_NOT_APPROVED",
44
- { agentId: agentId.toString() }
45
- );
46
- }
47
- };
48
-
49
- // src/utils/abis.ts
50
- var IDENTITY_REGISTRY_ABI = [
51
- "function ownerOf(uint256 agentId) view returns (address)",
52
- "function balanceOf(address owner) view returns (uint256)",
53
- "function totalSupply() view returns (uint256)",
54
- "function exists(uint256 agentId) view returns (bool)",
55
- "function register() returns (uint256 agentId)",
56
- "event Transfer(address indexed from, address indexed to, uint256 indexed tokenId)"
57
- ];
58
- var ACCOUNT_FACTORY_ABI = [
59
- "function getAccount(uint256 agentId) view returns (address)",
60
- "function accountExists(uint256 agentId) view returns (bool)",
61
- "function predictAddress(uint256 agentId) view returns (address)",
62
- "function totalAccounts() view returns (uint256)",
63
- "function getAgentId(address account) view returns (uint256)",
64
- "function createAccount(uint256 agentId) returns (address account)",
65
- "event AccountCreated(uint256 indexed agentId, address indexed account, address indexed owner)"
66
- ];
67
- var AGENT_ACCOUNT_ABI = [
68
- "function agentId() view returns (uint256)",
69
- "function owner() view returns (address)",
70
- "function factory() view returns (address)",
71
- "function validationRegistry() view returns (address)",
72
- "function identityRegistry() view returns (address)",
73
- "function balanceOf(address token) view returns (uint256)",
74
- "function ethBalance() view returns (uint256)",
75
- "function execute(address target, uint256 value, bytes data) payable returns (bytes)",
76
- "function executeBatch(address[] targets, uint256[] values, bytes[] datas) payable returns (bytes[])",
77
- "function fund(address token, uint256 amount)",
78
- "function withdraw(address token, uint256 amount, address to)",
79
- "function withdrawETH(uint256 amount, address to)",
80
- "function isValidSignature(bytes32 hash, bytes signature) view returns (bytes4)"
81
- ];
82
- var AGENT_REPUTATION_ABI = [
83
- "function getCreditScore(uint256 agentId) view returns (uint256)",
84
- "function getAttestation(uint256 agentId) view returns (tuple(uint256 score, uint256 timestamp, address signer))",
85
- "function isScoreFresh(uint256 agentId) view returns (bool fresh, uint256 age)",
86
- "function isEligible(uint256 agentId, uint256 minScore) view returns (bool eligible, uint256 currentScore)",
87
- "function oracleSigner() view returns (address)",
88
- "function submitScore(uint256 agentId, uint256 score_, uint256 timestamp_, bytes signature)",
89
- "function setOracleSigner(address signer_)",
90
- "event ScoreUpdated(uint256 indexed agentId, uint256 score, uint256 timestamp, address signer)"
91
- ];
92
- var VALIDATION_REGISTRY_ABI = [
93
- "function isAgentCodeApproved(uint256 agentId) view returns (bool)",
94
- "function isAgentCodeApprovedForTag(uint256 agentId, string tag) view returns (bool)",
95
- "function getAgentValidations(uint256 agentId) view returns (bytes32[])",
96
- "function getValidation(bytes32 requestHash) view returns (tuple(address validatorAddress, uint256 agentId, string requestURI, uint8 response, string responseURI, bytes32 responseHash, string tag, uint256 requestedAt, uint256 respondedAt, bool hasResponse))"
97
- ];
98
- var MORPHO_BLUE_ABI = [
99
- // Supply & Withdraw (lending side)
100
- "function supply(tuple(address loanToken, address collateralToken, address oracle, address irm, uint256 lltv) marketParams, uint256 assets, uint256 shares, address onBehalf, bytes data) returns (uint256 assetsSupplied, uint256 sharesSupplied)",
101
- "function withdraw(tuple(address loanToken, address collateralToken, address oracle, address irm, uint256 lltv) marketParams, uint256 assets, uint256 shares, address onBehalf, address receiver) returns (uint256 assetsWithdrawn, uint256 sharesWithdrawn)",
102
- // Collateral
103
- "function supplyCollateral(tuple(address loanToken, address collateralToken, address oracle, address irm, uint256 lltv) marketParams, uint256 assets, address onBehalf, bytes data)",
104
- "function withdrawCollateral(tuple(address loanToken, address collateralToken, address oracle, address irm, uint256 lltv) marketParams, uint256 assets, address onBehalf, address receiver)",
105
- // Borrow & Repay
106
- "function borrow(tuple(address loanToken, address collateralToken, address oracle, address irm, uint256 lltv) marketParams, uint256 assets, uint256 shares, address onBehalf, address receiver) returns (uint256 assetsBorrowed, uint256 sharesBorrowed)",
107
- "function repay(tuple(address loanToken, address collateralToken, address oracle, address irm, uint256 lltv) marketParams, uint256 assets, uint256 shares, address onBehalf, bytes data) returns (uint256 assetsRepaid, uint256 sharesRepaid)",
108
- // Authorization
109
- "function setAuthorization(address authorized, bool newIsAuthorized)",
110
- "function isAuthorized(address authorizer, address authorized) view returns (bool)",
111
- // Views
112
- "function position(bytes32 id, address user) view returns (uint256 supplyShares, uint128 borrowShares, uint128 collateral)",
113
- "function market(bytes32 id) view returns (uint128 totalSupplyAssets, uint128 totalSupplyShares, uint128 totalBorrowAssets, uint128 totalBorrowShares, uint128 lastUpdate, uint128 fee)",
114
- "function idToMarketParams(bytes32 id) view returns (tuple(address loanToken, address collateralToken, address oracle, address irm, uint256 lltv))"
115
- ];
116
- var ERC20_ABI = [
117
- "function balanceOf(address account) view returns (uint256)",
118
- "function allowance(address owner, address spender) view returns (uint256)",
119
- "function approve(address spender, uint256 amount) returns (bool)",
120
- "function transfer(address to, uint256 amount) returns (bool)",
121
- "function transferFrom(address from, address to, uint256 amount) returns (bool)",
122
- "function decimals() view returns (uint8)",
123
- "function symbol() view returns (string)",
124
- "function name() view returns (string)"
125
- ];
126
-
127
- // src/utils/config.ts
128
- var CONTRACT_ADDRESSES = {
129
- [1 /* Ethereum */]: {
130
- accountFactory: "0x0000000000000000000000000000000000000000",
131
- validationRegistry: "0x0000000000000000000000000000000000000000",
132
- agentReputation: "0x0000000000000000000000000000000000000000",
133
- usdc: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
134
- identityRegistry: "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432",
135
- morphoBlue: "0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb"
136
- },
137
- [8453 /* Base */]: {
138
- accountFactory: "0xeB72f248Ad9F4bf4024e8D9da75cf7AAD37B58f5",
139
- validationRegistry: "0x8842f2383A86134Dd80c3Ecf6Bbae2e38396A5ec",
140
- agentReputation: "0xF1bed094D4E33E47CC8C72E086FFFde09e2211b4",
141
- usdc: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
142
- identityRegistry: "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432",
143
- morphoBlue: "0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb"
144
- },
145
- [84532 /* BaseSepolia */]: {
146
- accountFactory: "0x0000000000000000000000000000000000000000",
147
- validationRegistry: "0x0000000000000000000000000000000000000000",
148
- agentReputation: "0x0000000000000000000000000000000000000000",
149
- usdc: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
150
- identityRegistry: "0x8004A818BFB912233c491871b3d84c89A494BD9e",
151
- morphoBlue: "0x0000000000000000000000000000000000000000"
152
- },
153
- [11155111 /* Sepolia */]: {
154
- accountFactory: "0x0000000000000000000000000000000000000000",
155
- validationRegistry: "0x0000000000000000000000000000000000000000",
156
- agentReputation: "0x0000000000000000000000000000000000000000",
157
- usdc: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
158
- identityRegistry: "0x8004A818BFB912233c491871b3d84c89A494BD9e",
159
- morphoBlue: "0x0000000000000000000000000000000000000000"
160
- },
161
- [31337 /* Hardhat */]: {
162
- accountFactory: "0x0000000000000000000000000000000000000000",
163
- validationRegistry: "0x0000000000000000000000000000000000000000",
164
- agentReputation: "0x0000000000000000000000000000000000000000",
165
- usdc: "0x56d4d6aEe0278c5Df2FA23Ecb32eC146C9446FDf",
166
- identityRegistry: "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432",
167
- morphoBlue: "0x0000000000000000000000000000000000000000"
168
- }
169
- };
170
- var RPC_URLS = {
171
- [1 /* Ethereum */]: "https://ethereum-rpc.publicnode.com",
172
- [8453 /* Base */]: "https://base-rpc.publicnode.com",
173
- [84532 /* BaseSepolia */]: "https://sepolia.base.org",
174
- [11155111 /* Sepolia */]: "https://rpc.sepolia.org",
175
- [31337 /* Hardhat */]: "http://127.0.0.1:8545"
176
- };
177
- var SCORING_ENDPOINTS = {
178
- [1 /* Ethereum */]: "https://scoring.agether.ai/v1",
179
- [8453 /* Base */]: "http://95.179.189.214:3001",
180
- [84532 /* BaseSepolia */]: "http://95.179.189.214:3001",
181
- [11155111 /* Sepolia */]: "https://scoring-testnet.agether.ai/v1",
182
- [31337 /* Hardhat */]: "http://127.0.0.1:3001"
183
- };
184
- function getDefaultConfig(chainId) {
185
- return {
186
- chainId,
187
- rpcUrl: RPC_URLS[chainId],
188
- contracts: CONTRACT_ADDRESSES[chainId],
189
- scoringEndpoint: SCORING_ENDPOINTS[chainId]
190
- };
191
- }
192
- function createConfig(chainId, options) {
193
- const defaultConfig = getDefaultConfig(chainId);
194
- return {
195
- ...defaultConfig,
196
- ...options,
197
- contracts: {
198
- ...defaultConfig.contracts,
199
- ...options?.contracts
200
- }
201
- };
202
- }
1
+ import {
2
+ ACCOUNT_FACTORY_ABI,
3
+ AGENT_ACCOUNT_ABI,
4
+ AGENT_REPUTATION_ABI,
5
+ AgentNotApprovedError,
6
+ AgetherError,
7
+ ChainId,
8
+ ERC20_ABI,
9
+ IDENTITY_REGISTRY_ABI,
10
+ InsufficientBalanceError,
11
+ MORPHO_BLUE_ABI,
12
+ MorphoClient,
13
+ ScoringRejectedError,
14
+ VALIDATION_REGISTRY_ABI,
15
+ createConfig,
16
+ getDefaultConfig
17
+ } from "./chunk-GAFDBPDW.mjs";
18
+ import {
19
+ X402Client
20
+ } from "./chunk-PTXYOTCG.mjs";
203
21
 
204
22
  // src/clients/AgetherClient.ts
23
+ import { ethers, Contract } from "ethers";
205
24
  var AgetherClient = class _AgetherClient {
206
25
  constructor(options) {
207
26
  this.config = options.config;
@@ -379,889 +198,12 @@ var AgetherClient = class _AgetherClient {
379
198
  }
380
199
  };
381
200
 
382
- // src/clients/MorphoClient.ts
383
- import { ethers as ethers2, Contract as Contract2 } from "ethers";
384
- import axios from "axios";
385
- var BASE_COLLATERALS = {
386
- WETH: { address: "0x4200000000000000000000000000000000000006", symbol: "WETH", decimals: 18 },
387
- wstETH: { address: "0xc1CBa3fCea344f92D9239c08C0568f6F2F0ee452", symbol: "wstETH", decimals: 18 },
388
- cbETH: { address: "0x2Ae3F1Ec7F1F5012CFEab0185bfc7aa3cf0DEc22", symbol: "cbETH", decimals: 18 }
389
- };
390
- var MORPHO_API_URL = "https://api.morpho.org/graphql";
391
- var morphoIface = new ethers2.Interface(MORPHO_BLUE_ABI);
392
- var erc20Iface = new ethers2.Interface(ERC20_ABI);
393
- var MorphoClient = class {
394
- constructor(config) {
395
- this._marketCache = /* @__PURE__ */ new Map();
396
- this._discoveredAt = 0;
397
- const chainId = config.chainId ?? 8453 /* Base */;
398
- const defaultCfg = getDefaultConfig(chainId);
399
- this.config = defaultCfg;
400
- this.agentId = config.agentId;
401
- this.provider = new ethers2.JsonRpcProvider(config.rpcUrl || defaultCfg.rpcUrl);
402
- this.wallet = new ethers2.Wallet(config.privateKey, this.provider);
403
- const addrs = { ...defaultCfg.contracts, ...config.contracts };
404
- this.accountFactory = new Contract2(addrs.accountFactory, ACCOUNT_FACTORY_ABI, this.wallet);
405
- this.morphoBlue = new Contract2(addrs.morphoBlue, MORPHO_BLUE_ABI, this.provider);
406
- this.agentReputation = new Contract2(addrs.agentReputation, AGENT_REPUTATION_ABI, this.provider);
407
- this.identityRegistry = new Contract2(addrs.identityRegistry, IDENTITY_REGISTRY_ABI, this.provider);
408
- }
409
- // ════════════════════════════════════════════════════════
410
- // Account Management
411
- // ════════════════════════════════════════════════════════
412
- /** Resolve the AgentAccount address (cached). */
413
- async getAccountAddress() {
414
- if (this._accountAddress) return this._accountAddress;
415
- if (!this.agentId) throw new AgetherError("agentId not set", "NO_AGENT_ID");
416
- const addr = await this.accountFactory.getAccount(BigInt(this.agentId));
417
- if (addr === ethers2.ZeroAddress) {
418
- throw new AgetherError("No AgentAccount found. Call register() first.", "NO_ACCOUNT");
419
- }
420
- this._accountAddress = addr;
421
- return addr;
422
- }
423
- getAgentId() {
424
- if (!this.agentId) throw new AgetherError("agentId not set", "NO_AGENT_ID");
425
- return this.agentId;
426
- }
427
- getWalletAddress() {
428
- return this.wallet.address;
429
- }
430
- /**
431
- * Register: create ERC-8004 identity + AgentAccount in one flow.
432
- * If already registered, returns existing state.
433
- */
434
- async register(_name) {
435
- const eoaAddr = this.wallet.address;
436
- if (this.agentId) {
437
- const exists = await this.accountFactory.accountExists(BigInt(this.agentId));
438
- if (exists) {
439
- const acct = await this.accountFactory.getAccount(BigInt(this.agentId));
440
- this._accountAddress = acct;
441
- return { agentId: this.agentId, address: eoaAddr, agentAccount: acct, alreadyRegistered: true };
442
- }
443
- }
444
- const balance = await this.identityRegistry.balanceOf(eoaAddr);
445
- let agentId;
446
- if (balance > 0n && this.agentId) {
447
- agentId = BigInt(this.agentId);
448
- } else if (balance > 0n) {
449
- throw new AgetherError(
450
- "Wallet already has an ERC-8004 identity but agentId is unknown. Pass agentId in config.",
451
- "AGENT_ID_UNKNOWN"
452
- );
453
- } else {
454
- const regTx = await this.identityRegistry.register();
455
- const regReceipt = await regTx.wait();
456
- agentId = 0n;
457
- for (const log of regReceipt.logs) {
458
- try {
459
- const parsed = this.identityRegistry.interface.parseLog({ topics: log.topics, data: log.data });
460
- if (parsed?.name === "Transfer") {
461
- agentId = parsed.args[2];
462
- break;
463
- }
464
- } catch {
465
- continue;
466
- }
467
- }
468
- if (agentId === 0n) throw new AgetherError("Failed to parse agentId from registration", "PARSE_ERROR");
469
- }
470
- this.agentId = agentId.toString();
471
- const acctExists = await this.accountFactory.accountExists(agentId);
472
- let txHash;
473
- if (!acctExists) {
474
- const tx = await this.accountFactory.createAccount(agentId);
475
- const receipt = await tx.wait();
476
- txHash = receipt.hash;
477
- }
478
- const acctAddr = await this.accountFactory.getAccount(agentId);
479
- this._accountAddress = acctAddr;
480
- return {
481
- agentId: this.agentId,
482
- address: eoaAddr,
483
- agentAccount: acctAddr,
484
- alreadyRegistered: acctExists,
485
- tx: txHash
486
- };
487
- }
488
- /** Get ETH / USDC balances for EOA and AgentAccount. */
489
- async getBalances() {
490
- const eoaAddr = this.wallet.address;
491
- const usdc = new Contract2(this.config.contracts.usdc, ERC20_ABI, this.provider);
492
- const ethBal = await this.provider.getBalance(eoaAddr);
493
- const usdcBal = await usdc.balanceOf(eoaAddr);
494
- const result = {
495
- agentId: this.agentId || "?",
496
- address: eoaAddr,
497
- eth: ethers2.formatEther(ethBal),
498
- usdc: ethers2.formatUnits(usdcBal, 6)
499
- };
500
- try {
501
- const acctAddr = await this.getAccountAddress();
502
- const acctEth = await this.provider.getBalance(acctAddr);
503
- const acctUsdc = await usdc.balanceOf(acctAddr);
504
- result.agentAccount = {
505
- address: acctAddr,
506
- eth: ethers2.formatEther(acctEth),
507
- usdc: ethers2.formatUnits(acctUsdc, 6)
508
- };
509
- } catch {
510
- }
511
- return result;
512
- }
513
- /** Transfer USDC from EOA to AgentAccount. */
514
- async fundAccount(usdcAmount) {
515
- const acctAddr = await this.getAccountAddress();
516
- const usdc = new Contract2(this.config.contracts.usdc, ERC20_ABI, this.wallet);
517
- const amount = ethers2.parseUnits(usdcAmount, 6);
518
- const tx = await usdc.transfer(acctAddr, amount);
519
- const receipt = await tx.wait();
520
- return { tx: receipt.hash, amount: usdcAmount, agentAccount: acctAddr };
521
- }
522
- // ════════════════════════════════════════════════════════
523
- // Market Discovery (Morpho GraphQL API)
524
- // ════════════════════════════════════════════════════════
525
- /**
526
- * Fetch USDC borrow markets on Base from Morpho API.
527
- * Caches results for 5 minutes.
528
- */
529
- async getMarkets(forceRefresh = false) {
530
- if (!forceRefresh && this._discoveredMarkets && Date.now() - this._discoveredAt < 3e5) {
531
- return this._discoveredMarkets;
532
- }
533
- const chainId = this.config.chainId;
534
- const usdcAddr = this.config.contracts.usdc.toLowerCase();
535
- const query = `{
536
- markets(
537
- first: 50
538
- orderBy: SupplyAssetsUsd
539
- orderDirection: Desc
540
- where: { chainId_in: [${chainId}], loanAssetAddress_in: ["${usdcAddr}"] }
541
- ) {
542
- items {
543
- uniqueKey
544
- lltv
545
- oracleAddress
546
- irmAddress
547
- loanAsset { address symbol decimals }
548
- collateralAsset { address symbol decimals }
549
- state {
550
- borrowAssets
551
- supplyAssets
552
- utilization
553
- }
554
- }
555
- }
556
- }`;
557
- try {
558
- const resp = await axios.post(MORPHO_API_URL, { query }, { timeout: 1e4 });
559
- const items = resp.data?.data?.markets?.items ?? [];
560
- this._discoveredMarkets = items.map((m) => ({
561
- uniqueKey: m.uniqueKey,
562
- loanAsset: m.loanAsset,
563
- collateralAsset: m.collateralAsset ?? { address: ethers2.ZeroAddress, symbol: "N/A", decimals: 0 },
564
- oracle: m.oracleAddress,
565
- irm: m.irmAddress,
566
- lltv: BigInt(m.lltv),
567
- totalSupplyAssets: BigInt(m.state?.supplyAssets ?? "0"),
568
- totalBorrowAssets: BigInt(m.state?.borrowAssets ?? "0"),
569
- utilization: m.state?.utilization ? Number(m.state.utilization) : 0
570
- }));
571
- this._discoveredAt = Date.now();
572
- for (const mi of this._discoveredMarkets) {
573
- if (mi.collateralAsset.address !== ethers2.ZeroAddress) {
574
- this._marketCache.set(mi.collateralAsset.address.toLowerCase(), {
575
- loanToken: mi.loanAsset.address,
576
- collateralToken: mi.collateralAsset.address,
577
- oracle: mi.oracle,
578
- irm: mi.irm,
579
- lltv: mi.lltv
580
- });
581
- }
582
- }
583
- return this._discoveredMarkets;
584
- } catch {
585
- return this._discoveredMarkets ?? [];
586
- }
587
- }
588
- /**
589
- * Get MarketParams for a collateral token.
590
- * Tries cache → API → on-chain idToMarketParams.
591
- */
592
- async findMarketForCollateral(collateralSymbolOrAddress) {
593
- const colInfo = BASE_COLLATERALS[collateralSymbolOrAddress];
594
- const colAddr = (colInfo?.address ?? collateralSymbolOrAddress).toLowerCase();
595
- const cached = this._marketCache.get(colAddr);
596
- if (cached) return cached;
597
- await this.getMarkets();
598
- const fromApi = this._marketCache.get(colAddr);
599
- if (fromApi) return fromApi;
600
- throw new AgetherError(
601
- `No Morpho market found for collateral ${collateralSymbolOrAddress}`,
602
- "MARKET_NOT_FOUND"
603
- );
604
- }
605
- /** Read MarketParams on-chain by market ID (bytes32). */
606
- async getMarketParams(marketId) {
607
- const result = await this.morphoBlue.idToMarketParams(marketId);
608
- return {
609
- loanToken: result.loanToken,
610
- collateralToken: result.collateralToken,
611
- oracle: result.oracle,
612
- irm: result.irm,
613
- lltv: result.lltv
614
- };
615
- }
616
- // ════════════════════════════════════════════════════════
617
- // Position Reads
618
- // ════════════════════════════════════════════════════════
619
- /** Read on-chain position for a specific market. */
620
- async getPosition(marketId) {
621
- const acctAddr = await this.getAccountAddress();
622
- const pos = await this.morphoBlue.position(marketId, acctAddr);
623
- return {
624
- supplyShares: pos.supplyShares,
625
- borrowShares: pos.borrowShares,
626
- collateral: pos.collateral
627
- };
628
- }
629
- /**
630
- * Full status: positions across all discovered markets.
631
- */
632
- async getStatus() {
633
- const acctAddr = await this.getAccountAddress();
634
- const markets = await this.getMarkets();
635
- const positions = [];
636
- let totalDebt = 0n;
637
- for (const m of markets) {
638
- if (!m.collateralAsset || m.collateralAsset.address === ethers2.ZeroAddress) continue;
639
- try {
640
- const pos = await this.morphoBlue.position(m.uniqueKey, acctAddr);
641
- if (pos.collateral === 0n && pos.borrowShares === 0n && pos.supplyShares === 0n) continue;
642
- let debt = 0n;
643
- if (pos.borrowShares > 0n) {
644
- try {
645
- const mkt = await this.morphoBlue.market(m.uniqueKey);
646
- const totalBorrowShares = BigInt(mkt.totalBorrowShares);
647
- const totalBorrowAssets = BigInt(mkt.totalBorrowAssets);
648
- debt = totalBorrowShares > 0n ? BigInt(pos.borrowShares) * totalBorrowAssets / totalBorrowShares : 0n;
649
- totalDebt += debt;
650
- } catch {
651
- }
652
- }
653
- positions.push({
654
- marketId: m.uniqueKey,
655
- collateralToken: m.collateralAsset.symbol,
656
- collateral: ethers2.formatUnits(pos.collateral, m.collateralAsset.decimals),
657
- borrowShares: pos.borrowShares.toString(),
658
- supplyShares: pos.supplyShares.toString(),
659
- debt: ethers2.formatUnits(debt, 6)
660
- });
661
- } catch {
662
- continue;
663
- }
664
- }
665
- return {
666
- agentId: this.agentId || "?",
667
- agentAccount: acctAddr,
668
- totalDebt: ethers2.formatUnits(totalDebt, 6),
669
- positions
670
- };
671
- }
672
- // ════════════════════════════════════════════════════════
673
- // Lending Operations (all via AgentAccount.executeBatch)
674
- // ════════════════════════════════════════════════════════
675
- /**
676
- * Deposit collateral into Morpho Blue.
677
- *
678
- * Flow:
679
- * 1. EOA transfers collateral to AgentAccount
680
- * 2. AgentAccount.executeBatch:
681
- * [collateral.approve(MorphoBlue), Morpho.supplyCollateral(params)]
682
- */
683
- async supplyCollateral(tokenSymbol, amount, marketParams) {
684
- const acctAddr = await this.getAccountAddress();
685
- const colInfo = BASE_COLLATERALS[tokenSymbol];
686
- if (!colInfo) throw new AgetherError(`Unknown collateral: ${tokenSymbol}`, "UNKNOWN_COLLATERAL");
687
- const params = marketParams ?? await this.findMarketForCollateral(tokenSymbol);
688
- const weiAmount = ethers2.parseUnits(amount, colInfo.decimals);
689
- const morphoAddr = this.config.contracts.morphoBlue;
690
- const colToken = new Contract2(colInfo.address, ERC20_ABI, this.wallet);
691
- const transferTx = await colToken.transfer(acctAddr, weiAmount);
692
- await transferTx.wait();
693
- const targets = [colInfo.address, morphoAddr];
694
- const values = [0n, 0n];
695
- const datas = [
696
- erc20Iface.encodeFunctionData("approve", [morphoAddr, weiAmount]),
697
- morphoIface.encodeFunctionData("supplyCollateral", [
698
- this._toTuple(params),
699
- weiAmount,
700
- acctAddr,
701
- "0x"
702
- ])
703
- ];
704
- const receipt = await this.batch(targets, values, datas);
705
- return {
706
- tx: receipt.hash,
707
- collateralToken: tokenSymbol,
708
- amount,
709
- agentAccount: acctAddr
710
- };
711
- }
712
- /**
713
- * Borrow USDC against existing collateral.
714
- *
715
- * AgentAccount.execute: Morpho.borrow(params, amount, 0, account, account)
716
- *
717
- * @param usdcAmount - USDC amount (e.g. '100')
718
- * @param tokenSymbol - collateral symbol to identify which market (default: first with collateral)
719
- */
720
- async borrow(usdcAmount, tokenSymbol, marketParams) {
721
- const acctAddr = await this.getAccountAddress();
722
- const amount = ethers2.parseUnits(usdcAmount, 6);
723
- const morphoAddr = this.config.contracts.morphoBlue;
724
- let params;
725
- let usedToken = tokenSymbol || "WETH";
726
- if (marketParams) {
727
- params = marketParams;
728
- } else if (tokenSymbol) {
729
- params = await this.findMarketForCollateral(tokenSymbol);
730
- } else {
731
- const { params: p, symbol } = await this._findActiveMarket();
732
- params = p;
733
- usedToken = symbol;
734
- }
735
- const data = morphoIface.encodeFunctionData("borrow", [
736
- this._toTuple(params),
737
- amount,
738
- 0n,
739
- acctAddr,
740
- acctAddr
741
- ]);
742
- const receipt = await this.exec(morphoAddr, data);
743
- return {
744
- tx: receipt.hash,
745
- amount: usdcAmount,
746
- collateralToken: usedToken,
747
- agentAccount: acctAddr
748
- };
749
- }
750
- /**
751
- * Deposit collateral AND borrow USDC in one batched transaction.
752
- *
753
- * AgentAccount.executeBatch:
754
- * [collateral.approve, Morpho.supplyCollateral, Morpho.borrow]
755
- *
756
- * The collateral must be transferred to AgentAccount first.
757
- */
758
- async depositAndBorrow(tokenSymbol, collateralAmount, borrowUsdcAmount, marketParams) {
759
- const acctAddr = await this.getAccountAddress();
760
- const colInfo = BASE_COLLATERALS[tokenSymbol];
761
- if (!colInfo) throw new AgetherError(`Unknown collateral: ${tokenSymbol}`, "UNKNOWN_COLLATERAL");
762
- const params = marketParams ?? await this.findMarketForCollateral(tokenSymbol);
763
- const colWei = ethers2.parseUnits(collateralAmount, colInfo.decimals);
764
- const borrowWei = ethers2.parseUnits(borrowUsdcAmount, 6);
765
- const morphoAddr = this.config.contracts.morphoBlue;
766
- const colToken = new Contract2(colInfo.address, ERC20_ABI, this.wallet);
767
- const transferTx = await colToken.transfer(acctAddr, colWei);
768
- await transferTx.wait();
769
- const targets = [colInfo.address, morphoAddr, morphoAddr];
770
- const values = [0n, 0n, 0n];
771
- const datas = [
772
- erc20Iface.encodeFunctionData("approve", [morphoAddr, colWei]),
773
- morphoIface.encodeFunctionData("supplyCollateral", [
774
- this._toTuple(params),
775
- colWei,
776
- acctAddr,
777
- "0x"
778
- ]),
779
- morphoIface.encodeFunctionData("borrow", [
780
- this._toTuple(params),
781
- borrowWei,
782
- 0n,
783
- acctAddr,
784
- acctAddr
785
- ])
786
- ];
787
- const receipt = await this.batch(targets, values, datas);
788
- return {
789
- tx: receipt.hash,
790
- collateralToken: tokenSymbol,
791
- collateralAmount,
792
- borrowAmount: borrowUsdcAmount,
793
- agentAccount: acctAddr
794
- };
795
- }
796
- /**
797
- * Repay borrowed USDC from AgentAccount.
798
- *
799
- * AgentAccount.executeBatch:
800
- * [USDC.approve(MorphoBlue), Morpho.repay(params)]
801
- */
802
- async repay(usdcAmount, tokenSymbol, marketParams) {
803
- const acctAddr = await this.getAccountAddress();
804
- const amount = ethers2.parseUnits(usdcAmount, 6);
805
- const morphoAddr = this.config.contracts.morphoBlue;
806
- const usdcAddr = this.config.contracts.usdc;
807
- let params;
808
- if (marketParams) {
809
- params = marketParams;
810
- } else if (tokenSymbol) {
811
- params = await this.findMarketForCollateral(tokenSymbol);
812
- } else {
813
- const { params: p } = await this._findActiveMarket();
814
- params = p;
815
- }
816
- const targets = [usdcAddr, morphoAddr];
817
- const values = [0n, 0n];
818
- const datas = [
819
- erc20Iface.encodeFunctionData("approve", [morphoAddr, amount]),
820
- morphoIface.encodeFunctionData("repay", [
821
- this._toTuple(params),
822
- amount,
823
- 0n,
824
- acctAddr,
825
- "0x"
826
- ])
827
- ];
828
- const receipt = await this.batch(targets, values, datas);
829
- let remainingDebt = "0";
830
- try {
831
- const status = await this.getStatus();
832
- remainingDebt = status.totalDebt;
833
- } catch {
834
- }
835
- return { tx: receipt.hash, amount: usdcAmount, remainingDebt };
836
- }
837
- /**
838
- * Withdraw collateral from Morpho Blue.
839
- *
840
- * AgentAccount.execute: Morpho.withdrawCollateral(params, amount, account, receiver)
841
- *
842
- * @param receiver - defaults to EOA wallet
843
- */
844
- async withdrawCollateral(tokenSymbol, amount, marketParams, receiver) {
845
- const acctAddr = await this.getAccountAddress();
846
- const colInfo = BASE_COLLATERALS[tokenSymbol];
847
- if (!colInfo) throw new AgetherError(`Unknown collateral: ${tokenSymbol}`, "UNKNOWN_COLLATERAL");
848
- const params = marketParams ?? await this.findMarketForCollateral(tokenSymbol);
849
- const morphoAddr = this.config.contracts.morphoBlue;
850
- const dest = receiver || this.wallet.address;
851
- let weiAmount;
852
- if (amount === "all") {
853
- const markets = await this.getMarkets();
854
- const market = markets.find(
855
- (m) => m.collateralAsset.address.toLowerCase() === colInfo.address.toLowerCase()
856
- );
857
- if (!market) throw new AgetherError("Market not found", "MARKET_NOT_FOUND");
858
- const pos = await this.morphoBlue.position(market.uniqueKey, acctAddr);
859
- weiAmount = pos.collateral;
860
- if (weiAmount === 0n) throw new AgetherError("No collateral to withdraw", "NO_COLLATERAL");
861
- } else {
862
- weiAmount = ethers2.parseUnits(amount, colInfo.decimals);
863
- }
864
- const data = morphoIface.encodeFunctionData("withdrawCollateral", [
865
- this._toTuple(params),
866
- weiAmount,
867
- acctAddr,
868
- dest
869
- ]);
870
- const receipt = await this.exec(morphoAddr, data);
871
- let remainingCollateral = "0";
872
- try {
873
- const markets = await this.getMarkets();
874
- const market = markets.find(
875
- (m) => m.collateralAsset.address.toLowerCase() === colInfo.address.toLowerCase()
876
- );
877
- if (market) {
878
- const pos = await this.morphoBlue.position(market.uniqueKey, acctAddr);
879
- remainingCollateral = ethers2.formatUnits(pos.collateral, colInfo.decimals);
880
- }
881
- } catch {
882
- }
883
- return {
884
- tx: receipt.hash,
885
- token: tokenSymbol,
886
- amount: amount === "all" ? ethers2.formatUnits(weiAmount, colInfo.decimals) : amount,
887
- remainingCollateral,
888
- destination: dest
889
- };
890
- }
891
- /**
892
- * Sponsor: transfer collateral to another agent's AgentAccount.
893
- * (The agent must then supplyCollateral themselves via their own account.)
894
- */
895
- async sponsor(target, tokenSymbol, amount) {
896
- const colInfo = BASE_COLLATERALS[tokenSymbol];
897
- if (!colInfo) throw new AgetherError(`Unknown collateral: ${tokenSymbol}`, "UNKNOWN_COLLATERAL");
898
- let targetAddr;
899
- if (target.address) {
900
- targetAddr = target.address;
901
- } else if (target.agentId) {
902
- targetAddr = await this.accountFactory.getAccount(BigInt(target.agentId));
903
- if (targetAddr === ethers2.ZeroAddress) throw new AgetherError("Target agent has no account", "NO_ACCOUNT");
904
- } else {
905
- throw new AgetherError("Provide agentId or address", "INVALID_TARGET");
906
- }
907
- const weiAmount = ethers2.parseUnits(amount, colInfo.decimals);
908
- const colToken = new Contract2(colInfo.address, ERC20_ABI, this.wallet);
909
- const tx = await colToken.transfer(targetAddr, weiAmount);
910
- const receipt = await tx.wait();
911
- return { tx: receipt.hash, targetAccount: targetAddr, targetAgentId: target.agentId };
912
- }
913
- // ════════════════════════════════════════════════════════
914
- // Reputation (AgentReputation contract)
915
- // ════════════════════════════════════════════════════════
916
- async getCreditScore() {
917
- if (!this.agentId) throw new AgetherError("agentId not set", "NO_AGENT_ID");
918
- return this.agentReputation.getCreditScore(BigInt(this.agentId));
919
- }
920
- async getAttestation() {
921
- if (!this.agentId) throw new AgetherError("agentId not set", "NO_AGENT_ID");
922
- const att = await this.agentReputation.getAttestation(BigInt(this.agentId));
923
- return { score: att.score, timestamp: att.timestamp, signer: att.signer };
924
- }
925
- async isEligible(minScore = 500n) {
926
- if (!this.agentId) throw new AgetherError("agentId not set", "NO_AGENT_ID");
927
- const [eligible, currentScore] = await this.agentReputation.isEligible(BigInt(this.agentId), minScore);
928
- return { eligible, currentScore };
929
- }
930
- async isScoreFresh() {
931
- if (!this.agentId) throw new AgetherError("agentId not set", "NO_AGENT_ID");
932
- const [fresh, age] = await this.agentReputation.isScoreFresh(BigInt(this.agentId));
933
- return { fresh, age };
934
- }
935
- // ════════════════════════════════════════════════════════
936
- // Internal Helpers
937
- // ════════════════════════════════════════════════════════
938
- /**
939
- * Execute a single call via AgentAccount.execute.
940
- */
941
- async exec(target, data, value = 0n) {
942
- const acctAddr = await this.getAccountAddress();
943
- const account = new Contract2(acctAddr, AGENT_ACCOUNT_ABI, this.wallet);
944
- let gasLimit;
945
- try {
946
- const estimate = await account.execute.estimateGas(target, value, data);
947
- gasLimit = estimate * 130n / 100n;
948
- } catch {
949
- gasLimit = 500000n;
950
- }
951
- const tx = await account.execute(target, value, data, { gasLimit });
952
- return tx.wait();
953
- }
954
- /**
955
- * Execute multiple calls via AgentAccount.executeBatch.
956
- */
957
- async batch(targets, values, datas) {
958
- const acctAddr = await this.getAccountAddress();
959
- const account = new Contract2(acctAddr, AGENT_ACCOUNT_ABI, this.wallet);
960
- let gasLimit;
961
- try {
962
- const estimate = await account.executeBatch.estimateGas(targets, values, datas);
963
- gasLimit = estimate * 130n / 100n;
964
- } catch {
965
- gasLimit = 800000n;
966
- }
967
- const tx = await account.executeBatch(targets, values, datas, { gasLimit });
968
- return tx.wait();
969
- }
970
- /** Convert MorphoMarketParams to Solidity tuple. */
971
- _toTuple(p) {
972
- return [p.loanToken, p.collateralToken, p.oracle, p.irm, p.lltv];
973
- }
974
- /** Find the first market where the agent has collateral deposited. */
975
- async _findActiveMarket() {
976
- const acctAddr = await this.getAccountAddress();
977
- const markets = await this.getMarkets();
978
- for (const m of markets) {
979
- if (!m.collateralAsset || m.collateralAsset.address === ethers2.ZeroAddress) continue;
980
- try {
981
- const pos = await this.morphoBlue.position(m.uniqueKey, acctAddr);
982
- if (pos.collateral > 0n) {
983
- return {
984
- params: {
985
- loanToken: m.loanAsset.address,
986
- collateralToken: m.collateralAsset.address,
987
- oracle: m.oracle,
988
- irm: m.irm,
989
- lltv: m.lltv
990
- },
991
- symbol: m.collateralAsset.symbol
992
- };
993
- }
994
- } catch {
995
- continue;
996
- }
997
- }
998
- const params = await this.findMarketForCollateral("WETH");
999
- return { params, symbol: "WETH" };
1000
- }
1001
- };
1002
-
1003
- // src/clients/ScoringClient.ts
1004
- import axios2 from "axios";
1005
-
1006
- // src/clients/X402Client.ts
1007
- import { ethers as ethers3 } from "ethers";
1008
- var USDC_DOMAINS = {
1009
- "eip155:1": { name: "USD Coin", version: "2", address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" },
1010
- "eip155:8453": { name: "USD Coin", version: "2", address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913" },
1011
- "eip155:84532": { name: "USD Coin", version: "2", address: "0x036CbD53842c5426634e7929541eC2318f3dCF7e" },
1012
- "eip155:42161": { name: "USD Coin", version: "2", address: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831" },
1013
- "eip155:10": { name: "USD Coin", version: "2", address: "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85" }
1014
- };
1015
- function chainIdFromNetwork(network) {
1016
- const m = network.match(/^eip155:(\d+)$/);
1017
- return m ? Number(m[1]) : 1;
1018
- }
1019
- var X402Client = class {
1020
- constructor(config) {
1021
- this.config = config;
1022
- const provider = new ethers3.JsonRpcProvider(config.rpcUrl);
1023
- this.wallet = new ethers3.Wallet(config.privateKey, provider);
1024
- }
1025
- async get(url, opts) {
1026
- return this.request(url, { ...opts, method: "GET" });
1027
- }
1028
- async post(url, body, opts) {
1029
- return this.request(url, {
1030
- ...opts,
1031
- method: "POST",
1032
- body: body ? JSON.stringify(body) : void 0,
1033
- headers: { "Content-Type": "application/json", ...opts?.headers }
1034
- });
1035
- }
1036
- getAddress() {
1037
- return this.wallet.address;
1038
- }
1039
- // ──────────── Core request / 402-retry loop ────────────
1040
- async request(url, options) {
1041
- try {
1042
- console.log(" [1/4] Calling resource server\u2026");
1043
- const response = await fetch(url, {
1044
- ...options,
1045
- headers: {
1046
- ...options?.headers,
1047
- "X-Agent-Id": this.config.agentId || ""
1048
- }
1049
- });
1050
- if (response.ok) {
1051
- const data = await response.json();
1052
- return { success: true, data };
1053
- }
1054
- if (response.status !== 402) {
1055
- return { success: false, error: `HTTP ${response.status}: ${await response.text()}` };
1056
- }
1057
- console.log(" [2/4] 402 received \u2014 parsing payment requirements\u2026");
1058
- const parsed = await this.parsePaymentRequired(response);
1059
- if (!parsed) {
1060
- return { success: false, error: "Could not parse payment requirements from 402 response" };
1061
- }
1062
- const { requirements, resource } = parsed;
1063
- console.log(` scheme : ${requirements.scheme}`);
1064
- console.log(` network : ${requirements.network}`);
1065
- console.log(` amount : ${requirements.amount} (atomic)`);
1066
- console.log(` asset : ${requirements.asset}`);
1067
- console.log(` payTo : ${requirements.payTo}`);
1068
- console.log(" [3/4] Signing EIP-3009 transferWithAuthorization\u2026");
1069
- const paymentPayload = await this.buildPaymentPayload(requirements, resource, url);
1070
- const paymentB64 = Buffer.from(JSON.stringify(paymentPayload)).toString("base64");
1071
- await this.riskCheck(paymentPayload, requirements);
1072
- console.log(" [4/4] Retrying with PAYMENT-SIGNATURE header\u2026");
1073
- const paidResponse = await fetch(url, {
1074
- ...options,
1075
- headers: {
1076
- ...options?.headers,
1077
- "X-Agent-Id": this.config.agentId || "",
1078
- // v2 header
1079
- "PAYMENT-SIGNATURE": paymentB64,
1080
- // v1 compat header (some servers still use this)
1081
- "X-PAYMENT": paymentB64
1082
- }
1083
- });
1084
- if (paidResponse.ok) {
1085
- const data = await paidResponse.json();
1086
- const settlementHeader = paidResponse.headers.get("PAYMENT-RESPONSE") || paidResponse.headers.get("X-PAYMENT-RESPONSE");
1087
- let txHash;
1088
- if (settlementHeader) {
1089
- try {
1090
- const settlement = JSON.parse(Buffer.from(settlementHeader, "base64").toString("utf-8"));
1091
- txHash = settlement.transaction;
1092
- } catch {
1093
- }
1094
- }
1095
- return {
1096
- success: true,
1097
- data,
1098
- paymentInfo: {
1099
- amount: requirements.amount,
1100
- asset: requirements.extra?.name || "USDC",
1101
- network: requirements.network,
1102
- txHash
1103
- }
1104
- };
1105
- }
1106
- const errBody = await paidResponse.text();
1107
- return { success: false, error: `Payment rejected (HTTP ${paidResponse.status}): ${errBody}` };
1108
- } catch (error) {
1109
- return { success: false, error: `Request failed: ${error instanceof Error ? error.message : String(error)}` };
1110
- }
1111
- }
1112
- // ──────────── Parse 402 response ────────────
1113
- async parsePaymentRequired(response) {
1114
- const prHeader = response.headers.get("PAYMENT-REQUIRED") || response.headers.get("x-payment-required");
1115
- if (prHeader) {
1116
- try {
1117
- const decoded = JSON.parse(Buffer.from(prHeader, "base64").toString("utf-8"));
1118
- if (decoded.accepts?.length) {
1119
- return { requirements: decoded.accepts[0], resource: decoded.resource };
1120
- }
1121
- } catch {
1122
- }
1123
- }
1124
- try {
1125
- const body = await response.json();
1126
- if (body.accepts && Array.isArray(body.accepts) && body.accepts.length > 0) {
1127
- return { requirements: body.accepts[0], resource: body.resource };
1128
- }
1129
- if (body.paymentRequirements) {
1130
- const pr = Array.isArray(body.paymentRequirements) ? body.paymentRequirements[0] : body.paymentRequirements;
1131
- return { requirements: pr, resource: body.resource };
1132
- }
1133
- if (body.scheme && body.network) {
1134
- return { requirements: body, resource: body.resource };
1135
- }
1136
- } catch {
1137
- }
1138
- const wwwAuth = response.headers.get("WWW-Authenticate");
1139
- if (wwwAuth) {
1140
- const m = wwwAuth.match(/x402[^"]*"([^"]+)"/);
1141
- if (m) {
1142
- try {
1143
- const decoded = JSON.parse(Buffer.from(m[1], "base64").toString("utf-8"));
1144
- const reqs = Array.isArray(decoded) ? decoded[0] : decoded;
1145
- return { requirements: reqs };
1146
- } catch {
1147
- }
1148
- }
1149
- }
1150
- return null;
1151
- }
1152
- // ──────────── Build x402 v2 PaymentPayload with EIP-3009 ────────────
1153
- //
1154
- // If an AgentAccount is configured, we use it as the `from` address
1155
- // (smart wallet pays directly). The AgentAccount implements EIP-1271
1156
- // so USDC's transferWithAuthorization will call isValidSignature()
1157
- // to verify the owner's ECDSA signature. The facilitator detects
1158
- // the >65-byte or smart-wallet case and uses the bytes overload.
1159
- async buildPaymentPayload(reqs, resource, url) {
1160
- const now = Math.floor(Date.now() / 1e3);
1161
- const validAfter = String(now - 60);
1162
- const validBefore = String(now + (reqs.maxTimeoutSeconds || 300));
1163
- const nonce = ethers3.hexlify(ethers3.randomBytes(32));
1164
- const chainId = chainIdFromNetwork(reqs.network);
1165
- const usdcDomain = USDC_DOMAINS[reqs.network] || USDC_DOMAINS["eip155:1"];
1166
- const payerAddress = this.config.accountAddress || this.wallet.address;
1167
- const isSmartWallet = !!this.config.accountAddress;
1168
- const domain = {
1169
- name: usdcDomain.name,
1170
- version: usdcDomain.version,
1171
- chainId,
1172
- verifyingContract: reqs.asset || usdcDomain.address
1173
- };
1174
- const types = {
1175
- TransferWithAuthorization: [
1176
- { name: "from", type: "address" },
1177
- { name: "to", type: "address" },
1178
- { name: "value", type: "uint256" },
1179
- { name: "validAfter", type: "uint256" },
1180
- { name: "validBefore", type: "uint256" },
1181
- { name: "nonce", type: "bytes32" }
1182
- ]
1183
- };
1184
- const value = {
1185
- from: payerAddress,
1186
- // AgentAccount or EOA
1187
- to: reqs.payTo,
1188
- value: reqs.amount,
1189
- validAfter,
1190
- validBefore,
1191
- nonce
1192
- };
1193
- let signature = await this.wallet.signTypedData(domain, types, value);
1194
- if (isSmartWallet) {
1195
- signature = signature + "00";
1196
- }
1197
- if (isSmartWallet) {
1198
- console.log(` \u2713 Signed for AgentAccount ${payerAddress.slice(0, 10)}\u2026 (EIP-1271, chain=${chainId})`);
1199
- } else {
1200
- console.log(` \u2713 Signed (from=${payerAddress.slice(0, 10)}\u2026, chain=${chainId})`);
1201
- }
1202
- return {
1203
- x402Version: 2,
1204
- resource: resource || { url, description: "", mimeType: "application/json" },
1205
- accepted: {
1206
- scheme: reqs.scheme,
1207
- network: reqs.network,
1208
- amount: reqs.amount,
1209
- asset: reqs.asset,
1210
- payTo: reqs.payTo,
1211
- maxTimeoutSeconds: reqs.maxTimeoutSeconds,
1212
- extra: reqs.extra || {}
1213
- },
1214
- payload: {
1215
- signature,
1216
- authorization: {
1217
- from: payerAddress,
1218
- // AgentAccount address — facilitator checks balance here
1219
- to: reqs.payTo,
1220
- value: reqs.amount,
1221
- validAfter,
1222
- validBefore,
1223
- nonce
1224
- }
1225
- }
1226
- };
1227
- }
1228
- // ──────────── Risk check via our backend ────────────
1229
- async riskCheck(paymentPayload, reqs) {
1230
- try {
1231
- const verifyUrl = `${this.config.backendUrl}/x402/verify`;
1232
- const resp = await fetch(verifyUrl, {
1233
- method: "POST",
1234
- headers: {
1235
- "Content-Type": "application/json",
1236
- "X-Agent-Id": this.config.agentId || "",
1237
- ...this.config.accountAddress ? { "X-Agent-Account": this.config.accountAddress } : {}
1238
- },
1239
- body: JSON.stringify({
1240
- x402Version: 2,
1241
- paymentPayload,
1242
- paymentRequirements: reqs
1243
- }),
1244
- signal: AbortSignal.timeout(5e3)
1245
- });
1246
- if (resp.ok) {
1247
- const result = await resp.json();
1248
- const decision = resp.headers.get("X-Risk-Decision") || (result.isValid ? "allow" : "unknown");
1249
- const score = resp.headers.get("X-Risk-Score") || "?";
1250
- console.log(` \u2713 Risk check: ${decision} (score=${score})`);
1251
- } else {
1252
- console.log(` \u26A0 Risk check failed (HTTP ${resp.status}) \u2014 continuing anyway`);
1253
- }
1254
- } catch {
1255
- console.log(" \u26A0 Risk check unavailable \u2014 continuing");
1256
- }
1257
- }
1258
- };
1259
-
1260
201
  // src/clients/ScoringClient.ts
202
+ import axios from "axios";
1261
203
  var ScoringClient = class {
1262
204
  constructor(config) {
1263
205
  this.endpoint = config.endpoint;
1264
- this.client = axios2.create({
206
+ this.client = axios.create({
1265
207
  baseURL: config.endpoint,
1266
208
  headers: { "Content-Type": "application/json" },
1267
209
  timeout: 3e4
@@ -1348,7 +290,7 @@ var ScoringClient = class {
1348
290
  };
1349
291
 
1350
292
  // src/clients/AgentIdentityClient.ts
1351
- import { ethers as ethers4 } from "ethers";
293
+ import { ethers as ethers2 } from "ethers";
1352
294
  var ERC8004_IDENTITY_ABI = [
1353
295
  // Registration
1354
296
  "function register() returns (uint256)",
@@ -1390,8 +332,8 @@ var AgentIdentityClient = class {
1390
332
  this.signer = options.signer;
1391
333
  const identityAddr = options.config.contracts?.identityRegistry || ERC8004_SEPOLIA.identityRegistry;
1392
334
  const reputationAddr = options.config.contracts?.reputationRegistry || ERC8004_SEPOLIA.reputationRegistry;
1393
- this.identityRegistry = new ethers4.Contract(identityAddr, ERC8004_IDENTITY_ABI, this.signer);
1394
- this.reputationRegistry = new ethers4.Contract(reputationAddr, ERC8004_REPUTATION_ABI, this.signer);
335
+ this.identityRegistry = new ethers2.Contract(identityAddr, ERC8004_IDENTITY_ABI, this.signer);
336
+ this.reputationRegistry = new ethers2.Contract(reputationAddr, ERC8004_REPUTATION_ABI, this.signer);
1395
337
  }
1396
338
  // ============ Identity Functions ============
1397
339
  /**
@@ -1458,7 +400,7 @@ var AgentIdentityClient = class {
1458
400
  async registerWithMetadata(agentURI, metadata) {
1459
401
  const metadataEntries = metadata.map((m) => ({
1460
402
  key: m.key,
1461
- value: ethers4.toUtf8Bytes(m.value)
403
+ value: ethers2.toUtf8Bytes(m.value)
1462
404
  }));
1463
405
  const tx = await this.identityRegistry["register(string,tuple(string,bytes)[])"](
1464
406
  agentURI,
@@ -1495,7 +437,7 @@ var AgentIdentityClient = class {
1495
437
  const tx = await this.identityRegistry.setMetadata(
1496
438
  agentId,
1497
439
  key,
1498
- ethers4.toUtf8Bytes(value)
440
+ ethers2.toUtf8Bytes(value)
1499
441
  );
1500
442
  const receipt = await tx.wait();
1501
443
  return receipt.hash;
@@ -1505,7 +447,7 @@ var AgentIdentityClient = class {
1505
447
  */
1506
448
  async getMetadata(agentId, key) {
1507
449
  const value = await this.identityRegistry.getMetadata(agentId, key);
1508
- return ethers4.toUtf8String(value);
450
+ return ethers2.toUtf8String(value);
1509
451
  }
1510
452
  /**
1511
453
  * Transfer agent to new owner
@@ -1539,8 +481,8 @@ var AgentIdentityClient = class {
1539
481
  * Give feedback to an agent
1540
482
  */
1541
483
  async giveFeedback(input) {
1542
- const feedbackHash = ethers4.keccak256(
1543
- ethers4.AbiCoder.defaultAbiCoder().encode(
484
+ const feedbackHash = ethers2.keccak256(
485
+ ethers2.AbiCoder.defaultAbiCoder().encode(
1544
486
  ["uint256", "int128", "uint256"],
1545
487
  [input.agentId, input.value, Date.now()]
1546
488
  )