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.
86 lines
2.6 KiB
JavaScript
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());
|
|
})();
|