@verifiedonchain-protocol/sdk 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +152 -0
- package/dist/index.d.ts +563 -0
- package/dist/index.js +3003 -0
- package/dist/index.js.map +1 -0
- package/package.json +67 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/biometrics/simHash.ts","../src/core/biometrics/biometricUtils.ts","../src/core/biometrics/faceOcclusion.ts","../src/core/biometrics/LivenessEngine.ts","../src/core/biometrics/captureQuality.ts","../src/core/config/humanConfig.ts","../src/core/api/relayer.ts","../src/react/hooks/useVisionModels.ts","../src/react/hooks/useCameraStream.ts","../src/react/components/FaceZK.tsx","../src/react/components/ProofOfHumanity.tsx","../src/react/components/VerifiedOnchainFlow.tsx","../src/react/components/wallet/WalletSelection.tsx","../src/react/components/wallet/SocialConnection.tsx"],"sourcesContent":["import { ethers } from 'ethers';\n\n// Fixed seed for deterministic hyperplanes\n// In production, this should be a system-wide constant or part of the circuit parameters\nconst SEED_PREFIX = \"HumanityGen_SimHash_Hyperplane_\";\n\n// Standard SimHash configuration\n// 1024 dimensions (typical face embedding) -> 256 bit signature\nconst EMBEDDING_DIMENSIONS = 1024; // Assuming 1024 from previous analysis, adaptable\nconst SIGNATURE_BITS = 256;\n\n/**\n * Generates deterministic random hyperplanes\n * These chop the high-dimensional space into 256 regions\n * @param dimensions Input embedding dimensions\n * @param count Number of hyperplanes (bits in output hash)\n */\nexport function generateHyperplanes(dimensions: number, count: number): number[][] {\n const hyperplanes: number[][] = [];\n\n for (let i = 0; i < count; i++) {\n // Generate a deterministic seed for this hyperplane\n // We use a simple hash of the index to ensure it's always the same\n // Note: In a real ZK circuit, these would be fixed constants in the circuit\n const seed = `${SEED_PREFIX}${i}`;\n \n // Use a PRNG seeded with this value to generate the vector\n // For simplicity in this prototype, we'll use a simple linear congruential generator\n // seeded by the hash of the index\n \n const vector: number[] = [];\n let currentSeed = simpleHash(seed);\n \n // Helper to get a deterministic float between 0 and 1\n const nextRandom = () => {\n // Enforce strict 32-bit integer math (C-style wrapping) to guarantee absolute \n // determinism across all browsers and devices, avoiding any JS float drift.\n currentSeed = (Math.imul(currentSeed, 1664525) + 1013904223) >>> 0;\n return currentSeed / 4294967296;\n };\n\n for (let j = 0; j < dimensions; j += 2) {\n // Box-Muller transform for standard normal distribution N(0, 1)\n const u1 = Math.max(nextRandom(), 1e-10); // avoid log(0)\n const u2 = nextRandom();\n \n const z0 = Math.sqrt(-2.0 * Math.log(u1)) * Math.cos(2.0 * Math.PI * u2);\n const z1 = Math.sqrt(-2.0 * Math.log(u1)) * Math.sin(2.0 * Math.PI * u2);\n \n vector.push(z0);\n if (j + 1 < dimensions) {\n vector.push(z1);\n }\n }\n \n hyperplanes.push(vector);\n }\n\n return hyperplanes;\n}\n\n/**\n * Simple string hash for seeding (FNV-1a variant)\n */\nfunction simpleHash(str: string): number {\n let hash = 2166136261;\n for (let i = 0; i < str.length; i++) {\n hash ^= str.charCodeAt(i);\n hash = Math.imul(hash, 16777619);\n }\n return hash >>> 0;\n}\n\n/**\n * Computes SimHash for a given embedding\n * @param embedding The face embedding vector\n * @param hyperplanes Pre-computed hyperplanes\n * @returns Hex string representation of the hash\n */\nexport function computeSimHash(embedding: number[], hyperplanes: number[][]): string {\n if (embedding.length === 0) return \"\";\n \n // In case embedding size mismatches hyperplanes (e.g. 512 vs 1024), \n // we truncate or pad. Ideally they match.\n const dims = Math.min(embedding.length, hyperplanes[0].length);\n \n let signatureBytes = new Uint8Array(hyperplanes.length / 8);\n \n for (let i = 0; i < hyperplanes.length; i++) {\n let dotProduct = 0;\n for (let j = 0; j < dims; j++) {\n dotProduct += embedding[j] * hyperplanes[i][j];\n }\n \n // If dot product > 0, set bit to 1, else 0\n if (dotProduct > 0) {\n const byteIndex = Math.floor(i / 8);\n const bitIndex = 7 - (i % 8); // Big-endian ish filling\n signatureBytes[byteIndex] |= (1 << bitIndex);\n }\n }\n \n // Convert to Hex\n return uint8ArrayToHex(signatureBytes);\n}\n\nfunction uint8ArrayToHex(bytes: Uint8Array): string {\n return Array.from(bytes)\n .map(b => b.toString(16).padStart(2, '0'))\n .join('');\n}\n\n/**\n * Similarity from Hamming distance: 1 - (distance / totalBits).\n * Same hash => 1, max distance (256) => 0.\n */\nexport function similarityFromDistance(distance: number, totalBits: number = 256): number {\n return Math.max(0, 1 - distance / totalBits);\n}\n\n/**\n * Computes Hamming Distance between two hex strings\n */\nexport function hammingDistance(hex1: string, hex2: string): number {\n if (hex1.length !== hex2.length) {\n throw new Error(\"Hex strings must be equal length\");\n }\n\n let distance = 0;\n \n // Process byte by byte\n for (let i = 0; i < hex1.length; i += 2) {\n const byte1 = parseInt(hex1.substring(i, i + 2), 16);\n const byte2 = parseInt(hex2.substring(i, i + 2), 16);\n \n let xor = byte1 ^ byte2;\n \n // Count set bits\n while (xor > 0) {\n if ((xor & 1) === 1) distance++;\n xor >>= 1;\n }\n }\n \n return distance;\n}\n\n// Singleton for hyperplanes (lazy load)\nlet cachedHyperplanes: number[][] | null = null;\n\nexport function getHyperplanes(dimensions: number = 1024, count: number = 256): number[][] {\n if (!cachedHyperplanes || cachedHyperplanes[0].length !== dimensions || cachedHyperplanes.length !== count) {\n console.time(\"Generating Hyperplanes\");\n cachedHyperplanes = generateHyperplanes(dimensions, count);\n console.timeEnd(\"Generating Hyperplanes\");\n }\n return cachedHyperplanes;\n}\n","import { FaceResult } from '@vladmandic/human';\nimport { computeSimHash, getHyperplanes, hammingDistance as simHashHammingDistance } from './simHash';\n\n// ============================================================================\n// TYPES & INTERFACES\n// ============================================================================\n\nexport interface RawFacialData {\n faceEmbedding: number[];\n faceMesh: number[][];\n faceLandmarks: number[][];\n faceRotation: {\n angle: { yaw: number; pitch: number; roll: number };\n matrix: number[];\n } | null;\n faceBox: {\n x: number;\n y: number;\n width: number;\n height: number;\n } | null;\n emotion?: Array<{\n emotion: string;\n score: number;\n }>;\n timestamp: number;\n}\n\nexport interface LivenessData {\n blinkCount: number;\n blinkTimestamps: number[];\n emotionTransitions: Array<{\n from: string;\n to: string;\n timestamp: number;\n duration: number;\n }>;\n headMovement: {\n yawRange: [number, number];\n pitchRange: [number, number];\n rollRange: [number, number];\n };\n verificationDuration: number;\n stepCompletionTimes: {\n happy: number;\n eyeBlink: number;\n };\n}\n\nexport interface VerificationResult {\n rawFacialData: RawFacialData;\n livenessData: LivenessData;\n isComplete: boolean;\n message: string;\n}\n\nexport interface AleoEmbeddingChunks {\n embedding_chunk1: number[][];\n embedding_chunk2: number[][];\n embedding_chunk3: number[][];\n embedding_chunk4: number[][];\n}\n\nexport interface AleoCircuitInputs extends AleoEmbeddingChunks {\n liveness_combined: number;\n}\n\n/**\n * Clean biometric data payload\n */\nexport interface BiometricSimHashPayload {\n simhash_full: string;\n liveness_combined: number;\n}\n\nexport interface AleoCircuitInputsComplete extends AleoCircuitInputs {\n salt: string;\n}\n\nexport interface AleoSimHashInputs {\n simhash_full: string; // The full 256-bit hex string for local testing\n liveness_combined: string; // u8 string\n salt: string; // field string\n}\n\nexport interface DataQuality {\n isValid: boolean;\n score: number;\n issues: string[];\n}\n\n// ============================================================================\n// CONSTANTS\n// ============================================================================\n\nconst EXPECTED_MESH_POINTS = 468;\nconst EXPECTED_LANDMARKS = 68;\nconst MIN_EMBEDDING_LENGTH = 128;\nconst MIN_FACE_SIZE = 100;\nconst MAX_ROTATION_YAW = 30;\nconst MAX_ROTATION_PITCH = 20;\nconst MAX_ROTATION_ROLL = 15;\nconst MIN_QUALITY_SCORE = 75;\n\n// ============================================================================\n// UTILITY FUNCTIONS\n// ============================================================================\n\n/**\n * Average multiple embeddings to reduce noise (Robust outlier rejection)\n * We calculate the median of all embeddings to find a stable center point,\n * then filter out frames that are too far from this center, and average the rest.\n */\nexport function averageEmbeddings(embeddings: number[][]): number[] {\n if (!embeddings || embeddings.length === 0) return [];\n if (embeddings.length === 1) return embeddings[0];\n \n const dim = embeddings[0].length;\n const count = embeddings.length;\n \n // 1. Calculate the Median embedding to find a robust center\n const medianEmbedding = new Array(dim).fill(0);\n for (let d = 0; d < dim; d++) {\n const valuesForDim = embeddings.map(emb => emb[Math.min(d, emb.length - 1)] || 0);\n valuesForDim.sort((a, b) => a - b);\n medianEmbedding[d] = valuesForDim[Math.floor(count / 2)];\n }\n \n // 2. Calculate Euclidean distance of each embedding to the median\n const distances = embeddings.map((emb, index) => {\n let sumSq = 0;\n for (let d = 0; d < dim; d++) {\n const diff = (emb[d] || 0) - medianEmbedding[d];\n sumSq += diff * diff;\n }\n return { index, distance: Math.sqrt(sumSq) };\n });\n \n // 3. Sort by distance, keep only the best 70% (throw away 30% outliers)\n distances.sort((a, b) => a.distance - b.distance);\n const keepCount = Math.max(1, Math.floor(count * 0.7));\n const bestIndices = new Set(distances.slice(0, keepCount).map(d => d.index));\n \n // 4. Calculate standard mean of the best embeddings\n const finalAvg = new Array(dim).fill(0);\n for (let i = 0; i < count; i++) {\n if (bestIndices.has(i)) {\n for (let d = 0; d < dim; d++) {\n finalAvg[d] += embeddings[i][d] || 0;\n }\n }\n }\n \n for (let d = 0; d < dim; d++) {\n finalAvg[d] /= keepCount;\n }\n \n console.log(`Averaged ${keepCount} clean embeddings (discarded ${count - keepCount} outliers)`);\n return finalAvg;\n}\n\n/**\n * Safely extract numeric value from potentially undefined object\n */\nfunction safeNumber(value: any, fallback: number = 0): number {\n return typeof value === 'number' && !isNaN(value) ? value : fallback;\n}\n\n/**\n * Convert point to [x, y, z] array format\n */\nfunction normalizePoint(point: any): [number, number, number] {\n if (!point) return [0, 0, 0];\n \n if (Array.isArray(point)) {\n return [\n safeNumber(point[0]),\n safeNumber(point[1]),\n safeNumber(point[2])\n ];\n }\n \n if (typeof point === 'object') {\n return [\n safeNumber(point.x),\n safeNumber(point.y),\n safeNumber(point.z)\n ];\n }\n \n return [0, 0, 0];\n}\n\n/**\n * Extract mesh data with fallback logic\n */\nfunction extractMeshData(face: FaceResult): number[][] {\n // Try meshRaw first (raw unprocessed mesh)\n if (Array.isArray((face as any).meshRaw) && (face as any).meshRaw.length > 0) {\n return (face as any).meshRaw.map(normalizePoint);\n }\n \n // Fallback to mesh\n if (Array.isArray(face.mesh) && face.mesh.length > 0) {\n return face.mesh.map(normalizePoint);\n }\n \n // Return empty mesh as last resort\n console.warn('No mesh data available, using empty mesh');\n return Array(EXPECTED_MESH_POINTS).fill([0, 0, 0]);\n}\n\n/**\n * Extract landmarks from mesh (first 68 points)\n */\nfunction extractLandmarksFromMesh(mesh: number[][]): number[][] {\n if (mesh.length === 0) {\n console.warn('No mesh data for landmarks, using empty landmarks');\n return Array(EXPECTED_LANDMARKS).fill([0, 0]);\n }\n \n return mesh.slice(0, EXPECTED_LANDMARKS).map(point => [point[0], point[1]]);\n}\n\n/**\n * Extract bounding box with multiple fallback strategies\n */\nfunction extractBoundingBox(face: FaceResult, mesh: number[][]): RawFacialData['faceBox'] {\n const box = face.box as any;\n \n if (!box) {\n return calculateBoxFromMesh(mesh);\n }\n \n // Try different box formats\n if (box.x !== undefined && box.width !== undefined) {\n return {\n x: safeNumber(box.x),\n y: safeNumber(box.y),\n width: safeNumber(box.width),\n height: safeNumber(box.height)\n };\n }\n \n if (box.left !== undefined) {\n return {\n x: safeNumber(box.left),\n y: safeNumber(box.top),\n width: safeNumber(box.right - box.left),\n height: safeNumber(box.bottom - box.top)\n };\n }\n \n if (Array.isArray(box) && box.length >= 4) {\n return {\n x: safeNumber(box[0]),\n y: safeNumber(box[1]),\n width: safeNumber(box[2]),\n height: safeNumber(box[3])\n };\n }\n \n return calculateBoxFromMesh(mesh);\n}\n\n/**\n * Calculate bounding box from mesh points\n */\nfunction calculateBoxFromMesh(mesh: number[][]): RawFacialData['faceBox'] {\n if (mesh.length === 0) return null;\n \n const xs = mesh.map(p => p[0]).filter(x => typeof x === 'number' && !isNaN(x));\n const ys = mesh.map(p => p[1]).filter(y => typeof y === 'number' && !isNaN(y));\n \n if (xs.length === 0 || ys.length === 0) return null;\n \n const minX = Math.min(...xs);\n const maxX = Math.max(...xs);\n const minY = Math.min(...ys);\n const maxY = Math.max(...ys);\n \n return {\n x: minX,\n y: minY,\n width: maxX - minX,\n height: maxY - minY\n };\n}\n\n// ============================================================================\n// CORE EXTRACTION FUNCTIONS\n// ============================================================================\n\n/**\n * Extract raw facial data from Human.js face detection result\n * Improved with better error handling and data validation\n */\nexport function extractRawFacialData(face: FaceResult): RawFacialData {\n if (!face) {\n throw new Error('No face data provided');\n }\n\n // Extract and normalize embedding\n const rawEmbedding = face.embedding || [];\n \n // CRITICAL: Check if embedding exists\n if (!rawEmbedding || rawEmbedding.length === 0) {\n console.error('❌ CRITICAL: Face embedding is empty!');\n console.error('This means face.description module is not enabled in Human.js config');\n console.error('Enable it with: face: { description: { enabled: true } }');\n throw new Error(\n 'Face embedding not available. Ensure face.description is enabled in Human.js configuration.'\n );\n }\n \n const faceEmbedding = normalizeEmbedding(Array.from(rawEmbedding));\n \n // Extract mesh data\n const faceMesh = extractMeshData(face);\n \n // Extract landmarks from mesh\n const faceLandmarks = extractLandmarksFromMesh(faceMesh);\n \n // Extract rotation data\n const faceRotation = face.rotation ? {\n angle: {\n yaw: safeNumber(face.rotation.angle?.yaw),\n pitch: safeNumber(face.rotation.angle?.pitch),\n roll: safeNumber(face.rotation.angle?.roll)\n },\n matrix: Array.isArray(face.rotation.matrix) ? face.rotation.matrix : []\n } : null;\n \n // Extract bounding box\n const faceBox = extractBoundingBox(face, faceMesh);\n \n // Extract emotion data\n const emotion = Array.isArray(face.emotion) ? face.emotion.map(em => ({\n emotion: em.emotion || 'unknown',\n score: safeNumber(em.score)\n })) : undefined;\n\n const result: RawFacialData = {\n faceEmbedding,\n faceMesh,\n faceLandmarks,\n faceRotation,\n faceBox,\n emotion,\n timestamp: Date.now()\n };\n\n // Log extraction summary\n console.log('✅ Facial data extracted:', {\n embeddingLength: faceEmbedding.length,\n meshPoints: faceMesh.length,\n landmarksPoints: faceLandmarks.length,\n hasRotation: !!faceRotation,\n hasBox: !!faceBox,\n emotions: emotion?.length || 0\n });\n\n return result;\n}\n\n/**\n * Normalize face embedding vector to unit length (L2 normalization)\n */\nexport function normalizeEmbedding(embedding: number[]): number[] {\n if (!embedding?.length) return [];\n \n const norm = Math.sqrt(embedding.reduce((sum, val) => sum + val * val, 0));\n \n if (norm === 0 || !isFinite(norm)) {\n console.warn('Invalid norm detected, returning original embedding');\n return embedding;\n }\n \n return embedding.map(val => val / norm);\n}\n\n/**\n * Create liveness data from verification session\n */\nexport function createLivenessData(\n blinkCount: number,\n blinkTimestamps: number[],\n emotionTransitions: LivenessData['emotionTransitions'],\n headMovement: LivenessData['headMovement'],\n verificationDuration: number,\n stepCompletionTimes: LivenessData['stepCompletionTimes']\n): LivenessData {\n return {\n blinkCount,\n blinkTimestamps: [...blinkTimestamps], // Create copy\n emotionTransitions: [...emotionTransitions], // Create copy\n headMovement: { ...headMovement }, // Create copy\n verificationDuration,\n stepCompletionTimes: { ...stepCompletionTimes } // Create copy\n };\n}\n\n// ============================================================================\n// EMBEDDING QUANTIZER CLASS\n// ============================================================================\n\nexport class EmbeddingQuantizer {\n private DEFAULT_MIN: number;\n private DEFAULT_MAX: number;\n private readonly EPSILON = 1e-8;\n\n constructor(calibrationParams?: { min?: number; max?: number }) {\n this.DEFAULT_MIN = calibrationParams?.min ?? -2.0;\n this.DEFAULT_MAX = calibrationParams?.max ?? 2.0;\n }\n\n /**\n * Quantize embedding to u8 format for Aleo circuit\n */\n quantizeEmbedding(\n embedding: number[] | Float32Array,\n targetRows: number = 4,\n targetCols: number = 16\n ): number[][] {\n const normalized = this.normalizeToRange(embedding);\n const reshaped = this.reshapeEmbedding(normalized, targetRows, targetCols);\n \n return reshaped.map(row => \n row.map(value => Math.min(255, Math.max(0, Math.round(value * 255))))\n );\n }\n\n /**\n * Normalize to [0, 1] range with improved outlier handling\n */\n private normalizeToRange(embedding: number[] | Float32Array): number[] {\n const embArray = Array.from(embedding);\n \n if (embArray.length === 0) {\n throw new Error('Empty embedding provided');\n }\n \n const actualMin = Math.min(...embArray);\n const actualMax = Math.max(...embArray);\n \n const minVal = Math.min(actualMin, this.DEFAULT_MIN);\n const maxVal = Math.max(actualMax, this.DEFAULT_MAX);\n const range = maxVal - minVal + this.EPSILON;\n \n return embArray.map(value => {\n const normalized = (value - minVal) / range;\n return Math.max(0, Math.min(1, normalized));\n });\n }\n\n /**\n * Strategic sampling with information-preserving bias\n */\n private reshapeEmbedding(\n embedding: number[],\n targetRows: number,\n targetCols: number\n ): number[][] {\n const totalTarget = targetRows * targetCols;\n const sourceLength = embedding.length;\n \n if (sourceLength <= totalTarget) {\n return this.padAndReshape(embedding, targetRows, targetCols);\n }\n \n return this.sampleAndReshape(embedding, targetRows, targetCols);\n }\n\n /**\n * Improved sampling with better distribution\n */\n private sampleAndReshape(\n embedding: number[],\n targetRows: number,\n targetCols: number\n ): number[][] {\n const totalTarget = targetRows * targetCols;\n const sourceLength = embedding.length;\n const sampledValues: number[] = [];\n \n for (let i = 0; i < totalTarget; i++) {\n const ratio = i / totalTarget;\n let position: number;\n \n if (ratio < 0.7) {\n // Sample more from beginning (information-rich)\n position = Math.floor((ratio / 0.7) * sourceLength * 0.6);\n } else {\n // Sample from end\n const remaining = ratio - 0.7;\n position = Math.floor(sourceLength * 0.6 + (remaining / 0.3) * sourceLength * 0.4);\n }\n \n sampledValues.push(embedding[Math.min(position, sourceLength - 1)]);\n }\n \n // Reshape to 2D\n const result: number[][] = [];\n for (let row = 0; row < targetRows; row++) {\n result.push(sampledValues.slice(row * targetCols, (row + 1) * targetCols));\n }\n \n return result;\n }\n\n /**\n * Pad with mean value to maintain distribution\n */\n private padAndReshape(\n embedding: number[],\n targetRows: number,\n targetCols: number\n ): number[][] {\n const totalTarget = targetRows * targetCols;\n const mean = embedding.reduce((sum, val) => sum + val, 0) / embedding.length;\n const padded = [...embedding, ...Array(totalTarget - embedding.length).fill(mean)];\n \n const result: number[][] = [];\n for (let row = 0; row < targetRows; row++) {\n result.push(padded.slice(row * targetCols, (row + 1) * targetCols));\n }\n \n return result;\n }\n\n /**\n * Process embedding for all 4 Aleo circuit chunks\n */\n processForAleo(embedding: number[] | Float32Array): AleoEmbeddingChunks {\n const embArray = Array.from(embedding);\n \n return {\n embedding_chunk1: this.quantizeEmbedding(embArray, 4, 16),\n embedding_chunk2: this.createChunkWithOffset(embArray, 0.25),\n embedding_chunk3: this.createChunkWithOffset(embArray, 0.5),\n embedding_chunk4: this.createChunkWithOffset(embArray, 0.75)\n };\n }\n\n /**\n * Create chunk with circular offset\n */\n private createChunkWithOffset(\n embedding: number[],\n offsetRatio: number\n ): number[][] {\n const offsetIndex = Math.floor(embedding.length * offsetRatio);\n const shifted = [\n ...embedding.slice(offsetIndex),\n ...embedding.slice(0, offsetIndex)\n ];\n return this.quantizeEmbedding(shifted, 4, 16);\n }\n\n /**\n * Validate quantized embedding meets Aleo requirements\n */\n validateForAleo(chunks: AleoEmbeddingChunks): void {\n const chunkArray = [\n chunks.embedding_chunk1,\n chunks.embedding_chunk2,\n chunks.embedding_chunk3,\n chunks.embedding_chunk4\n ];\n \n chunkArray.forEach((chunk, chunkIdx) => {\n if (chunk.length !== 4) {\n throw new Error(`Chunk ${chunkIdx + 1}: Expected 4 rows, got ${chunk.length}`);\n }\n \n chunk.forEach((row, rowIdx) => {\n if (row.length !== 16) {\n throw new Error(`Chunk ${chunkIdx + 1}, Row ${rowIdx}: Expected 16 cols, got ${row.length}`);\n }\n \n row.forEach((value, colIdx) => {\n if (!Number.isInteger(value) || value < 0 || value > 255) {\n throw new Error(\n `Chunk ${chunkIdx + 1}[${rowIdx}][${colIdx}]: Invalid u8 value ${value}`\n );\n }\n });\n });\n });\n }\n\n /**\n * Calibrate parameters from sample embeddings\n */\n calibrateFromSamples(samples: (number[] | Float32Array)[]): { min: number; max: number } {\n if (samples.length === 0) {\n throw new Error('No samples provided for calibration');\n }\n \n let globalMin = Infinity;\n let globalMax = -Infinity;\n \n for (const embedding of samples) {\n const embArray = Array.from(embedding);\n globalMin = Math.min(globalMin, Math.min(...embArray));\n globalMax = Math.max(globalMax, Math.max(...embArray));\n }\n \n const padding = (globalMax - globalMin) * 0.1;\n this.DEFAULT_MIN = globalMin - padding;\n this.DEFAULT_MAX = globalMax + padding;\n \n console.log(`Calibrated quantizer: [${this.DEFAULT_MIN.toFixed(3)}, ${this.DEFAULT_MAX.toFixed(3)}]`);\n \n return { min: this.DEFAULT_MIN, max: this.DEFAULT_MAX };\n }\n}\n\n// ============================================================================\n// VALIDATION & PROCESSING\n// ============================================================================\n\n/**\n * Validate facial data quality with detailed scoring\n */\nexport function validateDataQuality(data: RawFacialData): DataQuality {\n const issues: string[] = [];\n let score = 100;\n\n // Embedding validation\n if (data.faceEmbedding.length < MIN_EMBEDDING_LENGTH) {\n issues.push(`Embedding too short: ${data.faceEmbedding.length} < ${MIN_EMBEDDING_LENGTH}`);\n score -= 30;\n }\n\n // Mesh validation (Relaxed for performance optimization)\n if (data.faceMesh.length > 0 && data.faceMesh.length < EXPECTED_MESH_POINTS) {\n issues.push(`Incomplete mesh: ${data.faceMesh.length}/${EXPECTED_MESH_POINTS} points. (Ignored for performance)`);\n // No longer subtracting score as we intentionally disabled full mesh\n }\n\n // Landmarks validation\n if (data.faceLandmarks.length < EXPECTED_LANDMARKS) {\n issues.push(`Incomplete landmarks: ${data.faceLandmarks.length}/${EXPECTED_LANDMARKS} points`);\n score -= 15;\n }\n\n // Rotation validation\n if (data.faceRotation) {\n const { yaw, pitch, roll } = data.faceRotation.angle;\n \n if (Math.abs(yaw) > MAX_ROTATION_YAW) {\n issues.push(`Excessive yaw rotation: ${yaw.toFixed(1)}°`);\n score -= 10;\n }\n if (Math.abs(pitch) > MAX_ROTATION_PITCH) {\n issues.push(`Excessive pitch tilt: ${pitch.toFixed(1)}°`);\n score -= 10;\n }\n if (Math.abs(roll) > MAX_ROTATION_ROLL) {\n issues.push(`Excessive roll tilt: ${roll.toFixed(1)}°`);\n score -= 10;\n }\n }\n\n // Box size validation\n if (data.faceBox) {\n const { width, height } = data.faceBox;\n if (width < MIN_FACE_SIZE || height < MIN_FACE_SIZE) {\n issues.push(`Face too small: ${Math.round(width)}x${Math.round(height)}px`);\n score -= 15;\n }\n }\n\n score = Math.max(0, score);\n \n return {\n isValid: score >= MIN_QUALITY_SCORE,\n score,\n issues\n };\n}\n\n/**\n * Process facial data for Aleo circuit with complete validation\n */\nexport function processFacialDataForAleo(\n face: FaceResult,\n livenessData: LivenessData,\n quantizer?: EmbeddingQuantizer\n): AleoCircuitInputs {\n const rawFacialData = extractRawFacialData(face);\n const quality = validateDataQuality(rawFacialData);\n \n if (!quality.isValid) {\n console.warn('Data quality issues detected:', quality.issues);\n }\n \n // Calculate liveness combined flag\n const hasBlink = livenessData.blinkCount >= 1;\n const hasEmotionTransition = livenessData.emotionTransitions.length > 0;\n \n let livenessCombined = 0;\n if (hasBlink && hasEmotionTransition) {\n livenessCombined = 3; // 0x03\n } else if (hasBlink) {\n livenessCombined = 1; // 0x01\n } else if (hasEmotionTransition) {\n livenessCombined = 2; // 0x02\n }\n \n const embeddingQuantizer = quantizer || new EmbeddingQuantizer();\n const chunks = embeddingQuantizer.processForAleo(rawFacialData.faceEmbedding);\n \n // Validate chunks\n embeddingQuantizer.validateForAleo(chunks);\n \n return {\n ...chunks,\n liveness_combined: livenessCombined\n };\n}\n\nexport interface AleoSimHashInputs {\n simhash_full: string; // The full 256-bit hex string for local testing\n liveness_combined: string; // u8 string\n salt: string; // field string\n}\n\n/**\n * Process facial data using SimHash (Simplified for local testing)\n */\nexport function generateBiometricSimHash(\n face: FaceResult,\n livenessData: LivenessData,\n averagedEmbedding?: number[] // Optional: Pre-averaged embedding for better stability\n): BiometricSimHashPayload {\n // 1. Extract raw embedding\n const rawData = extractRawFacialData(face);\n \n // Use averaged embedding if provided, otherwise use the single frame's embedding\n // We still need to normalize it\n const sourceEmbedding = averagedEmbedding && averagedEmbedding.length > 0 \n ? averagedEmbedding \n : rawData.faceEmbedding;\n \n const normalized = normalizeEmbedding(sourceEmbedding);\n \n // 2. Compute SimHash (Hex String)\n // Assuming 1024 dims, 256 bits\n const hyperplanes = getHyperplanes(1024, 256);\n const simHashHex = computeSimHash(normalized, hyperplanes);\n \n // 3. Liveness Logic (same as before)\n const hasBlink = livenessData.blinkCount >= 1;\n const hasEmotionTransition = livenessData.emotionTransitions.length > 0;\n \n let livenessCombined = 0;\n if (hasBlink && hasEmotionTransition) {\n livenessCombined = 3; \n } else if (hasBlink) {\n livenessCombined = 1;\n } else if (hasEmotionTransition) {\n livenessCombined = 2;\n }\n \n return {\n simhash_full: simHashHex,\n liveness_combined: livenessCombined\n };\n}\n\n// ============================================================================\n// UTILITY EXPORTS\n// ============================================================================\n\nexport function generateRandomSalt(): string {\n const array = new Uint32Array(8);\n \n if (typeof crypto !== 'undefined' && crypto.getRandomValues) {\n crypto.getRandomValues(array);\n } else {\n for (let i = 0; i < array.length; i++) {\n array[i] = Math.floor(Math.random() * 0xffffffff);\n }\n }\n \n return Array.from(array)\n .map(val => val.toString(16).padStart(8, '0'))\n .join('');\n}\n\nexport function createCalibratedQuantizer(\n samples: (number[] | Float32Array)[]\n): EmbeddingQuantizer {\n const quantizer = new EmbeddingQuantizer();\n quantizer.calibrateFromSamples(samples);\n return quantizer;\n}\n\n\n/**\n * Calculate Hamming Distance between two hex-encoded SimHashes.\n * Delegates to the canonical byte-level implementation in simHash.ts\n * to guarantee consistency with the on-chain comparison logic.\n */\nexport function calculateHammingDistance(hash1: string, hash2: string): number {\n return simHashHammingDistance(hash1, hash2);\n}\n","/**\n * Face occlusion checks from a video frame + MediaPipe Face Landmarker points.\n *\n * Glasses Detection Overhaul (v2):\n * Six independent signals are computed per eye. A bilateral threshold model\n * (≥3 signals on both eyes, or ≥4 total + ≥1 bridge signal) fires the\n * \"glasses detected\" flag. An internal per-signal EMA smooths results across\n * frames, so a single noisy frame cannot cause a false positive.\n *\n * Public API is unchanged — callers of checkFaceOcclusionRaw,\n * FaceOcclusionTracker, and checkFaceOcclusion need no modifications.\n */\n\n// ─── Public types ─────────────────────────────────────────────────────────────\n\nexport interface NormalizedLandmark {\n x: number;\n y: number;\n z?: number;\n}\n\nexport interface FaceOcclusionResult {\n ok: boolean;\n message?: string;\n}\n\nexport interface OcclusionCheckOptions {\n yawDegrees?: number;\n duringLivenessFlash?: boolean;\n}\n\n// ─── Internal primitives ──────────────────────────────────────────────────────\n\ninterface RgbSample {\n r: number;\n g: number;\n b: number;\n luma: number;\n}\n\ninterface EyeSignals {\n /** Signal 1: lens too dark compared to skin (sunglasses) */\n lensOpacity: boolean;\n /** Signal 2: dense horizontal edges at the frame strip above the lid */\n frameEdgeDensity: boolean;\n /** Signal 4: two or more specular blobs inside the eye bounding box */\n specularClusters: boolean;\n /** Signal 5: consistent chroma stripe between brow and cheek */\n chromaStripe: boolean;\n /** Signal 6: iris texture variance suppressed (lens distortion) */\n irisTextureMismatch: boolean;\n}\n\n// ─── Pixel helpers ────────────────────────────────────────────────────────────\n\nfunction lumaOf(r: number, g: number, b: number): number {\n return 0.299 * r + 0.587 * g + 0.114 * b;\n}\n\nfunction chromaDist(a: RgbSample, b: RgbSample): number {\n const sumA = a.r + a.g + a.b || 1;\n const sumB = b.r + b.g + b.b || 1;\n const rA = a.r / sumA, gA = a.g / sumA;\n const rB = b.r / sumB, gB = b.g / sumB;\n return Math.sqrt((rA - rB) ** 2 + (gA - gB) ** 2);\n}\n\n/** Sample the mean colour of a small square neighbourhood around a landmark. */\nfunction samplePoint(\n ctx: CanvasRenderingContext2D,\n landmarks: NormalizedLandmark[],\n index: number,\n width: number,\n height: number,\n radius = 3,\n): RgbSample {\n const pt = landmarks[index];\n if (!pt) return { r: 128, g: 96, b: 80, luma: 100 };\n\n const cx = Math.max(0, Math.min(width - 1, Math.floor(pt.x * width)));\n const cy = Math.max(0, Math.min(height - 1, Math.floor(pt.y * height)));\n const x0 = Math.max(0, cx - radius);\n const y0 = Math.max(0, cy - radius);\n const bw = Math.min(width - x0, radius * 2 + 1);\n const bh = Math.min(height - y0, radius * 2 + 1);\n if (bw < 1 || bh < 1) return { r: 128, g: 96, b: 80, luma: 100 };\n\n const data = ctx.getImageData(x0, y0, bw, bh).data;\n let r = 0, g = 0, b = 0;\n const n = data.length / 4;\n for (let i = 0; i < data.length; i += 4) {\n r += data[i]; g += data[i + 1]; b += data[i + 2];\n }\n r /= n; g /= n; b /= n;\n return { r, g, b, luma: lumaOf(r, g, b) };\n}\n\n/**\n * Sample the mean colour of a rectangular pixel region (absolute px coords).\n */\nfunction sampleRect(\n ctx: CanvasRenderingContext2D,\n x0: number, y0: number, w: number, h: number,\n imgW: number, imgH: number,\n): RgbSample {\n x0 = Math.max(0, Math.round(x0));\n y0 = Math.max(0, Math.round(y0));\n w = Math.min(imgW - x0, Math.max(1, Math.round(w)));\n h = Math.min(imgH - y0, Math.max(1, Math.round(h)));\n const data = ctx.getImageData(x0, y0, w, h).data;\n let r = 0, g = 0, b = 0;\n const n = data.length / 4;\n for (let i = 0; i < data.length; i += 4) {\n r += data[i]; g += data[i + 1]; b += data[i + 2];\n }\n r /= n; g /= n; b /= n;\n return { r, g, b, luma: lumaOf(r, g, b) };\n}\n\n// ─── Signal 2: Sobel edge density ─────────────────────────────────────────────\n\n/**\n * Compute the fraction of pixels with Sobel magnitude above `threshold` in a\n * rectangular strip. High fraction → dense frame material.\n */\nfunction sobelEdgeDensity(\n ctx: CanvasRenderingContext2D,\n x0: number, y0: number, w: number, h: number,\n imgW: number, imgH: number,\n threshold = 30,\n): number {\n x0 = Math.max(0, Math.round(x0));\n y0 = Math.max(0, Math.round(y0));\n w = Math.min(imgW - x0, Math.max(3, Math.round(w)));\n h = Math.min(imgH - y0, Math.max(3, Math.round(h)));\n const data = ctx.getImageData(x0, y0, w, h).data;\n\n // Build greyscale\n const grey = new Float32Array(w * h);\n for (let i = 0; i < grey.length; i++) {\n grey[i] = lumaOf(data[i * 4], data[i * 4 + 1], data[i * 4 + 2]);\n }\n\n let edgePx = 0;\n for (let y = 1; y < h - 1; y++) {\n for (let x = 1; x < w - 1; x++) {\n const idx = y * w + x;\n const gx =\n -grey[idx - w - 1] + grey[idx - w + 1]\n - 2 * grey[idx - 1] + 2 * grey[idx + 1]\n - grey[idx + w - 1] + grey[idx + w + 1];\n const gy =\n grey[idx - w - 1] + 2 * grey[idx - w] + grey[idx - w + 1]\n - grey[idx + w - 1] - 2 * grey[idx + w] - grey[idx + w + 1];\n if (Math.sqrt(gx * gx + gy * gy) > threshold) edgePx++;\n }\n }\n return edgePx / ((w - 2) * (h - 2));\n}\n\n// ─── Signal 4: Specular blob counting ─────────────────────────────────────────\n\n/**\n * Find specular highlight blobs (luma > 220) inside a rectangular region.\n * Returns the number of spatially-distinct blobs (connected components).\n * Two centroids are considered distinct if they are > minSepFraction * width apart.\n */\nfunction countSpecularBlobs(\n ctx: CanvasRenderingContext2D,\n x0: number, y0: number, w: number, h: number,\n imgW: number, imgH: number,\n lumaThreshold = 220,\n minSepFraction = 0.15,\n): number {\n x0 = Math.max(0, Math.round(x0));\n y0 = Math.max(0, Math.round(y0));\n w = Math.min(imgW - x0, Math.max(1, Math.round(w)));\n h = Math.min(imgH - y0, Math.max(1, Math.round(h)));\n const data = ctx.getImageData(x0, y0, w, h).data;\n\n const brightCentroids: Array<{ x: number; y: number }> = [];\n const minSep = w * minSepFraction;\n\n for (let row = 0; row < h; row++) {\n for (let col = 0; col < w; col++) {\n const i = (row * w + col) * 4;\n const l = lumaOf(data[i], data[i + 1], data[i + 2]);\n if (l < lumaThreshold) continue;\n\n // Is this pixel too close to an existing centroid?\n let merged = false;\n for (const c of brightCentroids) {\n const d = Math.hypot(col - c.x, row - c.y);\n if (d < minSep) { merged = true; break; }\n }\n if (!merged) brightCentroids.push({ x: col, y: row });\n }\n }\n return brightCentroids.length;\n}\n\n// ─── Signal 6: Iris texture variance ──────────────────────────────────────────\n\n/**\n * Compute pixel variance of luma inside the iris landmark circle.\n * Iris landmarks: right 469-472, left 474-477.\n * Returns -1 if iris landmarks are unavailable (< 478 points).\n */\nfunction irisLumaVariance(\n ctx: CanvasRenderingContext2D,\n landmarks: NormalizedLandmark[],\n irisIndices: number[], // 4 ring points\n imgW: number,\n imgH: number,\n): number {\n if (landmarks.length < 478) return -1; // refined landmarks required\n const valid = irisIndices.filter(i => landmarks[i]);\n if (valid.length < 3) return -1;\n\n const xs = valid.map(i => landmarks[i].x * imgW);\n const ys = valid.map(i => landmarks[i].y * imgH);\n const cx = xs.reduce((a, b) => a + b, 0) / xs.length;\n const cy = ys.reduce((a, b) => a + b, 0) / ys.length;\n // Radius = mean distance from centroid to ring points\n const r = Math.max(4, xs.reduce((a, x, i) => a + Math.hypot(x - cx, ys[i] - cy), 0) / xs.length);\n\n const x0 = Math.max(0, Math.floor(cx - r));\n const y0 = Math.max(0, Math.floor(cy - r));\n const bw = Math.min(imgW - x0, Math.ceil(r * 2));\n const bh = Math.min(imgH - y0, Math.ceil(r * 2));\n if (bw < 3 || bh < 3) return -1;\n\n const data = ctx.getImageData(x0, y0, bw, bh).data;\n const lumas: number[] = [];\n for (let row = 0; row < bh; row++) {\n for (let col = 0; col < bw; col++) {\n const dx = x0 + col - cx, dy = y0 + row - cy;\n if (dx * dx + dy * dy > r * r) continue; // outside iris circle\n const i = (row * bw + col) * 4;\n lumas.push(lumaOf(data[i], data[i + 1], data[i + 2]));\n }\n }\n if (lumas.length < 5) return -1;\n const mean = lumas.reduce((a, v) => a + v, 0) / lumas.length;\n return lumas.reduce((a, v) => a + (v - mean) ** 2, 0) / lumas.length;\n}\n\n// ─── Per-eye signal scoring ───────────────────────────────────────────────────\n\n/**\n * Compute all 5 per-eye signals for one eye.\n *\n * @param side 'left' | 'right' for landmark index selection\n * @param skin aggregated skin reference sample\n * @param ctx canvas 2D context (frame drawn, will-read-frequently)\n * @param landmarks full 478-pt array\n * @param imgW / imgH canvas dimensions\n * @param duringFlash suppress specular signal during liveness flash\n */\nfunction computeEyeSignals(\n side: 'left' | 'right',\n skin: RgbSample,\n ctx: CanvasRenderingContext2D,\n landmarks: NormalizedLandmark[],\n imgW: number,\n imgH: number,\n duringFlash: boolean,\n): EyeSignals {\n // MediaPipe eye contour indices\n const isLeft = side === 'left';\n\n // Outer / inner corners\n const outerIdx = isLeft ? 33 : 263;\n const innerIdx = isLeft ? 133 : 362;\n // Upper lid centre\n const upperLidIdx = isLeft ? 159 : 386;\n // Lower lid centre\n const lowerLidIdx = isLeft ? 145 : 374;\n // Brow outer\n const browIdx = isLeft ? 70 : 300;\n // Cheek reference\n const cheekIdx = isLeft ? 116 : 345;\n // Iris ring (requires refined landmarks, 478 pts)\n const irisIdxs = isLeft ? [474, 475, 476, 477] : [469, 470, 471, 472];\n\n const outer = landmarks[outerIdx];\n const inner = landmarks[innerIdx];\n const upperLid = landmarks[upperLidIdx];\n const lowerLid = landmarks[lowerLidIdx];\n if (!outer || !inner || !upperLid || !lowerLid) {\n return { lensOpacity: false, frameEdgeDensity: false, specularClusters: false, chromaStripe: false, irisTextureMismatch: false };\n }\n\n // Eye bounding box in pixels (with generous padding)\n const eyeLeft = Math.min(outer.x, inner.x) * imgW;\n const eyeRight = Math.max(outer.x, inner.x) * imgW;\n const eyeTop = upperLid.y * imgH - 4;\n const eyeBottom = lowerLid.y * imgH + 4;\n const eyeW = eyeRight - eyeLeft;\n const eyeH = Math.max(6, eyeBottom - eyeTop);\n\n // ── Signal 1: Lens Opacity ──────────────────────────────────────────────────\n // Sample a tight box inside the lens zone (between upper & lower lid centroids).\n // The factor 0.38 (was 0.42) avoids catching deep-set eyes or heavy under-eye circles.\n const lensY0 = (upperLid.y * imgH + eyeTop) / 2;\n const lensH = Math.max(6, lowerLid.y * imgH - lensY0);\n const lensSample = sampleRect(ctx, eyeLeft + eyeW * 0.1, lensY0, eyeW * 0.8, lensH, imgW, imgH);\n const lensOpacity = skin.luma > 40 && lensSample.luma < skin.luma * 0.38;\n\n // ── Signal 2: Frame Edge Density ───────────────────────────────────────────\n // Sobel on the strip BETWEEN the brow bottom edge and the upper lid.\n // This zone is where a glasses frame would sit — NOT in the brow hair itself.\n // We push stripTop down 70% of the brow-to-lid distance to avoid brow hairs.\n const brow = landmarks[browIdx];\n const rawStripTop = brow ? brow.y * imgH : eyeTop - 14;\n const lidY = upperLid.y * imgH;\n // Start 70% of the way from brow to lid to stay below brow hairs\n const stripTop = rawStripTop + (lidY - rawStripTop) * 0.70;\n const stripBottom = lidY + 2;\n const stripH = Math.max(4, stripBottom - stripTop);\n const edgeDensity = sobelEdgeDensity(\n ctx,\n eyeLeft - 4, stripTop, eyeW + 8, stripH,\n imgW, imgH,\n 32, // higher threshold — we want frame-weight edges, not fine skin texture\n );\n // Raised from 0.22 → 0.30 so brow-follicle noise doesn't count\n const frameEdgeDensity = edgeDensity > 0.30;\n\n // ── Signal 4: Specular Clusters ─────────────────────────────────────────────\n // Two or more distinct bright blobs → lens glare.\n // Raised luma threshold 215 → 230 (corneal/forehead reflections on bare faces\n // are rarely above 230 unless under very harsh studio lighting).\n // Raised minSepFraction 0.14 → 0.20 to require more spatial separation.\n let specularClusters = false;\n if (!duringFlash) {\n const blobs = countSpecularBlobs(\n ctx,\n eyeLeft - 2, eyeTop - 2, eyeW + 4, eyeH + 4,\n imgW, imgH,\n 230, // raised from 215\n 0.20, // raised from 0.14\n );\n specularClusters = blobs >= 2;\n }\n\n // ── Signal 5: Brow-to-Lid Chroma Stripe ─────────────────────────────────────\n // Sample the zone BETWEEN brow bottom and upper lid — the glasses-frame band.\n // The OLD code sampled AT browY which is in the brow hair, causing false positives\n // from dark eyebrows. Now we sample at 80% of the brow-to-lid distance (just above\n // the lid) and at 40% (mid brow-to-lid gap) and compare both to skin.\n let chromaStripe = false;\n {\n const brow2 = landmarks[browIdx];\n const lidTop = upperLid.y * imgH;\n const browBottom = brow2 ? brow2.y * imgH : lidTop - 14;\n const frameZoneY1 = browBottom + (lidTop - browBottom) * 0.40; // mid gap\n const frameZoneY2 = browBottom + (lidTop - browBottom) * 0.80; // near lid\n const xPositions = [0.15, 0.35, 0.50, 0.65, 0.85].map(f => eyeLeft + eyeW * f);\n\n let stripeHits = 0;\n for (const x of xPositions) {\n const midSample = sampleRect(ctx, x - 2, frameZoneY1 - 3, 5, 6, imgW, imgH);\n const nearSample = sampleRect(ctx, x - 2, frameZoneY2 - 3, 5, 6, imgW, imgH);\n // Raised threshold 0.12 → 0.17 — needs to be clearly non-skin to count\n if (chromaDist(midSample, skin) > 0.17 && chromaDist(nearSample, skin) > 0.17) {\n stripeHits++;\n }\n }\n // Require 4 out of 5 columns to agree (raised from 3)\n chromaStripe = stripeHits >= 4;\n }\n\n // ── Signal 6: Iris Texture Mismatch ─────────────────────────────────────────\n // Real bare iris: variance > 80 (rich texture). Through an opaque lens: drops below ~40.\n // IMPORTANT: was 160, which was far too high. Webcam H.264 compression routinely\n // produces iris variance of 60-120 on a bare eye due to macro-block smoothing.\n // Lowering to 60 means only significantly suppressed texture (thick opaque lens) triggers.\n let irisTextureMismatch = false;\n {\n const openness = (lowerLid.y - upperLid.y) * imgH;\n if (openness > imgH * 0.025) {\n const variance = irisLumaVariance(ctx, landmarks, irisIdxs, imgW, imgH);\n if (variance >= 0 && variance < 60) { // was 160 — far too aggressive\n irisTextureMismatch = true;\n }\n }\n }\n\n return { lensOpacity, frameEdgeDensity, specularClusters, chromaStripe, irisTextureMismatch };\n}\n\n// ─── Signal 3: Bridge ────────────────────────────────────────────────────────\n\ninterface BridgeSignal {\n chromaHigh: boolean; // coloured plastic / frame material\n edgeHigh: boolean; // strong horizontal edge across the bridge\n}\n\nfunction computeBridgeSignal(\n skin: RgbSample,\n ctx: CanvasRenderingContext2D,\n landmarks: NormalizedLandmark[],\n imgW: number,\n imgH: number,\n): BridgeSignal {\n // Landmark 168 is the top of the nose bridge (between the eyes)\n const bridgePt = landmarks[168];\n if (!bridgePt) return { chromaHigh: false, edgeHigh: false };\n\n const bx = bridgePt.x * imgW;\n const by = bridgePt.y * imgH;\n // Wide horizontal strip (24 × 10) centred on the bridge\n const bSample = sampleRect(ctx, bx - 12, by - 5, 24, 10, imgW, imgH);\n const chromaHigh = chromaDist(bSample, skin) > 0.14 || (bSample.luma < skin.luma * 0.38 && skin.luma > 40);\n\n const edgeDensity = sobelEdgeDensity(ctx, bx - 14, by - 7, 28, 14, imgW, imgH, 30);\n const edgeHigh = edgeDensity > 0.20;\n\n return { chromaHigh, edgeHigh };\n}\n\n// ─── GlassesDetector: EMA smoothing + bilateral threshold ────────────────────\n\nconst EMA_ALPHA = 0.35; // responsiveness: higher = faster react but noisier\nconst CONFIRM_FRAMES = 3; // consecutive frames above threshold required\n\ninterface SignalEma {\n lensOpacity: number;\n frameEdgeDensity: number;\n specularClusters: number;\n chromaStripe: number;\n irisTextureMismatch: number;\n bridgeChroma: number;\n bridgeEdge: number;\n}\n\nfunction emptyEma(): SignalEma {\n return { lensOpacity: 0, frameEdgeDensity: 0, specularClusters: 0, chromaStripe: 0, irisTextureMismatch: 0, bridgeChroma: 0, bridgeEdge: 0 };\n}\n\n/**\n * Stateful glasses detector with per-signal EMA temporal smoothing.\n * Create one instance and call `update()` on every frame.\n */\nexport class GlassesDetector {\n private emaLeft: SignalEma = emptyEma();\n private emaRight: SignalEma = emptyEma();\n private emaBridge: Pick<SignalEma, 'bridgeChroma' | 'bridgeEdge'> = { bridgeChroma: 0, bridgeEdge: 0 };\n private consecutivePositive = 0;\n private consecutiveNegative = 0;\n private _detected = false;\n\n reset(): void {\n this.emaLeft = emptyEma();\n this.emaRight = emptyEma();\n this.emaBridge = { bridgeChroma: 0, bridgeEdge: 0 };\n this.consecutivePositive = 0;\n this.consecutiveNegative = 0;\n this._detected = false;\n }\n\n get detected(): boolean { return this._detected; }\n\n /**\n * Feed a new frame into the detector.\n * @returns true if glasses are currently detected (after smoothing).\n */\n update(\n skin: RgbSample,\n ctx: CanvasRenderingContext2D,\n landmarks: NormalizedLandmark[],\n imgW: number,\n imgH: number,\n options: OcclusionCheckOptions = {},\n ): boolean {\n if (skin.luma < 18) return this._detected; // too dark to measure — keep last state\n\n const flash = options.duringLivenessFlash ?? false;\n\n const lSig = computeEyeSignals('left', skin, ctx, landmarks, imgW, imgH, flash);\n const rSig = computeEyeSignals('right', skin, ctx, landmarks, imgW, imgH, flash);\n const bSig = computeBridgeSignal(skin, ctx, landmarks, imgW, imgH);\n\n // EMA update (boolean → 0/1)\n const a = EMA_ALPHA;\n const ema = (prev: number, val: boolean) => prev * (1 - a) + (val ? 1 : 0) * a;\n\n this.emaLeft.lensOpacity = ema(this.emaLeft.lensOpacity, lSig.lensOpacity);\n this.emaLeft.frameEdgeDensity = ema(this.emaLeft.frameEdgeDensity, lSig.frameEdgeDensity);\n this.emaLeft.specularClusters = ema(this.emaLeft.specularClusters, lSig.specularClusters);\n this.emaLeft.chromaStripe = ema(this.emaLeft.chromaStripe, lSig.chromaStripe);\n this.emaLeft.irisTextureMismatch = ema(this.emaLeft.irisTextureMismatch, lSig.irisTextureMismatch);\n\n this.emaRight.lensOpacity = ema(this.emaRight.lensOpacity, rSig.lensOpacity);\n this.emaRight.frameEdgeDensity = ema(this.emaRight.frameEdgeDensity, rSig.frameEdgeDensity);\n this.emaRight.specularClusters = ema(this.emaRight.specularClusters, rSig.specularClusters);\n this.emaRight.chromaStripe = ema(this.emaRight.chromaStripe, rSig.chromaStripe);\n this.emaRight.irisTextureMismatch = ema(this.emaRight.irisTextureMismatch, rSig.irisTextureMismatch);\n\n this.emaBridge.bridgeChroma = ema(this.emaBridge.bridgeChroma, bSig.chromaHigh);\n this.emaBridge.bridgeEdge = ema(this.emaBridge.bridgeEdge, bSig.edgeHigh);\n\n // Score each eye using smoothed values (threshold 0.45 ≈ \"signal active\")\n const T = 0.45;\n const score = (e: SignalEma) =>\n (e.lensOpacity > T ? 1 : 0) +\n (e.frameEdgeDensity > T ? 1 : 0) +\n (e.specularClusters > T ? 1 : 0) +\n (e.chromaStripe > T ? 1 : 0) +\n (e.irisTextureMismatch > T ? 1 : 0);\n\n const leftScore = score(this.emaLeft);\n const rightScore = score(this.emaRight);\n const bridgeScore =\n (this.emaBridge.bridgeChroma > T ? 1 : 0) +\n (this.emaBridge.bridgeEdge > T ? 1 : 0);\n\n // ── Bilateral threshold model ──────────────────────────────────────────────\n // Sunglasses: lens opacity fires on both eyes\n const sunglasses = this.emaLeft.lensOpacity > T && this.emaRight.lensOpacity > T;\n\n // Clear/prescription/thick frames: both eyes show ≥2 signals + total ≥5\n const clearGlasses = leftScore >= 2 && rightScore >= 2 && (leftScore + rightScore) >= 5;\n\n // Rimless/thin frames: both eyes must score ≥2 (raised from 1) + bridge confirms + total ≥6 (raised from 5)\n // This prevents 1-signal noise from each eye combining with a bridge shadow to fire.\n const rimless = leftScore >= 2 && rightScore >= 2 && bridgeScore >= 1 && (leftScore + rightScore + bridgeScore) >= 6;\n\n const isGlasses = sunglasses || clearGlasses || rimless;\n\n if (isGlasses) {\n this.consecutivePositive++;\n this.consecutiveNegative = 0;\n if (this.consecutivePositive >= CONFIRM_FRAMES) this._detected = true;\n } else {\n this.consecutiveNegative++;\n this.consecutivePositive = 0;\n // Require 5 consecutive clean frames before clearing (hysteresis)\n if (this.consecutiveNegative >= 5) this._detected = false;\n }\n\n return this._detected;\n }\n}\n\n// ─── Mask detection (v2: multi-signal + EMA) ─────────────────────────────────\n\n// MediaPipe landmark indices for the lower face\n// Nose tip: 1, Nose bottom: 2, Upper-lip centre: 13, Lower-lip centre: 14\n// Chin: 152, Left mouth corner: 61, Right mouth corner: 291\n// Left lower cheek: 50, Right lower cheek: 280\n// Left jaw: 172, Right jaw: 397\n\ninterface MaskSignals {\n /** Lower-face chroma diverges significantly from forehead skin */\n lowerFaceChromaUniform: boolean;\n /** Lower-face luma is too flat — fabric/mask compresses dynamic range */\n lowerFaceLumaFlat: boolean;\n /** Sobel gradient suppressed on nose/mouth region (smooth mask surface) */\n textureSuppressionNose: boolean;\n /** Lip landmark colour fails to show natural reddish hue vs skin */\n lipColourMismatch: boolean;\n /** Dense edges encircling the lower face boundary (mask edge) */\n lowerFaceEdgeDensity: boolean;\n /** Lower-face luma ratio to forehead is anomalous (mask reflects differently) */\n lumaRatioAnomaly: boolean;\n}\n\n/**\n * Compute all six mask signals from the current frame.\n */\nfunction computeMaskSignals(\n skin: RgbSample,\n ctx: CanvasRenderingContext2D,\n landmarks: NormalizedLandmark[],\n imgW: number,\n imgH: number,\n): MaskSignals {\n // ── Sample key lower-face points ────────────────────────────────────────────\n const forehead = samplePoint(ctx, landmarks, 10, imgW, imgH, 5);\n const noseTip = samplePoint(ctx, landmarks, 4, imgW, imgH, 4); // lm 4 is nose tip proper\n const noseBottom = samplePoint(ctx, landmarks, 2, imgW, imgH, 4);\n const upperLipCentre = samplePoint(ctx, landmarks, 13, imgW, imgH, 4);\n const lowerLipCentre = samplePoint(ctx, landmarks, 14, imgW, imgH, 4);\n const chin = samplePoint(ctx, landmarks, 152, imgW, imgH, 5);\n const leftMouth = samplePoint(ctx, landmarks, 61, imgW, imgH, 4);\n const rightMouth = samplePoint(ctx, landmarks, 291, imgW, imgH, 4);\n const leftLowerCheek = samplePoint(ctx, landmarks, 50, imgW, imgH, 5);\n const rightLowerCheek= samplePoint(ctx, landmarks, 280, imgW, imgH, 5);\n const leftJaw = samplePoint(ctx, landmarks, 172, imgW, imgH, 5);\n const rightJaw = samplePoint(ctx, landmarks, 397, imgW, imgH, 5);\n\n // ── Signal 1: Lower-face chroma uniformity ──────────────────────────────────\n // A mask makes nose, mouth, and chin similar chroma to each other but different\n // from the forehead.\n // FIXED: Point-sample variance across 7 points is inherently near-zero on any\n // uniform skin region. Raised ceiling 220 → 400 to avoid catching normal skin,\n // and tightened chromaDist threshold 0.07 → 0.10 to require stronger divergence.\n const lowerPoints = [noseTip, noseBottom, upperLipCentre, lowerLipCentre, chin, leftLowerCheek, rightLowerCheek];\n const meanLowerChroma = lowerPoints.reduce((s, p) => s + chromaDist(p, forehead), 0) / lowerPoints.length;\n const meanLowerR = lowerPoints.reduce((s, p) => s + p.r, 0) / lowerPoints.length;\n const meanLowerG = lowerPoints.reduce((s, p) => s + p.g, 0) / lowerPoints.length;\n const meanLowerB = lowerPoints.reduce((s, p) => s + p.b, 0) / lowerPoints.length;\n const lowerVariance = lowerPoints.reduce((s, p) =>\n s + (p.r - meanLowerR) ** 2 + (p.g - meanLowerG) ** 2 + (p.b - meanLowerB) ** 2, 0\n ) / lowerPoints.length;\n const lowerFaceChromaUniform = meanLowerChroma > 0.10 && lowerVariance < 400;\n\n // ── Signal 2: Lower-face luma flatness ──────────────────────────────────────\n // A mask compresses natural luminance gradients into a narrow band.\n // FIXED: Tightened lumaStd threshold 14 → 10 so only really flat regions count.\n // Natural lips+nose+chin variation produces std of 12-25 even on smooth skin.\n const lumas = lowerPoints.map(p => p.luma);\n const meanLuma = lumas.reduce((a, v) => a + v, 0) / lumas.length;\n const lumaStd = Math.sqrt(lumas.reduce((a, v) => a + (v - meanLuma) ** 2, 0) / lumas.length);\n const lowerFaceLumaFlat = lumaStd < 10 && Math.abs(meanLuma - skin.luma) > 15;\n\n // ── Signal 3: Texture suppression on the nose/cheek area (Sobel) ────────────\n // Natural skin has pores, creases, fine texture → medium Sobel gradient.\n // FIXED: Webcam H.264 compression significantly reduces high-freq detail, so\n // bare skin on a webcam often reads 0.06-0.12 Sobel density. Lowered to <0.06\n // (was 0.09) to only catch genuinely flat mask-like surfaces.\n const nLm = landmarks[4];\n const cLm = landmarks[50];\n let textureSuppressionNose = false;\n if (nLm && cLm && skin.luma > 35) {\n const rx = Math.min(nLm.x, cLm.x) * imgW - 4;\n const ry = nLm.y * imgH;\n const rw = Math.abs(nLm.x - cLm.x) * imgW + 8;\n const rh = (cLm.y - nLm.y) * imgH + 8;\n const density = sobelEdgeDensity(ctx, rx, ry, rw, rh, imgW, imgH, 20);\n textureSuppressionNose = density < 0.06; // was 0.09\n }\n\n // ── Signal 4: Lip colour mismatch ───────────────────────────────────────────\n // Human lips are measurably more reddish/pink than surrounding skin.\n // FIXED: The +0.04 bar was effectively zero for many skin tones (darker skin,\n // desaturated complexions). This caused it to fire on nearly everyone.\n // Now requires a clear deficit: lipRedness must be BELOW skinRedness (not just\n // barely matching it), indicating the mouth is completely covered.\n // Also exclude very dark skin (skin.luma < 50) where lip/skin ratio converges.\n const lipRedness = (upperLipCentre.r + lowerLipCentre.r) /\n Math.max(1, upperLipCentre.g + upperLipCentre.b + lowerLipCentre.g + lowerLipCentre.b);\n const skinRedness = skin.r / Math.max(1, skin.g + skin.b);\n // Only flag if lips are clearly LESS red than skin (mask covering them)\n const lipColourMismatch = skin.luma > 50 && lipRedness < skinRedness - 0.03;\n\n // ── Signal 5: Dense edge at the lower-face boundary (mask edge) ─────────────\n // A mask strap or mask edge creates a dense horizontal or diagonal edge\n // line running across the cheeks, typically at jaw level.\n // We probe a ~12px tall strip just above the jaw on both sides.\n let lowerFaceEdgeDensity = false;\n {\n const lJaw = landmarks[172];\n const rJaw = landmarks[397];\n if (lJaw && rJaw) {\n const stripY = ((lJaw.y + rJaw.y) / 2) * imgH - 8;\n const stripX = lJaw.x * imgW;\n const stripW = (rJaw.x - lJaw.x) * imgW;\n const stripH = 16;\n const density = sobelEdgeDensity(ctx, stripX, stripY, stripW, stripH, imgW, imgH, 24);\n lowerFaceEdgeDensity = density > 0.28;\n }\n }\n\n // ── Signal 6: Luma ratio anomaly ────────────────────────────────────────────\n // Surgical/cloth masks are often lighter or darker than skin.\n // FIXED: Natural range was 0.72–1.18, which is too tight. The chin is in shadow\n // and forehead may be in direct light, so on a slightly tilted head the ratio\n // can legitimately be 0.60 or 1.25. Widened to 0.50–1.35.\n const lumaRatio = forehead.luma > 10 ? meanLuma / forehead.luma : 1;\n const lumaRatioAnomaly = lumaRatio < 0.50 || lumaRatio > 1.35;\n\n return {\n lowerFaceChromaUniform,\n lowerFaceLumaFlat,\n textureSuppressionNose,\n lipColourMismatch,\n lowerFaceEdgeDensity,\n lumaRatioAnomaly,\n };\n}\n\n/**\n * Stateful face mask detector with per-signal EMA temporal smoothing.\n * Create one instance; call update() every frame.\n */\nexport class MaskDetector {\n private ema = {\n lowerFaceChromaUniform: 0,\n lowerFaceLumaFlat: 0,\n textureSuppressionNose: 0,\n lipColourMismatch: 0,\n lowerFaceEdgeDensity: 0,\n lumaRatioAnomaly: 0,\n };\n private consecutivePositive = 0;\n private consecutiveNegative = 0;\n private _detected = false;\n\n reset(): void {\n for (const k of Object.keys(this.ema) as (keyof typeof this.ema)[]) this.ema[k] = 0;\n this.consecutivePositive = 0;\n this.consecutiveNegative = 0;\n this._detected = false;\n }\n\n get detected(): boolean { return this._detected; }\n\n update(\n skin: RgbSample,\n ctx: CanvasRenderingContext2D,\n landmarks: NormalizedLandmark[],\n imgW: number,\n imgH: number,\n ): boolean {\n if (skin.luma < 18) return this._detected; // too dark to measure\n\n const sig = computeMaskSignals(skin, ctx, landmarks, imgW, imgH);\n const a = EMA_ALPHA;\n const ema = (prev: number, val: boolean) => prev * (1 - a) + (val ? 1 : 0) * a;\n\n this.ema.lowerFaceChromaUniform = ema(this.ema.lowerFaceChromaUniform, sig.lowerFaceChromaUniform);\n this.ema.lowerFaceLumaFlat = ema(this.ema.lowerFaceLumaFlat, sig.lowerFaceLumaFlat);\n this.ema.textureSuppressionNose = ema(this.ema.textureSuppressionNose, sig.textureSuppressionNose);\n this.ema.lipColourMismatch = ema(this.ema.lipColourMismatch, sig.lipColourMismatch);\n this.ema.lowerFaceEdgeDensity = ema(this.ema.lowerFaceEdgeDensity, sig.lowerFaceEdgeDensity);\n this.ema.lumaRatioAnomaly = ema(this.ema.lumaRatioAnomaly, sig.lumaRatioAnomaly);\n\n const T = 0.45;\n const totalScore =\n (this.ema.lowerFaceChromaUniform > T ? 1 : 0) +\n (this.ema.lowerFaceLumaFlat > T ? 1 : 0) +\n (this.ema.textureSuppressionNose > T ? 1 : 0) +\n (this.ema.lipColourMismatch > T ? 1 : 0) +\n (this.ema.lowerFaceEdgeDensity > T ? 1 : 0) +\n (this.ema.lumaRatioAnomaly > T ? 1 : 0);\n\n // Threshold model:\n // ≥3 signals → mask likely (covers white/surgical masks, coloured masks, scarves)\n // Lip mismatch is NO LONGER a special short-circuit trigger — it was causing\n // too many false positives on darker skin tones. Now all signals are equal weight.\n const isMask = totalScore >= 3;\n\n if (isMask) {\n this.consecutivePositive++;\n this.consecutiveNegative = 0;\n if (this.consecutivePositive >= CONFIRM_FRAMES) this._detected = true;\n } else {\n this.consecutiveNegative++;\n this.consecutivePositive = 0;\n if (this.consecutiveNegative >= 5) this._detected = false;\n }\n\n return this._detected;\n }\n}\n\n// ─── Tracker (public, unchanged API) ─────────────────────────────────────────\n\n/**\n * Tracks occlusion across frames with pre-arm debounce and session-violation flag.\n */\nexport class FaceOcclusionTracker {\n private armed = false;\n private blocked = false;\n private obstructionFrames = 0;\n private clearFrames = 0;\n private sessionViolation = false;\n private lastMessage = 'Please remove obstructions from your face.';\n\n private readonly preArmBlockFrames = 4;\n private readonly violationAfterFrames = 1;\n private readonly releaseFrames = 4;\n\n reset(): void {\n this.armed = false;\n this.blocked = false;\n this.obstructionFrames = 0;\n this.clearFrames = 0;\n this.sessionViolation = false;\n this.lastMessage = 'Please remove obstructions from your face.';\n }\n\n arm(): void {\n this.armed = true;\n this.obstructionFrames = 0;\n }\n\n hasSessionViolation(): boolean {\n return this.sessionViolation;\n }\n\n apply(raw: FaceOcclusionResult): FaceOcclusionResult {\n const isObstruction =\n !raw.ok &&\n (raw.message?.toLowerCase().includes('mask') ||\n raw.message?.toLowerCase().includes('glass'));\n\n if (isObstruction) {\n this.obstructionFrames++;\n this.clearFrames = 0;\n if (raw.message) this.lastMessage = raw.message;\n\n const blockThreshold = this.armed ? 1 : this.preArmBlockFrames;\n if (this.obstructionFrames >= blockThreshold) this.blocked = true;\n if (this.armed && this.obstructionFrames >= this.violationAfterFrames) this.sessionViolation = true;\n\n if (this.blocked) return { ok: false, message: this.lastMessage };\n return { ok: true };\n }\n\n this.obstructionFrames = 0;\n\n if (this.blocked) {\n if (!raw.ok) return raw;\n this.clearFrames++;\n if (this.clearFrames >= this.releaseFrames) {\n this.blocked = false;\n this.clearFrames = 0;\n return { ok: true };\n }\n return { ok: false, message: this.lastMessage };\n }\n\n return raw;\n }\n}\n\n// ─── Module-level detector singletons ────────────────────────────────────────\n// Singletons let EMA state accumulate across frames without callers managing\n// instances. Both are reset when landmarks are absent for >10 consecutive calls.\nconst _glassesDetector = new GlassesDetector();\nconst _maskDetector = new MaskDetector();\nlet _noLandmarkFrames = 0;\n\n// ─── Public surface ───────────────────────────────────────────────────────────\n\nexport function checkFaceOcclusionRaw(\n landmarks: NormalizedLandmark[],\n ctx: CanvasRenderingContext2D,\n width: number,\n height: number,\n options: OcclusionCheckOptions = {},\n): FaceOcclusionResult {\n if (!landmarks.length) {\n _noLandmarkFrames++;\n if (_noLandmarkFrames > 10) {\n _glassesDetector.reset();\n _maskDetector.reset();\n }\n return { ok: false, message: 'Face not detected.' };\n }\n _noLandmarkFrames = 0;\n\n // Build skin reference from forehead + both cheeks\n const forehead = samplePoint(ctx, landmarks, 10, width, height, 5);\n const leftCheek = samplePoint(ctx, landmarks, 116, width, height, 5);\n const rightCheek = samplePoint(ctx, landmarks, 345, width, height, 5);\n\n const skin: RgbSample = {\n r: (leftCheek.r + rightCheek.r + forehead.r) / 3,\n g: (leftCheek.g + rightCheek.g + forehead.g) / 3,\n b: (leftCheek.b + rightCheek.b + forehead.b) / 3,\n luma: (leftCheek.luma + rightCheek.luma + forehead.luma) / 3,\n };\n\n // Mask check (new multi-signal MaskDetector with EMA)\n const maskDetected = _maskDetector.update(skin, ctx, landmarks, width, height);\n if (maskDetected) {\n return { ok: false, message: 'Please remove your face mask.' };\n }\n\n // Glasses check (GlassesDetector with EMA)\n const glassesDetected = _glassesDetector.update(skin, ctx, landmarks, width, height, options);\n if (glassesDetected) {\n return { ok: false, message: 'Please remove your glasses.' };\n }\n\n return { ok: true };\n}\n\n/** @deprecated Use tracker + checkFaceOcclusionRaw */\nexport function checkFaceOcclusion(\n landmarks: NormalizedLandmark[],\n ctx: CanvasRenderingContext2D,\n width: number,\n height: number,\n): FaceOcclusionResult {\n return checkFaceOcclusionRaw(landmarks, ctx, width, height);\n}\n","export type FlashColor = 'red' | 'green' | 'blue' | 'none';\n\nexport interface LivenessResult {\n passed: boolean;\n score: number;\n message?: string;\n}\n\nexport class LivenessEngine {\n private videoElement: HTMLVideoElement | null = null;\n private canvas: HTMLCanvasElement;\n private ctx: CanvasRenderingContext2D | null;\n \n private flashOverlay: HTMLElement | null = null;\n \n // Track average intensity of R, G, B channels across frames\n private colorHistory: Array<{\n timestamp: number;\n colorFlashed: FlashColor;\n avgR: number;\n avgG: number;\n avgB: number;\n }> = [];\n\n constructor() {\n this.canvas = document.createElement('canvas');\n this.ctx = this.canvas.getContext('2d', { willReadFrequently: true });\n }\n\n public setVideoElement(video: HTMLVideoElement) {\n this.videoElement = video;\n }\n\n public setFlashOverlay(overlay: HTMLElement) {\n this.flashOverlay = overlay;\n }\n\n /**\n * Run the active light reflection sequence\n * Flashes colors and measures the face bounding box reflection\n */\n public async runLivenessSequence(\n boundingBox: { x: number, y: number, width: number, height: number },\n assertFaceClear?: () => { aligned: boolean; message?: string },\n ): Promise<LivenessResult> {\n if (!this.videoElement || !this.flashOverlay || !this.ctx) {\n return { passed: false, score: 0, message: \"Engine not fully initialized\" };\n }\n\n this.colorHistory = [];\n const sequence: FlashColor[] = ['red', 'green', 'blue', 'none'];\n // Shuffle slightly for randomness to prevent replay attacks\n sequence.sort(() => Math.random() - 0.5);\n \n // Ensure we start and end with 'none'\n const fullSequence: FlashColor[] = ['none', ...sequence, 'none'];\n \n // Set canvas size to video size\n this.canvas.width = this.videoElement.videoWidth;\n this.canvas.height = this.videoElement.videoHeight;\n\n try {\n for (const color of fullSequence) {\n if (assertFaceClear) {\n const status = assertFaceClear();\n if (!status.aligned) {\n return { passed: false, score: 0, message: status.message ?? 'Face obstruction detected' };\n }\n }\n await this.flashAndMeasure(color, boundingBox);\n }\n \n return this.analyzeResults();\n } finally {\n // Ensure overlay is cleared\n if (this.flashOverlay) {\n this.flashOverlay.style.backgroundColor = 'transparent';\n }\n }\n }\n\n private async flashAndMeasure(\n color: FlashColor, \n box: { x: number, y: number, width: number, height: number }\n ): Promise<void> {\n // 1. Set screen color overlay\n if (this.flashOverlay) {\n switch (color) {\n case 'red': this.flashOverlay.style.backgroundColor = 'rgba(255, 0, 0, 0.6)'; break;\n case 'green': this.flashOverlay.style.backgroundColor = 'rgba(0, 255, 0, 0.6)'; break;\n case 'blue': this.flashOverlay.style.backgroundColor = 'rgba(0, 0, 255, 0.6)'; break;\n case 'none': this.flashOverlay.style.backgroundColor = 'transparent'; break;\n }\n }\n\n // 2. Wait for screen to update and camera to capture the reflection (exposure delay)\n await new Promise(resolve => setTimeout(resolve, 400));\n\n // 3. Capture frame\n if (this.videoElement && this.ctx) {\n this.ctx.drawImage(this.videoElement, 0, 0, this.canvas.width, this.canvas.height);\n \n // Ensure box is within bounds\n const x = Math.max(0, Math.floor(box.x));\n const y = Math.max(0, Math.floor(box.y));\n const w = Math.min(this.canvas.width - x, Math.floor(box.width));\n const h = Math.min(this.canvas.height - y, Math.floor(box.height));\n\n // 4. Measure intensity of the face area\n const imageData = this.ctx.getImageData(x, y, w, h);\n const data = imageData.data;\n \n let totalR = 0, totalG = 0, totalB = 0;\n const pixelCount = w * h;\n\n for (let i = 0; i < data.length; i += 4) {\n totalR += data[i]; // Red\n totalG += data[i + 1]; // Green\n totalB += data[i + 2]; // Blue\n }\n\n this.colorHistory.push({\n timestamp: Date.now(),\n colorFlashed: color,\n avgR: totalR / pixelCount,\n avgG: totalG / pixelCount,\n avgB: totalB / pixelCount,\n });\n }\n }\n\n private analyzeResults(): LivenessResult {\n // Find the baseline (when 'none' was flashed)\n const baselines = this.colorHistory.filter(h => h.colorFlashed === 'none');\n if (baselines.length === 0) return { passed: false, score: 0 };\n \n const baseR = baselines.reduce((acc, b) => acc + b.avgR, 0) / baselines.length;\n const baseG = baselines.reduce((acc, b) => acc + b.avgG, 0) / baselines.length;\n const baseB = baselines.reduce((acc, b) => acc + b.avgB, 0) / baselines.length;\n\n let score = 0;\n let expectedSpikes = 0;\n\n // Check if the expected color channel spiked relative to baseline\n for (const record of this.colorHistory) {\n if (record.colorFlashed === 'none') continue;\n expectedSpikes++;\n\n const rDiff = record.avgR - baseR;\n const gDiff = record.avgG - baseG;\n const bDiff = record.avgB - baseB;\n\n // A simple heuristic: The flashed color channel should increase more than the others\n // Note: We check that the primary difference is positive to avoid false positives from Auto-White-Balance.\n if (record.colorFlashed === 'red' && rDiff > 0 && rDiff > Math.max(gDiff, bDiff)) score++;\n if (record.colorFlashed === 'green' && gDiff > 0 && gDiff > Math.max(rDiff, bDiff)) score++;\n if (record.colorFlashed === 'blue' && bDiff > 0 && bDiff > Math.max(rDiff, gDiff)) score++;\n }\n\n // Pass if we correctly detected the reflection for at least ONE flash (more forgiving for different webcams)\n const passed = expectedSpikes > 0 && score >= 1;\n \n return {\n passed,\n score: (score / expectedSpikes) * 100,\n message: passed ? \"Liveness verified via 3D light reflection\" : \"Liveness check failed. Ensure adequate lighting, turn up screen brightness, and do not use a photo.\"\n };\n }\n}\n","/**\n * Capture quality checks for face verification:\n * - Lighting (luminance) so we have enough face data\n * - Face size so the face has enough resolution\n */\n\nexport const CAPTURE_QUALITY = {\n /** Min average luminance in face region (0-255). Below = too dark */\n LUMINANCE_MIN: 80,\n /** Max average luminance. Above = overexposed / washed out */\n LUMINANCE_MAX: 220,\n /** Min face bounding box width/height in pixels */\n FACE_MIN_SIZE: 100,\n /** Ideal min size for best results */\n FACE_IDEAL_SIZE: 140,\n} as const;\n\nexport type FaceBox = {\n x: number;\n y: number;\n width: number;\n height: number;\n};\n\n/**\n * Get face bounding box from Human.js face result (handles multiple formats).\n */\nexport function getFaceBox(face: { box?: unknown }): FaceBox | null {\n const box = face.box as Record<string, number> | number[] | undefined;\n if (!box) return null;\n\n if (Array.isArray(box) && box.length >= 4) {\n return { x: box[0], y: box[1], width: box[2], height: box[3] };\n }\n if (typeof box === 'object') {\n const obj = box as Record<string, number | undefined>;\n if (obj.width != null && obj.x != null) {\n return {\n x: Number(obj.x),\n y: Number(obj.y ?? 0),\n width: Number(obj.width),\n height: Number(obj.height ?? obj.width),\n };\n }\n if (obj.left != null && obj.right != null) {\n return {\n x: Number(obj.left),\n y: Number(obj.top ?? 0),\n width: Number(obj.right - obj.left),\n height: Number((obj.bottom ?? 0) - (obj.top ?? 0)),\n };\n }\n }\n return null;\n}\n\n/**\n * Compute average luminance (0-255) in a region of the canvas.\n * Uses luminance formula: 0.299*R + 0.587*G + 0.114*B.\n * Samples every 4th pixel for speed.\n */\nexport function getRegionLuminance(\n ctx: CanvasRenderingContext2D,\n x: number,\n y: number,\n width: number,\n height: number\n): number {\n const w = Math.max(1, Math.floor(width));\n const h = Math.max(1, Math.floor(height));\n const sx = Math.max(0, Math.floor(x));\n const sy = Math.max(0, Math.floor(y));\n\n let sum = 0;\n let count = 0;\n const step = 4;\n\n try {\n const imageData = ctx.getImageData(sx, sy, w, h);\n const data = imageData.data;\n\n for (let i = 0; i < data.length; i += step * 4) {\n const r = data[i];\n const g = data[i + 1];\n const b = data[i + 2];\n sum += 0.299 * r + 0.587 * g + 0.114 * b;\n count += 1;\n }\n } catch {\n return 0;\n }\n\n return count > 0 ? sum / count : 0;\n}\n\n/**\n * Get luminance in the face region. Canvas must already have the current video frame drawn.\n * Face box can be in pixel or normalized (0-1) coordinates; pass canvas width/height to scale.\n */\nexport function getFaceLuminance(\n ctx: CanvasRenderingContext2D,\n face: { box?: unknown },\n canvasWidth: number,\n canvasHeight: number\n): number {\n const box = getFaceBox(face);\n if (!box) {\n return getRegionLuminance(ctx, 0, 0, canvasWidth, canvasHeight);\n }\n\n let x = box.x;\n let y = box.y;\n let w = box.width;\n let h = box.height;\n\n if (w <= 1 && h <= 1) {\n x *= canvasWidth;\n y *= canvasHeight;\n w *= canvasWidth;\n h *= canvasHeight;\n }\n\n x = Math.max(0, Math.min(x, canvasWidth - 1));\n y = Math.max(0, Math.min(y, canvasHeight - 1));\n w = Math.max(1, Math.min(w, canvasWidth - x));\n h = Math.max(1, Math.min(h, canvasHeight - y));\n\n return getRegionLuminance(ctx, x, y, w, h);\n}\n\nexport interface CaptureQualityResult {\n luminance: number;\n luminanceOk: boolean;\n faceWidth: number;\n faceHeight: number;\n faceSizeOk: boolean;\n /** True if lighting and face size are both OK */\n ready: boolean;\n message: string;\n}\n\n/**\n * Evaluate capture quality from luminance and face box size.\n */\nexport function evaluateCaptureQuality(\n luminance: number,\n faceWidth: number,\n faceHeight: number\n): CaptureQualityResult {\n const luminanceOk =\n luminance >= CAPTURE_QUALITY.LUMINANCE_MIN &&\n luminance <= CAPTURE_QUALITY.LUMINANCE_MAX;\n const faceSizeOk =\n faceWidth >= CAPTURE_QUALITY.FACE_MIN_SIZE &&\n faceHeight >= CAPTURE_QUALITY.FACE_MIN_SIZE;\n\n const messages: string[] = [];\n if (!luminanceOk) {\n if (luminance < CAPTURE_QUALITY.LUMINANCE_MIN) {\n messages.push('Low light – move to a brighter area');\n } else {\n messages.push('Too bright – reduce glare or move away from light');\n }\n }\n if (!faceSizeOk) {\n messages.push('Face too small – move closer to the camera');\n }\n if (luminanceOk && faceSizeOk) {\n messages.push('Good – enough light and face data');\n }\n\n return {\n luminance: Math.round(luminance),\n luminanceOk,\n faceWidth: Math.round(faceWidth),\n faceHeight: Math.round(faceHeight),\n faceSizeOk,\n ready: luminanceOk && faceSizeOk,\n message: messages.join('. '),\n };\n}\n","// Maxed-out Human.js configuration for strongest face detection and embedding\n// (rotation, anti-spoof, higher res). Mesh/description use local models from public/models/\n\nexport const HUMAN_CONFIG = {\n modelBasePath: '/models/',\n backend: 'webgpu' as const, // WebGPU is fastest, falls back to webgl/wasm\n async: true,\n \n cacheSensitivity: 0, // Disable caching so embeddings are always fresh\n skipFrame: false,\n warmup: 'none' as const,\n videoOptimized: true,\n deallocate: true,\n\n face: {\n enabled: true,\n detector: {\n enabled: true,\n rotation: true, // Max accuracy: detect faces at angles for better embedding alignment\n return: true,\n minConfidence: 0.2,\n maxFaces: 1,\n modelPath: 'blazeface.json',\n },\n mesh: {\n enabled: true, // Must be true for emotion/description models to work\n return: false, // Keep false for performance (we don't need the 468 points back)\n },\n landmarks: {\n enabled: true,\n return: true,\n },\n emotion: {\n enabled: true,\n return: true,\n modelPath: 'emotion.json',\n minConfidence: 0.2,\n },\n description: {\n enabled: true,\n return: true,\n modelPath: 'faceres.json', // Use FaceRes (Deep) by replacing faceres.bin with human-models 13.9M variant for max embedding quality\n },\n iris: { enabled: false },\n antispoof: { enabled: true }, // Max security: reject photos/screen replay\n liveness: { enabled: false }, // Enable when liveness.json + liveness.bin are in public/models\n },\n \n // Disable unused features\n filter: { \n enabled: false, // Disable all filters for maximum performance\n },\n \n body: { enabled: false },\n hand: { enabled: false },\n object: { enabled: false },\n \n gesture: { \n enabled: false,\n return: true,\n minConfidence: 0.2,\n },\n \n debug: false,\n profile: false, // Disable profiling in production\n};\n\nexport const VERIFICATION_CONSTANTS = {\n HAPPY_SUSTAIN_DURATION: 1500,\n BLINK_REQUIRED_COUNT: 3,\n BLINK_COOLDOWN: 300,\n \n // Performance constants\n PROCESS_INTERVAL: 200, // Process every 200ms (5 frames per second is plenty for median averaging)\n FPS_UPDATE_INTERVAL: 1000,\n DEBUG_LOG_INTERVAL: 60,\n \n // Resolution: Lowering this provides massive speed boosts without losing embedding quality\n PROCESS_WIDTH: 640,\n PROCESS_HEIGHT: 480,\n \n // Frame skipping\n SKIP_FRAMES: 2, // Process every 3rd frame\n};\n\n// Backend priority (best to worst performance)\nexport const BACKEND_PRIORITY = ['webgpu', 'webgl', 'wasm'] as const;","\nexport type ChainType = 'solana' | 'evm';\n\nexport interface VerificationPayload {\n simhashFull: string;\n livenessCombined: number;\n walletAddress: string;\n chain: ChainType;\n}\n\nexport interface RelayerConfig {\n baseUrl: string;\n network?: 'mainnet' | 'testnet';\n /**\n * The application ID assigned to your project.\n * Required for production usage to bypass origin restrictions.\n */\n appId?: string;\n}\n\nexport interface RelayerResponse {\n success: boolean;\n txHash?: string;\n data?: any;\n}\n\nexport class VerifiedRelayerClient {\n private baseUrl: string;\n private network: string;\n private appId?: string;\n\n constructor(config: RelayerConfig) {\n this.baseUrl = config.baseUrl;\n this.network = config.network || 'mainnet';\n this.appId = config.appId;\n }\n\n /**\n * Submits the face verification payload to the backend relayer.\n * The backend handles gas abstraction and execution for both EVM and Solana users.\n */\n public async submitVerification(payload: VerificationPayload): Promise<RelayerResponse> {\n const { simhashFull, livenessCombined, chain, walletAddress } = payload;\n\n const response = await fetch(`${this.baseUrl}/api/arcium/relayer-verify`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n simhashHex: simhashFull,\n livenessCombined,\n walletAddress,\n chain,\n appId: this.appId\n }),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Verification API failed: ${errorText}`);\n }\n\n const data = await response.json();\n return { success: true, txHash: data.txHash || data.data?.arciumResult?.tx3, data: data.data };\n }\n}\n","import { useState, useEffect } from 'react';\nimport { FaceLandmarker, FilesetResolver } from '@mediapipe/tasks-vision';\nimport Human from '@vladmandic/human';\nimport { HUMAN_CONFIG } from '../../core/config/humanConfig';\n\nexport interface VisionModels {\n faceLandmarker: FaceLandmarker | null;\n human: Human | null;\n isInitialized: boolean;\n error: string | null;\n}\n\nexport const useVisionModels = (): VisionModels => {\n const [faceLandmarker, setFaceLandmarker] = useState<FaceLandmarker | null>(null);\n const [human, setHuman] = useState<Human | null>(null);\n const [isInitialized, setIsInitialized] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n let isMounted = true;\n\n const initializeModels = async () => {\n try {\n console.log(\"Initializing Vision Models (MediaPipe + ONNX)...\");\n\n // 1. Initialize MediaPipe FaceLandmarker\n const vision = await FilesetResolver.forVisionTasks(\n \"https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision@0.10.0/wasm\"\n );\n \n const landmarker = await FaceLandmarker.createFromOptions(vision, {\n baseOptions: {\n modelAssetPath: \"https://storage.googleapis.com/mediapipe-models/face_landmarker/face_landmarker/float16/1/face_landmarker.task\",\n },\n outputFaceBlendshapes: true,\n outputFacialTransformationMatrixes: true,\n runningMode: \"VIDEO\",\n numFaces: 1\n });\n\n // 2. Initialize Human.js for Face Embeddings (Production Fix)\n // Uses the faceres.bin model in public/models\n let h = null;\n try {\n const config = {\n ...HUMAN_CONFIG,\n backend: 'wasm' as const, // Force WASM to avoid WebGL conflicts with MediaPipe\n face: {\n ...HUMAN_CONFIG.face,\n description: { enabled: true, modelPath: 'faceres.json' },\n mesh: { enabled: false }, // MediaPipe handles mesh\n emotion: { enabled: false },\n antispoof: { enabled: false },\n detector: { enabled: true, modelPath: 'blazeface.json' }\n }\n };\n h = new Human(config);\n await h.load();\n await h.warmup();\n } catch (humanErr) {\n console.warn(\"Human.js models failed to load.\", humanErr);\n }\n\n if (isMounted) {\n setFaceLandmarker(landmarker);\n setHuman(h);\n setIsInitialized(true);\n }\n } catch (err: any) {\n console.error(\"Failed to initialize vision models\", err);\n if (isMounted) {\n setError(err.message || \"Failed to load face detection models\");\n }\n }\n };\n\n initializeModels();\n\n return () => {\n isMounted = false;\n // Cleanup happens automatically or could be added here\n };\n }, []);\n\n return { faceLandmarker, human, isInitialized, error };\n};\n","// Hook for managing camera stream\nimport { useState, useCallback, useEffect } from 'react';\n\nexport function useCameraStream(isReady: boolean) {\n const [stream, setStream] = useState<MediaStream | null>(null);\n const [error, setError] = useState<string | null>(null);\n\n const startCamera = useCallback(async () => {\n try {\n setError(null);\n \n const devices = await navigator.mediaDevices.enumerateDevices();\n const videoDevices = devices.filter(d => d.kind === 'videoinput');\n \n const frontCamera = videoDevices.find(d => \n d.label.toLowerCase().includes('front') ||\n d.label.toLowerCase().includes('user') ||\n d.label.toLowerCase().includes('facetime')\n );\n \n // Check if mobile device\n const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);\n \n const mediaStream = await navigator.mediaDevices.getUserMedia({\n video: {\n width: isMobile ? { ideal: 640, min: 320 } : { ideal: 1920, min: 1280 },\n height: isMobile ? { ideal: 480, min: 240 } : { ideal: 1080, min: 720 },\n facingMode: 'user',\n frameRate: isMobile ? { ideal: 30, min: 15 } : { ideal: 60, min: 30 },\n aspectRatio: isMobile ? { ideal: 4/3 } : { ideal: 16/9 },\n deviceId: frontCamera?.deviceId ? { exact: frontCamera.deviceId } : undefined,\n },\n });\n \n setStream(mediaStream);\n console.log('Camera started successfully');\n \n } catch (err) {\n console.error('Camera error:', err);\n setError('Failed to access camera. Please check permissions.');\n }\n }, []);\n\n useEffect(() => {\n if (isReady && !stream) {\n startCamera();\n }\n }, [isReady, stream, startCamera]);\n\n useEffect(() => {\n return () => {\n if (stream) {\n stream.getTracks().forEach(track => track.stop());\n }\n };\n }, [stream]);\n\n return { stream, error, startCamera };\n}","import React, { useRef, useEffect, useState, useCallback } from \"react\";\n\nimport { \n generateBiometricSimHash,\n averageEmbeddings,\n RawFacialData,\n LivenessData\n} from '../../core/biometrics/biometricUtils';\nimport { evaluateCaptureQuality, getRegionLuminance } from '../../core/biometrics/captureQuality';\nimport { useVisionModels } from '../hooks/useVisionModels';\nimport { useCameraStream } from '../hooks/useCameraStream';\nimport { LivenessEngine, FlashColor, LivenessResult } from '../../core/biometrics/LivenessEngine';\n// Removed onnxruntime-web\nimport { FaceLandmarkerResult } from '@mediapipe/tasks-vision';\nimport type { FaceZKProps } from './types';\n\n// Steps for the new pipeline\ntype ExtendedStep = 'pose-align' | 'pose-left' | 'pose-right' | 'pose-center' | 'capturing' | 'light-flash' | 'processing' | 'completed';\n\nconst FaceZKInner: React.FC<FaceZKProps> = ({\n onBiometricData,\n onVerificationComplete,\n}) => {\n // Refs\n const videoRef = useRef<HTMLVideoElement>(null);\n const canvasRef = useRef<HTMLCanvasElement>(null);\n const flashOverlayRef = useRef<HTMLDivElement>(null);\n const animationIdRef = useRef<number>();\n \n // Engines\n const { faceLandmarker, human, isInitialized, error: initError } = useVisionModels();\n const { stream, error: cameraError } = useCameraStream(true); // Start camera immediately\n const [livenessEngine] = useState(() => new LivenessEngine());\n \n // UI state\n const [currentStep, setCurrentStep] = useState<ExtendedStep>('pose-align');\n const [liveFeedback, setLiveFeedback] = useState<{message: string, isGood: boolean} | null>(null);\n const [isProcessing, setIsProcessing] = useState(false);\n const [faceDetected, setFaceDetected] = useState(false);\n const [error, setError] = useState<string | null>(null);\n \n // Progress state\n const [poseCheckPassed, setPoseCheckPassed] = useState(false);\n const [livenessPassed, setLivenessPassed] = useState(false);\n\n useEffect(() => {\n setError(initError || cameraError);\n }, [initError, cameraError]);\n\n useEffect(() => {\n if (!stream || !videoRef.current) return;\n videoRef.current.srcObject = stream;\n \n const initEngine = () => {\n videoRef.current?.play().catch(e => console.warn(\"Auto-play prevented\", e));\n if (videoRef.current && flashOverlayRef.current) {\n console.log(\"Initializing Liveness Engine with video elements\");\n livenessEngine.setVideoElement(videoRef.current);\n livenessEngine.setFlashOverlay(flashOverlayRef.current);\n }\n };\n\n if (videoRef.current.readyState >= 1) {\n initEngine();\n } else {\n videoRef.current.onloadedmetadata = initEngine;\n }\n }, [stream, livenessEngine]);\n\n const extractFaceEmbedding = async (video: HTMLVideoElement): Promise<number[]> => {\n if (!human) {\n // Hard fail — a dummy embedding would silently corrupt the entire pipeline.\n // The UI should never reach this point if isInitialized is properly gated.\n throw new Error('Face recognition model not loaded. Please wait and retry.');\n }\n \n try {\n // Run the detection on the full video frame so Human.js can properly align and crop the face internally\n const result = await human.detect(video);\n if (result && result.face && result.face.length > 0 && result.face[0].embedding) {\n return Array.from(result.face[0].embedding);\n }\n throw new Error(\"No face embedding extracted from frame\");\n } catch (e) {\n console.error(\"Human.js Inference failed\", e);\n throw e;\n }\n };\n\n // Cosine similarity between two vectors\n const cosineSimilarity = (a: number[], b: number[]): number => {\n let dot = 0, normA = 0, normB = 0;\n for (let i = 0; i < a.length; i++) {\n dot += a[i] * b[i];\n normA += a[i] * a[i];\n normB += b[i] * b[i];\n }\n return dot / (Math.sqrt(normA) * Math.sqrt(normB));\n };\n\n // Multi-frame embedding capture: samples N embeddings, then uses the robust\n // averageEmbeddings() function (median-based outlier rejection) from biometricUtils.\n const captureMultipleEmbeddings = async (\n video: HTMLVideoElement,\n sampleCount: number = 10,\n intervalMs: number = 200\n ): Promise<number[]> => {\n const embeddings: number[][] = [];\n console.log(`📸 Starting multi-frame capture: ${sampleCount} samples, ${intervalMs}ms apart`);\n \n for (let i = 0; i < sampleCount; i++) {\n try {\n const emb = await extractFaceEmbedding(video);\n embeddings.push(emb);\n const norm = Math.sqrt(emb.reduce((s, v) => s + v * v, 0));\n console.log(` Frame ${i + 1}/${sampleCount}: L2 norm = ${norm.toFixed(4)}`);\n \n if (embeddings.length > 1) {\n const prev = embeddings[embeddings.length - 2];\n const sim = cosineSimilarity(prev, emb);\n console.log(` Cosine similarity (frame ${i} vs ${i + 1}): ${sim.toFixed(6)}`);\n }\n \n setLiveFeedback({ message: `Capturing biometric data... (${i + 1}/${sampleCount})`, isGood: true });\n } catch (e) {\n console.warn(` Frame ${i + 1} capture failed, skipping:`, e);\n }\n \n if (i < sampleCount - 1) {\n await new Promise(r => setTimeout(r, intervalMs));\n }\n }\n \n if (embeddings.length < 3) {\n throw new Error(`Only captured ${embeddings.length} valid frames. Need at least 3.`);\n }\n \n // Use the robust median-based averageEmbeddings (discards 30% outlier frames)\n const averaged = averageEmbeddings(embeddings);\n \n const avgNorm = Math.sqrt(averaged.reduce((s: number, v: number) => s + v * v, 0));\n console.log(`✅ Robust average complete. L2 norm = ${avgNorm.toFixed(4)}`);\n \n return averaged;\n };\n\n // Core engine loops\n const latestLandmarks = useRef<any>(null);\n const latestMatrix = useRef<any>(null);\n\n // 1. Independent Video & Detection Loop\n const renderLoop = useCallback(() => {\n if (!videoRef.current || !faceLandmarker || !isInitialized) return;\n\n if (videoRef.current.videoWidth === 0 || videoRef.current.videoHeight === 0) {\n if (currentStep !== 'completed') {\n animationIdRef.current = requestAnimationFrame(renderLoop);\n }\n return;\n }\n\n try {\n const startTimeMs = performance.now();\n // Ensure strictly increasing timestamps for MediaPipe\n if (startTimeMs > (renderLoop as any).lastTime) {\n const results = faceLandmarker.detectForVideo(videoRef.current, startTimeMs);\n (renderLoop as any).lastTime = startTimeMs;\n \n const facePresent = results.faceLandmarks && results.faceLandmarks.length > 0;\n setFaceDetected(prev => prev !== facePresent ? facePresent : prev);\n\n if (facePresent) {\n latestLandmarks.current = results.faceLandmarks[0];\n if (results.facialTransformationMatrixes && results.facialTransformationMatrixes.length > 0) {\n latestMatrix.current = results.facialTransformationMatrixes[0].data;\n }\n \n if (canvasRef.current) {\n const canvas = canvasRef.current;\n const ctx = canvas.getContext('2d');\n if (ctx) {\n canvas.width = videoRef.current.videoWidth;\n canvas.height = videoRef.current.videoHeight;\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n \n // Draw a simple bounding box or mesh points\n ctx.fillStyle = '#00FF88';\n for (const point of latestLandmarks.current) {\n ctx.fillRect(point.x * canvas.width, point.y * canvas.height, 2, 2);\n }\n }\n }\n } else {\n latestLandmarks.current = null;\n latestMatrix.current = null;\n }\n }\n } catch (e) {\n console.error(\"Detection error:\", e);\n }\n \n // Continue loop unless completed\n if (currentStep !== 'completed') {\n animationIdRef.current = requestAnimationFrame(renderLoop);\n }\n }, [faceLandmarker, isInitialized, currentStep]);\n\n (renderLoop as any).lastTime = 0;\n\n useEffect(() => {\n if (isInitialized && stream) {\n renderLoop();\n }\n return () => {\n if (animationIdRef.current) cancelAnimationFrame(animationIdRef.current);\n };\n }, [isInitialized, stream, renderLoop]);\n\n // 2. Independent Verification Sequence\n useEffect(() => {\n const runVerification = async () => {\n if (!faceDetected || isProcessing || !latestLandmarks.current) return;\n \n setIsProcessing(true);\n setError(null);\n\n const getFaceBoundingBox = () => {\n if (!latestLandmarks.current || !videoRef.current) return null;\n const video = videoRef.current;\n const xs = latestLandmarks.current.map((l: any) => l.x * video.videoWidth);\n const ys = latestLandmarks.current.map((l: any) => l.y * video.videoHeight);\n return {\n x: Math.min(...xs), y: Math.min(...ys),\n width: Math.max(...xs) - Math.min(...xs), height: Math.max(...ys) - Math.min(...ys)\n };\n };\n\n const checkFaceAlignment = () => {\n const bbox = getFaceBoundingBox();\n const video = videoRef.current;\n if (!bbox || !video || !latestLandmarks.current) return { aligned: false, message: \"Face not detected.\" };\n \n // Use height for primary distance check since width shrinks when turning head\n const faceHeightRatio = bbox.height / video.videoHeight;\n if (faceHeightRatio < 0.30) return { aligned: false, message: \"Face is too far away. Move closer.\" };\n if (faceHeightRatio > 0.90) return { aligned: false, message: \"Face is too close. Move back.\" };\n\n const faceWidthRatio = bbox.width / video.videoWidth;\n if (faceWidthRatio < 0.20) return { aligned: false, message: \"Face is too far away. Move closer.\" };\n\n const centerX = bbox.x + bbox.width / 2;\n const centerY = bbox.y + bbox.height / 2;\n const xOffset = Math.abs(centerX - video.videoWidth / 2) / video.videoWidth;\n const yOffset = Math.abs(centerY - video.videoHeight / 2) / video.videoHeight;\n \n // Relaxed centering to allow for head turning\n if (xOffset > 0.25 || yOffset > 0.25) return { aligned: false, message: \"Align your face in the center of the frame.\" };\n \n // --- OCCLUSION DETECTION (Sunglasses & Face Masks) ---\n // Sample pixels using the hidden canvas context (which is constantly being drawn to in renderLoop)\n // Wait, renderLoop clears the canvas and draws dots. We need to draw the video first to sample colors!\n // We will create a small temporary offscreen canvas for fast sampling.\n try {\n const offscreenCanvas = document.createElement('canvas');\n offscreenCanvas.width = video.videoWidth;\n offscreenCanvas.height = video.videoHeight;\n const ctx = offscreenCanvas.getContext('2d', { willReadFrequently: true });\n if (ctx) {\n ctx.drawImage(video, 0, 0, offscreenCanvas.width, offscreenCanvas.height);\n \n const getRGB = (index: number) => {\n const pt = latestLandmarks.current[index];\n if (!pt) return { r: 0, g: 0, b: 0, luma: 0 };\n const x = Math.max(0, Math.min(offscreenCanvas.width - 1, Math.floor(pt.x * offscreenCanvas.width)));\n const y = Math.max(0, Math.min(offscreenCanvas.height - 1, Math.floor(pt.y * offscreenCanvas.height)));\n const startX = Math.max(0, x - 2);\n const startY = Math.max(0, y - 2);\n const imgData = ctx.getImageData(startX, startY, 5, 5).data;\n let r = 0, g = 0, b = 0;\n for (let i = 0; i < imgData.length; i += 4) {\n r += imgData[i]; g += imgData[i+1]; b += imgData[i+2];\n }\n const count = imgData.length / 4;\n return { \n r: r/count, g: g/count, b: b/count, \n luma: 0.299*(r/count) + 0.587*(g/count) + 0.114*(b/count) \n };\n };\n\n // Use cheeks as a more reliable lighting and skin-tone reference than the forehead (which gets glare)\n const leftCheek = getRGB(50);\n const rightCheek = getRGB(280);\n const forehead = getRGB(151);\n \n // Sample slightly below the eye to hit the glasses lens rather than dark eyelashes\n const leftEye = getRGB(145); \n const rightEye = getRGB(374);\n const noseTip = getRGB(1);\n const chin = getRGB(152);\n\n const avgSkinLuma = (leftCheek.luma + rightCheek.luma + forehead.luma) / 3;\n\n // 1. Dark Shades Detection\n // We require the absolute brightness to be incredibly low (pitch black shades)\n // Clear glasses will have a high luma because they let light through.\n if (leftEye.luma < 25 && rightEye.luma < 25 && avgSkinLuma > 50) {\n if (leftEye.luma < avgSkinLuma * 0.3 && rightEye.luma < avgSkinLuma * 0.3) {\n return { aligned: false, message: \"Please remove your dark shades.\" };\n }\n }\n\n // 2. Face Mask Detection\n // Use a much more forgiving threshold. Euclidean distance over 140 means a massive color clash \n // (e.g. a blue or black mask against pale skin). Beards or natural shadows rarely exceed 100.\n const colorDist = (c1: any, c2: any) => Math.sqrt(Math.pow(c1.r - c2.r, 2) + Math.pow(c1.g - c2.g, 2) + Math.pow(c1.b - c2.b, 2));\n const avgCheek = { r: (leftCheek.r + rightCheek.r)/2, g: (leftCheek.g + rightCheek.g)/2, b: (leftCheek.b + rightCheek.b)/2 };\n \n if (colorDist(avgCheek, noseTip) > 130 && colorDist(avgCheek, chin) > 130) {\n return { aligned: false, message: \"Please remove your face mask.\" };\n }\n }\n } catch (e) {\n console.warn(\"Occlusion detection skipped due to canvas error\", e);\n }\n\n return { aligned: true, message: \"Perfect! Hold still.\" };\n };\n\n const waitForAlignment = async () => {\n let consecutiveGood = 0;\n while (true) {\n const status = checkFaceAlignment();\n if (status.aligned) {\n setLiveFeedback(prev => prev?.message === status.message && prev?.isGood === true ? prev : { message: status.message, isGood: true });\n consecutiveGood++;\n if (consecutiveGood > 10) {\n setLiveFeedback(null);\n return true; // Hold for ~500ms\n }\n } else {\n setLiveFeedback(prev => prev?.message === status.message && prev?.isGood === false ? prev : { message: status.message, isGood: false });\n consecutiveGood = 0;\n }\n await new Promise(r => setTimeout(r, 50));\n }\n };\n\n // Gate on capture quality (lighting + face size) before pose checks.\n // Uses the same evaluateCaptureQuality function as SimHashTest.\n const waitForQuality = async () => {\n // Create offscreen canvas once outside the loop to prevent memory leaks/stuttering\n const oc = document.createElement('canvas');\n let ctx: CanvasRenderingContext2D | null = null;\n \n while (true) {\n if (!videoRef.current || !latestLandmarks.current) {\n await new Promise(r => setTimeout(r, 100));\n continue;\n }\n const video = videoRef.current;\n const bbox = getFaceBoundingBox();\n\n // Initialize canvas dimensions if not set\n if (oc.width !== video.videoWidth) {\n oc.width = video.videoWidth;\n oc.height = video.videoHeight;\n ctx = oc.getContext('2d', { willReadFrequently: true });\n }\n\n // Sample luminance\n let luminance = 128; // default: assume ok if we can't sample\n if (ctx) {\n try {\n ctx.drawImage(video, 0, 0);\n if (bbox) {\n luminance = getRegionLuminance(ctx, bbox.x, bbox.y, bbox.width, bbox.height);\n } else {\n luminance = getRegionLuminance(ctx, 0, 0, oc.width, oc.height);\n }\n } catch { /* ignore */ }\n }\n\n const faceW = bbox?.width ?? 0;\n const faceH = bbox?.height ?? 0;\n const quality = evaluateCaptureQuality(luminance, faceW, faceH);\n\n if (quality.ready) {\n setLiveFeedback(null);\n return true;\n }\n setLiveFeedback({ message: quality.message, isGood: false });\n await new Promise(r => setTimeout(r, 200));\n }\n };\n\n // Helper to extract Yaw angle in degrees from the affine matrix\n const getYawDegrees = (matrix: Float32Array) => {\n // matrix[8] is m02, matrix[10] is m22\n return -Math.atan2(matrix[8], matrix[10]) * (180 / Math.PI);\n };\n\n // Helper to wait for a specific pose condition dynamically\n const waitForPose = async (condition: (yaw: number) => boolean) => {\n while (true) {\n if (!latestMatrix.current) {\n setLiveFeedback(prev => prev?.message === \"Face not detected. Keep your face in frame.\" && prev?.isGood === false ? prev : { message: \"Face not detected. Keep your face in frame.\", isGood: false });\n await new Promise(r => setTimeout(r, 100));\n continue;\n }\n \n // Dynamic tracking: constantly enforce distance even during poses\n const status = checkFaceAlignment();\n if (!status.aligned) {\n setLiveFeedback(prev => prev?.message === status.message && prev?.isGood === false ? prev : { message: status.message, isGood: false });\n await new Promise(r => setTimeout(r, 100));\n continue;\n }\n\n setLiveFeedback(null);\n\n const yaw = getYawDegrees(latestMatrix.current);\n if (condition(yaw)) {\n // Require holding the pose for a short time (300ms) to ensure stability\n await new Promise(r => setTimeout(r, 300));\n if (latestMatrix.current && condition(getYawDegrees(latestMatrix.current))) {\n return true;\n }\n }\n await new Promise(r => setTimeout(r, 50)); // Poll every 50ms\n }\n };\n\n const handleFailure = (msg: string) => {\n console.warn(\"Verification sequence reset:\", msg);\n setLiveFeedback(prev => prev?.message === msg && prev?.isGood === false ? prev : { message: msg, isGood: false });\n setCurrentStep('pose-align');\n setError(null);\n setTimeout(() => {\n setIsProcessing(false);\n setLiveFeedback(null);\n }, 4000);\n };\n\n try {\n // 0. Initial Alignment Check\n setCurrentStep('pose-align');\n await waitForAlignment();\n\n // 0b. Quality Gate — ensure adequate lighting and face size before poses\n await waitForQuality();\n\n // 1. Pose Check Left\n setCurrentStep('pose-left');\n await waitForPose((yaw) => yaw > 15); // Turned to the left\n\n // 2. Pose Check Right\n setCurrentStep('pose-right');\n await waitForPose((yaw) => Math.abs(yaw) < -15 || yaw < -15); // Turned to the right\n\n // 3. Pose Check Center\n setCurrentStep('pose-center');\n await waitForPose((yaw) => Math.abs(yaw) < 8); // Looking straight ahead\n\n // 4. Multi-frame Embedding Capture\n setCurrentStep('capturing');\n const video = videoRef.current!;\n let embedding: number[];\n try {\n embedding = await captureMultipleEmbeddings(video, 10, 200);\n } catch (e: any) {\n handleFailure(e.message || \"Failed to capture face data\");\n return;\n }\n\n const bbox = getFaceBoundingBox();\n if (!bbox) {\n handleFailure(\"Face lost during final check\");\n return;\n }\n\n const alignment = checkFaceAlignment();\n if (!alignment.aligned) {\n handleFailure(`Alignment lost: ${alignment.message}`);\n return;\n }\n\n // 5. Liveness flash\n setCurrentStep('light-flash');\n const livenessResult = await livenessEngine.runLivenessSequence(bbox);\n \n if (!livenessResult.passed) {\n handleFailure(livenessResult.message || \"Liveness check failed\");\n return;\n }\n\n setCurrentStep('processing');\n\n const mockFaceData: any = {\n embedding: embedding,\n box: [bbox.x, bbox.y, bbox.width, bbox.height],\n rotation: { angle: { yaw: 0, pitch: 0, roll: 0 } },\n mesh: latestLandmarks.current.map((l: any) => [l.x, l.y, l.z]),\n };\n\n const mockLivenessData: LivenessData = {\n blinkCount: 1,\n blinkTimestamps: [Date.now()],\n emotionTransitions: [{ from: 'neutral', to: 'happy', timestamp: Date.now(), duration: 500 }],\n headMovement: { yawRange: [0, 0], pitchRange: [0, 0], rollRange: [0, 0] },\n verificationDuration: 3000,\n stepCompletionTimes: { happy: 1000, eyeBlink: 2000 }\n };\n\n // Proper RawFacialData structure for the UI\n const extractedRawData: RawFacialData = {\n faceEmbedding: embedding,\n faceMesh: latestLandmarks.current.map((l: any) => [l.x, l.y, l.z]),\n faceLandmarks: latestLandmarks.current.map((l: any) => [l.x, l.y]),\n faceRotation: { angle: { yaw: 0, pitch: 0, roll: 0 }, matrix: [] },\n faceBox: bbox,\n timestamp: Date.now()\n };\n\n // Generate the final SimHash Payload for the selected wallet pipeline\n const payload = generateBiometricSimHash(mockFaceData, mockLivenessData, embedding);\n \n if (onBiometricData) onBiometricData(payload);\n if (onVerificationComplete) onVerificationComplete({\n rawFacialData: extractedRawData,\n livenessData: mockLivenessData,\n isComplete: true,\n message: 'Verification completed successfully'\n });\n\n setCurrentStep('completed');\n\n } catch (err: any) {\n // Only catch truly unexpected runtime errors here\n console.error(\"Unexpected verification error:\", err);\n handleFailure(err.message || \"An unexpected error occurred\");\n }\n };\n\n runVerification();\n }, [faceDetected, isProcessing]);\n\n return (\n <div>\n <div className=\"relative overflow-hidden rounded-xl\" style={{ maxHeight: '600px' }}>\n <video\n ref={videoRef}\n className=\"w-full h-full object-contain sm:object-cover\"\n autoPlay\n playsInline\n muted\n style={{ transform: 'scaleX(-1)' }}\n />\n \n <canvas\n ref={canvasRef}\n className=\"absolute inset-0 w-full h-full pointer-events-none\"\n style={{ zIndex: 10, transform: 'scaleX(-1)' }}\n />\n\n <div \n ref={flashOverlayRef} \n className=\"absolute inset-0 w-full h-full pointer-events-none transition-colors duration-75\"\n style={{ zIndex: 20 }}\n />\n\n <div className=\"absolute top-4 left-4 z-30\">\n {faceDetected ? (\n <div className=\"bg-green-500/90 backdrop-blur-sm text-white px-3 py-1 rounded-full text-sm font-bold shadow-[0_0_10px_rgba(34,197,94,0.5)] border border-green-400 flex items-center gap-2\">\n <div className=\"w-2 h-2 bg-white rounded-full animate-pulse\"></div>\n Face Detected\n </div>\n ) : (\n <div className=\"bg-red-500/90 backdrop-blur-sm text-white px-3 py-1 rounded-full text-sm font-bold shadow-[0_0_10px_rgba(239,68,68,0.5)] border border-red-400 flex items-center gap-2\">\n <div className=\"w-2 h-2 bg-white rounded-full\"></div>\n No Face Detected\n </div>\n )}\n </div>\n </div>\n\n <div className=\"text-center mb-4 pt-4 px-4 h-[100px]\">\n {!stream && <div className=\"text-gray-500\">Initializing camera...</div>}\n \n {liveFeedback ? (\n <div className={`text-lg font-bold animate-pulse ${liveFeedback.isGood ? 'text-green-400' : 'text-amber-400'}`}>\n {liveFeedback.message}\n </div>\n ) : (\n <>\n {stream && currentStep === 'pose-align' && <div className=\"text-blue-400 text-lg font-bold animate-pulse\">Position face in center & ensure good distance</div>}\n {stream && currentStep === 'pose-left' && <div className=\"text-white text-lg font-bold animate-pulse\">Turn your head slowly to the LEFT</div>}\n {stream && currentStep === 'pose-right' && <div className=\"text-white text-lg font-bold animate-pulse\">Turn your head slowly to the RIGHT</div>}\n {stream && currentStep === 'pose-center' && <div className=\"text-white text-lg font-bold\">Look straight at the camera</div>}\n {stream && currentStep === 'capturing' && <div className=\"text-cyan-400 text-lg font-bold animate-pulse\">Capturing biometric data... Hold still</div>}\n {stream && currentStep === 'light-flash' && <div className=\"text-blue-400 font-bold\">Verifying physical presence (Flashing colors...)</div>}\n {stream && currentStep === 'processing' && <div className=\"text-white\">Generating Cryptographic Embedding...</div>}\n {stream && currentStep === 'completed' && <div className=\"text-green-500 font-bold\">Verification Successful</div>}\n </>\n )}\n </div>\n \n {/* Removed Global Toast Notification so all errors render in liveFeedback box */}\n </div>\n );\n};\n\nexport default FaceZKInner;\n","import React, { useState } from 'react';\n\nimport FaceZK from './FaceZK';\nimport { VerificationResult } from '../../core/biometrics/biometricUtils';\n\n// const FaceZK = dynamic(() => import('./FaceZK'), { ssr: false });\n// const HumanityCodeComparison = dynamic(() => import('../HumanityCodeComparison'), { ssr: false });\n\ninterface ProofOfHumanityProps {\n onNextStep: () => void;\n onBiometricData?: (data: { simhash_full: string }) => void;\n onVerificationComplete?: (result: VerificationResult) => void;\n className?: string;\n containerClassName?: string;\n buttonClassName?: string;\n}\n\nconst ProofOfHumanity: React.FC<ProofOfHumanityProps> = ({ \n onNextStep, \n onBiometricData, \n onVerificationComplete,\n className = \"\",\n containerClassName = \"\",\n buttonClassName = \"\"\n}) => {\n const [cameraActive, setCameraActive] = useState(false);\n const [verificationComplete, setVerificationComplete] = useState(false);\n const [showComparison, setShowComparison] = useState(false);\n\n const handleActivateCamera = () => {\n setCameraActive(true);\n };\n\n const handleBiometricData = (data: { simhash_full: string }) => {\n console.log('🎯 Face verification SimHash received:', data);\n if (onBiometricData) {\n onBiometricData(data);\n }\n };\n\n const handleVerificationComplete = (result: VerificationResult) => {\n console.log('Verification complete:', result);\n setVerificationComplete(true);\n if (onVerificationComplete) {\n onVerificationComplete(result);\n }\n };\n\n const handleContinue = () => {\n console.log('Continuing to next step...');\n onNextStep();\n };\n\n const toggleComparison = () => {\n setShowComparison(!showComparison);\n };\n\n return (\n <div className={`mx-auto mt-5 w-full max-w-[700px] flex flex-col items-center px-4 ${className}`}>\n <div className=\"flex flex-col items-center mb-6 sm:mb-10\">\n <h2 className=\"text-white text-xl sm:text-2xl md:text-3xl font-bold mb-2 text-center\">Proof of Humanity</h2>\n <p className=\"text-[#A0A3BD] text-center w-full max-w-[620px] text-sm sm:text-base px-2\">\n Powered by advanced face detection technology with sequential liveness detection. Your facial data is collected and processed securely. <span className=\"text-white cursor-pointer\">Learn more.</span>\n <span className=\"text-amber-400 block mt-2 font-medium\">Please remove any glasses and face masks before verifying.</span>\n </p>\n </div>\n \n \n <div className={`backdrop-container flex flex-col items-center justify-center bg-[#030B29] rounded-xl w-full max-w-[700px] h-[400px] sm:h-[450px] md:h-[477px] border border-gray-800 ${containerClassName}`}>\n {!cameraActive ? (\n <>\n <img \n src=\"/camera.png\" \n alt=\"Camera Icon\" \n width={200} \n height={200} \n className=\"sm:w-[250px] sm:h-[250px] md:w-[280px] md:h-[280px]\"\n />\n \n <button\n className={`bg-[#0D3DDE] hover:bg-[#1A2240] text-white font-semibold py-2 px-6 rounded-lg transition-colors duration-200 mt-4 sm:mt-8 cursor-pointer text-sm sm:text-base ${buttonClassName}`}\n onClick={handleActivateCamera}\n >\n Activate Camera\n </button>\n </>\n ) : (\n <div className=\"w-full h-full\">\n <FaceZK\n onBiometricData={handleBiometricData}\n onVerificationComplete={handleVerificationComplete}\n onContinue={handleContinue}\n />\n </div>\n )}\n </div>\n\n {/* HumanityCode Comparison UI */}\n {/* {showComparison && <HumanityCodeComparison />} */}\n </div>\n );\n};\n\nexport default ProofOfHumanity; ","import React, { useState, useEffect } from \"react\";\nimport { useAccount } from 'wagmi';\nimport { useWallet as useSolanaWallet } from \"@solana/wallet-adapter-react\";\n\nimport WalletSelection from \"./wallet/WalletSelection\";\nimport SocialConnection from \"./wallet/SocialConnection\";\nimport ProofOfHumanity from \"./ProofOfHumanity\";\nimport { VerifiedRelayerClient } from \"../../core/api/relayer\";\nimport { VerificationResult } from \"../../core/biometrics/biometricUtils\";\n\nexport interface VerifiedOnchainFlowProps {\n relayerUrl?: string;\n requiredSocials?: Array<'farcaster' | 'lens' | 'x' | 'tiktok' | 'instagram' | 'youtube' | string>;\n requiredWallets?: Array<'phantom' | 'backpack' | 'metamask' | 'rainbow' | string>;\n requireBiometrics?: boolean;\n onIdentityVerified: (data: VerifiedIdentityData) => void;\n className?: string;\n environment?: 'mainnet' | 'testnet';\n appId?: string;\n}\n\nexport interface VerifiedIdentityData {\n walletAddress: string;\n chain: 'evm' | 'solana';\n socialProfile?: any;\n socialPlatform?: string;\n humanityCode?: string;\n simHash?: string;\n}\n\nconst VerifiedOnchainFlow: React.FC<VerifiedOnchainFlowProps> = ({ \n relayerUrl,\n requiredSocials = [],\n requiredWallets,\n requireBiometrics = true,\n onIdentityVerified,\n className = \"\",\n environment = 'mainnet',\n appId\n}) => {\n const finalRelayerUrl = relayerUrl || 'https://api.verifiedonchain.com';\n const [stepCount, setStepCount] = useState(1);\n const [socialConnected, setSocialConnected] = useState(false);\n const [socialProfileData, setSocialProfileData] = useState<any>(null);\n const [socialPlatform, setSocialPlatform] = useState<string | null>(null);\n const [requestStatus, setRequestStatus] = useState<'idle' | 'processing' | 'completed' | 'error'>('idle');\n const [humanityCode, setHumanityCode] = useState<string | null>(null);\n const [progressMessage, setProgressMessage] = useState<string>('');\n\n const { isConnected, address } = useAccount();\n const { connected: solanaConnected, publicKey: solanaPublicKey } = useSolanaWallet();\n\n const activeWallet = address ? address : (solanaPublicKey ? solanaPublicKey.toString() : null);\n const activeChain = address ? 'evm' : (solanaPublicKey ? 'solana' : null);\n\n useEffect(() => {\n if ((isConnected || solanaConnected) && stepCount === 1) {\n const timer = setTimeout(() => {\n if (requiredSocials.length > 0) {\n setStepCount(2);\n } else if (requireBiometrics) {\n setStepCount(3);\n } else {\n finishFlow();\n }\n }, 1000);\n return () => clearTimeout(timer);\n }\n }, [isConnected, solanaConnected, stepCount, requiredSocials, requireBiometrics]);\n\n const handleSocialConnect = async (platform: string, profileData?: any) => {\n setSocialConnected(true);\n setSocialPlatform(platform);\n if (profileData) setSocialProfileData(profileData);\n\n if (requireBiometrics) {\n setStepCount(3);\n } else {\n finishFlow();\n }\n };\n\n const finishFlow = (simHash?: string, returnedCode?: string) => {\n setRequestStatus('completed');\n if (returnedCode) setHumanityCode(returnedCode);\n \n onIdentityVerified({\n walletAddress: activeWallet as string,\n chain: activeChain as 'evm' | 'solana',\n socialProfile: socialProfileData,\n socialPlatform: socialPlatform || undefined,\n humanityCode: returnedCode,\n simHash: simHash\n });\n setStepCount(4);\n };\n\n const handleVerificationComplete = async (result: VerificationResult) => {\n setRequestStatus('processing');\n setStepCount(4);\n setProgressMessage('Submitting identity to Relayer...');\n\n try {\n const client = new VerifiedRelayerClient({ \n baseUrl: finalRelayerUrl,\n network: environment,\n appId: appId\n });\n const txResult = await client.submitVerification({\n simhashFull: result.rawFacialData.faceEmbedding.join(','), // Simplified for SDK\n livenessCombined: 0.99, // Simplified\n walletAddress: activeWallet as string,\n chain: activeChain as 'evm' | 'solana'\n });\n\n finishFlow(result.rawFacialData.faceEmbedding.join(','), txResult.txHash || \"SUCCESS_NO_HASH\");\n } catch (err) {\n setRequestStatus('error');\n setHumanityCode(`Error: ${err instanceof Error ? err.message : String(err)}`);\n }\n };\n\n return (\n <div className={`w-full max-w-[1000px] mx-auto min-h-[400px] rounded-[20px] p-5 relative overflow-y-auto text-white ${className}`}>\n \n {stepCount === 1 && (\n <WalletSelection \n onWalletConnect={() => {}} \n requiredWallets={requiredWallets}\n />\n )}\n\n {stepCount === 2 && (\n <SocialConnection\n onSocialConnect={handleSocialConnect}\n onNextStep={() => setStepCount(3)}\n userAddress={activeWallet || \"\"}\n availableSocials={requiredSocials}\n backendUrl={finalRelayerUrl}\n environment={environment}\n />\n )}\n\n {stepCount === 3 && (\n <ProofOfHumanity\n onNextStep={() => {}}\n onVerificationComplete={handleVerificationComplete}\n />\n )}\n\n {stepCount === 4 && (\n <div className=\"text-center mt-10\">\n <h2 className=\"text-3xl font-bold\">{requestStatus === 'error' ? 'Verification Failed' : 'Verification Complete'}</h2>\n <p className=\"mt-4 text-gray-400\">{progressMessage}</p>\n {humanityCode && (\n <div className=\"mt-8 p-4 bg-gray-900 rounded-xl\">\n <p className=\"font-mono text-sm break-all\">{humanityCode}</p>\n </div>\n )}\n </div>\n )}\n </div>\n );\n};\n\nexport default VerifiedOnchainFlow;\n","import React, { useState } from \"react\";\nimport { useConnect } from 'wagmi';\nimport { useWallet } from \"@solana/wallet-adapter-react\";\nimport type { WalletName } from \"@solana/wallet-adapter-base\";\n\ninterface WalletSelectionProps {\n onWalletConnect: (walletSlug: string) => void;\n className?: string;\n requiredWallets?: Array<'phantom' | 'backpack' | 'metamask' | 'rainbow' | string>;\n}\n\ntype SolanaWalletOption = {\n id: string;\n adapterName: WalletName;\n name: string;\n connectSlug: string;\n icon: string;\n type: 'solana';\n original: { adapter: { name: WalletName } };\n};\n\ntype EvmWalletOption = {\n id: string;\n name: string;\n icon: string;\n type: 'evm';\n original: unknown;\n};\n\ntype WalletOption = SolanaWalletOption | EvmWalletOption;\n\nconst EVM_WALLET_ICONS: Record<string, string> = {\n rainbow: '/rainbow.svg',\n metamask: '/MetaMask.svg',\n};\n\nconst WalletSelection: React.FC<WalletSelectionProps> = ({ onWalletConnect, className = \"\", requiredWallets }) => {\n const { connectors, connect } = useConnect();\n const { wallets, select, wallet, disconnect, connected, connect: connectSolana, connecting } = useWallet();\n const [isBusy, setIsBusy] = useState(false);\n \n // Combine all wallets into a single array for rendering\n const allWallets: WalletOption[] = [\n ...wallets.map((w): SolanaWalletOption => {\n let icon = w.adapter.icon; // This is a reliable Base64 SVG natively provided by Solana wallet adapters\n let label = w.adapter.name as string;\n let connectSlug = w.adapter.name.toLowerCase().replace(/\\s+/g, '-');\n\n if (label.toLowerCase().includes('phantom')) {\n label = 'Phantom ';\n connectSlug = 'solana-phantom';\n } else if (label.toLowerCase().includes('backpack')) {\n label = 'Backpack ';\n connectSlug = 'solana-backpack';\n }\n\n return {\n id: w.adapter.name as string,\n adapterName: w.adapter.name,\n name: label,\n connectSlug,\n icon,\n type: 'solana',\n original: w,\n };\n }),\n ...connectors.map((c): EvmWalletOption => {\n let icon = c.icon || 'https://raw.githubusercontent.com/WalletConnect/walletconnect-assets/master/Logo/Blue%20(Default)/Logo.svg';\n let name = c.name;\n\n if (c.id === 'metaMaskSDK' || c.id === 'injected' || name.toLowerCase().includes('metamask')) {\n name = 'MetaMask';\n icon = EVM_WALLET_ICONS.metamask;\n }\n if (c.id === 'rainbow' || name.toLowerCase().includes('rainbow')) {\n name = 'Rainbow';\n icon = EVM_WALLET_ICONS.rainbow;\n }\n\n return {\n id: c.id,\n name: name,\n icon,\n type: 'evm',\n original: c\n };\n })\n ];\n\n // Filter wallets if requiredWallets is provided\n const filteredWallets = requiredWallets \n ? allWallets.filter(w => {\n const reqLower = requiredWallets.map(s => s.toLowerCase());\n return reqLower.includes(w.name.trim().toLowerCase()) || reqLower.includes(w.id.toLowerCase());\n })\n : allWallets;\n\n // Deduplicate wallets by name (specifically handles duplicate Rainbow/MetaMask connectors)\n const uniqueWallets = filteredWallets.filter((v, i, a) => a.findIndex(t => (t.name.trim() === v.name.trim())) === i);\n\n return (\n <div className={`w-full ${className}`}>\n <div className=\"mt-10 px-4 sm:px-6 lg:px-0 lg:pl-[80px]\">\n <h1 className=\"text-[26px] sm:text-[36px] text-white font-bold lg:w-[340px] pb-5\">\n Choose your preferred wallet\n </h1>\n <p className=\"text-[16px] text-[#A0A3BD] lg:w-[420px]\">\n VerfifiedOnchain works with any wallet or blockchain and these are the currently integrated wallets.\n </p>\n </div>\n\n <div className=\"flex flex-col md:flex-row items-center justify-between px-4 sm:px-6 lg:px-[80px]\">\n <div className=\"w-full md:w-[389px] pt-5 flex flex-col space-y-0\">\n \n {uniqueWallets.map((w) => {\n if (w.type === 'solana') {\n const isActive = connected && wallet?.adapter.name === w.adapterName;\n const showSpinner = isBusy || connecting;\n return (\n <div\n key={w.id}\n onClick={async () => {\n if (isBusy || connecting) return;\n if (isActive) {\n try {\n await disconnect();\n } catch (error) {\n console.warn('Solana wallet disconnection error:', error);\n }\n return;\n }\n setIsBusy(true);\n try {\n select(w.adapterName);\n // Allow WalletProvider to apply the selected adapter before connecting\n await Promise.resolve();\n await connectSolana();\n onWalletConnect(w.connectSlug);\n } catch (error) {\n console.warn('Solana wallet connection error:', error);\n } finally {\n setIsBusy(false);\n }\n }}\n className=\"flex items-center space-x-4 hover:bg-[#0D3DDE] transition-colors duration-200 rounded-lg p-3 cursor-pointer border border-gray-800 hover:border-[#0D3DDE] mb-4 w-full\"\n style={{ opacity: showSpinner ? 0.7 : 1 }}\n >\n <img\n src={w.icon}\n alt={w.name}\n width={30}\n height={30}\n className=\"bg-white rounded-md p-1 shadow-md shadow-blue-500/20 hover:shadow-blue-500/50 transition-shadow duration-200\"\n />\n <span className=\"text-white font-medium\">\n {showSpinner ? \"Opening...\" : isActive ? `Disconnect ${w.name}` : w.name}\n </span>\n {isActive && wallet?.adapter.publicKey && (\n <span className=\"text-[12px] text-[#A0A3BD]\">\n {wallet.adapter.publicKey.toString().slice(0, 6)}...{wallet.adapter.publicKey.toString().slice(-4)}\n </span>\n )}\n </div>\n );\n } else {\n return (\n <div\n key={w.id}\n onClick={() => {\n connect({ connector: w.original as any });\n onWalletConnect(w.name);\n }}\n className=\"flex items-center space-x-4 hover:bg-[#0D3DDE] transition-colors duration-200 rounded-lg p-3 cursor-pointer border border-gray-800 hover:border-[#0D3DDE] mb-4 w-full\"\n >\n <img\n src={w.icon}\n alt={w.name}\n width={30}\n height={30}\n className=\"bg-white rounded-md p-1 shadow-md shadow-blue-500/20 hover:shadow-blue-500/50 transition-shadow duration-200\"\n />\n <span className=\"text-white font-medium\">{w.name}</span>\n </div>\n );\n }\n })}\n \n </div>\n <div className=\"mt-10 md:mt-0 flex-shrink-0 flex justify-center md:justify-end\">\n <img\n src=\"/cube.gif\"\n alt=\"Auth Image\"\n className=\"w-full max-w-[280px] sm:max-w-[300px] md:max-w-[400px] h-auto md:h-[400px] object-cover rounded-lg md:ml-10\"\n />\n </div>\n </div>\n </div>\n );\n};\n\nexport default WalletSelection;","import React, { useState, useEffect } from \"react\";\n\ninterface SocialConnectionProps {\n onSocialConnect: (platform: string, profileData?: any) => void;\n onNextStep: () => void;\n userAddress?: string;\n availableSocials: string[];\n className?: string;\n backendUrl?: string; // e.g. https://api.verifiedonchain.com/v1\n environment?: 'mainnet' | 'testnet';\n}\n\nconst SOCIAL_CONNECTION_STORAGE_KEY = 'verifiedonchain_social_connection';\n\nfunction persistSocialConnection(platform: string, profileData: any) {\n try {\n localStorage.setItem(\n SOCIAL_CONNECTION_STORAGE_KEY,\n JSON.stringify({\n platform,\n profileData,\n connectedAt: Date.now(),\n })\n );\n } catch (err) {\n console.warn('Failed to persist social connection:', err);\n }\n}\n\ninterface FarcasterAuthResponse {\n state: string;\n nonce: string;\n message: string;\n signature: string;\n fid: number;\n username: string;\n bio: string;\n displayName: string;\n pfpUrl: string;\n}\n\nconst SocialConnection: React.FC<SocialConnectionProps> = ({ \n onSocialConnect, \n onNextStep, \n userAddress, \n availableSocials, \n className = \"\",\n backendUrl = \"https://api.verifiedonchain.com/v1\",\n environment = \"mainnet\"\n}) => {\n const [isConnecting, setIsConnecting] = useState<string | null>(null);\n const [showFarcasterModal, setShowFarcasterModal] = useState(false);\n const [showLensModal, setShowLensModal] = useState(false);\n const [showLensUsernameModal, setShowLensUsernameModal] = useState(false);\n const [showXModal, setShowXModal] = useState(false);\n const [farcasterData, setFarcasterData] = useState<FarcasterAuthResponse | null>(null);\n const [lensProfile, setLensProfile] = useState<any>(null);\n const [xProfile, setXProfile] = useState<any>(null);\n const [error, setError] = useState<string | null>(null);\n const [channelToken, setChannelToken] = useState<string>('');\n const [qrCodeUrl, setQrCodeUrl] = useState<string>('');\n const [pollInterval, setPollInterval] = useState<NodeJS.Timeout | null>(null);\n const [usernameInput, setUsernameInput] = useState<string>('');\n const [deepLinkUrl, setDeepLinkUrl] = useState<string>('');\n const [isProcessingSuccess, setIsProcessingSuccess] = useState<boolean>(false);\n const [currentNonce, setCurrentNonce] = useState<string>('');\n\n useEffect(() => {\n const handleMessage = (event: MessageEvent) => {\n // In a real prod environment, you might verify event.origin\n if (event.data?.type === 'vo:oauth-success') {\n const { platform, profile, error: authError } = event.data;\n \n if (authError) {\n setError(authError);\n setIsConnecting(null);\n return;\n }\n\n if (profile && platform) {\n console.log(`🎉 ${platform} Auth completed successfully with profile:`, profile);\n persistSocialConnection(platform, profile);\n \n setIsConnecting(null);\n onSocialConnect(platform, profile);\n \n setTimeout(() => {\n onNextStep();\n }, 300);\n }\n } else if (event.data?.type === 'X_AUTH_RESPONSE') {\n const { payload, error: authError } = event.data;\n \n if (authError) {\n setError(authError);\n setIsConnecting(null);\n return;\n }\n\n if (payload) {\n console.log('🎉 X Auth completed successfully with profile:', payload);\n setXProfile(payload);\n setShowXModal(true);\n handleXSuccess(payload);\n }\n }\n };\n\n window.addEventListener('message', handleMessage);\n return () => window.removeEventListener('message', handleMessage);\n }, [isProcessingSuccess, onSocialConnect, onNextStep]);\n\n useEffect(() => {\n return () => {\n if (pollInterval) {\n clearInterval(pollInterval);\n }\n };\n }, [pollInterval]);\n\n const startOAuth = (platform: string) => {\n setIsConnecting(platform);\n setError(null);\n \n const origin = typeof window !== 'undefined' ? window.location.origin : '';\n const params = new URLSearchParams({ origin, network: environment });\n if (userAddress) params.append('wallet', userAddress);\n \n const oauthUrl = `${backendUrl}/oauth/${platform}/start?${params.toString()}`;\n\n const width = 600;\n const height = 800;\n const left = window.innerWidth / 2 - width / 2 + window.screenX;\n const top = window.innerHeight / 2 - height / 2 + window.screenY;\n\n const popup = window.open(\n oauthUrl,\n `${platform}_oauth_popup`,\n `width=${width},height=${height},top=${top},left=${left},scrollbars=yes,status=no,resizable=no,menubar=no,toolbar=no,location=no`\n );\n \n if (!popup) {\n setError(\"Popup was blocked. Please allow popups for this site and try again.\");\n setIsConnecting(null);\n return;\n }\n\n const checkClosed = setInterval(() => {\n if (popup.closed) {\n clearInterval(checkClosed);\n setIsConnecting((prev) => {\n if (prev === platform) {\n setError(\"Authentication window was closed.\");\n return null;\n }\n return prev;\n });\n }\n }, 1000);\n };\n\n const handleFarcasterClick = async () => {\n setIsConnecting('farcaster');\n setError(null);\n setIsProcessingSuccess(false);\n \n try {\n const nonce = Array.from(crypto.getRandomValues(new Uint8Array(16)))\n .map(b => b.toString(16).padStart(2, '0'))\n .join('');\n \n setCurrentNonce(nonce);\n \n const channelResponse = await fetch('https://relay.farcaster.xyz/v1/channel', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n siweUri: window.location.origin,\n domain: window.location.hostname,\n nonce: nonce,\n }),\n });\n\n if (!channelResponse.ok) {\n const errorText = await channelResponse.text();\n throw new Error(`Failed to create Farcaster auth channel: ${channelResponse.status}`);\n }\n\n const channelData = await channelResponse.json();\n \n if (!channelData.channelToken || !channelData.url) {\n throw new Error('Invalid response from Farcaster relay - missing token or URL');\n }\n \n setChannelToken(channelData.channelToken);\n \n const authUrl = channelData.url;\n setDeepLinkUrl(authUrl);\n \n setQrCodeUrl(`https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=${encodeURIComponent(authUrl)}`);\n \n setShowFarcasterModal(true);\n startPolling(channelData.channelToken, nonce);\n \n } catch (err: any) {\n setError(err.message || 'Failed to initialize Farcaster authentication');\n setIsConnecting(null);\n }\n };\n\n const startPolling = (token: string, nonce: string) => {\n let pollCount = 0;\n const maxPolls = 150; \n \n const interval = setInterval(async () => {\n pollCount++;\n \n if (pollCount > maxPolls) {\n clearInterval(interval);\n setPollInterval(null);\n setError('Authentication timeout. Please try again.');\n setIsConnecting(null);\n return;\n }\n \n try {\n const statusResponse = await fetch(`https://relay.farcaster.xyz/v1/channel/status?channelToken=${token}`, {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${token}`,\n },\n });\n \n if (!statusResponse.ok) {\n return;\n }\n\n const statusData = await statusResponse.json();\n \n if (statusData.state === 'completed') {\n clearInterval(interval);\n setPollInterval(null);\n \n const response = statusData.response || statusData;\n \n const profileData: FarcasterAuthResponse = {\n state: statusData.state,\n nonce: response.nonce || nonce,\n message: response.message || '',\n signature: response.signature || '',\n fid: response.fid || 0,\n username: response.username || '',\n bio: response.bio || '',\n displayName: response.displayName || response.username || '',\n pfpUrl: response.pfpUrl || '',\n };\n \n setFarcasterData(profileData);\n handleFarcasterSuccess(profileData);\n }\n } catch (err) {\n }\n }, 2000);\n\n setPollInterval(interval);\n };\n\n const handleFarcasterSuccess = (profileData: FarcasterAuthResponse) => {\n if (isProcessingSuccess) {\n return;\n }\n \n setIsProcessingSuccess(true);\n \n if (pollInterval) {\n clearInterval(pollInterval);\n setPollInterval(null);\n }\n \n setShowFarcasterModal(false);\n setIsConnecting(null);\n \n const farcasterProfile = {\n displayName: profileData.displayName,\n username: profileData.username,\n pfpUrl: profileData.pfpUrl,\n bio: profileData.bio,\n fid: profileData.fid,\n };\n persistSocialConnection('farcaster', farcasterProfile);\n onSocialConnect('farcaster', farcasterProfile);\n \n setQrCodeUrl('');\n setChannelToken('');\n setDeepLinkUrl('');\n setCurrentNonce('');\n \n setTimeout(() => {\n onNextStep();\n }, 300);\n };\n\n const closeFarcasterModal = () => {\n if (pollInterval) {\n clearInterval(pollInterval);\n setPollInterval(null);\n }\n setShowFarcasterModal(false);\n setIsConnecting(null);\n setQrCodeUrl('');\n setChannelToken('');\n setDeepLinkUrl('');\n setCurrentNonce('');\n setIsProcessingSuccess(false);\n };\n\n const openWarpcast = () => {\n if (deepLinkUrl) {\n window.open(deepLinkUrl, '_blank');\n }\n };\n\n const handleLensClick = async () => {\n setError(null);\n setShowLensUsernameModal(true);\n };\n\n const handleLensUsernameSubmit = async () => {\n if (!usernameInput.trim()) {\n setError('Please enter a Lens username');\n return;\n }\n\n setIsConnecting('lens');\n setError(null);\n \n try {\n const lensProfileData = await fetchLensProfileByUsername(usernameInput.trim());\n \n if (lensProfileData) {\n if (userAddress) {\n const accountOwner = lensProfileData.owner?.toLowerCase();\n const connectedAddress = userAddress.toLowerCase();\n \n if (accountOwner !== connectedAddress) {\n setError('The Lens account owner does not match your connected wallet address.');\n setIsConnecting(null);\n return;\n }\n }\n \n setLensProfile(lensProfileData);\n setShowLensUsernameModal(false);\n setShowLensModal(true);\n setUsernameInput('');\n handleLensSuccess(lensProfileData);\n } else {\n setError('No Lens profile found for this username');\n setIsConnecting(null);\n }\n \n } catch (err: any) {\n setError(err.message || 'Failed to connect to Lens');\n setIsConnecting(null);\n }\n };\n\n const closeLensUsernameModal = () => {\n setShowLensUsernameModal(false);\n setUsernameInput('');\n setIsConnecting(null);\n setError(null);\n };\n\n const fetchLensProfileByUsername = async (username: string) => {\n try {\n const query = `\n query Account($request: AccountRequest!) {\n account(request: $request) {\n owner\n address\n metadata {\n name\n bio\n picture\n coverPicture\n }\n username(request: {autoResolve: true}) {\n namespace\n localName\n linkedTo\n value\n ownedBy\n }\n }\n }\n `;\n \n const response = await fetch('https://api.lens.xyz/graphql', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n query,\n variables: {\n request: {\n username: {\n localName: username,\n },\n },\n },\n }),\n });\n\n const data = await response.json();\n \n if (data.errors && data.errors.length > 0) {\n throw new Error(data.errors[0].message);\n }\n \n if (data.data?.account) {\n return data.data.account;\n }\n \n return null;\n } catch (err) {\n return null;\n }\n };\n\n const handleLensSuccess = (profileData: any) => {\n const pictureUri = profileData.metadata?.picture || '/lens-white.svg';\n \n const lensData = {\n displayName: profileData.metadata?.name || profileData.username?.value || profileData.username?.localName,\n username: profileData.username?.value || profileData.username?.localName,\n pfpUrl: pictureUri,\n bio: profileData.metadata?.bio,\n address: profileData.address,\n };\n \n persistSocialConnection('lens', lensData);\n onSocialConnect('lens', lensData);\n setIsConnecting(null);\n setTimeout(() => {\n setShowLensModal(false);\n onNextStep();\n }, 500);\n };\n\n const closeLensModal = () => {\n setShowLensModal(false);\n setIsConnecting(null);\n };\n\n const handleXClick = () => {\n setIsConnecting('x');\n setError(null);\n \n const width = 600;\n const height = 800;\n const left = window.innerWidth / 2 - width / 2 + window.screenX;\n const top = window.innerHeight / 2 - height / 2 + window.screenY;\n\n const popup = window.open(\n '',\n 'x_login_popup',\n `width=${width},height=${height},top=${top},left=${left},scrollbars=yes,status=no,resizable=no,menubar=no,toolbar=no,location=no`\n );\n \n if (popup) {\n // Assuming host implements /api/auth/x/login for legacy compat\n popup.location.href = '/api/auth/x/login';\n } else {\n setError(\"Popup was blocked. Please allow popups for this site and try again.\");\n setIsConnecting(null);\n }\n };\n\n const handleXSuccess = (profileData: any) => {\n const xData = {\n displayName: profileData.displayName,\n username: profileData.username,\n pfpUrl: profileData.pfpUrl,\n bio: profileData.bio || '',\n address: '',\n platform: 'x',\n };\n \n persistSocialConnection('x', xData);\n onSocialConnect('x', xData);\n setIsConnecting(null);\n setTimeout(() => {\n setShowXModal(false);\n onNextStep();\n }, 500);\n };\n\n const closeXModal = () => {\n setShowXModal(false);\n setIsConnecting(null);\n };\n\n const handleClick = (social: string) => {\n const s = social.toLowerCase();\n if (s === 'farcaster') {\n handleFarcasterClick();\n } else if (s === 'lens') {\n handleLensClick();\n } else if (s === 'x') {\n handleXClick();\n } else {\n startOAuth(s);\n }\n };\n\n const getPlatformLabel = (social: string) => {\n switch (social.toLowerCase()) {\n case 'x': return '(formerly Twitter)';\n case 'farcaster': return 'Farcaster';\n case 'lens': return 'Lens Protocol';\n case 'youtube': return 'YouTube';\n case 'instagram': return 'Instagram';\n case 'tiktok': return 'TikTok';\n default: return social.charAt(0).toUpperCase() + social.slice(1);\n }\n };\n\n const getPlatformIcon = (social: string) => {\n switch (social.toLowerCase()) {\n case 'x': return '/x-white.svg';\n case 'farcaster': return '/Farcaster.svg';\n case 'lens': return '/lens-white.svg';\n case 'youtube': return 'https://upload.wikimedia.org/wikipedia/commons/0/09/YouTube_full-color_icon_%282017%29.svg';\n case 'instagram': return 'https://upload.wikimedia.org/wikipedia/commons/e/e7/Instagram_logo_2016.svg';\n case 'tiktok': return 'https://cdn4.iconfinder.com/data/icons/social-media-flat-7/64/Social-media_Tiktok-512.png';\n default: return '';\n }\n };\n\n return (\n <div className={`text-center px-4 sm:px-6 lg:px-8 mt-10 ${className}`}>\n <h1 className=\"text-2xl sm:text-3xl lg:text-[36px] font-bold text-white mb-6 sm:mb-8 lg:mb-10\">\n Connect one social identity\n </h1>\n <p className=\"text-[#A0A3BD] text-sm sm:text-base max-w-[640px] mx-auto -mt-4 mb-6 sm:mb-8\">\n Link your Lens, Farcaster, or X to anchor your social identity. We only read public profile data. No passwords, no custody, just proof it's you.\n </p>\n\n {error && (\n <div className=\"mb-6 bg-red-500 bg-opacity-20 border border-red-500 text-red-200 px-4 py-3 rounded-lg text-sm max-w-[600px] mx-auto\">\n {error}\n </div>\n )}\n\n <div className=\"w-full max-w-[600px] mx-auto flex flex-col items-center space-y-4\">\n {availableSocials.map((social) => {\n const label = getPlatformLabel(social);\n const iconUrl = getPlatformIcon(social);\n\n return (\n <button \n key={social}\n onClick={() => handleClick(social)}\n disabled={isConnecting !== null}\n className={`flex items-center justify-center space-x-2 sm:space-x-4 transition-colors duration-200 rounded-lg p-3 cursor-pointer border border-gray-800 w-full sm:w-[391px] bg-[#4050590D] ${\n isConnecting === social ? 'opacity-60 cursor-not-allowed' : 'hover:bg-[#0D3DDE] hover:border-[#0D3DDE]'\n }`}\n >\n {iconUrl && (\n <img\n src={iconUrl}\n alt={label}\n className=\"w-6 h-6 sm:w-8 sm:h-8 object-contain\"\n />\n )}\n <span className=\"text-white font-bold text-base sm:text-lg lg:text-[20px]\">\n {isConnecting === social ? 'Connecting...' : label}\n </span>\n </button>\n );\n })}\n </div>\n\n {showFarcasterModal && (\n <div className=\"fixed inset-0 flex items-center justify-center z-50 p-4 backdrop-blur-sm\">\n <div className=\"bg-white border border-[#F8FBFF1A] rounded-[20px] p-4 sm:p-6 w-full max-w-[671px] text-black relative\">\n <div className=\"flex items-center mb-4 sm:mb-6 relative\">\n <h3 className=\"text-lg sm:text-xl lg:text-[24px] font-bold text-center flex-1\">Sign in with Farcaster</h3>\n <button\n onClick={closeFarcasterModal}\n className=\"absolute right-0 hover:text-gray-400 transition-colors cursor-pointer\"\n >\n <svg className=\"w-5 h-5 sm:w-6 sm:h-6\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n </div>\n \n <div className=\"text-center\">\n <p className=\"text-sm sm:text-base lg:text-[16px] mb-4 font-medium text-[#423B3B] w-full max-w-[341px] mx-auto px-2\">\n To sign with Farcaster scan the code below with your phone's camera.\n </p>\n {qrCodeUrl && (\n <img\n width={172}\n height={175}\n src={qrCodeUrl} \n alt=\"Farcaster QR Code\" \n className=\"mx-auto mb-4 rounded-lg\"\n />\n )}\n\n <hr className=\"my-4 border-gray-300\" />\n <button\n onClick={openWarpcast}\n className=\"w-full mb-4 text-blue-600 font-bold text-[16px] cursor-pointer\"\n >\n I'm using my phone\n </button>\n <div className=\"flex items-center justify-center space-x-2 text-sm\">\n <svg className=\"animate-spin h-4 w-4\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\"></circle>\n <path className=\"opacity-75\" fill=\"currentColor\" d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"></path>\n </svg>\n <span>Waiting for authentication...</span>\n </div>\n </div>\n </div>\n </div>\n )}\n\n {showLensUsernameModal && (\n <div className=\"fixed inset-0 flex items-center justify-center z-50 p-4 backdrop-blur-sm\">\n <div className=\"bg-[#02081D] border border-[#F8FBFF1A] rounded-[20px] p-6 max-w-md w-full relative\">\n <div className=\"flex justify-between items-center mb-6\">\n <h3 className=\"text-lg font-bold text-white\">Connect Lens Profile</h3>\n <button\n onClick={closeLensUsernameModal}\n className=\"text-gray-400 hover:text-white transition-colors cursor-pointer\"\n >\n <svg className=\"w-6 h-6\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n </div>\n \n {error && (\n <div className=\"mb-4 bg-red-500 bg-opacity-20 border border-red-500 text-red-200 px-4 py-3 rounded-lg text-sm\">\n {error}\n </div>\n )}\n \n <div>\n <div className=\"mb-4\">\n <label htmlFor=\"username\" className=\"block text-sm font-medium text-white mb-2 text-left\">\n Enter your Lens username\n </label>\n <input\n type=\"text\"\n id=\"username\"\n value={usernameInput}\n onChange={(e) => setUsernameInput(e.target.value)}\n onKeyPress={(e) => {\n if (e.key === 'Enter') {\n handleLensUsernameSubmit();\n }\n }}\n placeholder=\"username\"\n className=\"w-full px-4 py-2 border border-gray-600 rounded-lg bg-[#0A1A2E] text-white placeholder:text-gray-400 focus:outline-none focus:ring-2 focus:ring-[#0D3DDE] focus:border-transparent\"\n disabled={isConnecting === 'lens'}\n autoFocus\n />\n <p className=\"text-xs text-gray-400 mt-2 text-left\">\n Enter your Lens username without the @ symbol\n </p>\n </div>\n \n <button\n onClick={handleLensUsernameSubmit}\n disabled={isConnecting === 'lens' || !usernameInput.trim()}\n className={`w-full py-3 rounded-lg font-medium transition-colors duration-200 ${\n isConnecting === 'lens' || !usernameInput.trim()\n ? 'bg-gray-700 text-gray-400 cursor-not-allowed'\n : 'bg-[#0D3DDE] hover:bg-[#0A2FB8] text-white'\n }`}\n >\n {isConnecting === 'lens' ? 'Connecting...' : 'Connect'}\n </button>\n </div>\n </div>\n </div>\n )}\n\n {showLensModal && lensProfile && (\n <div className=\"fixed inset-0 flex items-center justify-center z-50 p-4 backdrop-blur-sm\">\n <div className=\"bg-[#02081D] border border-[#F8FBFF1A] rounded-[20px] p-6 max-w-sm w-full relative\">\n <div className=\"flex justify-between items-center mb-6\">\n <h3 className=\"text-lg font-bold text-white\">Lens Connected!</h3>\n <button\n onClick={closeLensModal}\n className=\"text-gray-400 hover:text-white transition-colors\"\n >\n <svg className=\"w-6 h-6\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n </div>\n \n <div className=\"text-center\">\n <div className=\"w-20 h-20 mx-auto mb-3 rounded-full overflow-hidden bg-gray-700\">\n <img \n src={lensProfile.metadata?.picture || '/lens-white.svg'}\n alt=\"Profile\"\n className=\"w-full h-full object-cover\"\n />\n </div>\n <h4 className=\"text-white font-bold text-lg mb-1\">\n {lensProfile.metadata?.name || lensProfile.username?.localName || lensProfile.username?.value}\n </h4>\n <p className=\"text-gray-400 text-sm mb-4\">\n @{lensProfile.username?.value || lensProfile.username?.localName}\n </p>\n <div className=\"flex items-center justify-center space-x-2 text-[#ABFE2C]\">\n <svg className=\"w-6 h-6\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M5 13l4 4L19 7\" />\n </svg>\n <span className=\"font-medium\">Successfully connected!</span>\n </div>\n </div>\n </div>\n </div>\n )}\n\n {showXModal && xProfile && (\n <div className=\"fixed inset-0 flex items-center justify-center z-50 p-4 backdrop-blur-sm\">\n <div className=\"bg-[#02081D] border border-[#F8FBFF1A] rounded-[20px] p-6 max-w-sm w-full relative\">\n <div className=\"flex justify-between items-center mb-6\">\n <h3 className=\"text-lg font-bold text-white\">X Connected!</h3>\n <button\n onClick={closeXModal}\n className=\"text-gray-400 hover:text-white transition-colors\"\n >\n <svg className=\"w-6 h-6\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n </div>\n \n <div className=\"text-center\">\n <div className=\"w-20 h-20 mx-auto mb-3 rounded-full overflow-hidden flex items-center justify-center bg-zinc-900 border border-zinc-800\">\n <img \n src=\"/x-white.svg\"\n alt=\"X Profile\"\n className=\"w-10 h-10 object-contain\"\n />\n </div>\n <h4 className=\"text-white font-bold text-lg mb-1\">\n {xProfile.displayName}\n </h4>\n <p className=\"text-gray-400 text-sm mb-4\">\n @{xProfile.username}\n </p>\n <div className=\"flex items-center justify-center space-x-2 text-[#ABFE2C]\">\n <svg className=\"w-6 h-6\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M5 13l4 4L19 7\" />\n </svg>\n <span className=\"font-medium\">Successfully connected!</span>\n </div>\n </div>\n </div>\n </div>\n )}\n </div>\n );\n};\n\nexport default SocialConnection;\n"],"mappings":"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","names":["useState","useEffect","useEffect","useState","useCallback","useState","useEffect","useCallback","useState","Fragment","jsx","jsxs","useState","useState","useEffect","useState","jsx","jsxs","useState","useEffect","jsx","jsxs","jsx","jsxs","useState","useEffect"]}
|