1use alloy_primitives::U256;
2use alloy_signer_local::{
3 MnemonicBuilder, PrivateKeySigner,
4 coins_bip39::{
5 ChineseSimplified, ChineseTraditional, Czech, English, French, Italian, Japanese, Korean,
6 Portuguese, Spanish, Wordlist,
7 },
8};
9
10pub fn derive_key_path(path: &str, index: u32) -> String {
12 let mut out = path.to_string();
13 if !out.ends_with('/') {
14 out.push('/');
15 }
16 out.push_str(&index.to_string());
17 out
18}
19
20pub fn derive_private_key<W: Wordlist>(
22 mnemonic: &str,
23 path: &str,
24 index: u32,
25) -> Result<U256, String> {
26 let wallet = MnemonicBuilder::<W>::default()
27 .phrase(mnemonic)
28 .derivation_path(derive_key_path(path, index))
29 .map_err(|e| e.to_string())?
30 .build()
31 .map_err(|e| e.to_string())?;
32 Ok(U256::from_be_bytes(wallet.credential().to_bytes().into()))
33}
34
35pub fn derive_private_key_with_language(
40 mnemonic: &str,
41 path: &str,
42 index: u32,
43 language: &str,
44) -> Result<U256, String> {
45 match language {
46 "chinese_simplified" => derive_private_key::<ChineseSimplified>(mnemonic, path, index),
47 "chinese_traditional" => derive_private_key::<ChineseTraditional>(mnemonic, path, index),
48 "czech" => derive_private_key::<Czech>(mnemonic, path, index),
49 "english" => derive_private_key::<English>(mnemonic, path, index),
50 "french" => derive_private_key::<French>(mnemonic, path, index),
51 "italian" => derive_private_key::<Italian>(mnemonic, path, index),
52 "japanese" => derive_private_key::<Japanese>(mnemonic, path, index),
53 "korean" => derive_private_key::<Korean>(mnemonic, path, index),
54 "portuguese" => derive_private_key::<Portuguese>(mnemonic, path, index),
55 "spanish" => derive_private_key::<Spanish>(mnemonic, path, index),
56 _ => Err(format!("unsupported mnemonic language: {language:?}")),
57 }
58}
59
60pub fn private_key_from_u256(private_key: U256) -> Result<PrivateKeySigner, String> {
64 if private_key.is_zero() {
65 return Err("private key cannot be zero".to_string());
66 }
67 PrivateKeySigner::from_slice(&private_key.to_be_bytes::<32>()).map_err(|e| e.to_string())
68}