Esta guía explica cómo consultar datos históricos de la cadena Monad a través de RPC, cubriendo el comportamiento de nodos de archivo vs completos, los métodos JSON-RPC para lecturas históricas y un script práctico de ethers para paginar eth_getLogs. También cubre fallos comunes y compensaciones, y recomienda proveedores de archivo gestionados para historial profundo.
Respuesta Directa: Cómo Consultar Datos Históricos de Monad
Para consultar datos históricos de Monad a través de RPC, necesitas un endpoint que conserve el estado y los registros históricos. Un nodo completo estándar solo mantiene el estado reciente (podado), por lo que para lecturas en números de bloque antiguos—como eth_getBalance en el bloque 1,000,000 o eth_getLogs en un rango amplio—debes usar una fuente con capacidad de archivo. Monad es compatible con EVM, por lo que usas los mismos métodos JSON-RPC que en Ethereum, pero con el tiempo de bloque de sub-segundo de Monad, el número de bloques crece rápidamente, haciendo esencial una paginación eficiente.
Este artículo es el compañero específico de Monad de la guía general de OnFinality Learn sobre acceso a datos históricos de blockchain. Cubriremos los tipos de nodos, los métodos RPC exactos y un script ejecutable para obtener registros históricos de manera confiable.
Nodos Completos de Monad vs Nodos de Archivo: Qué se Conserva
La documentación de Monad distingue entre nodos completos y nodos de archivo. Un nodo completo típicamente poda el estado histórico, conservando solo el estado reciente (por ejemplo, los últimos 128 bloques, pero esto es específico de la implementación y no está documentado como un número fijo). Un nodo de archivo conserva todo el estado histórico, permitiendo consultas en cualquier bloque pasado. Para registros, ambos tipos de nodos pueden servir eth_getLogs, pero la disponibilidad de registros antiguos depende de la política de retención del nodo; algunos proveedores pueden podar registros en nodos completos.
La documentación oficial de Monad hace la misma distinción entre completo y archivo y señala que el estado histórico se sirve desde fuentes de archivo (ver la visión general de JSON-RPC de Monad y la documentación de nodo/archivo de Monad referenciada desde allí); no especifica ventanas de retención exactas. Como regla, si necesitas estado en un bloque antiguo específico (por ejemplo, un saldo de token en el bloque N), necesitas una fuente con capacidad de archivo. Para registros, es posible que puedas consultar historial reciente en un nodo completo, pero para retrocesos profundos, una fuente de archivo es más segura.
Debido a que Monad utiliza ejecución diferida y ejecución paralela, la producción de bloques es rápida—sub-segundo. Esto significa miles de bloques por hora. Una consulta de registros en una ventana de 1 día podría abarcar más de 100,000 bloques, lo que puede abrumar a un nodo si no se pagina. Siempre verifica la documentación del proveedor para retención y límites de velocidad; estos son específicos del proveedor y no están estandarizados.
- Nodo completo: conserva solo el estado reciente; adecuado para lecturas actuales y registros recientes.
- Nodo de archivo: conserva todo el estado histórico; requerido para eth_call, eth_getBalance, eth_getCode en bloques antiguos.
- Registros: pueden estar disponibles en nodos completos por una ventana limitada; los nodos de archivo típicamente conservan todos los registros.
- El tiempo de bloque rápido de Monad significa que los rangos históricos son grandes; planifica la paginación en consecuencia.
Métodos JSON-RPC para Lecturas Históricas
Monad soporta métodos JSON-RPC estándar de Ethereum. Para datos históricos, los métodos clave son:
eth_getBlockByNumber: Obtiene un bloque por número, incluyendo transacciones completas si se solicita. Usa la etiqueta de bloque 'earliest' o un número de bloque hexadecimal.
eth_getLogs: Filtra registros por dirección y temas en un rango de bloques. Este es el método principal para datos de eventos históricos.
eth_call: Ejecuta una llamada en un bloque específico para leer el estado del contrato (por ejemplo, balanceOf). Requiere nodo de archivo para bloques antiguos.
eth_getBalance, eth_getCode, eth_getStorageAt: Lee el estado de la cuenta en una etiqueta de bloque dada.
eth_getProof: Obtiene una prueba de cuenta y almacenamiento en un bloque específico, útil para verificación sin confianza.
- Etiquetas de bloque: 'latest', 'earliest', 'pending', o un número de bloque hexadecimal.
- Para eth_getLogs, fromBlock y toBlock son obligatorios; usa hexadecimal o etiquetas.
- eth_call acepta un parámetro de bloque; usa un número de bloque hexadecimal para estado histórico.
- eth_getProof está disponible en nodos de archivo y se puede usar para verificación cruzada.
Ejemplo Práctico: Paginando eth_getLogs con ethers.js
A continuación se muestra un script Node.js autónomo que pagina eth_getLogs a lo largo de un rango, manejando tiempos de espera y retroceso. Reemplaza RPC_URL con tu propio endpoint (por ejemplo, de endpoints RPC de Monad). El script obtiene registros en fragmentos de 10,000 bloques e imprime el recuento y un registro de muestra.
El script usa ethers v6 e incluye un reintento simple con retroceso exponencial en errores 429 o de tiempo de espera. También registra el progreso para que puedas monitorear retrocesos largos.
// Requiere Node.js 18+ y ethers v6: npm install ethers
const { ethers } = require('ethers');
const RPC_URL = process.env.RPC_URL || 'https://rpc.monad.xyz'; // Reemplaza con tu endpoint
const provider = new ethers.JsonRpcProvider(RPC_URL);
// Configuración
const CONTRACT_ADDRESS = '0x...'; // Opcional: filtra por dirección de contrato
const FROM_BLOCK = 1_000_000; // Bloque inicial (hex o número)
const TO_BLOCK = 1_100_000; // Bloque final
const CHUNK_SIZE = 10_000; // Bloques por solicitud
const MAX_RETRIES = 5;
const BASE_DELAY = 1000; // ms
async function getLogsWithRetry(filter) {
for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {
try {
return await provider.getLogs(filter);
} catch (error) {
if (error.code === 'SERVER_ERROR' || error.code === 'TIMEOUT' || error.code === 429) {
const delay = BASE_DELAY * Math.pow(2, attempt);
console.log(`Reintento ${attempt + 1} después de ${delay}ms: ${error.message}`);
await new Promise(resolve => setTimeout(resolve, delay));
} else {
throw error;
}
}
}
throw new Error('Máximo de reintentos excedido');
}
async function main() {
const allLogs = [];
let from = FROM_BLOCK;
while (from <= TO_BLOCK) {
const to = Math.min(from + CHUNK_SIZE - 1, TO_BLOCK);
console.log(`Obteniendo registros de ${from} a ${to}...`);
const filter = {
fromBlock: from,
toBlock: to,
address: CONTRACT_ADDRESS || undefined,
};
const logs = await getLogsWithRetry(filter);
allLogs.push(...logs);
console.log(`Encontrados ${logs.length} registros en este fragmento.`);
from = to + 1;
}
console.log(`Total de registros obtenidos: ${allLogs.length}`);
if (allLogs.length > 0) {
console.log('Registro de muestra:', JSON.stringify(allLogs[0], null, 2));
}
}
main().catch(console.error);Salida Esperada y Verificación
Cuando ejecutes el script, verás líneas de progreso y un recuento final. El registro de muestra mostrará la estructura estándar de registro de Ethereum: dirección, temas, datos, blockNumber, transactionHash, etc. Usa esto para verificar tu consulta.
Para verificar la corrección, puedes contrastar con un evento conocido. Por ejemplo, si estás consultando una transferencia de token, puedes comparar el recuento total con la lista de eventos de un explorador de bloques para el mismo rango. Ten en cuenta que los exploradores de bloques pueden tener indexación diferente, por lo que son posibles discrepancias menores.
Completa la tabla a continuación con tus resultados para documentar el comportamiento de tu endpoint.
| Rango de Fragmento | Recuento de Registros | Tiempo Tomado (s) | Errores/Reintentos |
|-------------|------------|----------------|----------------|
| 1,000,000-1,010,000 | ... | ... | ... |
| 1,010,001-1,020,000 | ... | ... | ... |
| ... | ... | ... | ... |
| Total | ... | ... | ... |Fallos Comunes y Soluciones
Al consultar datos históricos en Monad, puedes encontrar varios problemas. Aquí están los más comunes y cómo resolverlos.
Error: 'header not found' o 'missing trie node' — Esto indica que el nodo no tiene el estado histórico. Necesitas un nodo de archivo. Si estás usando un endpoint público, cambia a un proveedor que ofrezca datos de archivo.
Error: 'query returned more than 10000 results' — Muchos proveedores limitan los resultados de eth_getLogs. Reduce el tamaño de tu fragmento o estrecha el rango. El script anterior usa 10,000 bloques, pero es posible que necesites bajarlo a 1,000 o incluso 100 para registros densos.
Errores de tiempo de espera — Los endpoints RPC de Monad tienen tiempos de espera documentados (ver tiempos de espera y reintentos de RPC de Monad). El script incluye lógica de reintento, pero es posible que necesites aumentar el tiempo de espera en la configuración de tu proveedor.
Límite de velocidad (HTTP 429) — Los proveedores imponen límites de velocidad por IP. El script retrocede, pero para retrocesos grandes, considera usar un endpoint dedicado o distribuir las solicitudes en el tiempo. Ver límites de velocidad y 429 de RPC de Monad.
El comportamiento del proveedor en rangos de registro grandes varía: muchas puertas de enlace JSON-RPC limitan una sola respuesta de eth_getLogs por recuento de resultados en lugar de por recuento de bloques, por lo que paginar en ventanas de bloques fijas (como en el ejemplo anterior) es el patrón seguro en cadenas de alto rendimiento como Monad.
- Usa siempre un endpoint de archivo para lecturas de estado histórico.
- Si obtienes 'result too large', reduce el tamaño del fragmento.
- Implementa retroceso exponencial para 429 y tiempos de espera.
- Consulta la documentación del proveedor para límites específicos.
Compensaciones y Limitaciones
Consultar datos históricos tiene compensaciones inherentes. Los nodos de archivo son más costosos de ejecutar y a menudo tienen mayor latencia para consultas profundas. Los nodos completos son más rápidos para datos actuales pero no pueden servir estado antiguo.
Para dApps que necesitan saldos de tokens en bloques pasados arbitrarios, debes usar un nodo de archivo. Para retrocesos de registros, a menudo puedes usar un nodo completo si el rango es reciente, pero para historial completo, el archivo es necesario.
El tiempo de bloque rápido de Monad significa que incluso unos pocos días de registros pueden ser millones de bloques. Esto hace que los retrocesos completos sean costosos en términos de llamadas RPC y tiempo. Considera usar un servicio de indexación de datos para retrocesos muy grandes, pero para rangos moderados, el script anterior funciona.
Los límites de velocidad y las políticas de retención específicos del proveedor varían. Siempre verifica la documentación del proveedor. Para una comparación de proveedores, usa el Asistente RPC o consulta la lista de proveedores RPC de Monad.
- Nodos de archivo: mayor costo, más lentos para consultas profundas, pero necesarios para estado histórico.
- Nodos completos: rápidos, pero solo estado reciente; los registros pueden ser podados.
- Rangos de registro grandes: usa paginación y considera servicios de indexación.
- Políticas del proveedor: siempre verifica retención y límites de velocidad.
Próximos Pasos y Lecturas Adicionales
Para uso en producción, considera un proveedor de RPC de archivo gestionado para evitar la sobrecarga de ejecutar un nodo de archivo tú mismo. Para seleccionar y comparar proveedores concretos de Monad (incluyendo si exponen endpoints históricos con capacidad de archivo), usa la página de Asistente RPC de endpoints RPC de Monad y la lista de proveedores RPC de Monad.
Para más sobre rendimiento y confiabilidad de RPC de Monad, consulta nuestras guías sobre latencia y optimización de RPC de Monad, tiempos de espera y reintentos de RPC de Monad y límites de velocidad y 429 de RPC de Monad. También puedes explorar la página de red principal de Monad para detalles de endpoints.
Si necesitas seleccionar un proveedor, usa el Asistente RPC para Monad para comparar opciones. Y revisa el centro de OnFinality Learn para más guías.