alloy_rpc_types_eth/
filter.rs

1use crate::{BlockNumberOrTag, Log as RpcLog, Transaction};
2use alloc::{string::String, vec::Vec};
3use alloy_primitives::{
4    keccak256,
5    map::{hash_set, HashSet},
6    Address, BlockHash, Bloom, BloomInput, B256, U256, U64,
7};
8use core::{
9    hash::Hash,
10    ops::{RangeFrom, RangeInclusive, RangeToInclusive},
11};
12use itertools::{
13    EitherOrBoth::{Both, Left, Right},
14    Itertools,
15};
16
17/// Helper type to represent a bloom filter used for matching logs.
18#[derive(Debug, Default)]
19pub struct BloomFilter(Vec<Bloom>);
20
21impl From<Vec<Bloom>> for BloomFilter {
22    fn from(src: Vec<Bloom>) -> Self {
23        Self(src)
24    }
25}
26
27impl BloomFilter {
28    /// Returns whether the given bloom matches the list of Blooms in the current filter.
29    /// If the filter is empty (the list is empty), then any bloom matches
30    /// Otherwise, there must be at least one match for the BloomFilter to match.
31    pub fn matches(&self, bloom: Bloom) -> bool {
32        self.0.is_empty() || self.0.iter().any(|a| bloom.contains(a))
33    }
34}
35
36/// FilterSet is a set of values that will be used to filter logs.
37#[derive(Clone, Debug, Default, PartialEq, Eq)]
38#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
39pub struct FilterSet<T: Eq + Hash>(HashSet<T>);
40
41impl<T: Eq + Hash> From<T> for FilterSet<T> {
42    fn from(src: T) -> Self {
43        Self(core::iter::once(src).collect())
44    }
45}
46
47impl<T: Eq + Hash> Hash for FilterSet<T> {
48    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
49        for value in &self.0 {
50            value.hash(state);
51        }
52    }
53}
54
55impl<T: Eq + Hash> From<Vec<T>> for FilterSet<T> {
56    fn from(src: Vec<T>) -> Self {
57        Self(src.into_iter().collect())
58    }
59}
60
61impl<T: Eq + Hash> From<ValueOrArray<T>> for FilterSet<T> {
62    fn from(src: ValueOrArray<T>) -> Self {
63        match src {
64            ValueOrArray::Value(val) => val.into(),
65            ValueOrArray::Array(arr) => arr.into(),
66        }
67    }
68}
69
70impl<T: Eq + Hash> From<ValueOrArray<Option<T>>> for FilterSet<T> {
71    fn from(src: ValueOrArray<Option<T>>) -> Self {
72        match src {
73            ValueOrArray::Value(None) => Self(Default::default()),
74            ValueOrArray::Value(Some(val)) => val.into(),
75            ValueOrArray::Array(arr) => {
76                // If the array contains at least one `null` (ie. None), as it's considered
77                // a "wildcard" value, the whole filter should be treated as matching everything,
78                // thus is empty.
79                if arr.iter().contains(&None) {
80                    Self(Default::default())
81                } else {
82                    // Otherwise, we flatten the array, knowing there are no `None` values
83                    arr.into_iter().flatten().collect::<Vec<T>>().into()
84                }
85            }
86        }
87    }
88}
89
90impl<T: Eq + Hash> IntoIterator for FilterSet<T> {
91    type Item = T;
92    type IntoIter = hash_set::IntoIter<T>;
93
94    fn into_iter(self) -> Self::IntoIter {
95        self.0.into_iter()
96    }
97}
98
99impl<T: Eq + Hash> FromIterator<T> for FilterSet<T> {
100    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
101        Self(HashSet::from_iter(iter))
102    }
103}
104
105impl<T: Eq + Hash> FilterSet<T> {
106    /// Returns whether the filter is empty
107    pub fn is_empty(&self) -> bool {
108        self.0.is_empty()
109    }
110
111    /// Returns whether the given value matches the filter. It the filter is empty
112    /// any value matches. Otherwise, the filter must include the value
113    pub fn matches(&self, value: &T) -> bool {
114        self.is_empty() || self.0.contains(value)
115    }
116
117    /// Returns an iterator over the underlying HashSet. Values are visited
118    /// in an arbitrary order.
119    pub fn iter(&self) -> hash_set::Iter<'_, T> {
120        self.0.iter()
121    }
122}
123
124impl<T: AsRef<[u8]> + Eq + Hash> FilterSet<T> {
125    /// Returns a list of Bloom (BloomFilter) corresponding to the filter's values
126    pub fn to_bloom_filter(&self) -> BloomFilter {
127        self.0.iter().map(|a| BloomInput::Raw(a.as_ref()).into()).collect::<Vec<Bloom>>().into()
128    }
129}
130
131impl<T: Clone + Eq + Hash> FilterSet<T> {
132    /// Returns a ValueOrArray inside an Option, so that:
133    /// - If the filter is empty, it returns None
134    /// - If the filter has only 1 value, it returns the single value
135    /// - Otherwise it returns an array of values
136    pub fn to_value_or_array(&self) -> Option<ValueOrArray<T>> {
137        let mut values = self.0.iter().cloned().collect::<Vec<T>>();
138        match values.len() {
139            0 => None,
140            1 => Some(ValueOrArray::Value(values.pop().expect("values length is one"))),
141            _ => Some(ValueOrArray::Array(values)),
142        }
143    }
144}
145
146/// A single topic
147pub type Topic = FilterSet<B256>;
148
149impl Topic {
150    /// Extends the topic with a value that can be converted into a Topic
151    pub fn extend<T: Into<Self>>(mut self, value: T) -> Self {
152        self.0.extend(value.into().0);
153        self
154    }
155}
156
157impl From<U256> for Topic {
158    fn from(src: U256) -> Self {
159        Into::<B256>::into(src).into()
160    }
161}
162
163impl From<Address> for Topic {
164    fn from(address: Address) -> Self {
165        let mut bytes = [0u8; 32];
166        bytes[12..].copy_from_slice(address.as_slice());
167        B256::from(bytes).into()
168    }
169}
170
171impl From<bool> for Topic {
172    fn from(value: bool) -> Self {
173        let mut bytes = [0u8; 32];
174        bytes[31] = if value { 1 } else { 0 };
175        B256::from(bytes).into()
176    }
177}
178
179impl From<[u8; 32]> for Topic {
180    fn from(bytes: [u8; 32]) -> Self {
181        B256::from(bytes).into()
182    }
183}
184
185/// Represents errors that can occur when setting block filters in `FilterBlockOption`.
186#[derive(Debug, PartialEq, Eq, thiserror::Error)]
187pub enum FilterBlockError {
188    /// Error indicating that the `from_block` is greater than the `to_block`.
189    #[error("`from_block` ({from}) is greater than `to_block` ({to})")]
190    FromBlockGreaterThanToBlock {
191        /// The starting block number, which is greater than `to`.
192        from: u64,
193        /// The ending block number, which is less than `from`.
194        to: u64,
195    },
196}
197
198/// Represents the target range of blocks for the filter
199#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
200pub enum FilterBlockOption {
201    /// Represents a range of blocks with optional from and to blocks
202    ///
203    /// Note: ranges are considered to be __inclusive__
204    Range {
205        /// The block number or tag this filter should start at.
206        from_block: Option<BlockNumberOrTag>,
207        /// The block number or that this filter should end at.
208        to_block: Option<BlockNumberOrTag>,
209    },
210    /// The hash of the block if the filter only targets a single block
211    AtBlockHash(BlockHash),
212}
213
214impl FilterBlockOption {
215    /// Returns the `from_block` value, if any
216    pub const fn get_to_block(&self) -> Option<&BlockNumberOrTag> {
217        match self {
218            Self::Range { to_block, .. } => to_block.as_ref(),
219            Self::AtBlockHash(_) => None,
220        }
221    }
222
223    /// Returns the `to_block` value, if any
224    pub const fn get_from_block(&self) -> Option<&BlockNumberOrTag> {
225        match self {
226            Self::Range { from_block, .. } => from_block.as_ref(),
227            Self::AtBlockHash(_) => None,
228        }
229    }
230
231    /// Returns the range (`from_block`, `to_block`) if this is a range filter.
232    pub const fn as_range(&self) -> (Option<&BlockNumberOrTag>, Option<&BlockNumberOrTag>) {
233        match self {
234            Self::Range { from_block, to_block } => (from_block.as_ref(), to_block.as_ref()),
235            Self::AtBlockHash(_) => (None, None),
236        }
237    }
238
239    /// Returns the block hash if this is a block hash filter.
240    pub const fn as_block_hash(&self) -> Option<&BlockHash> {
241        match self {
242            Self::AtBlockHash(hash) => Some(hash),
243            Self::Range { .. } => None,
244        }
245    }
246
247    /// Returns true if this is a range filter.
248    pub const fn is_range(&self) -> bool {
249        matches!(self, Self::Range { .. })
250    }
251
252    /// Returns true if this is a block hash filter.
253    pub const fn is_block_hash(&self) -> bool {
254        matches!(self, Self::AtBlockHash(_))
255    }
256
257    /// Ensure block range validity
258    pub fn ensure_valid_block_range(&self) -> Result<(), FilterBlockError> {
259        // Check if from_block is greater than to_block
260        if let (Some(from), Some(to)) = (
261            self.get_from_block().and_then(|from| from.as_number()),
262            self.get_to_block().and_then(|to| to.as_number()),
263        ) {
264            if from > to {
265                return Err(FilterBlockError::FromBlockGreaterThanToBlock { from, to });
266            }
267        }
268        Ok(())
269    }
270
271    /// Sets the block number this range filter should start at.
272    #[must_use]
273    pub fn with_from_block(&self, block: BlockNumberOrTag) -> Self {
274        Self::Range { from_block: Some(block), to_block: self.get_to_block().copied() }
275    }
276
277    /// Sets the block number this range filter should end at.
278    #[must_use]
279    pub fn with_to_block(&self, block: BlockNumberOrTag) -> Self {
280        Self::Range { from_block: self.get_from_block().copied(), to_block: Some(block) }
281    }
282
283    /// Pins the block hash this filter should target.
284    #[must_use]
285    pub const fn with_block_hash(&self, hash: B256) -> Self {
286        Self::AtBlockHash(hash)
287    }
288}
289
290impl From<BlockNumberOrTag> for FilterBlockOption {
291    fn from(block: BlockNumberOrTag) -> Self {
292        let block = Some(block);
293        Self::Range { from_block: block, to_block: block }
294    }
295}
296
297impl From<U64> for FilterBlockOption {
298    fn from(block: U64) -> Self {
299        BlockNumberOrTag::from(block).into()
300    }
301}
302
303impl From<u64> for FilterBlockOption {
304    fn from(block: u64) -> Self {
305        BlockNumberOrTag::from(block).into()
306    }
307}
308
309impl<T: Into<BlockNumberOrTag>> From<RangeInclusive<T>> for FilterBlockOption {
310    fn from(r: RangeInclusive<T>) -> Self {
311        let (start, end) = r.into_inner();
312        let from_block = Some(start.into());
313        let to_block = Some(end.into());
314        Self::Range { from_block, to_block }
315    }
316}
317
318impl<T: Into<BlockNumberOrTag>> From<RangeToInclusive<T>> for FilterBlockOption {
319    fn from(r: RangeToInclusive<T>) -> Self {
320        let to_block = Some(r.end.into());
321        Self::Range { from_block: Some(BlockNumberOrTag::Earliest), to_block }
322    }
323}
324
325impl<T: Into<BlockNumberOrTag>> From<RangeFrom<T>> for FilterBlockOption {
326    fn from(r: RangeFrom<T>) -> Self {
327        let from_block = Some(r.start.into());
328        Self::Range { from_block, to_block: Some(BlockNumberOrTag::Latest) }
329    }
330}
331
332impl From<B256> for FilterBlockOption {
333    fn from(hash: B256) -> Self {
334        Self::AtBlockHash(hash)
335    }
336}
337
338impl Default for FilterBlockOption {
339    fn default() -> Self {
340        Self::Range { from_block: None, to_block: None }
341    }
342}
343
344/// Filter for logs.
345#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
346pub struct Filter {
347    /// Filter block options, specifying on which blocks the filter should match.
348    // https://eips.ethereum.org/EIPS/eip-234
349    pub block_option: FilterBlockOption,
350    /// A filter set for matching contract addresses in log queries.
351    ///
352    /// This field determines which contract addresses the filter applies to. It supports:
353    /// - A single address to match logs from that address only.
354    /// - Multiple addresses to match logs from any of them.
355    ///
356    /// ## Notes:
357    /// - An empty array (`[]`) may result in no logs being returned.
358    /// - Some RPC providers handle empty arrays differently than `None`.
359    /// - Large address lists may affect performance or hit provider limits.
360    pub address: FilterSet<Address>,
361    /// Topics (maximum of 4)
362    pub topics: [Topic; 4],
363}
364
365impl Filter {
366    /// Creates a new, empty filter
367    pub fn new() -> Self {
368        Self::default()
369    }
370
371    /// Sets the inner filter object
372    ///
373    /// *NOTE:* ranges are always inclusive
374    ///
375    /// # Examples
376    ///
377    /// Match only a specific block
378    ///
379    /// ```rust
380    /// # use alloy_rpc_types_eth::Filter;
381    /// # fn main() {
382    /// let filter = Filter::new().select(69u64);
383    /// # }
384    /// ```
385    /// This is the same as `Filter::new().from_block(1337u64).to_block(1337u64)`
386    ///
387    /// Match the latest block only
388    ///
389    /// ```rust
390    /// # use alloy_rpc_types_eth::BlockNumberOrTag;
391    /// # use alloy_rpc_types_eth::Filter;
392    /// # fn main() {
393    /// let filter = Filter::new().select(BlockNumberOrTag::Latest);
394    /// # }
395    /// ```
396    ///
397    /// Match a block by its hash
398    ///
399    /// ```rust
400    /// # use alloy_primitives::B256;
401    /// # use alloy_rpc_types_eth::Filter;
402    /// # fn main() {
403    /// let filter = Filter::new().select(B256::ZERO);
404    /// # }
405    /// ```
406    /// This is the same as `at_block_hash`
407    ///
408    /// Match a range of blocks
409    ///
410    /// ```rust
411    /// # use alloy_rpc_types_eth::Filter;
412    /// # fn main() {
413    /// let filter = Filter::new().select(0u64..=100u64);
414    /// # }
415    /// ```
416    ///
417    /// Match all blocks in range `(1337..BlockNumberOrTag::Latest)`
418    ///
419    /// ```rust
420    /// # use alloy_rpc_types_eth::Filter;
421    /// # fn main() {
422    /// let filter = Filter::new().select(1337u64..);
423    /// # }
424    /// ```
425    ///
426    /// Match all blocks in range `(BlockNumberOrTag::Earliest..1337)`
427    ///
428    /// ```rust
429    /// # use alloy_rpc_types_eth::Filter;
430    /// # fn main() {
431    /// let filter = Filter::new().select(..=1337u64);
432    /// # }
433    /// ```
434    #[must_use]
435    pub fn select(mut self, filter: impl Into<FilterBlockOption>) -> Self {
436        self.block_option = filter.into();
437        self
438    }
439
440    /// Sets the from block number
441    #[must_use]
442    pub fn from_block<T: Into<BlockNumberOrTag>>(mut self, block: T) -> Self {
443        self.block_option = self.block_option.with_from_block(block.into());
444        self
445    }
446
447    /// Sets the to block number
448    #[must_use]
449    pub fn to_block<T: Into<BlockNumberOrTag>>(mut self, block: T) -> Self {
450        self.block_option = self.block_option.with_to_block(block.into());
451        self
452    }
453
454    /// Return `true` if filter configured to match pending block.
455    /// This means that both from_block and to_block are set to the pending tag.
456    pub fn is_pending_block_filter(&self) -> bool {
457        self.block_option.get_from_block().is_some_and(BlockNumberOrTag::is_pending)
458            && self.block_option.get_to_block().is_some_and(BlockNumberOrTag::is_pending)
459    }
460
461    /// Pins the block hash for the filter
462    #[must_use]
463    pub fn at_block_hash<T: Into<B256>>(mut self, hash: T) -> Self {
464        self.block_option = self.block_option.with_block_hash(hash.into());
465        self
466    }
467
468    /// Sets the address to query with this filter.
469    ///
470    /// # Examples
471    ///
472    /// Match only a specific address `("0xAc4b3DacB91461209Ae9d41EC517c2B9Cb1B7DAF")`
473    ///
474    /// ```rust
475    /// # use alloy_primitives::Address;
476    /// # use alloy_rpc_types_eth::Filter;
477    /// # fn main() {
478    /// let filter = Filter::new()
479    ///     .address("0xAc4b3DacB91461209Ae9d41EC517c2B9Cb1B7DAF".parse::<Address>().unwrap());
480    /// # }
481    /// ```
482    ///
483    /// Match all addresses in array `(vec!["0xAc4b3DacB91461209Ae9d41EC517c2B9Cb1B7DAF",
484    /// "0x8ad599c3A0ff1De082011EFDDc58f1908eb6e6D8"])`
485    ///
486    /// ```rust
487    /// # use alloy_primitives::Address;
488    /// # use alloy_rpc_types_eth::Filter;
489    /// # fn main() {
490    /// let addresses = vec![
491    ///     "0xAc4b3DacB91461209Ae9d41EC517c2B9Cb1B7DAF".parse::<Address>().unwrap(),
492    ///     "0x8ad599c3A0ff1De082011EFDDc58f1908eb6e6D8".parse::<Address>().unwrap(),
493    /// ];
494    /// let filter = Filter::new().address(addresses);
495    /// # }
496    /// ```
497    #[must_use]
498    pub fn address<T: Into<ValueOrArray<Address>>>(mut self, address: T) -> Self {
499        self.address = address.into().into();
500        self
501    }
502
503    /// Given the event signature in string form, it hashes it and adds it to the topics to monitor
504    #[must_use]
505    pub fn event(self, event_name: &str) -> Self {
506        let hash = keccak256(event_name.as_bytes());
507        self.event_signature(hash)
508    }
509
510    /// Hashes all event signatures and sets them as array to event_signature(topic0)
511    #[must_use]
512    pub fn events(self, events: impl IntoIterator<Item = impl AsRef<[u8]>>) -> Self {
513        let events = events.into_iter().map(|e| keccak256(e.as_ref())).collect::<Vec<_>>();
514        self.event_signature(events)
515    }
516
517    /// Sets event_signature(topic0) (the event name for non-anonymous events)
518    #[must_use]
519    pub fn event_signature<T: Into<Topic>>(mut self, topic: T) -> Self {
520        self.topics[0] = topic.into();
521        self
522    }
523
524    /// Sets topic0 (the event name for non-anonymous events)
525    #[must_use]
526    #[deprecated(note = "use `event_signature` instead")]
527    pub fn topic0<T: Into<Topic>>(mut self, topic: T) -> Self {
528        self.topics[0] = topic.into();
529        self
530    }
531
532    /// Sets the 1st indexed topic
533    #[must_use]
534    pub fn topic1<T: Into<Topic>>(mut self, topic: T) -> Self {
535        self.topics[1] = topic.into();
536        self
537    }
538
539    /// Sets the 2nd indexed topic
540    #[must_use]
541    pub fn topic2<T: Into<Topic>>(mut self, topic: T) -> Self {
542        self.topics[2] = topic.into();
543        self
544    }
545
546    /// Sets the 3rd indexed topic
547    #[must_use]
548    pub fn topic3<T: Into<Topic>>(mut self, topic: T) -> Self {
549        self.topics[3] = topic.into();
550        self
551    }
552
553    /// Returns true if this is a range filter and has a from block
554    pub fn is_paginatable(&self) -> bool {
555        self.get_from_block().is_some()
556    }
557
558    /// Returns the numeric value of the `toBlock` field
559    pub fn get_to_block(&self) -> Option<u64> {
560        self.block_option.get_to_block().and_then(|b| b.as_number())
561    }
562
563    /// Returns the numeric value of the `fromBlock` field
564    pub fn get_from_block(&self) -> Option<u64> {
565        self.block_option.get_from_block().and_then(|b| b.as_number())
566    }
567
568    /// Returns the numeric value of the `fromBlock` field
569    pub const fn get_block_hash(&self) -> Option<B256> {
570        match self.block_option {
571            FilterBlockOption::AtBlockHash(hash) => Some(hash),
572            FilterBlockOption::Range { .. } => None,
573        }
574    }
575
576    /// Returns true if at least one topic is set
577    pub fn has_topics(&self) -> bool {
578        self.topics.iter().any(|t| !t.is_empty())
579    }
580}
581
582#[cfg(feature = "serde")]
583impl serde::Serialize for Filter {
584    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
585    where
586        S: serde::Serializer,
587    {
588        use serde::ser::SerializeStruct;
589
590        let mut s = serializer.serialize_struct("Filter", 5)?;
591        match self.block_option {
592            FilterBlockOption::Range { from_block, to_block } => {
593                if let Some(ref from_block) = from_block {
594                    s.serialize_field("fromBlock", from_block)?;
595                }
596
597                if let Some(ref to_block) = to_block {
598                    s.serialize_field("toBlock", to_block)?;
599                }
600            }
601
602            FilterBlockOption::AtBlockHash(ref h) => s.serialize_field("blockHash", h)?,
603        }
604
605        if let Some(address) = self.address.to_value_or_array() {
606            s.serialize_field("address", &address)?;
607        }
608
609        let mut filtered_topics = Vec::new();
610        let mut filtered_topics_len = 0;
611        for (i, topic) in self.topics.iter().enumerate() {
612            if !topic.is_empty() {
613                filtered_topics_len = i + 1;
614            }
615            filtered_topics.push(topic.to_value_or_array());
616        }
617        filtered_topics.truncate(filtered_topics_len);
618        s.serialize_field("topics", &filtered_topics)?;
619
620        s.end()
621    }
622}
623
624#[cfg(feature = "serde")]
625impl<'de> serde::Deserialize<'de> for Filter {
626    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
627    where
628        D: serde::Deserializer<'de>,
629    {
630        type RawAddressFilter = ValueOrArray<Option<Address>>;
631        type RawTopicsFilter = Vec<Option<ValueOrArray<Option<B256>>>>;
632
633        struct FilterVisitor;
634
635        impl<'de> serde::de::Visitor<'de> for FilterVisitor {
636            type Value = Filter;
637
638            fn expecting(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
639                formatter.write_str("Filter object")
640            }
641
642            fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
643            where
644                A: serde::de::MapAccess<'de>,
645            {
646                let mut from_block: Option<Option<BlockNumberOrTag>> = None;
647                let mut to_block: Option<Option<BlockNumberOrTag>> = None;
648                let mut block_hash: Option<Option<B256>> = None;
649                let mut address: Option<Option<RawAddressFilter>> = None;
650                let mut topics: Option<Option<RawTopicsFilter>> = None;
651
652                while let Some(key) = map.next_key::<String>()? {
653                    match key.as_str() {
654                        "fromBlock" => {
655                            if from_block.is_some() {
656                                return Err(serde::de::Error::duplicate_field("fromBlock"));
657                            }
658                            from_block = Some(map.next_value()?)
659                        }
660                        "toBlock" => {
661                            if to_block.is_some() {
662                                return Err(serde::de::Error::duplicate_field("toBlock"));
663                            }
664                            to_block = Some(map.next_value()?)
665                        }
666                        "blockHash" => {
667                            if block_hash.is_some() {
668                                return Err(serde::de::Error::duplicate_field("blockHash"));
669                            }
670                            block_hash = Some(map.next_value()?)
671                        }
672                        "address" => {
673                            if address.is_some() {
674                                return Err(serde::de::Error::duplicate_field("address"));
675                            }
676                            address = Some(map.next_value()?)
677                        }
678                        "topics" => {
679                            if topics.is_some() {
680                                return Err(serde::de::Error::duplicate_field("topics"));
681                            }
682                            topics = Some(map.next_value()?)
683                        }
684
685                        key => {
686                            return Err(serde::de::Error::unknown_field(
687                                key,
688                                &["fromBlock", "toBlock", "address", "topics", "blockHash"],
689                            ))
690                        }
691                    }
692                }
693
694                // conflict check between block_hash and from_block/to_block
695                let (block_hash, from_block, to_block) = if let Some(Some(hash)) = block_hash {
696                    if from_block.is_some_and(|inner| inner.is_some())
697                        || to_block.is_some_and(|inner| inner.is_some())
698                    {
699                        return Err(serde::de::Error::custom(
700                            "cannot specify both blockHash and fromBlock/toBlock, choose one or the other",
701                        ));
702                    }
703                    (Some(hash), None, None)
704                } else {
705                    (None, from_block.unwrap_or_default(), to_block.unwrap_or_default())
706                };
707
708                let address = address.flatten().map(|a| a.into()).unwrap_or_default();
709                let topics_vec = topics.flatten().unwrap_or_default();
710
711                // maximum allowed filter len
712                if topics_vec.len() > 4 {
713                    return Err(serde::de::Error::custom("exceeded maximum topics len"));
714                }
715                let mut topics: [Topic; 4] = [
716                    Default::default(),
717                    Default::default(),
718                    Default::default(),
719                    Default::default(),
720                ];
721                for (idx, topic) in topics_vec.into_iter().enumerate() {
722                    topics[idx] = topic.map(|t| t.into()).unwrap_or_default();
723                }
724
725                let block_option = block_hash
726                    .map_or(FilterBlockOption::Range { from_block, to_block }, |block_hash| {
727                        FilterBlockOption::AtBlockHash(block_hash)
728                    });
729
730                Ok(Filter { block_option, address, topics })
731            }
732        }
733
734        deserializer.deserialize_any(FilterVisitor)
735    }
736}
737
738/// Union type for representing a single value or a vector of values inside a filter
739#[derive(Clone, Debug, PartialEq, Eq, Hash)]
740pub enum ValueOrArray<T> {
741    /// A single value
742    Value(T),
743    /// A vector of values
744    Array(Vec<T>),
745}
746
747impl<T> ValueOrArray<T> {
748    /// Get the value if present.
749    pub const fn as_value(&self) -> Option<&T> {
750        if let Self::Value(value) = self {
751            Some(value)
752        } else {
753            None
754        }
755    }
756
757    /// Get the array if present.
758    pub fn as_array(&self) -> Option<&[T]> {
759        if let Self::Array(array) = self {
760            Some(array)
761        } else {
762            None
763        }
764    }
765
766    /// Check if the enum is a single value.
767    pub const fn is_value(&self) -> bool {
768        matches!(self, Self::Value(_))
769    }
770
771    /// Check if the enum is an array.
772    pub const fn is_array(&self) -> bool {
773        matches!(self, Self::Array(_))
774    }
775}
776
777impl From<Address> for ValueOrArray<Address> {
778    fn from(src: Address) -> Self {
779        Self::Value(src)
780    }
781}
782
783impl From<Vec<Address>> for ValueOrArray<Address> {
784    fn from(src: Vec<Address>) -> Self {
785        Self::Array(src)
786    }
787}
788
789impl From<Vec<B256>> for ValueOrArray<B256> {
790    fn from(src: Vec<B256>) -> Self {
791        Self::Array(src)
792    }
793}
794
795#[cfg(feature = "serde")]
796impl<T> serde::Serialize for ValueOrArray<T>
797where
798    T: serde::Serialize,
799{
800    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
801    where
802        S: serde::Serializer,
803    {
804        match self {
805            Self::Value(inner) => inner.serialize(serializer),
806            Self::Array(inner) => inner.serialize(serializer),
807        }
808    }
809}
810
811#[cfg(feature = "serde")]
812impl<'a, T> serde::Deserialize<'a> for ValueOrArray<T>
813where
814    T: serde::de::DeserializeOwned,
815{
816    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
817    where
818        D: serde::Deserializer<'a>,
819    {
820        let value = serde_json::Value::deserialize(deserializer)?;
821
822        if value.is_null() {
823            return Ok(Self::Array(Vec::new()));
824        }
825
826        #[derive(serde::Deserialize)]
827        #[serde(untagged)]
828        enum Variadic<T> {
829            Value(T),
830            Array(Vec<T>),
831        }
832
833        match serde_json::from_value::<Variadic<T>>(value).map_err(|err| {
834            serde::de::Error::custom(format!("Invalid variadic value or array type: {err}"))
835        })? {
836            Variadic::Value(val) => Ok(Self::Value(val)),
837            Variadic::Array(arr) => Ok(Self::Array(arr)),
838        }
839    }
840}
841
842/// Support for matching [Filter]s
843#[derive(Debug, Default)]
844pub struct FilteredParams {
845    /// The original filter, if any
846    pub filter: Option<Filter>,
847}
848
849impl FilteredParams {
850    /// Creates a new wrapper type for a [Filter], if any with flattened topics, that can be used
851    /// for matching
852    pub fn new(filter: Option<Filter>) -> Self {
853        filter.map_or_else(Default::default, |filter| Self { filter: Some(filter) })
854    }
855
856    /// Returns the [BloomFilter] for the given address
857    pub fn address_filter(address: &FilterSet<Address>) -> BloomFilter {
858        address.to_bloom_filter()
859    }
860
861    /// Returns the [BloomFilter] for the given topics
862    pub fn topics_filter(topics: &[FilterSet<B256>]) -> Vec<BloomFilter> {
863        topics.iter().map(|t| t.to_bloom_filter()).collect()
864    }
865
866    /// Returns `true` if the bloom matches the topics
867    pub fn matches_topics(bloom: Bloom, topic_filters: &[BloomFilter]) -> bool {
868        if topic_filters.is_empty() {
869            return true;
870        }
871
872        // for each filter, iterate through the list of filter blooms. for each set of filter
873        // (each BloomFilter), the given `bloom` must match at least one of them, unless the list is
874        // empty (no filters).
875        for filter in topic_filters {
876            if !filter.matches(bloom) {
877                return false;
878            }
879        }
880        true
881    }
882
883    /// Returns `true` if the bloom contains one of the address blooms, or the address blooms
884    /// list is empty (thus, no filters)
885    pub fn matches_address(bloom: Bloom, address_filter: &BloomFilter) -> bool {
886        address_filter.matches(bloom)
887    }
888
889    /// Returns true if the filter matches the given block number
890    pub fn filter_block_range(&self, block_number: u64) -> bool {
891        if self.filter.is_none() {
892            return true;
893        }
894        let filter = self.filter.as_ref().unwrap();
895        let mut res = true;
896
897        if let Some(BlockNumberOrTag::Number(num)) = filter.block_option.get_from_block() {
898            if *num > block_number {
899                res = false;
900            }
901        }
902
903        if let Some(to) = filter.block_option.get_to_block() {
904            match to {
905                BlockNumberOrTag::Number(num) => {
906                    if *num < block_number {
907                        res = false;
908                    }
909                }
910                BlockNumberOrTag::Earliest => {
911                    res = false;
912                }
913                _ => {}
914            }
915        }
916        res
917    }
918
919    /// Returns `true` if the filter matches the given block hash.
920    pub fn filter_block_hash(&self, block_hash: B256) -> bool {
921        if let Some(h) = self.filter.as_ref().and_then(|f| f.get_block_hash()) {
922            if h != block_hash {
923                return false;
924            }
925        }
926        true
927    }
928
929    /// Return `true` if the filter configured to match pending block.
930    /// This means that both from_block and to_block are set to the pending tag.
931    /// It calls [`Filter::is_pending_block_filter`] undercover.
932    pub fn is_pending_block_filter(&self) -> bool {
933        self.filter.as_ref().is_some_and(|f| f.is_pending_block_filter())
934    }
935
936    /// Returns `true` if the filter matches the given address.
937    pub fn filter_address(&self, address: &Address) -> bool {
938        self.filter.as_ref().map(|f| f.address.matches(address)).unwrap_or(true)
939    }
940
941    /// Returns `true` if the log matches the given topics
942    pub fn filter_topics(&self, log_topics: &[B256]) -> bool {
943        let topics = match self.filter.as_ref() {
944            None => return true,
945            Some(f) => &f.topics,
946        };
947        for topic_tuple in topics.iter().zip_longest(log_topics.iter()) {
948            match topic_tuple {
949                // We exhausted the `log.topics`, so if there's a filter set for
950                // this topic index, there is no match. Otherwise (empty filter), continue.
951                Left(filter_topic) => {
952                    if !filter_topic.is_empty() {
953                        return false;
954                    }
955                }
956                // We exhausted the filter topics, therefore any subsequent log topic
957                // will match.
958                Right(_) => return true,
959                // Check that `log_topic` is included in `filter_topic`
960                Both(filter_topic, log_topic) => {
961                    if !filter_topic.matches(log_topic) {
962                        return false;
963                    }
964                }
965            }
966        }
967        true
968    }
969}
970
971/// Response of the `eth_getFilterChanges` RPC.
972#[derive(Default, Clone, Debug, PartialEq, Eq)]
973#[cfg_attr(feature = "serde", derive(serde::Serialize))]
974#[cfg_attr(feature = "serde", serde(untagged))]
975pub enum FilterChanges<T = Transaction> {
976    /// Empty result.
977    #[cfg_attr(feature = "serde", serde(with = "empty_array"))]
978    #[default]
979    Empty,
980    /// New logs.
981    Logs(Vec<RpcLog>),
982    /// New hashes (block or transactions).
983    Hashes(Vec<B256>),
984    /// New transactions.
985    Transactions(Vec<T>),
986}
987
988impl From<Vec<RpcLog>> for FilterChanges {
989    fn from(logs: Vec<RpcLog>) -> Self {
990        Self::Logs(logs)
991    }
992}
993
994impl From<Vec<B256>> for FilterChanges {
995    fn from(hashes: Vec<B256>) -> Self {
996        Self::Hashes(hashes)
997    }
998}
999
1000impl From<Vec<Transaction>> for FilterChanges {
1001    fn from(transactions: Vec<Transaction>) -> Self {
1002        Self::Transactions(transactions)
1003    }
1004}
1005
1006impl<T> FilterChanges<T> {
1007    /// Get the hashes if present.
1008    pub fn as_hashes(&self) -> Option<&[B256]> {
1009        if let Self::Hashes(hashes) = self {
1010            Some(hashes)
1011        } else {
1012            None
1013        }
1014    }
1015
1016    /// Get the logs if present.
1017    pub fn as_logs(&self) -> Option<&[RpcLog]> {
1018        if let Self::Logs(logs) = self {
1019            Some(logs)
1020        } else {
1021            None
1022        }
1023    }
1024
1025    /// Get the transactions if present.
1026    pub fn as_transactions(&self) -> Option<&[T]> {
1027        if let Self::Transactions(transactions) = self {
1028            Some(transactions)
1029        } else {
1030            None
1031        }
1032    }
1033
1034    /// Check if the filter changes are empty.
1035    pub const fn is_empty(&self) -> bool {
1036        matches!(self, Self::Empty)
1037    }
1038
1039    /// Check if the filter changes contain logs.
1040    pub const fn is_logs(&self) -> bool {
1041        matches!(self, Self::Logs(_))
1042    }
1043
1044    /// Check if the filter changes contain hashes.
1045    pub const fn is_hashes(&self) -> bool {
1046        matches!(self, Self::Hashes(_))
1047    }
1048
1049    /// Check if the filter changes contain transactions.
1050    pub const fn is_transactions(&self) -> bool {
1051        matches!(self, Self::Transactions(_))
1052    }
1053}
1054
1055#[cfg(feature = "serde")]
1056mod empty_array {
1057    use serde::{Serialize, Serializer};
1058
1059    pub(super) fn serialize<S>(s: S) -> Result<S::Ok, S::Error>
1060    where
1061        S: Serializer,
1062    {
1063        (&[] as &[()]).serialize(s)
1064    }
1065}
1066
1067#[cfg(feature = "serde")]
1068impl<'de, T> serde::Deserialize<'de> for FilterChanges<T>
1069where
1070    T: serde::Deserialize<'de>,
1071{
1072    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1073    where
1074        D: serde::Deserializer<'de>,
1075    {
1076        #[derive(serde::Deserialize)]
1077        #[serde(untagged)]
1078        enum Changes<T = Transaction> {
1079            Hashes(Vec<B256>),
1080            Logs(Vec<RpcLog>),
1081            Transactions(Vec<T>),
1082        }
1083
1084        let changes = Changes::deserialize(deserializer)?;
1085        let changes = match changes {
1086            Changes::Logs(vals) => {
1087                if vals.is_empty() {
1088                    Self::Empty
1089                } else {
1090                    Self::Logs(vals)
1091                }
1092            }
1093            Changes::Hashes(vals) => {
1094                if vals.is_empty() {
1095                    Self::Empty
1096                } else {
1097                    Self::Hashes(vals)
1098                }
1099            }
1100            Changes::Transactions(vals) => {
1101                if vals.is_empty() {
1102                    Self::Empty
1103                } else {
1104                    Self::Transactions(vals)
1105                }
1106            }
1107        };
1108        Ok(changes)
1109    }
1110}
1111
1112/// Owned equivalent of a `SubscriptionId`
1113#[derive(Clone, Debug, PartialEq, Eq, Hash)]
1114#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1115#[cfg_attr(feature = "serde", serde(deny_unknown_fields))]
1116#[cfg_attr(feature = "serde", serde(untagged))]
1117pub enum FilterId {
1118    /// Numeric id
1119    Num(u64),
1120    /// String id
1121    Str(String),
1122}
1123
1124impl From<u64> for FilterId {
1125    fn from(num: u64) -> Self {
1126        Self::Num(num)
1127    }
1128}
1129
1130impl From<String> for FilterId {
1131    fn from(str: String) -> Self {
1132        Self::Str(str)
1133    }
1134}
1135
1136#[cfg(feature = "jsonrpsee-types")]
1137impl From<FilterId> for jsonrpsee_types::SubscriptionId<'_> {
1138    fn from(value: FilterId) -> Self {
1139        match value {
1140            FilterId::Num(n) => jsonrpsee_types::SubscriptionId::Num(n),
1141            FilterId::Str(s) => jsonrpsee_types::SubscriptionId::Str(s.into()),
1142        }
1143    }
1144}
1145
1146#[cfg(feature = "jsonrpsee-types")]
1147impl From<jsonrpsee_types::SubscriptionId<'_>> for FilterId {
1148    fn from(value: jsonrpsee_types::SubscriptionId<'_>) -> Self {
1149        match value {
1150            jsonrpsee_types::SubscriptionId::Num(n) => n.into(),
1151            jsonrpsee_types::SubscriptionId::Str(s) => s.into_owned().into(),
1152        }
1153    }
1154}
1155/// Specifies the kind of information you wish to receive from the `eth_newPendingTransactionFilter`
1156/// RPC endpoint.
1157///
1158/// When this type is used in a request, it determines whether the client wishes to receive:
1159/// - Only the transaction hashes (`Hashes` variant), or
1160/// - Full transaction details (`Full` variant).
1161#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
1162pub enum PendingTransactionFilterKind {
1163    /// Receive only the hashes of the transactions.
1164    #[default]
1165    Hashes,
1166    /// Receive full details of the transactions.
1167    Full,
1168}
1169
1170#[cfg(feature = "serde")]
1171impl serde::Serialize for PendingTransactionFilterKind {
1172    /// Serializes the `PendingTransactionFilterKind` into a boolean value:
1173    /// - `false` for `Hashes`
1174    /// - `true` for `Full`
1175    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1176    where
1177        S: serde::Serializer,
1178    {
1179        match self {
1180            Self::Hashes => false.serialize(serializer),
1181            Self::Full => true.serialize(serializer),
1182        }
1183    }
1184}
1185
1186#[cfg(feature = "serde")]
1187impl<'a> serde::Deserialize<'a> for PendingTransactionFilterKind {
1188    /// Deserializes a boolean value into `PendingTransactionFilterKind`:
1189    /// - `false` becomes `Hashes`
1190    /// - `true` becomes `Full`
1191    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1192    where
1193        D: serde::Deserializer<'a>,
1194    {
1195        let val = Option::<bool>::deserialize(deserializer)?;
1196        match val {
1197            Some(true) => Ok(Self::Full),
1198            _ => Ok(Self::Hashes),
1199        }
1200    }
1201}
1202
1203#[cfg(test)]
1204mod tests {
1205    use super::*;
1206    use serde_json::json;
1207    use similar_asserts::assert_eq;
1208
1209    #[cfg(feature = "serde")]
1210    fn serialize<T: serde::Serialize>(t: &T) -> serde_json::Value {
1211        serde_json::to_value(t).expect("Failed to serialize value")
1212    }
1213
1214    #[test]
1215    #[cfg(feature = "serde")]
1216    fn test_empty_filter_topics_list() {
1217        let s = r#"{"fromBlock": "0xfc359e", "toBlock": "0xfc359e", "topics": [["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925"], [], ["0x0000000000000000000000000c17e776cd218252adfca8d4e761d3fe757e9778"]]}"#;
1218        let filter = serde_json::from_str::<Filter>(s).unwrap();
1219        assert_eq!(
1220            filter.topics,
1221            [
1222                "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925"
1223                    .parse::<B256>()
1224                    .unwrap()
1225                    .into(),
1226                Default::default(),
1227                "0x0000000000000000000000000c17e776cd218252adfca8d4e761d3fe757e9778"
1228                    .parse::<B256>()
1229                    .unwrap()
1230                    .into(),
1231                Default::default(),
1232            ]
1233        );
1234    }
1235
1236    #[test]
1237    fn test_with_from_block_correct_range() {
1238        // Test scenario where from_block is less than to_block
1239        let original = FilterBlockOption::Range {
1240            from_block: Some(BlockNumberOrTag::Number(1)),
1241            to_block: Some(BlockNumberOrTag::Number(10)),
1242        };
1243        let updated = original.with_from_block(BlockNumberOrTag::Number(5));
1244        assert!(updated.ensure_valid_block_range().is_ok());
1245    }
1246
1247    #[test]
1248    fn test_with_from_block_failure() {
1249        // Test scenario where from_block is greater than to_block
1250        let original = FilterBlockOption::Range {
1251            from_block: Some(BlockNumberOrTag::Number(10)),
1252            to_block: Some(BlockNumberOrTag::Number(5)),
1253        };
1254
1255        assert!(matches!(
1256            original.ensure_valid_block_range(),
1257            Err(FilterBlockError::FromBlockGreaterThanToBlock { .. })
1258        ));
1259    }
1260
1261    #[test]
1262    #[cfg(feature = "serde")]
1263    fn test_block_hash() {
1264        let s =
1265            r#"{"blockHash":"0x58dc57ab582b282c143424bd01e8d923cddfdcda9455bad02a29522f6274a948"}"#;
1266        let filter = serde_json::from_str::<Filter>(s).unwrap();
1267        assert_eq!(
1268            filter.block_option,
1269            FilterBlockOption::AtBlockHash(
1270                "0x58dc57ab582b282c143424bd01e8d923cddfdcda9455bad02a29522f6274a948"
1271                    .parse()
1272                    .unwrap()
1273            )
1274        );
1275    }
1276
1277    #[test]
1278    #[cfg(feature = "serde")]
1279    fn test_filter_topics_middle_wildcard() {
1280        let s = r#"{"fromBlock": "0xfc359e", "toBlock": "0xfc359e", "topics": [["0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925"], [], [null, "0x0000000000000000000000000c17e776cd218252adfca8d4e761d3fe757e9778"]]}"#;
1281        let filter = serde_json::from_str::<Filter>(s).unwrap();
1282        assert_eq!(
1283            filter.topics,
1284            [
1285                "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925"
1286                    .parse::<B256>()
1287                    .unwrap()
1288                    .into(),
1289                Default::default(),
1290                Default::default(),
1291                Default::default(),
1292            ]
1293        );
1294    }
1295
1296    #[test]
1297    #[cfg(feature = "serde")]
1298    fn can_serde_value_or_array() {
1299        #[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
1300        struct Item {
1301            value: ValueOrArray<U256>,
1302        }
1303
1304        let item = Item { value: ValueOrArray::Value(U256::from(1u64)) };
1305        let json = serde_json::to_value(item.clone()).unwrap();
1306        let deserialized: Item = serde_json::from_value(json).unwrap();
1307        assert_eq!(item, deserialized);
1308
1309        let item = Item { value: ValueOrArray::Array(vec![U256::from(1u64), U256::ZERO]) };
1310        let json = serde_json::to_value(item.clone()).unwrap();
1311        let deserialized: Item = serde_json::from_value(json).unwrap();
1312        assert_eq!(item, deserialized);
1313    }
1314
1315    #[test]
1316    #[cfg(feature = "serde")]
1317    fn filter_serialization_test() {
1318        let t1 = "0000000000000000000000009729a6fbefefc8f6005933898b13dc45c3a2c8b7"
1319            .parse::<B256>()
1320            .unwrap();
1321        let t2 = B256::from([0; 32]);
1322        let t3 = U256::from(123);
1323
1324        let t1_padded = t1;
1325        let t3_padded = B256::from({
1326            let mut x = [0; 32];
1327            x[31] = 123;
1328            x
1329        });
1330
1331        let event = "ValueChanged(address,string,string)";
1332        let t0 = keccak256(event.as_bytes());
1333        let addr: Address = "f817796F60D268A36a57b8D2dF1B97B14C0D0E1d".parse().unwrap();
1334        let filter = Filter::new();
1335
1336        let ser = serialize(&filter);
1337        assert_eq!(ser, json!({ "topics": [] }));
1338
1339        let filter = filter.address(ValueOrArray::Value(addr));
1340
1341        let ser = serialize(&filter);
1342        assert_eq!(ser, json!({"address" : addr, "topics": []}));
1343
1344        let filter = filter.event(event);
1345
1346        // 0
1347        let ser = serialize(&filter);
1348        assert_eq!(ser, json!({ "address" : addr, "topics": [t0]}));
1349
1350        // 1
1351        let ser = serialize(&filter.clone().topic1(t1));
1352        assert_eq!(ser, json!({ "address" : addr, "topics": [t0, t1_padded]}));
1353
1354        // 2
1355        let ser = serialize(&filter.clone().topic2(t2));
1356        assert_eq!(ser, json!({ "address" : addr, "topics": [t0, null, t2]}));
1357
1358        // 3
1359        let ser = serialize(&filter.clone().topic3(t3));
1360        assert_eq!(ser, json!({ "address" : addr, "topics": [t0, null, null, t3_padded]}));
1361
1362        // 1 & 2
1363        let ser = serialize(&filter.clone().topic1(t1).topic2(t2));
1364        assert_eq!(ser, json!({ "address" : addr, "topics": [t0, t1_padded, t2]}));
1365
1366        // 1 & 3
1367        let ser = serialize(&filter.clone().topic1(t1).topic3(t3));
1368        assert_eq!(ser, json!({ "address" : addr, "topics": [t0, t1_padded, null, t3_padded]}));
1369
1370        // 2 & 3
1371        let ser = serialize(&filter.clone().topic2(t2).topic3(t3));
1372        assert_eq!(ser, json!({ "address" : addr, "topics": [t0, null, t2, t3_padded]}));
1373
1374        // 1 & 2 & 3
1375        let ser = serialize(&filter.topic1(t1).topic2(t2).topic3(t3));
1376        assert_eq!(ser, json!({ "address" : addr, "topics": [t0, t1_padded, t2, t3_padded]}));
1377    }
1378
1379    fn build_bloom(address: Address, topic1: B256, topic2: B256) -> Bloom {
1380        let mut block_bloom = Bloom::default();
1381        block_bloom.accrue(BloomInput::Raw(&address[..]));
1382        block_bloom.accrue(BloomInput::Raw(&topic1[..]));
1383        block_bloom.accrue(BloomInput::Raw(&topic2[..]));
1384        block_bloom
1385    }
1386
1387    fn topic_filter(topic1: B256, topic2: B256, topic3: B256) -> Filter {
1388        Filter {
1389            block_option: Default::default(),
1390            address: Default::default(),
1391            topics: [
1392                topic1.into(),
1393                vec![topic2, topic3].into(),
1394                Default::default(),
1395                Default::default(),
1396            ],
1397        }
1398    }
1399
1400    #[test]
1401    fn can_detect_different_topics() {
1402        let topic1 = B256::random();
1403        let topic2 = B256::random();
1404        let topic3 = B256::random();
1405
1406        let topics = topic_filter(topic1, topic2, topic3).topics;
1407        let topics_bloom = FilteredParams::topics_filter(&topics);
1408        assert!(!FilteredParams::matches_topics(
1409            build_bloom(Address::random(), B256::random(), B256::random()),
1410            &topics_bloom
1411        ));
1412    }
1413
1414    #[test]
1415    fn can_match_topic() {
1416        let topic1 = B256::random();
1417        let topic2 = B256::random();
1418        let topic3 = B256::random();
1419
1420        let topics = topic_filter(topic1, topic2, topic3).topics;
1421        let _topics_bloom = FilteredParams::topics_filter(&topics);
1422
1423        let topics_bloom = FilteredParams::topics_filter(&topics);
1424        assert!(FilteredParams::matches_topics(
1425            build_bloom(Address::random(), topic1, topic2),
1426            &topics_bloom
1427        ));
1428    }
1429
1430    #[test]
1431    fn can_match_empty_topics() {
1432        let filter = Filter {
1433            block_option: Default::default(),
1434            address: Default::default(),
1435            topics: Default::default(),
1436        };
1437        let topics = filter.topics;
1438
1439        let topics_bloom = FilteredParams::topics_filter(&topics);
1440        assert!(FilteredParams::matches_topics(
1441            build_bloom(Address::random(), B256::random(), B256::random()),
1442            &topics_bloom
1443        ));
1444    }
1445
1446    #[test]
1447    fn can_match_address_and_topics() {
1448        let rng_address = Address::random();
1449        let topic1 = B256::random();
1450        let topic2 = B256::random();
1451        let topic3 = B256::random();
1452
1453        let filter = Filter {
1454            block_option: Default::default(),
1455            address: rng_address.into(),
1456            topics: [
1457                topic1.into(),
1458                vec![topic2, topic3].into(),
1459                Default::default(),
1460                Default::default(),
1461            ],
1462        };
1463        let topics = filter.topics;
1464
1465        let address_filter = FilteredParams::address_filter(&filter.address);
1466        let topics_filter = FilteredParams::topics_filter(&topics);
1467        assert!(
1468            FilteredParams::matches_address(
1469                build_bloom(rng_address, topic1, topic2),
1470                &address_filter
1471            ) && FilteredParams::matches_topics(
1472                build_bloom(rng_address, topic1, topic2),
1473                &topics_filter
1474            )
1475        );
1476    }
1477
1478    #[test]
1479    fn can_match_topics_wildcard() {
1480        let topic1 = B256::random();
1481        let topic2 = B256::random();
1482        let topic3 = B256::random();
1483
1484        let filter = Filter {
1485            block_option: Default::default(),
1486            address: Default::default(),
1487            topics: [
1488                Default::default(),
1489                vec![topic2, topic3].into(),
1490                Default::default(),
1491                Default::default(),
1492            ],
1493        };
1494        let topics = filter.topics;
1495
1496        let topics_bloom = FilteredParams::topics_filter(&topics);
1497        assert!(FilteredParams::matches_topics(
1498            build_bloom(Address::random(), topic1, topic2),
1499            &topics_bloom
1500        ));
1501    }
1502
1503    #[test]
1504    fn can_match_topics_wildcard_mismatch() {
1505        let filter = Filter {
1506            block_option: Default::default(),
1507            address: Default::default(),
1508            topics: [
1509                Default::default(),
1510                vec![B256::random(), B256::random()].into(),
1511                Default::default(),
1512                Default::default(),
1513            ],
1514        };
1515        let topics_input = filter.topics;
1516
1517        let topics_bloom = FilteredParams::topics_filter(&topics_input);
1518        assert!(!FilteredParams::matches_topics(
1519            build_bloom(Address::random(), B256::random(), B256::random()),
1520            &topics_bloom
1521        ));
1522    }
1523
1524    #[test]
1525    fn can_match_address_filter() {
1526        let rng_address = Address::random();
1527        let filter = Filter {
1528            block_option: Default::default(),
1529            address: rng_address.into(),
1530            topics: Default::default(),
1531        };
1532        let address_bloom = FilteredParams::address_filter(&filter.address);
1533        assert!(FilteredParams::matches_address(
1534            build_bloom(rng_address, B256::random(), B256::random(),),
1535            &address_bloom
1536        ));
1537    }
1538
1539    #[test]
1540    fn can_detect_different_address() {
1541        let bloom_address = Address::random();
1542        let rng_address = Address::random();
1543        let filter = Filter {
1544            block_option: Default::default(),
1545            address: rng_address.into(),
1546            topics: Default::default(),
1547        };
1548        let address_bloom = FilteredParams::address_filter(&filter.address);
1549        assert!(!FilteredParams::matches_address(
1550            build_bloom(bloom_address, B256::random(), B256::random(),),
1551            &address_bloom
1552        ));
1553    }
1554
1555    #[test]
1556    #[cfg(feature = "serde")]
1557    fn can_convert_to_ethers_filter() {
1558        let json = json!(
1559                    {
1560          "fromBlock": "0x429d3b",
1561          "toBlock": "0x429d3b",
1562          "address": "0xb59f67a8bff5d8cd03f6ac17265c550ed8f33907",
1563          "topics": [
1564          "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
1565          "0x00000000000000000000000000b46c2526e227482e2ebb8f4c69e4674d262e75",
1566          "0x00000000000000000000000054a2d42a40f51259dedd1978f6c118a0f0eff078"
1567          ]
1568        }
1569            );
1570
1571        let filter: Filter = serde_json::from_value(json).unwrap();
1572        assert_eq!(
1573            filter,
1574            Filter {
1575                block_option: FilterBlockOption::Range {
1576                    from_block: Some(4365627u64.into()),
1577                    to_block: Some(4365627u64.into()),
1578                },
1579                address: "0xb59f67a8bff5d8cd03f6ac17265c550ed8f33907"
1580                    .parse::<Address>()
1581                    .unwrap()
1582                    .into(),
1583                topics: [
1584                    "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"
1585                        .parse::<B256>()
1586                        .unwrap()
1587                        .into(),
1588                    "0x00000000000000000000000000b46c2526e227482e2ebb8f4c69e4674d262e75"
1589                        .parse::<B256>()
1590                        .unwrap()
1591                        .into(),
1592                    "0x00000000000000000000000054a2d42a40f51259dedd1978f6c118a0f0eff078"
1593                        .parse::<B256>()
1594                        .unwrap()
1595                        .into(),
1596                    Default::default(),
1597                ],
1598            }
1599        );
1600    }
1601
1602    #[test]
1603    #[cfg(feature = "serde")]
1604    fn can_convert_to_ethers_filter_with_null_fields() {
1605        let json = json!(
1606                    {
1607          "fromBlock": "0x429d3b",
1608          "toBlock": "0x429d3b",
1609          "address": null,
1610          "topics": null
1611        }
1612            );
1613
1614        let filter: Filter = serde_json::from_value(json).unwrap();
1615        assert_eq!(
1616            filter,
1617            Filter {
1618                block_option: FilterBlockOption::Range {
1619                    from_block: Some(4365627u64.into()),
1620                    to_block: Some(4365627u64.into()),
1621                },
1622                address: Default::default(),
1623                topics: Default::default(),
1624            }
1625        );
1626    }
1627
1628    #[test]
1629    #[cfg(feature = "serde")]
1630    fn test_filter_with_null_range_block() {
1631        let json = json!(
1632                    {
1633          "fromBlock": null,
1634          "toBlock": null,
1635          "blockHash": "0xe903ebc49101d30b28d7256be411f81418bf6809ddbaefc40201b1b97f2e64ee",
1636          "address": null,
1637          "topics": null
1638        }
1639            );
1640
1641        let filter: Filter = serde_json::from_value(json).unwrap();
1642        assert_eq!(
1643            filter.block_option,
1644            FilterBlockOption::AtBlockHash(
1645                "0xe903ebc49101d30b28d7256be411f81418bf6809ddbaefc40201b1b97f2e64ee"
1646                    .parse()
1647                    .unwrap()
1648            )
1649        );
1650    }
1651
1652    #[test]
1653    #[cfg(feature = "serde")]
1654    fn test_filter_with_null_block_hash() {
1655        let json = json!(
1656                    {
1657          "fromBlock": "0x1",
1658          "toBlock": "0x2",
1659          "blockHash": null,
1660          "address": null,
1661          "topics": null
1662        }
1663            );
1664
1665        let filter: Filter = serde_json::from_value(json).unwrap();
1666        assert_eq!(
1667            filter.block_option,
1668            FilterBlockOption::Range { from_block: Some(1u64.into()), to_block: Some(2u64.into()) }
1669        );
1670    }
1671
1672    #[test]
1673    #[cfg(feature = "serde")]
1674    fn test_filter_with_null_block_hash_and_null_from_block() {
1675        let json = json!(
1676                    {
1677          "fromBlock": null,
1678          "toBlock": "0x2",
1679          "blockHash": null,
1680          "address": null,
1681          "topics": null
1682        }
1683            );
1684
1685        let filter: Filter = serde_json::from_value(json).unwrap();
1686        assert_eq!(
1687            filter.block_option,
1688            FilterBlockOption::Range { from_block: None, to_block: Some(2u64.into()) }
1689        );
1690    }
1691
1692    #[test]
1693    #[cfg(feature = "serde")]
1694    fn test_filter_with_null_block_hash_and_null_to_block() {
1695        let json = json!(
1696                    {
1697          "fromBlock": "0x1",
1698          "toBlock": null,
1699          "blockHash": null,
1700          "address": null,
1701          "topics": null
1702        }
1703            );
1704
1705        let filter: Filter = serde_json::from_value(json).unwrap();
1706        assert_eq!(
1707            filter.block_option,
1708            FilterBlockOption::Range { from_block: Some(1u64.into()), to_block: None }
1709        );
1710    }
1711
1712    #[test]
1713    fn test_is_pending_block_filter() {
1714        let filter = Filter {
1715            block_option: FilterBlockOption::Range {
1716                from_block: Some(BlockNumberOrTag::Pending),
1717                to_block: Some(BlockNumberOrTag::Pending),
1718            },
1719            address: "0xb59f67a8bff5d8cd03f6ac17265c550ed8f33907"
1720                .parse::<Address>()
1721                .unwrap()
1722                .into(),
1723            topics: [
1724                "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"
1725                    .parse::<B256>()
1726                    .unwrap()
1727                    .into(),
1728                "0x00000000000000000000000000b46c2526e227482e2ebb8f4c69e4674d262e75"
1729                    .parse::<B256>()
1730                    .unwrap()
1731                    .into(),
1732                "0x00000000000000000000000054a2d42a40f51259dedd1978f6c118a0f0eff078"
1733                    .parse::<B256>()
1734                    .unwrap()
1735                    .into(),
1736                Default::default(),
1737            ],
1738        };
1739        assert!(filter.is_pending_block_filter());
1740        let filter_params = FilteredParams::new(Some(filter));
1741        assert!(filter_params.is_pending_block_filter());
1742
1743        let filter = Filter {
1744            block_option: FilterBlockOption::Range {
1745                from_block: Some(4365627u64.into()),
1746                to_block: Some(4365627u64.into()),
1747            },
1748            address: "0xb59f67a8bff5d8cd03f6ac17265c550ed8f33907"
1749                .parse::<Address>()
1750                .unwrap()
1751                .into(),
1752            topics: [
1753                "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"
1754                    .parse::<B256>()
1755                    .unwrap()
1756                    .into(),
1757                "0x00000000000000000000000000b46c2526e227482e2ebb8f4c69e4674d262e75"
1758                    .parse::<B256>()
1759                    .unwrap()
1760                    .into(),
1761                "0x00000000000000000000000054a2d42a40f51259dedd1978f6c118a0f0eff078"
1762                    .parse::<B256>()
1763                    .unwrap()
1764                    .into(),
1765                Default::default(),
1766            ],
1767        };
1768        assert!(!filter.is_pending_block_filter());
1769        let filter_params = FilteredParams::new(Some(filter));
1770        assert!(!filter_params.is_pending_block_filter());
1771    }
1772
1773    #[test]
1774    fn test_filter_set_topic_extend() {
1775        let mut topic = Topic::default();
1776
1777        // extending with different types that can be converted into Topic
1778        topic =
1779            topic.extend(U256::from(123)).extend(Address::random()).extend(true).extend([0u8; 32]);
1780
1781        assert_eq!(topic.0.len(), 4);
1782
1783        topic = topic.extend(U256::from(123));
1784        assert_eq!(topic.0.len(), 4);
1785
1786        topic = topic.extend(U256::from(456));
1787        assert_eq!(topic.0.len(), 5);
1788    }
1789}