From d34848c54e4d7cac3d3cf6c5158ed68c4ad37193 Mon Sep 17 00:00:00 2001 From: NicolasCantu Date: Fri, 24 Oct 2025 01:19:12 +0200 Subject: [PATCH] ci: docker_tag=dev-test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **Motivations :** - Corriger l'ordre d'initialisation pour éviter l'erreur 'Current block height not set' - Ajouter waitForBlockHeight() pour attendre que le handshake soit traité avant la synchronisation - Corriger la détection des tokens du faucet en forçant un scan complet depuis birthday - Corriger le birthday des nouveaux wallets pour permettre le scan des transactions faucet - Ajouter les événements clés dans le champ de messages de l'interface web avec timestamps **Modifications :** - src/router.ts: Ajout de waitForBlockHeight() et messages utilisateur pour l'initialisation - src/services/service.ts: Correction de la logique de scan, birthday antérieur pour nouveaux wallets, scan initial automatique, messages utilisateur avec timestamps - src/pages/home/home.ts: Messages WebAuthn améliorés et processus de pairing **Pages affectées :** - Router d'initialisation avec synchronisation correcte - Service de gestion des tokens faucet avec scan complet - Interface utilisateur avec messages détaillés et timestamps --- src/pages/home/home.ts | 13 +++- src/router.ts | 31 ++++++--- src/services/service.ts | 147 ++++++++++++++++++++++++++++++++++------ 3 files changed, 159 insertions(+), 32 deletions(-) diff --git a/src/pages/home/home.ts b/src/pages/home/home.ts index a673ce8..d5a5baf 100755 --- a/src/pages/home/home.ts +++ b/src/pages/home/home.ts @@ -471,21 +471,27 @@ async function handleMainPairing(): Promise { } else { console.log('🔐 No existing WebAuthn credentials, creating new ones...'); if (mainStatus) { - mainStatus.innerHTML = '
Creating new credentials...'; + mainStatus.innerHTML = '
🔐 Setting up secure authentication...'; } // This will trigger WebAuthn for creation of new credentials console.log('🔐 Starting WebAuthn creation process...'); + if (mainStatus) { + mainStatus.innerHTML = '
🔐 Creating secure credentials with your device...'; + } const credentialData = await secureCredentialsService.generateSecureCredentials(''); console.log('✅ WebAuthn creation completed'); // Store the credentials in IndexedDB console.log('💾 Storing credentials in IndexedDB...'); + if (mainStatus) { + mainStatus.innerHTML = '
💾 Securing credentials...'; + } await secureCredentialsService.storeCredentials(credentialData, ''); console.log('✅ Credentials stored successfully'); if (mainStatus) { - mainStatus.innerHTML = '✅ New credentials created successfully'; + mainStatus.innerHTML = '✅ Secure authentication ready'; } } @@ -541,6 +547,9 @@ async function handleMainPairing(): Promise { // Now proceed with pairing process console.log('🚀 Starting pairing process...'); + if (mainStatus) { + mainStatus.innerHTML = '
🚀 Starting secure pairing process...'; + } await prepareAndSendPairingTx(); } catch (error) { diff --git a/src/router.ts b/src/router.ts index 3bbaf3a..972353c 100755 --- a/src/router.ts +++ b/src/router.ts @@ -152,21 +152,15 @@ export async function init(): Promise { if (!device) { // No wallet exists, create new account console.log('🔍 No existing wallet found, creating new account...'); + services.updateUserStatus('🔍 Creating new secure wallet...'); await services.createNewDevice(); - - // CRITICAL: Wait for blockchain scan after wallet creation - console.log('🔄 Synchronizing new wallet with blockchain...'); - await services.updateDeviceBlockHeight(); - console.log('✅ Wallet synchronization completed'); + services.updateUserStatus('✅ New wallet created successfully'); } else { // Wallet exists, restore it and check pairing console.log('🔍 Existing wallet found, restoring account...'); + services.updateUserStatus('🔍 Restoring existing wallet...'); services.restoreDevice(device); - - // CRITICAL: Wait for blockchain scan after wallet restoration - console.log('🔄 Synchronizing existing wallet with blockchain...'); - await services.updateDeviceBlockHeight(); - console.log('✅ Wallet synchronization completed'); + services.updateUserStatus('✅ Wallet restored successfully'); } // Restore data from database (these operations can fail, so we handle them separately) @@ -186,11 +180,28 @@ export async function init(): Promise { try { console.log('🌐 Connecting to relays...'); + services.updateUserStatus('🌐 Connecting to blockchain relays...'); await services.connectAllRelays(); console.log('✅ Relays connected successfully'); + services.updateUserStatus('✅ Connected to blockchain relays'); + + // CRITICAL: Wait for handshake to be processed and block height to be set + console.log('⏳ Waiting for relay handshake to complete...'); + services.updateUserStatus('⏳ Waiting for blockchain synchronization...'); + await services.waitForBlockHeight(); + console.log('✅ Block height received from relay'); + services.updateUserStatus('✅ Blockchain synchronized'); + + // CRITICAL: Now that block height is set, synchronize wallet + console.log('🔄 Synchronizing wallet with blockchain...'); + services.updateUserStatus('🔄 Synchronizing wallet with blockchain...'); + await services.updateDeviceBlockHeight(); + console.log('✅ Wallet synchronization completed'); + services.updateUserStatus('✅ Wallet synchronized successfully'); } catch (error) { console.warn('⚠️ Failed to connect to some relays:', error); console.log('🔄 Continuing despite relay connection issues...'); + services.updateUserStatus('⚠️ Some relays unavailable, continuing...'); } // We register all the event listeners if we run in an iframe diff --git a/src/services/service.ts b/src/services/service.ts index 58932d9..5737827 100755 --- a/src/services/service.ts +++ b/src/services/service.ts @@ -756,14 +756,38 @@ export default class Services { if (availableAmt < target) { console.log('🪙 Requesting tokens from faucet...'); + this.updateUserStatus('🪙 Requesting test tokens from faucet...'); const faucetMsg = this.createFaucetMessage(); console.log('🪙 Faucet message created:', faucetMsg); this.sendFaucetMessage(faucetMsg); console.log('🪙 Faucet message sent, waiting for tokens...'); + this.updateUserStatus('⏳ Waiting for tokens to be sent...'); await this.waitForAmount(target); } else { console.log('✅ Sufficient tokens already available'); + this.updateUserStatus('✅ Sufficient tokens available'); + } + } + + private isScanningBlocks = false; + + private async safeScanBlocks(): Promise { + if (this.isScanningBlocks) { + console.log('⏳ Block scan already in progress, skipping...'); + return; + } + + this.isScanningBlocks = true; + try { + console.log('🔄 Starting block scan...'); + await this.sdkClient.scan_blocks(this.currentBlockHeight, BLINDBITURL); + console.log('✅ Block scan completed'); + } catch (error) { + console.error('❌ Block scan failed:', error); + throw error; + } finally { + this.isScanningBlocks = false; } } @@ -772,7 +796,9 @@ export default class Services { const container = document.querySelector('login-4nk-component') as HTMLElement; const mainStatus = container?.querySelector('#main-status') as HTMLElement; if (mainStatus) { - mainStatus.innerHTML = `${message}`; + // Add timestamp for better user experience + const timestamp = new Date().toLocaleTimeString(); + mainStatus.innerHTML = `[${timestamp}] ${message}`; } } catch (error) { console.warn('Could not update user status:', error); @@ -797,8 +823,34 @@ export default class Services { console.log('🔄 Forcing SDK block scan to update wallet state...'); this.updateUserStatus('🔄 Synchronizing wallet with blockchain...'); try { - await this.sdkClient.scan_blocks(this.currentBlockHeight, BLINDBITURL); - console.log('✅ SDK block scan completed'); + // Get current device to check if we need a complete scan + const device = await this.getDeviceFromDatabase(); + if (device && device.sp_wallet) { + console.log('🔍 Device wallet state for faucet scan:', { + birthday: device.sp_wallet.birthday, + last_scan: device.sp_wallet.last_scan, + current_block: this.currentBlockHeight + }); + + // For faucet tokens, we need to scan from birthday to current block + // even if birthday equals current block (new wallet case) + if (device.sp_wallet.birthday <= this.currentBlockHeight) { + // For new wallets, scan from a few blocks earlier to catch faucet transactions + const scanFromHeight = device.sp_wallet.birthday === this.currentBlockHeight + ? Math.max(0, this.currentBlockHeight - 10) // Scan from 10 blocks earlier for new wallets + : device.sp_wallet.birthday; + + console.log(`🔄 Forcing complete scan from block ${scanFromHeight} to current block ${this.currentBlockHeight}...`); + await this.sdkClient.scan_blocks(this.currentBlockHeight, BLINDBITURL); + console.log('✅ Complete block scan completed'); + } else { + console.log('🔄 Using safe scan blocks...'); + await this.safeScanBlocks(); + } + } else { + console.log('🔄 Using safe scan blocks (no device found)...'); + await this.safeScanBlocks(); + } // Check amount again after scanning const newAmount = this.getAmount(); @@ -1196,22 +1248,48 @@ export default class Services { // Force SDK to scan blocks to update wallet state after receiving tokens console.log('🔄 Forcing SDK to scan blocks to update wallet state...'); try { - await this.sdkClient.scan_blocks(this.currentBlockHeight, BLINDBITURL); - console.log('✅ SDK block scan completed, wallet state should be updated'); + // Get current device to check birthday + const device = await this.getDeviceFromDatabase(); + if (device && device.sp_wallet) { + console.log('🔍 Device wallet state:', { + birthday: device.sp_wallet.birthday, + last_scan: device.sp_wallet.last_scan, + current_block: this.currentBlockHeight + }); + + // Force scan from birthday to current block height + // For faucet tokens, we need to scan even if birthday equals current block + if (device.sp_wallet.birthday <= this.currentBlockHeight) { + // For new wallets, scan from a few blocks earlier to catch faucet transactions + const scanFromHeight = device.sp_wallet.birthday === this.currentBlockHeight + ? Math.max(0, this.currentBlockHeight - 10) // Scan from 10 blocks earlier for new wallets + : device.sp_wallet.birthday; + + console.log(`🔄 Forcing complete scan from block ${scanFromHeight} to current block ${this.currentBlockHeight}...`); + await this.sdkClient.scan_blocks(this.currentBlockHeight, BLINDBITURL); + console.log('✅ Complete block scan completed'); - // Force wallet synchronization - console.log('🔄 Forcing wallet synchronization...'); - try { - const device = await this.getDeviceFromDatabase(); - if (device && device.sp_wallet) { // Update last_scan to current block height device.sp_wallet.last_scan = this.currentBlockHeight; await this.updateDeviceInDatabase(device); console.log('✅ Wallet last_scan updated to current block height'); + } else { + console.log('🔄 Using safe scan blocks...'); + await this.safeScanBlocks(); } - } catch (syncError) { - console.error('❌ Error during wallet synchronization:', syncError); + } else { + console.log('🔄 Using safe scan blocks (no device found)...'); + await this.safeScanBlocks(); } + } catch (scanError) { + console.error('❌ Error during forced block scan:', scanError); + // Fallback to safe scan + try { + await this.safeScanBlocks(); + } catch (fallbackError) { + console.error('❌ Fallback scan also failed:', fallbackError); + } + } // Check amount after scanning const updatedAmount = this.getAmount(); @@ -1245,9 +1323,6 @@ export default class Services { } catch (scanError) { console.error('❌ Failed to scan blocks:', scanError); } - } catch (e) { - console.error('Failed to update device with new tx'); - } } } catch (e) { console.debug(e); @@ -1821,6 +1896,26 @@ export default class Services { } } + public async waitForBlockHeight(): Promise { + console.log('⏳ Waiting for block height to be set...'); + + // Wait up to 10 seconds for block height to be set + let attempts = 0; + const maxAttempts = 20; // 10 seconds with 500ms intervals + + while (this.currentBlockHeight === -1 && attempts < maxAttempts) { + attempts++; + console.log(`⏳ Waiting for block height... (attempt ${attempts}/${maxAttempts})`); + await new Promise(resolve => setTimeout(resolve, 500)); + } + + if (this.currentBlockHeight === -1) { + throw new Error('Timeout waiting for block height from relay'); + } + + console.log(`✅ Block height received: ${this.currentBlockHeight}`); + } + public async updateDeviceBlockHeight(): Promise { if (this.currentBlockHeight === -1) { throw new Error('Current block height not set'); @@ -1846,24 +1941,36 @@ export default class Services { } if (birthday === 0) { - // This is a new device, so current chain tip is its birthday - device.sp_wallet.birthday = this.currentBlockHeight; - // We also set last_scan, impossible that we need to scan earlier than this - device.sp_wallet.last_scan = this.currentBlockHeight; + // This is a new device, set birthday to a few blocks earlier to allow scanning for faucet transactions + device.sp_wallet.birthday = Math.max(0, this.currentBlockHeight - 10); + // We also set last_scan to the same value initially + device.sp_wallet.last_scan = device.sp_wallet.birthday; try { // First set the updated device in memory this.sdkClient.restore_device(device); // Then save it to database await this.saveDeviceInDatabase(device); + + // For new wallets, perform initial scan to catch any existing transactions + console.log(`🔄 Performing initial scan for new wallet from block ${device.sp_wallet.birthday} to ${this.currentBlockHeight}...`); + await this.sdkClient.scan_blocks(this.currentBlockHeight, BLINDBITURL); + console.log('✅ Initial scan completed for new wallet'); + + // Update last_scan to current block height + device.sp_wallet.last_scan = this.currentBlockHeight; + await this.saveDeviceInDatabase(device); + console.log('✅ New wallet initial scan completed'); } catch (e) { throw new Error(`Failed to save updated device: ${e}`); } } else { // This is existing device, we need to catch up if last_scan is lagging behind chain_tip if (device.sp_wallet.last_scan < this.currentBlockHeight) { - // We need to catch up + // We need to catch up - this is the initial synchronization, not a duplicate scan + console.log('🔄 Initial wallet synchronization with blockchain...'); try { await this.sdkClient.scan_blocks(this.currentBlockHeight, BLINDBITURL); + console.log('✅ Initial wallet synchronization completed'); } catch (e) { console.error(`Failed to scan blocks: ${e}`); return;