Skip to content
Snippets Groups Projects
Commit 80d3023d authored by poka's avatar poka
Browse files

add non interactive mode

parent a36c8318
No related branches found
No related tags found
2 merge requests!45Nostr,!44feat: Can choose between ed25519 ans sr25519
Pipeline #40105 passed
...@@ -4,6 +4,7 @@ use crate::commands::cesium::compute_g1v1_public_key; ...@@ -4,6 +4,7 @@ use crate::commands::cesium::compute_g1v1_public_key;
use crate::entities::vault_account; use crate::entities::vault_account;
use crate::entities::vault_account::{AccountTreeNode, ActiveModel, DbAccountId}; use crate::entities::vault_account::{AccountTreeNode, ActiveModel, DbAccountId};
use crate::*; use crate::*;
use crate::keys::seed_from_cesium;
use age::secrecy::Secret; use age::secrecy::Secret;
use sea_orm::ActiveValue::Set; use sea_orm::ActiveValue::Set;
use sea_orm::{ConnectionTrait, TransactionTrait}; use sea_orm::{ConnectionTrait, TransactionTrait};
...@@ -45,6 +46,30 @@ pub enum Subcommand { ...@@ -45,6 +46,30 @@ pub enum Subcommand {
/// Crypto scheme to use (sr25519, ed25519) /// Crypto scheme to use (sr25519, ed25519)
#[clap(short = 'c', long, required = false, default_value = CryptoScheme::Ed25519)] #[clap(short = 'c', long, required = false, default_value = CryptoScheme::Ed25519)]
crypto_scheme: CryptoScheme, crypto_scheme: CryptoScheme,
/// Substrate URI to import (non-interactive mode)
#[clap(short = 'u', long, required = false)]
uri: Option<String>,
/// G1v1 ID (non-interactive mode for g1v1 format)
#[clap(long, required = false)]
g1v1_id: Option<String>,
/// G1v1 password (non-interactive mode for g1v1 format)
#[clap(long, required = false)]
g1v1_password: Option<String>,
/// Password for encrypting the key (non-interactive mode)
#[clap(short = 'p', long, required = false)]
password: Option<String>,
/// Use empty password (non-interactive mode)
#[clap(long, required = false)]
no_password: bool,
/// Name for the wallet entry (non-interactive mode)
#[clap(short = 'n', long, required = false)]
name: Option<String>,
}, },
/// Add a derivation to an existing SS58 Address /// Add a derivation to an existing SS58 Address
#[clap(long_about = "Add a derivation to an existing SS58 Address.\n\ #[clap(long_about = "Add a derivation to an existing SS58 Address.\n\
...@@ -250,9 +275,49 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE ...@@ -250,9 +275,49 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE
let mnemonic = bip39::Mnemonic::generate(12).unwrap(); let mnemonic = bip39::Mnemonic::generate(12).unwrap();
println!("{mnemonic}"); println!("{mnemonic}");
} }
Subcommand::Import { secret_format, crypto_scheme } => { Subcommand::Import { secret_format, crypto_scheme, uri, g1v1_id, g1v1_password, password, no_password, name } => {
let vault_data_for_import = let vault_data_for_import = if let Some(uri_str) = uri {
prompt_secret_and_compute_vault_data_to_import(secret_format, crypto_scheme)?; // Non-interactive mode with provided URI
if secret_format != SecretFormat::Substrate {
return Err(GcliError::Input(format!(
"URI can only be provided directly with secret_format=substrate, got: {:?}",
secret_format
)));
}
// Create keypair from provided URI
let key_pair = compute_keypair(crypto_scheme, &uri_str)?;
VaultDataToImport {
secret_format,
secret_suri: uri_str,
key_pair,
}
} else if let (Some(id), Some(pwd)) = (&g1v1_id, &g1v1_password) {
// Non-interactive mode with provided G1v1 ID and password
if secret_format != SecretFormat::G1v1 {
return Err(GcliError::Input(format!(
"G1v1 ID and password can only be provided directly with secret_format=g1v1, got: {:?}",
secret_format
)));
}
// Create keypair from provided G1v1 ID and password
let seed = seed_from_cesium(id, pwd);
let secret_suri = format!("0x{}", hex::encode(seed));
// G1v1 always uses Ed25519
let key_pair = compute_keypair(CryptoScheme::Ed25519, &secret_suri)?;
VaultDataToImport {
secret_format,
secret_suri,
key_pair,
}
} else {
// Interactive mode
prompt_secret_and_compute_vault_data_to_import(secret_format, crypto_scheme)?
};
//Extra check for SecretFormat::G1v1 (old cesium) - showing the G1v1 cesium public key for confirmation //Extra check for SecretFormat::G1v1 (old cesium) - showing the G1v1 cesium public key for confirmation
if secret_format == SecretFormat::G1v1 { if secret_format == SecretFormat::G1v1 {
...@@ -260,17 +325,28 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE ...@@ -260,17 +325,28 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE
"The G1v1 public key for the provided secret is: '{}'", "The G1v1 public key for the provided secret is: '{}'",
compute_g1v1_public_key(&vault_data_for_import.key_pair)? compute_g1v1_public_key(&vault_data_for_import.key_pair)?
); );
// Skip confirmation in non-interactive mode
let is_non_interactive_g1v1 = g1v1_id.is_some() && g1v1_password.is_some();
if !is_non_interactive_g1v1 {
let confirmed = inputs::confirm_action("Is it the correct one (if not, you should try again to input G1v1 id/password) ?".to_string())?; let confirmed = inputs::confirm_action("Is it the correct one (if not, you should try again to input G1v1 id/password) ?".to_string())?;
if !confirmed { if !confirmed {
return Ok(()); return Ok(());
} }
} }
}
let txn = db.begin().await?; let txn = db.begin().await?;
println!(); // Handle password in non-interactive mode
let provided_password = if no_password {
Some(String::new()) // Empty password
} else {
password
};
let _account = let _account =
create_base_account_for_vault_data_to_import(&txn, &vault_data_for_import, None, Some(crypto_scheme)) create_base_account_for_vault_data_to_import(&txn, &vault_data_for_import, provided_password.as_ref(), Some(crypto_scheme), name)
.await?; .await?;
txn.commit().await?; txn.commit().await?;
...@@ -489,6 +565,7 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE ...@@ -489,6 +565,7 @@ pub async fn handle_command(data: Data, command: Subcommand) -> Result<(), GcliE
&vault_data_to_import, &vault_data_to_import,
Some(&vault_data_from_file.password), Some(&vault_data_from_file.password),
Some(CryptoScheme::Ed25519), Some(CryptoScheme::Ed25519),
None,
) )
.await; .await;
...@@ -757,6 +834,7 @@ pub async fn create_base_account_for_vault_data_to_import<C>( ...@@ -757,6 +834,7 @@ pub async fn create_base_account_for_vault_data_to_import<C>(
vault_data: &VaultDataToImport, vault_data: &VaultDataToImport,
password_opt: Option<&String>, password_opt: Option<&String>,
crypto_scheme: Option<CryptoScheme>, crypto_scheme: Option<CryptoScheme>,
name_opt: Option<String>,
) -> Result<vault_account::Model, GcliError> ) -> Result<vault_account::Model, GcliError>
where where
C: ConnectionTrait, C: ConnectionTrait,
...@@ -780,14 +858,16 @@ where ...@@ -780,14 +858,16 @@ where
existing_vault_account existing_vault_account
))? { ))? {
true => { true => {
println!( let name = if let Some(name) = name_opt {
"(Optional) Enter a name for the vault entry (leave empty to remove the name)" Some(name)
); } else {
let name = inputs::prompt_vault_name_and_check_availability( println!("(Optional) Enter a name for the vault entry (leave empty to remove the name)");
inputs::prompt_vault_name_and_check_availability(
db_tx, db_tx,
existing_vault_account.name.as_ref(), existing_vault_account.name.as_ref(),
) )
.await?; .await?
};
// Since links are made based on address / parent(address) we can just edit the existing entry and it should be fine // Since links are made based on address / parent(address) we can just edit the existing entry and it should be fine
let mut vault_account: ActiveModel = existing_vault_account.into(); let mut vault_account: ActiveModel = existing_vault_account.into();
...@@ -797,7 +877,7 @@ where ...@@ -797,7 +877,7 @@ where
map_secret_format_to_crypto_scheme(vault_data.secret_format, crypto_scheme).into(), map_secret_format_to_crypto_scheme(vault_data.secret_format, crypto_scheme).into(),
)); ));
vault_account.encrypted_suri = Set(Some(encrypted_suri)); vault_account.encrypted_suri = Set(Some(encrypted_suri));
vault_account.name = Set(name.clone()); vault_account.name = Set(name);
vault_account.secret_format = Set(Some(vault_data.secret_format.into())); vault_account.secret_format = Set(Some(vault_data.secret_format.into()));
let updated_vault_account = let updated_vault_account =
vault_account::update_account(db_tx, vault_account).await?; vault_account::update_account(db_tx, vault_account).await?;
...@@ -815,8 +895,12 @@ where ...@@ -815,8 +895,12 @@ where
let encrypted_suri = compute_encrypted_suri(password, vault_data.secret_suri.clone())?; let encrypted_suri = compute_encrypted_suri(password, vault_data.secret_suri.clone())?;
let name = if let Some(name) = name_opt {
Some(name)
} else {
println!("(Optional) Enter a name for the vault entry"); println!("(Optional) Enter a name for the vault entry");
let name = inputs::prompt_vault_name_and_check_availability(db_tx, None).await?; inputs::prompt_vault_name_and_check_availability(db_tx, None).await?
};
let crypto_scheme = map_secret_format_to_crypto_scheme(secret_format, crypto_scheme); let crypto_scheme = map_secret_format_to_crypto_scheme(secret_format, crypto_scheme);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment