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#[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 pub fn matches(&self, bloom: Bloom) -> bool {
32 self.0.is_empty() || self.0.iter().any(|a| bloom.contains(a))
33 }
34}
35
36#[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 arr.iter().contains(&None) {
80 Self(Default::default())
81 } else {
82 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 pub fn is_empty(&self) -> bool {
108 self.0.is_empty()
109 }
110
111 pub fn matches(&self, value: &T) -> bool {
114 self.is_empty() || self.0.contains(value)
115 }
116
117 pub fn iter(&self) -> hash_set::Iter<'_, T> {
120 self.0.iter()
121 }
122}
123
124impl<T: AsRef<[u8]> + Eq + Hash> FilterSet<T> {
125 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 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
146pub type Topic = FilterSet<B256>;
148
149impl Topic {
150 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#[derive(Debug, PartialEq, Eq, thiserror::Error)]
187pub enum FilterBlockError {
188 #[error("`from_block` ({from}) is greater than `to_block` ({to})")]
190 FromBlockGreaterThanToBlock {
191 from: u64,
193 to: u64,
195 },
196}
197
198#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
200pub enum FilterBlockOption {
201 Range {
205 from_block: Option<BlockNumberOrTag>,
207 to_block: Option<BlockNumberOrTag>,
209 },
210 AtBlockHash(BlockHash),
212}
213
214impl FilterBlockOption {
215 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 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 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 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 pub const fn is_range(&self) -> bool {
249 matches!(self, Self::Range { .. })
250 }
251
252 pub const fn is_block_hash(&self) -> bool {
254 matches!(self, Self::AtBlockHash(_))
255 }
256
257 pub fn ensure_valid_block_range(&self) -> Result<(), FilterBlockError> {
259 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 #[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 #[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 #[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#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
346pub struct Filter {
347 pub block_option: FilterBlockOption,
350 pub address: FilterSet<Address>,
361 pub topics: [Topic; 4],
363}
364
365impl Filter {
366 pub fn new() -> Self {
368 Self::default()
369 }
370
371 #[must_use]
435 pub fn select(mut self, filter: impl Into<FilterBlockOption>) -> Self {
436 self.block_option = filter.into();
437 self
438 }
439
440 #[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 #[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 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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 pub fn is_paginatable(&self) -> bool {
555 self.get_from_block().is_some()
556 }
557
558 pub fn get_to_block(&self) -> Option<u64> {
560 self.block_option.get_to_block().and_then(|b| b.as_number())
561 }
562
563 pub fn get_from_block(&self) -> Option<u64> {
565 self.block_option.get_from_block().and_then(|b| b.as_number())
566 }
567
568 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 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 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 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#[derive(Clone, Debug, PartialEq, Eq, Hash)]
740pub enum ValueOrArray<T> {
741 Value(T),
743 Array(Vec<T>),
745}
746
747impl<T> ValueOrArray<T> {
748 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 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 pub const fn is_value(&self) -> bool {
768 matches!(self, Self::Value(_))
769 }
770
771 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#[derive(Debug, Default)]
844pub struct FilteredParams {
845 pub filter: Option<Filter>,
847}
848
849impl FilteredParams {
850 pub fn new(filter: Option<Filter>) -> Self {
853 filter.map_or_else(Default::default, |filter| Self { filter: Some(filter) })
854 }
855
856 pub fn address_filter(address: &FilterSet<Address>) -> BloomFilter {
858 address.to_bloom_filter()
859 }
860
861 pub fn topics_filter(topics: &[FilterSet<B256>]) -> Vec<BloomFilter> {
863 topics.iter().map(|t| t.to_bloom_filter()).collect()
864 }
865
866 pub fn matches_topics(bloom: Bloom, topic_filters: &[BloomFilter]) -> bool {
868 if topic_filters.is_empty() {
869 return true;
870 }
871
872 for filter in topic_filters {
876 if !filter.matches(bloom) {
877 return false;
878 }
879 }
880 true
881 }
882
883 pub fn matches_address(bloom: Bloom, address_filter: &BloomFilter) -> bool {
886 address_filter.matches(bloom)
887 }
888
889 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 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 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 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 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 Left(filter_topic) => {
952 if !filter_topic.is_empty() {
953 return false;
954 }
955 }
956 Right(_) => return true,
959 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#[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 #[cfg_attr(feature = "serde", serde(with = "empty_array"))]
978 #[default]
979 Empty,
980 Logs(Vec<RpcLog>),
982 Hashes(Vec<B256>),
984 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 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 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 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 pub const fn is_empty(&self) -> bool {
1036 matches!(self, Self::Empty)
1037 }
1038
1039 pub const fn is_logs(&self) -> bool {
1041 matches!(self, Self::Logs(_))
1042 }
1043
1044 pub const fn is_hashes(&self) -> bool {
1046 matches!(self, Self::Hashes(_))
1047 }
1048
1049 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#[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 Num(u64),
1120 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#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
1162pub enum PendingTransactionFilterKind {
1163 #[default]
1165 Hashes,
1166 Full,
1168}
1169
1170#[cfg(feature = "serde")]
1171impl serde::Serialize for PendingTransactionFilterKind {
1172 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 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 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 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 let ser = serialize(&filter);
1348 assert_eq!(ser, json!({ "address" : addr, "topics": [t0]}));
1349
1350 let ser = serialize(&filter.clone().topic1(t1));
1352 assert_eq!(ser, json!({ "address" : addr, "topics": [t0, t1_padded]}));
1353
1354 let ser = serialize(&filter.clone().topic2(t2));
1356 assert_eq!(ser, json!({ "address" : addr, "topics": [t0, null, t2]}));
1357
1358 let ser = serialize(&filter.clone().topic3(t3));
1360 assert_eq!(ser, json!({ "address" : addr, "topics": [t0, null, null, t3_padded]}));
1361
1362 let ser = serialize(&filter.clone().topic1(t1).topic2(t2));
1364 assert_eq!(ser, json!({ "address" : addr, "topics": [t0, t1_padded, t2]}));
1365
1366 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 let ser = serialize(&filter.clone().topic2(t2).topic3(t3));
1372 assert_eq!(ser, json!({ "address" : addr, "topics": [t0, null, t2, t3_padded]}));
1373
1374 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 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}