Skip to main content

cairn_cli/
config.rs

1use serde::{Deserialize, Serialize};
2use std::fs;
3use std::path::PathBuf;
4
5/// Persistent CLI configuration stored at ~/.backpac/config.json
6#[derive(Debug, Serialize, Deserialize, Clone)]
7pub struct CairnConfig {
8    #[serde(default = "default_chain")]
9    pub chain: String,
10    #[serde(default = "default_network")]
11    pub network: String,
12    #[serde(default = "default_tier")]
13    pub tier: String,
14    pub default_confirmations: Option<u32>,
15    pub default_rebroadcast_max: Option<u32>,
16    pub default_valid_for: Option<u64>,
17    pub key_file: Option<String>,
18    pub credentials_path: Option<String>,
19    #[serde(default = "default_output")]
20    pub output: String,
21    pub api_url: Option<String>,
22    pub worker_url: Option<String>,
23    #[serde(default = "default_api_domain")]
24    pub api_domain: String,
25    #[serde(default = "default_worker_domain")]
26    pub worker_domain: String,
27}
28
29fn default_chain() -> String { "ethereum".to_string() }
30fn default_network() -> String { "mainnet".to_string() }
31fn default_tier() -> String { "standard".to_string() }
32fn default_output() -> String { "json".to_string() }
33fn default_api_domain() -> String { "api.backpac.xyz".to_string() }
34fn default_worker_domain() -> String { "backpac.xyz".to_string() }
35
36impl Default for CairnConfig {
37    fn default() -> Self {
38        Self {
39            chain: default_chain(),
40            network: default_network(),
41            tier: default_tier(),
42            default_confirmations: Some(24),
43            default_rebroadcast_max: Some(3),
44            default_valid_for: Some(600),
45            key_file: None,
46            credentials_path: None,
47            output: default_output(),
48            api_url: None,
49            worker_url: None,
50            api_domain: default_api_domain(),
51            worker_domain: default_worker_domain(),
52        }
53    }
54}
55
56/// Credentials stored at ~/.backpac/credentials.json
57#[derive(Debug, Serialize, Deserialize, Clone)]
58pub struct Credentials {
59    pub jwt: String,
60    pub agent_id: Option<String>,
61    pub wallet: Option<String>,
62    pub expires_at: Option<String>,
63}
64
65impl CairnConfig {
66    pub fn config_dir() -> PathBuf {
67        dirs::home_dir()
68            .unwrap_or_else(|| PathBuf::from("."))
69            .join(".backpac")
70    }
71
72    pub fn config_path() -> PathBuf {
73        Self::config_dir().join("config.json")
74    }
75
76    pub fn credentials_path() -> PathBuf {
77        Self::config_dir().join("credentials.json")
78    }
79
80    pub fn load() -> Self {
81        let path = Self::config_path();
82        if path.exists() {
83            let data = fs::read_to_string(&path).unwrap_or_default();
84            serde_json::from_str(&data).unwrap_or_default()
85        } else {
86            Self::default()
87        }
88    }
89
90    pub fn save(&self) -> Result<(), std::io::Error> {
91        let dir = Self::config_dir();
92        fs::create_dir_all(&dir)?;
93        let data = serde_json::to_string_pretty(self)?;
94        fs::write(Self::config_path(), data)
95    }
96}
97
98impl Credentials {
99    pub fn load() -> Option<Self> {
100        let path = CairnConfig::credentials_path();
101        if path.exists() {
102            let data = fs::read_to_string(&path).ok()?;
103            serde_json::from_str(&data).ok()
104        } else {
105            None
106        }
107    }
108
109    pub fn save(&self) -> Result<(), std::io::Error> {
110        let dir = CairnConfig::config_dir();
111        fs::create_dir_all(&dir)?;
112        let data = serde_json::to_string_pretty(self)?;
113        fs::write(CairnConfig::credentials_path(), data)
114    }
115}