feat: cero dependencias externas y caché de peticiones al nodo

Las librerías (React, Babel) venían de unpkg.com y las fuentes de Google.
Ninguno veía qué transacciones analizabas, pero ambos recibían tu IP y la hora
en cada apertura: sabían que usabas Txoko, cuándo y desde dónde — el metadato
que la propia herramienta enseña a proteger. Ahora se sirven desde el nodo,
con verificación por hash y versiones fijadas. El dashboard funciona sin
internet.

Además, caché con TTL y coalescencia en useApi: las transacciones confirmadas
son inmutables y se cachean toda la sesión, así que repetir un análisis ya
explorado no cuesta ninguna petición al nodo (medido).
This commit is contained in:
2026-07-27 13:22:08 +02:00
parent fd2e38fd45
commit 020f9318aa
5 changed files with 269 additions and 13 deletions
+79
View File
@@ -159,6 +159,85 @@ Cuatro comandos después de la descarga. Siempre los mismos.
---
## Librerías del frontend (obligatorio)
El dashboard usa React y Babel. **Se sirven desde tu propio nodo, no desde un
CDN.** El motivo es de privacidad, no de comodidad: un CDN externo no ve qué
transacciones analizas, pero sí ve que usas Txoko, cuándo y desde qué IP
pública — exactamente la clase de metadato que esta herramienta enseña a
proteger. Sirviéndolas en local, *"ninguna consulta sale de tu red"* pasa a ser
literal, y el dashboard funciona sin conexión a internet.
Estas librerías **no están en el repo** (son de terceros y pesan ~3 MB). Se
descargan una vez, en el nodo:
```bash
sudo mkdir -p /usr/share/nginx/html/vendor
cd /usr/share/nginx/html/vendor
sudo curl -sSLO https://unpkg.com/react@18.3.1/umd/react.production.min.js
sudo curl -sSLO https://unpkg.com/react-dom@18.3.1/umd/react-dom.production.min.js
sudo curl -sSL -o babel.min.js https://unpkg.com/@babel/standalone@7.23.10/babel.min.js
```
### Verifica lo que has descargado
No te fíes: comprueba que los archivos son los que deben ser.
```bash
sha256sum *.js
```
Debe dar exactamente esto:
```
85ba0c7207cf1b1850e40372f26a7e69a481457a29649b7ca19bbfce8604f30c babel.min.js
35f4f974f4b2bcd44da73963347f8952e341f83909e4498227d4e26b98f66f0d react-dom.production.min.js
d949f1c3687aedadcedac85261865f29b17cd273997e7f6b2bfc53b2f9d4c4dd react.production.min.js
```
Si algún hash no coincide, **no uses esos archivos**: significa que has
recibido algo distinto a lo esperado.
Las versiones están fijadas a propósito (`18.3.1`, `7.23.10`). Usar un rango
como `react@18` dejaría que el servidor decidiera qué versión te entrega, y
cambiaría con el tiempo sin que te enteres.
### Dónde deben quedar los archivos
El dashboard las busca en `vendor/` con **ruta relativa**, es decir, en un
subdirectorio junto al propio `dashboard.html`. Así funciona tanto si sirves el
dashboard en la raíz como bajo un prefijo, sin tocar nginx.
Con la configuración típica de Mempool self-hosted:
```nginx
location /dashboard {
alias /usr/share/nginx/html/;
}
```
…el `dashboard.html` vive en `/usr/share/nginx/html/` y las librerías deben ir
en `/usr/share/nginx/html/vendor/` — que es justo donde las deja el comando de
arriba.
**Importante:** abre el dashboard **con la barra final** (`.../dashboard/`, no
`.../dashboard`). Sin ella, el navegador resuelve las rutas relativas un nivel
por encima y no encuentra las librerías.
Para comprobar que nginx las sirve bien, lo que importa no es solo el código
200 sino el tipo de contenido:
```bash
curl -sk -o /dev/null -w '%{http_code} %{content_type}\n' \
https://localhost:4081/dashboard/vendor/react.production.min.js
```
Debe responder `200 application/javascript`. Si devuelve `200 text/html`,
nginx está entregando otra cosa (por ejemplo el index de Mempool) y las rutas
no son las correctas.
---
## HTTPS para watch-only (opcional)
La función watch-only (derivar tus direcciones desde el xpub) usa la Web Crypto