@agether/sdk 1.5.4 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -553,26 +553,48 @@ var MorphoClient = class {
553
553
  tx: txHash
554
554
  };
555
555
  }
556
- /** Get ETH / USDC balances for EOA and AgentAccount. */
556
+ /** Get ETH / USDC / collateral balances for EOA and AgentAccount. */
557
557
  async getBalances() {
558
558
  const eoaAddr = this.wallet.address;
559
559
  const usdc = new import_ethers2.Contract(this.config.contracts.usdc, ERC20_ABI, this.provider);
560
560
  const ethBal = await this.provider.getBalance(eoaAddr);
561
561
  const usdcBal = await usdc.balanceOf(eoaAddr);
562
+ const eoaCollateral = {};
563
+ for (const [symbol, info] of Object.entries(BASE_COLLATERALS)) {
564
+ try {
565
+ const token = new import_ethers2.Contract(info.address, ERC20_ABI, this.provider);
566
+ const bal = await token.balanceOf(eoaAddr);
567
+ eoaCollateral[symbol] = import_ethers2.ethers.formatUnits(bal, info.decimals);
568
+ } catch {
569
+ eoaCollateral[symbol] = "0";
570
+ }
571
+ }
562
572
  const result = {
563
573
  agentId: this.agentId || "?",
564
574
  address: eoaAddr,
565
575
  eth: import_ethers2.ethers.formatEther(ethBal),
566
- usdc: import_ethers2.ethers.formatUnits(usdcBal, 6)
576
+ usdc: import_ethers2.ethers.formatUnits(usdcBal, 6),
577
+ collateral: eoaCollateral
567
578
  };
568
579
  try {
569
580
  const acctAddr = await this.getAccountAddress();
570
581
  const acctEth = await this.provider.getBalance(acctAddr);
571
582
  const acctUsdc = await usdc.balanceOf(acctAddr);
583
+ const acctCollateral = {};
584
+ for (const [symbol, info] of Object.entries(BASE_COLLATERALS)) {
585
+ try {
586
+ const token = new import_ethers2.Contract(info.address, ERC20_ABI, this.provider);
587
+ const bal = await token.balanceOf(acctAddr);
588
+ acctCollateral[symbol] = import_ethers2.ethers.formatUnits(bal, info.decimals);
589
+ } catch {
590
+ acctCollateral[symbol] = "0";
591
+ }
592
+ }
572
593
  result.agentAccount = {
573
594
  address: acctAddr,
574
595
  eth: import_ethers2.ethers.formatEther(acctEth),
575
- usdc: import_ethers2.ethers.formatUnits(acctUsdc, 6)
596
+ usdc: import_ethers2.ethers.formatUnits(acctUsdc, 6),
597
+ collateral: acctCollateral
576
598
  };
577
599
  } catch {
578
600
  }
@@ -1072,23 +1094,19 @@ var MorphoClient = class {
1072
1094
  var import_axios2 = __toESM(require("axios"));
1073
1095
 
1074
1096
  // src/clients/X402Client.ts
1075
- var import_ethers3 = require("ethers");
1076
- var USDC_DOMAINS = {
1077
- "eip155:1": { name: "USD Coin", version: "2", address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" },
1078
- "eip155:8453": { name: "USD Coin", version: "2", address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913" },
1079
- "eip155:84532": { name: "USD Coin", version: "2", address: "0x036CbD53842c5426634e7929541eC2318f3dCF7e" },
1080
- "eip155:42161": { name: "USD Coin", version: "2", address: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831" },
1081
- "eip155:10": { name: "USD Coin", version: "2", address: "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85" }
1082
- };
1083
- function chainIdFromNetwork(network) {
1084
- const m = network.match(/^eip155:(\d+)$/);
1085
- return m ? Number(m[1]) : 1;
1086
- }
1097
+ var import_fetch = require("@x402/fetch");
1098
+ var import_client = require("@x402/core/client");
1099
+ var import_client2 = require("@x402/evm/exact/client");
1100
+ var import_accounts = require("viem/accounts");
1087
1101
  var X402Client = class {
1088
1102
  constructor(config) {
1089
1103
  this.config = config;
1090
- const provider = new import_ethers3.ethers.JsonRpcProvider(config.rpcUrl);
1091
- this.wallet = new import_ethers3.ethers.Wallet(config.privateKey, provider);
1104
+ const privateKey = config.privateKey.startsWith("0x") ? config.privateKey : `0x${config.privateKey}`;
1105
+ const signer = (0, import_accounts.privateKeyToAccount)(privateKey);
1106
+ this.address = signer.address;
1107
+ const client = new import_client.x402Client();
1108
+ (0, import_client2.registerExactEvmScheme)(client, { signer });
1109
+ this.paidFetch = (0, import_fetch.wrapFetchWithPayment)(fetch, client);
1092
1110
  }
1093
1111
  async get(url, opts) {
1094
1112
  return this.request(url, { ...opts, method: "GET" });
@@ -1102,13 +1120,13 @@ var X402Client = class {
1102
1120
  });
1103
1121
  }
1104
1122
  getAddress() {
1105
- return this.wallet.address;
1123
+ return this.address;
1106
1124
  }
1107
- // ──────────── Core request / 402-retry loop ────────────
1125
+ // ──────────── Core request — @x402/fetch handles 402 automatically ────────────
1108
1126
  async request(url, options) {
1109
1127
  try {
1110
- console.log(" [1/4] Calling resource server\u2026");
1111
- const response = await fetch(url, {
1128
+ console.log(` [x402] ${options?.method || "GET"} ${url}`);
1129
+ const response = await this.paidFetch(url, {
1112
1130
  ...options,
1113
1131
  headers: {
1114
1132
  ...options?.headers,
@@ -1117,45 +1135,13 @@ var X402Client = class {
1117
1135
  });
1118
1136
  if (response.ok) {
1119
1137
  const data = await response.json();
1120
- return { success: true, data };
1121
- }
1122
- if (response.status !== 402) {
1123
- return { success: false, error: `HTTP ${response.status}: ${await response.text()}` };
1124
- }
1125
- console.log(" [2/4] 402 received \u2014 parsing payment requirements\u2026");
1126
- const parsed = await this.parsePaymentRequired(response);
1127
- if (!parsed) {
1128
- return { success: false, error: "Could not parse payment requirements from 402 response" };
1129
- }
1130
- const { requirements, resource } = parsed;
1131
- console.log(` scheme : ${requirements.scheme}`);
1132
- console.log(` network : ${requirements.network}`);
1133
- console.log(` amount : ${requirements.amount} (atomic)`);
1134
- console.log(` asset : ${requirements.asset}`);
1135
- console.log(` payTo : ${requirements.payTo}`);
1136
- console.log(" [3/4] Signing EIP-3009 transferWithAuthorization\u2026");
1137
- const paymentPayload = await this.buildPaymentPayload(requirements, resource, url);
1138
- const paymentB64 = Buffer.from(JSON.stringify(paymentPayload)).toString("base64");
1139
- await this.riskCheck(paymentPayload, requirements);
1140
- console.log(" [4/4] Retrying with PAYMENT-SIGNATURE header\u2026");
1141
- const paidResponse = await fetch(url, {
1142
- ...options,
1143
- headers: {
1144
- ...options?.headers,
1145
- "X-Agent-Id": this.config.agentId || "",
1146
- // v2 header
1147
- "PAYMENT-SIGNATURE": paymentB64,
1148
- // v1 compat header (some servers still use this)
1149
- "X-PAYMENT": paymentB64
1150
- }
1151
- });
1152
- if (paidResponse.ok) {
1153
- const data = await paidResponse.json();
1154
- const settlementHeader = paidResponse.headers.get("PAYMENT-RESPONSE") || paidResponse.headers.get("X-PAYMENT-RESPONSE");
1138
+ const paymentResponse = response.headers.get("PAYMENT-RESPONSE");
1155
1139
  let txHash;
1156
- if (settlementHeader) {
1140
+ if (paymentResponse) {
1157
1141
  try {
1158
- const settlement = JSON.parse(Buffer.from(settlementHeader, "base64").toString("utf-8"));
1142
+ const settlement = JSON.parse(
1143
+ Buffer.from(paymentResponse, "base64").toString("utf-8")
1144
+ );
1159
1145
  txHash = settlement.transaction;
1160
1146
  } catch {
1161
1147
  }
@@ -1163,164 +1149,26 @@ var X402Client = class {
1163
1149
  return {
1164
1150
  success: true,
1165
1151
  data,
1166
- paymentInfo: {
1167
- amount: requirements.amount,
1168
- asset: requirements.extra?.name || "USDC",
1169
- network: requirements.network,
1170
- txHash
1171
- }
1152
+ ...txHash ? {
1153
+ paymentInfo: {
1154
+ amount: "",
1155
+ asset: "USDC",
1156
+ network: "eip155:8453",
1157
+ txHash
1158
+ }
1159
+ } : {}
1172
1160
  };
1173
1161
  }
1174
- const errBody = await paidResponse.text();
1175
- return { success: false, error: `Payment rejected (HTTP ${paidResponse.status}): ${errBody}` };
1162
+ const errBody = await response.text();
1163
+ return {
1164
+ success: false,
1165
+ error: `HTTP ${response.status}: ${errBody}`
1166
+ };
1176
1167
  } catch (error) {
1177
- return { success: false, error: `Request failed: ${error instanceof Error ? error.message : String(error)}` };
1178
- }
1179
- }
1180
- // ──────────── Parse 402 response ────────────
1181
- async parsePaymentRequired(response) {
1182
- const prHeader = response.headers.get("PAYMENT-REQUIRED") || response.headers.get("x-payment-required");
1183
- if (prHeader) {
1184
- try {
1185
- const decoded = JSON.parse(Buffer.from(prHeader, "base64").toString("utf-8"));
1186
- if (decoded.accepts?.length) {
1187
- return { requirements: decoded.accepts[0], resource: decoded.resource };
1188
- }
1189
- } catch {
1190
- }
1191
- }
1192
- try {
1193
- const body = await response.json();
1194
- if (body.accepts && Array.isArray(body.accepts) && body.accepts.length > 0) {
1195
- return { requirements: body.accepts[0], resource: body.resource };
1196
- }
1197
- if (body.paymentRequirements) {
1198
- const pr = Array.isArray(body.paymentRequirements) ? body.paymentRequirements[0] : body.paymentRequirements;
1199
- return { requirements: pr, resource: body.resource };
1200
- }
1201
- if (body.scheme && body.network) {
1202
- return { requirements: body, resource: body.resource };
1203
- }
1204
- } catch {
1205
- }
1206
- const wwwAuth = response.headers.get("WWW-Authenticate");
1207
- if (wwwAuth) {
1208
- const m = wwwAuth.match(/x402[^"]*"([^"]+)"/);
1209
- if (m) {
1210
- try {
1211
- const decoded = JSON.parse(Buffer.from(m[1], "base64").toString("utf-8"));
1212
- const reqs = Array.isArray(decoded) ? decoded[0] : decoded;
1213
- return { requirements: reqs };
1214
- } catch {
1215
- }
1216
- }
1217
- }
1218
- return null;
1219
- }
1220
- // ──────────── Build x402 v2 PaymentPayload with EIP-3009 ────────────
1221
- //
1222
- // If an AgentAccount is configured, we use it as the `from` address
1223
- // (smart wallet pays directly). The AgentAccount implements EIP-1271
1224
- // so USDC's transferWithAuthorization will call isValidSignature()
1225
- // to verify the owner's ECDSA signature. The facilitator detects
1226
- // the >65-byte or smart-wallet case and uses the bytes overload.
1227
- async buildPaymentPayload(reqs, resource, url) {
1228
- const now = Math.floor(Date.now() / 1e3);
1229
- const validAfter = String(now - 60);
1230
- const validBefore = String(now + (reqs.maxTimeoutSeconds || 300));
1231
- const nonce = import_ethers3.ethers.hexlify(import_ethers3.ethers.randomBytes(32));
1232
- const chainId = chainIdFromNetwork(reqs.network);
1233
- const usdcDomain = USDC_DOMAINS[reqs.network] || USDC_DOMAINS["eip155:1"];
1234
- const payerAddress = this.config.accountAddress || this.wallet.address;
1235
- const isSmartWallet = !!this.config.accountAddress;
1236
- const domain = {
1237
- name: usdcDomain.name,
1238
- version: usdcDomain.version,
1239
- chainId,
1240
- verifyingContract: reqs.asset || usdcDomain.address
1241
- };
1242
- const types = {
1243
- TransferWithAuthorization: [
1244
- { name: "from", type: "address" },
1245
- { name: "to", type: "address" },
1246
- { name: "value", type: "uint256" },
1247
- { name: "validAfter", type: "uint256" },
1248
- { name: "validBefore", type: "uint256" },
1249
- { name: "nonce", type: "bytes32" }
1250
- ]
1251
- };
1252
- const value = {
1253
- from: payerAddress,
1254
- // AgentAccount or EOA
1255
- to: reqs.payTo,
1256
- value: reqs.amount,
1257
- validAfter,
1258
- validBefore,
1259
- nonce
1260
- };
1261
- let signature = await this.wallet.signTypedData(domain, types, value);
1262
- if (isSmartWallet) {
1263
- signature = signature + "00";
1264
- }
1265
- if (isSmartWallet) {
1266
- console.log(` \u2713 Signed for AgentAccount ${payerAddress.slice(0, 10)}\u2026 (EIP-1271, chain=${chainId})`);
1267
- } else {
1268
- console.log(` \u2713 Signed (from=${payerAddress.slice(0, 10)}\u2026, chain=${chainId})`);
1269
- }
1270
- return {
1271
- x402Version: 2,
1272
- resource: resource || { url, description: "", mimeType: "application/json" },
1273
- accepted: {
1274
- scheme: reqs.scheme,
1275
- network: reqs.network,
1276
- amount: reqs.amount,
1277
- asset: reqs.asset,
1278
- payTo: reqs.payTo,
1279
- maxTimeoutSeconds: reqs.maxTimeoutSeconds,
1280
- extra: reqs.extra || {}
1281
- },
1282
- payload: {
1283
- signature,
1284
- authorization: {
1285
- from: payerAddress,
1286
- // AgentAccount address — facilitator checks balance here
1287
- to: reqs.payTo,
1288
- value: reqs.amount,
1289
- validAfter,
1290
- validBefore,
1291
- nonce
1292
- }
1293
- }
1294
- };
1295
- }
1296
- // ──────────── Risk check via our backend ────────────
1297
- async riskCheck(paymentPayload, reqs) {
1298
- try {
1299
- const verifyUrl = `${this.config.backendUrl}/x402/verify`;
1300
- const resp = await fetch(verifyUrl, {
1301
- method: "POST",
1302
- headers: {
1303
- "Content-Type": "application/json",
1304
- "X-Agent-Id": this.config.agentId || "",
1305
- ...this.config.accountAddress ? { "X-Agent-Account": this.config.accountAddress } : {}
1306
- },
1307
- body: JSON.stringify({
1308
- x402Version: 2,
1309
- paymentPayload,
1310
- paymentRequirements: reqs
1311
- }),
1312
- signal: AbortSignal.timeout(5e3)
1313
- });
1314
- if (resp.ok) {
1315
- const result = await resp.json();
1316
- const decision = resp.headers.get("X-Risk-Decision") || (result.isValid ? "allow" : "unknown");
1317
- const score = resp.headers.get("X-Risk-Score") || "?";
1318
- console.log(` \u2713 Risk check: ${decision} (score=${score})`);
1319
- } else {
1320
- console.log(` \u26A0 Risk check failed (HTTP ${resp.status}) \u2014 continuing anyway`);
1321
- }
1322
- } catch {
1323
- console.log(" \u26A0 Risk check unavailable \u2014 continuing");
1168
+ return {
1169
+ success: false,
1170
+ error: `Request failed: ${error instanceof Error ? error.message : String(error)}`
1171
+ };
1324
1172
  }
1325
1173
  }
1326
1174
  };
@@ -1416,7 +1264,7 @@ var ScoringClient = class {
1416
1264
  };
1417
1265
 
1418
1266
  // src/clients/AgentIdentityClient.ts
1419
- var import_ethers4 = require("ethers");
1267
+ var import_ethers3 = require("ethers");
1420
1268
  var ERC8004_IDENTITY_ABI = [
1421
1269
  // Registration
1422
1270
  "function register() returns (uint256)",
@@ -1458,8 +1306,8 @@ var AgentIdentityClient = class {
1458
1306
  this.signer = options.signer;
1459
1307
  const identityAddr = options.config.contracts?.identityRegistry || ERC8004_SEPOLIA.identityRegistry;
1460
1308
  const reputationAddr = options.config.contracts?.reputationRegistry || ERC8004_SEPOLIA.reputationRegistry;
1461
- this.identityRegistry = new import_ethers4.ethers.Contract(identityAddr, ERC8004_IDENTITY_ABI, this.signer);
1462
- this.reputationRegistry = new import_ethers4.ethers.Contract(reputationAddr, ERC8004_REPUTATION_ABI, this.signer);
1309
+ this.identityRegistry = new import_ethers3.ethers.Contract(identityAddr, ERC8004_IDENTITY_ABI, this.signer);
1310
+ this.reputationRegistry = new import_ethers3.ethers.Contract(reputationAddr, ERC8004_REPUTATION_ABI, this.signer);
1463
1311
  }
1464
1312
  // ============ Identity Functions ============
1465
1313
  /**
@@ -1526,7 +1374,7 @@ var AgentIdentityClient = class {
1526
1374
  async registerWithMetadata(agentURI, metadata) {
1527
1375
  const metadataEntries = metadata.map((m) => ({
1528
1376
  key: m.key,
1529
- value: import_ethers4.ethers.toUtf8Bytes(m.value)
1377
+ value: import_ethers3.ethers.toUtf8Bytes(m.value)
1530
1378
  }));
1531
1379
  const tx = await this.identityRegistry["register(string,tuple(string,bytes)[])"](
1532
1380
  agentURI,
@@ -1563,7 +1411,7 @@ var AgentIdentityClient = class {
1563
1411
  const tx = await this.identityRegistry.setMetadata(
1564
1412
  agentId,
1565
1413
  key,
1566
- import_ethers4.ethers.toUtf8Bytes(value)
1414
+ import_ethers3.ethers.toUtf8Bytes(value)
1567
1415
  );
1568
1416
  const receipt = await tx.wait();
1569
1417
  return receipt.hash;
@@ -1573,7 +1421,7 @@ var AgentIdentityClient = class {
1573
1421
  */
1574
1422
  async getMetadata(agentId, key) {
1575
1423
  const value = await this.identityRegistry.getMetadata(agentId, key);
1576
- return import_ethers4.ethers.toUtf8String(value);
1424
+ return import_ethers3.ethers.toUtf8String(value);
1577
1425
  }
1578
1426
  /**
1579
1427
  * Transfer agent to new owner
@@ -1607,8 +1455,8 @@ var AgentIdentityClient = class {
1607
1455
  * Give feedback to an agent
1608
1456
  */
1609
1457
  async giveFeedback(input) {
1610
- const feedbackHash = import_ethers4.ethers.keccak256(
1611
- import_ethers4.ethers.AbiCoder.defaultAbiCoder().encode(
1458
+ const feedbackHash = import_ethers3.ethers.keccak256(
1459
+ import_ethers3.ethers.AbiCoder.defaultAbiCoder().encode(
1612
1460
  ["uint256", "int128", "uint256"],
1613
1461
  [input.agentId, input.value, Date.now()]
1614
1462
  )