> ## 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 System

> Build a comprehensive achievement system using ZKScore SDK

## Overview

Create a complete achievement system that tracks user progress, displays achievements, and handles claiming.

## Basic Achievement System

### Achievement Display

<CodeGroup>
  ```javascript JavaScript theme={null}
  import { ZKScoreClient } from '@zkscore/sdk';

  const client = new ZKScoreClient({
    apiKey: process.env.ZKSCORE_API_KEY
  });

  class AchievementSystem {
    constructor() {
      this.client = client;
    }
    
    async getUserAchievements(userAddress) {
      try {
        const achievements = await this.client.getAchievements(userAddress);
        return achievements.map(achievement => ({
          id: achievement.id,
          name: achievement.name,
          description: achievement.description,
          category: achievement.category,
          rarity: achievement.rarity,
          points: achievement.points,
          claimedAt: achievement.claimedAt,
          imageUrl: achievement.imageUrl
        }));
      } catch (error) {
        console.error('Error getting achievements:', error);
        return [];
      }
    }
    
    async getAvailableAchievements(userAddress) {
      try {
        const allAchievements = await this.client.listAchievements();
        const userAchievements = await this.getUserAchievements(userAddress);
        const userAchievementIds = userAchievements.map(a => a.id);
        
        return allAchievements.filter(achievement => 
          !userAchievementIds.includes(achievement.id)
        );
      } catch (error) {
        console.error('Error getting available achievements:', error);
        return [];
      }
    }
  }
  ```
</CodeGroup>

### Achievement Progress Tracking

<CodeGroup>
  ```javascript JavaScript theme={null}
  class AchievementProgress {
    constructor(client) {
      this.client = client;
    }
    
    async getAchievementProgress(userAddress, achievementId) {
      try {
        const progress = await this.client.getAchievementProgress(userAddress, achievementId);
        return {
          achievementId,
          current: progress.current,
          required: progress.required,
          percentage: (progress.current / progress.required) * 100,
          isComplete: progress.current >= progress.required
        };
      } catch (error) {
        console.error('Error getting progress:', error);
        return null;
      }
    }
    
    async getAllProgress(userAddress) {
      try {
        const availableAchievements = await this.getAvailableAchievements(userAddress);
        const progressPromises = availableAchievements.map(achievement => 
          this.getAchievementProgress(userAddress, achievement.id)
        );
        
        return await Promise.all(progressPromises);
      } catch (error) {
        console.error('Error getting all progress:', error);
        return [];
      }
    }
  }
  ```
</CodeGroup>

## React Achievement Component

### Achievement List Component

<CodeGroup>
  ```javascript JavaScript theme={null}
  import React, { useState, useEffect } from 'react';
  import { ZKScoreClient } from '@zkscore/sdk';

  const AchievementList = ({ userAddress }) => {
    const [achievements, setAchievements] = useState([]);
    const [loading, setLoading] = useState(true);
    const [error, setError] = useState(null);
    
    useEffect(() => {
      loadAchievements();
    }, [userAddress]);
    
    const loadAchievements = async () => {
      try {
        setLoading(true);
        const client = new ZKScoreClient({
          apiKey: process.env.REACT_APP_ZKSCORE_API_KEY
        });
        
        const userAchievements = await client.getAchievements(userAddress);
        setAchievements(userAchievements);
      } catch (err) {
        setError(err.message);
      } finally {
        setLoading(false);
      }
    };
    
    if (loading) return <div>Loading achievements...</div>;
    if (error) return <div>Error: {error}</div>;
    
    return (
      <div className="achievement-list">
        <h2>Achievements ({achievements.length})</h2>
        {achievements.map(achievement => (
          <AchievementCard 
            key={achievement.id} 
            achievement={achievement} 
          />
        ))}
      </div>
    );
  };

  const AchievementCard = ({ achievement }) => {
    const getRarityColor = (rarity) => {
      const colors = {
        common: '#gray',
        uncommon: '#green',
        rare: '#blue',
        epic: '#purple',
        legendary: '#gold'
      };
      return colors[rarity] || '#gray';
    };
    
    return (
      <div 
        className="achievement-card"
        style={{ borderColor: getRarityColor(achievement.rarity) }}
      >
        <div className="achievement-header">
          <h3>{achievement.name}</h3>
          <span className={`rarity ${achievement.rarity}`}>
            {achievement.rarity.toUpperCase()}
          </span>
        </div>
        <p>{achievement.description}</p>
        <div className="achievement-meta">
          <span>Points: {achievement.points}</span>
          <span>Category: {achievement.category}</span>
          <span>Claimed: {new Date(achievement.claimedAt).toLocaleDateString()}</span>
        </div>
      </div>
    );
  };
  ```
</CodeGroup>

### Achievement Progress Component

<CodeGroup>
  ```javascript JavaScript theme={null}
  const AchievementProgress = ({ userAddress }) => {
    const [progress, setProgress] = useState([]);
    const [loading, setLoading] = useState(true);
    
    useEffect(() => {
      loadProgress();
    }, [userAddress]);
    
    const loadProgress = async () => {
      try {
        setLoading(true);
        const client = new ZKScoreClient({
          apiKey: process.env.REACT_APP_ZKSCORE_API_KEY
        });
        
        const availableAchievements = await client.listAchievements();
        const progressPromises = availableAchievements.map(async (achievement) => {
          const progress = await client.getAchievementProgress(userAddress, achievement.id);
          return { ...achievement, progress };
        });
        
        const allProgress = await Promise.all(progressPromises);
        setProgress(allProgress.filter(p => !p.progress.isComplete));
      } catch (error) {
        console.error('Error loading progress:', error);
      } finally {
        setLoading(false);
      }
    };
    
    if (loading) return <div>Loading progress...</div>;
    
    return (
      <div className="achievement-progress">
        <h2>Progress ({progress.length})</h2>
        {progress.map(item => (
          <ProgressCard 
            key={item.id} 
            achievement={item} 
            progress={item.progress}
          />
        ))}
      </div>
    );
  };

  const ProgressCard = ({ achievement, progress }) => {
    const percentage = (progress.current / progress.required) * 100;
    
    return (
      <div className="progress-card">
        <div className="progress-header">
          <h3>{achievement.name}</h3>
          <span>{progress.current}/{progress.required}</span>
        </div>
        <div className="progress-bar">
          <div 
            className="progress-fill"
            style={{ width: `${percentage}%` }}
          />
        </div>
        <p>{achievement.description}</p>
      </div>
    );
  };
  ```
</CodeGroup>

## Achievement Claiming

### Claim Achievement Function

<CodeGroup>
  ```javascript JavaScript theme={null}
  class AchievementClaimer {
    constructor(client) {
      this.client = client;
    }
    
    async claimAchievement(userAddress, achievementId) {
      try {
        // Check if user can claim
        const canClaim = await this.client.canClaimAchievement(userAddress, achievementId);
        if (!canClaim) {
          throw new Error('Cannot claim this achievement');
        }
        
        // Claim achievement
        const result = await this.client.claimAchievement(userAddress, achievementId);
        
        return {
          success: true,
          achievementId,
          transactionHash: result.transactionHash
        };
      } catch (error) {
        return {
          success: false,
          error: error.message
        };
      }
    }
    
    async claimAllEligibleAchievements(userAddress) {
      try {
        const availableAchievements = await this.client.listAchievements();
        const claimPromises = availableAchievements.map(async (achievement) => {
          const canClaim = await this.client.canClaimAchievement(userAddress, achievement.id);
          if (canClaim) {
            return this.claimAchievement(userAddress, achievement.id);
          }
          return null;
        });
        
        const results = await Promise.all(claimPromises);
        return results.filter(result => result !== null);
      } catch (error) {
        console.error('Error claiming achievements:', error);
        return [];
      }
    }
  }
  ```
</CodeGroup>

## Achievement Notifications

### Real-time Notifications

<CodeGroup>
  ```javascript JavaScript theme={null}
  class AchievementNotifier {
    constructor(client) {
      this.client = client;
      this.listeners = [];
    }
    
    subscribe(callback) {
      this.listeners.push(callback);
    }
    
    unsubscribe(callback) {
      this.listeners = this.listeners.filter(listener => listener !== callback);
    }
    
    notify(achievement) {
      this.listeners.forEach(callback => callback(achievement));
    }
    
    async checkForNewAchievements(userAddress) {
      try {
        const achievements = await this.client.getAchievements(userAddress);
        const latestAchievement = achievements[achievements.length - 1];
        
        if (latestAchievement) {
          const now = Date.now();
          const claimedAt = new Date(latestAchievement.claimedAt).getTime();
          
          // If claimed within last 5 minutes, notify
          if (now - claimedAt < 5 * 60 * 1000) {
            this.notify(latestAchievement);
          }
        }
      } catch (error) {
        console.error('Error checking achievements:', error);
      }
    }
  }

  // Usage
  const notifier = new AchievementNotifier(client);
  notifier.subscribe((achievement) => {
    showNotification(`Achievement unlocked: ${achievement.name}!`);
  });
  ```
</CodeGroup>

## Best Practices

1. **Progress Tracking**: Always show progress toward achievements
2. **Real-time Updates**: Use event listeners for live updates
3. **Error Handling**: Handle claim failures gracefully
4. **User Feedback**: Provide clear feedback on achievement status
5. **Performance**: Cache achievement data to reduce API calls

## Related Documentation

* [Achievement Registry](/contracts/achievement-registry/overview)
* [Claim Achievement API](/api-reference/achievements/claim-achievement)
* [Basic Integration](/sdk/examples/basic-integration)
