event_scanner/event_scanner/scanner/sync/
from_block.rs

1use alloy::network::Network;
2
3use crate::{
4    EventScannerBuilder, ScannerError,
5    event_scanner::{
6        EventScanner, SyncFromBlock,
7        scanner::common::{ConsumerMode, handle_stream},
8    },
9};
10
11impl EventScannerBuilder<SyncFromBlock> {
12    #[must_use]
13    pub fn max_block_range(mut self, max_block_range: u64) -> Self {
14        self.block_range_scanner.max_block_range = max_block_range;
15        self
16    }
17
18    #[must_use]
19    pub fn block_confirmations(mut self, count: u64) -> Self {
20        self.config.block_confirmations = count;
21        self
22    }
23}
24
25impl<N: Network> EventScanner<SyncFromBlock, N> {
26    /// Starts the scanner.
27    ///
28    /// # Important notes
29    ///
30    /// * Register event streams via [`scanner.subscribe(filter)`][subscribe] **before** calling
31    ///   this function.
32    /// * The method returns immediately; events are delivered asynchronously.
33    ///
34    /// # Errors
35    ///
36    /// Can error out if the service fails to start.
37    ///
38    /// [subscribe]: EventScanner::subscribe
39    pub async fn start(self) -> Result<(), ScannerError> {
40        let client = self.block_range_scanner.run()?;
41        let stream =
42            client.stream_from(self.config.from_block, self.config.block_confirmations).await?;
43
44        let provider = self.block_range_scanner.provider().clone();
45        let listeners = self.listeners.clone();
46
47        tokio::spawn(async move {
48            handle_stream(stream, &provider, &listeners, ConsumerMode::Stream).await;
49        });
50
51        Ok(())
52    }
53}
54
55#[cfg(test)]
56mod tests {
57    use alloy::eips::BlockNumberOrTag;
58
59    use super::*;
60
61    #[test]
62    fn sync_scanner_builder_pattern() {
63        let builder =
64            EventScannerBuilder::sync().from_block(50).max_block_range(25).block_confirmations(5);
65
66        assert_eq!(builder.block_range_scanner.max_block_range, 25);
67        assert_eq!(builder.config.block_confirmations, 5);
68        assert!(matches!(builder.config.from_block, BlockNumberOrTag::Number(50)));
69    }
70
71    #[test]
72    fn sync_scanner_builder_with_different_block_types() {
73        let builder = EventScannerBuilder::sync()
74            .from_block(BlockNumberOrTag::Earliest)
75            .block_confirmations(20)
76            .max_block_range(100);
77
78        assert!(matches!(builder.config.from_block, BlockNumberOrTag::Earliest));
79        assert_eq!(builder.config.block_confirmations, 20);
80        assert_eq!(builder.block_range_scanner.max_block_range, 100);
81    }
82
83    #[test]
84    fn sync_scanner_builder_with_zero_confirmations() {
85        let builder =
86            EventScannerBuilder::sync().from_block(0).block_confirmations(0).max_block_range(75);
87
88        assert!(matches!(builder.config.from_block, BlockNumberOrTag::Number(0)));
89        assert_eq!(builder.config.block_confirmations, 0);
90        assert_eq!(builder.block_range_scanner.max_block_range, 75);
91    }
92
93    #[test]
94    fn sync_scanner_builder_last_call_wins() {
95        let builder = EventScannerBuilder::sync()
96            .from_block(2)
97            .max_block_range(25)
98            .max_block_range(55)
99            .max_block_range(105)
100            .block_confirmations(5)
101            .block_confirmations(7);
102
103        assert_eq!(builder.block_range_scanner.max_block_range, 105);
104        assert!(matches!(builder.config.from_block, BlockNumberOrTag::Number(2)));
105        assert_eq!(builder.config.block_confirmations, 7);
106    }
107}