use bip32::{Mnemonic, Language, ExtendedPrivateKey, DerivationPath};
use k256::{
SecretKey,
ecdsa::{SigningKey, Signature, signature::Signer},
elliptic_curve::sec1::ToEncodedPoint,
};
use tiny_keccak::{Keccak, Hasher};
use std::str::FromStr;
use eyre::Result;
use sha3::{Keccak256, Digest};
fn generate_mnemonic() -> Result<String> {
let mnemonic = Mnemonic::random(&mut rand::thread_rng(), Language::English);
Ok(mnemonic.phrase().to_string())
}
pub(crate) fn get_wallet(mnemonic_str: &str, on_fail_gen_mnemonic : bool) -> Result<(String, String, String)> {
let mnemonic = match Mnemonic::new(mnemonic_str.trim(), Language::English) {
Ok(m) => m,
Err(_) => {
if on_fail_gen_mnemonic{
let new_mnemonic = generate_mnemonic()?;
println!("=============================================");
println!(" \n\n Generated new mnemonic: {} \n\n", new_mnemonic);
println!("=============================================");
Mnemonic::new(new_mnemonic.trim(), Language::English)?
}else{
panic!("Unable to parse mnemonic , set to generate mnemonic by changing level")
}
}
};
let seed = mnemonic.to_seed("");
let path = DerivationPath::from_str("m/44'/60'/0'/0/0")?;
let key = ExtendedPrivateKey::<SecretKey>::derive_from_path(&seed, &path)?;
let private_key = key.private_key();
let public_key = private_key.public_key();
let public_key_bytes = public_key.to_encoded_point(false).as_bytes().to_vec();
let public_key_string = hex::encode(&public_key_bytes);
let public_key_hex = format!("0x{}", public_key_string);
let mut hasher = Keccak::v256();
hasher.update(&public_key_bytes[1..]); let mut hash = [0u8; 32];
hasher.finalize(&mut hash);
let address = format!("0x{}", hex::encode(&hash[12..]));
let private_key_hex = hex::encode(private_key.to_bytes());
Ok((address.to_lowercase(), public_key_hex, private_key_hex))
}
pub(crate) fn create_ethereum_signature(private_key_hex: &str, verification_hash: &str) -> Result<String> {
let private_key_bytes = hex::decode(private_key_hex)?;
let secret_key = SecretKey::from_slice(&private_key_bytes)?;
let signing_key = SigningKey::from(secret_key);
let message = format!(
"I sign the following page verification_hash: [0x{}]",
verification_hash
);
let prefix = format!("\x19Ethereum Signed Message:\n{}", message.len());
let prefixed_message = [prefix.as_bytes(), message.as_bytes()].concat();
let mut hasher = Keccak256::new();
hasher.update(&prefixed_message);
let message_hash = hasher.finalize();
let signature: Signature = signing_key.sign(&message_hash);
let mut sig_bytes = signature.to_bytes().to_vec();
sig_bytes.push(27);
Ok(format!("0x{}", hex::encode(sig_bytes)))
}