El método eth_getLogs
devuelve un array de todos los logs que coinciden con un objeto de filtro dado, permitiendo a los desarrolladores consultar datos de eventos históricos directamente sin necesidad de crear primero un filtro. Este es uno de los métodos más potentes y frecuentemente utilizados para recuperar datos de eventos de blockchain, esencial para el desarrollo de dApps y el análisis de datos blockchain.
Este método acepta un objeto de filtro con criterios para los logs a devolver y es una de las llamadas RPC más intensivas en consultas.
Objeto de opciones de filtro de logs
Número/etiqueta de bloque desde donde comenzar la búsqueda
Número/etiqueta de bloque hasta donde buscar
Dirección(es) de contrato para filtrar logs
Array de filtros de temas (firmas de eventos y parámetros indexados)
Hash del bloque del cual obtener logs (alternativa a fromBlock/toBlock)
Array de objetos log que coinciden con los criterios del filtro
Dirección desde la cual se originó este log
Array de argumentos de log indexados (hasta 4 temas)
Datos de log no indexados (codificados en hex)
Número de bloque que contiene este log (hex)
Hash de transacción que creó este log
Índice de la transacción en el bloque
Hash del bloque que contiene este log
Posición de índice de este log en el bloque
Si este log fue eliminado debido a una reorganización de la cadena
{
"jsonrpc": "2.0",
"id": 1,
"result": [
{
"address": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
"topics": [
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"0x00000000000000000000000068b3465833fb72a70ecdf485e0e4c7bd8665fc45",
"0x00000000000000000000000027182842e098f60e3d576794a5bffb0777e025d3"
],
"data": "0x000000000000000000000000000000000000000000000043e1f92f1839951800",
"blockNumber": "0x10d4f40",
"transactionHash": "0x7d5b3f1d5b32c2b6da53acaace3894412f3b1ec2384a9b8e6c1a52325e880db2",
"transactionIndex": "0xc1",
"blockHash": "0xe2ccfc7b29eb6cad4bd3e55a00275a3b05d2d5f984ef63683f115e92d213d5b2",
"logIndex": "0x5a",
"removed": false
}
]
}
Cada objeto de log devuelto contiene:
true
si el log fue eliminado debido a una reorganización de la cadenaEl parámetro topics
ofrece potentes capacidades de filtrado:
Coincidencia Simple de Tema:
"topics": ["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"]
Esto coincide con todos los eventos Transfer de ERC-20.
Coincidencia Específica de Posición (lógica AND entre posiciones):
"topics": [
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"0x000000000000000000000000abc123..."
]
Esto coincide con eventos Transfer DESDE una dirección específica.
Lógica OR Dentro de una Posición:
"topics": [
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
["0x000000000000000000000000abc123...", "0x000000000000000000000000def456..."]
]
Esto coincide con eventos Transfer DESDE cualquiera de dos direcciones.
Omitir Posiciones con null
:
"topics": [
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
null,
"0x000000000000000000000000xyz789..."
]
Esto coincide con eventos Transfer A una dirección específica (ignorando el campo FROM).
Aquí hay ejemplos completos para casos de uso comunes:
// 1. Obtener todos los eventos de transferencia ERC-20 para un token específico
async function getTokenTransfers(tokenAddress, fromBlock = '0x0', toBlock = 'latest') {
// Firma de evento Transfer: keccak256("Transfer(address,address,uint256)")
const transferEventSignature = '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef';
return await provider.send('eth_getLogs', [{
address: tokenAddress,
topics: [transferEventSignature],
fromBlock,
toBlock
}]);
}
// 2. Obtener transferencias hacia o desde una dirección de cartera específica
async function getUserTransfers(tokenAddress, userAddress, fromBlock = '0x0', toBlock = 'latest') {
const transferEventSignature = '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef';
const paddedAddress = userAddress.replace('0x', '0x000000000000000000000000');
// Array de temas para coincidir con eventos donde el usuario es remitente O receptor
return await provider.send('eth_getLogs', [{
address: tokenAddress,
topics: [
transferEventSignature,
[paddedAddress, null], // Desde usuario (OR)
[paddedAddress, null] // A usuario (OR)
],
fromBlock,
toBlock
}]);
}
// 3. Rastrear eventos de acuñación de NFT
async function getNFTMints(nftAddress, fromBlock = '0x0', toBlock = 'latest') {
// Evento Transfer desde dirección 0x0 es una acuñación
const transferEventSignature = '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef';
const zeroAddress = '0x0000000000000000000000000000000000000000000000000000000000000000';
return await provider.send('eth_getLogs', [{
address: nftAddress,
topics: [
transferEventSignature,
zeroAddress // La dirección desde es dirección cero (acuñación)
],
fromBlock,
toBlock
}]);
}
// 4. Decodificador completo para eventos de Transfer ERC-20
function decodeTransferEvent(log) {
// Analizar parámetros indexados desde temas
const from = '0x' + log.topics[1].substring(26);
const to = '0x' + log.topics[2].substring(26);
// Analizar cantidad desde el campo data
const amount = BigInt(log.data);
return {
from,
to,
amount,
blockNumber: parseInt(log.blockNumber, 16),
txHash: log.transactionHash
};
}
Para un uso eficiente de eth_getLogs
:
Limitaciones de Rango de Bloques: La mayoría de proveedores limitan el rango de bloques (por ejemplo, 2000-10000 bloques) por solicitud
Estrategia de Paginación: Para consultas grandes, paginar por rangos de bloques:
async function paginatedLogs(filter, maxBlocksPerPage = 2000) {
const fromBlock = parseInt(filter.fromBlock === 'earliest' ? '0x0' : filter.fromBlock, 16);
const latestBlock = parseInt(await provider.send('eth_blockNumber', []), 16);
const toBlock = filter.toBlock === 'latest' ? latestBlock : parseInt(filter.toBlock, 16);
let allLogs = [];
for (let i = fromBlock; i <= toBlock; i += maxBlocksPerPage) {
const pageToBlock = Math.min(i + maxBlocksPerPage - 1, toBlock);
const pageFilter = {
...filter,
fromBlock: '0x' + i.toString(16),
toBlock: '0x' + pageToBlock.toString(16)
};
const logs = await provider.send('eth_getLogs', [pageFilter]);
allLogs = allLogs.concat(logs);
}
return allLogs;
}
Especificidad de Temas: Los filtros de temas más específicos reducen la transferencia de datos y el tiempo de procesamiento
Filtrado de Direcciones: Consultar un solo contrato es más eficiente que múltiples contratos
Optimización de Proveedor: Algunos proveedores como Infura tienen endpoints especializados para consultas de logs
Limitación de Tasas: Este método a menudo tiene límites de tasa más estrictos y puede contar como múltiples solicitudes
Caché: Considere almacenar en caché resultados para datos históricos accedidos con frecuencia
Nodos de Archivo: Algunas consultas pueden requerir nodos de archivo en lugar de nodos completos
Aquí hay firmas de eventos frecuentemente utilizadas para filtrado:
0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef
0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925
0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef
(igual que ERC-20)0xd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822
0xc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62
0x4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb