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

* Small clean up of `clap` arguments

   * Put back simple `address` and `name` arguments in main.rs (with conflicts_with statement to prevent their usage at the same time)
   * Declared conflicts between indexer <=> no-indexer, indexer <=> network, url <=> network
   * Kept AddressOrVaultNameGroup args for vault usage since it's the only way to define one required arg within a group cleanly
parent 0b9222c2
No related branches found
No related tags found
1 merge request!41Adding db persistence for all SecretFormat of vault keys as well as supporting derivations
...@@ -94,6 +94,17 @@ pub enum ListChoice { ...@@ -94,6 +94,17 @@ pub enum ListChoice {
Base, Base,
} }
#[derive(Debug, clap::Args, Clone)]
#[group(required = true, multiple = false)]
pub struct AddressOrVaultNameGroup {
/// SS58 Address
#[clap(short)]
address: Option<AccountId>,
/// Name of an SS58 Address in the vault
#[clap(short = 'v')]
name: Option<String>,
}
pub struct VaultDataToImport { pub struct VaultDataToImport {
secret_format: SecretFormat, secret_format: SecretFormat,
secret_suri: String, secret_suri: String,
...@@ -640,68 +651,30 @@ pub fn compute_vault_accounts_row(account_tree_node: &Rc<RefCell<AccountTreeNode ...@@ -640,68 +651,30 @@ pub fn compute_vault_accounts_row(account_tree_node: &Rc<RefCell<AccountTreeNode
] ]
} }
pub async fn retrieve_address_string<C, T: AddressOrVaultName>( pub async fn retrieve_vault_account_for_name<C>(
db: &C, db: &C,
address_or_vault_name: T, name_input: &String,
) -> Result<String, GcliError> ) -> Result<vault_account::Model, GcliError>
where where
C: ConnectionTrait, C: ConnectionTrait,
{ {
if let Some(address) = address_or_vault_name.address() { let account_tree_node = retrieve_account_tree_node_for_name(db, name_input).await?;
return Ok(address.to_string());
}
let account = retrieve_vault_account(db, address_or_vault_name).await?;
Ok(account.address.to_string()) //Need this extra step to avoid borrowing issues
let account = account_tree_node.borrow().account.clone();
Ok(account)
} }
pub async fn retrieve_account_tree_node<C, T: AddressOrVaultName>( pub async fn retrieve_account_tree_node<C>(
db: &C, db: &C,
address_or_vault_name: T, address_or_vault_name: AddressOrVaultNameGroup,
) -> Result<Rc<RefCell<AccountTreeNode>>, GcliError> ) -> Result<Rc<RefCell<AccountTreeNode>>, GcliError>
where where
C: ConnectionTrait, C: ConnectionTrait,
{ {
let account_tree_node = if let Some(name_input) = address_or_vault_name.name() { let account_tree_node = if let Some(name_input) = &address_or_vault_name.name {
let (name, derivation_path_opt) = retrieve_account_tree_node_for_name(db, name_input).await?
parse_prefix_and_derivation_path_from_string_for_vault_name(name_input.to_string())?; } else if let Some(address) = &address_or_vault_name.address {
let account_for_name = vault_account::find_by_name(db, &name).await?;
let account_for_name = account_for_name.ok_or(GcliError::Input(format!(
"No account found with name:'{name}'"
)))?;
let base_account_tree_node =
vault_account::fetch_base_account_tree_node_hierarchy_unwrapped(
db,
&account_for_name.address.to_string(),
)
.await?;
let account_tree_node_for_name = vault_account::get_account_tree_node_for_address(
&base_account_tree_node,
&account_for_name.address.to_string(),
);
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 base_account_tree_node = let base_account_tree_node =
vault_account::fetch_base_account_tree_node_hierarchy_unwrapped( vault_account::fetch_base_account_tree_node_hierarchy_unwrapped(
db, db,
...@@ -722,9 +695,52 @@ where ...@@ -722,9 +695,52 @@ where
Ok(account_tree_node) Ok(account_tree_node)
} }
pub async fn retrieve_vault_account<C, T: AddressOrVaultName>( pub async fn retrieve_account_tree_node_for_name<C>(
db: &C,
name_input: &String,
) -> Result<Rc<RefCell<AccountTreeNode>>, GcliError>
where
C: ConnectionTrait,
{
let (name, derivation_path_opt) =
parse_prefix_and_derivation_path_from_string_for_vault_name(name_input.to_string())?;
let account_for_name = vault_account::find_by_name(db, &name).await?;
let account_for_name = account_for_name.ok_or(GcliError::Input(format!(
"No account found with name:'{name}'"
)))?;
let base_account_tree_node = vault_account::fetch_base_account_tree_node_hierarchy_unwrapped(
db,
&account_for_name.address.to_string(),
)
.await?;
let account_tree_node_for_name = vault_account::get_account_tree_node_for_address(
&base_account_tree_node,
&account_for_name.address.to_string(),
);
Ok(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)
}
})
}
pub async fn retrieve_vault_account<C>(
db: &C, db: &C,
address_or_vault_name: T, address_or_vault_name: AddressOrVaultNameGroup,
) -> Result<vault_account::Model, GcliError> ) -> Result<vault_account::Model, GcliError>
where where
C: ConnectionTrait, C: ConnectionTrait,
......
...@@ -2,7 +2,6 @@ use crate::commands::vault; ...@@ -2,7 +2,6 @@ use crate::commands::vault;
use crate::*; use crate::*;
use indexer::Indexer; use indexer::Indexer;
use sea_orm::DatabaseConnection; use sea_orm::DatabaseConnection;
use std::str::FromStr;
// consts // consts
pub const LOCAL_DUNITER_ENDPOINT: &str = "ws://localhost:9944"; pub const LOCAL_DUNITER_ENDPOINT: &str = "ws://localhost:9944";
...@@ -198,15 +197,20 @@ impl Data { ...@@ -198,15 +197,20 @@ impl Data {
self.cfg.address = Some(keypair.address()); self.cfg.address = Some(keypair.address());
self.keypair = Some(keypair); self.keypair = Some(keypair);
} }
// address or vault name // address
if let Some(address_or_vault_name) = self.args.address_or_vault_name.clone() { if let Some(address) = self.args.address.clone() {
let address = self.cfg.address = Some(address.clone());
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 // if giving address, cancel secret
self.keypair = None self.keypair = None
} }
// (vault)name
if let Some(name) = self.args.name.clone() {
let account = vault::retrieve_vault_account_for_name(self.connect_db(), &name).await?;
self.cfg.address = Some(account.address.0.clone());
// if giving (vault)name, cancel secret
self.keypair = None
}
Ok(self) Ok(self)
} }
/// build a client from url /// build a client from url
......
...@@ -41,7 +41,7 @@ pub struct Args { ...@@ -41,7 +41,7 @@ pub struct Args {
#[clap(subcommand)] #[clap(subcommand)]
pub subcommand: Subcommand, pub subcommand: Subcommand,
/// Overwrite indexer endpoint /// Overwrite indexer endpoint
#[clap(short, long)] #[clap(short, long, conflicts_with_all=["no_indexer","network"])]
indexer: Option<String>, indexer: Option<String>,
/// Do not use indexer /// Do not use indexer
#[clap(long)] #[clap(long)]
...@@ -53,11 +53,14 @@ pub struct Args { ...@@ -53,11 +53,14 @@ pub struct Args {
/// Secret key format (seed, substrate, cesium) /// Secret key format (seed, substrate, cesium)
#[clap(short = 'S', long)] #[clap(short = 'S', long)]
secret_format: Option<SecretFormat>, secret_format: Option<SecretFormat>,
/// Address /// SS58 Address
#[clap(flatten)] #[clap(short, conflicts_with = "name")]
address_or_vault_name: Option<AddressOrVaultNameGroupOptional>, address: Option<AccountId>,
/// Name of an SS58 Address in the vault
#[clap(short = 'v')]
name: Option<String>,
/// Overwrite duniter websocket RPC endpoint /// Overwrite duniter websocket RPC endpoint
#[clap(short, long)] #[clap(short, long, conflicts_with = "network")]
url: Option<String>, url: Option<String>,
/// Target network (local, gdev, gtest...) /// Target network (local, gdev, gtest...)
#[clap(short, long)] #[clap(short, long)]
...@@ -70,51 +73,6 @@ pub struct Args { ...@@ -70,51 +73,6 @@ pub struct Args {
output_format: OutputFormat, output_format: OutputFormat,
} }
trait AddressOrVaultName {
fn address(&self) -> Option<&AccountId>;
fn name(&self) -> Option<&String>;
}
#[derive(Debug, clap::Args, Clone)]
#[group(required = false, multiple = false)]
pub struct AddressOrVaultNameGroupOptional {
/// SS58 Address
#[clap(short)]
address: Option<AccountId>,
/// Name of an SS58 Address in the vault
#[clap(short = 'v')]
name: Option<String>,
}
impl AddressOrVaultName for AddressOrVaultNameGroupOptional {
fn address(&self) -> Option<&AccountId> {
self.address.as_ref()
}
fn name(&self) -> Option<&String> {
self.name.as_ref()
}
}
#[derive(Debug, clap::Args, Clone)]
#[group(required = true, multiple = false)]
pub struct AddressOrVaultNameGroup {
/// SS58 Address
#[clap(short)]
address: Option<AccountId>,
/// Name of an SS58 Address in the vault
#[clap(short = 'v')]
name: Option<String>,
}
impl AddressOrVaultName for AddressOrVaultNameGroup {
fn address(&self) -> Option<&AccountId> {
self.address.as_ref()
}
fn name(&self) -> Option<&String> {
self.name.as_ref()
}
}
// TODO derive the fromstr implementation // TODO derive the fromstr implementation
/// secret format /// secret format
#[derive(Clone, Copy, Debug, Eq, PartialEq, Default)] #[derive(Clone, Copy, Debug, Eq, PartialEq, Default)]
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment