starknet_rust_providers/sequencer/models/
block.rs1use serde::Deserialize;
2use serde_with::serde_as;
3use starknet_rust_core::{
4 serde::unsigned_field_element::{UfeHex, UfeHexOption},
5 types::{Felt, L1DataAvailabilityMode, ResourcePrice},
6};
7
8use super::{ConfirmedTransactionReceipt, TransactionType};
9
10#[derive(Debug, Clone, Copy)]
11pub enum BlockId {
12 Hash(Felt),
13 Number(u64),
14 Pending,
15 Latest,
16}
17
18#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Eq)]
19#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
20#[cfg_attr(feature = "no_unknown_fields", serde(deny_unknown_fields))]
21pub enum BlockStatus {
22 Pending,
24 Aborted,
26 Reverted,
28 AcceptedOnL2,
30 AcceptedOnL1,
32}
33
34#[serde_as]
35#[derive(Debug, Deserialize)]
36#[cfg_attr(feature = "no_unknown_fields", serde(deny_unknown_fields))]
37pub struct Block {
38 #[serde(default)]
39 #[serde_as(as = "UfeHexOption")]
40 pub block_hash: Option<Felt>,
41 pub block_number: Option<u64>,
42 #[serde_as(as = "UfeHex")]
43 pub parent_block_hash: Felt,
44 pub timestamp: u64,
45 #[serde(default)]
47 #[serde_as(as = "UfeHexOption")]
48 pub sequencer_address: Option<Felt>,
49 #[serde(default)]
50 #[serde_as(as = "UfeHexOption")]
51 pub state_root: Option<Felt>,
52 #[serde(default)]
53 #[serde_as(as = "UfeHexOption")]
54 pub transaction_commitment: Option<Felt>,
55 #[serde(default)]
56 #[serde_as(as = "UfeHexOption")]
57 pub event_commitment: Option<Felt>,
58 pub status: BlockStatus,
59 pub l1_da_mode: L1DataAvailabilityMode,
60 pub l1_gas_price: ResourcePrice,
61 pub l2_gas_price: ResourcePrice,
62 pub l1_data_gas_price: ResourcePrice,
63 pub transactions: Vec<TransactionType>,
64 pub transaction_receipts: Vec<ConfirmedTransactionReceipt>,
65 pub starknet_version: Option<String>,
67}
68
69#[cfg(test)]
70mod tests {
71 use super::{super::transaction_receipt::TransactionExecutionStatus, *};
72
73 #[test]
74 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
75 fn test_block_deser_with_transactions() {
76 let raw = include_str!(
77 "../../../test-data/raw_gateway_responses/get_block/1_with_transactions.txt"
78 );
79
80 let block: Block = serde_json::from_str(raw).unwrap();
81
82 assert_eq!(block.block_number.unwrap(), 100);
83 assert_eq!(block.status, BlockStatus::AcceptedOnL1);
84 assert_eq!(
85 block.state_root.unwrap(),
86 Felt::from_hex("051098918fd96edda4e251f695181c063e21fb0666352e3469db507c7fd62b89")
87 .unwrap()
88 );
89 assert_eq!(
90 block.transaction_commitment.unwrap(),
91 Felt::from_hex("0576db32d35cf011694a73c6ce400d5d77f768cbd77ee7cf87d12902e0f9b4ec")
92 .unwrap()
93 );
94 assert_eq!(
95 block.event_commitment.unwrap(),
96 Felt::from_hex("01c972780140fd16dde94639226ca25818e4f24ecd5b5c3065cc1f5f5fc410f9")
97 .unwrap()
98 );
99 assert_eq!(block.transactions.len(), 4);
100 assert_eq!(block.transaction_receipts.len(), 4);
101
102 if let TransactionType::InvokeFunction(tx) = &block.transactions[0] {
103 assert_eq!(tx.calldata.len(), 16);
104 } else {
105 panic!("Did not deserialize Transaction::InvokeFunction properly");
106 }
107 let receipt = &block.transaction_receipts[0];
108 assert_eq!(receipt.execution_resources.as_ref().unwrap().n_steps, 10552);
109 }
110
111 #[test]
112 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
113 fn test_block_deser_with_messages() {
114 let raw =
116 include_str!("../../../test-data/raw_gateway_responses/get_block/2_with_messages.txt");
117
118 let block: Block = serde_json::from_str(raw).unwrap();
119
120 assert_eq!(block.block_number.unwrap(), 25);
121 assert_eq!(block.transaction_receipts.len(), 11);
122 let receipt = &block.transaction_receipts[10];
123 assert_eq!(receipt.l2_to_l1_messages.len(), 1);
124 assert_eq!(receipt.l2_to_l1_messages[0].payload.len(), 2);
125 }
126
127 #[test]
128 #[ignore = "block with the same criteria not found in alpha-sepolia yet"]
129 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
130 fn test_block_deser_with_messages_without_nonce() {
131 let raw = include_str!(
133 "../../../test-data/raw_gateway_responses/get_block/9_with_messages_without_nonce.txt"
134 );
135
136 let block: Block = serde_json::from_str(raw).unwrap();
137
138 assert_eq!(block.block_number.unwrap(), 1564);
139 assert_eq!(block.transaction_receipts.len(), 4);
140 let receipt = &block.transaction_receipts[1];
141 assert_eq!(receipt.l2_to_l1_messages.len(), 1);
142 assert_eq!(receipt.l2_to_l1_messages[0].payload.len(), 2);
143
144 let receipt = &block.transaction_receipts[2];
145 assert!(receipt.l1_to_l2_consumed_message.is_some());
146 }
147
148 #[test]
149 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
150 fn test_block_deser_with_events() {
151 let raw =
153 include_str!("../../../test-data/raw_gateway_responses/get_block/3_with_events.txt");
154
155 let block: Block = serde_json::from_str(raw).unwrap();
156
157 assert_eq!(block.block_number.unwrap(), 4);
158 assert_eq!(block.transaction_receipts.len(), 4);
159 let receipt = &block.transaction_receipts[3];
160 assert_eq!(receipt.events.len(), 1);
161 assert_eq!(receipt.events[0].keys.len(), 1);
162 assert_eq!(receipt.events[0].data.len(), 4);
163 }
164
165 #[test]
166 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
167 fn test_block_deser_pending() {
168 let raw = include_str!("../../../test-data/raw_gateway_responses/get_block/4_pending.txt");
170
171 let block: Block = serde_json::from_str(raw).unwrap();
172
173 assert!(block.block_hash.is_none());
174 assert!(block.block_number.is_none());
175 assert!(block.state_root.is_none());
176 assert_eq!(block.status, BlockStatus::Pending);
177 }
178
179 #[test]
180 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
181 fn test_block_deser_new_attributes_0_8_2() {
182 let new_block: Block = serde_json::from_str(include_str!(
184 "../../../test-data/raw_gateway_responses/get_block/6_with_sequencer_address.txt"
185 ))
186 .unwrap();
187 assert!(new_block.sequencer_address.is_some());
188 }
189
190 #[test]
191 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
192 fn test_block_deser_new_attributes_0_9_1() {
193 let new_block: Block = serde_json::from_str(include_str!(
195 "../../../test-data/raw_gateway_responses/get_block/8_with_starknet_version.txt"
196 ))
197 .unwrap();
198 assert!(new_block.starknet_version.is_some());
199 }
200
201 #[test]
202 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
203 fn test_block_deser_with_declare_tx() {
204 let raw = include_str!(
205 "../../../test-data/raw_gateway_responses/get_block/7_with_declare_tx.txt"
206 );
207
208 let block: Block = serde_json::from_str(raw).unwrap();
209
210 let tx = match &block.transactions[2] {
211 TransactionType::Declare(tx) => tx,
212 _ => panic!("Unexpected tx type"),
213 };
214
215 assert_eq!(
216 tx.sender_address,
217 Felt::from_hex("0x68922eb87daed71fc3099031e178b6534fc39a570022342e8c166024da893f5")
218 .unwrap()
219 );
220 }
221
222 #[test]
223 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
224 fn test_block_deser_with_l1_handler() {
225 let raw = include_str!(
226 "../../../test-data/raw_gateway_responses/get_block/10_with_l1_handler.txt"
227 );
228
229 let block: Block = serde_json::from_str(raw).unwrap();
230
231 let tx = match &block.transactions[0] {
232 TransactionType::L1Handler(tx) => tx,
233 _ => panic!("Unexpected tx type"),
234 };
235
236 assert_eq!(
237 tx.contract_address,
238 Felt::from_hex("0x4c5772d1914fe6ce891b64eb35bf3522aeae1315647314aac58b01137607f3f")
239 .unwrap()
240 );
241 }
242
243 #[test]
244 #[ignore = "block with the same criteria not found in alpha-sepolia yet"]
245 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
246 fn test_block_deser_without_execution_resources() {
247 let raw = include_str!(
248 "../../../test-data/raw_gateway_responses/get_block/11_without_execution_resources.txt"
249 );
250
251 let block: Block = serde_json::from_str(raw).unwrap();
252
253 let receipt = &block.transaction_receipts[17];
254
255 assert!(receipt.execution_resources.is_none());
256 }
257
258 #[test]
259 #[ignore = "block with the same criteria not found in alpha-sepolia yet"]
260 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
261 fn test_block_deser_l1_handler_without_nonce() {
262 let raw = include_str!(
263 "../../../test-data/raw_gateway_responses/get_block/12_l1_handler_without_nonce.txt"
264 );
265
266 let block: Block = serde_json::from_str(raw).unwrap();
267
268 let tx = match &block.transactions[22] {
269 TransactionType::L1Handler(tx) => tx,
270 _ => panic!("Unexpected tx type"),
271 };
272
273 assert!(tx.nonce.is_none());
274 }
275
276 #[test]
277 #[ignore = "block with the same criteria not found in alpha-sepolia yet"]
278 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
279 fn test_block_deser_without_entry_point() {
280 let raw = include_str!(
281 "../../../test-data/raw_gateway_responses/get_block/13_without_entry_point.txt"
282 );
283
284 let block: Block = serde_json::from_str(raw).unwrap();
285
286 let tx = match &block.transactions[16] {
287 TransactionType::InvokeFunction(tx) => tx,
288 _ => panic!("Unexpected tx type"),
289 };
290
291 assert!(tx.entry_point_selector.is_none());
292 }
293
294 #[test]
295 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
296 fn test_block_deser_with_deploy_account() {
297 let raw = include_str!(
298 "../../../test-data/raw_gateway_responses/get_block/14_deploy_account.txt"
299 );
300
301 let block: Block = serde_json::from_str(raw).unwrap();
302
303 let tx = match &block.transactions[1] {
304 TransactionType::DeployAccount(tx) => tx,
305 _ => panic!("Unexpected tx type"),
306 };
307
308 assert_eq!(tx.signature.len(), 2);
309 }
310
311 #[test]
312 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
313 fn test_block_deser_with_declare_v2() {
314 let raw =
315 include_str!("../../../test-data/raw_gateway_responses/get_block/15_declare_v2.txt");
316
317 let block: Block = serde_json::from_str(raw).unwrap();
318
319 assert!(block
320 .transactions
321 .into_iter()
322 .any(|tx| matches!(tx, TransactionType::Declare(_))));
323 }
324
325 #[test]
326 #[ignore = "block with the same criteria not found in alpha-sepolia yet"]
327 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
328 fn test_block_deser_with_reverted_tx() {
329 let raw = include_str!(
330 "../../../test-data/raw_gateway_responses/get_block/16_with_reverted_tx.txt"
331 );
332
333 let block: Block = serde_json::from_str(raw).unwrap();
334
335 assert!(block.transaction_receipts.into_iter().any(|tx| matches!(
336 tx.execution_status,
337 Some(TransactionExecutionStatus::Reverted)
338 )));
339 }
340}