Overview
This guide provides comprehensive examples for integrating with the ZKScore Trust Registry contract. It covers attestation creation, verification workflows, trust score calculation, and best practices for production deployments.Always test your integration on testnet before deploying to mainnet. Use the testnet contract addresses provided in the Contract Overview section.
Web3 Integration
Basic Setup
Copy
import { ethers } from 'ethers';
// Contract configuration
const TRUST_REGISTRY_ADDRESS = '0x4567890123456789012345678901234567890123';
const SCHEMA_REGISTRY_ADDRESS = '0x6789012345678901234567890123456789012345';
// Initialize provider
const provider = new ethers.providers.JsonRpcProvider('https://mainnet.infura.io/v3/YOUR_KEY');
// Initialize contracts
const trustRegistry = new ethers.Contract(
TRUST_REGISTRY_ADDRESS,
TRUST_REGISTRY_ABI,
provider
);
const schemaRegistry = new ethers.Contract(
SCHEMA_REGISTRY_ADDRESS,
SCHEMA_REGISTRY_ABI,
provider
);
// For transactions
const signer = provider.getSigner();
const trustRegistryWithSigner = trustRegistry.connect(signer);
Integration Class
Copy
class TrustRegistryIntegration {
constructor(provider, registryAddress, abi) {
this.provider = provider;
this.contract = new ethers.Contract(registryAddress, abi, provider);
this.contractWithSigner = null;
this.schemaCache = new Map();
}
setSigner(signer) {
this.contractWithSigner = this.contract.connect(signer);
}
// Register a new schema
async registerSchema(definition, revocable = true) {
if (!this.contractWithSigner) {
throw new Error('Signer not set');
}
try {
const tx = await this.contractWithSigner.registerSchema(
definition,
ethers.constants.AddressZero, // No resolver
revocable
);
const receipt = await tx.wait();
const event = receipt.events.find(e => e.event === 'SchemaRegistered');
const schemaUID = event.args.uid;
// Cache schema
this.schemaCache.set(schemaUID, { definition, revocable });
return {
success: true,
schemaUID,
definition,
revocable,
transactionHash: receipt.transactionHash
};
} catch (error) {
return {
success: false,
error: error.message
};
}
}
// Create attestation
async attest(recipient, schemaUID, data, expirationTime = 0) {
if (!this.contractWithSigner) {
throw new Error('Signer not set');
}
try {
const attestationRequest = {
schema: schemaUID,
data: {
recipient,
expirationTime,
revocable: true,
refUID: ethers.constants.HashZero,
data
}
};
const tx = await this.contractWithSigner.attest(attestationRequest);
const receipt = await tx.wait();
const event = receipt.events.find(e => e.event === 'Attested');
return {
success: true,
uid: event.args.uid,
recipient: event.args.recipient,
attester: event.args.attester,
schema: event.args.schema,
transactionHash: receipt.transactionHash
};
} catch (error) {
return {
success: false,
error: error.message
};
}
}
// Get attestation
async getAttestation(uid) {
try {
const attestation = await this.contract.getAttestation(uid);
return {
success: true,
attestation: {
uid: attestation.uid,
schema: attestation.schema,
attester: attestation.attester,
recipient: attestation.recipient,
time: attestation.time,
expirationTime: attestation.expirationTime,
revocable: attestation.revocable,
revoked: attestation.revoked,
data: attestation.data
}
};
} catch (error) {
return {
success: false,
error: error.message
};
}
}
// Get user attestations
async getUserAttestations(address, schemaUID = ethers.constants.HashZero) {
try {
const uids = await this.contract.getReceivedAttestationUIDs(
address,
schemaUID,
0,
100,
true
);
const attestations = await Promise.all(
uids.map(uid => this.getAttestation(uid))
);
return {
success: true,
count: uids.length,
attestations: attestations
.filter(a => a.success)
.map(a => a.attestation)
};
} catch (error) {
return {
success: false,
error: error.message
};
}
}
// Verify attestation validity
async isValid(uid) {
try {
const isValid = await this.contract.isAttestationValid(uid);
return {
success: true,
isValid
};
} catch (error) {
return {
success: false,
error: error.message
};
}
}
}
// Usage
const integration = new TrustRegistryIntegration(
provider,
TRUST_REGISTRY_ADDRESS,
TRUST_REGISTRY_ABI
);
integration.setSigner(signer);
// Register schema
const schemaResult = await integration.registerSchema(
"bool verified,uint256 level,uint256 timestamp"
);
console.log('Schema:', schemaResult);
// Create attestation
const attestResult = await integration.attest(
'0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb',
schemaResult.schemaUID,
ethers.utils.defaultAbiCoder.encode(
['bool', 'uint256', 'uint256'],
[true, 5, Math.floor(Date.now() / 1000)]
)
);
console.log('Attestation:', attestResult);
Complete Trust System
Trust Score Dashboard
Copy
class TrustDashboard {
constructor(integration) {
this.integration = integration;
this.attestationCache = new Map();
}
// Get complete trust profile
async getTrustProfile(address) {
try {
// Get all attestations
const attestationsResult = await this.integration.getUserAttestations(address);
if (!attestationsResult.success) {
throw new Error(attestationsResult.error);
}
const attestations = attestationsResult.attestations;
// Calculate trust metrics
const metrics = {
totalAttestations: attestations.length,
activeAttestations: attestations.filter(a => !a.revoked).length,
revokedAttestations: attestations.filter(a => a.revoked).length,
uniqueAttesters: new Set(attestations.map(a => a.attester)).size,
schemaDistribution: this.getSchemaDistribution(attestations),
oldestAttestation: this.getOldest(attestations),
newestAttestation: this.getNewest(attestations)
};
// Calculate trust score
const trustScore = this.calculateTrustScore(attestations);
return {
success: true,
address,
metrics,
trustScore,
attestations
};
} catch (error) {
return {
success: false,
error: error.message
};
}
}
getSchemaDistribution(attestations) {
const distribution = {};
attestations.forEach(a => {
const schema = a.schema;
distribution[schema] = (distribution[schema] || 0) + 1;
});
return distribution;
}
getOldest(attestations) {
if (attestations.length === 0) return null;
return attestations.reduce((oldest, a) =>
a.time < oldest.time ? a : oldest
);
}
getNewest(attestations) {
if (attestations.length === 0) return null;
return attestations.reduce((newest, a) =>
a.time > newest.time ? a : newest
);
}
calculateTrustScore(attestations) {
const active = attestations.filter(a => !a.revoked);
// Base score from attestation count
let score = Math.min(active.length * 100, 500);
// Bonus for unique attesters
const uniqueAttesters = new Set(active.map(a => a.attester)).size;
score += Math.min(uniqueAttesters * 50, 300);
// Bonus for age (older attestations = more trust)
const now = Math.floor(Date.now() / 1000);
const avgAge = active.reduce((sum, a) => sum + (now - a.time), 0) / active.length;
const ageBonus = Math.min((avgAge / (30 * 24 * 60 * 60)) * 100, 200); // Max 200 for 30+ days
score += ageBonus;
return Math.min(Math.round(score), 1000);
}
}
// Usage
const dashboard = new TrustDashboard(integration);
const profile = await dashboard.getTrustProfile('0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb');
console.log('Trust Profile:', profile);
console.log(`Trust Score: ${profile.trustScore}/1000`);
console.log(`Active Attestations: ${profile.metrics.activeAttestations}`);
Attestation Workflows
Identity Verification Workflow
Copy
class IdentityVerificationWorkflow {
constructor(integration, schemaUID) {
this.integration = integration;
this.schemaUID = schemaUID;
}
// Step 1: Request verification
async requestVerification(address, verificationData) {
console.log(`Verification requested for ${address}`);
// In production, this would trigger off-chain verification
return {
requestId: ethers.utils.id(`${address}-${Date.now()}`),
status: 'pending',
address,
verificationData
};
}
// Step 2: Complete verification (called by verifier)
async completeVerification(address, verified, level) {
try {
// Encode attestation data
const attestationData = ethers.utils.defaultAbiCoder.encode(
['bool', 'uint256', 'uint256'],
[verified, level, Math.floor(Date.now() / 1000)]
);
// Create attestation
const result = await this.integration.attest(
address,
this.schemaUID,
attestationData
);
if (result.success) {
console.log(`✅ Verification complete for ${address}`);
console.log(`Attestation UID: ${result.uid}`);
}
return result;
} catch (error) {
console.error('Verification failed:', error.message);
throw error;
}
}
// Step 3: Check verification status
async checkVerification(address) {
try {
const attestations = await this.integration.getUserAttestations(
address,
this.schemaUID
);
if (!attestations.success) {
return {
verified: false,
level: 0,
attestationCount: 0
};
}
const activeAttestations = attestations.attestations.filter(a => !a.revoked);
if (activeAttestations.length === 0) {
return {
verified: false,
level: 0,
attestationCount: 0
};
}
// Decode latest attestation
const latest = activeAttestations[0];
const [verified, level] = ethers.utils.defaultAbiCoder.decode(
['bool', 'uint256', 'uint256'],
latest.data
);
return {
verified,
level: level.toNumber(),
attestationCount: activeAttestations.length,
latestUID: latest.uid
};
} catch (error) {
console.error('Check failed:', error.message);
return {
verified: false,
level: 0,
attestationCount: 0,
error: error.message
};
}
}
}
// Usage
const verificationWorkflow = new IdentityVerificationWorkflow(
integration,
schemaUID
);
// Request verification
const request = await verificationWorkflow.requestVerification(
'0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb',
{ email: 'user@example.com', phone: '+1234567890' }
);
// Complete verification
const result = await verificationWorkflow.completeVerification(
'0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb',
true,
5
);
// Check status
const status = await verificationWorkflow.checkVerification(
'0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb'
);
console.log('Verification Status:', status);
Error Handling
Copy
class TrustRegistryErrorHandler {
static handleError(error) {
const errorMessage = error.message || error.toString();
if (errorMessage.includes('InvalidSchema')) {
return {
type: 'INVALID_SCHEMA',
message: 'Schema does not exist. Please register it first.',
code: 'TR001'
};
}
if (errorMessage.includes('NotAttester')) {
return {
type: 'NOT_ATTESTER',
message: 'Only the attester can perform this action.',
code: 'TR002'
};
}
if (errorMessage.includes('NotRevocable')) {
return {
type: 'NOT_REVOCABLE',
message: 'This attestation cannot be revoked.',
code: 'TR003'
};
}
if (errorMessage.includes('AlreadyRevoked')) {
return {
type: 'ALREADY_REVOKED',
message: 'Attestation has already been revoked.',
code: 'TR004'
};
}
if (errorMessage.includes('Expired')) {
return {
type: 'EXPIRED',
message: 'Attestation has expired.',
code: 'TR005'
};
}
return {
type: 'UNKNOWN_ERROR',
message: errorMessage,
code: 'TR999'
};
}
static async safeExecute(operation, retries = 3) {
for (let attempt = 1; attempt <= retries; attempt++) {
try {
return await operation();
} catch (error) {
const errorInfo = this.handleError(error);
if (attempt === retries) {
throw errorInfo;
}
await new Promise(resolve => setTimeout(resolve, 1000 * Math.pow(2, attempt - 1)));
}
}
}
}
// Usage
try {
const result = await TrustRegistryErrorHandler.safeExecute(async () => {
return await integration.attest(recipient, schemaUID, data);
});
console.log('Success:', result);
} catch (error) {
console.error(`Error [${error.code}]:`, error.message);
}
Best Practices
Security
- Verify Attestations: Always check validity before trusting
- Attester Reputation: Consider attester trustworthiness
- Schema Validation: Use well-defined schemas
- Expiration: Set appropriate expiration times
- Revocation: Monitor for revocations
Performance
- Batch Operations: Use multiAttest for multiple attestations
- Cache Schemas: Cache schema definitions locally
- Event Listening: Use events for real-time updates
- Pagination: Paginate large attestation lists
- Gas Optimization: Estimate gas before transactions
Integration
- Test Thoroughly: Test on testnet first
- Error Handling: Implement comprehensive error handling
- Monitor Events: Track all attestation events
- Documentation: Document your attestation schemas
- User Experience: Provide clear feedback to users
Related Documentation
- Contract Overview - Contract architecture
- Functions Reference - Function documentation
- Events Reference - Event documentation
- Trust Modules - Module development