wisdom-sdk
Version:
Core business logic and data access layer for prediction markets
1 lines • 11.8 kB
Source Map (JSON)
{"version":3,"sources":["../src/utils.ts"],"names":[],"mappings":"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","file":"utils.cjs","sourcesContent":["/**\n * Utility functions for OP Predict\n */\n\n// Admin user IDs\nexport const ADMIN_USER_IDS = [\n 'user_2tjVcbojjJk2bkQd856eNE1Ax0S', // rozar\n 'user_2tkBcBEVGanm3LHkg6XK7j91DRj', // kraken\n];\n\n// Check if a user is an admin\nexport function isAdmin(userId: string): boolean {\n return ADMIN_USER_IDS.includes(userId);\n}\n\n/**\n * Generates a UUID using the Web Crypto API which is available in both\n * Node.js and edge runtime environments. This replaces the Node.js-specific\n * crypto.randomUUID() function.\n * \n * @returns A UUID v4 string\n */\nexport function generateUUID(): string {\n // Use crypto.randomUUID() from Web Crypto API if available (modern browsers and Node.js 16+)\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n return crypto.randomUUID();\n }\n\n // Fallback implementation for environments where crypto.randomUUID() is not available\n // Based on the RFC4122 specification for UUID v4\n const getRandomBytes = (n: number): Uint8Array => {\n const bytes = new Uint8Array(n);\n if (typeof crypto !== 'undefined' && typeof crypto.getRandomValues === 'function') {\n crypto.getRandomValues(bytes);\n } else {\n // Final fallback for extremely unlikely case - not cryptographically secure\n for (let i = 0; i < n; i++) {\n bytes[i] = Math.floor(Math.random() * 256);\n }\n }\n return bytes;\n };\n\n const randomBytes = getRandomBytes(16);\n\n // Set version (4) and variant bits\n // Use non-null assertion as we know index 6 and 8 exist in our 16-byte array\n randomBytes[6] = (randomBytes[6]! & 0x0f) | 0x40; // version 4\n randomBytes[8] = (randomBytes[8]! & 0x3f) | 0x80; // variant 10\n\n // Convert to hex string with proper formatting\n let hex = '';\n for (let i = 0; i < 16; i++) {\n // We know all indexes exist in our 16-byte array\n hex += randomBytes[i]!.toString(16).padStart(2, '0');\n if (i === 3 || i === 5 || i === 7 || i === 9) {\n hex += '-';\n }\n }\n\n return hex;\n}\n\n/**\n * Calculate outcome percentages based on staked amounts with fallback to votes\n * @param outcomes Market outcomes\n * @returns Outcomes with percentages and a flag indicating if vote-based fallback was used\n */\nexport function calculateOutcomePercentages(outcomes: { id: number; name: string; amount?: number; votes?: number }[]) {\n // Calculate total amount staked for percentage\n const totalAmount = outcomes.reduce((sum, outcome) => sum + (outcome.amount || 0), 0);\n const useFallbackVotes = totalAmount === 0;\n\n // If no amount data is available, fall back to votes\n const totalVotes = useFallbackVotes\n ? outcomes.reduce((sum, outcome) => sum + (outcome.votes || 0), 0)\n : 0;\n\n // Update percentages\n const outcomesWithPercentages = outcomes.map(outcome => ({\n ...outcome,\n percentage: useFallbackVotes\n ? (totalVotes > 0 ? Math.round(((outcome.votes || 0) / totalVotes) * 100) : 0)\n : (totalAmount > 0 ? Math.round(((outcome.amount || 0) / totalAmount) * 100) : 0)\n }));\n\n return {\n outcomesWithPercentages,\n useFallbackVotes\n };\n}\n\n/**\n * Safely get the base URL of the application without causing SSR issues\n * with window access\n */\nexport function getBaseUrl(): string {\n // Check for environment variable first\n if (process.env.NEXT_PUBLIC_APP_URL) {\n return process.env.NEXT_PUBLIC_APP_URL;\n }\n\n // Then check if window is available (client-side only)\n if (typeof window !== 'undefined') {\n // In development, use window.location.origin\n if (process.env.NODE_ENV === 'development') {\n return window.location.origin;\n }\n }\n\n // Default fallback for SSR and production without env var\n return 'https://oppredict.com';\n}\n\n// Market query and search utilities\n\nexport type MarketStatus = 'active' | 'resolved' | 'cancelled' | 'closed' | 'all';\nexport type MarketType = 'binary' | 'multiple' | 'all';\nexport type SortField = 'createdAt' | 'endDate' | 'poolAmount' | 'participants';\nexport type SortDirection = 'asc' | 'desc';\n\nexport interface MarketQueryOptions {\n status?: MarketStatus;\n category?: string;\n type?: MarketType;\n search?: string;\n creatorId?: string;\n limit?: number;\n offset?: number;\n cursor?: string;\n sortBy?: SortField;\n sortDirection?: SortDirection;\n resolvedOutcomeId?: number;\n resolvedAt?: string;\n resolvedBy?: string;\n adminFee?: number;\n remainingPot?: number;\n totalWinningAmount?: number;\n}\n\nexport interface PaginatedResult<T> {\n items: T[];\n total: number;\n hasMore: boolean;\n nextCursor?: string;\n}\n\n/**\n * Simple text search for markets\n * Searches for terms in name and description\n */\nexport function searchMarketText(market: any, searchText: string): boolean {\n if (!searchText) return true;\n\n const text = `${market.name} ${market.description}`.toLowerCase();\n const terms = searchText.toLowerCase().split(/\\s+/).filter(Boolean);\n\n return terms.every(term => text.includes(term));\n}\n\n/**\n * Filter markets by multiple criteria\n */\nexport function filterMarkets(markets: any[], options: MarketQueryOptions = {}): any[] {\n return markets.filter(market => {\n console.log(options.status, market.status)\n // Status filter\n if (options.status && options.status !== 'all' && market.status !== options.status) {\n return false;\n }\n\n // Category filter\n if (options.category && market.category !== options.category) {\n return false;\n }\n\n // Type filter\n if (options.type && options.type !== 'all' && market.type !== options.type) {\n return false;\n }\n\n // Creator filter\n if (options.creatorId && market.createdBy !== options.creatorId) {\n return false;\n }\n\n // Text search\n if (options.search && !searchMarketText(market, options.search)) {\n return false;\n }\n\n return true;\n });\n}\n\n/**\n * Sort markets by specified field and direction\n */\nexport function sortMarkets(markets: any[], sortBy: SortField = 'createdAt', sortDirection: SortDirection = 'desc'): any[] {\n return [...markets].sort((a, b) => {\n let comparison = 0;\n\n // Handle different field types\n if (sortBy === 'createdAt' || sortBy === 'endDate') {\n const dateA = new Date(a[sortBy] || 0).getTime();\n const dateB = new Date(b[sortBy] || 0).getTime();\n comparison = dateA - dateB;\n } else {\n // Numeric fields\n const valA = a[sortBy] || 0;\n const valB = b[sortBy] || 0;\n comparison = valA - valB;\n }\n\n // Apply sort direction\n return sortDirection === 'asc' ? comparison : -comparison;\n });\n}\n\n/**\n * Apply pagination to results\n */\nexport function paginateResults<T>(items: T[], options: { limit?: number; offset?: number }): PaginatedResult<T> {\n const limit = options.limit || 20;\n const offset = options.offset || 0;\n const paginatedItems = items.slice(offset, offset + limit);\n\n return {\n items: paginatedItems,\n total: items.length,\n hasMore: offset + paginatedItems.length < items.length,\n nextCursor: offset + paginatedItems.length < items.length\n ? `${offset + limit}`\n : undefined\n };\n}"]}