**Motivations:** - Parcours login contrat: sélection service → membre → build path → proof, vérification côté parent (service-login-verify) - Scripts data: initialisation SQLite (utxos, anchors, fees), migration depuis fichiers, sync UTXOs - Website-skeleton: intégration contrat, extraction validateurs login, vérification preuve **Root causes:** - N/A (évolutions) **Correctifs:** - N/A **Evolutions:** - UserWallet: MemberSelectionScreen, LoginScreen machine à états (S_LOGIN_SELECT_SERVICE → S_LOGIN_SELECT_MEMBER → build path), service/membre via query params, useChannel/iframeChannel - Website-skeleton: contract.ts (extractLoginValidators, isValidContract, isValidAction), main.ts validateurs depuis contrat, config étendu - Data: init-db.js (tables utxos/anchors/fees), migrate-from-files.js **Pages affectées:** - data/init-db.js, data/migrate-from-files.js, data/sync-utxos.log - userwallet: App, LoginCollectShare, LoginScreen, MemberSelectionScreen, ServiceListScreen, useChannel, iframeChannel - website-skeleton: README, config, contract, main
218 lines
7.0 KiB
JavaScript
218 lines
7.0 KiB
JavaScript
/**
|
|
* 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();
|