icon_sdk/
wallet.rs

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                // Decode the provided private key string and create a SecretKey
18                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                // Generate a new keypair
24                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            // Ensure the string is long enough before slicing to avoid panics
44            format!("hx{}", &hex_digest[hex_digest.len() - 40..])
45        } else {
46            panic!("Digest too short");
47        }
48    }
49
50    // Accessor methods
51    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}