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

> Implement score-based access control using ZKScore SDK

## Overview

Implement score-based access control to gate features, content, or functionality based on user ZKScore.

## Basic Score Gating

### Simple Score Check

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

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

  async function checkAccess(userAddress, requiredScore) {
    try {
      const score = await client.getScore(userAddress);
      return score.total >= requiredScore;
    } catch (error) {
      console.error('Error checking score:', error);
      return false;
    }
  }

  // Usage
  const hasAccess = await checkAccess(userAddress, 500);
  if (hasAccess) {
    // Grant access to premium feature
    showPremiumContent();
  } else {
    // Show upgrade prompt
    showUpgradePrompt();
  }
  ```
</CodeGroup>

### Category-Based Gating

<CodeGroup>
  ```javascript JavaScript theme={null}
  async function checkCategoryAccess(userAddress, category, requiredScore) {
    try {
      const breakdown = await client.getScoreBreakdown(userAddress);
      return breakdown[category] >= requiredScore;
    } catch (error) {
      console.error('Error checking category score:', error);
      return false;
    }
  }

  // Check DeFi access
  const hasDeFiAccess = await checkCategoryAccess(userAddress, 'defi', 200);
  if (hasDeFiAccess) {
    showDeFiFeatures();
  }
  ```
</CodeGroup>

## Advanced Gating

### Multi-Criteria Gating

<CodeGroup>
  ```javascript JavaScript theme={null}
  class ScoreGate {
    constructor(client) {
      this.client = client;
    }
    
    async checkAccess(userAddress, criteria) {
      try {
        const score = await client.getScore(userAddress);
        const breakdown = await client.getScoreBreakdown(userAddress);
        
        // Check total score
        if (criteria.totalScore && score.total < criteria.totalScore) {
          return { access: false, reason: 'Insufficient total score' };
        }
        
        // Check category scores
        for (const [category, requiredScore] of Object.entries(criteria.categories || {})) {
          if (breakdown[category] < requiredScore) {
            return { access: false, reason: `Insufficient ${category} score` };
          }
        }
        
        // Check achievements
        if (criteria.achievements) {
          const achievements = await client.getAchievements(userAddress);
          const achievementIds = achievements.map(a => a.id);
          
          for (const requiredAchievement of criteria.achievements) {
            if (!achievementIds.includes(requiredAchievement)) {
              return { access: false, reason: 'Missing required achievement' };
            }
          }
        }
        
        return { access: true };
      } catch (error) {
        return { access: false, reason: 'Error checking access' };
      }
    }
  }

  // Usage
  const gate = new ScoreGate(client);
  const result = await gate.checkAccess(userAddress, {
    totalScore: 600,
    categories: {
      defi: 200,
      nft: 100
    },
    achievements: ['defi-pioneer', 'nft-collector']
  });

  if (result.access) {
    grantAccess();
  } else {
    showAccessDenied(result.reason);
  }
  ```
</CodeGroup>

## React Component Example

### Score Gate Component

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

  const ScoreGate = ({ 
    userAddress, 
    requiredScore, 
    children, 
    fallback,
    category,
    requiredCategoryScore 
  }) => {
    const [hasAccess, setHasAccess] = useState(false);
    const [loading, setLoading] = useState(true);
    const [error, setError] = useState(null);
    
    useEffect(() => {
      checkAccess();
    }, [userAddress, requiredScore, category, requiredCategoryScore]);
    
    const checkAccess = async () => {
      try {
        setLoading(true);
        setError(null);
        
        const client = new ZKScoreClient({
          apiKey: process.env.REACT_APP_ZKSCORE_API_KEY
        });
        
        if (category && requiredCategoryScore) {
          const breakdown = await client.getScoreBreakdown(userAddress);
          setHasAccess(breakdown[category] >= requiredCategoryScore);
        } else {
          const score = await client.getScore(userAddress);
          setHasAccess(score.total >= requiredScore);
        }
      } catch (err) {
        setError(err.message);
        setHasAccess(false);
      } finally {
        setLoading(false);
      }
    };
    
    if (loading) {
      return <div>Checking access...</div>;
    }
    
    if (error) {
      return <div>Error: {error}</div>;
    }
    
    if (hasAccess) {
      return children;
    }
    
    return fallback || <div>Access denied</div>;
  };

  // Usage
  function PremiumFeature() {
    return (
      <ScoreGate 
        userAddress={userAddress}
        requiredScore={500}
        fallback={<div>You need a score of 500+ to access this feature</div>}
      >
        <div>Premium content here!</div>
      </ScoreGate>
    );
  }
  ```
</CodeGroup>

## Vue Component Example

### Score Gate Directive

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

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

  export const scoreGate = {
    async inserted(el, binding) {
      const { userAddress, requiredScore, category, requiredCategoryScore } = binding.value;
      
      try {
        let hasAccess = false;
        
        if (category && requiredCategoryScore) {
          const breakdown = await client.getScoreBreakdown(userAddress);
          hasAccess = breakdown[category] >= requiredCategoryScore;
        } else {
          const score = await client.getScore(userAddress);
          hasAccess = score.total >= requiredScore;
        }
        
        if (!hasAccess) {
          el.style.display = 'none';
        }
      } catch (error) {
        console.error('Score gate error:', error);
        el.style.display = 'none';
      }
    }
  };

  // Usage in Vue component
  export default {
    directives: { scoreGate },
    template: `
      <div v-score-gate="{ userAddress, requiredScore: 500 }">
        Premium content
      </div>
    `
  };
  ```
</CodeGroup>

## Server-Side Gating

### Express.js Middleware

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

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

  export const scoreGate = (requiredScore, category, requiredCategoryScore) => {
    return async (req, res, next) => {
      try {
        const userAddress = req.user.address; // From auth middleware
        
        if (category && requiredCategoryScore) {
          const breakdown = await client.getScoreBreakdown(userAddress);
          if (breakdown[category] < requiredCategoryScore) {
            return res.status(403).json({ 
              error: 'Insufficient score', 
              required: requiredCategoryScore,
              current: breakdown[category]
            });
          }
        } else {
          const score = await client.getScore(userAddress);
          if (score.total < requiredScore) {
            return res.status(403).json({ 
              error: 'Insufficient score', 
              required: requiredScore,
              current: score.total
            });
          }
        }
        
        next();
      } catch (error) {
        res.status(500).json({ error: 'Score check failed' });
      }
    };
  };

  // Usage
  app.get('/premium-content', 
    scoreGate(500), 
    (req, res) => {
      res.json({ content: 'Premium content here' });
    }
  );
  ```
</CodeGroup>

## Best Practices

1. **Graceful Degradation**: Always provide fallbacks for failed checks
2. **Caching**: Cache score data to reduce API calls
3. **User Feedback**: Clearly communicate access requirements
4. **Security**: Never trust client-side score checks alone
5. **Performance**: Use batch operations when checking multiple users

## Related Documentation

* [Trust Gating Guide](/guides/trust-gating)
* [Basic Integration](/sdk/examples/basic-integration)
* [Complete Integration](/sdk/examples/complete-integration)
