ncantu cad73cb265 UTXO-list: dates/blockTime historiques, récupération frais depuis ancrages, diagnostic Bloc Rewards
**Motivations:**
- Ajouter dates manquantes dans hash_list.txt et compléter historique
- Compléter blockTime manquants dans utxo_list.txt et compléter historique
- Récupérer frais depuis transactions d'ancrage (OP_RETURN) et les stocker
- Bouton UI pour déclencher récupération frais
- Diagnostic Bloc Rewards (pourquoi ~4700 BTC au lieu de 50 BTC)

**Root causes:**
- hash_list.txt sans date (format ancien)
- utxo_list.txt blockTime souvent vide
- Frais absents du fichier (métadonnées OP_RETURN non stockées)
- Pas de moyen de récupérer/compléter frais depuis UI

**Correctifs:**
- hash_list.txt : format étendu avec date (rétrocompatible)
- utxo_list.txt : blockTime complété automatiquement lors écritures
- fees_list.txt : nouveau fichier pour stocker frais
- updateFeesFromAnchors() : récupère frais depuis OP_RETURN ancrages
- Endpoint /api/utxo/fees/update pour déclencher récupération
- Bouton "Récupérer les frais depuis les ancrages" dans section Frais (spinner)
- Scripts batch : complete-hash-list-dates.js, complete-utxo-list-blocktime.js
- Script diagnostic : diagnose-bloc-rewards.js (subsidy, coinbase, listunspent)

**Evolutions:**
- Frais chargés depuis fees_list.txt dans getUtxoList
- Complétion automatique dates/blockTime lors écritures futures

**Pages affectées:**
- signet-dashboard/src/bitcoin-rpc.js
- signet-dashboard/src/server.js
- signet-dashboard/public/utxo-list.html
- scripts/complete-hash-list-dates.js
- scripts/complete-utxo-list-blocktime.js
- scripts/diagnose-bloc-rewards.js
- features/utxo-list-fees-update-and-historical-completion.md
2026-01-26 01:59:46 +01:00

122 lines
3.5 KiB
TypeScript

import { useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import { getStoredRelays, storeRelays, testRelay } from '../utils/relay';
import type { RelayConfig } from '../types/identity';
export function RelaySettingsScreen(): JSX.Element {
const navigate = useNavigate();
const [relays, setRelays] = useState<RelayConfig[]>([]);
const [newEndpoint, setNewEndpoint] = useState('');
const [testing, setTesting] = useState<string | null>(null);
useEffect(() => {
setRelays(getStoredRelays());
}, []);
const handleAdd = (): void => {
if (newEndpoint.trim() === '') {
return;
}
const newRelay: RelayConfig = {
endpoint: newEndpoint.trim(),
priority: relays.length,
enabled: true,
};
const updated = [...relays, newRelay];
setRelays(updated);
storeRelays(updated);
setNewEndpoint('');
};
const handleRemove = (index: number): void => {
const updated = relays.filter((_, i) => i !== index);
setRelays(updated);
storeRelays(updated);
};
const handleToggle = (index: number): void => {
const updated = [...relays];
updated[index] = { ...updated[index]!, enabled: !updated[index]!.enabled };
setRelays(updated);
storeRelays(updated);
};
const handleTest = async (endpoint: string): Promise<void> => {
setTesting(endpoint);
const isOk = await testRelay(endpoint);
setTesting(null);
if (isOk) {
alert('Relais accessible');
} else {
alert('Relais inaccessible');
}
};
return (
<main>
<h1>Réglages relais</h1>
<section aria-labelledby="relays-list">
<h2 id="relays-list">Liste des relais</h2>
{relays.length === 0 ? (
<p>Aucun relais configuré</p>
) : (
<ul role="list">
{relays.map((relay, index) => (
<li key={index}>
<div>
<input
type="checkbox"
checked={relay.enabled}
onChange={() => {
handleToggle(index);
}}
aria-label={`Activer ${relay.endpoint}`}
/>
<span>{relay.endpoint}</span>
<button
onClick={() => {
handleTest(relay.endpoint);
}}
disabled={testing === relay.endpoint}
>
{testing === relay.endpoint ? 'Test...' : 'Tester'}
</button>
<button
onClick={() => {
handleRemove(index);
}}
>
Supprimer
</button>
</div>
</li>
))}
</ul>
)}
</section>
<section aria-labelledby="add-relay">
<h2 id="add-relay">Ajouter un relais</h2>
<div>
<input
type="text"
value={newEndpoint}
onChange={(e) => {
setNewEndpoint(e.target.value);
}}
placeholder="http://relay.example.com:3019"
onKeyDown={(e) => {
if (e.key === 'Enter') {
handleAdd();
}
}}
/>
<button onClick={handleAdd}>Ajouter</button>
</div>
</section>
<div>
<button onClick={() => navigate('/')}>Retour</button>
</div>
</main>
);
}