diff --git a/src/commands/vault.rs b/src/commands/vault.rs index 267a0c26bc870482f0c246fab2ba48eb20c2ce4e..fe0583292692fc65c71f87297a39648de5542a77 100644 --- a/src/commands/vault.rs +++ b/src/commands/vault.rs @@ -1,9 +1,6 @@ use crate::commands::cesium::compute_g1v1_public_key; use crate::entities::vault_account; -use crate::entities::vault_account::{ - fetch_base_account_tree_node_hierarchy_unwrapped, get_account_tree_node_for_address, - get_base_parent_hierarchy_account_tree_node, AccountTreeNode, ActiveModel, DbAccountId, -}; +use crate::entities::vault_account::{AccountTreeNode, ActiveModel, DbAccountId}; use crate::*; use age::secrecy::Secret; use comfy_table::{Cell, Table}; @@ -88,7 +85,7 @@ pub enum ListChoice { /// List all <Base> accounts and their linked derivations SS58 Addresses in the vault #[default] All, - /// List <Base> and Derivations SS58 Addresses linked to the selected one + /// List <Base> and Derivation SS58 Addresses linked to the selected one For { #[clap(flatten)] address_or_vault_name: AddressOrVaultNameGroup, @@ -156,18 +153,18 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE ListChoice::For { address_or_vault_name, } => { - let account = retrieve_vault_account(&data, address_or_vault_name).await?; + let account_tree_node = + retrieve_account_tree_node(db, address_or_vault_name).await?; - let account_tree_node_hierarchy = - vault_account::fetch_base_account_tree_node_hierarchy_unwrapped( - db, - &account.address.to_string(), - ) - .await?; + let base_account_tree_node = + vault_account::get_base_account_tree_node(&account_tree_node); - let table = compute_vault_accounts_table(&[account_tree_node_hierarchy])?; + let table = compute_vault_accounts_table(&[base_account_tree_node])?; - println!("available SS58 Addresses linked to {account}:"); + println!( + "available SS58 Addresses linked to {}:", + account_tree_node.borrow().account + ); println!("{table}"); } }, @@ -182,7 +179,7 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE Subcommand::Use { address_or_vault_name, } => { - let account = retrieve_vault_account(&data, address_or_vault_name).await?; + let account = retrieve_vault_account(db, address_or_vault_name).await?; println!("Using: {}", account); @@ -230,7 +227,7 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE address_or_vault_name, } => { let account_tree_node_to_derive = - retrieve_account_tree_node(&data, address_or_vault_name).await?; + retrieve_account_tree_node(db, address_or_vault_name).await?; let account_to_derive = account_tree_node_to_derive.borrow().account.clone(); @@ -262,7 +259,9 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE println!("Adding derivation to: {account_to_derive}"); let base_parent_hierarchy_account_tree_node_to_derive = - get_base_parent_hierarchy_account_tree_node(&account_tree_node_to_derive); + vault_account::get_base_parent_hierarchy_account_tree_node( + &account_tree_node_to_derive, + ); let parent_hierarchy_table_account_to_derive = compute_vault_accounts_table(&[base_parent_hierarchy_account_tree_node_to_derive])?; @@ -336,7 +335,7 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE address_or_vault_name, } => { let account_tree_node_to_delete = - retrieve_account_tree_node(&data, address_or_vault_name).await?; + retrieve_account_tree_node(db, address_or_vault_name).await?; let txn = db.begin().await?; @@ -375,11 +374,11 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE &account_tree_node_to_delete, )? { let delete_result = account_to_delete.delete(&txn).await?; - println!("Deleted {} address", delete_result.rows_affected); + println!("Deleting {} address", delete_result.rows_affected); } } else { let delete_result = account_to_delete.delete(&txn).await?; - println!("Deleted {} address", delete_result.rows_affected); + println!("Deleting {} address", delete_result.rows_affected); } txn.commit().await?; @@ -390,7 +389,7 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE address_or_vault_name, } => { let account_tree_node_to_derive = - retrieve_account_tree_node(&data, address_or_vault_name).await?; + retrieve_account_tree_node(db, address_or_vault_name).await?; println!("Enter password to decrypt the <Base> account key"); let password = inputs::prompt_password()?; @@ -641,94 +640,99 @@ pub fn compute_vault_accounts_row(account_tree_node: &Rc<RefCell<AccountTreeNode ] } -pub async fn retrieve_address_string<T: AddressOrVaultName>( - data: &Data, +pub async fn retrieve_address_string<C, T: AddressOrVaultName>( + db: &C, address_or_vault_name: T, -) -> Result<String, GcliError> { +) -> Result<String, GcliError> +where + C: ConnectionTrait, +{ if let Some(address) = address_or_vault_name.address() { return Ok(address.to_string()); } - let account = retrieve_vault_account(data, address_or_vault_name).await?; + let account = retrieve_vault_account(db, address_or_vault_name).await?; Ok(account.address.to_string()) } -pub async fn retrieve_account_tree_node<T: AddressOrVaultName>( - data: &Data, - address_or_vault_name: T, -) -> Result<Rc<RefCell<AccountTreeNode>>, GcliError> { - //FIXME Should do the inverse as we do potentially several times same operation - let account = retrieve_vault_account(data, address_or_vault_name).await?; - - let account_tree_node = vault_account::fetch_base_account_tree_node_hierarchy_unwrapped( - data.connect_db(), - &account.address.to_string(), - ) - .await?; - - Ok(vault_account::get_account_tree_node_for_address( - &account_tree_node, - &account.address.to_string(), - )) -} - -pub async fn retrieve_vault_account<T: AddressOrVaultName>( - data: &Data, +pub async fn retrieve_account_tree_node<C, T: AddressOrVaultName>( + db: &C, address_or_vault_name: T, -) -> Result<vault_account::Model, GcliError> { - let account = if let Some(name_input) = address_or_vault_name.name() { +) -> Result<Rc<RefCell<AccountTreeNode>>, GcliError> +where + C: ConnectionTrait, +{ + let account_tree_node = if let Some(name_input) = address_or_vault_name.name() { let (name, derivation_path_opt) = parse_prefix_and_derivation_path_from_string_for_vault_name(name_input.to_string())?; - let account = vault_account::find_by_name(data.connect_db(), &name).await?; + let account_for_name = vault_account::find_by_name(db, &name).await?; - let account = account.ok_or(GcliError::Input(format!( + let account_for_name = account_for_name.ok_or(GcliError::Input(format!( "No account found with name:'{name}'" )))?; - match derivation_path_opt { - None => account, - Some(path) => { - let account_tree_node_hierarchy = - vault_account::fetch_base_account_tree_node_hierarchy_unwrapped( - data.connect_db(), - &account.address.to_string(), - ) - .await?; - - let account_tree_node_hierarchy = vault_account::get_account_tree_node_for_address( - &account_tree_node_hierarchy, - &account.address.to_string(), - ); - - let account_tree_node = vault_account::compute_name_map_for_account_tree_node( - &account_tree_node_hierarchy, - )? - .get(name_input) - .cloned() - .ok_or(GcliError::Input(format!( - "No account found with name:'{name}' and path:'{path}'" - )))?; + let base_account_tree_node = + vault_account::fetch_base_account_tree_node_hierarchy_unwrapped( + db, + &account_for_name.address.to_string(), + ) + .await?; - //Need this extra step to avoid borrowing issues - let account = account_tree_node.borrow().account.clone(); + let account_tree_node_for_name = vault_account::get_account_tree_node_for_address( + &base_account_tree_node, + &account_for_name.address.to_string(), + ); - account + match derivation_path_opt { + None => Rc::clone(&account_tree_node_for_name), + Some(path) => { + let account_tree_node_for_name_input = + vault_account::compute_name_map_for_account_tree_node( + &account_tree_node_for_name, + )? + .get(name_input) + .cloned() + .ok_or(GcliError::Input(format!( + "No account found with name:'{name}' and path:'{path}'" + )))?; + + Rc::clone(&account_tree_node_for_name_input) } } } else if let Some(address) = address_or_vault_name.address() { - let account = - vault_account::find_by_id(data.connect_db(), &DbAccountId::from(address.clone())) - .await?; + let base_account_tree_node = + vault_account::fetch_base_account_tree_node_hierarchy_unwrapped( + db, + &address.to_string(), + ) + .await?; - account.ok_or(GcliError::Input(format!( - "No vault entry found with Address:'{address}'" - )))? + let account_tree_node_for_address = vault_account::get_account_tree_node_for_address( + &base_account_tree_node, + &address.to_string(), + ); + + Rc::clone(&account_tree_node_for_address) } else { //Should never happen since clap enforces exactly one of the 2 options return Err(GcliError::Input("No address or name provided".to_string())); }; + Ok(account_tree_node) +} + +pub async fn retrieve_vault_account<C, T: AddressOrVaultName>( + db: &C, + address_or_vault_name: T, +) -> Result<vault_account::Model, GcliError> +where + C: ConnectionTrait, +{ + let account_tree_node = retrieve_account_tree_node(db, address_or_vault_name).await?; + + //Need this extra step to avoid borrowing issues + let account = account_tree_node.borrow().account.clone(); Ok(account) } @@ -799,12 +803,20 @@ where } else { // Existing derivation account let account_tree_node_hierarchy = - fetch_base_account_tree_node_hierarchy_unwrapped(db_tx, &address_to_import).await?; - let account_tree_node_for_address = - get_account_tree_node_for_address(&account_tree_node_hierarchy, &address_to_import); + vault_account::fetch_base_account_tree_node_hierarchy_unwrapped( + db_tx, + &address_to_import, + ) + .await?; + let account_tree_node_for_address = vault_account::get_account_tree_node_for_address( + &account_tree_node_hierarchy, + &address_to_import, + ); let base_parent_hierarchy_account_tree_node = - get_base_parent_hierarchy_account_tree_node(&account_tree_node_for_address); + vault_account::get_base_parent_hierarchy_account_tree_node( + &account_tree_node_for_address, + ); let parent_hierarchy_table = compute_vault_accounts_table(&[base_parent_hierarchy_account_tree_node])?; @@ -921,15 +933,20 @@ where } else { //Existing derivation let existing_account_tree_node_hierarchy = - fetch_base_account_tree_node_hierarchy_unwrapped(db_tx, derivation_address).await?; + vault_account::fetch_base_account_tree_node_hierarchy_unwrapped( + db_tx, + derivation_address, + ) + .await?; - let existing_account_tree_node_for_address = get_account_tree_node_for_address( - &existing_account_tree_node_hierarchy, - derivation_address, - ); + let existing_account_tree_node_for_address = + vault_account::get_account_tree_node_for_address( + &existing_account_tree_node_hierarchy, + derivation_address, + ); let base_parent_hierarchy_existing_account_tree_node = - get_base_parent_hierarchy_account_tree_node( + vault_account::get_base_parent_hierarchy_account_tree_node( &existing_account_tree_node_for_address, ); diff --git a/src/data.rs b/src/data.rs index 67d9928652491e6dce3bfc5718bc878d0b9ae43f..3ad00206a18a982edbb21fb24af3a5b524e115c1 100644 --- a/src/data.rs +++ b/src/data.rs @@ -200,7 +200,8 @@ impl Data { } // address or vault name if let Some(address_or_vault_name) = self.args.address_or_vault_name.clone() { - let address = vault::retrieve_address_string(&self, address_or_vault_name).await?; + let address = + vault::retrieve_address_string(self.connect_db(), address_or_vault_name).await?; self.cfg.address = Some(AccountId::from_str(&address).expect("invalid address")); // if giving address, cancel secret