pub struct EventScannerBuilder<M> { /* private fields */ }Implementations§
Source§impl EventScannerBuilder<Historic>
impl EventScannerBuilder<Historic>
pub fn max_block_range(self, max_block_range: u64) -> Self
pub fn from_block(self, block: impl Into<BlockNumberOrTag>) -> Self
pub fn to_block(self, block: impl Into<BlockNumberOrTag>) -> Self
Source§impl EventScannerBuilder<LatestEvents>
impl EventScannerBuilder<LatestEvents>
pub fn max_block_range(self, max_block_range: u64) -> Self
pub fn block_confirmations(self, confirmations: u64) -> Self
pub fn from_block(self, block: impl Into<BlockNumberOrTag>) -> Self
pub fn to_block(self, block: impl Into<BlockNumberOrTag>) -> Self
Source§impl EventScannerBuilder<Live>
impl EventScannerBuilder<Live>
pub fn max_block_range(self, max_block_range: u64) -> Self
pub fn block_confirmations(self, confirmations: u64) -> Self
Source§impl EventScannerBuilder<SyncFromBlock>
impl EventScannerBuilder<SyncFromBlock>
pub fn max_block_range(self, max_block_range: u64) -> Self
pub fn block_confirmations(self, count: u64) -> Self
Source§impl EventScannerBuilder<SyncFromLatestEvents>
impl EventScannerBuilder<SyncFromLatestEvents>
pub fn block_confirmations(self, count: u64) -> Self
Source§impl EventScannerBuilder<Synchronize>
impl EventScannerBuilder<Synchronize>
Sourcepub fn from_latest(
self,
count: usize,
) -> EventScannerBuilder<SyncFromLatestEvents>
pub fn from_latest( self, count: usize, ) -> EventScannerBuilder<SyncFromLatestEvents>
Scans the latest count matching events per registered listener, then automatically
transitions to live streaming mode.
This method combines two scanning phases into a single operation:
- Latest events phase: Collects up to
countmost recent events by scanning backwards from the current chain tip - Automatic transition: Emits
ScannerStatus::SwitchingToLiveto signal the mode change - Live streaming phase: Continuously monitors and streams new events as they arrive on-chain
§Example
// Fetch the latest 10 events, then stream new events continuously
let mut scanner = EventScannerBuilder::sync()
.from_latest(10)
.connect_ws::<Ethereum>(ws_url)
.await?;
let filter = EventFilter::new().contract_address(contract_address);
let mut stream = scanner.subscribe(filter);
scanner.start().await?;
while let Some(msg) = stream.next().await {
match msg {
Message::Data(logs) => {
println!("Received {} events", logs.len());
}
Message::Status(status) => {
println!("Status update: {:?}", status);
// You'll see ScannerStatus::SwitchingToLive when transitioning
}
Message::Error(e) => {
eprintln!("Error: {}", e);
}
}
}§How it works
The scanner captures the latest block number before starting to establish a clear boundary between phases. The historical phase scans from genesis block to the current latest block, while the live phase starts from the block after the latest block. This design prevents duplicate events and handles race conditions where new blocks arrive during setup.
§Key behaviors
- No duplicates: Events are not delivered twice across the phase transition
- Flexible count: If fewer than
countevents exist, returns all available events - Reorg handling: Both phases handle reorgs appropriately:
- Historical phase: resets and rescans on reorg detection
- Live phase: resets stream to the first post-reorg block that satisfies the configured block confirmations
- Continuous operation: Live phase continues indefinitely until the scanner is dropped
§Arguments
count- Maximum number of recent events to collect per listener before switching to live streaming
§Important notes
- The live phase continues indefinitely until the scanner is dropped or encounters an error
§Detailed reorg behavior
- Historical rewind phase: Restart the scanner. On detecting a reorg, emits
ScannerStatus::ReorgDetected, resets the rewind start to the new tip, and continues until collectors accumulatecountlogs. Final delivery to listeners preserves chronological order. - Live streaming phase: Starts from
latest_block + 1and respects the configured block confirmations. On reorg, emitsScannerStatus::ReorgDetected, adjusts the next confirmed window (possibly re-emitting confirmed portions), and continues streaming.
Sourcepub fn from_block(
self,
block: impl Into<BlockNumberOrTag>,
) -> EventScannerBuilder<SyncFromBlock>
pub fn from_block( self, block: impl Into<BlockNumberOrTag>, ) -> EventScannerBuilder<SyncFromBlock>
Streams events from a specific starting block to the present, then automatically transitions to live streaming mode.
This method combines two scanning phases into a single operation:
- Historical sync phase: Streams events from
from_blockup to the current confirmed tip - Automatic transition: Emits
ScannerStatus::SwitchingToLiveto signal the mode change - Live streaming phase: Continuously monitors and streams new events as they arrive on-chain
§Example
// Sync from block 1_000_000 to present, then stream new events
let mut scanner = EventScannerBuilder::sync()
.from_block(1_000_000)
.connect_ws::<Ethereum>(ws_url)
.await?;
let filter = EventFilter::new().contract_address(contract_address);
let mut stream = scanner.subscribe(filter);
scanner.start().await?;
while let Some(msg) = stream.next().await {
match msg {
Message::Data(logs) => {
println!("Received {} events", logs.len());
}
Message::Status(status) => {
println!("Status update: {:?}", status);
// You'll see ScannerStatus::SwitchingToLive when transitioning
}
Message::Error(e) => {
eprintln!("Error: {}", e);
}
}
}Using block tags:
// Sync from genesis block
let mut scanner = EventScannerBuilder::sync()
.from_block(BlockNumberOrTag::Earliest)
.connect_ws::<Ethereum>(ws_url)
.await?;§How it works
The scanner first streams all events from the specified starting block up to the current
confirmed tip (respecting block_confirmations). Once caught up, it seamlessly transitions
to live mode and continues streaming new events as blocks are produced.
§Key behaviors
- No duplicates: Events are not delivered twice across the phase transition
- Chronological order: Historical events are delivered oldest to newest
- Seamless transition: Automatically switches to live mode when caught up
- Continuous operation: Live phase continues indefinitely until the scanner is dropped
§Arguments
block- Starting block number or tag (e.g.,Earliest,Latest, or a specific number)
§Important notes
- The live phase continues indefinitely until the scanner is dropped or encounters an error
§Reorg behavior
- Historical sync phase: Streams events in chronological order without reorg detection
- Live streaming phase: Respects the configured block confirmations. On reorg, emits
ScannerStatus::ReorgDetected, adjusts the next confirmed window (possibly re-emitting confirmed portions), and continues streaming.
Source§impl EventScannerBuilder<Unspecified>
impl EventScannerBuilder<Unspecified>
Sourcepub fn historic() -> EventScannerBuilder<Historic>
pub fn historic() -> EventScannerBuilder<Historic>
Streams events from a historical block range.
§Example
// Stream all events from genesis to latest block
let mut scanner = EventScannerBuilder::historic()
.connect_ws::<Ethereum>(ws_url)
.await?;
let filter = EventFilter::new().contract_address(contract_address);
let mut stream = scanner.subscribe(filter);
scanner.start().await?;
while let Some(Message::Data(logs)) = stream.next().await {
println!("Received {} logs", logs.len());
}Specifying a custom block range:
// Stream events between blocks [1_000_000, 2_000_000]
let mut scanner = EventScannerBuilder::historic()
.from_block(1_000_000)
.to_block(2_000_000)
.connect_ws::<Ethereum>(ws_url)
.await?;§How it works
The scanner streams events in chronological order (oldest to newest) within the specified
block range. Events are delivered in batches as they are fetched from the provider, with
batch sizes controlled by the max_block_range configuration.
§Key behaviors
- Continuous streaming: Events are delivered in multiple messages as they are fetched
- Chronological order: Events are always delivered oldest to newest
- Default range: By default, scans from
EarliesttoLatestblock - Batch control: Use
.max_block_range(n)to control how many blocks are queried per RPC call - Completion: The scanner completes when the entire range has been processed
Sourcepub fn live() -> EventScannerBuilder<Live>
pub fn live() -> EventScannerBuilder<Live>
Streams new events as blocks are produced on-chain.
§Example
// Stream new events as they arrive
let mut scanner = EventScannerBuilder::live()
.block_confirmations(20)
.connect_ws::<Ethereum>(ws_url)
.await?;
let filter = EventFilter::new().contract_address(contract_address);
let mut stream = scanner.subscribe(filter);
scanner.start().await?;
while let Some(msg) = stream.next().await {
match msg {
Message::Data(logs) => {
println!("Received {} new events", logs.len());
}
Message::Status(status) => {
println!("Status: {:?}", status);
}
Message::Error(e) => {
eprintln!("Error: {}", e);
}
}
}§How it works
The scanner subscribes to new blocks via WebSocket and streams events from confirmed
blocks. The block_confirmations setting determines how many blocks to wait before
considering a block confirmed, providing protection against chain reorganizations.
§Key behaviors
- Real-time streaming: Events are delivered as new blocks are confirmed
- Reorg protection: Waits for configured confirmations before emitting events
- Continuous operation: Runs indefinitely until the scanner is dropped or encounters an error
- Default confirmations: By default, waits for 12 block confirmations
§Reorg behavior
When a reorg is detected:
- Emits
ScannerStatus::ReorgDetectedto all listeners - Adjusts the next confirmed range using
block_confirmations - Re-emits events from the corrected confirmed block range
- Continues streaming from the new chain state
Sourcepub fn sync() -> EventScannerBuilder<Synchronize>
pub fn sync() -> EventScannerBuilder<Synchronize>
Creates a builder for sync mode scanners that combine historical catch-up with live streaming.
This method returns a builder that must be further narrowed down:
// Sync from block mode
EventScannerBuilder::sync().from_block(1_000_000);
// Sync from latest events mode
EventScannerBuilder::sync().from_latest(10);See the sync module documentation for details on each mode.
Sourcepub fn latest(count: usize) -> EventScannerBuilder<LatestEvents>
pub fn latest(count: usize) -> EventScannerBuilder<LatestEvents>
Streams the latest count matching events per registered listener.
§Example
// Collect the latest 10 events across Earliest..=Latest
let mut scanner = EventScannerBuilder::latest(10)
.connect_ws::<Ethereum>(ws_url)
.await?;
let filter = EventFilter::new().contract_address(contract_address);
let mut stream = scanner.subscribe(filter);
scanner.start().await?;
// Expect a single message with up to 10 logs, then the stream ends
while let Some(Message::Data(logs)) = stream.next().await {
println!("Latest logs: {}", logs.len());
}Restricting to a specific block range:
// Collect the latest 5 events between blocks [1_000_000, 1_100_000]
let mut scanner = EventScannerBuilder::latest(5)
.from_block(1_000_000)
.to_block(1_100_000)
.connect_ws::<Ethereum>(ws_url)
.await?;§How it works
The scanner performs a reverse-ordered scan (newest to oldest) within the specified block
range, collecting up to count events per registered listener. Once the target count is
reached or the range is exhausted, it delivers the events in chronological order (oldest to
newest) and completes.
When using a custom block range, the scanner automatically normalizes the range boundaries.
This means you can specify from_block and to_block in any order - the scanner will
always scan from the higher block number down to the lower one, regardless of which
parameter holds which value.
§Key behaviors
- Single delivery: Each registered stream receives at most
countlogs in a single message, chronologically ordered - One-shot operation: The scanner completes after delivering messages; it does not continue streaming
- Flexible count: If fewer than
countevents exist in the range, returns all available events - Default range: By default, scans from
EarliesttoLatestblock - Reorg handling: Periodically checks the tip to detect reorgs during the scan
§Arguments
count- Maximum number of recent events to collect per listener
§Reorg behavior
During the scan, the scanner periodically checks the tip to detect reorgs. On reorg detection:
- Emits
ScannerStatus::ReorgDetectedto all listeners - Resets to the updated tip
- Restarts the scan from the new tip
- Continues until
countevents are collected
Final delivery to log listeners preserves chronological order regardless of reorgs.
§Notes
For continuous streaming after collecting latest events, use
EventScannerBuilder::sync().from_latest(count) instead
Source§impl EventScannerBuilder<SyncFromBlock>
impl EventScannerBuilder<SyncFromBlock>
pub fn new(from_block: BlockNumberOrTag) -> Self
Source§impl<M> EventScannerBuilder<M>
impl<M> EventScannerBuilder<M>
Sourcepub async fn connect_ws<N: Network>(
self,
ws_url: Url,
) -> TransportResult<EventScanner<M, N>>
pub async fn connect_ws<N: Network>( self, ws_url: Url, ) -> TransportResult<EventScanner<M, N>>
Connects to the provider via WebSocket.
Final builder method: consumes the builder and returns the built [HistoricEventScanner].
§Errors
Returns an error if the connection fails
Sourcepub async fn connect_ipc<N: Network>(
self,
ipc_path: String,
) -> TransportResult<EventScanner<M, N>>
pub async fn connect_ipc<N: Network>( self, ipc_path: String, ) -> TransportResult<EventScanner<M, N>>
Connects to the provider via IPC.
Final builder method: consumes the builder and returns the built [HistoricEventScanner].
§Errors
Returns an error if the connection fails
Sourcepub fn connect<N: Network>(
self,
provider: RootProvider<N>,
) -> EventScanner<M, N>
pub fn connect<N: Network>( self, provider: RootProvider<N>, ) -> EventScanner<M, N>
Connects to an existing provider.
Final builder method: consumes the builder and returns the built [HistoricEventScanner].
§Errors
Returns an error if the connection fails
Trait Implementations§
Source§impl<M: Default> Default for EventScannerBuilder<M>
impl<M: Default> Default for EventScannerBuilder<M>
Source§fn default() -> EventScannerBuilder<M>
fn default() -> EventScannerBuilder<M>
Auto Trait Implementations§
impl<M> Freeze for EventScannerBuilder<M>where
M: Freeze,
impl<M> RefUnwindSafe for EventScannerBuilder<M>where
M: RefUnwindSafe,
impl<M> Send for EventScannerBuilder<M>where
M: Send,
impl<M> Sync for EventScannerBuilder<M>where
M: Sync,
impl<M> Unpin for EventScannerBuilder<M>where
M: Unpin,
impl<M> UnwindSafe for EventScannerBuilder<M>where
M: UnwindSafe,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more