Skip to main content

Overview

This comprehensive example demonstrates how to integrate all ZKScore smart contracts together to build a complete reputation system. It covers identity creation, score calculation, achievement claiming, attestations, and protocol integration.
This example provides a complete production-ready integration pattern. Adapt it to your specific use case and requirements.

Complete Integration Example

Full System Integration

const { ethers } = require('ethers');

class ZKScoreContractIntegration {
  constructor(provider, contracts) {
    this.provider = provider;
    this.contracts = {
      identitySBT: new ethers.Contract(contracts.identitySBT, IDENTITY_SBT_ABI, provider),
      scoreCalculator: new ethers.Contract(contracts.scoreCalculator, SCORE_CALCULATOR_ABI, provider),
      achievementRegistry: new ethers.Contract(contracts.achievementRegistry, ACHIEVEMENT_REGISTRY_ABI, provider),
      trustRegistry: new ethers.Contract(contracts.trustRegistry, TRUST_REGISTRY_ABI, provider),
      protocolRegistry: new ethers.Contract(contracts.protocolRegistry, PROTOCOL_REGISTRY_ABI, provider)
    };
  }
  
  setSigner(signer) {
    this.signer = signer;
    Object.keys(this.contracts).forEach(key => {
      this.contracts[key] = this.contracts[key].connect(signer);
    });
  }
  
  // Complete onboarding flow
  async onboardUser(address, zksId, metadata) {
    const results = {
      identity: null,
      score: null,
      attestation: null
    };
    
    try {
      // Step 1: Mint identity
      console.log('Step 1: Minting identity...');
      const mintTx = await this.contracts.identitySBT.mint(
        address,
        zksId,
        metadata
      );
      const mintReceipt = await mintTx.wait();
      const mintEvent = mintReceipt.events.find(e => e.event === 'IdentityMinted');
      results.identity = {
        tokenId: mintEvent.args.tokenId.toString(),
        zksId: zksId
      };
      console.log(`✅ Identity minted: ${results.identity.tokenId}`);
      
      // Step 2: Activate identity
      console.log('Step 2: Activating identity...');
      const activateTx = await this.contracts.identitySBT.activate(results.identity.tokenId);
      await activateTx.wait();
      console.log('✅ Identity activated (soulbound)');
      
      // Step 3: Calculate initial score
      console.log('Step 3: Calculating initial score...');
      const scoreTx = await this.contracts.scoreCalculator.calculateScore(address);
      const scoreReceipt = await scoreTx.wait();
      const scoreEvent = scoreReceipt.events.find(e => e.event === 'ScoreCalculated');
      results.score = {
        total: scoreEvent.args.totalScore.toString()
      };
      console.log(`✅ Score calculated: ${results.score.total}`);
      
      // Step 4: Create identity attestation
      console.log('Step 4: Creating identity attestation...');
      const attestationData = ethers.utils.defaultAbiCoder.encode(
        ['bool', 'uint256', 'uint256'],
        [true, 1, Math.floor(Date.now() / 1000)]
      );
      
      const attestationRequest = {
        schema: this.identitySchemaUID,
        data: {
          recipient: address,
          expirationTime: 0,
          revocable: true,
          refUID: ethers.constants.HashZero,
          data: attestationData
        }
      };
      
      const attestTx = await this.contracts.trustRegistry.attest(attestationRequest);
      const attestReceipt = await attestTx.wait();
      const attestEvent = attestReceipt.events.find(e => e.event === 'Attested');
      results.attestation = {
        uid: attestEvent.args.uid
      };
      console.log(`✅ Attestation created: ${results.attestation.uid}`);
      
      // Step 5: Check for claimable achievements
      console.log('Step 5: Checking achievements...');
      const progress = await this.contracts.achievementRegistry.getProgress(address, 1); // "First Identity" achievement
      if (progress.canClaim) {
        const claimTx = await this.contracts.achievementRegistry.claimAchievement(1, '0x');
        await claimTx.wait();
        console.log('✅ Achievement claimed: First Identity');
      }
      
      return {
        success: true,
        ...results
      };
      
    } catch (error) {
      console.error('Onboarding failed:', error.message);
      return {
        success: false,
        error: error.message,
        partialResults: results
      };
    }
  }
  
  // Complete score update flow
  async updateUserScore(address) {
    try {
      // Recalculate score
      const tx = await this.contracts.scoreCalculator.calculateScore(address);
      const receipt = await tx.wait();
      
      const scoreEvent = receipt.events.find(e => e.event === 'ScoreCalculated');
      const newScore = scoreEvent.args.totalScore;
      
      // Check for score-based achievements
      await this.checkScoreAchievements(address, newScore);
      
      return {
        success: true,
        score: newScore.toString()
      };
    } catch (error) {
      return {
        success: false,
        error: error.message
      };
    }
  }
  
  async checkScoreAchievements(address, score) {
    const scoreThresholds = [
      { id: 10, threshold: 100 },
      { id: 11, threshold: 500 },
      { id: 12, threshold: 1000 }
    ];
    
    for (const { id, threshold } of scoreThresholds) {
      if (score.toNumber() >= threshold) {
        const canClaim = await this.contracts.achievementRegistry.canClaim(address, id);
        if (canClaim) {
          await this.contracts.achievementRegistry.claimAchievement(id, '0x');
          console.log(`✅ Achievement claimed: Score ${threshold}`);
        }
      }
    }
  }
  
  // Get complete user profile
  async getUserProfile(address) {
    try {
      const [identityTokens, score, breakdown, achievements, attestations] = await Promise.all([
        this.contracts.identitySBT.balanceOf(address),
        this.contracts.scoreCalculator.getScore(address),
        this.contracts.scoreCalculator.getScoreBreakdown(address),
        this.contracts.achievementRegistry.getUserAchievements(address),
        this.contracts.trustRegistry.getReceivedAttestationUIDs(address, ethers.constants.HashZero, 0, 100, true)
      ]);
      
      return {
        success: true,
        profile: {
          address,
          hasIdentity: identityTokens.toNumber() > 0,
          score: score.toString(),
          breakdown: breakdown.map(c => c.total.toString()),
          achievementCount: achievements.length,
          attestationCount: attestations.length
        }
      };
    } catch (error) {
      return {
        success: false,
        error: error.message
      };
    }
  }
}

// Usage
const integration = new ZKScoreContractIntegration(provider, {
  identitySBT: '0x1234...',
  scoreCalculator: '0x2345...',
  achievementRegistry: '0x3456...',
  trustRegistry: '0x4567...',
  protocolRegistry: '0x5678...'
});

integration.setSigner(signer);

// Complete onboarding
const onboardResult = await integration.onboardUser(
  '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb',
  'alice.zks',
  'https://api.onzks.com/metadata/alice.zks'
);

console.log('Onboarding result:', onboardResult);

// Get complete profile
const profile = await integration.getUserProfile('0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb');
console.log('User profile:', profile);

Best Practices

  1. Error Handling: Implement comprehensive error handling at each step
  2. Transaction Ordering: Execute transactions in correct sequence
  3. Gas Management: Estimate gas for each operation
  4. Event Monitoring: Listen for all relevant events
  5. State Verification: Verify state after each step