1use eyre::WrapErr as _;
4use std::time::Duration;
5
6pub(crate) fn install_crypto_provider() {
17 rustls::crypto::ring::default_provider()
19 .install_default()
20 .expect("Failed to install default rustls crypto provider");
21}
22
23pub(crate) fn block_on_consensus_public_key(
24 args: &tempo_consensus::Args,
25) -> eyre::Result<Option<commonware_cryptography::ed25519::PublicKey>> {
26 tokio::runtime::Builder::new_current_thread()
27 .enable_time()
28 .build()
29 .wrap_err("failed building runtime for consensus key parsing")?
30 .block_on(args.public_key())
31}
32
33pub(crate) fn print_extensions_footer() {
36 let is_subcommand_help = std::env::args()
37 .skip(1)
38 .any(|a| !a.starts_with('-') && a != "help");
39 if is_subcommand_help {
40 return;
41 }
42
43 let extensions = match tempo_ext::installed_extensions() {
44 Ok(e) => e,
45 Err(_) => return,
46 };
47 if extensions.is_empty() {
48 return;
49 }
50 let use_color = std::io::IsTerminal::is_terminal(&std::io::stdout());
51 let (b, bu, r) = if use_color {
52 ("\x1b[1m", "\x1b[1m\x1b[4m", "\x1b[0m")
53 } else {
54 ("", "", "")
55 };
56 println!("\n{bu}Extensions:{r}");
57 for (name, desc) in &extensions {
58 if desc.is_empty() {
59 println!(" {b}{name}{r}");
60 } else {
61 println!(" {b}{name:<22}{r} {desc}");
62 }
63 }
64}
65
66pub(crate) async fn fetch_bootnodes(
71 endpoint: &str,
72 chain_id: u64,
73) -> eyre::Result<Vec<reth_network_peers::NodeRecord>> {
74 let client = reqwest::Client::builder()
75 .timeout(Duration::from_secs(5))
76 .build()
77 .wrap_err("failed to build HTTP client")?;
78
79 let resp: std::collections::HashMap<String, Vec<String>> = client
80 .get(endpoint)
81 .send()
82 .await
83 .wrap_err("request failed")?
84 .error_for_status()
85 .wrap_err("endpoint returned error status")?
86 .json()
87 .await
88 .wrap_err("failed to parse response as JSON")?;
89
90 Ok(resp
91 .get(&chain_id.to_string())
92 .map(reth_network_peers::parse_nodes)
93 .unwrap_or_default())
94}