use account_address::*;
use aptos_crypto::ed25519::{Ed25519PrivateKey, Ed25519PublicKey};
use serde::{Deserialize, Serialize};
use std::{
collections::HashMap,
path::{Path, PathBuf},
};
use utils::{from_yaml, open_file, read_from_file, write_to_user_only_file};
pub mod error;
pub mod utils;
pub use error::*;
#[derive(Debug, Serialize, Deserialize)]
pub struct CliConfig {
pub profiles: Option<HashMap<String, ProfileConfig>>,
}
const CONFIG_FILE: &str = "config.yaml";
const LEGACY_CONFIG_FILE: &str = "config.yml";
const CONFIG_FOLDER: &str = ".aptos";
#[derive(Debug, Default, Serialize, Deserialize)]
pub struct ProfileConfig {
pub private_key: Option<Ed25519PrivateKey>,
pub public_key: Option<Ed25519PublicKey>,
pub account: Option<AccountAddress>,
pub rest_url: Option<String>,
pub faucet_url: Option<String>,
}
impl Default for CliConfig {
fn default() -> Self {
CliConfig {
profiles: Some(HashMap::new()),
}
}
}
impl CliConfig {
pub fn config_exists() -> bool {
if let Ok(folder) = Self::aptos_folder() {
let config_file = folder.join(CONFIG_FILE);
let old_config_file = folder.join(LEGACY_CONFIG_FILE);
config_file.exists() || old_config_file.exists()
} else {
false
}
}
pub fn load() -> CliTypedResult<Self> {
let folder = Self::aptos_folder()?;
let config_file = folder.join(CONFIG_FILE);
let old_config_file = folder.join(LEGACY_CONFIG_FILE);
if config_file.exists() {
from_yaml(
&String::from_utf8(read_from_file(config_file.as_path())?)
.map_err(CliError::from)?,
)
} else if old_config_file.exists() {
from_yaml(
&String::from_utf8(read_from_file(old_config_file.as_path())?)
.map_err(CliError::from)?,
)
} else {
Err(CliError::ConfigNotFoundError(format!(
"{}",
config_file.display()
)))
}
}
pub fn load_profile(profile: &str) -> CliTypedResult<Option<ProfileConfig>> {
let mut config = Self::load()?;
Ok(config.remove_profile(profile))
}
pub fn remove_profile(&mut self, profile: &str) -> Option<ProfileConfig> {
if let Some(ref mut profiles) = self.profiles {
profiles.remove(&profile.to_string())
} else {
None
}
}
pub fn save(&self) -> CliTypedResult<()> {
let aptos_folder = Self::aptos_folder()?;
if !aptos_folder.exists() {
std::fs::create_dir(&aptos_folder).map_err(|err| {
CliError::CommandArgumentError(format!(
"Unable to create {} directory {}",
aptos_folder.display(),
err
))
})?;
}
let config_file = aptos_folder.join(CONFIG_FILE);
let config_bytes = self.try_to_string()?;
write_to_user_only_file(&config_file, CONFIG_FILE, config_bytes.as_bytes())?;
let legacy_config_file = aptos_folder.join(LEGACY_CONFIG_FILE);
if legacy_config_file.exists() {
eprintln!("Removing legacy config file {}", LEGACY_CONFIG_FILE);
let _ = std::fs::remove_file(legacy_config_file);
}
Ok(())
}
fn aptos_folder() -> CliTypedResult<PathBuf> {
std::env::current_dir()
.map_err(|err| {
CliError::UnexpectedError(format!("Unable to get current directory {}", err))
})
.map(|dir| dir.join(CONFIG_FOLDER))
}
pub fn load_from_path(path: &Path) -> CliTypedResult<CliConfig> {
Ok(serde_yaml::from_reader(open_file(path)?)?)
}
pub fn load_from_root(root: &Path) -> CliTypedResult<CliConfig> {
Self::load_from_path(&root.join(CONFIG_FOLDER).join(CONFIG_FILE))
}
pub fn try_to_string(&self) -> CliTypedResult<String> {
serde_yaml::to_string(&self)
.map_err(|err| CliError::UnexpectedError(format!("Failed to serialize config {}", err)))
}
}