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}
23
24fn default_chain() -> String { "ethereum".to_string() }
25fn default_network() -> String { "mainnet".to_string() }
26fn default_tier() -> String { "standard".to_string() }
27fn default_output() -> String { "json".to_string() }
28
29impl Default for CairnConfig {
30    fn default() -> Self {
31        Self {
32            chain: default_chain(),
33            network: default_network(),
34            tier: default_tier(),
35            default_confirmations: Some(24),
36            default_rebroadcast_max: Some(3),
37            default_valid_for: Some(600),
38            key_file: None,
39            credentials_path: None,
40            output: default_output(),
41            api_url: None,
42        }
43    }
44}
45
46/// Credentials stored at ~/.backpac/credentials.json
47#[derive(Debug, Serialize, Deserialize, Clone)]
48pub struct Credentials {
49    pub jwt: String,
50    pub agent_id: Option<String>,
51    pub wallet: Option<String>,
52    pub expires_at: Option<String>,
53}
54
55impl CairnConfig {
56    pub fn config_dir() -> PathBuf {
57        dirs::home_dir()
58            .unwrap_or_else(|| PathBuf::from("."))
59            .join(".backpac")
60    }
61
62    pub fn config_path() -> PathBuf {
63        Self::config_dir().join("config.json")
64    }
65
66    pub fn credentials_path() -> PathBuf {
67        Self::config_dir().join("credentials.json")
68    }
69
70    pub fn load() -> Self {
71        let path = Self::config_path();
72        if path.exists() {
73            let data = fs::read_to_string(&path).unwrap_or_default();
74            serde_json::from_str(&data).unwrap_or_default()
75        } else {
76            Self::default()
77        }
78    }
79
80    pub fn save(&self) -> Result<(), std::io::Error> {
81        let dir = Self::config_dir();
82        fs::create_dir_all(&dir)?;
83        let data = serde_json::to_string_pretty(self)?;
84        fs::write(Self::config_path(), data)
85    }
86}
87
88impl Credentials {
89    pub fn load() -> Option<Self> {
90        let path = CairnConfig::credentials_path();
91        if path.exists() {
92            let data = fs::read_to_string(&path).ok()?;
93            serde_json::from_str(&data).ok()
94        } else {
95            None
96        }
97    }
98
99    pub fn save(&self) -> Result<(), std::io::Error> {
100        let dir = CairnConfig::config_dir();
101        fs::create_dir_all(&dir)?;
102        let data = serde_json::to_string_pretty(self)?;
103        fs::write(CairnConfig::credentials_path(), data)
104    }
105}