document.addEventListener("DOMContentLoaded", async () => { console.log("🔄 Block sync page loaded"); const status = document.getElementById("status") as HTMLElement; const progressBar = document.getElementById("progressBar") as HTMLElement; const continueBtn = document.getElementById("continueBtn") as HTMLButtonElement; function updateStatus(message: string, type: 'loading' | 'success' | 'error') { if (status) { status.textContent = message; status.className = `status ${type}`; } } function updateProgress(percentage: number) { if (progressBar) { progressBar.style.width = `${percentage}%`; } } function updateSyncItem(elementId: string, value: string, status: 'pending' | 'completed' | 'error' = 'pending') { const element = document.getElementById(elementId); if (element) { element.textContent = value; element.className = `sync-status ${status}`; } } // Gestion du bouton continuer (définie avant le try pour être toujours disponible) if (continueBtn) { continueBtn.addEventListener('click', async () => { console.log('🏠 Redirecting to main application...'); // Rediriger vers l'application principale console.log('🔄 Block sync completed, checking storage state...'); const { checkStorageStateAndNavigate } = await import('../../router'); await checkStorageStateAndNavigate(); }); } try { // Étape 1: Vérification des prérequis updateStatus('🔍 Vérification des prérequis...', 'loading'); updateProgress(10); // Vérifier que le PBKDF2 key existe d'abord (prérequis le plus basique) dans le store pbkdf2keys const { SecureCredentialsService } = await import('../../services/secure-credentials.service'); const secureCredentials = SecureCredentialsService.getInstance(); let pbkdf2KeyFound = false; const securityModes = ['none', 'otp', 'password', 'os', 'proton-pass']; for (const mode of securityModes) { try { const hasKey = await secureCredentials.hasPBKDF2Key(mode as any); if (hasKey) { const key = await secureCredentials.retrievePBKDF2Key(mode as any); if (key) { pbkdf2KeyFound = true; console.log(`✅ PBKDF2 key found in pbkdf2keys store for security mode: ${mode}`); break; } } } catch (error) { console.log(`⚠️ No PBKDF2 key found in pbkdf2keys store for mode ${mode}`); } } if (!pbkdf2KeyFound) { console.log('⚠️ PBKDF2 key not found in pbkdf2keys store, redirecting to security-setup...'); updateStatus('⚠️ Redirection vers la configuration de sécurité...', 'loading'); setTimeout(() => { window.location.href = '/src/pages/security-setup/security-setup.html'; }, 1000); return; } // Étape 2: Initialisation des services updateStatus('🔄 Initialisation des services...', 'loading'); updateProgress(20); const { default: Services } = await import('../../services/service'); if (!Services) { throw new Error('Services class not found in default export'); } console.log('🔄 Waiting for services to be ready...'); let attempts = 0; const maxAttempts = 30; const delayMs = 2000; let services; while (attempts < maxAttempts) { try { console.log(`🔄 Attempting to get services (attempt ${attempts + 1}/${maxAttempts})...`); services = await Services.getInstance(); console.log('✅ Services initialized successfully'); break; } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); console.log(`⏳ Services not ready yet (attempt ${attempts + 1}/${maxAttempts}):`, errorMessage); // Si c'est une erreur de mémoire, arrêter immédiatement if (errorMessage.includes('Out of memory') || errorMessage.includes('insufficient memory')) { console.error('🚫 Memory error detected - stopping retry attempts'); updateStatus('❌ Erreur: Mémoire insuffisante. Veuillez actualiser la page.', 'error'); throw new Error('WebAssembly initialization failed due to insufficient memory. Please refresh the page.'); } attempts++; if (attempts >= maxAttempts) { throw new Error(`Services failed to initialize after ${maxAttempts} attempts.`); } await new Promise(resolve => setTimeout(resolve, delayMs)); } } if (!services) { throw new Error('Services not initialized'); } // Vérifier que le wallet existe en base (avec plusieurs tentatives pour gérer les problèmes de synchronisation) let wallet = await services.getDeviceFromDatabase(); if (!wallet) { console.log('⚠️ Wallet not found, waiting for database synchronization...'); for (let attempt = 0; attempt < 5; attempt++) { await new Promise(resolve => setTimeout(resolve, 500)); wallet = await services.getDeviceFromDatabase(); if (wallet) { console.log(`✅ Wallet found after ${attempt + 1} attempts`); break; } } if (!wallet) { console.log('⚠️ Wallet still not found after retries, redirecting to wallet-setup...'); updateStatus('⚠️ Redirection vers la configuration du wallet...', 'loading'); setTimeout(() => { window.location.href = '/src/pages/wallet-setup/wallet-setup.html'; }, 1000); return; } } // Vérifier que le wallet contient bien les données attendues if (wallet.sp_wallet && wallet.sp_wallet.birthday !== undefined) { console.log('✅ Wallet found in database with birthday:', wallet.sp_wallet.birthday); } else { throw new Error('Wallet found but missing required data (sp_wallet or birthday)'); } // Vérifier que le birthday est configuré (> 0) if (!wallet.sp_wallet.birthday || wallet.sp_wallet.birthday === 0) { console.log('⚠️ Birthday not configured (birthday = 0), redirecting to birthday-setup...'); updateStatus('⚠️ Redirection vers la configuration de la date anniversaire...', 'loading'); setTimeout(() => { window.location.href = '/src/pages/birthday-setup/birthday-setup.html'; }, 1000); return; } console.log('✅ All prerequisites verified for block sync'); // Étape 3: Connexion aux relais si nécessaire updateStatus('🔗 Connexion aux relais...', 'loading'); updateProgress(40); let currentBlockHeight = services.getCurrentBlockHeight(); if (currentBlockHeight === -1 || currentBlockHeight === 0) { console.log('⚠️ Block height not available, connecting to relays...'); await services.connectAllRelays(); // Attendre que le handshake arrive et que chain_tip soit défini await new Promise((resolve, reject) => { const timeout = setTimeout(() => { reject(new Error('Timeout waiting for block height from handshake')); }, 15000); // 15 secondes de timeout const checkBlockHeight = () => { const blockHeight = services.getCurrentBlockHeight(); if (blockHeight !== -1 && blockHeight > 0) { console.log(`✅ Block height set from handshake: ${blockHeight}`); currentBlockHeight = blockHeight; clearTimeout(timeout); resolve(); } else { setTimeout(checkBlockHeight, 100); } }; checkBlockHeight(); }); } // Étape 4: Récupération des informations de synchronisation updateStatus('📊 Récupération des informations de synchronisation...', 'loading'); updateProgress(50); const birthday = wallet.sp_wallet.birthday; const lastScan = wallet.sp_wallet.last_scan || birthday; const blocksToScan = currentBlockHeight - lastScan; // Mettre à jour l'interface avec les informations updateSyncItem('currentBlock', currentBlockHeight.toString(), 'completed'); updateSyncItem('birthday', birthday.toString(), 'completed'); updateSyncItem('blocksToScan', blocksToScan.toString(), 'pending'); console.log(`📊 Sync info: current=${currentBlockHeight}, birthday=${birthday}, lastScan=${lastScan}, toScan=${blocksToScan}`); // Vérifier si une synchronisation est nécessaire if (blocksToScan <= 0) { console.log('✅ Wallet already synchronized'); updateStatus('✅ Wallet déjà synchronisé!', 'success'); updateProgress(100); updateSyncItem('blocksScanned', lastScan.toString(), 'completed'); updateSyncItem('blocksToScan', '0', 'completed'); continueBtn.disabled = false; return; } // Étape 5: Synchronisation réelle des blocs updateStatus('🔍 Synchronisation des blocs en cours...', 'loading'); updateProgress(60); console.log(`🔄 Starting real block scan from ${lastScan} to ${currentBlockHeight}...`); // Utiliser updateDeviceBlockHeight qui gère la synchronisation si nécessaire // Cette méthode vérifie si last_scan < currentBlockHeight et synchronise si nécessaire try { await services.updateDeviceBlockHeight(); console.log('✅ Block scan completed successfully'); // Vérifier que la mise à jour a été sauvegardée const finalWallet = await services.getDeviceFromDatabase(); if (finalWallet?.sp_wallet?.last_scan) { const finalLastScan = finalWallet.sp_wallet.last_scan; console.log('✅ Wallet updated with last_scan:', finalLastScan); // Finalisation updateStatus('✅ Synchronisation terminée avec succès!', 'success'); updateProgress(100); updateSyncItem('blocksScanned', finalLastScan.toString(), 'completed'); updateSyncItem('blocksToScan', blocksToScan.toString(), 'completed'); // Activer le bouton continuer if (continueBtn) { continueBtn.disabled = false; } console.log('🎉 Block sync completed successfully'); } else { throw new Error('Failed to verify wallet update - last_scan not found'); } } catch (error) { console.error('❌ Error during block scan:', error); throw error; } } catch (error) { console.error('❌ Error during block sync:', error); const errorMessage = (error as Error).message; updateStatus(`❌ Erreur: ${errorMessage}`, 'error'); // Si l'erreur est liée aux prérequis, rediriger vers la page appropriée if (errorMessage.includes('PBKDF2') || errorMessage.includes('security')) { console.log('⚠️ Security error detected, redirecting to security-setup...'); updateStatus('⚠️ Redirection vers la configuration de sécurité...', 'loading'); setTimeout(() => { window.location.href = '/src/pages/security-setup/security-setup.html'; }, 2000); } else if (errorMessage.includes('wallet') || errorMessage.includes('device')) { console.log('⚠️ Wallet error detected, redirecting to wallet-setup...'); updateStatus('⚠️ Redirection vers la configuration du wallet...', 'loading'); setTimeout(() => { window.location.href = '/src/pages/wallet-setup/wallet-setup.html'; }, 2000); } else if (errorMessage.includes('birthday')) { console.log('⚠️ Birthday error detected, redirecting to birthday-setup...'); updateStatus('⚠️ Redirection vers la configuration de la date anniversaire...', 'loading'); setTimeout(() => { window.location.href = '/src/pages/birthday-setup/birthday-setup.html'; }, 2000); } else { // Erreur générale, afficher et permettre de réessayer updateSyncItem('currentBlock', 'Erreur', 'error'); updateSyncItem('birthday', 'Erreur', 'error'); updateSyncItem('blocksToScan', 'Erreur', 'error'); } } });