use ethers::prelude::*;
use ethers::signers::{LocalWallet, Signer, Wallet};
use ethers::utils::hex;
use k256::ecdsa::SigningKey;
use sha2::{Digest, Sha256};
use std::str::FromStr;
use super::networks::NetworkConfig;
use crate::error::CryptoError;
use crate::keyspace::KeyPair;
#[derive(Debug, Clone)]
pub struct EthereumWallet {
pub address: Address,
pub wallet: Wallet<SigningKey>,
pub network: NetworkConfig,
}
impl EthereumWallet {
pub fn from_keypair(
keypair: &crate::keyspace::keypair_types::KeyPair,
network: NetworkConfig,
) -> Result<Self, CryptoError> {
let private_key_bytes = keypair.signing_key.to_bytes();
let private_key_hex = hex::encode(private_key_bytes);
let wallet = LocalWallet::from_str(&private_key_hex)
.map_err(|_e| CryptoError::InvalidKeyLength)?
.with_chain_id(network.chain_id);
let address = wallet.address();
Ok(EthereumWallet {
address,
wallet,
network,
})
}
pub fn from_name_and_keypair(
name: &str,
keypair: &KeyPair,
network: NetworkConfig,
) -> Result<Self, CryptoError> {
let private_key_bytes = keypair.signing_key.to_bytes();
let mut hasher = Sha256::default();
hasher.update(name.as_bytes());
hasher.update(&private_key_bytes);
let seed = hasher.finalize();
let private_key_hex = hex::encode(seed);
let wallet = LocalWallet::from_str(&private_key_hex)
.map_err(|_e| CryptoError::InvalidKeyLength)?
.with_chain_id(network.chain_id);
let address = wallet.address();
Ok(EthereumWallet {
address,
wallet,
network,
})
}
pub fn from_private_key(
private_key: &str,
network: NetworkConfig,
) -> Result<Self, CryptoError> {
let private_key_clean = private_key.trim_start_matches("0x");
let wallet = LocalWallet::from_str(private_key_clean)
.map_err(|_e| CryptoError::InvalidKeyLength)?
.with_chain_id(network.chain_id);
let address = wallet.address();
Ok(EthereumWallet {
address,
wallet,
network,
})
}
pub fn address_string(&self) -> String {
format!("{:?}", self.address)
}
pub async fn sign_message(&self, message: &[u8]) -> Result<String, CryptoError> {
let signature = self
.wallet
.sign_message(message)
.await
.map_err(|e| CryptoError::SignatureFormatError(e.to_string()))?;
Ok(signature.to_string())
}
pub fn private_key_hex(&self) -> String {
let bytes = self.wallet.signer().to_bytes();
hex::encode(bytes)
}
}