anchorage_layer_simple/data/migrate-from-files.js
ncantu 8208809f03 UserWallet login flow, website-skeleton contract verify, data init/migrate
**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
2026-01-28 01:20:43 +01:00

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();