fuel_streams_core/blocks/
subjects.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
use fuel_streams_macros::subject::{IntoSubject, Subject, SubjectBuildable};

use crate::types::*;

/// Represents a NATS subject for blocks in the Fuel network.
///
/// This subject format allows for efficient querying and filtering of blocks
/// based on their producer and height.
///
/// # Examples
///
/// Creating a subject for a specific block:
///
/// ```
/// # use fuel_streams_core::blocks::BlocksSubject;
/// # use fuel_streams_core::types::*;
/// # use fuel_streams_macros::subject::IntoSubject;
/// let subject = BlocksSubject {
///     producer: Some(Address::zeroed()),
///     height: Some(23.into()),
/// };
/// assert_eq!(subject.parse(), "blocks.0x0000000000000000000000000000000000000000000000000000000000000000.23");
/// ```
///
/// All blocks wildcard:
///
/// ```
/// # use fuel_streams_core::blocks::BlocksSubject;
/// assert_eq!(BlocksSubject::WILDCARD, "blocks.>");
/// ```
///
/// Creating a subject query using the `wildcard` method for flexible parameter-based filtering
///
/// ```
/// # use fuel_streams_core::blocks::BlocksSubject;
/// # use fuel_streams_core::types::*;
/// let wildcard = BlocksSubject::wildcard(None, Some(23.into()));
/// assert_eq!(wildcard, "blocks.*.23");
/// ```
///
/// Using the builder pattern for flexible subject construction:
/// This approach allows for step-by-step creation of a `BlocksSubject`,
///
/// ```
/// # use fuel_streams_core::blocks::BlocksSubject;
/// # use fuel_streams_core::types::*;
/// # use fuel_streams_macros::subject::*;
/// let subject = BlocksSubject::new()
///     .with_producer(Some(Address::zeroed()))
///     .with_height(Some(23.into()));
/// assert_eq!(subject.parse(), "blocks.0x0000000000000000000000000000000000000000000000000000000000000000.23");
/// ```
#[derive(Subject, Debug, Clone, Default)]
#[subject_wildcard = "blocks.>"]
#[subject_format = "blocks.{producer}.{height}"]
pub struct BlocksSubject {
    pub producer: Option<Address>,
    pub height: Option<BlockHeight>,
}

impl From<&Block> for BlocksSubject {
    fn from(block: &Block) -> Self {
        let block_height = *block.header().height();
        BlocksSubject::new().with_height(Some(BlockHeight::from(block_height)))
    }
}

#[cfg(test)]
mod test {
    use pretty_assertions::assert_eq;

    use super::*;

    #[test]
    fn block_subjects_from_block() {
        let mock_block = &MockBlock::build(1);
        let subject: BlocksSubject = mock_block.into();

        assert!(subject.producer.is_none());
        assert_eq!(subject.height.unwrap(), mock_block.clone().into());
    }
}