> ## 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 Calculator Integration

> Complete integration guide for the Score Calculator contract

## Overview

This guide provides comprehensive examples for integrating with the ZKScore Score Calculator contract. It covers Web3 integration, real-time monitoring, error handling, 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/score-calculator/overview) section.
</Tip>

## Web3 Integration

### Basic Setup

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

  // Contract configuration
  const CONTRACT_ADDRESS = '0x2345678901234567890123456789012345678901';
  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 = '0x2345678901234567890123456789012345678901'
  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 ScoreCalculatorIntegration {
    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'];
    }
    
    // Set signer for transactions
    setSigner(signer) {
      this.contractWithSigner = this.contract.connect(signer);
    }
    
    // Get user score
    async getUserScore(userAddress) {
      try {
        const score = await this.contract.getScore(userAddress);
        return {
          success: true,
          score: score.toString(),
          address: userAddress
        };
      } catch (error) {
        return {
          success: false,
          error: error.message
        };
      }
    }
    
    // Get detailed score breakdown
    async getScoreBreakdown(userAddress) {
      try {
        const breakdown = await this.contract.getScoreBreakdown(userAddress);
        
        const formattedBreakdown = breakdown.map((category, index) => ({
          name: this.categories[index],
          score: category.total.toString(),
          weight: category.weight.toNumber() / 100, // Convert basis points to percentage
          lastUpdated: new Date(category.lastUpdated.toNumber() * 1000).toISOString(),
          isActive: category.isActive
        }));
        
        return {
          success: true,
          address: userAddress,
          breakdown: formattedBreakdown
        };
      } catch (error) {
        return {
          success: false,
          error: error.message
        };
      }
    }
    
    // Calculate and refresh score
    async refreshScore(userAddress) {
      if (!this.contractWithSigner) {
        throw new Error('Signer not set');
      }
      
      try {
        const tx = await this.contractWithSigner.calculateScore(userAddress);
        const receipt = await tx.wait();
        
        // Get score from event
        const event = receipt.events.find(e => e.event === 'ScoreCalculated');
        const newScore = event.args.totalScore;
        
        return {
          success: true,
          score: newScore.toString(),
          transactionHash: receipt.transactionHash,
          blockNumber: receipt.blockNumber
        };
      } catch (error) {
        return {
          success: false,
          error: error.message
        };
      }
    }
    
    // Get category score
    async getCategoryScore(userAddress, categoryIndex) {
      try {
        const score = await this.contract.getCategoryScore(userAddress, categoryIndex);
        
        return {
          success: true,
          category: this.categories[categoryIndex],
          score: score.toString(),
          address: userAddress
        };
      } catch (error) {
        return {
          success: false,
          error: error.message
        };
      }
    }
    
    // Batch get scores
    async batchGetScores(userAddresses) {
      try {
        const scores = await this.contract.batchGetScores(userAddresses);
        
        return {
          success: true,
          scores: userAddresses.map((address, index) => ({
            address,
            score: scores[index].toString()
          }))
        };
      } catch (error) {
        return {
          success: false,
          error: error.message
        };
      }
    }
  }

  // Usage
  const integration = new ScoreCalculatorIntegration(
    provider,
    '0x2345678901234567890123456789012345678901',
    SCORE_CALCULATOR_ABI
  );

  integration.setSigner(signer);

  // Get score
  const scoreResult = await integration.getUserScore('0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb');
  console.log('User score:', scoreResult);

  // Get breakdown
  const breakdownResult = await integration.getScoreBreakdown('0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb');
  console.log('Score breakdown:', breakdownResult);
  ```

  ```python Python theme={null}
  class ScoreCalculatorIntegration:
      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']
      
      # Set account for transactions
      def set_account(self, private_key):
          self.account = self.w3.eth.account.from_key(private_key)
      
      # Get user score
      def get_user_score(self, user_address):
          try:
              score = self.contract.functions.getScore(user_address).call()
              return {
                  'success': True,
                  'score': str(score),
                  'address': user_address
              }
          except Exception as error:
              return {
                  'success': False,
                  'error': str(error)
              }
      
      # Get detailed score breakdown
      def get_score_breakdown(self, user_address):
          try:
              breakdown = self.contract.functions.getScoreBreakdown(user_address).call()
              
              formatted_breakdown = [{
                  'name': self.categories[i],
                  'score': str(category[0]),
                  'weight': category[2] / 100,  # Convert basis points to percentage
                  'lastUpdated': category[3],
                  'isActive': category[4]
              } for i, category in enumerate(breakdown)]
              
              return {
                  'success': True,
                  'address': user_address,
                  'breakdown': formatted_breakdown
              }
          except Exception as error:
              return {
                  'success': False,
                  'error': str(error)
              }
      
      # Calculate and refresh score
      def refresh_score(self, user_address):
          if not self.account:
              raise ValueError('Account not set')
          
          try:
              tx = self.contract.functions.calculateScore(user_address).buildTransaction({
                  'from': self.account.address,
                  'gas': 250000,
                  '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 score from event
              event = self.contract.events.ScoreCalculated().processReceipt(receipt)[0]
              new_score = event['args']['totalScore']
              
              return {
                  'success': True,
                  'score': str(new_score),
                  'transactionHash': receipt.transactionHash.hex(),
                  'blockNumber': receipt.blockNumber
              }
          except Exception as error:
              return {
                  'success': False,
                  'error': str(error)
              }
      
      # Get category score
      def get_category_score(self, user_address, category_index):
          try:
              score = self.contract.functions.getCategoryScore(user_address, category_index).call()
              
              return {
                  'success': True,
                  'category': self.categories[category_index],
                  'score': str(score),
                  'address': user_address
              }
          except Exception as error:
              return {
                  'success': False,
                  'error': str(error)
              }
      
      # Batch get scores
      def batch_get_scores(self, user_addresses):
          try:
              scores = self.contract.functions.batchGetScores(user_addresses).call()
              
              return {
                  'success': True,
                  'scores': [{
                      'address': address,
                      'score': str(score)
                  } for address, score in zip(user_addresses, scores)]
              }
          except Exception as error:
              return {
                  'success': False,
                  'error': str(error)
              }

  # Usage
  integration = ScoreCalculatorIntegration(
      w3,
      '0x2345678901234567890123456789012345678901',
      SCORE_CALCULATOR_ABI
  )

  integration.set_account('YOUR_PRIVATE_KEY')

  # Get score
  score_result = integration.get_user_score('0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb')
  print('User score:', score_result)

  # Get breakdown
  breakdown_result = integration.get_score_breakdown('0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb')
  print('Score breakdown:', breakdown_result)
  ```
</CodeGroup>

## Real-time Monitoring

### Score Update Tracker

<CodeGroup>
  ```javascript JavaScript theme={null}
  class ScoreUpdateTracker {
    constructor(contract) {
      this.contract = contract;
      this.subscribers = new Map();
      this.scoreCache = new Map();
      this.startMonitoring();
    }
    
    startMonitoring() {
      // Monitor score calculations
      this.contract.on('ScoreCalculated', (user, totalScore, timestamp, event) => {
        this.handleScoreCalculated(user, totalScore, timestamp, event);
      });
      
      // Monitor score updates
      this.contract.on('ScoreUpdated', (user, oldScore, newScore, event) => {
        this.handleScoreUpdated(user, oldScore, newScore, event);
      });
      
      // Monitor category updates
      this.contract.on('CategoryScoreUpdated', (user, category, score, event) => {
        this.handleCategoryUpdated(user, category, score, event);
      });
    }
    
    handleScoreCalculated(user, totalScore, timestamp, event) {
      const scoreData = {
        score: totalScore.toString(),
        timestamp: timestamp.toNumber(),
        blockNumber: event.blockNumber,
        transactionHash: event.transactionHash
      };
      
      // Update cache
      this.scoreCache.set(user, scoreData);
      
      // Notify subscribers
      this.notifySubscribers(user, 'scoreCalculated', scoreData);
    }
    
    handleScoreUpdated(user, oldScore, newScore, event) {
      const updateData = {
        oldScore: oldScore.toString(),
        newScore: newScore.toString(),
        change: newScore.sub(oldScore).toString(),
        blockNumber: event.blockNumber
      };
      
      this.notifySubscribers(user, 'scoreUpdated', updateData);
    }
    
    handleCategoryUpdated(user, category, score, event) {
      const categories = ['DeFi', 'NFT', 'Social', 'Trading', 'Governance', 'Gaming', 'Identity', 'Trust'];
      
      const categoryData = {
        category: categories[category],
        categoryIndex: category,
        score: score.toString(),
        blockNumber: event.blockNumber
      };
      
      this.notifySubscribers(user, 'categoryUpdated', categoryData);
    }
    
    subscribe(user, eventType, callback) {
      const key = `${user}-${eventType}`;
      
      if (!this.subscribers.has(key)) {
        this.subscribers.set(key, []);
      }
      
      this.subscribers.get(key).push(callback);
    }
    
    notifySubscribers(user, eventType, data) {
      const key = `${user}-${eventType}`;
      
      if (this.subscribers.has(key)) {
        this.subscribers.get(key).forEach(callback => {
          try {
            callback(data);
          } catch (error) {
            console.error(`Error in subscriber callback: ${error.message}`);
          }
        });
      }
    }
    
    getCachedScore(user) {
      return this.scoreCache.get(user);
    }
    
    stopMonitoring() {
      this.contract.removeAllListeners();
    }
  }

  // Usage
  const tracker = new ScoreUpdateTracker(contract);

  // Subscribe to user score updates
  tracker.subscribe('0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb', 'scoreCalculated', (data) => {
    console.log('Score calculated:', data);
  });

  tracker.subscribe('0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb', 'scoreUpdated', (data) => {
    console.log('Score updated:', data);
    console.log(`Change: ${data.change}`);
  });

  tracker.subscribe('0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb', 'categoryUpdated', (data) => {
    console.log(`${data.category} score updated: ${data.score}`);
  });
  ```

  ```python Python theme={null}
  class ScoreUpdateTracker:
      def __init__(self, contract):
          self.contract = contract
          self.subscribers = {}
          self.score_cache = {}
          self.categories = ['DeFi', 'NFT', 'Social', 'Trading', 'Governance', 'Gaming', 'Identity', 'Trust']
          self.start_monitoring()
      
      def start_monitoring(self):
          # Monitor score calculations
          self.contract.events.ScoreCalculated().on('data', self.handle_score_calculated)
          
          # Monitor score updates
          self.contract.events.ScoreUpdated().on('data', self.handle_score_updated)
          
          # Monitor category updates
          self.contract.events.CategoryScoreUpdated().on('data', self.handle_category_updated)
      
      def handle_score_calculated(self, event):
          user = event['args']['user']
          total_score = event['args']['totalScore']
          timestamp = event['args']['timestamp']
          
          score_data = {
              'score': str(total_score),
              'timestamp': timestamp,
              'blockNumber': event['blockNumber'],
              'transactionHash': event['transactionHash'].hex()
          }
          
          # Update cache
          self.score_cache[user] = score_data
          
          # Notify subscribers
          self.notify_subscribers(user, 'scoreCalculated', score_data)
      
      def handle_score_updated(self, event):
          user = event['args']['user']
          old_score = event['args']['oldScore']
          new_score = event['args']['newScore']
          
          update_data = {
              'oldScore': str(old_score),
              'newScore': str(new_score),
              'change': str(new_score - old_score),
              'blockNumber': event['blockNumber']
          }
          
          self.notify_subscribers(user, 'scoreUpdated', update_data)
      
      def handle_category_updated(self, event):
          user = event['args']['user']
          category = event['args']['category']
          score = event['args']['score']
          
          category_data = {
              'category': self.categories[category],
              'categoryIndex': category,
              'score': str(score),
              'blockNumber': event['blockNumber']
          }
          
          self.notify_subscribers(user, 'categoryUpdated', category_data)
      
      def subscribe(self, user, event_type, callback):
          key = f"{user}-{event_type}"
          
          if key not in self.subscribers:
              self.subscribers[key] = []
          
          self.subscribers[key].append(callback)
      
      def notify_subscribers(self, user, event_type, data):
          key = f"{user}-{event_type}"
          
          if key in self.subscribers:
              for callback in self.subscribers[key]:
                  try:
                      callback(data)
                  except Exception as error:
                      print(f"Error in subscriber callback: {error}")
      
      def get_cached_score(self, user):
          return self.score_cache.get(user)

  # Usage
  tracker = ScoreUpdateTracker(contract)

  # Subscribe to user score updates
  def on_score_calculated(data):
      print('Score calculated:', data)

  def on_score_updated(data):
      print('Score updated:', data)
      print(f"Change: {data['change']}")

  def on_category_updated(data):
      print(f"{data['category']} score updated: {data['score']}")

  tracker.subscribe('0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb', 'scoreCalculated', on_score_calculated)
  tracker.subscribe('0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb', 'scoreUpdated', on_score_updated)
  tracker.subscribe('0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb', 'categoryUpdated', on_category_updated)
  ```
</CodeGroup>

## Complete Dashboard Integration

### Score Dashboard

<CodeGroup>
  ```javascript JavaScript theme={null}
  class ScoreDashboard {
    constructor(integration, tracker) {
      this.integration = integration;
      this.tracker = tracker;
      this.leaderboard = [];
      this.userScores = new Map();
    }
    
    // Initialize dashboard for a user
    async initializeUser(userAddress) {
      try {
        // Get current score
        const scoreResult = await this.integration.getUserScore(userAddress);
        if (!scoreResult.success) {
          throw new Error(scoreResult.error);
        }
        
        // Get detailed breakdown
        const breakdownResult = await this.integration.getScoreBreakdown(userAddress);
        if (!breakdownResult.success) {
          throw new Error(breakdownResult.error);
        }
        
        // Store user data
        this.userScores.set(userAddress, {
          score: scoreResult.score,
          breakdown: breakdownResult.breakdown,
          lastUpdated: new Date()
        });
        
        // Subscribe to updates
        this.tracker.subscribe(userAddress, 'scoreUpdated', (data) => {
          this.handleUserScoreUpdate(userAddress, data);
        });
        
        return {
          success: true,
          score: scoreResult.score,
          breakdown: breakdownResult.breakdown
        };
      } catch (error) {
        return {
          success: false,
          error: error.message
        };
      }
    }
    
    // Handle real-time score updates
    handleUserScoreUpdate(userAddress, data) {
      const userData = this.userScores.get(userAddress);
      
      if (userData) {
        userData.score = data.newScore;
        userData.lastUpdated = new Date();
        
        console.log(`Score updated for ${userAddress}:`);
        console.log(`  Old: ${data.oldScore}`);
        console.log(`  New: ${data.newScore}`);
        console.log(`  Change: ${data.change}`);
        
        // Trigger UI update
        this.updateUI(userAddress, userData);
      }
    }
    
    // Get leaderboard
    async updateLeaderboard(userAddresses) {
      try {
        const result = await this.integration.batchGetScores(userAddresses);
        
        if (result.success) {
          this.leaderboard = result.scores
            .sort((a, b) => parseInt(b.score) - parseInt(a.score))
            .map((entry, index) => ({
              rank: index + 1,
              ...entry
            }));
          
          return {
            success: true,
            leaderboard: this.leaderboard
          };
        }
        
        throw new Error(result.error);
      } catch (error) {
        return {
          success: false,
          error: error.message
        };
      }
    }
    
    // Get user ranking
    getUserRanking(userAddress) {
      const entry = this.leaderboard.find(e => e.address === userAddress);
      return entry ? entry.rank : null;
    }
    
    // Refresh user score
    async refreshUserScore(userAddress) {
      try {
        const result = await this.integration.refreshScore(userAddress);
        
        if (result.success) {
          // Update local cache
          const userData = this.userScores.get(userAddress);
          if (userData) {
            userData.score = result.score;
            userData.lastUpdated = new Date();
          }
          
          return result;
        }
        
        throw new Error(result.error);
      } catch (error) {
        return {
          success: false,
          error: error.message
        };
      }
    }
    
    // Update UI (placeholder - implement with your UI framework)
    updateUI(userAddress, userData) {
      console.log(`UI Update for ${userAddress}:`, userData);
      // Implement with your UI framework (React, Vue, etc.)
    }
  }

  // Usage
  const dashboard = new ScoreDashboard(integration, tracker);

  // Initialize dashboard for a user
  const initResult = await dashboard.initializeUser('0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb');
  console.log('Dashboard initialized:', initResult);

  // Update leaderboard
  const leaderboardResult = await dashboard.updateLeaderboard([
    '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb',
    '0x1234567890123456789012345678901234567890',
    '0x9876543210987654321098765432109876543210'
  ]);
  console.log('Leaderboard:', leaderboardResult);

  // Get user ranking
  const ranking = dashboard.getUserRanking('0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb');
  console.log(`User ranking: #${ranking}`);
  ```
</CodeGroup>

## Error Handling

### Comprehensive Error Handler

<CodeGroup>
  ```javascript JavaScript theme={null}
  class ScoreCalculatorErrorHandler {
    static handleError(error) {
      const errorMessage = error.message || error.toString();
      
      // Common error patterns
      if (errorMessage.includes('Invalid user address')) {
        return {
          type: 'INVALID_ADDRESS',
          message: 'Please provide a valid Ethereum address',
          code: 'E001'
        };
      }
      
      if (errorMessage.includes('Invalid category')) {
        return {
          type: 'INVALID_CATEGORY',
          message: 'Category index must be between 0 and 7',
          code: 'E002'
        };
      }
      
      if (errorMessage.includes('Score out of range')) {
        return {
          type: 'INVALID_SCORE',
          message: 'Score must be between 0 and 1000',
          code: 'E003'
        };
      }
      
      if (errorMessage.includes('Update too soon')) {
        return {
          type: 'UPDATE_COOLDOWN',
          message: 'Please wait before refreshing score again',
          code: 'E004'
        };
      }
      
      if (errorMessage.includes('AccessControl')) {
        return {
          type: 'ACCESS_DENIED',
          message: 'Insufficient permissions for this operation',
          code: 'E005'
        };
      }
      
      // Default error
      return {
        type: 'UNKNOWN_ERROR',
        message: errorMessage,
        code: 'E999'
      };
    }
    
    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 ScoreCalculatorErrorHandler.safeExecute(async () => {
      return await integration.refreshScore('0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb');
    });
    console.log('Success:', result);
  } catch (error) {
    console.error('Error:', error.message);
    console.error('Code:', error.code);
    console.error('Type:', error.type);
  }
  ```
</CodeGroup>

## Best Practices

### Performance Optimization

1. **Batch Operations**: Use batch functions for multiple queries
2. **Caching**: Cache frequently accessed scores
3. **Event Listening**: Use events for real-time updates
4. **Rate Limiting**: Implement rate limiting for API calls
5. **Connection Pooling**: Reuse connections when possible

### Security Considerations

1. **Input Validation**: Validate all user inputs
2. **Private Keys**: Secure private key storage
3. **Gas Estimation**: Estimate gas before transactions
4. **Error Handling**: Implement comprehensive error handling
5. **Event Monitoring**: Monitor for unusual activity

### Testing

1. **Unit Tests**: Test individual functions
2. **Integration Tests**: Test complete workflows
3. **Performance Tests**: Test under load
4. **Security Tests**: Test for vulnerabilities
5. **End-to-End Tests**: Test complete user flows

## Related Documentation

* [Contract Overview](/contracts/score-calculator/overview) - Contract architecture and features
* [Functions Reference](/contracts/score-calculator/functions) - Complete function documentation
* [Events Reference](/contracts/score-calculator/events) - Event documentation
* [Identity SBT](/contracts/identity-sbt/overview) - Identity contract documentation
