**Motivations :** - La page block-sync ne vérifie pas les prérequis comme les autres pages - La synchronisation est simulée au lieu d'être réelle - Il manque les vérifications de PBKDF2, wallet et birthday **Modifications :** - Ajout des vérifications de prérequis (PBKDF2 key, wallet, birthday) dans block-sync.ts - Remplacement de la synchronisation simulée par une synchronisation réelle via updateDeviceBlockHeight() - Ajout de la connexion aux relais si chain_tip n'est pas disponible - Ajout de vérifications de wallet avec retry pour gérer les problèmes de synchronisation - Ajout de la gestion d'erreur avec redirection vers les pages appropriées selon le type d'erreur - Amélioration de la gestion d'erreur avec messages clairs et redirections automatiques - Déplacement de l'écouteur du bouton continuer avant le try pour être toujours disponible - Ajout de vérifications de nullité pour les éléments DOM **Pages affectées :** - src/pages/block-sync/block-sync.ts (ajout des vérifications de prérequis et synchronisation réelle) - src/pages/home/home.ts (ajout des vérifications de prérequis pour la page de pairing)
281 lines
13 KiB
TypeScript
281 lines
13 KiB
TypeScript
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) {
|
|
console.log(`⏳ Services not ready yet (attempt ${attempts + 1}/${maxAttempts}):`, (error as Error).message);
|
|
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<void>((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');
|
|
}
|
|
}
|
|
});
|