From f70f165ba01bff72c92e20b523b05df414be7c2e Mon Sep 17 00:00:00 2001 From: Nicolas80 <nicolas.pmail@protonmail.com> Date: Wed, 5 Feb 2025 14:14:23 +0100 Subject: [PATCH] * Moved Vault display only functions and tests into display sub module --- src/commands/vault.rs | 174 ++++------------------------------ src/commands/vault/display.rs | 157 ++++++++++++++++++++++++++++++ 2 files changed, 174 insertions(+), 157 deletions(-) create mode 100644 src/commands/vault/display.rs diff --git a/src/commands/vault.rs b/src/commands/vault.rs index ee5b235..534091f 100644 --- a/src/commands/vault.rs +++ b/src/commands/vault.rs @@ -1,9 +1,10 @@ +mod display; + use crate::commands::cesium::compute_g1v1_public_key; use crate::entities::vault_account; use crate::entities::vault_account::{AccountTreeNode, ActiveModel, DbAccountId}; use crate::*; use age::secrecy::Secret; -use comfy_table::{Cell, Table}; use sea_orm::ActiveValue::Set; use sea_orm::{ConnectionTrait, TransactionTrait}; use sea_orm::{DbErr, ModelTrait}; @@ -153,7 +154,8 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE ListChoice::All => { let all_account_tree_node_hierarchies = vault_account::fetch_all_base_account_tree_node_hierarchies(db).await?; - let table = compute_vault_accounts_table(&all_account_tree_node_hierarchies)?; + let table = + display::compute_vault_accounts_table(&all_account_tree_node_hierarchies)?; println!("available SS58 Addresses:"); println!("{table}"); @@ -162,7 +164,7 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE let base_account_tree_nodes = vault_account::fetch_only_base_account_tree_nodes(db).await?; - let table = compute_vault_accounts_table(&base_account_tree_nodes)?; + let table = display::compute_vault_accounts_table(&base_account_tree_nodes)?; println!("available <Base> SS58 Addresses:"); println!("{table}"); @@ -176,7 +178,7 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE let base_account_tree_node = vault_account::get_base_account_tree_node(&account_tree_node); - let table = compute_vault_accounts_table(&[base_account_tree_node])?; + let table = display::compute_vault_accounts_table(&[base_account_tree_node])?; println!( "available SS58 Addresses linked to {}:", @@ -188,7 +190,7 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE Subcommand::ListFiles => { let vault_key_addresses = fetch_vault_key_addresses(&data).await?; - let table = compute_vault_key_files_table(&vault_key_addresses).await?; + let table = display::compute_vault_key_files_table(&vault_key_addresses)?; println!("available key files (needs to be migrated with command `vault migrate` in order to use them):"); println!("{table}"); @@ -281,7 +283,9 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE ); let parent_hierarchy_table_account_to_derive = - compute_vault_accounts_table(&[base_parent_hierarchy_account_tree_node_to_derive])?; + display::compute_vault_accounts_table(&[ + base_parent_hierarchy_account_tree_node_to_derive, + ])?; println!(); println!("Its parent hierarchy is this:"); @@ -361,7 +365,8 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE //If account to delete has children; also delete all linked derivations if !account_tree_node_to_delete.borrow().children.is_empty() { - let table = compute_vault_accounts_table(&[account_tree_node_to_delete.clone()])?; + let table = + display::compute_vault_accounts_table(&[account_tree_node_to_delete.clone()])?; println!("All addresses linked to: {account_to_delete}"); println!("{table}"); @@ -423,7 +428,7 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE let vault_key_addresses = fetch_vault_key_addresses(&data).await?; - let table = compute_vault_key_files_table(&vault_key_addresses).await?; + let table = display::compute_vault_key_files_table(&vault_key_addresses)?; println!("available key files to possibly migrate:"); println!("{table}"); @@ -568,93 +573,6 @@ async fn fetch_vault_key_addresses(data: &Data) -> Result<Vec<String>, GcliError Ok(vault_key_addresses) } -#[deprecated( - note = "Should be removed in a future version when db persistence of vault is present for a while" -)] -async fn compute_vault_key_files_table(vault_key_addresses: &[String]) -> Result<Table, GcliError> { - let mut table = Table::new(); - table.load_preset(comfy_table::presets::UTF8_BORDERS_ONLY); - table.set_header(vec!["Key file"]); - - vault_key_addresses.iter().for_each(|address| { - table.add_row(vec![Cell::new(address)]); - }); - - Ok(table) -} - -pub fn compute_vault_accounts_table( - account_tree_nodes: &[Rc<RefCell<AccountTreeNode>>], -) -> Result<Table, GcliError> { - let mut table = Table::new(); - table.load_preset(comfy_table::presets::UTF8_BORDERS_ONLY); - table.set_header(vec!["SS58 Address", "Format", "Account/Path", "Name"]); - - for account_tree_node in account_tree_nodes { - add_account_tree_node_to_table(&mut table, account_tree_node); - } - - Ok(table) -} - -fn add_account_tree_node_to_table( - table: &mut Table, - account_tree_node: &Rc<RefCell<AccountTreeNode>>, -) { - let row = compute_vault_accounts_row(account_tree_node); - table.add_row(row); - - for child in &account_tree_node.borrow().children { - add_account_tree_node_to_table(table, child); - } -} - -pub fn compute_vault_accounts_row(account_tree_node: &Rc<RefCell<AccountTreeNode>>) -> Vec<Cell> { - let empty_string = "".to_string(); - - let depth_account_tree_node = vault_account::count_depth_account_tree_node(account_tree_node); - - let name = if let Some(name) = account_tree_node.borrow().account.name.clone() { - name - } else if let Some(computed_name) = - vault_account::compute_name_account_tree_node(account_tree_node) - { - format!("<{}>", computed_name) - } else { - empty_string.clone() - }; - - let account_tree_node = account_tree_node.borrow(); - - let address = if depth_account_tree_node > 0 { - let ancestors = "│ ".repeat(depth_account_tree_node - 1); - format!("{}├─{}", ancestors, account_tree_node.account.address) - } else { - account_tree_node.account.address.to_string() - }; - - let (path, format) = if let Some(path) = account_tree_node.account.path.clone() { - (path, empty_string.clone()) - } else { - let secret_format = match account_tree_node.account.crypto_scheme.unwrap().into() { - CryptoScheme::Sr25519 => SecretFormat::Substrate, - CryptoScheme::Ed25519 => SecretFormat::Cesium, - }; - let secret_format_str: &str = secret_format.into(); - ( - format!("<{}>", account_tree_node.account.account_type()), - secret_format_str.to_string(), - ) - }; - - vec![ - Cell::new(&address), - Cell::new(format), - Cell::new(&path), - Cell::new(&name), - ] -} - pub async fn retrieve_vault_account_for_name<C>( db: &C, name_input: &String, @@ -839,7 +757,7 @@ where ); let parent_hierarchy_table = - compute_vault_accounts_table(&[base_parent_hierarchy_account_tree_node])?; + display::compute_vault_accounts_table(&[base_parent_hierarchy_account_tree_node])?; println!("You are trying to add {address_to_import} as a <Base> account"); println!( @@ -971,7 +889,9 @@ where ); let parent_hierarchy_table_existing_account = - compute_vault_accounts_table(&[base_parent_hierarchy_existing_account_tree_node])?; + display::compute_vault_accounts_table(&[ + base_parent_hierarchy_existing_account_tree_node, + ])?; println!( "but it is already present as `{}` derivation of '{}' account.", @@ -1293,64 +1213,4 @@ mod tests { other => panic!("Should have been an Input error; got: {:?}", other), } } - - mod vault_accounts_table_tests { - use crate::commands::vault::compute_vault_accounts_table; - use crate::entities::vault_account::tests::account_tree_node_tests::mother_account_tree_node; - use indoc::indoc; - - #[test] - fn test_compute_vault_accounts_table_empty() { - let table = compute_vault_accounts_table(&[]).unwrap(); - - let expected_table = indoc! {r#" - ┌─────────────────────────────────────────────┠- │ SS58 Address Format Account/Path Name │ - ╞â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•¡ - └─────────────────────────────────────────────┘"# - }; - - assert_eq!(table.to_string(), expected_table); - } - - #[test] - fn test_compute_vault_accounts_table() { - let account_tree_node = mother_account_tree_node(); - - let table = compute_vault_accounts_table(&[account_tree_node]).unwrap(); - - let expected_table = indoc! {r#" - ┌──────────────────────────────────────────────────────────────────────────────────────────────────┠- │ SS58 Address Format Account/Path Name │ - ╞â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•¡ - │ 5DfhGyQdFobKM8NsWvEeAKk5EQQgYe9AydgJ7rMB6E1EqRzV substrate <Base> Mother │ - │ ├─5D34dL5prEUaGNQtPPZ3yN5Y6BnkfXunKXXz6fo7ZJbLwRRH //0 Child 1 │ - │ │ ├─5Fh5PLQNt1xuEXm71dfDtQdnwceSew4oHewWBLsWAkKspV7d //0 Grandchild 1 │ - │ ├─5GBNeWRhZc2jXu7D55rBimKYDk8PGk8itRYFTPfC8RJLKG5o //1 <Mother//1> │ - │ │ ├─5CvdJuB9HLXSi5FS9LW57cyHF13iCv5HDimo2C45KxnxriCT //1 <Mother//1//1> │ - └──────────────────────────────────────────────────────────────────────────────────────────────────┘"# - }; - - assert_eq!(table.to_string(), expected_table); - } - - #[test] - fn test_compute_vault_accounts_table_partial() { - let mother = mother_account_tree_node(); - let child1 = mother.borrow().children[0].clone(); - - let table = compute_vault_accounts_table(&[child1]).unwrap(); - - let expected_table = indoc! {r#" - ┌─────────────────────────────────────────────────────────────────────────────────────────────┠- │ SS58 Address Format Account/Path Name │ - ╞â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•¡ - │ ├─5D34dL5prEUaGNQtPPZ3yN5Y6BnkfXunKXXz6fo7ZJbLwRRH //0 Child 1 │ - │ │ ├─5Fh5PLQNt1xuEXm71dfDtQdnwceSew4oHewWBLsWAkKspV7d //0 Grandchild 1 │ - └─────────────────────────────────────────────────────────────────────────────────────────────┘"# - }; - - assert_eq!(table.to_string(), expected_table); - } - } } diff --git a/src/commands/vault/display.rs b/src/commands/vault/display.rs new file mode 100644 index 0000000..f7bab79 --- /dev/null +++ b/src/commands/vault/display.rs @@ -0,0 +1,157 @@ +use crate::entities::vault_account; +use crate::entities::vault_account::AccountTreeNode; +use crate::keys::{CryptoScheme, SecretFormat}; +use crate::utils::GcliError; +use comfy_table::{Cell, Table}; +use std::cell::RefCell; +use std::rc::Rc; + +#[deprecated( + note = "Should be removed in a future version when db persistence of vault is present for a while" +)] +pub fn compute_vault_key_files_table(vault_key_addresses: &[String]) -> Result<Table, GcliError> { + let mut table = Table::new(); + table.load_preset(comfy_table::presets::UTF8_BORDERS_ONLY); + table.set_header(vec!["Key file"]); + + vault_key_addresses.iter().for_each(|address| { + table.add_row(vec![Cell::new(address)]); + }); + + Ok(table) +} + +pub fn compute_vault_accounts_table( + account_tree_nodes: &[Rc<RefCell<AccountTreeNode>>], +) -> Result<Table, GcliError> { + let mut table = Table::new(); + table.load_preset(comfy_table::presets::UTF8_BORDERS_ONLY); + table.set_header(vec!["SS58 Address", "Format", "Account/Path", "Name"]); + + for account_tree_node in account_tree_nodes { + add_account_tree_node_to_table(&mut table, account_tree_node); + } + + Ok(table) +} + +fn add_account_tree_node_to_table( + table: &mut Table, + account_tree_node: &Rc<RefCell<AccountTreeNode>>, +) { + let row = compute_vault_accounts_row(account_tree_node); + table.add_row(row); + + for child in &account_tree_node.borrow().children { + add_account_tree_node_to_table(table, child); + } +} + +pub fn compute_vault_accounts_row(account_tree_node: &Rc<RefCell<AccountTreeNode>>) -> Vec<Cell> { + let empty_string = "".to_string(); + + let depth_account_tree_node = vault_account::count_depth_account_tree_node(account_tree_node); + + let name = if let Some(name) = account_tree_node.borrow().account.name.clone() { + name + } else if let Some(computed_name) = + vault_account::compute_name_account_tree_node(account_tree_node) + { + format!("<{}>", computed_name) + } else { + empty_string.clone() + }; + + let account_tree_node = account_tree_node.borrow(); + + let address = if depth_account_tree_node > 0 { + let ancestors = "│ ".repeat(depth_account_tree_node - 1); + format!("{}├─{}", ancestors, account_tree_node.account.address) + } else { + account_tree_node.account.address.to_string() + }; + + let (path, format) = if let Some(path) = account_tree_node.account.path.clone() { + (path, empty_string.clone()) + } else { + let secret_format = match account_tree_node.account.crypto_scheme.unwrap().into() { + CryptoScheme::Sr25519 => SecretFormat::Substrate, + CryptoScheme::Ed25519 => SecretFormat::Cesium, + }; + let secret_format_str: &str = secret_format.into(); + ( + format!("<{}>", account_tree_node.account.account_type()), + secret_format_str.to_string(), + ) + }; + + vec![ + Cell::new(&address), + Cell::new(format), + Cell::new(&path), + Cell::new(&name), + ] +} + +#[cfg(test)] +mod tests { + mod vault_accounts_table_tests { + use crate::commands::vault::display::compute_vault_accounts_table; + use crate::entities::vault_account::tests::account_tree_node_tests::mother_account_tree_node; + use indoc::indoc; + + #[test] + fn test_compute_vault_accounts_table_empty() { + let table = compute_vault_accounts_table(&[]).unwrap(); + + let expected_table = indoc! {r#" + ┌─────────────────────────────────────────────┠+ │ SS58 Address Format Account/Path Name │ + ╞â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•¡ + └─────────────────────────────────────────────┘"# + }; + + assert_eq!(table.to_string(), expected_table); + } + + #[test] + fn test_compute_vault_accounts_table() { + let account_tree_node = mother_account_tree_node(); + + let table = compute_vault_accounts_table(&[account_tree_node]).unwrap(); + + let expected_table = indoc! {r#" + ┌──────────────────────────────────────────────────────────────────────────────────────────────────┠+ │ SS58 Address Format Account/Path Name │ + ╞â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•¡ + │ 5DfhGyQdFobKM8NsWvEeAKk5EQQgYe9AydgJ7rMB6E1EqRzV substrate <Base> Mother │ + │ ├─5D34dL5prEUaGNQtPPZ3yN5Y6BnkfXunKXXz6fo7ZJbLwRRH //0 Child 1 │ + │ │ ├─5Fh5PLQNt1xuEXm71dfDtQdnwceSew4oHewWBLsWAkKspV7d //0 Grandchild 1 │ + │ ├─5GBNeWRhZc2jXu7D55rBimKYDk8PGk8itRYFTPfC8RJLKG5o //1 <Mother//1> │ + │ │ ├─5CvdJuB9HLXSi5FS9LW57cyHF13iCv5HDimo2C45KxnxriCT //1 <Mother//1//1> │ + └──────────────────────────────────────────────────────────────────────────────────────────────────┘"# + }; + + assert_eq!(table.to_string(), expected_table); + } + + #[test] + fn test_compute_vault_accounts_table_partial() { + let mother = mother_account_tree_node(); + let child1 = mother.borrow().children[0].clone(); + + let table = compute_vault_accounts_table(&[child1]).unwrap(); + + let expected_table = indoc! {r#" + ┌─────────────────────────────────────────────────────────────────────────────────────────────┠+ │ SS58 Address Format Account/Path Name │ + ╞â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•¡ + │ ├─5D34dL5prEUaGNQtPPZ3yN5Y6BnkfXunKXXz6fo7ZJbLwRRH //0 Child 1 │ + │ │ ├─5Fh5PLQNt1xuEXm71dfDtQdnwceSew4oHewWBLsWAkKspV7d //0 Grandchild 1 │ + └─────────────────────────────────────────────────────────────────────────────────────────────┘"# + }; + + assert_eq!(table.to_string(), expected_table); + } + } +} -- GitLab