1use crate::NetworkName;
18
19use leo_errors::{CliError, PackageError, Result};
20
21use std::{fmt, fs, path::Path};
22
23pub const ENV_FILENAME: &str = ".env";
24
25#[derive(Clone, Debug)]
26pub struct Env {
27 pub network: NetworkName,
28 pub private_key: String,
29 pub endpoint: String,
30}
31
32impl Env {
33 pub fn new(network: NetworkName, private_key: String, endpoint: String) -> Self {
34 Env { network, private_key, endpoint }
35 }
36
37 pub fn write_to_file<P: AsRef<Path>>(&self, path: P) -> Result<(), PackageError> {
38 let contents = self.to_string();
39 fs::write(path, contents).map_err(PackageError::io_error_env_file)
40 }
41
42 pub fn read_from_file_or_environment<P: AsRef<Path>>(path: P) -> Result<Self> {
43 let contents = std::fs::read_to_string(&path)
44 .map_err(|e| PackageError::failed_to_read_file(path.as_ref().display(), e))?;
45 let mut network: Option<String> = None;
46 let mut private_key: Option<String> = None;
47 let mut endpoint: Option<String> = None;
48
49 for line in contents.lines() {
50 if let Some((lhs, rhs)) = line.split_once('=') {
51 match lhs.trim() {
52 "NETWORK" => network = Some(rhs.to_string()),
53 "PRIVATE_KEY" => private_key = Some(rhs.to_string()),
54 "ENDPOINT" => endpoint = Some(rhs.to_string()),
55 _ => {}
56 }
57 }
58 }
59
60 for (variable, name) in
61 [(&mut network, "NETWORK"), (&mut private_key, "PRIVATE_KEY"), (&mut endpoint, "ENDPOINT")]
62 {
63 if let Ok(env_var_value) = std::env::var(name) {
64 if !env_var_value.is_empty() {
65 *variable = Some(env_var_value);
66 }
67 }
68 }
69
70 let network: Option<NetworkName> = network.and_then(|net| net.parse().ok());
71
72 match (network, private_key, endpoint) {
73 (Some(network), Some(private_key), Some(endpoint)) => Ok(Env { network, private_key, endpoint }),
74 (None, _, _) => Err(CliError::failed_to_get_network_from_env().into()),
75 (_, None, _) => Err(CliError::failed_to_get_private_key_from_env().into()),
76 (_, _, None) => Err(CliError::failed_to_get_endpoint_from_env().into()),
77 }
78 }
79}
80
81impl fmt::Display for Env {
82 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
83 write!(f, "NETWORK={}\nPRIVATE_KEY={}\nENDPOINT={}\n", self.network, self.private_key, self.endpoint)
84 }
85}