openzeppelin_monitor/models/blockchain/solana/
block.rs1use serde::{Deserialize, Serialize};
7use std::ops::Deref;
8
9use crate::models::SolanaTransaction;
10
11#[derive(Debug, Serialize, Deserialize, Clone, Default)]
16#[serde(rename_all = "camelCase")]
17pub struct ConfirmedBlock {
18 pub slot: u64,
20
21 pub blockhash: String,
23
24 pub previous_blockhash: String,
26
27 pub parent_slot: u64,
29
30 pub block_time: Option<i64>,
32
33 pub block_height: Option<u64>,
35
36 #[serde(default)]
38 pub transactions: Vec<SolanaTransaction>,
39}
40
41#[derive(Debug, Serialize, Deserialize, Clone, Default)]
46pub struct Block(pub ConfirmedBlock);
47
48impl Block {
49 pub fn number(&self) -> Option<u64> {
51 Some(self.0.slot)
52 }
53
54 pub fn blockhash(&self) -> &str {
56 &self.0.blockhash
57 }
58
59 pub fn block_time(&self) -> Option<i64> {
61 self.0.block_time
62 }
63}
64
65impl From<ConfirmedBlock> for Block {
66 fn from(confirmed_block: ConfirmedBlock) -> Self {
67 Self(confirmed_block)
68 }
69}
70
71impl Deref for Block {
72 type Target = ConfirmedBlock;
73
74 fn deref(&self) -> &Self::Target {
75 &self.0
76 }
77}
78
79#[cfg(test)]
80mod tests {
81 use super::*;
82
83 #[test]
84 fn test_block_creation_and_number() {
85 let confirmed_block = ConfirmedBlock {
86 slot: 123456789,
87 blockhash: "4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZAMdL4VZHirAn".to_string(),
88 previous_blockhash: "3sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZAMdL4VZHirAn".to_string(),
89 parent_slot: 123456788,
90 block_time: Some(1234567890),
91 block_height: Some(100000000),
92 transactions: vec![],
93 };
94
95 let block = Block::from(confirmed_block.clone());
96
97 assert_eq!(block.number(), Some(123456789));
99
100 assert_eq!(
102 block.blockhash,
103 "4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZAMdL4VZHirAn"
104 );
105 assert_eq!(block.slot, 123456789);
106 assert_eq!(block.block_time, Some(1234567890));
107 }
108
109 #[test]
110 fn test_default_implementation() {
111 let block = Block::default();
112
113 assert_eq!(block.slot, 0);
114 assert_eq!(block.blockhash, "");
115 assert_eq!(block.previous_blockhash, "");
116 assert_eq!(block.parent_slot, 0);
117 assert!(block.block_time.is_none());
118 assert!(block.block_height.is_none());
119 assert!(block.transactions.is_empty());
120 }
121
122 #[test]
123 fn test_serde_serialization() {
124 let confirmed_block = ConfirmedBlock {
125 slot: 123456789,
126 blockhash: "4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZAMdL4VZHirAn".to_string(),
127 previous_blockhash: "3sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZAMdL4VZHirAn".to_string(),
128 parent_slot: 123456788,
129 block_time: Some(1234567890),
130 block_height: Some(100000000),
131 transactions: vec![],
132 };
133
134 let block = Block(confirmed_block);
135
136 let serialized = serde_json::to_string(&block).unwrap();
138
139 let deserialized: Block = serde_json::from_str(&serialized).unwrap();
141
142 assert_eq!(
143 deserialized.blockhash,
144 "4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZAMdL4VZHirAn"
145 );
146 assert_eq!(deserialized.slot, 123456789);
147 assert_eq!(deserialized.number(), Some(123456789));
148 }
149
150 #[test]
151 fn test_block_helpers() {
152 let confirmed_block = ConfirmedBlock {
153 slot: 123456789,
154 blockhash: "4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZAMdL4VZHirAn".to_string(),
155 previous_blockhash: "3sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZAMdL4VZHirAn".to_string(),
156 parent_slot: 123456788,
157 block_time: Some(1234567890),
158 block_height: Some(100000000),
159 transactions: vec![],
160 };
161
162 let block = Block::from(confirmed_block);
163
164 assert_eq!(
165 block.blockhash(),
166 "4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZAMdL4VZHirAn"
167 );
168 assert_eq!(block.block_time(), Some(1234567890));
169 }
170}