starknet_rust_providers/sequencer/models/
state_update.rs1use serde::Deserialize;
2use serde_with::serde_as;
3use starknet_rust_core::{serde::unsigned_field_element::UfeHex, types::Felt};
4use std::collections::HashMap;
5
6use super::Block;
7
8#[serde_as]
9#[derive(Debug, Deserialize)]
10#[cfg_attr(feature = "no_unknown_fields", serde(deny_unknown_fields))]
11pub struct StateUpdateWithBlock {
12 pub state_update: StateUpdate,
13 pub block: Block,
14}
15
16#[serde_as]
17#[derive(Debug, Deserialize)]
18#[cfg_attr(feature = "no_unknown_fields", serde(deny_unknown_fields))]
19pub struct StateUpdate {
20 #[serde_as(as = "Option<UfeHex>")]
21 pub block_hash: Option<Felt>,
22 #[serde_as(as = "Option<UfeHex>")]
23 pub new_root: Option<Felt>,
24 #[serde_as(as = "UfeHex")]
25 pub old_root: Felt,
26 pub state_diff: StateDiff,
27}
28
29#[serde_as]
30#[derive(Debug, Deserialize)]
31#[cfg_attr(feature = "no_unknown_fields", serde(deny_unknown_fields))]
32pub struct StateDiff {
33 #[serde_as(as = "HashMap<UfeHex, _>")]
34 pub storage_diffs: HashMap<Felt, Vec<StorageDiff>>,
35 pub deployed_contracts: Vec<DeployedContract>,
36 #[serde_as(as = "Vec<UfeHex>")]
37 pub old_declared_contracts: Vec<Felt>,
38 pub declared_classes: Vec<DeclaredContract>,
39 #[serde(default)]
40 #[serde_as(as = "HashMap<UfeHex, UfeHex>")]
41 pub nonces: HashMap<Felt, Felt>,
42 pub replaced_classes: Vec<DeployedContract>,
43}
44
45#[serde_as]
46#[derive(Debug, Deserialize)]
47#[cfg_attr(feature = "no_unknown_fields", serde(deny_unknown_fields))]
48pub struct StorageDiff {
49 #[serde_as(as = "UfeHex")]
50 pub key: Felt,
51 #[serde_as(as = "UfeHex")]
52 pub value: Felt,
53}
54
55#[serde_as]
56#[derive(Debug, Deserialize)]
57#[cfg_attr(feature = "no_unknown_fields", serde(deny_unknown_fields))]
58pub struct DeployedContract {
59 #[serde_as(as = "UfeHex")]
60 pub address: Felt,
61 #[serde_as(as = "UfeHex")]
62 pub class_hash: Felt,
63}
64
65#[serde_as]
66#[derive(Debug, Deserialize)]
67#[cfg_attr(feature = "no_unknown_fields", serde(deny_unknown_fields))]
68pub struct DeclaredContract {
69 #[serde_as(as = "UfeHex")]
70 pub class_hash: Felt,
71 #[serde_as(as = "UfeHex")]
72 pub compiled_class_hash: Felt,
73}
74
75#[cfg(test)]
76mod tests {
77 use super::*;
78
79 #[test]
80 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
81 fn test_state_update_deser() {
82 let raw =
83 include_str!("../../../test-data/raw_gateway_responses/get_state_update/1_success.txt");
84
85 let state_update: StateUpdate = serde_json::from_str(raw).unwrap();
86
87 let storage_diff = &state_update
88 .state_diff
89 .storage_diffs
90 .get(
91 &Felt::from_hex(
92 "0x197b9913e67947b0605934ec72db497d341a0199282c1da6d4aae46b17e0e76",
93 )
94 .unwrap(),
95 )
96 .unwrap()[0];
97
98 assert_eq!(
99 storage_diff.key,
100 Felt::from_hex("0x34c0d833897dbc937dd35e9f49a5184aecd6ab47829de999f9587549f82d0e")
101 .unwrap()
102 );
103 assert_eq!(
104 storage_diff.value,
105 Felt::from_hex("0x74fd8ca6e84097ad9ae00febfb690ad032fc4477155ec2193382c1b30b5e12b")
106 .unwrap()
107 );
108 }
109
110 #[test]
111 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
112 fn test_pending_state_update_deser() {
113 let raw = include_str!(
114 "../../../test-data/raw_gateway_responses/get_state_update/2_pending_block.txt"
115 );
116
117 serde_json::from_str::<StateUpdate>(raw).unwrap();
118 }
119
120 #[test]
121 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
122 fn test_state_update_deser_with_nonce_changes() {
123 let raw = include_str!(
124 "../../../test-data/raw_gateway_responses/get_state_update/4_with_nonce_changes.txt"
125 );
126
127 let state_update: StateUpdate = serde_json::from_str(raw).unwrap();
128 assert_eq!(state_update.state_diff.nonces.len(), 2);
129 }
130
131 #[test]
132 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
133 fn test_state_update_deser_with_declare_v2() {
134 let raw = include_str!(
135 "../../../test-data/raw_gateway_responses/get_state_update/5_with_declare_v2.txt"
136 );
137 serde_json::from_str::<StateUpdate>(raw).unwrap();
138 }
139
140 #[test]
141 #[ignore = "block with the same criteria not found in alpha-sepolia yet"]
142 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
143 fn test_state_update_deser_with_replaced_classes() {
144 let raw = include_str!(
145 "../../../test-data/raw_gateway_responses/get_state_update/6_with_replaced_classes.txt"
146 );
147
148 let state_update: StateUpdate = serde_json::from_str(raw).unwrap();
149 assert_eq!(state_update.state_diff.replaced_classes.len(), 1);
150 }
151
152 #[test]
153 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
154 fn test_state_update_deser_with_deployed_contracts() {
155 let raw = include_str!(
156 "../../../test-data/raw_gateway_responses/get_state_update/7_with_deployed_contracts.txt"
157 );
158
159 let state_update: StateUpdate = serde_json::from_str(raw).unwrap();
160 assert_eq!(state_update.state_diff.deployed_contracts.len(), 5);
161 }
162}