/ cli / src / helpers / args.rs
args.rs
 1  // Copyright (c) 2025 ADnet Contributors
 2  // This file is part of the AlphaOS library.
 3  
 4  // Licensed under the Apache License, Version 2.0 (the "License");
 5  // you may not use this file except in compliance with the License.
 6  // You may obtain a copy of the License at:
 7  
 8  // http://www.apache.org/licenses/LICENSE-2.0
 9  
10  // Unless required by applicable law or agreed to in writing, software
11  // distributed under the License is distributed on an "AS IS" BASIS,
12  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  // See the License for the specific language governing permissions and
14  // limitations under the License.
15  
16  use alphavm::{
17      console::network::{CanaryV0, MainnetV0},
18      prelude::{Network, PrivateKey},
19  };
20  
21  use anyhow::{Context, Result, anyhow};
22  use clap::builder::RangedU64ValueParser;
23  use std::{path::PathBuf, str::FromStr};
24  use ureq::http::{Uri, uri};
25  
26  use crate::helpers::dev::get_development_key;
27  
28  pub(crate) fn network_id_parser() -> RangedU64ValueParser<u16> {
29      RangedU64ValueParser::<u16>::new().range((MainnetV0::ID as u64)..=(CanaryV0::ID as u64))
30  }
31  
32  /// Make sure a proper scheme (http or https) is set for the endpoint.
33  pub(crate) fn prepare_endpoint(endpoint: Uri) -> Result<Uri> {
34      let mut parts = endpoint.into_parts();
35  
36      if parts.scheme.is_none() {
37          println!("No scheme given for endpoint. Defaulting to HTTP.");
38          parts.scheme = Some(uri::Scheme::HTTP);
39      }
40  
41      if parts.path_and_query.is_none() {
42          // An empty path is fine for the base URL.
43          parts.path_and_query = Some(uri::PathAndQuery::from_static(""));
44      }
45  
46      // Given that the input URI is valid and the scheme we assign is valid, this should never fail.
47      Uri::from_parts(parts).with_context(|| "Invalid endpoint URL")
48  }
49  
50  /// Fetch the private key, either from the commandline or from a file.
51  pub(crate) fn parse_private_key<N: Network>(
52      cmdline: Option<String>,
53      file_name: Option<String>,
54      dev_key: Option<u16>,
55  ) -> Result<PrivateKey<N>> {
56      if let Some(index) = dev_key {
57          let private_key = get_development_key(index)?;
58          println!("🔑 Using development private key for node {index} ({private_key})\n");
59          return Ok(private_key);
60      }
61  
62      let key_str = if let Some(keystr) = cmdline {
63          keystr
64      } else if let Some(file_name) = file_name {
65          let path = file_name.parse::<PathBuf>().map_err(|e| anyhow!("Invalid path - {e}"))?;
66          std::fs::read_to_string(path).with_context(|| "Failed to read private key from disk")?.trim().to_string()
67      } else {
68          unreachable!();
69      };
70  
71      // Retrieve the private key.
72      let private_key = PrivateKey::from_str(&key_str).with_context(|| "Failed to parse private key")?;
73  
74      Ok(private_key)
75  }
76  
77  #[cfg(test)]
78  mod tests {
79      use super::*;
80  
81      #[test]
82      fn test_prepare_endpoint() {
83          let before = Uri::try_from("localhost:3030").unwrap();
84          let after = prepare_endpoint(before).unwrap();
85          assert_eq!(after.to_string(), "http://localhost:3030/");
86      }
87  }