1use secp256k1::rand::rngs::OsRng;
2use secp256k1::{Secp256k1, SecretKey, PublicKey};
3use sha3::{Digest, Sha3_256};
4use hex::{encode, decode};
5
6pub struct Wallet {
7 private_key: String,
8 public_key: String,
9 public_address: String,
10}
11
12impl Wallet {
13 pub fn new(private_key: Option<String>) -> Self {
14 let secp = Secp256k1::new();
15 let (private_key, public_key) = match private_key {
16 Some(key_str) => {
17 let private_key = SecretKey::from_slice(&decode(key_str).expect("Invalid private key format")).expect("Invalid private key");
19 let public_key = PublicKey::from_secret_key(&secp, &private_key);
20 (private_key, public_key)
21 },
22 None => {
23 let (private_key, public_key) = secp.generate_keypair(&mut OsRng::default());
25 (private_key, public_key)
26 },
27 };
28 let public_key_hex = encode(public_key.serialize_uncompressed()[1..].to_vec());
29
30 let public_address = Wallet::pub_key_to_address(&public_key_hex);
31
32 Wallet {
33 private_key: private_key.display_secret().to_string(),
34 public_key: public_key_hex,
35 public_address,
36 }
37 }
38
39 fn pub_key_to_address(public_key: &str) -> String {
40 let digest = Sha3_256::digest(&decode(public_key).expect("Invalid hex in public key"));
41 let hex_digest = encode(&digest);
42 if hex_digest.len() >= 40 {
43 format!("hx{}", &hex_digest[hex_digest.len() - 40..])
45 } else {
46 panic!("Digest too short");
47 }
48 }
49
50 pub fn get_private_key(&self) -> String {
52 self.private_key.clone()
53 }
54
55 pub fn get_public_key(&self) -> String {
56 self.public_key.clone()
57 }
58
59 pub fn get_public_address(&self) -> String {
60 self.public_address.clone()
61 }
62}