Overview
The ZK Proofs SDK enables you to generate zero-knowledge proofs that verify user reputation without revealing sensitive data. Prove score thresholds, achievements, attestations, and more while maintaining user privacy.
Generate Proof
Create a zero-knowledge proof for various verification types:
const proof = await sdk . zkProofs . generate ({
address: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb1' ,
type: 'score-threshold' ,
threshold: 700 ,
hideExactScore: true ,
});
console . log ( proof );
// {
// proofId: "zkp_abc123",
// type: "score-threshold",
// proof: "0x1234567890abcdef...", // ZK proof data
// publicInputs: {
// threshold: 700,
// timestamp: "2024-10-23T14:30:00Z"
// },
// expiresAt: "2024-10-23T15:30:00Z", // 1 hour validity
// metadata: {
// circuit: "score-threshold-v1",
// protocol: "groth16"
// }
// }
Proof Types
Score Threshold
Achievement
Attestation
Age
Trading Volume
Prove score is above/below a threshold without revealing exact value const proof = await sdk . zkProofs . generate ({
address: '0x742d35...' ,
type: 'score-threshold' ,
threshold: 700 ,
operator: 'gte' , // 'gte' | 'lte' | 'eq'
hideExactScore: true ,
});
Prove achievement completion without revealing other achievements const proof = await sdk . zkProofs . generate ({
address: '0x742d35...' ,
type: 'achievement' ,
achievementId: 'defi-expert' ,
hideOtherAchievements: true ,
});
Prove having a specific attestation without revealing details const proof = await sdk . zkProofs . generate ({
address: '0x742d35...' ,
type: 'attestation' ,
schema: 'kyc-verification' ,
conditions: {
'data.verified' : true ,
'data.level' : [ 'tier-2' , 'tier-3' ],
},
hideAttester: true ,
});
Prove wallet age without revealing exact creation date const proof = await sdk . zkProofs . generate ({
address: '0x742d35...' ,
type: 'wallet-age' ,
minDays: 365 ,
hideExactAge: true ,
});
Prove trading volume threshold without revealing exact amount const proof = await sdk . zkProofs . generate ({
address: '0x742d35...' ,
type: 'trading-volume' ,
minVolume: '100000' ,
timeRange: '30d' ,
hideExactVolume: true ,
});
Parameters
Proof generation parameters Address to generate proof for
Type of proof: 'score-threshold', 'achievement', 'attestation', 'wallet-age', 'trading-volume'
Threshold value (for threshold proofs)
Comparison operator: 'gte', 'lte', 'eq'
Hide exact score in proof (default: true)
Proof validity time in seconds (default: 3600)
Verify Proof
Verify a zero-knowledge proof’s validity:
const isValid = await sdk . zkProofs . verify ( proof );
console . log ( isValid );
// {
// valid: true,
// proofId: "zkp_abc123",
// type: "score-threshold",
// verified: true,
// timestamp: "2024-10-23T14:30:00Z",
// publicInputs: {
// threshold: 700
// }
// }
Parameters
Proof object or proof ID to verify
Returns
Whether the proof is valid
Whether the underlying claim is verified
Whether the proof has expired
Advanced Examples
Score-Gated Access with Privacy
async function checkAccessWithPrivacy ( userAddress : string , minScore : number ) {
try {
// User generates proof
const proof = await sdk . zkProofs . generate ({
address: userAddress ,
type: 'score-threshold' ,
threshold: minScore ,
operator: 'gte' ,
hideExactScore: true ,
});
// Application verifies proof without seeing exact score
const verification = await sdk . zkProofs . verify ( proof );
if ( verification . valid && verification . verified ) {
console . log ( '✅ Access granted (score meets threshold)' );
return true ;
} else {
console . log ( '❌ Access denied' );
return false ;
}
} catch ( error ) {
console . error ( 'Error checking access:' , error );
return false ;
}
}
// Usage
const hasAccess = await checkAccessWithPrivacy ( '0x742d35...' , 700 );
Multi-Condition Proof
async function generateComplexProof ( address : string ) {
// Generate multiple proofs in parallel
const [ scoreProof , ageProof , kycProof ] = await Promise . all ([
sdk . zkProofs . generate ({
address ,
type: 'score-threshold' ,
threshold: 700 ,
hideExactScore: true ,
}),
sdk . zkProofs . generate ({
address ,
type: 'wallet-age' ,
minDays: 365 ,
hideExactAge: true ,
}),
sdk . zkProofs . generate ({
address ,
type: 'attestation' ,
schema: 'kyc-verification' ,
conditions: {
'data.verified' : true ,
},
hideAttester: true ,
}),
]);
// Verify all proofs
const verifications = await Promise . all ([
sdk . zkProofs . verify ( scoreProof ),
sdk . zkProofs . verify ( ageProof ),
sdk . zkProofs . verify ( kycProof ),
]);
const allValid = verifications . every (( v ) => v . valid && v . verified );
return {
valid: allValid ,
proofs: {
score: scoreProof ,
age: ageProof ,
kyc: kycProof ,
},
verifications ,
};
}
Selective Disclosure
async function selectiveDisclosure ( address : string , fieldsToDisclose : string []) {
const score = await sdk . scores . getScore ( address );
// Create proof with selective disclosure
const proof = await sdk . zkProofs . generate ({
address ,
type: 'selective-disclosure' ,
disclose: fieldsToDisclose ,
hide: Object . keys ( score . breakdown ). filter (
( key ) => ! fieldsToDisclose . includes ( key )
),
});
return proof ;
}
// Example: Only disclose DeFi score
const proof = await selectiveDisclosure ( '0x742d35...' , [ 'defi' ]);
Proof Caching
class ProofCache {
private cache = new Map < string , { proof : any ; expiresAt : number }>();
async getOrGenerateProof (
address : string ,
type : string ,
params : any
) : Promise < any > {
const cacheKey = ` ${ address } - ${ type } - ${ JSON . stringify ( params ) } ` ;
const cached = this . cache . get ( cacheKey );
// Return cached proof if still valid
if ( cached && Date . now () < cached . expiresAt ) {
return cached . proof ;
}
// Generate new proof
const proof = await sdk . zkProofs . generate ({
address ,
type ,
... params ,
});
// Cache with expiry
this . cache . set ( cacheKey , {
proof ,
expiresAt: new Date ( proof . expiresAt ). getTime (),
});
return proof ;
}
clearExpired () {
const now = Date . now ();
for ( const [ key , value ] of this . cache . entries ()) {
if ( now >= value . expiresAt ) {
this . cache . delete ( key );
}
}
}
}
const proofCache = new ProofCache ();
// Usage
const proof = await proofCache . getOrGenerateProof ( '0x742d35...' , 'score-threshold' , {
threshold: 700 ,
});
Batch Verification
async function verifyMultipleProofs ( proofs : any []) {
const verifications = await Promise . all (
proofs . map (( proof ) => sdk . zkProofs . verify ( proof ))
);
const results = verifications . map (( v , i ) => ({
proofId: proofs [ i ]. proofId ,
valid: v . valid ,
verified: v . verified ,
}));
const allValid = results . every (( r ) => r . valid && r . verified );
return {
allValid ,
results ,
validCount: results . filter (( r ) => r . valid && r . verified ). length ,
invalidCount: results . filter (( r ) => ! r . valid || ! r . verified ). length ,
};
}
Time-Bound Proofs
async function generateTimeBoundProof ( address : string , validityMinutes : number ) {
const proof = await sdk . zkProofs . generate ({
address ,
type: 'score-threshold' ,
threshold: 700 ,
ttl: validityMinutes * 60 , // Convert to seconds
});
console . log ( `Proof valid until: ${ proof . expiresAt } ` );
return proof ;
}
// Generate proof valid for 30 minutes
const shortLivedProof = await generateTimeBoundProof ( '0x742d35...' , 30 );
NFT Mint Proof
async function generateMintEligibilityProof ( address : string ) {
// Combine multiple proofs for NFT mint eligibility
const [ scoreProof , tradingProof , achievementProof ] = await Promise . all ([
sdk . zkProofs . generate ({
address ,
type: 'score-threshold' ,
threshold: 800 ,
hideExactScore: true ,
}),
sdk . zkProofs . generate ({
address ,
type: 'trading-volume' ,
minVolume: '10000' ,
timeRange: '90d' ,
hideExactVolume: true ,
}),
sdk . zkProofs . generate ({
address ,
type: 'achievement' ,
achievementId: 'nft-collector' ,
hideOtherAchievements: true ,
}),
]);
// Verify all proofs
const [ scoreValid , tradingValid , achievementValid ] = await Promise . all ([
sdk . zkProofs . verify ( scoreProof ),
sdk . zkProofs . verify ( tradingProof ),
sdk . zkProofs . verify ( achievementProof ),
]);
const eligible =
scoreValid . valid &&
tradingValid . valid &&
achievementValid . valid ;
return {
eligible ,
proofs: {
score: scoreProof ,
trading: tradingProof ,
achievement: achievementProof ,
},
};
}
Recursive Proofs
async function generateRecursiveProof ( address : string ) {
// Generate base proof
const baseProof = await sdk . zkProofs . generate ({
address ,
type: 'score-threshold' ,
threshold: 700 ,
});
// Generate proof that proves the first proof is valid
const metaProof = await sdk . zkProofs . generate ({
address ,
type: 'proof-verification' ,
proofToVerify: baseProof . proofId ,
});
return {
baseProof ,
metaProof ,
};
}
Anonymous Voting
async function generateVotingProof ( voterAddress : string , minReputation : number ) {
// Generate proof of voting eligibility without revealing identity
const proof = await sdk . zkProofs . generate ({
address: voterAddress ,
type: 'score-threshold' ,
threshold: minReputation ,
hideExactScore: true ,
anonymize: true , // Don't include address in public inputs
});
// Generate nullifier to prevent double voting
const nullifier = await sdk . zkProofs . generateNullifier ({
address: voterAddress ,
context: 'proposal-123' ,
});
return {
proof ,
nullifier ,
};
}
On-Chain Verification
For on-chain verification, you can export proofs compatible with Solidity verifiers:
// Generate proof with on-chain format
const proof = await sdk . zkProofs . generate ({
address: '0x742d35...' ,
type: 'score-threshold' ,
threshold: 700 ,
format: 'solidity' ,
});
console . log ( proof . solidityCalldata );
// "0x1234567890abcdef..." - Ready for smart contract call
Smart Contract Integration
// Example Solidity verifier
contract ZKScoreVerifier {
function verifyScoreProof (
uint [ 2 ] memory a ,
uint [ 2 ][ 2 ] memory b ,
uint [ 2 ] memory c ,
uint [ 1 ] memory input
) public view returns ( bool ) {
// Verification logic
return zkVerifier. verifyProof (a, b, c, input);
}
function mintWithProof (
uint [ 2 ] memory a ,
uint [ 2 ][ 2 ] memory b ,
uint [ 2 ] memory c ,
uint [ 1 ] memory input
) public {
require ( verifyScoreProof (a, b, c, input), "Invalid proof" );
// Mint logic
}
}
Privacy Guarantees
ZK proofs guarantee:
Zero Knowledge : No information leaked beyond the claim
Soundness : Invalid proofs cannot be generated
Completeness : Valid claims always produce valid proofs
Privacy : Original data remains confidential
// Proof generation times (approximate)
const perfMetrics = {
'score-threshold' : '~2s' ,
'achievement' : '~1.5s' ,
'attestation' : '~2.5s' ,
'wallet-age' : '~1s' ,
'trading-volume' : '~3s' ,
};
// Optimization: Generate proofs in advance
async function preGenerateProofs ( address : string ) {
const proofs = await Promise . all ([
sdk . zkProofs . generate ({ address , type: 'score-threshold' , threshold: 700 }),
sdk . zkProofs . generate ({ address , type: 'wallet-age' , minDays: 365 }),
// ... more proofs
]);
// Cache for instant access
return proofs ;
}
Error Handling
try {
const proof = await sdk . zkProofs . generate ({
address: '0x742d35...' ,
type: 'score-threshold' ,
threshold: 700 ,
});
} catch ( error ) {
if ( error . code === 'INSUFFICIENT_DATA' ) {
console . log ( 'Not enough data to generate proof' );
} else if ( error . code === 'BELOW_THRESHOLD' ) {
console . log ( 'User does not meet threshold requirements' );
} else if ( error . code === 'PROOF_GENERATION_FAILED' ) {
console . log ( 'ZK proof generation failed' );
} else {
console . error ( 'Error generating proof:' , error );
}
}
TypeScript Types
interface ZKProof {
proofId : string ;
type : string ;
proof : string ;
publicInputs : Record < string , any >;
expiresAt : string ;
metadata : {
circuit : string ;
protocol : string ;
};
solidityCalldata ?: string ;
}
interface ProofVerification {
valid : boolean ;
verified : boolean ;
expired : boolean ;
proofId : string ;
timestamp : string ;
}
Best Practices
Cache Proofs : Proof generation is computationally expensive
Set Appropriate TTL : Balance security and user experience
Verify Before Use : Always verify proofs on the server side
Handle Expiry : Check proof expiration before verification
Use Appropriate Type : Choose the right proof type for your use case
Next Steps