switchboard_container_utils/
env.rs1use std::sync::OnceLock;
2
3use serde::Deserialize;
4use std::{fs, sync::Arc};
5use switchboard_common::SbError;
6
7pub fn get_qvn_env() -> &'static QvnEnvironment {
8 static ENV: OnceLock<QvnEnvironment> = OnceLock::new();
9 ENV.get_or_init(|| QvnEnvironment::parse().unwrap())
10}
11
12fn default_heartbeat_interval() -> i64 {
13 30
14}
15fn default_mode() -> String {
16 "default".to_string()
17}
18
19fn read_and_trim_file(file_path: &str) -> Result<String, SbError> {
20 if !std::path::Path::new(file_path).exists() {
22 return Err(SbError::CustomError {
23 message: "File not found".to_string(),
24 source: Arc::new(std::io::Error::new(
25 std::io::ErrorKind::NotFound,
26 format!("File not found: {}", file_path),
27 )),
28 });
29 }
30
31 let content = fs::read_to_string(file_path).map_err(|e| SbError::CustomError {
33 message: "Failed to read file".to_string(),
34 source: Arc::new(e),
35 })?;
36
37 Ok(content.trim().to_string())
39}
40
41#[derive(Deserialize, Debug, Default)]
42#[serde(default)]
43pub struct QvnEnvironment {
44 pub chain: String,
45 pub chain_id: String, pub quote_key: String,
47 pub rpc_url: String,
48 #[serde(default = "default_heartbeat_interval")]
49 pub heartbeat_interval: i64,
50
51 #[serde(default = "default_mode")]
52 pub mode: String,
53
54 pub ipfs_url: String,
56 pub ipfs_key: String,
57 pub ipfs_secret: String,
58
59 #[serde(default)]
60 pub queue: String, #[serde(default)]
64 pub payer_secret: String,
65 #[serde(default)]
66 pub fs_payer_secret_path: String,
67 #[serde(default)]
68 pub google_payer_secret_path: String,
69 #[serde(default)]
70 pub google_application_credentials: String,
71
72 #[serde(default)]
74 pub contract_address: String, #[serde(default)]
76 pub funding_threshold: String, #[serde(default)]
78 pub funding_amount: String, }
80impl QvnEnvironment {
81 pub fn parse() -> Result<Self, SbError> {
82 match envy::from_env::<QvnEnvironment>() {
83 Ok(env) => Ok(env),
84 Err(error) => Err(SbError::CustomMessage(format!(
85 "failed to decode environment variables: {}",
86 error
87 ))),
88 }
89 }
90
91 pub fn get_payer(&self) -> Result<String, SbError> {
92 if !self.payer_secret.is_empty() {
93 return Ok(self.payer_secret.clone().trim().to_string());
94 }
95
96 if !self.fs_payer_secret_path.is_empty() {
97 return read_and_trim_file(&self.fs_payer_secret_path);
98 }
99
100 Ok(String::new())
101 }
102}
103
104impl std::fmt::Display for QvnEnvironment {
105 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
106 write!(f, "=====Node Environment=====\n")?;
107 write!(f, "CHAIN: {}\n", self.chain)?;
108 write!(f, "RPC_URL: {}\n", self.rpc_url)?;
109
110 if self.queue.len() != 0 {
111 write!(f, "QUEUE: {}\n", self.queue)?;
112 }
113 write!(f, "QUOTE: {}\n", self.quote_key)?;
114 write!(
115 f,
116 "GOOGLE_PAYER_SECRET_PATH: {}\n",
117 self.google_payer_secret_path
118 )?;
119 write!(f, "CONTRACT_ADDRESS: {}\n", self.contract_address)?;
120 write!(f, "CHAIN_ID: {}\n", self.chain_id)?;
121 write!(f, "FUNDING_THRESHOLD: {}\n", self.funding_threshold)?;
122 write!(f, "FUNDING_AMOUNT: {}\n", self.funding_amount)?;
123 write!(f, "=========================\n")?;
124 Ok(())
125 }
126}