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.All score operations support both ZKS IDs and wallet addresses. The SDK automatically resolves ZKS IDs to their corresponding wallet addresses when needed.
Basic Score Operations
1. Get Current Score
Copy
// 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
Copy
// 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
Copy
// 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
Copy
// 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
Copy
// 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
Copy
// 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
Copy
// 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
Copy
// 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
Copy
// 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
Copy
// 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
Copy
// 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
Copy
// 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
Copy
// 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
Copy
// 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 setup and configuration
- Identity Management - Identity operations
- Achievements - Achievement system
- API Reference - Score API endpoints