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

# Achievements

> Complete guide to managing achievements with the JavaScript SDK

## Overview

The ZKScore JavaScript SDK provides comprehensive achievement management capabilities, including listing achievements, tracking progress, claiming rewards, and real-time updates. The SDK handles both ZKS IDs and wallet addresses seamlessly.

<Tip>
  All achievement operations support both ZKS IDs and wallet addresses. The SDK automatically resolves ZKS IDs to their corresponding wallet addresses when needed.
</Tip>

## Basic Achievement Operations

### 1. List All Achievements

```javascript theme={null}
// Get all available achievements
async function listAchievements(options = {}) {
  try {
    const achievements = await sdk.achievements.listAchievements({
      category: options.category,
      rarity: options.rarity,
      status: options.status,
      limit: options.limit || 50,
      offset: options.offset || 0
    });
    
    console.log(`Found ${achievements.total} achievements`);
    console.log('Achievements:', achievements.achievements);
    
    return achievements;
  } catch (error) {
    console.error('Error listing achievements:', error.message);
    throw error;
  }
}

// Usage with different filters
const allAchievements = await listAchievements();
const defiAchievements = await listAchievements({ category: 'defi' });
const rareAchievements = await listAchievements({ rarity: 'legendary' });
const activeAchievements = await listAchievements({ status: 'active' });
```

### 2. Get User Achievements

```javascript theme={null}
// Get achievements for a specific user
async function getUserAchievements(identity) {
  try {
    const userAchievements = await sdk.achievements.getUserAchievements(identity);
    
    console.log(`Achievements for ${identity}:`);
    console.log('- Earned:', userAchievements.earned.length);
    console.log('- Claimable:', userAchievements.claimable.length);
    console.log('- In Progress:', userAchievements.inProgress.length);
    
    return userAchievements;
  } catch (error) {
    console.error('Error fetching user achievements:', error.message);
    throw error;
  }
}

// Usage
const achievements = await getUserAchievements('alice.zks');
```

### 3. Get Achievement Progress

```javascript theme={null}
// Get progress for a specific achievement
async function getAchievementProgress(identity, achievementId) {
  try {
    const progress = await sdk.achievements.getProgress(identity, achievementId);
    
    console.log(`Progress for achievement ${achievementId}:`);
    console.log('- Current progress:', progress.current);
    console.log('- Required:', progress.required);
    console.log('- Percentage:', progress.percentage);
    console.log('- Is completed:', progress.isCompleted);
    console.log('- Is claimable:', progress.isClaimable);
    
    return progress;
  } catch (error) {
    console.error('Error fetching achievement progress:', error.message);
    throw error;
  }
}

// Usage
const progress = await getAchievementProgress('alice.zks', 'defi-pioneer');
```

### 4. Claim Achievement

```javascript theme={null}
// Claim an achievement
async function claimAchievement(identity, achievementId, proof) {
  try {
    const result = await sdk.achievements.claimAchievement(identity, achievementId, {
      proof: proof,
      signature: await wallet.signMessage(`Claim achievement: ${achievementId}`)
    });
    
    console.log('✅ Achievement claimed successfully');
    console.log('- Achievement:', result.achievement.name);
    console.log('- Points earned:', result.points);
    console.log('- Total points:', result.totalPoints);
    console.log('- Claimed at:', result.claimedAt);
    
    return result;
  } catch (error) {
    if (error.code === 'ACHIEVEMENT_NOT_CLAIMABLE') {
      console.error('❌ Achievement is not claimable yet');
    } else if (error.code === 'ALREADY_CLAIMED') {
      console.error('❌ Achievement already claimed');
    } else if (error.code === 'INVALID_PROOF') {
      console.error('❌ Invalid proof provided');
    } else {
      console.error('❌ Error claiming achievement:', error.message);
    }
    throw error;
  }
}

// Usage
const claimResult = await claimAchievement('alice.zks', 'defi-pioneer', '0x...');
```

## Advanced Achievement Operations

### 1. Achievement Discovery

```javascript theme={null}
// Discover new achievements based on user activity
async function discoverAchievements(identity) {
  try {
    const discoveries = await sdk.achievements.discover(identity);
    
    console.log(`Found ${discoveries.length} potential achievements`);
    
    discoveries.forEach(discovery => {
      console.log(`- ${discovery.name}: ${discovery.description}`);
      console.log(`  Progress: ${discovery.progress.current}/${discovery.progress.required}`);
      console.log(`  Rarity: ${discovery.rarity}`);
    });
    
    return discoveries;
  } catch (error) {
    console.error('Error discovering achievements:', error.message);
    throw error;
  }
}

// Usage
const discoveries = await discoverAchievements('alice.zks');
```

### 2. Achievement Analytics

```javascript theme={null}
// Analyze achievement patterns and statistics
async function analyzeAchievements(identity) {
  try {
    const userAchievements = await sdk.achievements.getUserAchievements(identity);
    const allAchievements = await sdk.achievements.listAchievements();
    
    const analysis = {
      totalEarned: userAchievements.earned.length,
      totalAvailable: allAchievements.total,
      completionRate: (userAchievements.earned.length / allAchievements.total) * 100,
      categories: {},
      rarities: {},
      points: {
        total: userAchievements.earned.reduce((sum, a) => sum + a.points, 0),
        average: 0
      }
    };
    
    // Analyze by category
    userAchievements.earned.forEach(achievement => {
      const category = achievement.category;
      analysis.categories[category] = (analysis.categories[category] || 0) + 1;
    });
    
    // Analyze by rarity
    userAchievements.earned.forEach(achievement => {
      const rarity = achievement.rarity;
      analysis.rarities[rarity] = (analysis.rarities[rarity] || 0) + 1;
    });
    
    analysis.points.average = analysis.points.total / userAchievements.earned.length;
    
    console.log('Achievement Analysis:');
    console.log('- Total earned:', analysis.totalEarned);
    console.log('- Completion rate:', analysis.completionRate.toFixed(2) + '%');
    console.log('- Total points:', analysis.points.total);
    console.log('- Average points per achievement:', analysis.points.average.toFixed(2));
    console.log('- Categories:', analysis.categories);
    console.log('- Rarities:', analysis.rarities);
    
    return analysis;
  } catch (error) {
    console.error('Error analyzing achievements:', error.message);
    throw error;
  }
}

// Usage
const analysis = await analyzeAchievements('alice.zks');
```

### 3. Achievement Leaderboard

```javascript theme={null}
// Get achievement leaderboard
async function getAchievementLeaderboard(options = {}) {
  try {
    const leaderboard = await sdk.achievements.getLeaderboard({
      metric: options.metric || 'points', // points, count, rarity
      category: options.category,
      timeframe: options.timeframe || 'all',
      limit: options.limit || 10,
      offset: options.offset || 0
    });
    
    console.log('Achievement Leaderboard:');
    leaderboard.rankings.forEach((entry, index) => {
      console.log(`${index + 1}. ${entry.identity}: ${entry.value} ${options.metric || 'points'}`);
    });
    
    return leaderboard;
  } catch (error) {
    console.error('Error fetching achievement leaderboard:', error.message);
    throw error;
  }
}

// Usage
const pointsLeaderboard = await getAchievementLeaderboard({ metric: 'points' });
const countLeaderboard = await getAchievementLeaderboard({ metric: 'count' });
const defiLeaderboard = await getAchievementLeaderboard({ category: 'defi' });
```

## Real-time Achievement Updates

### 1. Subscribe to Achievement Updates

```javascript theme={null}
// Subscribe to real-time achievement updates
async function subscribeToAchievementUpdates(identity) {
  try {
    const unsubscribe = sdk.achievements.subscribeToUpdates(identity, (update) => {
      console.log('Achievement update:', update);
      
      switch (update.type) {
        case 'earned':
          console.log('🎉 New achievement earned:', update.achievement.name);
          break;
        case 'claimed':
          console.log('✅ Achievement claimed:', update.achievement.name);
          break;
        case 'progress':
          console.log('📈 Progress updated:', update.achievement.name, update.progress);
          break;
      }
    });
    
    console.log('✅ Subscribed to achievement updates');
    return unsubscribe;
  } catch (error) {
    console.error('❌ Error subscribing to updates:', error.message);
    throw error;
  }
}

// Usage
const unsubscribe = await subscribeToAchievementUpdates('alice.zks');

// Clean up subscription
setTimeout(() => {
  unsubscribe();
  console.log('Unsubscribed from achievement updates');
}, 300000); // 5 minutes
```

### 2. Achievement Notifications

```javascript theme={null}
// Set up achievement notifications
class AchievementNotificationService {
  constructor(sdk) {
    this.sdk = sdk;
    this.subscriptions = new Map();
    this.notifications = [];
  }
  
  async subscribe(identity, options = {}) {
    const {
      notifyOnEarn = true,
      notifyOnClaim = true,
      notifyOnProgress = false,
      callback = null
    } = options;
    
    const unsubscribe = await this.sdk.achievements.subscribeToUpdates(identity, (update) => {
      this.handleAchievementUpdate(identity, update, { notifyOnEarn, notifyOnClaim, notifyOnProgress, callback });
    });
    
    this.subscriptions.set(identity, unsubscribe);
    return unsubscribe;
  }
  
  handleAchievementUpdate(identity, update, options) {
    const notification = {
      identity,
      type: update.type,
      achievement: update.achievement,
      timestamp: new Date().toISOString()
    };
    
    let shouldNotify = false;
    
    switch (update.type) {
      case 'earned':
        shouldNotify = options.notifyOnEarn;
        notification.message = `🎉 New achievement earned: ${update.achievement.name}`;
        break;
      case 'claimed':
        shouldNotify = options.notifyOnClaim;
        notification.message = `✅ Achievement claimed: ${update.achievement.name}`;
        break;
      case 'progress':
        shouldNotify = options.notifyOnProgress;
        notification.message = `📈 Progress updated: ${update.achievement.name} (${update.progress}%)`;
        break;
    }
    
    if (shouldNotify) {
      this.notifications.push(notification);
      
      if (options.callback) {
        options.callback(notification);
      } else {
        console.log(notification.message);
      }
    }
  }
  
  getNotifications(identity) {
    return this.notifications.filter(n => n.identity === identity);
  }
  
  clearNotifications(identity) {
    this.notifications = this.notifications.filter(n => n.identity !== identity);
  }
  
  unsubscribe(identity) {
    const unsubscribe = this.subscriptions.get(identity);
    if (unsubscribe) {
      unsubscribe();
      this.subscriptions.delete(identity);
    }
  }
}

// Usage
const notificationService = new AchievementNotificationService(sdk);

await notificationService.subscribe('alice.zks', {
  notifyOnEarn: true,
  notifyOnClaim: true,
  notifyOnProgress: false,
  callback: (notification) => {
    console.log('Achievement notification:', notification);
  }
});
```

## Achievement Caching and Optimization

### 1. Achievement Caching

```javascript theme={null}
// Implement achievement caching
class AchievementCache {
  constructor(ttl = 300000) { // 5 minutes
    this.cache = new Map();
    this.ttl = ttl;
  }
  
  async getUserAchievements(identity) {
    const key = `user:${identity.toLowerCase()}`;
    const cached = this.cache.get(key);
    
    if (cached && Date.now() - cached.timestamp < this.ttl) {
      return cached.data;
    }
    
    const achievements = await sdk.achievements.getUserAchievements(identity);
    this.cache.set(key, {
      data: achievements,
      timestamp: Date.now()
    });
    
    return achievements;
  }
  
  async getAchievementProgress(identity, achievementId) {
    const key = `progress:${identity.toLowerCase()}:${achievementId}`;
    const cached = this.cache.get(key);
    
    if (cached && Date.now() - cached.timestamp < this.ttl) {
      return cached.data;
    }
    
    const progress = await sdk.achievements.getProgress(identity, achievementId);
    this.cache.set(key, {
      data: progress,
      timestamp: Date.now()
    });
    
    return progress;
  }
  
  invalidateUser(identity) {
    const keys = Array.from(this.cache.keys()).filter(key => 
      key.startsWith(`user:${identity.toLowerCase()}`) || 
      key.startsWith(`progress:${identity.toLowerCase()}`)
    );
    
    keys.forEach(key => this.cache.delete(key));
  }
  
  clear() {
    this.cache.clear();
  }
}

// Usage
const achievementCache = new AchievementCache();
const achievements = await achievementCache.getUserAchievements('alice.zks');
```

### 2. Batch Achievement Operations

```javascript theme={null}
// Batch multiple achievement operations
async function batchAchievementOperations(operations) {
  const results = [];
  const errors = [];
  
  for (const operation of operations) {
    try {
      const result = await operation();
      results.push(result);
    } catch (error) {
      errors.push({ operation, error });
    }
  }
  
  return { results, errors };
}

// Usage
const operations = [
  () => sdk.achievements.getUserAchievements('alice.zks'),
  () => sdk.achievements.getUserAchievements('bob.zks'),
  () => sdk.achievements.getUserAchievements('charlie.zks')
];

const { results, errors } = await batchAchievementOperations(operations);
console.log('Successful operations:', results.length);
console.log('Failed operations:', errors.length);
```

## Achievement Validation

### 1. Achievement Requirements Validation

```javascript theme={null}
// Validate achievement requirements
class AchievementValidator {
  static validateRequirements(achievement, userData) {
    const validation = {
      isValid: true,
      errors: [],
      warnings: []
    };
    
    // Check if achievement is active
    if (achievement.status !== 'active') {
      validation.isValid = false;
      validation.errors.push('Achievement is not active');
    }
    
    // Check if user meets requirements
    if (achievement.requirements) {
      Object.entries(achievement.requirements).forEach(([key, value]) => {
        if (userData[key] < value) {
          validation.warnings.push(`Requirement not met: ${key} (${userData[key]}/${value})`);
        }
      });
    }
    
    // Check if achievement is already earned
    if (userData.earnedAchievements?.includes(achievement.id)) {
      validation.isValid = false;
      validation.errors.push('Achievement already earned');
    }
    
    return validation;
  }
}

// Usage
const achievement = await sdk.achievements.getAchievement('defi-pioneer');
const userData = await sdk.scores.getScore('alice.zks');
const validation = AchievementValidator.validateRequirements(achievement, userData);
```

### 2. Achievement Progress Tracking

```javascript theme={null}
// Track achievement progress over time
class AchievementProgressTracker {
  constructor(sdk) {
    this.sdk = sdk;
    this.progressHistory = new Map();
  }
  
  async trackProgress(identity, achievementId) {
    const progress = await this.sdk.achievements.getProgress(identity, achievementId);
    const key = `${identity}:${achievementId}`;
    
    if (!this.progressHistory.has(key)) {
      this.progressHistory.set(key, []);
    }
    
    const history = this.progressHistory.get(key);
    history.push({
      progress: progress.percentage,
      timestamp: new Date().toISOString()
    });
    
    // Keep only last 10 progress points
    if (history.length > 10) {
      history.shift();
    }
    
    return {
      current: progress,
      history: history,
      trend: this.calculateTrend(history)
    };
  }
  
  calculateTrend(history) {
    if (history.length < 2) return 'stable';
    
    const first = history[0].progress;
    const last = history[history.length - 1].progress;
    const change = last - first;
    
    if (change > 5) return 'increasing';
    if (change < -5) return 'decreasing';
    return 'stable';
  }
}

// Usage
const tracker = new AchievementProgressTracker(sdk);
const progressData = await tracker.trackProgress('alice.zks', 'defi-pioneer');
```

## Error Handling

### 1. Achievement-Specific Error Handling

```javascript theme={null}
// Handle achievement-specific errors
function handleAchievementError(error) {
  switch (error.code) {
    case 'ACHIEVEMENT_NOT_FOUND':
      return 'Achievement not found.';
    
    case 'ACHIEVEMENT_NOT_CLAIMABLE':
      return 'Achievement is not claimable yet.';
    
    case 'ALREADY_CLAIMED':
      return 'Achievement already claimed.';
    
    case 'INVALID_PROOF':
      return 'Invalid proof provided.';
    
    case 'INSUFFICIENT_PROGRESS':
      return 'Insufficient progress to claim achievement.';
    
    case 'ACHIEVEMENT_EXPIRED':
      return 'Achievement has expired.';
    
    default:
      return `Unexpected error: ${error.message}`;
  }
}

// Usage
try {
  const result = await sdk.achievements.claimAchievement('alice.zks', 'defi-pioneer', '0x...');
} catch (error) {
  const message = handleAchievementError(error);
  console.error(message);
}
```

### 2. Retry Logic for Achievement Operations

```javascript theme={null}
// Retry achievement operations with exponential backoff
async function retryAchievementOperation(operation, maxRetries = 3) {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      return await operation();
    } catch (error) {
      if (attempt === maxRetries) {
        throw error;
      }
      
      if (error.code === 'NETWORK_ERROR' || error.code === 'TIMEOUT') {
        const delay = Math.pow(2, attempt) * 1000;
        console.log(`Retrying achievement operation in ${delay}ms... (attempt ${attempt}/${maxRetries})`);
        await new Promise(resolve => setTimeout(resolve, delay));
      } else {
        throw error;
      }
    }
  }
}

// Usage
const result = await retryAchievementOperation(
  () => sdk.achievements.claimAchievement('alice.zks', 'defi-pioneer', '0x...')
);
```

## Best Practices

### 1. Achievement Monitoring

```javascript theme={null}
// Monitor achievement progress and notify users
class AchievementMonitor {
  constructor(sdk) {
    this.sdk = sdk;
    this.monitoredAchievements = new Map();
  }
  
  async startMonitoring(identity, achievementIds) {
    for (const achievementId of achievementIds) {
      const progress = await this.sdk.achievements.getProgress(identity, achievementId);
      
      if (!progress.isCompleted) {
        this.monitoredAchievements.set(`${identity}:${achievementId}`, {
          identity,
          achievementId,
          progress: progress.percentage,
          lastChecked: new Date()
        });
      }
    }
    
    // Check progress every 5 minutes
    setInterval(() => {
      this.checkProgress();
    }, 300000);
  }
  
  async checkProgress() {
    for (const [key, monitored] of this.monitoredAchievements) {
      try {
        const progress = await this.sdk.achievements.getProgress(monitored.identity, monitored.achievementId);
        
        if (progress.percentage > monitored.progress) {
          console.log(`Progress update: ${monitored.achievementId} - ${progress.percentage}%`);
          monitored.progress = progress.percentage;
          monitored.lastChecked = new Date();
        }
        
        if (progress.isCompleted) {
          console.log(`Achievement completed: ${monitored.achievementId}`);
          this.monitoredAchievements.delete(key);
        }
      } catch (error) {
        console.error(`Error checking progress for ${key}:`, error.message);
      }
    }
  }
}

// Usage
const monitor = new AchievementMonitor(sdk);
await monitor.startMonitoring('alice.zks', ['defi-pioneer', 'nft-collector']);
```

### 2. Achievement Analytics

```javascript theme={null}
// Analyze achievement patterns and provide insights
class AchievementAnalytics {
  constructor(sdk) {
    this.sdk = sdk;
  }
  
  async analyzeUserAchievements(identity) {
    const achievements = await this.sdk.achievements.getUserAchievements(identity);
    
    const analysis = {
      totalEarned: achievements.earned.length,
      totalPoints: achievements.earned.reduce((sum, a) => sum + a.points, 0),
      categories: {},
      rarities: {},
      recent: achievements.earned
        .sort((a, b) => new Date(b.earnedAt) - new Date(a.earnedAt))
        .slice(0, 5),
      recommendations: []
    };
    
    // Analyze by category
    achievements.earned.forEach(achievement => {
      const category = achievement.category;
      analysis.categories[category] = (analysis.categories[category] || 0) + 1;
    });
    
    // Analyze by rarity
    achievements.earned.forEach(achievement => {
      const rarity = achievement.rarity;
      analysis.rarities[rarity] = (analysis.rarities[rarity] || 0) + 1;
    });
    
    // Generate recommendations
    if (analysis.categories.defi < 3) {
      analysis.recommendations.push('Try more DeFi activities to earn DeFi achievements');
    }
    
    if (analysis.categories.nft < 2) {
      analysis.recommendations.push('Explore NFT collections to earn NFT achievements');
    }
    
    return analysis;
  }
}

// Usage
const analytics = new AchievementAnalytics(sdk);
const analysis = await analytics.analyzeUserAchievements('alice.zks');
```

## Related Documentation

* [Getting Started](/sdk/javascript/getting-started) - SDK setup and configuration
* [Identity Management](/sdk/javascript/identity-management) - Identity operations
* [Score Queries](/sdk/javascript/score-queries) - Score and analytics
* [API Reference](/api-reference/achievements) - Achievement API endpoints
