Overview
Implement zero-knowledge proof verification to prove score thresholds or achievements without revealing exact values.Basic ZK Verification
Score Threshold Proof
Copy
import { ZKScoreClient } from '@zkscore/sdk';
const client = new ZKScoreClient({
apiKey: process.env.ZKSCORE_API_KEY
});
class ZKVerification {
constructor() {
this.client = client;
}
async generateScoreProof(userAddress, threshold) {
try {
const score = await this.client.getScore(userAddress);
if (score.total < threshold) {
throw new Error('Score below threshold');
}
// Generate ZK proof that score >= threshold without revealing exact score
const proof = await this.client.generateZKProof({
type: 'score_threshold',
user: userAddress,
threshold: threshold,
actualScore: score.total
});
return {
proof,
threshold,
isValid: true
};
} catch (error) {
console.error('Error generating proof:', error);
return { isValid: false, error: error.message };
}
}
async verifyScoreProof(proof, threshold) {
try {
const isValid = await this.client.verifyZKProof(proof, {
type: 'score_threshold',
threshold: threshold
});
return { isValid, threshold };
} catch (error) {
console.error('Error verifying proof:', error);
return { isValid: false, error: error.message };
}
}
}
Achievement Proof
Copy
class AchievementProof {
constructor(client) {
this.client = client;
}
async generateAchievementProof(userAddress, achievementId) {
try {
const achievements = await this.client.getAchievements(userAddress);
const hasAchievement = achievements.some(a => a.id === achievementId);
if (!hasAchievement) {
throw new Error('User does not have this achievement');
}
const proof = await this.client.generateZKProof({
type: 'achievement',
user: userAddress,
achievementId: achievementId
});
return {
proof,
achievementId,
isValid: true
};
} catch (error) {
console.error('Error generating achievement proof:', error);
return { isValid: false, error: error.message };
}
}
async verifyAchievementProof(proof, achievementId) {
try {
const isValid = await this.client.verifyZKProof(proof, {
type: 'achievement',
achievementId: achievementId
});
return { isValid, achievementId };
} catch (error) {
console.error('Error verifying achievement proof:', error);
return { isValid: false, error: error.message };
}
}
}
React ZK Verification Component
Proof Generation Component
Copy
import React, { useState } from 'react';
import { ZKScoreClient } from '@zkscore/sdk';
const ZKProofGenerator = ({ userAddress }) => {
const [threshold, setThreshold] = useState(500);
const [proof, setProof] = useState(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const client = new ZKScoreClient({
apiKey: process.env.REACT_APP_ZKSCORE_API_KEY
});
const generateProof = async () => {
try {
setLoading(true);
setError(null);
const result = await client.generateZKProof({
type: 'score_threshold',
user: userAddress,
threshold: threshold
});
setProof(result);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
};
return (
<div className="zk-proof-generator">
<h2>Generate ZK Proof</h2>
<div className="form-group">
<label>Score Threshold:</label>
<input
type="number"
value={threshold}
onChange={(e) => setThreshold(parseInt(e.target.value))}
min="0"
max="1000"
/>
</div>
<button
onClick={generateProof}
disabled={loading}
className="generate-button"
>
{loading ? 'Generating...' : 'Generate Proof'}
</button>
{error && <div className="error">{error}</div>}
{proof && (
<div className="proof-result">
<h3>Generated Proof</h3>
<div className="proof-details">
<p><strong>Threshold:</strong> {proof.threshold}</p>
<p><strong>Valid:</strong> {proof.isValid ? 'Yes' : 'No'}</p>
</div>
<div className="proof-data">
<textarea
value={JSON.stringify(proof.proof, null, 2)}
readOnly
rows="10"
/>
</div>
</div>
)}
</div>
);
};
Proof Verification Component
Copy
const ZKProofVerifier = () => {
const [proofData, setProofData] = useState('');
const [threshold, setThreshold] = useState(500);
const [verificationResult, setVerificationResult] = useState(null);
const [loading, setLoading] = useState(false);
const client = new ZKScoreClient({
apiKey: process.env.REACT_APP_ZKSCORE_API_KEY
});
const verifyProof = async () => {
try {
setLoading(true);
const proof = JSON.parse(proofData);
const result = await client.verifyZKProof(proof, {
type: 'score_threshold',
threshold: threshold
});
setVerificationResult(result);
} catch (error) {
setVerificationResult({
isValid: false,
error: error.message
});
} finally {
setLoading(false);
}
};
return (
<div className="zk-proof-verifier">
<h2>Verify ZK Proof</h2>
<div className="form-group">
<label>Proof Data:</label>
<textarea
value={proofData}
onChange={(e) => setProofData(e.target.value)}
placeholder="Paste proof JSON here..."
rows="8"
/>
</div>
<div className="form-group">
<label>Expected Threshold:</label>
<input
type="number"
value={threshold}
onChange={(e) => setThreshold(parseInt(e.target.value))}
min="0"
max="1000"
/>
</div>
<button
onClick={verifyProof}
disabled={loading || !proofData}
className="verify-button"
>
{loading ? 'Verifying...' : 'Verify Proof'}
</button>
{verificationResult && (
<div className={`verification-result ${verificationResult.isValid ? 'valid' : 'invalid'}`}>
<h3>Verification Result</h3>
<p><strong>Valid:</strong> {verificationResult.isValid ? 'Yes' : 'No'}</p>
{verificationResult.error && (
<p><strong>Error:</strong> {verificationResult.error}</p>
)}
</div>
)}
</div>
);
};
Privacy-Preserving Access Control
ZK Gating System
Copy
class ZKGatingSystem {
constructor(client) {
this.client = client;
}
async checkZKAccess(userAddress, requirements) {
try {
const proofs = [];
// Generate proofs for each requirement
for (const requirement of requirements) {
if (requirement.type === 'score_threshold') {
const proof = await this.client.generateZKProof({
type: 'score_threshold',
user: userAddress,
threshold: requirement.threshold
});
proofs.push(proof);
} else if (requirement.type === 'achievement') {
const proof = await this.client.generateZKProof({
type: 'achievement',
user: userAddress,
achievementId: requirement.achievementId
});
proofs.push(proof);
}
}
return {
hasAccess: true,
proofs: proofs
};
} catch (error) {
return {
hasAccess: false,
error: error.message
};
}
}
async verifyZKAccess(proofs, requirements) {
try {
for (let i = 0; i < proofs.length; i++) {
const proof = proofs[i];
const requirement = requirements[i];
const isValid = await this.client.verifyZKProof(proof, requirement);
if (!isValid) {
return { hasAccess: false, reason: 'Invalid proof' };
}
}
return { hasAccess: true };
} catch (error) {
return { hasAccess: false, error: error.message };
}
}
}
Advanced ZK Features
Batch Proof Generation
Copy
class BatchZKProofs {
constructor(client) {
this.client = client;
}
async generateBatchProofs(userAddress, requirements) {
try {
const proofPromises = requirements.map(async (requirement) => {
const proof = await this.client.generateZKProof({
type: requirement.type,
user: userAddress,
...requirement.params
});
return { requirement, proof };
});
const results = await Promise.all(proofPromises);
return results;
} catch (error) {
console.error('Error generating batch proofs:', error);
return [];
}
}
async verifyBatchProofs(proofs, requirements) {
try {
const verificationPromises = proofs.map(async (proofData, index) => {
const requirement = requirements[index];
const isValid = await this.client.verifyZKProof(
proofData.proof,
requirement
);
return { requirement, isValid };
});
const results = await Promise.all(verificationPromises);
return results;
} catch (error) {
console.error('Error verifying batch proofs:', error);
return [];
}
}
}
Best Practices
- Privacy First: Never reveal exact scores or sensitive data
- Proof Validation: Always verify proofs before granting access
- Error Handling: Handle proof generation failures gracefully
- Performance: Consider proof generation time for UX
- Security: Use secure proof generation and verification