starknet_devnet_core/starknet/
starknet_config.rs1use std::num::NonZeroU128;
2
3use clap::Error;
4use serde::{Serialize, Serializer};
5use starknet_rs_core::types::Felt;
6use starknet_types::chain_id::ChainId;
7use starknet_types::contract_class::ContractClass;
8use starknet_types::rpc::state::Balance;
9use starknet_types::traits::HashProducer;
10use url::Url;
11
12use crate::constants::{
13 CAIRO_1_ACCOUNT_CONTRACT_SIERRA, DEVNET_DEFAULT_CHAIN_ID, DEVNET_DEFAULT_INITIAL_BALANCE,
14 DEVNET_DEFAULT_L1_DATA_GAS_PRICE, DEVNET_DEFAULT_L1_GAS_PRICE, DEVNET_DEFAULT_L2_GAS_PRICE,
15 DEVNET_DEFAULT_TEST_SEED, DEVNET_DEFAULT_TOTAL_ACCOUNTS, ETH_ERC20_CONTRACT_CLASS,
16 ETH_ERC20_CONTRACT_CLASS_HASH, MAXIMUM_CONTRACT_BYTECODE_SIZE, MAXIMUM_CONTRACT_CLASS_SIZE,
17 MAXIMUM_SIERRA_LENGTH, STRK_ERC20_CONTRACT_CLASS, STRK_ERC20_CONTRACT_CLASS_HASH,
18};
19
20#[derive(Copy, Clone, Debug, clap::ValueEnum, Serialize)]
21#[serde(rename_all = "snake_case")]
22pub enum DumpOn {
23 Exit,
24 Block,
25 Request,
26}
27
28#[derive(Default, Copy, Clone, Debug, Eq, PartialEq, clap::ValueEnum, Serialize)]
29#[serde(rename_all = "snake_case")]
30#[clap(rename_all = "snake_case")]
31pub enum StateArchiveCapacity {
32 #[default]
33 None,
34 Full,
35}
36
37#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)]
38#[serde(rename_all = "snake_case")]
39pub enum BlockGenerationOn {
40 Transaction,
41 Demand,
42 Interval(u64),
43}
44
45#[derive(Clone, Debug, Serialize)]
46pub struct ClassSizeConfig {
47 pub maximum_contract_class_size: u64,
48 pub maximum_contract_bytecode_size: u64,
49 pub maximum_sierra_length: u64,
50}
51
52impl Default for ClassSizeConfig {
53 fn default() -> Self {
54 Self {
55 maximum_contract_class_size: MAXIMUM_CONTRACT_CLASS_SIZE,
56 maximum_contract_bytecode_size: MAXIMUM_CONTRACT_BYTECODE_SIZE,
57 maximum_sierra_length: MAXIMUM_SIERRA_LENGTH,
58 }
59 }
60}
61
62impl std::str::FromStr for BlockGenerationOn {
63 type Err = Error;
64
65 fn from_str(s: &str) -> Result<Self, Self::Err> {
66 match s {
67 "transaction" => Ok(BlockGenerationOn::Transaction),
68 "demand" => Ok(BlockGenerationOn::Demand),
69 value => {
70 let interval_value = value
71 .parse::<u64>()
72 .map_err(|_| Error::new(clap::error::ErrorKind::InvalidValue))?;
73
74 if interval_value > 0 {
75 Ok(BlockGenerationOn::Interval(interval_value))
76 } else {
77 Err(Error::new(clap::error::ErrorKind::InvalidValue))
78 }
79 }
80 }
81 }
82}
83
84#[derive(Debug, Clone, Default, Serialize)]
85pub struct ForkConfig {
86 #[serde(serialize_with = "serialize_config_url")]
87 pub url: Option<Url>,
88 pub block_number: Option<u64>,
89 #[serde(skip)]
90 pub block_hash: Option<Felt>,
91}
92
93pub fn serialize_config_url<S>(url: &Option<Url>, serializer: S) -> Result<S::Ok, S::Error>
94where
95 S: Serializer,
96{
97 match url {
98 Some(url) => serializer.serialize_str(url.as_ref()),
99 None => serializer.serialize_none(),
100 }
101}
102
103pub fn serialize_initial_balance<S>(balance: &Balance, serializer: S) -> Result<S::Ok, S::Error>
104where
105 S: Serializer,
106{
107 serializer.serialize_str(&balance.to_str_radix(10))
108}
109
110pub fn serialize_chain_id<S>(chain_id: &ChainId, serializer: S) -> Result<S::Ok, S::Error>
111where
112 S: Serializer,
113{
114 serializer.serialize_str(&format!("{chain_id}"))
115}
116
117#[derive(Clone, Debug, Serialize)]
118pub struct StarknetConfig {
119 pub seed: u32,
120 pub total_accounts: u8,
121 #[serde(skip_serializing)]
122 pub account_contract_class: ContractClass,
123 pub account_contract_class_hash: Felt,
124 #[serde(serialize_with = "serialize_initial_balance")]
125 pub predeployed_accounts_initial_balance: Balance,
126 pub start_time: Option<u64>,
127 pub gas_price_wei: NonZeroU128,
128 pub gas_price_fri: NonZeroU128,
129 pub data_gas_price_wei: NonZeroU128,
130 pub data_gas_price_fri: NonZeroU128,
131 pub l2_gas_price_wei: NonZeroU128,
132 pub l2_gas_price_fri: NonZeroU128,
133 #[serde(serialize_with = "serialize_chain_id")]
134 pub chain_id: ChainId,
135 pub dump_on: Option<DumpOn>,
136 pub dump_path: Option<String>,
137 pub block_generation_on: BlockGenerationOn,
138 pub lite_mode: bool,
139 pub state_archive: StateArchiveCapacity,
140 pub fork_config: ForkConfig,
141 pub eth_erc20_class_hash: Felt,
142 pub strk_erc20_class_hash: Felt,
143 #[serde(skip_serializing)]
144 pub eth_erc20_contract_class: String,
145 #[serde(skip_serializing)]
146 pub strk_erc20_contract_class: String,
147 #[serde(skip_serializing)]
148 pub predeclare_argent: bool,
149 pub class_size_config: ClassSizeConfig,
150}
151
152impl StarknetConfig {
153 pub fn uses_pre_confirmed_block(&self) -> bool {
154 match self.block_generation_on {
155 BlockGenerationOn::Transaction => false,
156 BlockGenerationOn::Demand | BlockGenerationOn::Interval(_) => true,
157 }
158 }
159}
160
161#[allow(clippy::unwrap_used)]
162impl Default for StarknetConfig {
163 fn default() -> Self {
164 let account_contract_class: ContractClass =
166 ContractClass::cairo_1_from_sierra_json_str(CAIRO_1_ACCOUNT_CONTRACT_SIERRA)
167 .unwrap()
168 .into();
169 StarknetConfig {
170 seed: DEVNET_DEFAULT_TEST_SEED,
171 total_accounts: DEVNET_DEFAULT_TOTAL_ACCOUNTS,
172 account_contract_class_hash: account_contract_class.generate_hash().unwrap(),
174 account_contract_class,
175 predeployed_accounts_initial_balance: DEVNET_DEFAULT_INITIAL_BALANCE.into(),
176 start_time: None,
177 gas_price_wei: DEVNET_DEFAULT_L1_GAS_PRICE.get().try_into().unwrap(),
178 gas_price_fri: DEVNET_DEFAULT_L1_GAS_PRICE.get().try_into().unwrap(),
179 data_gas_price_wei: DEVNET_DEFAULT_L1_DATA_GAS_PRICE.get().try_into().unwrap(),
180 data_gas_price_fri: DEVNET_DEFAULT_L1_DATA_GAS_PRICE.get().try_into().unwrap(),
181 l2_gas_price_wei: DEVNET_DEFAULT_L2_GAS_PRICE.get().try_into().unwrap(),
182 l2_gas_price_fri: DEVNET_DEFAULT_L2_GAS_PRICE.get().try_into().unwrap(),
183 chain_id: DEVNET_DEFAULT_CHAIN_ID,
184 dump_on: None,
185 dump_path: None,
186 block_generation_on: BlockGenerationOn::Transaction,
187 lite_mode: false,
188 state_archive: StateArchiveCapacity::default(),
189 fork_config: ForkConfig::default(),
190 eth_erc20_class_hash: ETH_ERC20_CONTRACT_CLASS_HASH,
191 strk_erc20_class_hash: STRK_ERC20_CONTRACT_CLASS_HASH,
192 eth_erc20_contract_class: ETH_ERC20_CONTRACT_CLASS.to_string(),
193 strk_erc20_contract_class: STRK_ERC20_CONTRACT_CLASS.to_string(),
194 predeclare_argent: false,
195 class_size_config: ClassSizeConfig::default(),
196 }
197 }
198}