// express-402-paid-endpoint.js // // Drop-in example: a paid `/v1/inference` endpoint that charges $0.0125 // in USDC.e per call via AERE402 settlement on Chain 2800. // // Run: // yarn add express @aere/sdk-js ethers // FACILITATOR=0x... PAYEE=0x... PROVIDER_PRIVATE_KEY=0x... node express-402-paid-endpoint.js // // Then the agent-side does: // 1. curl http://localhost:3000/v1/inference // → 402 with X-AERE402-Quote JSON header // 2. agent EIP-712-signs the quote using its registered signing key // 3. curl -H "X-AERE402-Sig: 0x.." -H "X-AERE402-AgentId: 1234" \ // -H "X-AERE402-Quote: " \ // http://localhost:3000/v1/inference // → 200 with the actual inference output, X-AERE402-TxHash header set const express = require('express'); const { ethers } = require('ethers'); const { createAere402Middleware } = require('@aere/sdk-js'); const FACILITATOR = process.env.FACILITATOR; const USDC_E = process.env.USDC_E ?? '0x0000000000000000000000000000000000000000'; const PAYEE = process.env.PAYEE; const PROVIDER_PK = process.env.PROVIDER_PRIVATE_KEY; const RPC_URL = process.env.RPC_URL ?? 'https://rpc.aere.network'; const CHAIN_ID = parseInt(process.env.CHAIN_ID ?? '2800', 10); if (!FACILITATOR || !PAYEE || !PROVIDER_PK) { console.error('FACILITATOR, PAYEE, and PROVIDER_PRIVATE_KEY env vars required'); process.exit(1); } const provider = new ethers.JsonRpcProvider(RPC_URL); const providerWallet = new ethers.Wallet(PROVIDER_PK, provider); // Real `settle()` ABI from AERE402Facilitator. Pulled minimal — just what we call. const FAC_ABI = [ 'function settle(uint256 agentId, address token, address payee, uint256 amount, bytes32 resourceId, uint256 nonce, uint256 deadline, bytes signature) external', ]; const facContract = new ethers.Contract(FACILITATOR, FAC_ABI, providerWallet); const charge = createAere402Middleware({ facilitator: FACILITATOR, chainId: CHAIN_ID, token: USDC_E, payee: PAYEE, pricer: () => 12500n, // $0.0125 in USDC.e (6 decimals) submit: async (auth, signature) => { const tx = await facContract.settle( BigInt(auth.agentId), auth.token, auth.payee, BigInt(auth.amount), auth.resourceId, BigInt(auth.nonce), BigInt(auth.deadline), signature, ); const rcpt = await tx.wait(); return rcpt.hash; }, }); const app = express(); app.get('/v1/inference', charge, (req, res) => { // The middleware paid us — we can read req.aere402 for receipt info. const { txHash, auth } = req.aere402; console.log(`paid call: agent=${auth.agentId} amount=${auth.amount} tx=${txHash}`); res.json({ output: 'Pretend this is an LLM completion.', aere402: { txHash, amountCharged: auth.amount, token: auth.token }, }); }); const PORT = parseInt(process.env.PORT ?? '3000', 10); app.listen(PORT, () => { console.log(`paid endpoint running at http://localhost:${PORT}/v1/inference`); console.log(`facilitator: ${FACILITATOR}`); console.log(`payee: ${PAYEE}`); console.log(`provider wallet: ${providerWallet.address}`); });