1use std::{env, fs::File, path::Path};
2
3use anyhow::{anyhow, Result};
4use console::style;
5use lazy_static::lazy_static;
6use regex::Regex;
7
8use crate::{config::data::*, program_errors::*};
9
10pub fn parse_solana_config() -> Option<SolanaConfig> {
11 let home = if cfg!(unix) {
12 env::var_os("HOME").expect("Couldn't find UNIX home key.")
13 } else if cfg!(windows) {
14 let drive = env::var_os("HOMEDRIVE").expect("Couldn't find Windows home drive key.");
15 let path = env::var_os("HOMEPATH").expect("Couldn't find Windows home path key.");
16 Path::new(&drive).join(path).as_os_str().to_owned()
17 } else if cfg!(target_os = "macos") {
18 env::var_os("HOME").expect("Couldn't find MacOS home key.")
19 } else {
20 panic!("Unsupported OS!");
21 };
22
23 let config_path = Path::new(&home)
24 .join(".config")
25 .join("miraland")
26 .join("cli")
27 .join("config.yml");
28
29 let conf_file = match File::open(config_path) {
30 Ok(f) => f,
31 Err(e) => {
32 println!(
33 "{} {}",
34 style("Failed to open Miraland config file:").bold().red(),
35 style(e).bold().red(),
36 );
37 std::process::exit(1);
38 }
39 };
40 serde_yaml::from_reader(&conf_file).ok()
41}
42
43pub fn path_to_string(path: &Path) -> Result<String> {
44 match path.to_str() {
45 Some(s) => Ok(s.to_string()),
46 None => Err(anyhow!("Couldn't convert path to string.")),
47 }
48}
49
50pub fn parse_sugar_errors(msg: &str) -> String {
51 lazy_static! {
52 static ref RE: Regex =
53 Regex::new(r"(0x[A-Za-z0-9]+)").expect("Failed to compile parse_client_error regex.");
54 }
55
56 let mat = RE.find(msg);
57
58 match mat {
60 Some(m) => {
61 let code = msg[m.start()..m.end()].to_string();
62 find_external_program_error(code)
63 }
64 None => msg.to_owned(),
65 }
66}
67
68fn find_external_program_error(code: String) -> String {
69 let code = code.to_uppercase();
70
71 let parsed_code = if code.contains("0X") {
72 code.replace("0X", "")
73 } else {
74 format!("{:X}", code.parse::<i64>().unwrap())
75 };
76
77 if let Some(e) = ANCHOR_ERROR.get(&parsed_code) {
78 format!("Anchor Error: {e}")
79 } else if let Some(e) = METADATA_ERROR.get(&parsed_code) {
80 format!("Token Metadata Error: {e}")
81 } else {
82 let mut errors = Vec::with_capacity(2);
83
84 if let Some(e) = CANDY_CORE_ERROR.get(&parsed_code) {
85 errors.push(format!("Candy Machine: {e}"));
86 }
87 if let Some(e) = CANDY_GUARD_ERROR.get(&parsed_code) {
88 errors.push(format!("Candy Guard: {e}"));
89 }
90
91 if errors.is_empty() {
92 format!("Unknown error. Code: {code}")
93 } else {
94 let mut message = String::from("Command failed due to the following reason(s):");
95
96 for error in errors {
97 message.push_str(&format!("\n • {}", error).to_string());
98 }
99
100 message
101 }
102 }
103}