openzeppelin_monitor/utils/tests/builders/midnight/
block.rs1use crate::models::{
2	MidnightBaseTransaction, MidnightBlock, MidnightBlockDigest, MidnightBlockHeader,
3	MidnightRpcBlock, MidnightRpcTransactionEnum,
4};
5
6#[derive(Debug)]
8pub struct BlockBuilder {
9	header: MidnightBlockHeader,
10	body: Vec<MidnightRpcTransactionEnum>,
11	transactions_index: Vec<(String, String)>,
12}
13
14impl Default for BlockBuilder {
15	fn default() -> Self {
17		Self {
18			header: MidnightBlockHeader {
19				parent_hash: "0x0000000000000000000000000000000000000000000000000000000000000000"
20					.to_string(),
21				number: "0".to_string(),
22				state_root: "0x0000000000000000000000000000000000000000000000000000000000000000"
23					.to_string(),
24				extrinsics_root:
25					"0x0000000000000000000000000000000000000000000000000000000000000000".to_string(),
26				digest: MidnightBlockDigest { logs: vec![] },
27			},
28			body: vec![],
29			transactions_index: vec![],
30		}
31	}
32}
33
34impl BlockBuilder {
35	pub fn new() -> Self {
37		Self::default()
38	}
39
40	pub fn header(mut self, header: MidnightBlockHeader) -> Self {
42		self.header = header;
43		self
44	}
45
46	pub fn number(mut self, number: u64) -> Self {
48		self.header.number = format!("0x{:x}", number);
49		self
50	}
51
52	pub fn parent_hash(mut self, parent_hash: String) -> Self {
54		self.header.parent_hash = parent_hash;
55		self
56	}
57
58	pub fn body(mut self, body: Vec<MidnightRpcTransactionEnum>) -> Self {
60		self.body = body;
61		self
62	}
63
64	pub fn add_transaction(mut self, transaction: MidnightRpcTransactionEnum) -> Self {
66		self.body.push(transaction);
67		self
68	}
69
70	pub fn add_rpc_transaction(mut self, transaction: MidnightBaseTransaction) -> Self {
72		let tx_hash = transaction.clone().tx_hash;
73		let tx_operation = MidnightRpcTransactionEnum::MidnightTransaction {
74			tx_raw: "".to_string(),
75			tx: transaction,
76		};
77
78		self.body.push(tx_operation.clone());
79
80		self.transactions_index.push((tx_hash, "".to_string()));
83		self
84	}
85
86	pub fn transactions_index(mut self, transactions_index: Vec<(String, String)>) -> Self {
88		self.transactions_index = transactions_index;
89		self
90	}
91
92	pub fn build(self) -> MidnightBlock {
94		let base_block = MidnightRpcBlock {
95			header: self.header,
96			body: self.body,
97			transactions_index: self.transactions_index,
98		};
99
100		MidnightBlock::from(base_block)
101	}
102}
103
104#[cfg(test)]
105mod tests {
106	use super::*;
107	use crate::utils::tests::builders::midnight::transaction::TransactionBuilder;
108
109	#[test]
110	fn test_builder_default() {
111		let block = BlockBuilder::new().build();
112		assert_eq!(block.header.number, "0");
113		assert_eq!(
114			block.header.parent_hash,
115			"0x0000000000000000000000000000000000000000000000000000000000000000"
116		);
117		assert_eq!(
118			block.header.state_root,
119			"0x0000000000000000000000000000000000000000000000000000000000000000"
120		);
121		assert_eq!(
122			block.header.extrinsics_root,
123			"0x0000000000000000000000000000000000000000000000000000000000000000"
124		);
125		assert!(block.body.is_empty());
126		assert!(block.transactions_index.is_empty());
127	}
128
129	#[test]
130	fn test_builder_with_header() {
131		let header = MidnightBlockHeader {
132			number: "123".to_string(),
133			parent_hash: "0xabc".to_string(),
134			..Default::default()
135		};
136		let block = BlockBuilder::new().header(header.clone()).build();
137		assert_eq!(block.header, header);
138	}
139
140	#[test]
141	fn test_builder_with_number() {
142		let number = 123u64;
143		let block = BlockBuilder::new().number(number).build();
144		assert_eq!(block.header.number, format!("0x{:x}", number));
145	}
146
147	#[test]
148	fn test_builder_with_parent_hash() {
149		let parent_hash = "0xabc".to_string();
150		let block = BlockBuilder::new().parent_hash(parent_hash.clone()).build();
151		assert_eq!(block.header.parent_hash, parent_hash);
152	}
153
154	#[test]
155	fn test_builder_with_body() {
156		let tx1 = TransactionBuilder::new()
157			.add_call_operation("0x123".to_string(), "main".to_string())
158			.build();
159		let tx2 = TransactionBuilder::new()
160			.add_deploy_operation("0x456".to_string())
161			.build();
162
163		let body = vec![
164			MidnightRpcTransactionEnum::MidnightTransaction {
165				tx_raw: "".to_string(),
166				tx: tx1.into(),
167			},
168			MidnightRpcTransactionEnum::MidnightTransaction {
169				tx_raw: "".to_string(),
170				tx: tx2.into(),
171			},
172		];
173
174		let block = BlockBuilder::new().body(body.clone()).build();
175		assert_eq!(block.body, body);
176	}
177
178	#[test]
179	fn test_builder_add_transaction() {
180		let tx = TransactionBuilder::new()
181			.add_call_operation("0x123".to_string(), "main".to_string())
182			.build();
183
184		let rpc_tx = MidnightRpcTransactionEnum::MidnightTransaction {
185			tx_raw: "".to_string(),
186			tx: tx.into(),
187		};
188
189		let block = BlockBuilder::new().add_transaction(rpc_tx.clone()).build();
190		assert_eq!(block.body, vec![rpc_tx]);
191	}
192
193	#[test]
194	fn test_builder_add_rpc_transaction() {
195		let tx = TransactionBuilder::new()
196			.add_call_operation("0x123".to_string(), "main".to_string())
197			.build();
198
199		let block = BlockBuilder::new()
200			.add_rpc_transaction(tx.clone().into())
201			.build();
202		assert_eq!(
203			block.body,
204			vec![MidnightRpcTransactionEnum::MidnightTransaction {
205				tx_raw: "".to_string(),
206				tx: tx.into(),
207			}]
208		);
209	}
210
211	#[test]
212	fn test_builder_with_transactions_index() {
213		let transactions_index = vec![
214			("0x123".to_string(), "0xabc".to_string()),
215			("0x456".to_string(), "0xdef".to_string()),
216		];
217		let block = BlockBuilder::new()
218			.transactions_index(transactions_index.clone())
219			.build();
220		assert_eq!(block.transactions_index, transactions_index);
221	}
222
223	#[test]
224	fn test_builder_complete_block() {
225		let tx1 = TransactionBuilder::new()
227			.add_call_operation("0x123".to_string(), "main".to_string())
228			.build();
229		let tx2 = TransactionBuilder::new()
230			.add_deploy_operation("0x456".to_string())
231			.build();
232
233		let transactions_index = vec![
235			("0x123".to_string(), "0xabc".to_string()),
236			("0x456".to_string(), "0xdef".to_string()),
237		];
238
239		let block = BlockBuilder::new()
241			.number(123)
242			.parent_hash("0xparent".to_string())
243			.add_rpc_transaction(tx1.into())
244			.add_rpc_transaction(tx2.into())
245			.transactions_index(transactions_index.clone())
246			.build();
247
248		assert_eq!(block.header.number, "0x7b");
250		assert_eq!(block.header.parent_hash, "0xparent");
251		assert_eq!(block.body.len(), 2);
252		assert_eq!(block.transactions_index, transactions_index);
253	}
254
255	#[test]
256	fn test_builder_multiple_transactions() {
257		let tx1 = TransactionBuilder::new()
258			.add_call_operation("0x123".to_string(), "main".to_string())
259			.build();
260		let tx2 = TransactionBuilder::new()
261			.add_deploy_operation("0x456".to_string())
262			.build();
263		let tx3 = TransactionBuilder::new()
264			.add_fallible_coins_operation()
265			.build();
266
267		let block = BlockBuilder::new()
268			.add_rpc_transaction(tx1.into())
269			.add_rpc_transaction(tx2.into())
270			.add_rpc_transaction(tx3.into())
271			.build();
272
273		assert_eq!(block.body.len(), 3);
274	}
275}