1use k256::{
2 ecdsa::SigningKey,
3 elliptic_curve::rand_core::OsRng,
4};
5use sha3::{Digest, Keccak256};
6
7pub struct Wallet {
8 pub address: String,
9 pub privkey: String,
10 pub pubkey_compressed: String,
11 pub pubkey_uncompressed: String,
12}
13
14impl Wallet {
15 pub fn new() -> Self {
17 let private_key = SigningKey::random(&mut OsRng);
18 let privkey_hex = hex::encode(private_key.to_bytes());
19
20 let public_key = private_key.verifying_key();
21 let pubkey_compressed = public_key.to_encoded_point(true).as_bytes().to_vec();
23 let pubkey_compressed_hex = hex::encode(&pubkey_compressed);
24 let pubkey_uncompressed = public_key.to_encoded_point(false).as_bytes().to_vec();
26 let pubkey_uncompressed_hex = hex::encode(&pubkey_uncompressed);
27
28 let hash = Keccak256::digest(&pubkey_uncompressed[1..]); let address = format!("0x{}", hex::encode(&hash[12..]));
31
32 Self {
33 address,
34 privkey: privkey_hex,
35 pubkey_compressed:pubkey_compressed_hex,
36 pubkey_uncompressed:pubkey_uncompressed_hex,
37 }
38 }
39 pub async fn sign_message(&self, message: &str) -> Result<String, String> {
41 use ethers::core::types::Signature;
42 use ethers::signers::{LocalWallet, Signer};
43 use ethers::core::k256::SecretKey;
44 use std::time::{SystemTime, UNIX_EPOCH};
45
46 let secret_bytes = hex::decode(&self.privkey).map_err(|e| e.to_string())?;
48 let secret_key = SecretKey::from_slice(&secret_bytes).map_err(|e| e.to_string())?;
49 let wallet = LocalWallet::from(secret_key);
50
51 let address = &self.address;
52 let timestamps = SystemTime::now()
53 .duration_since(UNIX_EPOCH)
54 .unwrap()
55 .as_secs();
56 let message_with_timestamp = format!("{}:{}", message, timestamps);
57
58 let wallet_addr = format!("0x{}", hex::encode(wallet.address().as_bytes()));
60 debug_assert_eq!(wallet_addr.to_lowercase(), address.to_lowercase());
61
62 let signature: Signature = wallet
64 .sign_message(message_with_timestamp.clone())
65 .await
66 .map_err(|e| e.to_string())?;
67
68 let result = serde_json::json!({
70 "address": address,
71 "signed_message": message_with_timestamp,
72 "signature": format!("0x{}", hex::encode(signature.to_vec())),
73 });
74 Ok(result.to_string())
75 }
76}
77
78