UNPKG

@agentic-trust/8004-sdk

Version:

ERC-8004 Trustless Agents SDK - A TypeScript SDK for interacting with ERC-8004 compliant implementations

153 lines 7.62 kB
/** * Validation Client for ERC-8004 * Handles validation requests and responses */ import ValidationRegistryABI from './abis/ValidationRegistry.json'; import { ethers } from 'ethers'; export class ValidationClient { adapter; contractAddress; constructor(adapter, contractAddress) { this.adapter = adapter; this.contractAddress = contractAddress; } /** * Request validation from a validator * Spec: function validationRequest(address validatorAddress, uint256 agentId, string requestUri, bytes32 requestHash) * Note: MUST be called by owner or operator of agentId * Note: requestHash MUST be keccak256 of the content at requestUri * * @param params - Validation request parameters * @returns Transaction result with requestHash */ async validationRequest(params) { const result = await this.adapter.send(this.contractAddress, ValidationRegistryABI, 'validationRequest', [params.validatorAddress, params.agentId, params.requestUri, params.requestHash]); return { txHash: result.hash || result.txHash, requestHash: params.requestHash, }; } /** * Provide a validation response * Spec: function validationResponse(bytes32 requestHash, uint8 response, string responseUri, bytes32 responseHash, bytes32 tag) * Note: MUST be called by the validatorAddress specified in the original request * Note: Can be called multiple times for the same requestHash * * @param params - Validation response parameters * @returns Transaction result */ async validationResponse(params) { // Validate response is 0-100 if (params.response < 0 || params.response > 100) { throw new Error('Response MUST be between 0 and 100'); } // Convert optional parameters to proper format const responseUri = params.responseUri || ''; const responseHash = params.responseHash || ethers.ZeroHash; const tag = params.tag ? ethers.id(params.tag).slice(0, 66) : ethers.ZeroHash; const result = await this.adapter.send(this.contractAddress, ValidationRegistryABI, 'validationResponse', [params.requestHash, params.response, responseUri, responseHash, tag]); return { txHash: result.hash || result.txHash }; } /** * Get the identity registry address * Spec: function getIdentityRegistry() external view returns (address identityRegistry) */ async getIdentityRegistry() { return await this.adapter.call(this.contractAddress, ValidationRegistryABI, 'getIdentityRegistry', []); } /** * Get validation status for a request * Spec (new): function getValidationStatus(bytes32 requestHash) returns (address validatorAddress, uint256 agentId, uint8 response, bytes32 responseHash, bytes32 tag, uint256 lastUpdate) * Spec (old): function getValidationStatus(bytes32 requestHash) returns (address validatorAddress, uint256 agentId, uint8 response, bytes32 tag, uint256 lastUpdate) * Note: Backward compatible with both old and new contract versions * * @param requestHash - The request hash (bytes32) * @returns Validation status */ async getValidationStatus(requestHash) { try { // Try with new ABI first (6 return values) const result = await this.adapter.call(this.contractAddress, ValidationRegistryABI, 'getValidationStatus', [requestHash]); return { validatorAddress: result.validatorAddress || result[0], agentId: BigInt(result.agentId || result[1]), response: Number(result.response || result[2]), responseHash: result.responseHash || result[3], tag: result.tag || result[4], lastUpdate: BigInt(result.lastUpdate || result[5]), }; } catch (error) { // If decoding fails, try with old ABI (5 return values, no responseHash) if (error.code === 'BAD_DATA' || error.message?.includes('could not decode result data')) { // Create old ABI for getValidationStatus without responseHash const oldABI = [ { inputs: [{ internalType: 'bytes32', name: 'requestHash', type: 'bytes32' }], name: 'getValidationStatus', outputs: [ { internalType: 'address', name: 'validatorAddress', type: 'address' }, { internalType: 'uint256', name: 'agentId', type: 'uint256' }, { internalType: 'uint8', name: 'response', type: 'uint8' }, { internalType: 'bytes32', name: 'tag', type: 'bytes32' }, { internalType: 'uint256', name: 'lastUpdate', type: 'uint256' } ], stateMutability: 'view', type: 'function' } ]; const result = await this.adapter.call(this.contractAddress, oldABI, 'getValidationStatus', [requestHash]); return { validatorAddress: result.validatorAddress || result[0], agentId: BigInt(result.agentId || result[1]), response: Number(result.response || result[2]), responseHash: ethers.ZeroHash, // Default for old contracts tag: result.tag || result[3], lastUpdate: BigInt(result.lastUpdate || result[4]), }; } // Re-throw other errors throw error; } } /** * Get validation summary for an agent * Spec: function getSummary(uint256 agentId, address[] validatorAddresses, bytes32 tag) returns (uint64 count, uint8 avgResponse) * Note: agentId is ONLY mandatory parameter, validatorAddresses and tag are OPTIONAL filters * * @param agentId - The agent ID (MANDATORY) * @param validatorAddresses - OPTIONAL filter by specific validators * @param tag - OPTIONAL filter by tag * @returns Summary statistics */ async getSummary(agentId, validatorAddresses, tag) { const validators = validatorAddresses || []; const tagBytes = tag ? ethers.id(tag).slice(0, 66) : ethers.ZeroHash; const result = await this.adapter.call(this.contractAddress, ValidationRegistryABI, 'getSummary', [agentId, validators, tagBytes]); return { count: BigInt(result.count || result[0]), avgResponse: Number(result.avgResponse || result[1]), }; } /** * Get all validation request hashes for an agent * Spec: function getAgentValidations(uint256 agentId) returns (bytes32[] requestHashes) * * @param agentId - The agent ID * @returns Array of request hashes */ async getAgentValidations(agentId) { return await this.adapter.call(this.contractAddress, ValidationRegistryABI, 'getAgentValidations', [agentId]); } /** * Get all request hashes for a validator * Spec: function getValidatorRequests(address validatorAddress) returns (bytes32[] requestHashes) * * @param validatorAddress - The validator address * @returns Array of request hashes */ async getValidatorRequests(validatorAddress) { return await this.adapter.call(this.contractAddress, ValidationRegistryABI, 'getValidatorRequests', [validatorAddress]); } } //# sourceMappingURL=ValidationClient.js.map