wisdom-sdk
Version:
Core business logic and data access layer for prediction markets
1 lines • 44.9 kB
Source Map (JSON)
{"version":3,"sources":["../src/logger.ts","../src/kv-store.ts","../src/user-stats-store.ts"],"names":["kv"],"mappings":"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","file":"user-stats-store.cjs","sourcesContent":["// Simple logger interface\nexport interface Logger {\n info: (obj: Record<string, unknown>, msg?: string) => void;\n error: (obj: Record<string, unknown>, msg?: string) => void;\n warn: (obj: Record<string, unknown>, msg?: string) => void;\n debug: (obj: Record<string, unknown>, msg?: string) => void;\n child: (bindings: object) => Logger;\n}\n\n/**\n * Centralized logger configuration\n * \n * This provides consistent logging across all modules with proper\n * context and standardized error handling.\n */\n\n// Simple console-based logger factory - no external dependencies\nconst createLogger = (): Logger => {\n // Get log level from environment or default to 'info'\n const logLevel = process.env.LOG_LEVEL || 'info';\n \n // Map log levels to numeric values for comparison\n const logLevels = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3\n } as const;\n \n // Current log level\n const currentLevelValue = logLevel in logLevels \n ? logLevels[logLevel as keyof typeof logLevels] \n : logLevels.info;\n \n // Format a log message with timestamp and metadata\n const formatLog = (level: string, obj: Record<string, unknown>, msg?: string): string => {\n const timestamp = new Date().toISOString();\n const service = 'wisdom-sdk';\n const objStr = JSON.stringify(obj);\n return `[${timestamp}] ${level.toUpperCase()} [${service}] ${msg || ''} ${objStr}`;\n };\n \n // Simple implementation using console methods\n return {\n debug: (obj: Record<string, unknown>, msg?: string) => {\n if (currentLevelValue <= 0) { // debug level\n console.debug(formatLog('debug', obj, msg));\n }\n },\n info: (obj: Record<string, unknown>, msg?: string) => {\n if (currentLevelValue <= 1) { // info level\n console.info(formatLog('info', obj, msg));\n }\n },\n warn: (obj: Record<string, unknown>, msg?: string) => {\n if (currentLevelValue <= 2) { // warn level\n console.warn(formatLog('warn', obj, msg));\n }\n },\n error: (obj: Record<string, unknown>, msg?: string) => {\n if (currentLevelValue <= 3) { // error level\n console.error(formatLog('error', obj, msg));\n }\n },\n child: (bindings: object) => {\n // For child loggers, we merge the bindings with the log objects\n const childLogger = createLogger();\n \n // Override methods to include the bindings\n return {\n debug: (obj: Record<string, unknown>, msg?: string) => \n childLogger.debug({ ...obj, ...bindings }, msg),\n info: (obj: Record<string, unknown>, msg?: string) => \n childLogger.info({ ...obj, ...bindings }, msg),\n warn: (obj: Record<string, unknown>, msg?: string) => \n childLogger.warn({ ...obj, ...bindings }, msg),\n error: (obj: Record<string, unknown>, msg?: string) => \n childLogger.error({ ...obj, ...bindings }, msg),\n child: (nestedBindings: object) => \n childLogger.child({ ...bindings, ...nestedBindings })\n };\n }\n };\n};\n\n// Default logger instance\nexport const logger = createLogger();\n\n// Create a child logger with context\nexport function getContextLogger(context: string): Logger {\n return logger.child({ context });\n}\n\n// Error handling utilities\nexport class AppError extends Error {\n public readonly context: string;\n public readonly code: string;\n public readonly originalError?: Error;\n public readonly data?: Record<string, unknown>;\n\n constructor({\n message,\n context = 'general',\n code = 'INTERNAL_ERROR',\n originalError,\n data,\n }: {\n message: string;\n context?: string;\n code?: string;\n originalError?: Error;\n data?: Record<string, unknown>;\n }) {\n super(message);\n this.name = 'AppError';\n this.context = context;\n this.code = code;\n this.originalError = originalError;\n this.data = data;\n // Preserve stack trace\n Error.captureStackTrace(this, this.constructor);\n }\n\n // Logs this error with appropriate context and returns it\n log() {\n const contextLogger = getContextLogger(this.context);\n const logObj = {\n code: this.code,\n error: this.message,\n ...(this.originalError && { originalError: this.originalError.message }),\n ...(this.data && { data: this.data }),\n };\n\n contextLogger.error(logObj, this.message);\n return this;\n }\n}\n\nexport default logger;","import { kv } from '@vercel/kv';\nimport { AppError, logger } from './logger';\n\n/**\n * Centralized KV Store Helper\n * \n * This provides standardized methods for interacting with Vercel KV storage,\n * ensuring consistent key formats, serialization/deserialization, and error handling.\n * \n * Also provides transaction support to ensure data consistency for complex operations.\n */\n\n// Create a logger instance for this module\nconst kvLogger = logger.child({ context: 'kv-store' });\n\n// Define constant prefixes for all entity types\nexport const KV_PREFIXES = {\n MARKET: 'market',\n MARKET_IDS: 'market_ids',\n USER_MARKETS: 'user_markets',\n MARKET_PARTICIPANTS: 'market_participants',\n MARKET_CATEGORY: 'market_category', // Index for markets by category\n MARKET_STATUS: 'market_status', // Index for markets by status\n PREDICTION: 'prediction',\n USER_PREDICTIONS: 'user_predictions',\n MARKET_PREDICTIONS: 'market_predictions',\n PREDICTION_NFT: 'prediction_nft',\n USER_BALANCE: 'user_balance',\n USER_STATS: 'user_stats',\n LEADERBOARD: 'leaderboard',\n LEADERBOARD_EARNINGS: 'leaderboard_earnings',\n LEADERBOARD_ACCURACY: 'leaderboard_accuracy',\n BUG_REPORT: 'bug_report',\n BUG_REPORT_IDS: 'bug_report_ids',\n USER_BUG_REPORTS: 'user_bug_reports',\n // Transaction custody-related prefixes\n CUSTODY_TRANSACTION: 'custody_transaction',\n CUSTODY_TRANSACTION_IDS: 'custody_transaction_ids',\n USER_TRANSACTIONS: 'user_transactions',\n SIGNER_TRANSACTIONS: 'signer_transactions',\n MARKET_TRANSACTIONS: 'market_transactions',\n CUSTODY_NFT_RECEIPT: 'custody_nft_receipt',\n // Claim reward transaction prefixes\n CLAIM_REWARD_TRANSACTION: 'claim_reward_transaction',\n USER_CLAIM_REWARDS: 'user_claim_rewards'\n} as const;\n\n// Type safety for valid entity types\nexport type EntityType = keyof typeof KV_PREFIXES;\n\n/**\n * Get a formatted key for a specific entity\n */\nexport function getKey(entityType: EntityType, id?: string): string {\n const prefix = KV_PREFIXES[entityType];\n\n // Special handling for MARKET_IDS - it doesn't use a colon format\n if (entityType === 'MARKET_IDS' && !id) {\n return prefix;\n }\n\n return id ? `${prefix}:${id}` : prefix;\n}\n\n/**\n * Store an entity in KV\n */\nexport async function storeEntity<T>(entityType: EntityType, id: string, data: T): Promise<T> {\n try {\n const key = getKey(entityType, id);\n await kv.set(key, JSON.stringify(data));\n return data;\n } catch (error) {\n throw new AppError({\n message: `Failed to store ${entityType} with ID ${id}`,\n context: 'kv-store',\n code: 'KV_STORE_ERROR',\n originalError: error instanceof Error ? error : new Error(String(error)),\n data: { entityType, id, operation: 'store' }\n }).log();\n }\n}\n\n/**\n * Get an entity from KV - with backward compatibility\n */\nexport async function getEntity<T>(entityType: EntityType, id: string): Promise<T | null> {\n try {\n // Try with new key format\n const key = getKey(entityType, id);\n let data = await kv.get<string>(key);\n\n // If not found and it's a MARKET, try the old plural format (markets:id)\n if (!data && entityType === 'MARKET') {\n data = await kv.get<string>(`markets:${id}`);\n }\n\n if (!data) {\n // Not an error, just not found\n kvLogger.debug({ entityType, id }, `Entity not found: ${entityType}:${id}`);\n return null;\n }\n\n // If data is already in object format (newer KV might handle JSON automatically)\n if (typeof data !== 'string') {\n return data as unknown as T;\n }\n\n // Parse JSON string\n try {\n return JSON.parse(data) as T;\n } catch (e) {\n throw new AppError({\n message: `Error parsing JSON for ${entityType} with ID ${id}`,\n context: 'kv-store',\n code: 'KV_JSON_PARSE_ERROR',\n originalError: e instanceof Error ? e : new Error(String(e)),\n data: { entityType, id, operation: 'parse' }\n }).log();\n }\n } catch (error) {\n // Only throw AppError if it's not already one\n if (error instanceof AppError) {\n throw error;\n }\n\n throw new AppError({\n message: `Failed to retrieve ${entityType} with ID ${id}`,\n context: 'kv-store',\n code: 'KV_RETRIEVE_ERROR',\n originalError: error instanceof Error ? error : new Error(String(error)),\n data: { entityType, id, operation: 'get' }\n }).log();\n }\n}\n\n/**\n * Delete an entity from KV\n */\nexport async function deleteEntity(entityType: EntityType, id: string): Promise<boolean> {\n try {\n const key = getKey(entityType, id);\n await kv.del(key);\n\n // If it's a MARKET, also try to delete the legacy format\n if (entityType === 'MARKET') {\n await kv.del(`markets:${id}`);\n }\n\n return true;\n } catch (error) {\n // Log error but don't throw - deletion errors are often non-critical\n new AppError({\n message: `Failed to delete ${entityType} with ID ${id}`,\n context: 'kv-store',\n code: 'KV_DELETE_ERROR',\n originalError: error instanceof Error ? error : new Error(String(error)),\n data: { entityType, id, operation: 'delete' }\n }).log();\n\n return false;\n }\n}\n\n/**\n * Add an ID to a set - with backward compatibility\n */\nexport async function addToSet(setType: EntityType, id: string, memberId: string): Promise<boolean> {\n try {\n const key = getKey(setType, id);\n await kv.sadd(key, memberId);\n\n // If it's MARKET_IDS, also add to the old format for backward compatibility\n if (setType === 'MARKET_IDS') {\n await kv.sadd('market_ids', memberId);\n }\n\n return true;\n } catch (error) {\n new AppError({\n message: `Failed to add member ${memberId} to set ${setType}:${id}`,\n context: 'kv-store',\n code: 'KV_SET_ADD_ERROR',\n originalError: error instanceof Error ? error : new Error(String(error)),\n data: { setType, id, memberId, operation: 'sadd' }\n }).log();\n\n return false;\n }\n}\n\n/**\n * Remove an ID from a set\n */\nexport async function removeFromSet(setType: EntityType, id: string, memberId: string): Promise<boolean> {\n try {\n const key = getKey(setType, id);\n await kv.srem(key, memberId);\n\n // If it's MARKET_IDS, also remove from the old format for backward compatibility\n if (setType === 'MARKET_IDS') {\n await kv.srem('market_ids', memberId);\n }\n\n return true;\n } catch (error) {\n new AppError({\n message: `Failed to remove member ${memberId} from set ${setType}:${id}`,\n context: 'kv-store',\n code: 'KV_SET_REMOVE_ERROR',\n originalError: error instanceof Error ? error : new Error(String(error)),\n data: { setType, id, memberId, operation: 'srem' }\n }).log();\n\n return false;\n }\n}\n\n/**\n * Get all members of a set - with backward compatibility\n */\nexport async function getSetMembers(setType: EntityType, id: string): Promise<string[]> {\n try {\n const key = getKey(setType, id);\n let members = await kv.smembers(key) as string[];\n\n // For backward compatibility with market_ids\n if (setType === 'MARKET_IDS' && members.length === 0) {\n const legacyMembers = await kv.smembers('market_ids') as string[];\n if (legacyMembers.length > 0) {\n // Migrate the data to the new format\n for (const marketId of legacyMembers) {\n await addToSet('MARKET_IDS', '', marketId);\n }\n members = legacyMembers;\n }\n }\n\n return members;\n } catch (error) {\n new AppError({\n message: `Failed to get members from set ${setType}:${id}`,\n context: 'kv-store',\n code: 'KV_SET_MEMBERS_ERROR',\n originalError: error instanceof Error ? error : new Error(String(error)),\n data: { setType, id, operation: 'smembers' }\n }).log();\n\n return [];\n }\n}\n\n/**\n * Check if a member is in a set\n */\nexport async function isSetMember(setType: EntityType, id: string, memberId: string): Promise<boolean> {\n try {\n const key = getKey(setType, id);\n const result = await kv.sismember(key, memberId);\n return !!result;\n } catch (error) {\n console.error(`Error checking set membership for ${setType} with ID ${id}:`, error);\n return false;\n }\n}\n\n/**\n * Add a member to a sorted set with score\n */\nexport async function addToSortedSet(setType: EntityType, memberId: string, score: number): Promise<boolean> {\n try {\n const key = getKey(setType);\n await kv.zadd(key, { score, member: memberId });\n return true;\n } catch (error) {\n console.error(`Error adding to sorted set ${setType}:`, error);\n return false;\n }\n}\n\n/**\n * Get top members from a sorted set\n */\nexport async function getTopFromSortedSet(setType: EntityType, limit: number = 10, reverse: boolean = true): Promise<string[]> {\n try {\n const key = getKey(setType);\n return await kv.zrange(key, 0, limit - 1, { rev: reverse }) as string[];\n } catch (error) {\n console.error(`Error getting top members from sorted set ${setType}:`, error);\n return [];\n }\n}\n\n/**\n * Get scores for specific members from a sorted set\n * Returns a map of memberId -> score\n */\nexport async function getScoresFromSortedSet(setType: EntityType, memberIds: string[]): Promise<Record<string, number>> {\n try {\n const key = getKey(setType);\n const result: Record<string, number> = {};\n\n // Process members in batches if there are many\n const batchSize = 50;\n for (let i = 0; i < memberIds.length; i += batchSize) {\n const batch = memberIds.slice(i, i + batchSize);\n\n // Get scores for this batch\n const batchScores = await Promise.all(\n batch.map(async (memberId) => {\n const score = await kv.zscore(key, memberId);\n return { memberId, score: score ? Number(score) : null };\n })\n );\n\n // Add scores to result map\n batchScores.forEach(({ memberId, score }) => {\n if (score !== null) {\n result[memberId] = score;\n }\n });\n }\n\n return result;\n } catch (error) {\n console.error(`Error getting scores from sorted set ${setType}:`, error);\n return {};\n }\n}\n\n/**\n * Get all keys matching a pattern\n */\nexport async function getKeys(pattern: string): Promise<string[]> {\n try {\n return await kv.keys(pattern) as string[];\n } catch (error) {\n console.error(`Error getting keys with pattern ${pattern}:`, error);\n return [];\n }\n}\n\n/**\n * Check if a key exists\n */\nexport async function keyExists(entityType: EntityType, id: string): Promise<boolean> {\n try {\n const key = getKey(entityType, id);\n const result = await kv.exists(key);\n return result === 1;\n } catch (error) {\n console.error(`Error checking if key exists for ${entityType} with ID ${id}:`, error);\n return false;\n }\n}\n\n/**\n * Debug function to get information about KV store\n */\nexport async function getDebugInfo(): Promise<Record<string, unknown>> {\n try {\n const allKeys = await kv.keys('*');\n const patterns = [\n 'market:*',\n 'markets:*',\n 'market_ids',\n 'prediction:*',\n 'predictions:*',\n 'user_predictions:*',\n 'market_predictions:*',\n 'prediction_nft:*',\n 'prediction_nfts:*'\n ];\n\n const result: Record<string, unknown> = {\n totalKeys: allKeys.length,\n keysByPattern: {} as Record<string, { count: number; sample: string[] }>\n };\n\n const keysByPattern = result.keysByPattern as Record<string, { count: number; sample: string[] }>;\n\n for (const pattern of patterns) {\n const keys = await kv.keys(pattern);\n keysByPattern[pattern] = {\n count: keys.length,\n sample: keys.slice(0, 5) as string[]\n };\n }\n\n return result;\n } catch (error) {\n console.error('Error getting debug info:', error);\n return { error: String(error) };\n }\n}\n\n/**\n * Transaction interface for atomic operations\n */\nexport interface KvTransaction {\n operations: Array<{\n type: 'entity' | 'set' | 'sortedSet';\n entityType: EntityType;\n id: string;\n data?: unknown;\n }>;\n addEntity<T>(entityType: EntityType, id: string, data: T): Promise<void>;\n addToSetInTransaction(setType: EntityType, id: string, memberId: string): Promise<void>;\n addToSortedSetInTransaction(setType: EntityType, memberId: string, score: number): Promise<void>;\n execute(): Promise<boolean>;\n}\n\n/**\n * Start a Redis transaction for atomic operations\n * @returns A transaction object with methods that queue commands to be executed atomically\n */\nexport async function startTransaction(): Promise<KvTransaction> {\n try {\n // @vercel/kv supports Redis transactions via the multi() method\n const transaction = kv.multi();\n\n // Track operations for potential rollback planning\n const operations: Array<{\n type: 'entity' | 'set' | 'sortedSet';\n entityType: EntityType;\n id: string;\n data?: unknown;\n }> = [];\n\n const txObject: KvTransaction = {\n operations,\n\n // Add entity to transaction\n async addEntity<T>(entityType: EntityType, id: string, data: T): Promise<void> {\n const key = getKey(entityType, id);\n transaction.set(key, JSON.stringify(data));\n operations.push({ type: 'entity', entityType, id, data });\n },\n\n // Add to set in transaction\n async addToSetInTransaction(setType: EntityType, id: string, memberId: string): Promise<void> {\n const key = getKey(setType, id);\n transaction.sadd(key, memberId);\n operations.push({ type: 'set', entityType: setType, id: memberId });\n\n // Handle backward compatibility if needed\n if (setType === 'MARKET_IDS') {\n transaction.sadd('market_ids', memberId);\n }\n },\n\n // Add to sorted set in transaction\n async addToSortedSetInTransaction(setType: EntityType, memberId: string, score: number): Promise<void> {\n const key = getKey(setType);\n transaction.zadd(key, { score, member: memberId });\n operations.push({ type: 'sortedSet', entityType: setType, id: memberId, data: score });\n },\n\n // Execute all queued commands atomically\n async execute(): Promise<boolean> {\n try {\n kvLogger.debug(\n { operationCount: operations.length },\n `Executing transaction with ${operations.length} operations`\n );\n\n await transaction.exec();\n return true;\n } catch (error) {\n const appError = new AppError({\n message: 'Transaction execution failed',\n context: 'kv-store',\n code: 'TRANSACTION_FAILED',\n originalError: error instanceof Error ? error : new Error(String(error)),\n data: { operationCount: operations.length }\n });\n\n appError.log();\n\n // Note: Redis transactions are atomic - they either all succeed or all fail\n // No manual rollback is needed as failed transactions don't apply any changes\n\n return false;\n }\n }\n };\n\n return txObject;\n } catch (error) {\n throw new AppError({\n message: 'Failed to start transaction',\n context: 'kv-store',\n code: 'TRANSACTION_START_ERROR',\n originalError: error instanceof Error ? error : new Error(String(error))\n }).log();\n }\n}","import * as kvStore from './kv-store';\n\n// User stats store with Vercel KV\nexport const userStatsStore = {\n // Helper to calculate user score consistently across the app\n calculateUserScore(stats: any): number {\n // Only count users with at least 5 predictions for the accuracy component\n const accuracyComponent = stats.totalPredictions >= 5 ? stats.accuracy : 0;\n\n // Normalize earnings (0-100 scale typically)\n const normalizedEarnings = stats.totalEarnings / 100;\n\n // Prediction volume factor (logarithmic scale to prevent domination by volume)\n const volumeFactor = stats.totalPredictions > 0 ? Math.log10(stats.totalPredictions + 1) * 10 : 0;\n\n // Consistency factor - higher for users who maintain accuracy across more predictions\n const consistencyFactor = stats.totalPredictions >= 10 ?\n (accuracyComponent * Math.min(stats.totalPredictions / 20, 1.5)) :\n accuracyComponent;\n\n // Final composite score\n return (consistencyFactor * 0.4) +\n (normalizedEarnings * 0.3) +\n (Math.min(volumeFactor, 25) * 0.3);\n },\n\n // Get user stats for a specific user\n async getUserStats(userId: string) {\n try {\n if (!userId) return null;\n\n const stats = await kvStore.getEntity('USER_STATS', userId);\n return stats || null;\n } catch (error) {\n console.error(`Error getting user stats for ${userId}:`, error);\n return null;\n }\n },\n\n // Update user stats when a prediction is made\n async updateStatsForNewPrediction(userId: string, prediction: any) {\n try {\n // Get current stats or create new ones\n const currentStats: any = await this.getUserStats(userId) || {\n userId,\n totalPredictions: 0,\n correctPredictions: 0,\n accuracy: 0,\n totalAmount: 0,\n totalEarnings: 0,\n lastUpdated: new Date().toISOString()\n };\n\n // Update stats\n const updatedStats = {\n ...currentStats,\n totalPredictions: currentStats.totalPredictions + 1,\n totalAmount: currentStats.totalAmount + prediction.amount,\n lastUpdated: new Date().toISOString()\n };\n\n // Recalculate accuracy\n updatedStats.accuracy =\n updatedStats.totalPredictions > 0\n ? (updatedStats.correctPredictions / updatedStats.totalPredictions) * 100\n : 0;\n\n // Store updated stats\n await kvStore.storeEntity('USER_STATS', userId, updatedStats);\n\n // Update leaderboard sorted sets for efficient querying\n await this.updateLeaderboardEntries(updatedStats);\n\n return updatedStats;\n } catch (error) {\n console.error(`Error updating stats for user ${userId}:`, error);\n throw error;\n }\n },\n\n // Update user stats when a prediction is resolved\n async updateStatsForResolvedPrediction(\n userId: string,\n prediction: any,\n isCorrect: boolean,\n earnings: number\n ) {\n try {\n // Handle anonymous/test users specially\n if (!userId || userId === 'anonymous') {\n console.log('Skipping stats update for anonymous user');\n return {\n userId,\n totalPredictions: 1,\n correctPredictions: isCorrect ? 1 : 0,\n accuracy: isCorrect ? 100 : 0,\n totalAmount: prediction?.amount || 0,\n totalEarnings: earnings,\n lastUpdated: new Date().toISOString()\n };\n }\n\n // Get current stats\n const currentStats: any = await this.getUserStats(userId);\n if (!currentStats) {\n console.log(`Creating new stats for user ${userId}`);\n // Create default stats if not found\n const newStats = {\n userId,\n totalPredictions: 1,\n correctPredictions: isCorrect ? 1 : 0,\n accuracy: isCorrect ? 100 : 0,\n totalAmount: prediction?.amount || 0,\n totalEarnings: earnings,\n lastUpdated: new Date().toISOString()\n };\n \n // Store new stats\n await kvStore.storeEntity('USER_STATS', userId, newStats);\n \n // Update leaderboard sorted sets\n await this.updateLeaderboardEntries(newStats);\n \n return newStats;\n }\n\n // Update stats\n const updatedStats = {\n ...currentStats,\n correctPredictions: isCorrect\n ? currentStats.correctPredictions + 1\n : currentStats.correctPredictions,\n totalEarnings: currentStats.totalEarnings + earnings,\n lastUpdated: new Date().toISOString()\n };\n\n // Recalculate accuracy\n updatedStats.accuracy =\n updatedStats.totalPredictions > 0\n ? (updatedStats.correctPredictions / updatedStats.totalPredictions) * 100\n : 0;\n\n // Store updated stats\n await kvStore.storeEntity('USER_STATS', userId, updatedStats);\n\n // Update leaderboard sorted sets\n await this.updateLeaderboardEntries(updatedStats);\n\n return updatedStats;\n } catch (error) {\n console.error(`Error updating stats for resolved prediction, user ${userId}:`, error);\n throw error;\n }\n },\n\n // Update user's username (when available from auth provider)\n async updateUsername(userId: string, username: string) {\n try {\n const stats: any = await this.getUserStats(userId);\n if (!stats) return null;\n\n const updatedStats = {\n ...stats,\n username,\n lastUpdated: new Date().toISOString()\n };\n\n await kvStore.storeEntity('USER_STATS', userId, updatedStats);\n\n // Update leaderboard entries\n await this.updateLeaderboardEntries(updatedStats);\n\n return updatedStats;\n } catch (error) {\n console.error(`Error updating username for user ${userId}:`, error);\n return null;\n }\n },\n\n // Update leaderboard sorted sets for efficient querying\n async updateLeaderboardEntries(stats: any): Promise<void> {\n try {\n // Add to earnings leaderboard (sorted by total earnings)\n await kvStore.addToSortedSet(\n 'LEADERBOARD_EARNINGS',\n stats.userId,\n stats.totalEarnings\n );\n\n // Add to accuracy leaderboard (sorted by accuracy)\n // Only count users with at least 5 predictions for accuracy\n const accuracyScore = stats.totalPredictions >= 5 ? stats.accuracy : 0;\n await kvStore.addToSortedSet(\n 'LEADERBOARD_ACCURACY',\n stats.userId,\n accuracyScore\n );\n\n // Advanced scoring algorithm for leaderboard ranking\n // Calculate the composite score using the helper method\n const compositeScore = this.calculateUserScore(stats);\n\n // Store in the main leaderboard\n await kvStore.addToSortedSet(\n 'LEADERBOARD',\n stats.userId,\n compositeScore\n );\n } catch (error) {\n console.error('Error updating leaderboard entries:', error);\n throw error;\n }\n },\n\n // Get top leaderboard entries by earnings\n async getTopEarners(limit: number = 10) {\n try {\n // Get top user IDs sorted by earnings (highest first)\n const userIds = await kvStore.getTopFromSortedSet('LEADERBOARD_EARNINGS', limit);\n\n // Get full stats for each user ID\n const leaderboard = await this.getUserStatsForIds(userIds);\n\n // Get scores from the same sorted set to ensure consistency\n const scoresMap = await kvStore.getScoresFromSortedSet('LEADERBOARD_EARNINGS', userIds);\n\n // Add rank and use the actual scores from Redis\n return leaderboard.map((entry: any, index) => {\n return {\n ...entry,\n rank: index + 1,\n score: scoresMap[entry.userId] || this.calculateUserScore(entry)\n };\n });\n } catch (error) {\n console.error('Error getting top earners:', error);\n return [];\n }\n },\n\n // Get top leaderboard entries by accuracy\n async getTopAccurate(limit: number = 10) {\n try {\n // Get top user IDs sorted by accuracy (highest first)\n const userIds = await kvStore.getTopFromSortedSet('LEADERBOARD_ACCURACY', limit);\n\n // Get full stats for each user ID\n const leaderboard = await this.getUserStatsForIds(userIds);\n\n // Get scores from the same sorted set to ensure consistency\n const scoresMap = await kvStore.getScoresFromSortedSet('LEADERBOARD_ACCURACY', userIds);\n\n // Add rank and use the actual scores from Redis\n return leaderboard.map((entry: any, index) => {\n return {\n ...entry,\n rank: index + 1,\n score: scoresMap[entry.userId] || this.calculateUserScore(entry)\n };\n });\n } catch (error) {\n console.error('Error getting top accuracy:', error);\n return [];\n }\n },\n\n // Get top leaderboard entries by combined score\n async getTopUsers(limit: number = 10) {\n try {\n // Get top user IDs sorted by combined score (highest first)\n const userIds = await kvStore.getTopFromSortedSet('LEADERBOARD', limit);\n\n // Get full stats for each user ID\n const leaderboard = await this.getUserStatsForIds(userIds);\n\n // Get scores from the same sorted set to ensure consistency\n const scoresMap = await kvStore.getScoresFromSortedSet('LEADERBOARD', userIds);\n\n // Add rank and use the actual scores from Redis\n return leaderboard.map((entry: any, index) => {\n return {\n ...entry,\n rank: index + 1,\n score: scoresMap[entry.userId] || this.calculateUserScore(entry)\n };\n });\n } catch (error) {\n console.error('Error getting leaderboard:', error);\n return [];\n }\n },\n\n // Helper to get multiple user stats by IDs\n async getUserStatsForIds(userIds: string[]) {\n try {\n if (userIds.length === 0) return [];\n\n // Get stats for each user ID\n const statsPromises = userIds.map(id => this.getUserStats(id));\n const statsResults = await Promise.all(statsPromises);\n\n // Filter out any null results\n return statsResults.filter(Boolean);\n } catch (error) {\n console.error('Error getting user stats for IDs:', error);\n return [];\n }\n }\n};"]}