init4_bin_base/utils/
constants_from_env.rs

1use crate::utils::from_env::{EnvItemInfo, FromEnv, FromEnvErr, FromEnvVar};
2use alloy::primitives::{hex::FromHexError, Address};
3use signet_constants::{
4    HostConstants, ParseChainError, PredeployTokens, RollupConstants, SignetConstants,
5    SignetEnvironmentConstants, SignetSystemConstants,
6};
7use std::{borrow::Cow, num::ParseIntError};
8
9/// EnvItemInfo for .env variable holding chain name
10/// Used to implement FromEnv for SignetConstants type structs
11/// that can be instantiated from a single chain name
12const CHAIN_NAME: EnvItemInfo = EnvItemInfo {
13    var: "CHAIN_NAME",
14    description: "The name of the chain, e.g. `pecorino`. If CHAIN_NAME is present, the known, hard-coded constants for the chain will be loaded from the SDK. If CHAIN_NAME is not present, each constant will be loaded from environment variables.",
15    optional: true,
16};
17
18// --- RollupConstants ---
19const ROLLUP_CHAIN_ID: &str = "ROLLUP_CHAIN_ID";
20const ROLLUP_BASE_FEE_RECIPIENT: &str = "ROLLUP_BASE_FEE_RECIPIENT";
21const ROLLUP_ORDERS: &str = "ROLLUP_ORDERS";
22const ROLLUP_PASSAGE: &str = "ROLLUP_PASSAGE";
23const ROLLUP_USDC: &str = "ROLLUP_USDC";
24const ROLLUP_USDT: &str = "ROLLUP_USDT";
25const ROLLUP_WBTC: &str = "ROLLUP_WBTC";
26// --- HostConstants ---
27const HOST_CHAIN_ID: &str = "HOST_CHAIN_ID";
28const HOST_DEPLOY_HEIGHT: &str = "HOST_DEPLOY_HEIGHT";
29const HOST_ZENITH: &str = "HOST_ZENITH";
30const HOST_ORDERS: &str = "HOST_ORDERS";
31const HOST_PASSAGE: &str = "HOST_PASSAGE";
32const HOST_TRANSACTOR: &str = "HOST_TRANSACTOR";
33const HOST_USDC: &str = "HOST_USDC";
34const HOST_USDT: &str = "HOST_USDT";
35const HOST_WBTC: &str = "HOST_WBTC";
36// --- SignetEnvironmentConstants ---
37const SIGNET_HOST_NAME: &str = "SIGNET_HOST_NAME";
38const SIGNET_ROLLUP_NAME: &str = "SIGNET_ROLLUP_NAME";
39const SIGNET_TRANSACTION_CACHE: &str = "SIGNET_TRANSACTION_CACHE";
40
41/// Error type for parsing SignetConstants from environment variables.
42#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
43pub enum ConstantsFromEnvError {
44    /// Error parsing a chain name.
45    #[error(transparent)]
46    ParseChainError(#[from] ParseChainError),
47    /// Error parsing a u64.
48    #[error(transparent)]
49    ParseIntError(#[from] ParseIntError),
50    /// Error parsing a hex string.
51    #[error(transparent)]
52    FromHexError(#[from] FromHexError),
53}
54
55impl From<FromEnvErr<ParseChainError>> for FromEnvErr<ConstantsFromEnvError> {
56    fn from(e: FromEnvErr<ParseChainError>) -> Self {
57        match e {
58            FromEnvErr::ParseError(i) => FromEnvErr::ParseError(i.into()),
59            FromEnvErr::Empty(i) => FromEnvErr::Empty(i),
60            FromEnvErr::EnvError(var, err) => FromEnvErr::EnvError(var, err),
61        }
62    }
63}
64
65impl From<FromEnvErr<ParseIntError>> for FromEnvErr<ConstantsFromEnvError> {
66    fn from(e: FromEnvErr<ParseIntError>) -> Self {
67        match e {
68            FromEnvErr::ParseError(i) => FromEnvErr::ParseError(i.into()),
69            FromEnvErr::Empty(i) => FromEnvErr::Empty(i),
70            FromEnvErr::EnvError(var, err) => FromEnvErr::EnvError(var, err),
71        }
72    }
73}
74
75impl From<FromEnvErr<FromHexError>> for FromEnvErr<ConstantsFromEnvError> {
76    fn from(e: FromEnvErr<FromHexError>) -> Self {
77        match e {
78            FromEnvErr::ParseError(i) => FromEnvErr::ParseError(i.into()),
79            FromEnvErr::Empty(i) => FromEnvErr::Empty(i),
80            FromEnvErr::EnvError(var, err) => FromEnvErr::EnvError(var, err),
81        }
82    }
83}
84
85impl FromEnv for RollupConstants {
86    type Error = ConstantsFromEnvError;
87
88    fn inventory() -> Vec<&'static EnvItemInfo> {
89        vec![
90            &CHAIN_NAME,
91            &EnvItemInfo {
92                var: ROLLUP_CHAIN_ID,
93                description: "Rollup chain ID.",
94                optional: false,
95            },
96            &EnvItemInfo {
97                var: ROLLUP_BASE_FEE_RECIPIENT,
98                description: "Rollup address of the base fee recipient.",
99                optional: false,
100            },
101            &EnvItemInfo {
102                var: ROLLUP_ORDERS,
103                description: "Rollup address of the orders contract.",
104                optional: false,
105            },
106            &EnvItemInfo {
107                var: ROLLUP_PASSAGE,
108                description: "Rollup address of the passage contract.",
109                optional: false,
110            },
111            &EnvItemInfo {
112                var: ROLLUP_USDC,
113                description: "Rollup address of usdc token.",
114                optional: false,
115            },
116            &EnvItemInfo {
117                var: ROLLUP_USDT,
118                description: "Rollup address of usdt token.",
119                optional: false,
120            },
121            &EnvItemInfo {
122                var: ROLLUP_WBTC,
123                description: "Rollup address of wbtc token.",
124                optional: false,
125            },
126        ]
127    }
128
129    fn from_env() -> Result<Self, FromEnvErr<Self::Error>> {
130        match Self::from_env_var(CHAIN_NAME.var) {
131            Ok(c) => Ok(c),
132            Err(e) => {
133                match e {
134                    // if chain name is present but malformed, propagate the error
135                    FromEnvErr::ParseError(_) => Err(e.into()),
136                    // if the chain name is empty or missing,
137                    // instantiate each prop from env vars
138                    FromEnvErr::EnvError(_, _) | FromEnvErr::Empty(_) => Ok(RollupConstants::new(
139                        u64::from_env_var(ROLLUP_CHAIN_ID)?,
140                        Address::from_env_var(ROLLUP_ORDERS)?,
141                        Address::from_env_var(ROLLUP_PASSAGE)?,
142                        Address::from_env_var(ROLLUP_BASE_FEE_RECIPIENT)?,
143                        PredeployTokens::new(
144                            Address::from_env_var(ROLLUP_USDC)?,
145                            Address::from_env_var(ROLLUP_USDT)?,
146                            Address::from_env_var(ROLLUP_WBTC)?,
147                        ),
148                    )),
149                }
150            }
151        }
152    }
153}
154
155impl FromEnv for HostConstants {
156    type Error = ConstantsFromEnvError;
157
158    fn inventory() -> Vec<&'static EnvItemInfo> {
159        vec![
160            &CHAIN_NAME,
161            &EnvItemInfo {
162                var: HOST_CHAIN_ID,
163                description: "Host chain ID.",
164                optional: false,
165            },
166            &EnvItemInfo {
167                var: HOST_DEPLOY_HEIGHT,
168                description: "Height at which the host chain deployed the rollup contracts.",
169                optional: false,
170            },
171            &EnvItemInfo {
172                var: HOST_ZENITH,
173                description: "Host address for the zenith contract",
174                optional: false,
175            },
176            &EnvItemInfo {
177                var: HOST_ORDERS,
178                description: "Host address for the orders contract",
179                optional: false,
180            },
181            &EnvItemInfo {
182                var: HOST_PASSAGE,
183                description: "Host address for the passage contract",
184                optional: false,
185            },
186            &EnvItemInfo {
187                var: HOST_TRANSACTOR,
188                description: "Host address for the transactor contract",
189                optional: false,
190            },
191            &EnvItemInfo {
192                var: HOST_USDC,
193                description: "Host address for the USDC token",
194                optional: false,
195            },
196            &EnvItemInfo {
197                var: HOST_USDT,
198                description: "Host address for the USDT token",
199                optional: false,
200            },
201            &EnvItemInfo {
202                var: HOST_WBTC,
203                description: "Host address for the WBTC token",
204                optional: false,
205            },
206        ]
207    }
208
209    fn from_env() -> Result<Self, FromEnvErr<Self::Error>> {
210        match Self::from_env_var(CHAIN_NAME.var) {
211            Ok(c) => Ok(c),
212            Err(e) => {
213                match e {
214                    // if chain name is present but malformed, propagate the error
215                    FromEnvErr::ParseError(_) => Err(e.into()),
216                    // if the chain name is empty or missing,
217                    // instantiate each prop from env vars
218                    FromEnvErr::EnvError(_, _) | FromEnvErr::Empty(_) => Ok(HostConstants::new(
219                        u64::from_env_var(HOST_CHAIN_ID)?,
220                        u64::from_env_var(HOST_DEPLOY_HEIGHT)?,
221                        Address::from_env_var(HOST_ZENITH)?,
222                        Address::from_env_var(HOST_ORDERS)?,
223                        Address::from_env_var(HOST_PASSAGE)?,
224                        Address::from_env_var(HOST_TRANSACTOR)?,
225                        PredeployTokens::new(
226                            Address::from_env_var(HOST_USDC)?,
227                            Address::from_env_var(HOST_USDT)?,
228                            Address::from_env_var(HOST_WBTC)?,
229                        ),
230                    )),
231                }
232            }
233        }
234    }
235}
236
237impl FromEnv for SignetEnvironmentConstants {
238    type Error = ConstantsFromEnvError;
239
240    fn inventory() -> Vec<&'static EnvItemInfo> {
241        vec![
242            &CHAIN_NAME,
243            &EnvItemInfo {
244                var: SIGNET_HOST_NAME,
245                description: "Name of the host chain.",
246                optional: false,
247            },
248            &EnvItemInfo {
249                var: SIGNET_ROLLUP_NAME,
250                description: "Name of the rollup.",
251                optional: false,
252            },
253            &EnvItemInfo {
254                var: SIGNET_TRANSACTION_CACHE,
255                description: "URL of the Transaction Cache",
256                optional: false,
257            },
258        ]
259    }
260
261    fn from_env() -> Result<Self, FromEnvErr<Self::Error>> {
262        match Self::from_env_var(CHAIN_NAME.var) {
263            Ok(c) => Ok(c),
264            Err(e) => {
265                match e {
266                    // if chain name is present but malformed, propagate the error
267                    FromEnvErr::ParseError(_) => Err(e.into()),
268                    // if the chain name is empty or missing,
269                    // instantiate each prop from env vars
270                    FromEnvErr::EnvError(_, _) | FromEnvErr::Empty(_) => {
271                        Ok(SignetEnvironmentConstants::new(
272                            Cow::from_env_var(SIGNET_HOST_NAME)
273                                .map_err(|e| e.infallible_into::<ConstantsFromEnvError>())?,
274                            Cow::from_env_var(SIGNET_ROLLUP_NAME)
275                                .map_err(|e| e.infallible_into::<ConstantsFromEnvError>())?,
276                            Cow::from_env_var(SIGNET_TRANSACTION_CACHE)
277                                .map_err(|e| e.infallible_into::<ConstantsFromEnvError>())?,
278                        ))
279                    }
280                }
281            }
282        }
283    }
284}
285
286impl FromEnv for SignetSystemConstants {
287    type Error = ConstantsFromEnvError;
288
289    fn inventory() -> Vec<&'static EnvItemInfo> {
290        let mut inventory = Vec::new();
291        inventory.extend_from_slice(&HostConstants::inventory());
292        inventory.extend_from_slice(&RollupConstants::inventory()[1..]);
293        inventory
294    }
295
296    fn from_env() -> Result<Self, FromEnvErr<Self::Error>> {
297        match Self::from_env_var(CHAIN_NAME.var) {
298            Ok(c) => Ok(c),
299            Err(e) => {
300                match e {
301                    // if chain name is present but malformed, propagate the error
302                    FromEnvErr::ParseError(_) => Err(e.into()),
303                    // if the chain name is empty or missing,
304                    // instantiate each prop from env vars
305                    FromEnvErr::EnvError(_, _) | FromEnvErr::Empty(_) => {
306                        Ok(SignetSystemConstants::new(
307                            HostConstants::from_env()?,
308                            RollupConstants::from_env()?,
309                        ))
310                    }
311                }
312            }
313        }
314    }
315}
316
317impl FromEnv for SignetConstants {
318    type Error = ConstantsFromEnvError;
319
320    fn inventory() -> Vec<&'static EnvItemInfo> {
321        let mut inventory = Vec::new();
322        inventory.extend_from_slice(&SignetSystemConstants::inventory());
323        inventory.extend_from_slice(&SignetEnvironmentConstants::inventory()[1..]);
324        inventory
325    }
326
327    fn from_env() -> Result<Self, FromEnvErr<Self::Error>> {
328        match Self::from_env_var(CHAIN_NAME.var) {
329            Ok(c) => Ok(c),
330            Err(e) => {
331                match e {
332                    // if chain name is present but malformed, propagate the error
333                    FromEnvErr::ParseError(_) => Err(e.into()),
334                    // if the chain name is empty or missing,
335                    // instantiate each prop from env vars
336                    FromEnvErr::EnvError(_, _) | FromEnvErr::Empty(_) => Ok(SignetConstants::new(
337                        SignetSystemConstants::from_env()?,
338                        SignetEnvironmentConstants::from_env()?,
339                    )),
340                }
341            }
342        }
343    }
344}