> ## Documentation Index
> Fetch the complete documentation index at: https://core.anylayer.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Achievement Registry Integration

> Complete integration guide for the Achievement Registry contract

## Overview

This guide provides comprehensive examples for integrating with the ZKScore Achievement Registry contract. It covers Web3 integration, claiming workflows, progress tracking, and best practices for production deployments.

<Tip>
  Always test your integration on testnet before deploying to mainnet. Use the testnet contract addresses provided in the [Contract Overview](/contracts/achievement-registry/overview) section.
</Tip>

## Web3 Integration

### Basic Setup

<CodeGroup>
  ```javascript JavaScript theme={null}
  import { ethers } from 'ethers';

  // Contract configuration
  const CONTRACT_ADDRESS = '0x3456789012345678901234567890123456789012';
  const CONTRACT_ABI = [
    // ... ABI definitions
  ];

  // Initialize provider and contract
  const provider = new ethers.providers.JsonRpcProvider('https://mainnet.infura.io/v3/YOUR_KEY');
  const contract = new ethers.Contract(CONTRACT_ADDRESS, CONTRACT_ABI, provider);

  // Initialize with signer for transactions
  const signer = provider.getSigner();
  const contractWithSigner = contract.connect(signer);
  ```

  ```python Python theme={null}
  from web3 import Web3

  # Contract configuration
  CONTRACT_ADDRESS = '0x3456789012345678901234567890123456789012'
  CONTRACT_ABI = [
      # ... ABI definitions
  ]

  # Initialize provider and contract
  w3 = Web3(Web3.HTTPProvider('https://mainnet.infura.io/v3/YOUR_KEY'))
  contract = w3.eth.contract(address=CONTRACT_ADDRESS, abi=CONTRACT_ABI)

  # Initialize with account for transactions
  account = w3.eth.account.from_key('YOUR_PRIVATE_KEY')
  ```
</CodeGroup>

### Integration Class

<CodeGroup>
  ```javascript JavaScript theme={null}
  class AchievementRegistryIntegration {
    constructor(provider, contractAddress, abi) {
      this.provider = provider;
      this.contract = new ethers.Contract(contractAddress, abi, provider);
      this.contractWithSigner = null;
      this.categories = ['DeFi', 'NFT', 'Social', 'Trading', 'Governance', 'Gaming', 'Identity', 'Trust'];
      this.rarities = ['Common', 'Uncommon', 'Rare', 'Epic', 'Legendary'];
    }
    
    setSigner(signer) {
      this.contractWithSigner = this.contract.connect(signer);
    }
    
    // Get achievement details
    async getAchievement(achievementId) {
      try {
        const achievement = await this.contract.getAchievement(achievementId);
        
        return {
          success: true,
          achievement: {
            id: achievement.id.toString(),
            name: achievement.name,
            description: achievement.description,
            imageURI: achievement.imageURI,
            category: this.categories[achievement.category],
            rarity: this.rarities[achievement.rarity],
            points: achievement.points.toString(),
            scoreBoost: achievement.scoreBoost.toString(),
            totalClaimed: achievement.totalClaimed.toString(),
            maxClaims: achievement.maxClaims.toString(),
            isActive: achievement.isActive
          }
        };
      } catch (error) {
        return {
          success: false,
          error: error.message
        };
      }
    }
    
    // Get user's achievements
    async getUserAchievements(userAddress) {
      try {
        const achievementIds = await this.contract.getUserAchievements(userAddress);
        
        // Get details for each achievement
        const achievements = await Promise.all(
          achievementIds.map(id => this.getAchievement(id))
        );
        
        return {
          success: true,
          count: achievementIds.length,
          achievements: achievements.filter(a => a.success).map(a => a.achievement)
        };
      } catch (error) {
        return {
          success: false,
          error: error.message
        };
      }
    }
    
    // Get progress for achievement
    async getProgress(userAddress, achievementId) {
      try {
        const progress = await this.contract.getProgress(userAddress, achievementId);
        
        return {
          success: true,
          progress: {
            current: progress.current.toString(),
            required: progress.required.toString(),
            percentage: progress.percentage.toString(),
            lastUpdated: new Date(progress.lastUpdated.toNumber() * 1000).toISOString(),
            canClaim: progress.canClaim
          }
        };
      } catch (error) {
        return {
          success: false,
          error: error.message
        };
      }
    }
    
    // Claim achievement
    async claimAchievement(achievementId, proof = '0x') {
      if (!this.contractWithSigner) {
        throw new Error('Signer not set');
      }
      
      try {
        const tx = await this.contractWithSigner.claimAchievement(achievementId, proof);
        const receipt = await tx.wait();
        
        // Get events
        const claimEvent = receipt.events.find(e => e.event === 'AchievementClaimed');
        const badgeEvent = receipt.events.find(e => e.event === 'BadgeMinted');
        
        return {
          success: true,
          achievementId: claimEvent.args.achievementId.toString(),
          badgeTokenId: badgeEvent.args.tokenId.toString(),
          timestamp: claimEvent.args.timestamp.toNumber(),
          transactionHash: receipt.transactionHash
        };
      } catch (error) {
        return {
          success: false,
          error: error.message
        };
      }
    }
    
    // Check if can claim
    async canClaim(userAddress, achievementId) {
      try {
        const canClaim = await this.contract.canClaim(userAddress, achievementId);
        
        return {
          success: true,
          canClaim
        };
      } catch (error) {
        return {
          success: false,
          error: error.message
        };
      }
    }
  }

  // Usage
  const integration = new AchievementRegistryIntegration(
    provider,
    '0x3456789012345678901234567890123456789012',
    ACHIEVEMENT_REGISTRY_ABI
  );

  integration.setSigner(signer);

  // Get user's achievements
  const result = await integration.getUserAchievements('0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb');
  console.log('User achievements:', result);
  ```

  ```python Python theme={null}
  class AchievementRegistryIntegration:
      def __init__(self, w3, contract_address, abi):
          self.w3 = w3
          self.contract = w3.eth.contract(address=contract_address, abi=abi)
          self.account = None
          self.categories = ['DeFi', 'NFT', 'Social', 'Trading', 'Governance', 'Gaming', 'Identity', 'Trust']
          self.rarities = ['Common', 'Uncommon', 'Rare', 'Epic', 'Legendary']
      
      def set_account(self, private_key):
          self.account = self.w3.eth.account.from_key(private_key)
      
      def get_achievement(self, achievement_id):
          try:
              achievement = self.contract.functions.getAchievement(achievement_id).call()
              
              return {
                  'success': True,
                  'achievement': {
                      'id': str(achievement[0]),
                      'name': achievement[1],
                      'description': achievement[2],
                      'imageURI': achievement[3],
                      'category': self.categories[achievement[4]],
                      'rarity': self.rarities[achievement[5]],
                      'points': str(achievement[6]),
                      'scoreBoost': str(achievement[7]),
                      'totalClaimed': str(achievement[10]),
                      'maxClaims': str(achievement[11]),
                      'isActive': achievement[12]
                  }
              }
          except Exception as error:
              return {
                  'success': False,
                  'error': str(error)
              }
      
      def get_user_achievements(self, user_address):
          try:
              achievement_ids = self.contract.functions.getUserAchievements(user_address).call()
              
              achievements = [self.get_achievement(aid) for aid in achievement_ids]
              
              return {
                  'success': True,
                  'count': len(achievement_ids),
                  'achievements': [a['achievement'] for a in achievements if a['success']]
              }
          except Exception as error:
              return {
                  'success': False,
                  'error': str(error)
              }
      
      def get_progress(self, user_address, achievement_id):
          try:
              progress = self.contract.functions.getProgress(user_address, achievement_id).call()
              
              return {
                  'success': True,
                  'progress': {
                      'current': str(progress[0]),
                      'required': str(progress[1]),
                      'percentage': str(progress[2]),
                      'lastUpdated': progress[3],
                      'canClaim': progress[4]
                  }
              }
          except Exception as error:
              return {
                  'success': False,
                  'error': str(error)
              }
      
      def claim_achievement(self, achievement_id, proof=b''):
          if not self.account:
              raise ValueError('Account not set')
          
          try:
              tx = self.contract.functions.claimAchievement(achievement_id, proof).buildTransaction({
                  'from': self.account.address,
                  'gas': 200000,
                  'gasPrice': self.w3.eth.gas_price,
                  'nonce': self.w3.eth.get_transaction_count(self.account.address)
              })
              
              signed_tx = self.w3.eth.account.sign_transaction(tx, self.account.key)
              tx_hash = self.w3.eth.send_raw_transaction(signed_tx.rawTransaction)
              
              receipt = self.w3.eth.wait_for_transaction_receipt(tx_hash)
              
              # Get events
              claim_event = self.contract.events.AchievementClaimed().processReceipt(receipt)[0]
              badge_event = self.contract.events.BadgeMinted().processReceipt(receipt)[0]
              
              return {
                  'success': True,
                  'achievementId': str(claim_event['args']['achievementId']),
                  'badgeTokenId': str(badge_event['args']['tokenId']),
                  'timestamp': claim_event['args']['timestamp'],
                  'transactionHash': receipt.transactionHash.hex()
              }
          except Exception as error:
              return {
                  'success': False,
                  'error': str(error)
              }
      
      def can_claim(self, user_address, achievement_id):
          try:
              can_claim = self.contract.functions.canClaim(user_address, achievement_id).call()
              
              return {
                  'success': True,
                  'canClaim': can_claim
              }
          except Exception as error:
              return {
                  'success': False,
                  'error': str(error)
              }

  # Usage
  integration = AchievementRegistryIntegration(
      w3,
      '0x3456789012345678901234567890123456789012',
      ACHIEVEMENT_REGISTRY_ABI
  )

  integration.set_account('YOUR_PRIVATE_KEY')

  # Get user's achievements
  result = integration.get_user_achievements('0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb')
  print('User achievements:', result)
  ```
</CodeGroup>

## Achievement Dashboard

### Complete Achievement Tracker

<CodeGroup>
  ```javascript JavaScript theme={null}
  class AchievementDashboard {
    constructor(integration) {
      this.integration = integration;
      this.achievementCache = new Map();
      this.userProgress = new Map();
    }
    
    // Initialize dashboard for user
    async initializeUser(userAddress) {
      try {
        // Get user's achievements
        const earnedResult = await this.integration.getUserAchievements(userAddress);
        
        if (!earnedResult.success) {
          throw new Error(earnedResult.error);
        }
        
        // Get all available achievements (example: first 100)
        const allAchievements = await this.getAllAchievements(100);
        
        // Calculate progress for achievements not yet earned
        const notEarnedIds = allAchievements
          .filter(a => !earnedResult.achievements.find(ea => ea.id === a.id))
          .map(a => a.id);
        
        const progressResults = await Promise.all(
          notEarnedIds.map(id => 
            this.integration.getProgress(userAddress, id)
          )
        );
        
        // Store progress
        progressResults.forEach((result, index) => {
          if (result.success) {
            this.userProgress.set(notEarnedIds[index], result.progress);
          }
        });
        
        return {
          success: true,
          earned: earnedResult.achievements,
          inProgress: this.getInProgress(),
          claimable: this.getClaimable()
        };
      } catch (error) {
        return {
          success: false,
          error: error.message
        };
      }
    }
    
    // Get all available achievements
    async getAllAchievements(limit = 100) {
      const achievements = [];
      
      for (let i = 1; i <= limit; i++) {
        const result = await this.integration.getAchievement(i);
        
        if (result.success && result.achievement.isActive) {
          achievements.push(result.achievement);
          this.achievementCache.set(result.achievement.id, result.achievement);
        } else {
          break; // Stop if achievement doesn't exist
        }
      }
      
      return achievements;
    }
    
    // Get achievements in progress
    getInProgress() {
      const inProgress = [];
      
      for (const [id, progress] of this.userProgress.entries()) {
        if (parseInt(progress.percentage) > 0 && !progress.canClaim) {
          const achievement = this.achievementCache.get(id);
          if (achievement) {
            inProgress.push({
              ...achievement,
              progress
            });
          }
        }
      }
      
      return inProgress.sort((a, b) => 
        parseInt(b.progress.percentage) - parseInt(a.progress.percentage)
      );
    }
    
    // Get claimable achievements
    getClaimable() {
      const claimable = [];
      
      for (const [id, progress] of this.userProgress.entries()) {
        if (progress.canClaim) {
          const achievement = this.achievementCache.get(id);
          if (achievement) {
            claimable.push({
              ...achievement,
              progress
            });
          }
        }
      }
      
      return claimable;
    }
    
    // Claim achievement with UI feedback
    async claimWithFeedback(achievementId) {
      try {
        console.log(`Claiming achievement ${achievementId}...`);
        
        const result = await this.integration.claimAchievement(achievementId);
        
        if (result.success) {
          console.log('🎉 Achievement claimed!');
          console.log(`Badge Token ID: ${result.badgeTokenId}`);
          console.log(`Transaction: ${result.transactionHash}`);
          
          // Update local state
          this.userProgress.delete(achievementId);
          
          return result;
        }
        
        throw new Error(result.error);
      } catch (error) {
        console.error('❌ Claim failed:', error.message);
        throw error;
      }
    }
    
    // Get achievement by category
    getByCategory(category) {
      const achievements = [];
      
      for (const [id, achievement] of this.achievementCache.entries()) {
        if (achievement.category === category) {
          achievements.push(achievement);
        }
      }
      
      return achievements;
    }
    
    // Get achievement by rarity
    getByRarity(rarity) {
      const achievements = [];
      
      for (const [id, achievement] of this.achievementCache.entries()) {
        if (achievement.rarity === rarity) {
          achievements.push(achievement);
        }
      }
      
      return achievements;
    }
  }

  // Usage
  const dashboard = new AchievementDashboard(integration);

  // Initialize for user
  const userAddress = '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb';
  const dashboardData = await dashboard.initializeUser(userAddress);

  console.log('Earned achievements:', dashboardData.earned);
  console.log('In progress:', dashboardData.inProgress);
  console.log('Claimable:', dashboardData.claimable);

  // Claim achievement
  if (dashboardData.claimable.length > 0) {
    const firstClaimable = dashboardData.claimable[0];
    await dashboard.claimWithFeedback(firstClaimable.id);
  }
  ```
</CodeGroup>

## Real-time Progress Tracking

### Progress Monitor

<CodeGroup>
  ```javascript JavaScript theme={null}
  class ProgressMonitor {
    constructor(contract, userAddress) {
      this.contract = contract;
      this.userAddress = userAddress;
      this.progressListeners = new Map();
      this.startMonitoring();
    }
    
    startMonitoring() {
      // Listen for progress updates
      const filter = this.contract.filters.ProgressUpdated(this.userAddress);
      
      this.contract.on(filter, (user, achievementId, progress, event) => {
        this.handleProgressUpdate(achievementId, progress, event);
      });
      
      // Listen for achievements claimed
      const claimFilter = this.contract.filters.AchievementClaimed(this.userAddress);
      
      this.contract.on(claimFilter, (user, achievementId, timestamp, event) => {
        this.handleAchievementClaimed(achievementId, timestamp, event);
      });
    }
    
    handleProgressUpdate(achievementId, progress, event) {
      console.log(`Progress update for achievement ${achievementId.toString()}: ${progress.toString()}`);
      
      // Notify listeners
      if (this.progressListeners.has(achievementId.toString())) {
        const callbacks = this.progressListeners.get(achievementId.toString());
        callbacks.forEach(callback => callback(progress.toString(), event));
      }
      
      // Check if now claimable
      this.checkClaimable(achievementId);
    }
    
    handleAchievementClaimed(achievementId, timestamp, event) {
      console.log(`🎉 Achievement ${achievementId.toString()} claimed!`);
      
      // Trigger celebration
      this.celebrateClaim(achievementId, timestamp);
    }
    
    async checkClaimable(achievementId) {
      const progress = await this.contract.getProgress(this.userAddress, achievementId);
      
      if (progress.canClaim) {
        console.log(`✨ Achievement ${achievementId.toString()} is now claimable!`);
        this.notifyClaimable(achievementId);
      }
    }
    
    onProgress(achievementId, callback) {
      const id = achievementId.toString();
      
      if (!this.progressListeners.has(id)) {
        this.progressListeners.set(id, []);
      }
      
      this.progressListeners.get(id).push(callback);
    }
    
    celebrateClaim(achievementId, timestamp) {
      // Implement celebration logic
      console.log(`🏆 Congratulations! Achievement ${achievementId.toString()} unlocked!`);
    }
    
    notifyClaimable(achievementId) {
      // Implement notification logic
      console.log(`📢 Achievement ${achievementId.toString()} is ready to claim!`);
    }
    
    stopMonitoring() {
      this.contract.removeAllListeners();
    }
  }

  // Usage
  const monitor = new ProgressMonitor(contract, userAddress);

  // Subscribe to progress updates
  monitor.onProgress(123, (progress, event) => {
    console.log(`Achievement 123 progress: ${progress}`);
    
    // Update UI
    updateProgressBar(progress);
  });
  ```
</CodeGroup>

## Error Handling

### Comprehensive Error Handler

<CodeGroup>
  ```javascript JavaScript theme={null}
  class AchievementErrorHandler {
    static handleError(error) {
      const errorMessage = error.message || error.toString();
      
      if (errorMessage.includes('Achievement not active')) {
        return {
          type: 'ACHIEVEMENT_INACTIVE',
          message: 'This achievement is no longer available',
          code: 'ACH001'
        };
      }
      
      if (errorMessage.includes('Already claimed')) {
        return {
          type: 'ALREADY_CLAIMED',
          message: 'You have already claimed this achievement',
          code: 'ACH002'
        };
      }
      
      if (errorMessage.includes('Requirements not met')) {
        return {
          type: 'REQUIREMENTS_NOT_MET',
          message: 'You do not meet the requirements for this achievement',
          code: 'ACH003'
        };
      }
      
      if (errorMessage.includes('Invalid proof')) {
        return {
          type: 'INVALID_PROOF',
          message: 'Verification proof is invalid',
          code: 'ACH004'
        };
      }
      
      if (errorMessage.includes('Max claims reached')) {
        return {
          type: 'MAX_CLAIMS_REACHED',
          message: 'Maximum number of claims reached for this achievement',
          code: 'ACH005'
        };
      }
      
      return {
        type: 'UNKNOWN_ERROR',
        message: errorMessage,
        code: 'ACH999'
      };
    }
    
    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;
          }
          
          // Wait before retry (exponential backoff)
          await new Promise(resolve => setTimeout(resolve, 1000 * Math.pow(2, attempt - 1)));
        }
      }
    }
  }

  // Usage
  try {
    const result = await AchievementErrorHandler.safeExecute(async () => {
      return await integration.claimAchievement(123);
    });
    console.log('Success:', result);
  } catch (error) {
    console.error(`Error [${error.code}]:`, error.message);
    console.error('Type:', error.type);
  }
  ```
</CodeGroup>

## Best Practices

### Performance Optimization

1. **Cache Achievement Data**: Cache achievement metadata locally
2. **Batch Queries**: Query multiple achievements in parallel
3. **Event Listening**: Use events for real-time updates
4. **Progress Caching**: Cache progress data with TTL
5. **Gas Estimation**: Estimate gas before claiming

### Security Considerations

1. **Verify Requirements**: Always check canClaim() before claiming
2. **Validate Proofs**: Ensure proof generation is secure
3. **Monitor Events**: Track all claim events
4. **Gas Limits**: Set appropriate gas limits
5. **Error Handling**: Implement comprehensive error handling

### User Experience

1. **Progress Feedback**: Show real-time progress updates
2. **Clear Requirements**: Display achievement requirements clearly
3. **Claim Notifications**: Notify users when achievements are claimable
4. **Celebration**: Celebrate achievement claims
5. **Badge Display**: Show earned badges prominently

## Related Documentation

* [Contract Overview](/contracts/achievement-registry/overview) - Contract architecture and features
* [Functions Reference](/contracts/achievement-registry/functions) - Complete function documentation
* [Events Reference](/contracts/achievement-registry/events) - Event documentation
* [Custom Achievements](/contracts/achievement-registry/custom-achievements) - Creating custom achievements
