cpchain_rust_sdk/
accounts.rs1use bip39::Mnemonic;
2use secp256k1::{rand, PublicKey, Secp256k1, SecretKey};
3use web3::{signing, types::Address as Web3Address};
4
5use crate::{address::Address, hd::HDNode, utils, keystore::Keystore};
6
7#[derive(Debug, Clone)]
17pub struct Account {
18 pub secret_key: SecretKey,
19 #[allow(dead_code)]
20 public_key: PublicKey,
21 pub address: Address,
22 pub mnemonic: Option<Mnemonic>,
23}
24
25fn generate_address(public_key: &PublicKey) -> Address {
26 let public_key = public_key.serialize_uncompressed();
27 debug_assert_eq!(public_key[0], 0x04);
28 let hash = signing::keccak256(&public_key[1..]);
29 let h160 = Web3Address::from_slice(&hash[12..]);
30 Address::new(h160)
31}
32
33impl Account {
34 pub fn new(derive_path: Option<String>) -> Result<Self, Box<dyn std::error::Error>> {
35 let hd_node = HDNode::new()?;
36 Account::_new(derive_path, &hd_node)
37 }
38
39 fn _new(derive_path: Option<String>, hd_node: &HDNode) -> Result<Account, Box<dyn std::error::Error>> {
40 let hd_node = hd_node.derive_path(
41 derive_path
42 .unwrap_or("m/44'/337'/0'/0/0".to_string())
43 .as_str(),
44 )?;
45 let secret_key = SecretKey::from_slice(&hd_node.private_key.unwrap())?;
46 let secp = Secp256k1::new();
47 let public_key = PublicKey::from_secret_key(&secp, &secret_key);
48 let address = generate_address(&public_key);
49 Ok(Self {
50 secret_key,
51 public_key,
52 address,
53 mnemonic: hd_node.mnemonic,
54 })
55 }
56
57 pub fn from_phrase(phrase: &str, derive_path: Option<String>) -> Result<Account, Box<dyn std::error::Error>> {
58 let hd_node = HDNode::from_phrase(phrase)?;
59 Account::_new(derive_path, &hd_node)
60 }
61
62 pub fn from_keystore(json: &str, password: &str) -> Result<Account, Box<dyn std::error::Error + Send + Sync>> {
63 let ks = Keystore::from(json.to_string());
64 ks.decrypt(password)
65 }
66
67 fn from_secert_key(secret_key: SecretKey) -> Self {
68 let secp = Secp256k1::new();
69 let public_key = PublicKey::from_secret_key(&secp, &secret_key);
70 let address = generate_address(&public_key);
71 Self {
72 secret_key,
73 public_key,
74 address,
75 mnemonic: None,
76 }
77 }
78
79 pub fn from_private_key(private_key: &str) -> Result<Self, Box<dyn std::error::Error + Send + Sync>> {
80 let bytes = utils::hex_to_bytes(private_key)?;
81 let secret_key = SecretKey::from_slice(&bytes)?;
82 Ok(Account::from_secert_key(secret_key))
83 }
84
85 pub fn random() -> Account {
86 let secret_key = SecretKey::new(&mut rand::thread_rng());
87 Account::from_secert_key(secret_key)
88 }
89
90 pub fn private_key_bytes(&self) -> [u8; 32] {
91 self.secret_key.serialize_secret()
92 }
93
94 pub fn private_key(&self) -> String {
95 let bytes = self.secret_key.serialize_secret().to_vec();
96 format!("0x{}", hex::encode(&bytes))
97 }
98
99 pub fn sign_tx(&self) {
101
102 }
103
104}
105
106#[cfg(test)]
107mod tests {
108 use bip39::{Language, Mnemonic, MnemonicType};
109
110 use crate::address::Address;
111
112 use super::Account;
113
114 #[test]
115 fn test_create_account() {
116 let account = Account::random();
117 assert!(account.private_key().len() == 66);
118 let account = Account::new(None).unwrap();
119 println!("{} {}", account.mnemonic.unwrap().phrase(), account.address)
120 }
121
122 #[test]
123 fn test_from_phrase() {
124 let account = Account::from_phrase("length much pull abstract almost spin hair chest ankle harbor dizzy life", None).unwrap();
125 assert_eq!(account.address.to_checksum(), "0x7D491C482eBa270700b584888f864177205c5159");
126 }
127
128 #[test]
129 fn test_from_private_key() {
130 let account = Account::from_private_key(
131 "0x6c0296556144bf09864f0583886867e5cb2eea02206ca7187d998529ff8ef069",
132 )
133 .unwrap();
134 assert!(
135 account.address
136 == Address::from_str("0x7de6c6E04Ea0CDc76fD51c6F441C25a7DCA236A0").unwrap()
137 )
138 }
139
140 #[test]
141 fn test_bip39() {
142 let mnemonic = Mnemonic::new(MnemonicType::Words12, Language::English);
143 println!("{}", mnemonic.phrase());
144 println!("{:?}", mnemonic.entropy().len())
145 }
146
147 #[test]
148 fn test_mnemonic_of_account() {
149 let addr = "0xd7998FD7F5454722a16Cd67E881CedF9896CE396";
150 let private_key = "0xf07ab943a5cd880d273ec38878bfa914bbfa1fe46dc6deb78590f8ef137a0690";
151 let account = Account::from_private_key(private_key).unwrap();
153 assert!(account.address == Address::from_str(addr).unwrap());
154 assert_eq!(account.mnemonic.is_none(), true);
155 }
156}