/** * Script de migration des fichiers texte vers SQLite */ import Database from 'better-sqlite3'; import { readFileSync, existsSync } from 'fs'; import { join, dirname } from 'path'; import { fileURLToPath } from 'url'; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); const dbPath = join(__dirname, 'signet.db'); const db = new Database(dbPath); // Activer les clés étrangères db.pragma('foreign_keys = ON'); // Préparer les requêtes d'insertion const insertUtxo = db.prepare(` INSERT OR REPLACE INTO utxos (category, txid, vout, amount, confirmations, is_anchor_change, block_time, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP) `); const insertAnchor = db.prepare(` INSERT OR REPLACE INTO anchors (hash, txid, block_height, confirmations, date, updated_at) VALUES (?, ?, ?, ?, ?, CURRENT_TIMESTAMP) `); const insertFee = db.prepare(` INSERT OR REPLACE INTO fees (txid, fee, fee_sats, block_height, block_time, confirmations, change_address, change_amount, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP) `); const insertManyUtxos = db.transaction((utxos) => { for (const utxo of utxos) { insertUtxo.run( utxo.category, utxo.txid, utxo.vout, utxo.amount, utxo.confirmations, utxo.is_anchor_change ? 1 : 0, utxo.block_time || null ); } }); const insertManyAnchors = db.transaction((anchors) => { for (const anchor of anchors) { insertAnchor.run( anchor.hash, anchor.txid, anchor.block_height, anchor.confirmations, anchor.date ); } }); const insertManyFees = db.transaction((fees) => { for (const fee of fees) { insertFee.run( fee.txid, fee.fee, fee.fee_sats, fee.block_height, fee.block_time, fee.confirmations, fee.change_address, fee.change_amount ); } }); // Migrer utxo_list.txt console.log('📦 Migration de utxo_list.txt...'); const utxoListPath = join(__dirname, '../utxo_list.txt'); if (existsSync(utxoListPath)) { const content = readFileSync(utxoListPath, 'utf8').trim(); const lines = content.split('\n').filter(line => line.trim()); const utxos = []; for (const line of lines) { const parts = line.split(';'); if (parts.length >= 6) { let category, txid, vout, amount, confirmations, isAnchorChange, blockTime; if (parts.length === 7 && !isNaN(parseFloat(parts[3]))) { // Nouveau format: category;txid;vout;amount;confirmations;isAnchorChange;blockTime [category, txid, vout, amount, confirmations, isAnchorChange, blockTime] = parts; } else if (parts.length >= 6) { // Ancien format: category;txid;vout;address;amount;confirmations;isAnchorChange [category, txid, vout, , amount, confirmations] = parts; isAnchorChange = parts.length > 6 ? parts[6] === 'true' : false; blockTime = parts.length > 7 ? parseInt(parts[7], 10) || null : null; } utxos.push({ category: category.trim(), txid: txid.trim(), vout: parseInt(vout, 10), amount: parseFloat(amount), confirmations: parseInt(confirmations, 10) || 0, is_anchor_change: isAnchorChange === 'true' || isAnchorChange === true, block_time: blockTime ? parseInt(blockTime, 10) : null }); } } insertManyUtxos(utxos); console.log(`✅ ${utxos.length} UTXOs migrés`); } else { console.log('⚠️ utxo_list.txt non trouvé'); } // Migrer hash_list.txt console.log('📦 Migration de hash_list.txt...'); const hashListPath = join(__dirname, '../hash_list.txt'); if (existsSync(hashListPath)) { const content = readFileSync(hashListPath, 'utf8').trim(); const lines = content.split('\n').filter(line => line.trim()); const anchors = []; for (const line of lines) { const parts = line.split(';'); if (parts.length >= 2) { const [hash, txid, blockHeight, confirmations, date] = parts; anchors.push({ hash: hash.trim(), txid: txid.trim(), block_height: blockHeight ? parseInt(blockHeight, 10) : null, confirmations: confirmations ? parseInt(confirmations, 10) : 0, date: date || new Date().toISOString() }); } } insertManyAnchors(anchors); console.log(`✅ ${anchors.length} ancrages migrés`); } else { console.log('⚠️ hash_list.txt non trouvé'); } // Migrer fees_list.txt console.log('📦 Migration de fees_list.txt...'); const feesListPath = join(__dirname, '../fees_list.txt'); if (existsSync(feesListPath)) { const content = readFileSync(feesListPath, 'utf8').trim(); const lines = content.split('\n').filter(line => line.trim()); const fees = []; for (const line of lines) { const parts = line.split(';'); // Format: txid;fee;fee_sats;blockHeight;blockTime;confirmations;changeAddress;changeAmount if (parts.length >= 3) { const [txid, fee, feeSats, blockHeight, blockTime, confirmations, changeAddress, changeAmount] = parts; fees.push({ txid: txid.trim(), fee: parseFloat(fee) || 0, fee_sats: parseInt(feeSats, 10) || 0, block_height: blockHeight ? parseInt(blockHeight, 10) : null, block_time: blockTime ? parseInt(blockTime, 10) : null, confirmations: confirmations ? parseInt(confirmations, 10) : 0, change_address: changeAddress || null, change_amount: changeAmount ? parseFloat(changeAmount) : null }); } } insertManyFees(fees); console.log(`✅ ${fees.length} frais migrés`); } else { console.log('⚠️ fees_list.txt non trouvé'); } // Migrer les caches console.log('📦 Migration des caches...'); const utxoCachePath = join(__dirname, '../utxo_list_cache.txt'); if (existsSync(utxoCachePath)) { const cacheContent = readFileSync(utxoCachePath, 'utf8').trim(); const parts = cacheContent.split(';'); if (parts.length >= 2) { const insertCache = db.prepare('INSERT OR REPLACE INTO cache (key, value) VALUES (?, ?)'); insertCache.run('utxo_list_cache', cacheContent); console.log('✅ Cache UTXO migré'); } } const hashCachePath = join(__dirname, '../hash_list_cache.txt'); if (existsSync(hashCachePath)) { const cacheContent = readFileSync(hashCachePath, 'utf8').trim(); const parts = cacheContent.split(';'); if (parts.length >= 2) { const insertCache = db.prepare('INSERT OR REPLACE INTO cache (key, value) VALUES (?, ?)'); insertCache.run('hash_list_cache', cacheContent); console.log('✅ Cache hash migré'); } } console.log('\n✅ Migration terminée avec succès!'); console.log(`📁 Base de données: ${dbPath}`); // Afficher les statistiques const utxoCount = db.prepare('SELECT COUNT(*) as count FROM utxos').get(); const anchorCount = db.prepare('SELECT COUNT(*) as count FROM anchors').get(); const feeCount = db.prepare('SELECT COUNT(*) as count FROM fees').get(); console.log('\n📊 Statistiques:'); console.log(` UTXOs: ${utxoCount.count}`); console.log(` Ancrages: ${anchorCount.count}`); console.log(` Frais: ${feeCount.count}`); db.close();