⚠️Blast API (blastapi.io) ends Oct 31. Migrate to Dwellir and skip Alchemy's expensive compute units.
Switch Today →
Skip to main content

eth_getLogs

Returns an array of logs matching specified filter criteria on Avalanche C-Chain.

When to Use This Method

eth_getLogs is essential for:

  • Event Monitoring - Track contract events in real-time
  • DeFi Analytics - Analyze trading, lending, and yield farming activities
  • Audit Trails - Create comprehensive transaction histories
  • Data Indexing - Build custom indexing solutions for dApps

Parameters

Filter Object with the following fields:

  • fromBlock - (optional) Earliest block to search (hex or "latest")
  • toBlock - (optional) Latest block to search (hex or "latest")
  • address - (optional) Contract address or array of addresses
  • topics - (optional) Array of topic filters
  • blockhash - (optional) Specific block hash to search
{
"jsonrpc": "2.0",
"method": "eth_getLogs",
"params": [{
"fromBlock": "0x1",
"toBlock": "0x2",
"address": "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",
"topics": [
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"
]
}],
"id": 1
}

Returns

Array - Array of log objects matching the filter:

  • address - Address of the contract that generated the log
  • topics - Array of indexed event parameters
  • data - Non-indexed event data
  • blockNumber - Block number in hex
  • transactionHash - Transaction hash
  • transactionIndex - Transaction index in block
  • blockHash - Block hash
  • logIndex - Log index in block
  • removed - True if log was removed due to chain reorganization

Implementation Examples

curl -X POST https://api-avalanche-mainnet-archive.n.dwellir.com/YOUR_API_KEY/ext/bc/C/rpc \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "eth_getLogs",
"params": [{
"fromBlock": "0x1",
"toBlock": "latest",
"address": "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",
"topics": [
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"
]
}],
"id": 1
}'

Response Example

Successful Response

{
"jsonrpc": "2.0",
"id": 1,
"result": [
{
"address": "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",
"topics": [
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"0x000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebcccc",
"0x000000000000000000000000eff8bf1e28ffb1bfa76b6dc3e619d5a6e3b6b9b9"
],
"data": "0x000000000000000000000000000000000000000000000000000000000000000a",
"blockNumber": "0x2",
"transactionHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"transactionIndex": "0x0",
"blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"logIndex": "0x0",
"removed": false
}
]
}

Common Use Cases

1. DeFi Portfolio Tracking

Track user's DeFi activities across protocols:

async function trackDeFiPortfolio(userAddress, protocolAddresses) {
const activities = [];

// Common DeFi event signatures
const eventSignatures = {
transfer: '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
deposit: '0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c',
withdrawal: '0x7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65',
swap: '0xd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822'
};

const userTopic = '0x000000000000000000000000' + userAddress.slice(2).toLowerCase();

for (const [protocolName, protocolAddress] of Object.entries(protocolAddresses)) {
const filter = {
address: protocolAddress,
topics: [
Object.values(eventSignatures),
[userTopic, null],
[null, userTopic]
],
fromBlock: 'earliest',
toBlock: 'latest'
};

try {
const logs = await provider.getLogs(filter);

for (const log of logs) {
const eventType = Object.keys(eventSignatures).find(
key => eventSignatures[key] === log.topics[0]
);

activities.push({
protocol: protocolName,
eventType: eventType || 'unknown',
transactionHash: log.transactionHash,
blockNumber: parseInt(log.blockNumber, 16),
address: log.address,
topics: log.topics,
data: log.data
});
}
} catch (error) {
console.error(`Error fetching ${protocolName} logs:`, error);
}
}

return activities.sort((a, b) => b.blockNumber - a.blockNumber);
}

2. Token Analytics Dashboard

Build comprehensive token analytics:

async function analyzeTokenActivity(tokenAddress, timeframe = 24) {
const currentBlock = await provider.getBlockNumber();
const currentTime = Math.floor(Date.now() / 1000);
const timeframeStart = currentTime - (timeframe * 3600); // hours to seconds

// Estimate block number for timeframe start
const avgBlockTime = 2; // Avalanche ~2 second blocks
const blocksInTimeframe = Math.floor((timeframe * 3600) / avgBlockTime);
const fromBlock = Math.max(1, currentBlock - blocksInTimeframe);

const filter = {
address: tokenAddress,
topics: [TRANSFER_TOPIC],
fromBlock: `0x${fromBlock.toString(16)}`,
toBlock: 'latest'
};

const logs = await provider.getLogs(filter);

// Analyze the data
const analytics = {
totalTransfers: logs.length,
uniqueAddresses: new Set(),
totalVolume: 0n,
topHolders: new Map(),
hourlyActivity: new Array(timeframe).fill(0)
};

for (const log of logs) {
const from = '0x' + log.topics[1].slice(26);
const to = '0x' + log.topics[2].slice(26);
const value = BigInt(log.data);

analytics.uniqueAddresses.add(from);
analytics.uniqueAddresses.add(to);
analytics.totalVolume += value;

// Track holder balances (simplified)
if (from !== '0x0000000000000000000000000000000000000000') {
analytics.topHolders.set(from, (analytics.topHolders.get(from) || 0n) - value);
}
if (to !== '0x0000000000000000000000000000000000000000') {
analytics.topHolders.set(to, (analytics.topHolders.get(to) || 0n) + value);
}
}

return {
...analytics,
uniqueAddresses: analytics.uniqueAddresses.size,
totalVolume: analytics.totalVolume.toString(),
topHolders: Array.from(analytics.topHolders.entries())
.sort(([,a], [,b]) => Number(b - a))
.slice(0, 10)
};
}

3. Cross-Chain Bridge Monitoring

Monitor bridge activities:

async function monitorBridgeActivity(bridgeAddresses) {
// Common bridge event signatures
const DEPOSIT_EVENT = '0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c';
const WITHDRAWAL_EVENT = '0x7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65';

const bridgeActivity = [];

for (const bridgeAddress of bridgeAddresses) {
const filter = {
address: bridgeAddress,
topics: [
[DEPOSIT_EVENT, WITHDRAWAL_EVENT]
],
fromBlock: 'earliest',
toBlock: 'latest'
};

const logs = await provider.getLogs(filter);

for (const log of logs) {
const isDeposit = log.topics[0] === DEPOSIT_EVENT;

bridgeActivity.push({
bridgeAddress: log.address,
type: isDeposit ? 'deposit' : 'withdrawal',
transactionHash: log.transactionHash,
blockNumber: parseInt(log.blockNumber, 16),
user: '0x' + log.topics[1].slice(26),
amount: BigInt(log.data).toString()
});
}
}

return bridgeActivity.sort((a, b) => b.blockNumber - a.blockNumber);
}

4. NFT Marketplace Analytics

Track NFT trading activity:

async function analyzeNFTMarketplace(marketplaceAddress) {
// ERC721 Transfer event and marketplace specific events
const ERC721_TRANSFER = '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef';
const SALE_EVENT = '0x4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb';

const filter = {
address: marketplaceAddress,
topics: [
[ERC721_TRANSFER, SALE_EVENT]
],
fromBlock: 'earliest',
toBlock: 'latest'
};

const logs = await provider.getLogs(filter);

const analytics = {
totalSales: 0,
totalVolume: 0n,
uniqueCollections: new Set(),
topCollections: new Map(),
recentSales: []
};

for (const log of logs) {
if (log.topics[0] === SALE_EVENT) {
analytics.totalSales++;

// Decode sale data (simplified)
const collection = log.address;
const price = BigInt(log.data);

analytics.totalVolume += price;
analytics.uniqueCollections.add(collection);
analytics.topCollections.set(
collection,
(analytics.topCollections.get(collection) || 0n) + price
);

analytics.recentSales.push({
collection,
price: price.toString(),
transactionHash: log.transactionHash,
blockNumber: parseInt(log.blockNumber, 16)
});
}
}

return {
...analytics,
uniqueCollections: analytics.uniqueCollections.size,
totalVolume: analytics.totalVolume.toString(),
topCollections: Array.from(analytics.topCollections.entries())
.sort(([,a], [,b]) => Number(b - a))
.slice(0, 10),
recentSales: analytics.recentSales
.sort((a, b) => b.blockNumber - a.blockNumber)
.slice(0, 50)
};
}

Performance Optimization

Batch Log Queries

Query logs efficiently with proper batching:

async function batchLogQueries(queries) {
const batch = queries.map((query, i) => ({
jsonrpc: '2.0',
method: 'eth_getLogs',
params: [query],
id: i
}));

const response = await fetch('https://api-avalanche-mainnet-archive.n.dwellir.com/YOUR_API_KEY/ext/bc/C/rpc', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(batch)
});

const results = await response.json();
return results.map(r => r.result || []);
}

Block Range Optimization

Split large block ranges for better performance:

async function optimizedLogQuery(filter, maxBlockRange = 5000) {
const fromBlock = typeof filter.fromBlock === 'string' ?
parseInt(filter.fromBlock, 16) : filter.fromBlock;
const toBlock = typeof filter.toBlock === 'string' ?
(filter.toBlock === 'latest' ? await provider.getBlockNumber() : parseInt(filter.toBlock, 16)) : filter.toBlock;

const allLogs = [];

for (let start = fromBlock; start <= toBlock; start += maxBlockRange) {
const end = Math.min(start + maxBlockRange - 1, toBlock);

const batchFilter = {
...filter,
fromBlock: `0x${start.toString(16)}`,
toBlock: `0x${end.toString(16)}`
};

try {
const logs = await provider.getLogs(batchFilter);
allLogs.push(...logs);
} catch (error) {
console.error(`Error fetching logs for blocks ${start}-${end}:`, error);
}
}

return allLogs;
}

Error Handling

Common errors and solutions:

Error CodeDescriptionSolution
-32602Invalid parametersCheck filter object format
-32005Rate limit exceededReduce query frequency
-32000Query timeoutReduce block range or add more filters
async function safeLogs(filter, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
const logs = await provider.getLogs(filter);
return { success: true, logs };
} catch (error) {
if (error.message.includes('query timeout')) {
// Reduce block range
const fromBlock = parseInt(filter.fromBlock || '0x1', 16);
const toBlock = parseInt(filter.toBlock || 'latest', 16);
const range = toBlock - fromBlock;

if (range > 1000) {
return optimizedLogQuery(filter, 1000);
}
}

if (i === maxRetries - 1) {
return { success: false, error: error.message };
}

await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)));
}
}
}

Need help? Contact our support team or check the Avalanche documentation.