Documentation Index Fetch the complete documentation index at: https://voltaire.tevm.sh/llms.txt
Use this file to discover all available pages before exploring further.
Try it Live Run EventLog examples in the interactive playground
Filter Fields
Address Filter
Single address or array (OR logic):
import { EventLog , Address } from 'tevm' ;
// Single address
const matches1 = log . matchesFilter ({
address: usdcAddress ,
});
// Multiple addresses
const matches2 = log . matchesFilter ({
address: [ usdcAddress , daiAddress , wethAddress ],
});
// Undefined: matches all addresses
const matches3 = log . matchesFilter ({
topics: [ TRANSFER_SIG ],
});
Topics Filter
Array with null wildcards and OR logic:
import { EventLog , Hash } from 'tevm' ;
const TRANSFER_SIG = Hash ( '0xddf252ad...' );
const userHash = Hash ( '0x000...user' );
const matches = log . matchesFilter ({
topics: [
TRANSFER_SIG , // topic0: exact match
null , // topic1: any value
userHash , // topic2: exact match
],
});
Block Range Filter
Inclusive bounds on block number:
import { EventLog } from 'tevm' ;
// Blocks 18M to 18.5M (inclusive)
const matches = log . matchesFilter ({
fromBlock: 18000000 n ,
toBlock: 18500000 n ,
});
// Only requires log.blockNumber to be defined
Block Hash Filter
Exact block match:
import { EventLog , Hash } from 'tevm' ;
const blockHash = Hash ( '0xabc...' );
const matches = log . matchesFilter ({
blockHash: blockHash ,
});
// Only requires log.blockHash to be defined
Filter Combinations
All specified filters use AND logic:
import { EventLog , Address , Hash } from 'tevm' ;
// Must match ALL conditions
const matches = log . matchesFilter ({
address: [ usdc , dai ], // AND address is USDC or DAI
topics: [ TRANSFER_SIG , null , userHash ], // AND is Transfer to user
fromBlock: 18000000 n , // AND block >= 18M
toBlock: 18500000 n , // AND block <= 18.5M
});
Usage Patterns
Complete RPC-Style Filter
import { EventLog , Address , Hash } from 'tevm' ;
const TRANSFER_SIG = Hash ( '0xddf252ad...' );
const userHash = Hash ( '0x000...user' );
// Equivalent to eth_getLogs filter
const filtered = allLogs . filter ( log =>
log . matchesFilter ({
address: [
Address ( '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48' ), // USDC
Address ( '0x6B175474E89094C44Da98b954EedeAC495271d0F' ), // DAI
],
topics: [
TRANSFER_SIG , // Transfer events
null , // from any
userHash , // to user
],
fromBlock: 18000000 n ,
toBlock: 18500000 n ,
})
);
console . log ( `Found ${ filtered . length } matching logs` );
Partial Filters
Omit unnecessary fields:
import { EventLog } from 'tevm' ;
// Only address filter
const byAddress = log . matchesFilter ({
address: tokenAddress ,
});
// Only topics filter
const byTopics = log . matchesFilter ({
topics: [ TRANSFER_SIG , null , userHash ],
});
// Only block range
const byBlock = log . matchesFilter ({
fromBlock: 18000000 n ,
toBlock: 18500000 n ,
});
Block Hash vs Block Range
Block hash is alternative to from/to block:
import { EventLog , Hash } from 'tevm' ;
// Option 1: Block range
const range = log . matchesFilter ({
fromBlock: 18000000 n ,
toBlock: 18000000 n , // Same block
});
// Option 2: Block hash (more precise)
const hash = log . matchesFilter ({
blockHash: Hash ( '0xabc...' ),
});
// Don't mix: blockHash takes precedence
const mixed = log . matchesFilter ({
blockHash: Hash ( '0xabc...' ),
fromBlock: 18000000 n , // Ignored
toBlock: 18500000 n , // Ignored
});
Multi-Stage Filtering
import { EventLog , Address , Hash } from 'tevm' ;
// Stage 1: Coarse filter (address + block range)
const coarse = allLogs . filter ( log =>
log . matchesFilter ({
address: [ usdc , dai , weth ],
fromBlock: 18000000 n ,
toBlock: 18500000 n ,
})
);
// Stage 2: Refined filter (specific event + parameters)
const refined = coarse . filter ( log =>
log . matchesFilter ({
topics: [ TRANSFER_SIG , null , userHash ],
})
);
console . log ( `Coarse: ${ coarse . length } , Refined: ${ refined . length } ` );
Validating Log Completeness
import { EventLog } from 'tevm' ;
function requiresBlockNumber ( filter : Filter ) : boolean {
return filter . fromBlock !== undefined || filter . toBlock !== undefined ;
}
function requiresBlockHash ( filter : Filter ) : boolean {
return filter . blockHash !== undefined ;
}
// Check if log has required fields
const filter = { fromBlock: 18000000 n };
if ( requiresBlockNumber ( filter ) && log . blockNumber === undefined ) {
console . error ( 'Log missing blockNumber for filter' );
}
Batch Filtering
For multiple logs, use filterLogs instead:
import { EventLog } from 'tevm' ;
// Efficient: Single pass with optimizations
const filtered = EventLog . filterLogs ( allLogs , {
address: [ usdc , dai ],
topics: [ TRANSFER_SIG , null , userHash ],
fromBlock: 18000000 n ,
toBlock: 18500000 n ,
});
// Less efficient: Multiple passes
const filtered2 = allLogs . filter ( log =>
log . matchesFilter ({
address: [ usdc , dai ],
topics: [ TRANSFER_SIG , null , userHash ],
fromBlock: 18000000 n ,
toBlock: 18500000 n ,
})
);
Missing Optional Fields
Filter checks only apply if log has required fields:
import { EventLog } from 'tevm' ;
const pendingLog = EventLog ({
address: contractAddress ,
topics: [ TRANSFER_SIG ],
data: Bytes (),
// No blockNumber, blockHash, etc.
});
// Block range filter ignored (no blockNumber)
const matches1 = pendingLog . matchesFilter ({
fromBlock: 18000000 n ,
toBlock: 18500000 n ,
});
console . log ( matches1 ); // true (block filters skipped)
// Block hash filter ignored (no blockHash)
const matches2 = pendingLog . matchesFilter ({
blockHash: Hash ( '0xabc...' ),
});
console . log ( matches2 ); // true (block hash filter skipped)
See Also