Docs
Docs
Home
Getting Started
Agent Tooling
CLI
Supported Chains
Acala
Aptos
Arbitrum
Arc
Asset Hub
Astar
Avalanche
Base
Berachain
Bifrost
Binance Smart Chain
Bittensor
Blast
Boba Network
Bridge Hub
Celo
Centrifuge
Chiliz
Cronos
Enjin
Ethereum
Etherlink
Flow EVM Gateway
Gnosis
Hydration
Hyperliquid
Immutable
Ink
IoTeX
Kusama
Linea
LISK
Manta Atlantic
Manta Pacific
Mantle
MegaETH
Monad
Movement
Neuroweb
opBNB
Optimism
Plasma
Polkadot
Polygon
Pulsechain
Robinhood
Ronin
Scroll
Sonic
Starknet
Taiko
Tempo
Sui
TRON
Unichain
Viction
World Chain
XDC Network
XX Network
Zetachain
zkSync Era
Zora
Supported ChainsZetachainJSON-RPC APISmart Contract Methods

eth_getFilterLogs - Zetachain RPC Method

Returns all logs matching a previously created filter on Zetachain. Essential for initial log retrieval, backfilling event data, and one-time historical queries for omnichain DeFi, native Bitcoin smart contracts, cross-chain asset management, and unified liquidity aggregation.

Zetachain RPC endpoint: endpoint URLs, plans and pricing.

Returns an array of all logs matching the filter that was previously created with eth_newFilter on Zetachain. Unlike eth_getFilterChanges which returns only new logs since the last poll, this method returns the complete set of matching logs for the filter's block range.

Why Zetachain? Build on the universal omnichain blockchain enabling cross-chain smart contracts across 50+ chains including Bitcoin with native Bitcoin support, 50+ chain interoperability via UNISON, no bridging required, and partnerships with Curve and SushiSwap.

When to Use This Method

eth_getFilterLogs is essential for cross-chain dApp developers, Bitcoin DeFi builders, and teams requiring native multi-chain interoperability:

  • Initial Log Retrieval - Fetch the complete set of matching logs when you first create a filter on Zetachain
  • Backfilling Event Data - Recover historical events after an indexer restart or gap in polling
  • One-Time Queries - Retrieve all logs for a specific block range without incremental polling
  • Data Reconciliation - Compare against incrementally collected data from eth_getFilterChanges to detect missed events

Best Practices

  • Prefer eth_getLogs for most use cases; this method is designed for filters created with eth_newFilter
  • Results are subject to node log retention limits; historical queries may return incomplete data
  • Always call eth_uninstallFilter after retrieving logs to free filter resources
JSON-RPC request
{
  "jsonrpc": "2.0",
  "method": "eth_getFilterLogs",
  "params": ["0x1a"],
  "id": 1
}

Code Examples

Common Use Cases

1. Backfill Event Data After Indexer Restart

Recover missed events when your indexer goes down and comes back:

JavaScript
async function backfillEvents(provider, contractAddress, topics, lastProcessedBlock) {
  const currentBlock = await provider.getBlockNumber();

  // Create a filter covering the gap
  const filterId = await provider.send('eth_newFilter', [{
    fromBlock: '0x' + (lastProcessedBlock + 1).toString(16),
    toBlock: '0x' + currentBlock.toString(16),
    address: contractAddress,
    topics: topics
  }]);

  // Retrieve all logs in the gap
  const logs = await provider.send('eth_getFilterLogs', [filterId]);
  console.log(`Backfilling ${logs.length} events from blocks ${lastProcessedBlock + 1} to ${currentBlock}`);

  for (const log of logs) {
    await processEvent(log);
  }

  // Clean up and switch to incremental polling
  await provider.send('eth_uninstallFilter', [filterId]);
  return currentBlock;
}

2. Compare Filter Results with Direct Query

Verify data consistency between filter-based and direct log queries:

JavaScript
async function verifyFilterResults(provider, filterParams) {
  // Create filter and get logs via eth_getFilterLogs
  const filterId = await provider.send('eth_newFilter', [filterParams]);
  const filterLogs = await provider.send('eth_getFilterLogs', [filterId]);

  // Get logs directly via eth_getLogs
  const directLogs = await provider.send('eth_getLogs', [filterParams]);

  console.log(`Filter logs: ${filterLogs.length}, Direct logs: ${directLogs.length}`);

  if (filterLogs.length !== directLogs.length) {
    console.warn('Mismatch detected - investigate missing events');
  }

  await provider.send('eth_uninstallFilter', [filterId]);
  return { filterLogs, directLogs };
}

3. Paginated Historical Event Loader

Load large volumes of historical events in manageable chunks:

JavaScript
async function loadHistoricalEvents(provider, contractAddress, startBlock, endBlock, chunkSize = 2000) {
  const allLogs = [];

  for (let from = startBlock; from <= endBlock; from += chunkSize) {
    const to = Math.min(from + chunkSize - 1, endBlock);

    const filterId = await provider.send('eth_newFilter', [{
      fromBlock: '0x' + from.toString(16),
      toBlock: '0x' + to.toString(16),
      address: contractAddress
    }]);

    const logs = await provider.send('eth_getFilterLogs', [filterId]);
    allLogs.push(...logs);

    console.log(`Blocks ${from}-${to}: ${logs.length} events (total: ${allLogs.length})`);

    await provider.send('eth_uninstallFilter', [filterId]);
  }

  return allLogs;
}

Error Handling

Common errors and solutions:

Error CodeDescriptionSolution
-32000Filter not foundFilter expired or was uninstalled - recreate with eth_newFilter
-32000Query returned more than 10000 resultsNarrow the block range in your filter - use smaller fromBlock/toBlock windows
-32600Invalid requestVerify the filter ID is a valid hex string
-32603Internal errorNode may be overloaded - retry with exponential backoff
-32005Rate limit exceededReduce request frequency or implement client-side rate limiting
JavaScript
async function safeGetFilterLogs(provider, filterId, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await provider.send('eth_getFilterLogs', [filterId]);
    } catch (error) {
      if (error.message.includes('filter not found')) {
        throw new Error('Filter expired - must recreate before retrying');
      }
      if (error.message.includes('more than 10000 results')) {
        throw new Error('Too many results - narrow your block range');
      }
      if (i < maxRetries - 1) {
        const delay = Math.pow(2, i) * 1000;
        await new Promise(r => setTimeout(r, delay));
      } else {
        throw error;
      }
    }
  }
}

Related Methods

  • eth_newFilter - Create the log filter whose results this method returns
  • eth_getFilterChanges - Poll for only new logs since the last call (incremental)
  • eth_getLogs - Query logs directly without creating a filter first
  • eth_uninstallFilter - Remove a filter when no longer needed

eth_getFilterChanges

Poll a filter for new results since the last poll on Zetachain. Essential for event streaming, real-time monitoring, and efficient log indexing for omnichain DeFi, native Bitcoin smart contracts, cross-chain asset management, and unified liquidity aggregation.

eth_uninstallFilter

Remove a filter on Zetachain created by eth_newFilter, eth_newBlockFilter, or eth_newPendingTransactionFilter. Essential for resource cleanup after event monitoring.

On this page

When to Use This MethodBest PracticesCode ExamplesCommon Use Cases1. Backfill Event Data After Indexer Restart2. Compare Filter Results with Direct Query3. Paginated Historical Event LoaderError HandlingRelated Methods