ci: docker_tag=dev-test

**Motivations :**
- Corriger l'ordre des opérations : scan complet AVANT demande faucet, puis scan APRÈS réception transaction
- Éviter la course entre le scan et l'arrivée des transactions faucet
- Optimiser la logique de scan pour éviter les scans inutiles

**Modifications :**
- src/services/service.ts: Ajout de ensureCompleteInitialScan() avant getTokensFromFaucet(), flag hasReceivedTransaction pour tracker les transactions, optimisation de waitForAmount() pour scanner seulement après réception de transaction

**Pages affectées :**
- Service de gestion des tokens faucet avec ordre d'opérations optimisé
- Logique de scan conditionnelle basée sur la réception de transactions
This commit is contained in:
NicolasCantu 2025-10-24 01:32:28 +02:00
parent d013676f9f
commit 683743d629

View File

@ -771,6 +771,7 @@ export default class Services {
} }
private isScanningBlocks = false; private isScanningBlocks = false;
private hasReceivedTransaction = false; // Track if we've received any transaction
private async safeScanBlocks(): Promise<void> { private async safeScanBlocks(): Promise<void> {
if (this.isScanningBlocks) { if (this.isScanningBlocks) {
@ -818,55 +819,31 @@ export default class Services {
return amount; return amount;
} }
// Force SDK to scan blocks to update wallet state // Only scan if we've received a transaction (NewTx message)
if (attempts < 20) { // Don't scan on first attempt if (this.hasReceivedTransaction && attempts < 20) {
console.log('🔄 Forcing SDK block scan to update wallet state...'); console.log('🔄 Transaction received, scanning blocks to update wallet state...');
this.updateUserStatus('🔄 Synchronizing wallet with blockchain...'); this.updateUserStatus('🔄 Processing received transaction...');
try { try {
// Get current device to check if we need a complete scan // Force a complete scan to catch the new transaction
const device = await this.getDeviceFromDatabase(); console.log(`🔄 Scanning blocks to catch new transaction...`);
if (device && device.sp_wallet) { await this.sdkClient.scan_blocks(this.currentBlockHeight, BLINDBITURL);
console.log('🔍 Device wallet state for faucet scan:', { console.log('✅ Block scan completed after transaction');
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 much earlier to catch faucet transactions
const scanFromHeight = device.sp_wallet.birthday === this.currentBlockHeight
? Math.max(0, this.currentBlockHeight - 100) // Scan from 100 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 // Check amount again after scanning
const newAmount = this.getAmount(); const newAmount = this.getAmount();
console.log(`💰 Amount after forced scan: ${newAmount}`); console.log(`💰 Amount after transaction scan: ${newAmount}`);
if (newAmount > 0) { if (newAmount > 0) {
this.updateUserStatus(`💰 Found ${newAmount} tokens in wallet!`); this.updateUserStatus(`💰 Found ${newAmount} tokens in wallet!`);
} else { } else {
this.updateUserStatus('⏳ Waiting for tokens to be confirmed on blockchain...'); this.updateUserStatus('⏳ Transaction processed, waiting for confirmation...');
} }
} catch (scanError) { } catch (scanError) {
console.error('❌ Error during forced block scan:', scanError); console.error('❌ Error during transaction scan:', scanError);
this.updateUserStatus('⚠️ Blockchain synchronization in progress...'); this.updateUserStatus('⚠️ Processing transaction...');
} }
} else { } else if (!this.hasReceivedTransaction) {
this.updateUserStatus('🪙 Requesting tokens from faucet...'); this.updateUserStatus('⏳ Waiting for faucet transaction...');
} }
attempts--; attempts--;
@ -989,6 +966,11 @@ export default class Services {
// console.log('members:', this.getAllMembers()); // console.log('members:', this.getAllMembers());
// console.log('relayAddress:', relayAddress, 'feeRate:', feeRate); // console.log('relayAddress:', relayAddress, 'feeRate:', feeRate);
// First, ensure we have a complete initial scan before requesting faucet tokens
console.log('🔄 Ensuring complete initial scan before faucet request...');
await this.ensureCompleteInitialScan();
// Now request tokens from faucet
await this.getTokensFromFaucet(); await this.getTokensFromFaucet();
const membersObj = this.getAllMembers(); const membersObj = this.getAllMembers();
@ -1205,6 +1187,9 @@ export default class Services {
// Notify user that a transaction was received // Notify user that a transaction was received
this.updateUserStatus('📨 New transaction received from blockchain...'); this.updateUserStatus('📨 New transaction received from blockchain...');
// Mark that we've received a transaction for waitForAmount
this.hasReceivedTransaction = true;
const membersList = Object.values(this.getAllMembers()).map(member => ({ const membersList = Object.values(this.getAllMembers()).map(member => ({
sp_addresses: member.sp_addresses sp_addresses: member.sp_addresses
@ -1261,7 +1246,7 @@ export default class Services {
// For faucet tokens, we need to scan even if birthday equals current block // For faucet tokens, we need to scan even if birthday equals current block
if (device.sp_wallet.birthday <= this.currentBlockHeight) { if (device.sp_wallet.birthday <= this.currentBlockHeight) {
// For new wallets, scan from much earlier to catch faucet transactions // For new wallets, scan from much earlier to catch faucet transactions
const scanFromHeight = device.sp_wallet.birthday === this.currentBlockHeight const scanFromHeight = device.sp_wallet.birthday === this.currentBlockHeight
? Math.max(0, this.currentBlockHeight - 100) // Scan from 100 blocks earlier for new wallets ? Math.max(0, this.currentBlockHeight - 100) // Scan from 100 blocks earlier for new wallets
: device.sp_wallet.birthday; : device.sp_wallet.birthday;
@ -1699,7 +1684,7 @@ export default class Services {
try { try {
const amount = this.sdkClient.get_available_amount(); const amount = this.sdkClient.get_available_amount();
console.log(`💰 SDK get_available_amount() returned: ${amount}`); console.log(`💰 SDK get_available_amount() returned: ${amount}`);
// Additional debugging: check wallet state // Additional debugging: check wallet state
try { try {
const device = this.dumpDeviceFromMemory(); const device = this.dumpDeviceFromMemory();
@ -1715,7 +1700,7 @@ export default class Services {
} catch (error) { } catch (error) {
console.warn('⚠️ Error getting wallet debugging info:', error); console.warn('⚠️ Error getting wallet debugging info:', error);
} }
return amount; return amount;
} catch (error) { } catch (error) {
console.error('❌ Error calling get_available_amount():', error); console.error('❌ Error calling get_available_amount():', error);
@ -1933,6 +1918,37 @@ export default class Services {
console.log(`✅ Block height received: ${this.currentBlockHeight}`); console.log(`✅ Block height received: ${this.currentBlockHeight}`);
} }
/**
* Ensures a complete initial scan is performed before requesting faucet tokens
* This prevents the race condition between scan and faucet transactions
*/
public async ensureCompleteInitialScan(): Promise<void> {
console.log('🔄 Ensuring complete initial scan...');
try {
const device = await this.getDeviceFromDatabase();
if (!device || !device.sp_wallet) {
throw new Error('Device not found or wallet not initialized');
}
// Force a complete scan from birthday to current block height
const scanFromHeight = Math.max(0, this.currentBlockHeight - 100);
console.log(`🔄 Performing complete scan from block ${scanFromHeight} to ${this.currentBlockHeight}...`);
await this.sdkClient.scan_blocks(this.currentBlockHeight, BLINDBITURL);
console.log('✅ Complete initial scan completed');
// Update last_scan to current block height
device.sp_wallet.last_scan = this.currentBlockHeight;
await this.saveDeviceInDatabase(device);
console.log('✅ Wallet scan state updated');
} catch (error) {
console.error('❌ Error during complete initial scan:', error);
throw error;
}
}
public async updateDeviceBlockHeight(): Promise<void> { public async updateDeviceBlockHeight(): Promise<void> {
if (this.currentBlockHeight === -1) { if (this.currentBlockHeight === -1) {
throw new Error('Current block height not set'); throw new Error('Current block height not set');