seedelf_cli/
display.rs

1use crate::constants::{Config, get_config};
2use crate::koios::{contains_policy_id, credential_utxos, extract_bytes_with_logging, tip};
3use crate::version_control::{compare_versions, get_latest_version};
4use blstrs::Scalar;
5use colored::Colorize;
6
7pub async fn is_their_an_update() {
8    match get_latest_version().await {
9        Ok(tag) => {
10            if !compare_versions(env!("CARGO_PKG_VERSION"), &tag) {
11                println!(
12                    "\n{} {}\n{}",
13                    "A new version is available:".bold().bright_blue(),
14                    tag.yellow(),
15                    "Please update to the newest version of Seedelf"
16                        .bold()
17                        .bright_blue(),
18                );
19            }
20        }
21        Err(err) => {
22            eprintln!(
23                "Failed to fetch newest version: {}\nWait a few moments and try again.",
24                err
25            );
26            std::process::exit(1);
27        }
28    }
29}
30
31pub async fn block_number_and_time(network_flag: bool) {
32    match tip(network_flag).await {
33        Ok(tips) => {
34            if let Some(tip) = tips.first() {
35                println!(
36                    "\n{} {}\n{} {}",
37                    "Block Number:".bold().bright_blue(),
38                    tip.block_no.to_string().yellow(),
39                    "Time:".bold().bright_blue(),
40                    tip.block_time.to_string().yellow()
41                );
42            }
43        }
44        Err(err) => {
45            eprintln!(
46                "Failed to fetch blockchain tip: {}\nWait a few moments and try again.",
47                err
48            );
49            std::process::exit(1);
50        }
51    }
52}
53
54pub fn preprod_text(network_flag: bool) {
55    if network_flag {
56        println!("{}", "\nRunning On The Pre-Production Network".cyan());
57    }
58}
59
60pub async fn all_seedelfs(sk: Scalar, network_flag: bool, variant: u64) {
61    let mut seedelfs: Vec<String> = Vec::new();
62
63    let config: Config = get_config(variant, network_flag).unwrap_or_else(|| {
64        eprintln!("Error: Invalid Variant");
65        std::process::exit(1);
66    });
67
68    match credential_utxos(config.contract.wallet_contract_hash, network_flag).await {
69        Ok(utxos) => {
70            for utxo in utxos {
71                // Extract bytes
72                if let Some(inline_datum) = extract_bytes_with_logging(&utxo.inline_datum) {
73                    // utxo must be owned by this secret scaler
74                    if inline_datum.is_owned(sk) {
75                        // its owned but lets not count the seedelf in the balance
76                        if contains_policy_id(&utxo.asset_list, config.contract.seedelf_policy_id) {
77                            let asset_name: &String = utxo
78                                .asset_list
79                                .as_ref()
80                                .and_then(|vec| {
81                                    vec.iter()
82                                        .find(|asset| {
83                                            asset.policy_id == config.contract.seedelf_policy_id
84                                        })
85                                        .map(|asset| &asset.asset_name)
86                                })
87                                .unwrap();
88                            seedelfs.push(asset_name.to_string());
89                        }
90                    }
91                }
92            }
93        }
94        Err(err) => {
95            eprintln!(
96                "Failed to fetch UTxOs: {}\nWait a few moments and try again.",
97                err
98            );
99            std::process::exit(1);
100        }
101    }
102    if !seedelfs.is_empty() {
103        println!("{}", "\nCurrent Seedelf:\n".bright_green());
104        for seedelf in seedelfs {
105            println!("\nSeedelf: {}", seedelf.white());
106            seedelf_label(seedelf);
107        }
108    }
109}
110
111pub fn seedelf_label(seedelf: String) {
112    let substring: String = seedelf[8..38].to_string();
113    let label: String = hex_to_ascii(&substring).unwrap();
114    if !label.starts_with('.') {
115        let cleaned: String = label.chars().filter(|&c| c != '.').collect();
116        println!("Label: {}", cleaned.bright_yellow())
117    }
118}
119
120pub fn hex_to_ascii(hex: &str) -> Result<String, &'static str> {
121    // Ensure the length of the hex string is even
122    if hex.len() % 2 != 0 {
123        return Err("Hex string must have an even length");
124    }
125
126    let ascii = (0..hex.len())
127        .step_by(2)
128        .map(|i| u8::from_str_radix(&hex[i..i + 2], 16))
129        .collect::<Result<Vec<_>, _>>()
130        .map_err(|_| "Invalid hex string")?
131        .into_iter()
132        .map(|b| {
133            if b.is_ascii_graphic() || b.is_ascii_whitespace() {
134                char::from(b)
135            } else {
136                '.'
137            }
138        })
139        .map(|c| {
140            if c == '\n' || c == '\r' || c == '\t' {
141                '.'
142            } else {
143                c
144            }
145        }) // Replace control characters
146        .collect::<String>();
147
148    Ok(ascii)
149}