sdk-js/examples/agent-402-client.js
Liviu 99abfff98a feat(sdk): SDK clients for the 2026-06-08 ship batch
Six new clients (dependency-free EIP-1193 wrappers, precomputed
4-byte selectors, ABI tuple/string encoders inline):

- AereAgentBondClient        — bondOf, isBonded, postBond, requestWithdraw,
                               withdraw, slash; oracle-only on slash
- AereAIReputationClient     — scoreOf, statsOf, attest (delta -1/0/+1)
- AereInferNetClient         — modelEpochCount, registerModel, commitEpoch;
                               EU AI Act Article 12 provider surface
- AereAgentMemoryVaultClient — grant, revoke, write, canReadNow,
                               permissionOf; user-owned namespace
- AereAttestationGatewayClient — publishSchema, setAttestor, attest,
                                 revoke, isValidNow, subjectCurrentlyAttested
- AereCompliancePoolClient   — deposit, withdraw, publishAssociationRoot,
                               setComplianceProvider; Privacy Pools surface

All exported from the package barrel. Zero TS errors.
2026-06-08 03:33:52 +03:00

86 lines
2.6 KiB
JavaScript

// 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());
})();