sdk-js/src/agentic/NewAgenticClients.ts
Liviu 7b0fc3dc93 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

228 lines
9.6 KiB
TypeScript

/**
* 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<unknown>;
}
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<string> {
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<string> {
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<BondInfo> {
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<boolean> {
const data = BOND_SEL.isBonded + encA(operator) + encB(agentId) + encU(minBond);
return BigInt(await call(this.provider, this.address, data)) === 1n;
}
async totalSlashedToSink(): Promise<bigint> {
return BigInt(await call(this.provider, this.address, BOND_SEL.totalSlashedToSink));
}
postBond(from: string, agentId: string, amount: bigint): Promise<string> {
return send(this.provider, from, this.address, BOND_SEL.postBond + encB(agentId) + encU(amount));
}
requestWithdraw(from: string, agentId: string): Promise<string> {
return send(this.provider, from, this.address, BOND_SEL.requestWithdraw + encB(agentId));
}
withdraw(from: string, operator: string, agentId: string): Promise<string> {
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<string> {
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<bigint> {
return BigInt(await call(this.provider, this.address, REP_SEL.scoreOf + encA(operator) + encB(agentId)));
}
async statsOf(operator: string, agentId: string): Promise<AgentStats> {
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<string> {
// 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<bigint> {
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<string> {
// 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<string> {
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<boolean> {
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<Permission> {
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<string> {
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<string> {
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<string> {
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);
}
}