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

# Score Queries

> Complete guide to querying scores and analytics with the JavaScript SDK

## Overview

The ZKScore JavaScript SDK provides comprehensive score querying capabilities, including current scores, historical data, breakdowns, and real-time updates. The SDK handles both ZKS IDs and wallet addresses seamlessly.

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

## Basic Score Operations

### 1. Get Current Score

```javascript theme={null}
// Get current score for an identity
async function getCurrentScore(identity) {
  try {
    const score = await sdk.scores.getScore(identity);
    
    console.log('Current Score:', score.total);
    console.log('Categories:', score.breakdown);
    console.log('Last updated:', score.lastUpdated);
    
    return score;
  } catch (error) {
    console.error('Error fetching score:', error.message);
    throw error;
  }
}

// Usage with ZKS ID
const scoreByZksId = await getCurrentScore('alice.zks');

// Usage with wallet address
const scoreByAddress = await getCurrentScore('0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb');
```

### 2. Get Score Breakdown

```javascript theme={null}
// Get detailed score breakdown
async function getScoreBreakdown(identity) {
  try {
    const breakdown = await sdk.scores.getBreakdown(identity);
    
    console.log('Score Breakdown:');
    console.log('- DeFi Score:', breakdown.defi);
    console.log('- NFT Score:', breakdown.nft);
    console.log('- Social Score:', breakdown.social);
    console.log('- Trading Score:', breakdown.trading);
    console.log('- Governance Score:', breakdown.governance);
    console.log('- Gaming Score:', breakdown.gaming);
    console.log('- Identity Score:', breakdown.identity);
    console.log('- Trust Score:', breakdown.trust);
    
    return breakdown;
  } catch (error) {
    console.error('Error fetching breakdown:', error.message);
    throw error;
  }
}

// Usage
const breakdown = await getScoreBreakdown('alice.zks');
```

### 3. Get Score History

```javascript theme={null}
// Get historical score data
async function getScoreHistory(identity, options = {}) {
  try {
    const history = await sdk.scores.getScoreHistory(identity, {
      timeframe: options.timeframe || '30d',
      interval: options.interval || 'daily',
      chainId: options.chainId,
      includeBreakdown: options.includeBreakdown || false
    });
    
    console.log(`Score history for ${identity}:`);
    console.log(`- Timeframe: ${options.timeframe || '30d'}`);
    console.log(`- Data points: ${history.length}`);
    console.log('- Latest score:', history[history.length - 1]?.total);
    console.log('- Earliest score:', history[0]?.total);
    
    return history;
  } catch (error) {
    console.error('Error fetching score history:', error.message);
    throw error;
  }
}

// Usage with different timeframes
const dailyHistory = await getScoreHistory('alice.zks', { timeframe: '7d', interval: 'daily' });
const hourlyHistory = await getScoreHistory('alice.zks', { timeframe: '24h', interval: 'hourly' });
const monthlyHistory = await getScoreHistory('alice.zks', { timeframe: '1y', interval: 'monthly' });
```

## Advanced Score Operations

### 1. Score Comparison

```javascript theme={null}
// Compare scores between identities
async function compareScores(identities) {
  try {
    const scores = await Promise.all(
      identities.map(identity => sdk.scores.getScore(identity))
    );
    
    const comparison = identities.map((identity, index) => ({
      identity,
      score: scores[index].total,
      breakdown: scores[index].breakdown
    }));
    
    // Sort by score
    comparison.sort((a, b) => b.score - a.score);
    
    console.log('Score Comparison:');
    comparison.forEach((item, index) => {
      console.log(`${index + 1}. ${item.identity}: ${item.score}`);
    });
    
    return comparison;
  } catch (error) {
    console.error('Error comparing scores:', error.message);
    throw error;
  }
}

// Usage
const comparison = await compareScores(['alice.zks', 'bob.zks', 'charlie.zks']);
```

### 2. Score Analytics

```javascript theme={null}
// Analyze score trends and patterns
async function analyzeScoreTrends(identity, timeframe = '30d') {
  try {
    const history = await sdk.scores.getScoreHistory(identity, {
      timeframe,
      interval: 'daily',
      includeBreakdown: true
    });
    
    const analysis = {
      current: history[history.length - 1],
      trend: calculateTrend(history),
      volatility: calculateVolatility(history),
      peak: Math.max(...history.map(h => h.total)),
      low: Math.min(...history.map(h => h.total)),
      average: history.reduce((sum, h) => sum + h.total, 0) / history.length
    };
    
    console.log('Score Analysis:');
    console.log('- Current score:', analysis.current.total);
    console.log('- Trend:', analysis.trend);
    console.log('- Volatility:', analysis.volatility);
    console.log('- Peak score:', analysis.peak);
    console.log('- Low score:', analysis.low);
    console.log('- Average score:', analysis.average);
    
    return analysis;
  } catch (error) {
    console.error('Error analyzing score trends:', error.message);
    throw error;
  }
}

// Helper functions
function calculateTrend(history) {
  if (history.length < 2) return 'stable';
  
  const first = history[0].total;
  const last = history[history.length - 1].total;
  const change = (last - first) / first;
  
  if (change > 0.1) return 'increasing';
  if (change < -0.1) return 'decreasing';
  return 'stable';
}

function calculateVolatility(history) {
  if (history.length < 2) return 0;
  
  const scores = history.map(h => h.total);
  const mean = scores.reduce((sum, score) => sum + score, 0) / scores.length;
  const variance = scores.reduce((sum, score) => sum + Math.pow(score - mean, 2), 0) / scores.length;
  
  return Math.sqrt(variance);
}

// Usage
const analysis = await analyzeScoreTrends('alice.zks', '90d');
```

### 3. Score Leaderboard

```javascript theme={null}
// Get score leaderboard
async function getScoreLeaderboard(options = {}) {
  try {
    const leaderboard = await sdk.scores.getLeaderboard({
      limit: options.limit || 10,
      offset: options.offset || 0,
      category: options.category,
      chainId: options.chainId,
      timeframe: options.timeframe || 'all'
    });
    
    console.log('Score Leaderboard:');
    leaderboard.rankings.forEach((entry, index) => {
      console.log(`${index + 1}. ${entry.identity}: ${entry.score}`);
    });
    
    return leaderboard;
  } catch (error) {
    console.error('Error fetching leaderboard:', error.message);
    throw error;
  }
}

// Usage
const topScores = await getScoreLeaderboard({ limit: 20 });
const defiLeaders = await getScoreLeaderboard({ category: 'defi', limit: 10 });
```

## Real-time Score Updates

### 1. Subscribe to Score Updates

```javascript theme={null}
// Subscribe to real-time score updates
async function subscribeToScoreUpdates(identity) {
  try {
    const unsubscribe = sdk.scores.subscribeToUpdates(identity, (update) => {
      console.log('Score updated:', update);
      console.log('- New score:', update.total);
      console.log('- Previous score:', update.previous?.total);
      console.log('- Change:', update.change);
      console.log('- Updated at:', update.updatedAt);
    });
    
    console.log('✅ Subscribed to score updates');
    return unsubscribe;
  } catch (error) {
    console.error('❌ Error subscribing to updates:', error.message);
    throw error;
  }
}

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

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

### 2. Score Change Notifications

```javascript theme={null}
// Set up score change notifications
class ScoreNotificationService {
  constructor(sdk) {
    this.sdk = sdk;
    this.subscriptions = new Map();
    this.thresholds = new Map();
  }
  
  async subscribe(identity, options = {}) {
    const {
      threshold = 10, // Minimum change to notify
      categories = ['total'], // Categories to monitor
      callback = null
    } = options;
    
    this.thresholds.set(identity, { threshold, categories });
    
    const unsubscribe = await this.sdk.scores.subscribeToUpdates(identity, (update) => {
      this.handleScoreUpdate(identity, update, callback);
    });
    
    this.subscriptions.set(identity, unsubscribe);
    return unsubscribe;
  }
  
  handleScoreUpdate(identity, update, callback) {
    const config = this.thresholds.get(identity);
    if (!config) return;
    
    const changes = this.calculateChanges(update);
    const significantChanges = changes.filter(change => 
      Math.abs(change.change) >= config.threshold
    );
    
    if (significantChanges.length > 0) {
      const notification = {
        identity,
        changes: significantChanges,
        timestamp: update.updatedAt
      };
      
      if (callback) {
        callback(notification);
      } else {
        console.log('Score change notification:', notification);
      }
    }
  }
  
  calculateChanges(update) {
    const changes = [];
    
    if (update.previous) {
      changes.push({
        category: 'total',
        previous: update.previous.total,
        current: update.total,
        change: update.total - update.previous.total
      });
      
      if (update.breakdown && update.previous.breakdown) {
        Object.keys(update.breakdown).forEach(category => {
          const previous = update.previous.breakdown[category];
          const current = update.breakdown[category];
          if (previous !== undefined && current !== undefined) {
            changes.push({
              category,
              previous,
              current,
              change: current - previous
            });
          }
        });
      }
    }
    
    return changes;
  }
  
  unsubscribe(identity) {
    const unsubscribe = this.subscriptions.get(identity);
    if (unsubscribe) {
      unsubscribe();
      this.subscriptions.delete(identity);
      this.thresholds.delete(identity);
    }
  }
}

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

await notificationService.subscribe('alice.zks', {
  threshold: 50,
  categories: ['total', 'defi', 'nft'],
  callback: (notification) => {
    console.log('Significant score change:', notification);
  }
});
```

## Score Caching and Optimization

### 1. Score Caching

```javascript theme={null}
// Implement score caching
class ScoreCache {
  constructor(ttl = 300000) { // 5 minutes
    this.cache = new Map();
    this.ttl = ttl;
  }
  
  async getScore(identity) {
    const key = `score:${identity.toLowerCase()}`;
    const cached = this.cache.get(key);
    
    if (cached && Date.now() - cached.timestamp < this.ttl) {
      return cached.data;
    }
    
    const score = await sdk.scores.getScore(identity);
    this.cache.set(key, {
      data: score,
      timestamp: Date.now()
    });
    
    return score;
  }
  
  async getScoreHistory(identity, options) {
    const key = `history:${identity.toLowerCase()}:${JSON.stringify(options)}`;
    const cached = this.cache.get(key);
    
    if (cached && Date.now() - cached.timestamp < this.ttl) {
      return cached.data;
    }
    
    const history = await sdk.scores.getScoreHistory(identity, options);
    this.cache.set(key, {
      data: history,
      timestamp: Date.now()
    });
    
    return history;
  }
  
  clear() {
    this.cache.clear();
  }
  
  getStats() {
    return {
      size: this.cache.size,
      keys: Array.from(this.cache.keys())
    };
  }
}

// Usage
const scoreCache = new ScoreCache();
const score = await scoreCache.getScore('alice.zks');
```

### 2. Batch Score Queries

```javascript theme={null}
// Batch multiple score queries
async function batchScoreQueries(identities) {
  try {
    const scores = await Promise.all(
      identities.map(identity => sdk.scores.getScore(identity))
    );
    
    const results = identities.map((identity, index) => ({
      identity,
      score: scores[index]
    }));
    
    return results;
  } catch (error) {
    console.error('Error in batch score queries:', error.message);
    throw error;
  }
}

// Usage
const identities = ['alice.zks', 'bob.zks', 'charlie.zks'];
const batchResults = await batchScoreQueries(identities);
```

## Error Handling

### 1. Score-Specific Error Handling

```javascript theme={null}
// Handle score-specific errors
function handleScoreError(error) {
  switch (error.code) {
    case 'SCORE_NOT_FOUND':
      return 'Score not found for this identity.';
    
    case 'INVALID_TIMEFRAME':
      return 'Invalid timeframe. Use: 1d, 7d, 30d, 90d, 1y, or all.';
    
    case 'INVALID_INTERVAL':
      return 'Invalid interval. Use: hourly, daily, weekly, or monthly.';
    
    case 'RATE_LIMIT_EXCEEDED':
      return 'Rate limit exceeded. Please wait before making more requests.';
    
    case 'NETWORK_ERROR':
      return 'Network error. Please check your connection.';
    
    default:
      return `Unexpected error: ${error.message}`;
  }
}

// Usage
try {
  const score = await sdk.scores.getScore('alice.zks');
} catch (error) {
  const message = handleScoreError(error);
  console.error(message);
}
```

### 2. Retry Logic for Score Queries

```javascript theme={null}
// Retry score queries with exponential backoff
async function retryScoreQuery(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 score query in ${delay}ms... (attempt ${attempt}/${maxRetries})`);
        await new Promise(resolve => setTimeout(resolve, delay));
      } else {
        throw error;
      }
    }
  }
}

// Usage
const score = await retryScoreQuery(
  () => sdk.scores.getScore('alice.zks')
);
```

## Performance Optimization

### 1. Lazy Loading

```javascript theme={null}
// Implement lazy loading for score data
class LazyScoreLoader {
  constructor(sdk) {
    this.sdk = sdk;
    this.cache = new Map();
    this.loading = new Set();
  }
  
  async getScore(identity) {
    if (this.cache.has(identity)) {
      return this.cache.get(identity);
    }
    
    if (this.loading.has(identity)) {
      // Wait for existing request
      return new Promise((resolve) => {
        const checkInterval = setInterval(() => {
          if (this.cache.has(identity)) {
            clearInterval(checkInterval);
            resolve(this.cache.get(identity));
          }
        }, 100);
      });
    }
    
    this.loading.add(identity);
    
    try {
      const score = await this.sdk.scores.getScore(identity);
      this.cache.set(identity, score);
      return score;
    } finally {
      this.loading.delete(identity);
    }
  }
}

// Usage
const lazyLoader = new LazyScoreLoader(sdk);
const score = await lazyLoader.getScore('alice.zks');
```

### 2. Score Aggregation

```javascript theme={null}
// Aggregate scores from multiple sources
class ScoreAggregator {
  constructor(sdk) {
    this.sdk = sdk;
  }
  
  async getAggregatedScore(identity, sources = ['defi', 'nft', 'social']) {
    try {
      const breakdown = await this.sdk.scores.getBreakdown(identity);
      
      const aggregated = {
        total: breakdown.total,
        sources: {},
        weighted: 0
      };
      
      sources.forEach(source => {
        if (breakdown[source] !== undefined) {
          aggregated.sources[source] = breakdown[source];
          aggregated.weighted += breakdown[source];
        }
      });
      
      aggregated.average = aggregated.weighted / sources.length;
      
      return aggregated;
    } catch (error) {
      console.error('Error aggregating scores:', error.message);
      throw error;
    }
  }
}

// Usage
const aggregator = new ScoreAggregator(sdk);
const aggregated = await aggregator.getAggregatedScore('alice.zks', ['defi', 'nft']);
```

## Related Documentation

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