/** * NewAgenticClients — SDK clients for the 2026-06-08 ship batch. * Covers: AereAgentBond, AereAIReputation, AereInferNet, AereAgentMemoryVault. * * Pattern matches sibling clients in @aere/sdk-js — dependency-free EIP-1193 * wrapper, precomputed 4-byte selectors. Callers supply provider + signer. */ export interface RpcProvider { request(args: { method: string; params: unknown[] }): Promise; } const pad32 = (h: string) => h.toLowerCase().replace(/^0x/, '').padStart(64, '0'); const encU = (n: bigint) => pad32(n.toString(16)); const encA = (a: string) => pad32(a.replace(/^0x/, '')); const encB = (b: string) => pad32(b.replace(/^0x/, '')); async function call(p: RpcProvider, to: string, data: string): Promise { return (await p.request({ method: 'eth_call', params: [{ to, data }, 'latest'] })) as string; } async function send(p: RpcProvider, from: string, to: string, data: string): Promise { return (await p.request({ method: 'eth_sendTransaction', params: [{ from, to, data, value: '0x0' }] })) as string; } function encString(s: string): { offset: bigint; body: string } { const b = Buffer.from(s, 'utf8'); const padded = Buffer.alloc(Math.ceil(b.length / 32) * 32); b.copy(padded); return { offset: BigInt(b.length), body: encU(BigInt(b.length)) + padded.toString('hex') }; } /* ============================== AereAgentBond ============================== */ const BOND_SEL = { AERE: '0xe3b11fda', SINK: '0xae9fc205', WITHDRAWAL_COOLDOWN: '0xfeedab00', bondOf: '0xb416623b', isBonded: '0x52bd7947', isOracle: '0xa97e5c93', oracles: '0x2857373a', totalSlashedToSink: '0x8ca95389', postBond: '0x18b348af', requestWithdraw: '0x1fad8338', withdraw: '0x40e5e9aa', slash: '0x6d68fdd7', } as const; export interface BondInfo { amount: bigint; requestedAt: bigint; lifetimeSlashed: bigint; exists: boolean; } export class AereAgentBondClient { constructor(public readonly provider: RpcProvider, public readonly address: string) {} async bondOf(operator: string, agentId: string): Promise { const res = await call(this.provider, this.address, BOND_SEL.bondOf + encA(operator) + encB(agentId)); const r = res.replace(/^0x/, ''); return { amount: BigInt('0x' + r.slice(0, 64)), requestedAt: BigInt('0x' + r.slice(64, 128)), lifetimeSlashed: BigInt('0x' + r.slice(128, 192)), exists: BigInt('0x' + r.slice(192, 256)) === 1n, }; } async isBonded(operator: string, agentId: string, minBond: bigint): Promise { const data = BOND_SEL.isBonded + encA(operator) + encB(agentId) + encU(minBond); return BigInt(await call(this.provider, this.address, data)) === 1n; } async totalSlashedToSink(): Promise { return BigInt(await call(this.provider, this.address, BOND_SEL.totalSlashedToSink)); } postBond(from: string, agentId: string, amount: bigint): Promise { return send(this.provider, from, this.address, BOND_SEL.postBond + encB(agentId) + encU(amount)); } requestWithdraw(from: string, agentId: string): Promise { return send(this.provider, from, this.address, BOND_SEL.requestWithdraw + encB(agentId)); } withdraw(from: string, operator: string, agentId: string): Promise { return send(this.provider, from, this.address, BOND_SEL.withdraw + encA(operator) + encB(agentId)); } /** Oracle-only. reasonUri is a free-form ipfs:// or https:// link. */ slash(from: string, operator: string, agentId: string, amount: bigint, reasonHash: string, reasonUri: string): Promise { const head = encA(operator) + encB(agentId) + encU(amount) + encB(reasonHash) + encU(0xa0n); const s = encString(reasonUri); return send(this.provider, from, this.address, BOND_SEL.slash + head + s.body); } } /* ============================ AereAIReputation ============================ */ const REP_SEL = { BOND: '0xc1c1d218', MAX_SCORE: '0x27ff6223', SLASH_UNIT: '0xd50a3e76', statsOf: '0xcf212c5f', scoreOf: '0x7377fa36', attest: '0x37637f60', isAttestor: '0x2e2f4e24', attestors: '0xe7eb466f', } as const; export interface AgentStats { positiveCount: bigint; disputeCount: bigint; lifetimeSlashed: bigint; } export class AereAIReputationClient { constructor(public readonly provider: RpcProvider, public readonly address: string) {} async scoreOf(operator: string, agentId: string): Promise { return BigInt(await call(this.provider, this.address, REP_SEL.scoreOf + encA(operator) + encB(agentId))); } async statsOf(operator: string, agentId: string): Promise { const res = (await call(this.provider, this.address, REP_SEL.statsOf + encA(operator) + encB(agentId))).replace(/^0x/, ''); return { positiveCount: BigInt('0x' + res.slice(0, 64)), disputeCount: BigInt('0x' + res.slice(64, 128)), lifetimeSlashed: BigInt('0x' + res.slice(128, 192)), }; } /** delta ∈ {-1, 0, 1}. Attestor-only. */ attest(from: string, operator: string, agentId: string, delta: number, evidenceHash: string, evidenceUri: string): Promise { // int8 is sign-extended to 32 bytes; negatives become 0xFF...FF const deltaWord = delta < 0 ? 'f'.repeat(64 - 2) + (256 + delta).toString(16).padStart(2, '0') : pad32(delta.toString(16)); const head = encA(operator) + encB(agentId) + deltaWord + encB(evidenceHash) + encU(0xa0n); const s = encString(evidenceUri); return send(this.provider, from, this.address, REP_SEL.attest + head + s.body); } } /* ============================== AereInferNet ============================== */ const INFER_SEL = { modelEpochCount: '0xf407005b', modelOf: '0x1548a0e9', epochOf: '0xc1a5ae12', registerModel: '0x703722ac', commitEpoch: '0x7f11fb10', verifyInference: '0xa2a98a64', } as const; export class AereInferNetClient { constructor(public readonly provider: RpcProvider, public readonly address: string) {} async modelEpochCount(provider_: string, modelId: string): Promise { return BigInt(await call(this.provider, this.address, INFER_SEL.modelEpochCount + encA(provider_) + encB(modelId))); } /** RiskTier: 0=Minimal, 1=Limited, 2=High, 3=Unacceptable. */ registerModel( from: string, modelId: string, modelDigest: string, attestationDigest: string, risk: number, modelName: string, attestationUri: string ): Promise { // head = modelId(32) + modelDigest(32) + attestationDigest(32) + risk(32) + offset_name(32) + offset_attUri(32) // tail = nameLen+nameBody, attUriLen+attUriBody const name = encString(modelName); const att = encString(attestationUri); const offsetName = 6n * 32n; const nameBodyLen = name.body.length / 2; // including length word + padded const offsetAtt = offsetName + BigInt(nameBodyLen); const head = encB(modelId) + encB(modelDigest) + encB(attestationDigest) + pad32(risk.toString(16)) + encU(offsetName) + encU(offsetAtt); return send(this.provider, from, this.address, INFER_SEL.registerModel + head + name.body + att.body); } commitEpoch( from: string, modelId: string, epochId: bigint, root: string, inferenceCount: bigint, metadataUri: string ): Promise { const m = encString(metadataUri); const head = encB(modelId) + encU(epochId) + encB(root) + encU(inferenceCount) + encU(0xa0n); return send(this.provider, from, this.address, INFER_SEL.commitEpoch + head + m.body); } } /* =========================== AereAgentMemoryVault ========================== */ const MEM_SEL = { permissionOf: '0xef928267', canReadNow: '0x80b4e9ba', headOf: '0xcc92a9ed', nextVersion: '0xba7badeb', grant: '0xbb9f078e', revoke: '0x88e62721', write: '0x2a7ae64c', } as const; export interface Permission { canRead: boolean; canWrite: boolean; validUntil: bigint; exists: boolean; } export interface MemEntry { contentHash: string; blobUri: string; writer: string; version: bigint; writtenAt: bigint; } export class AereAgentMemoryVaultClient { constructor(public readonly provider: RpcProvider, public readonly address: string) {} async canReadNow(user: string, agent: string, slot: string): Promise { const data = MEM_SEL.canReadNow + encA(user) + encA(agent) + encB(slot); return BigInt(await call(this.provider, this.address, data)) === 1n; } async permissionOf(user: string, agent: string, slot: string): Promise { const data = MEM_SEL.permissionOf + encA(user) + encA(agent) + encB(slot); const r = (await call(this.provider, this.address, data)).replace(/^0x/, ''); return { canRead: BigInt('0x' + r.slice(0, 64)) === 1n, canWrite: BigInt('0x' + r.slice(64, 128)) === 1n, validUntil: BigInt('0x' + r.slice(128, 192)), exists: BigInt('0x' + r.slice(192, 256)) === 1n, }; } /** User grants per-slot permission. validUntil=0n means no expiry. */ grant(from: string, agent: string, slot: string, canRead: boolean, canWrite: boolean, validUntil: bigint): Promise { const data = MEM_SEL.grant + encA(agent) + encB(slot) + pad32(canRead ? '1' : '0') + pad32(canWrite ? '1' : '0') + encU(validUntil); return send(this.provider, from, this.address, data); } revoke(from: string, agent: string, slot: string): Promise { return send(this.provider, from, this.address, MEM_SEL.revoke + encA(agent) + encB(slot)); } /** Agent writes memory entry. contentHash = SHA256(encrypted blob). */ write(from: string, user: string, slot: string, contentHash: string, blobUri: string): Promise { const u = encString(blobUri); const head = encA(user) + encB(slot) + encB(contentHash) + encU(0x80n); return send(this.provider, from, this.address, MEM_SEL.write + head + u.body); } }