// agent-402-client.js // // Drop-in example: agent-side AERE402 client. Calls a paid endpoint, // receives 402, signs the quote via the agent's signing key, retries. // // Run: // yarn add ethers // AGENT_PRIVATE_KEY=0x... AGENT_ID=1234 ENDPOINT=http://localhost:3000/v1/inference node agent-402-client.js // // Prereq: the agent's signing key (AGENT_PRIVATE_KEY) must already be // registered on AereAgent with sufficient prepaid balance + un-exceeded // rate limits. const { ethers } = require('ethers'); const AGENT_PK = process.env.AGENT_PRIVATE_KEY; const AGENT_ID = process.env.AGENT_ID; const ENDPOINT = process.env.ENDPOINT ?? 'http://localhost:3000/v1/inference'; if (!AGENT_PK || !AGENT_ID) { console.error('AGENT_PRIVATE_KEY + AGENT_ID env required'); process.exit(1); } const signer = new ethers.Wallet(AGENT_PK); (async () => { console.log(`agent ${AGENT_ID} calling ${ENDPOINT}...`); // 1. Unpaid request. const r1 = await fetch(ENDPOINT); if (r1.status !== 402) { console.log(`unexpected status ${r1.status} on first call`); console.log(await r1.text()); return; } const quoteJson = r1.headers.get('x-aere402-quote'); if (!quoteJson) throw new Error('server did not return X-AERE402-Quote'); const quote = JSON.parse(quoteJson); console.log(' received quote:', quote); // 2. Build EIP-712 domain + types. const domain = { name: 'AERE402Facilitator', version: '1', chainId: quote.chainId, verifyingContract: quote.facilitator, }; const types = { PaymentAuth: [ { name: 'agentId', type: 'uint256' }, { name: 'token', type: 'address' }, { name: 'payee', type: 'address' }, { name: 'amount', type: 'uint256' }, { name: 'resourceId', type: 'bytes32' }, { name: 'nonce', type: 'uint256' }, { name: 'deadline', type: 'uint256' }, ], }; const value = { agentId: BigInt(AGENT_ID), token: quote.token, payee: quote.payee, amount: BigInt(quote.amount), resourceId: quote.resourceId, nonce: BigInt(quote.nonce), deadline: BigInt(quote.deadline), }; // 3. Sign. const signature = await signer.signTypedData(domain, types, value); console.log(` signed: ${signature.slice(0, 18)}...`); // 4. Retry with the signature. const r2 = await fetch(ENDPOINT, { headers: { 'X-AERE402-Sig': signature, 'X-AERE402-AgentId': AGENT_ID, 'X-AERE402-Quote': quoteJson, }, }); console.log(` retry status: ${r2.status}`); console.log(` tx hash: ${r2.headers.get('x-aere402-txhash')}`); console.log(' body:', await r2.json()); })();