Skip to content
Snippets Groups Projects
Commit cf7a4292 authored by Nicolas80's avatar Nicolas80
Browse files

* Adapted to have more coherent commands descriptions and added `long_about`...

* Adapted to have more coherent commands descriptions and added `long_about` more detailed description for `import` and `derivation`
* Added the `vault list for` command
* Added display of "format" of <Root> derivations in all `vault list` commands
* Only allowing derivations for format "substrate" and "seed"
parent 747e02da
Branches
Tags
1 merge request!41Adding db persistence for all SecretFormat of vault keys as well as supporting derivations
......@@ -13,10 +13,10 @@ use std::path::PathBuf;
/// define universal dividends subcommands
#[derive(Clone, Debug, clap::Parser)]
pub enum Subcommand {
/// List available keys
/// List available derivations
#[clap(subcommand)]
List(ListChoice),
/// Use specific vault key (changes the config address)
/// Use specific derivation (changes the config Address)
Use {
#[clap(flatten)]
address_or_vault_name: AddressOrVaultNameGroup,
......@@ -24,29 +24,40 @@ pub enum Subcommand {
/// Generate a mnemonic
Generate,
/// Import key from (substrate)mnemonic or other format with interactive prompt
#[clap(
long_about = "Import key from (substrate)mnemonic or other format with interactive prompt\n\
\n\
If a (substrate)mnemonic is provided with a derivation path, it will ensure the <Root> derivation\n\
and associated key exists before creating the new derivation; but please use command \n\
`vault derivation|derive|deriv` to add a derivation to an existing <Root> derivation instead."
)]
Import {
/// Secret key format (substrate, seed, cesium)
#[clap(short = 'S', long, required = false, default_value = SecretFormat::Substrate)]
secret_format: SecretFormat,
},
/// Add a derivation to an existing (root) vault key
/// Add a derivation to an existing <Root> derivation
#[clap(long_about = "Add a derivation to an existing <Root> derivation\n\
\n\
Only \"substrate\" and \"seed\" format are supported for derivations\n\
Use command `vault list root` to see available <Root> derivations and their format")]
#[clap(alias = "deriv")]
#[clap(alias = "derive")]
Derivation {
#[clap(flatten)]
address_or_vault_name: AddressOrVaultNameGroup,
},
/// Give a meaningful vault name to a vault key or derivation
/// Give a meaningful derivation name to a key derivation (can be for a <Root> derivation)
Rename {
/// key SS58 Address
/// SS58 Address
address: AccountId,
},
/// Remove a vault key (and potential derivations if it's a root key)
/// Remove a derivation (and all linked derivations along with the key if a <Root> derivation is given)
Remove {
#[clap(flatten)]
address_or_vault_name: AddressOrVaultNameGroup,
},
/// (deprecated)List available key files (needs to be migrated with command "vault migrate" in order to use them)
/// (deprecated)List available key files (needs to be migrated with command `vault migrate` in order to use them)
ListFiles,
/// (deprecated)Migrate old key files into db (will have to provide password for each key)
Migrate,
......@@ -56,10 +67,15 @@ pub enum Subcommand {
#[derive(Clone, Default, Debug, clap::Parser)]
pub enum ListChoice {
/// List all keys and derivations in the vault
/// List all <Root> derivations and their linked derivations in the vault
#[default]
All,
/// List only root keys
/// List all derivations linked to the one selected
For {
#[clap(flatten)]
address_or_vault_name: AddressOrVaultNameGroup,
},
/// List only <Root> derivations in the vault
Root,
}
......@@ -107,9 +123,13 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE
)
.await?;
let table = compute_vault_derivations_table(&derivations).await?;
let table = compute_vault_derivations_table(
data.connection.as_ref().unwrap(),
&derivations,
)
.await?;
println!("available keys:");
println!("available derivations:");
println!("{table}");
}
ListChoice::Root => {
......@@ -118,9 +138,34 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE
)
.await?;
let table = compute_vault_derivations_table(&derivations).await?;
let table = compute_vault_derivations_table(
data.connection.as_ref().unwrap(),
&derivations,
)
.await?;
println!("available <Root> derivations:");
println!("{table}");
}
ListChoice::For {
address_or_vault_name,
} => {
let root_derivation =
retrieve_vault_derivation(&data, address_or_vault_name).await?;
let linked_derivations = vault_derivation::fetch_all_linked_derivations_in_order(
data.connection.as_ref().unwrap(),
&root_derivation.root_address,
)
.await?;
let table = compute_vault_derivations_table(
data.connection.as_ref().unwrap(),
&linked_derivations,
)
.await?;
println!("available root keys:");
println!("available derivations linked to {root_derivation}:");
println!("{table}");
}
},
......@@ -176,7 +221,11 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE
.await?;
println!("Here are all the linked derivations already present in the vault:");
let table = compute_vault_derivations_table(&linked_derivations).await?;
let table = compute_vault_derivations_table(
data.connection.as_ref().unwrap(),
&linked_derivations,
)
.await?;
println!("{table}");
return Ok(());
......@@ -225,6 +274,16 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE
root_derivation.address
)))?;
if vault_account.crypto_type == CryptoType::Ed25519Seed {
println!(
"Only \"{}\" and \"{}\" format are supported for derivations",
Into::<&str>::into(SecretFormat::Substrate),
Into::<&str>::into(SecretFormat::Seed)
);
println!("Use command `vault list root` to see available <Root> derivations and their format");
return Ok(());
}
println!("Adding derivation to root key: {root_derivation}");
println!("Enter password to decrypt the root key");
......@@ -308,7 +367,8 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE
)
.await?;
let table = compute_vault_derivations_table(&all_derivations_to_delete).await?;
let table =
compute_vault_derivations_table(&txn, &all_derivations_to_delete).await?;
println!("All derivations linked to the root derivation:");
println!("{table}");
......@@ -468,17 +528,22 @@ async fn compute_vault_key_files_table(vault_key_addresses: &[String]) -> Result
Ok(table)
}
async fn compute_vault_derivations_table(
async fn compute_vault_derivations_table<C>(
db: &C,
derivations_ordered: &[vault_derivation::Model],
) -> Result<Table, GcliError> {
) -> Result<Table, GcliError>
where
C: ConnectionTrait,
{
let mut table = Table::new();
table.load_preset(comfy_table::presets::UTF8_BORDERS_ONLY);
table.set_header(vec!["SS58 Address", "Path", "Vault Name"]);
let empty_name = "".to_string();
table.set_header(vec!["SS58 Address", "Format", "Path", "Derivation Name"]);
let empty_string = "".to_string();
let root_path = "<Root>".to_string();
let mut current_root_address = "".to_string();
let mut current_root_name: Option<String> = None;
let mut current_vault_format: Option<&str> = None;
for derivation in derivations_ordered {
if derivation.root_address != current_root_address {
......@@ -490,6 +555,19 @@ async fn compute_vault_derivations_table(
}
current_root_address = derivation.root_address.clone();
current_root_name = derivation.name.clone();
let vault_account = vault_account::Entity::find_by_id(current_root_address.clone())
.one(db)
.await?
.ok_or(GcliError::Input(format!(
"No vault account found with address:'{current_root_address}'"
)))?;
current_vault_format = match vault_account.crypto_type {
CryptoType::Sr25519Mnemonic => Some(SecretFormat::Substrate.into()),
CryptoType::Sr25519Seed => Some(SecretFormat::Seed.into()),
CryptoType::Ed25519Seed => Some(SecretFormat::Cesium.into()),
};
} else {
// Validate that the RootAddress is the same as current_root_address
if derivation.root_address != current_root_address {
......@@ -505,15 +583,15 @@ async fn compute_vault_derivations_table(
" ".to_string() + &derivation.address
};
let path = if derivation.path.is_none() {
root_path.clone()
let (path, format) = if derivation.path.is_none() {
(root_path.clone(), current_vault_format.unwrap())
} else {
derivation.path.clone().unwrap()
(derivation.path.clone().unwrap(), empty_string.as_str())
};
let name = if derivation.name.is_none() {
if derivation.path.is_none() {
empty_name.clone()
empty_string.clone()
} else if let Some(current_root_name) = &current_root_name {
format!(
"<{}{}>",
......@@ -521,7 +599,7 @@ async fn compute_vault_derivations_table(
derivation.path.clone().unwrap()
)
} else {
empty_name.clone()
empty_string.clone()
}
} else {
derivation.name.clone().unwrap()
......@@ -529,6 +607,7 @@ async fn compute_vault_derivations_table(
table.add_row(vec![
Cell::new(&address),
Cell::new(format),
Cell::new(&path),
Cell::new(&name),
]);
......
......@@ -91,7 +91,7 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE
)
.await?
{
println!("(Vault entry: {})", derivation);
println!("(Vault derivation: {})", derivation);
}
}
}
......
......@@ -78,11 +78,11 @@ trait AddressOrVaultName {
#[derive(Debug, clap::Args, Clone)]
#[group(required = false, multiple = false)]
pub struct AddressOrVaultNameGroupOptional {
/// key SS58 Address
/// SS58 Address
#[clap(short)]
address: Option<AccountId>,
/// Vault name for a key
#[clap(short = 'v')]
/// Derivation name for a SS58 Address (can be a <Root> derivation name)
#[clap(short = 'd')]
name: Option<String>,
}
......@@ -98,11 +98,11 @@ impl AddressOrVaultName for AddressOrVaultNameGroupOptional {
#[derive(Debug, clap::Args, Clone)]
#[group(required = true, multiple = false)]
pub struct AddressOrVaultNameGroup {
/// key SS58 Address
/// SS58 Address
#[clap(short)]
address: Option<AccountId>,
/// Vault name for a key
#[clap(short = 'v')]
/// Derivation name for a SS58 Address (can be a <Root> derivation name)
#[clap(short = 'd')]
name: Option<String>,
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment