kobe_sol/
standard_wallet.rs1use alloc::string::String;
4use ed25519_dalek::{SigningKey, VerifyingKey};
5use zeroize::Zeroizing;
6
7use crate::Error;
8
9#[derive(Debug)]
11pub struct StandardWallet {
12 signing_key: SigningKey,
13}
14
15impl StandardWallet {
16 #[cfg(feature = "rand")]
22 pub fn generate() -> Result<Self, Error> {
23 use rand_core::OsRng;
24 let signing_key = SigningKey::generate(&mut OsRng);
25 Ok(Self { signing_key })
26 }
27
28 #[must_use]
30 pub fn from_private_key(private_key: &[u8; 32]) -> Self {
31 let signing_key = SigningKey::from_bytes(private_key);
32 Self { signing_key }
33 }
34
35 pub fn from_private_key_hex(hex_key: &str) -> Result<Self, Error> {
41 let bytes = hex::decode(hex_key)
42 .map_err(|e| Error::Derivation(alloc::format!("invalid hex: {e}")))?;
43
44 if bytes.len() != 32 {
45 return Err(Error::Derivation(alloc::format!(
46 "expected 32 bytes, got {}",
47 bytes.len()
48 )));
49 }
50
51 let mut key_bytes = [0u8; 32];
52 key_bytes.copy_from_slice(&bytes);
53 Ok(Self::from_private_key(&key_bytes))
54 }
55
56 #[inline]
58 #[must_use]
59 pub fn address_string(&self) -> String {
60 let verifying_key: VerifyingKey = self.signing_key.verifying_key();
61 bs58::encode(verifying_key.as_bytes()).into_string()
62 }
63
64 #[inline]
66 #[must_use]
67 pub fn private_key_hex(&self) -> Zeroizing<String> {
68 Zeroizing::new(hex::encode(self.signing_key.as_bytes()))
69 }
70
71 #[inline]
73 #[must_use]
74 pub fn public_key_hex(&self) -> String {
75 let verifying_key: VerifyingKey = self.signing_key.verifying_key();
76 hex::encode(verifying_key.as_bytes())
77 }
78}
79
80#[cfg(test)]
81mod tests {
82 use super::*;
83
84 #[cfg(feature = "rand")]
85 #[test]
86 fn test_generate() {
87 let wallet = StandardWallet::generate().unwrap();
88 let address = wallet.address_string();
89
90 assert!(address.len() >= 32 && address.len() <= 44);
92 }
93
94 #[test]
95 fn test_from_private_key() {
96 let key = [1u8; 32];
97 let wallet = StandardWallet::from_private_key(&key);
98 let address = wallet.address_string();
99
100 assert!(address.len() >= 32 && address.len() <= 44);
101 }
102
103 #[test]
104 fn test_from_private_key_hex() {
105 let hex_key = "0101010101010101010101010101010101010101010101010101010101010101";
106 let wallet = StandardWallet::from_private_key_hex(hex_key).unwrap();
107 let address = wallet.address_string();
108
109 assert!(address.len() >= 32 && address.len() <= 44);
110 }
111
112 #[test]
113 fn test_deterministic() {
114 let key = [42u8; 32];
115 let wallet1 = StandardWallet::from_private_key(&key);
116 let wallet2 = StandardWallet::from_private_key(&key);
117
118 assert_eq!(wallet1.address_string(), wallet2.address_string());
119 }
120}