1use serde::{Deserialize, Serialize};
2use std::fs;
3use std::path::PathBuf;
4
5#[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#[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}