moonbeam_cli_opt/
account_key.rs1use bip32::{
18 Error as Bip32Error, ExtendedPrivateKey, PrivateKey as PrivateKeyT, PrivateKeyBytes,
19 PublicKey as PublicKeyT, PublicKeyBytes,
20};
21use bip39::{Language, Mnemonic, MnemonicType, Seed};
22use clap::{Parser, ValueEnum};
23use libsecp256k1::{PublicKey, SecretKey};
24use primitive_types::H256;
25use sp_runtime::traits::IdentifyAccount;
26
27#[derive(Debug, Clone, ValueEnum)]
28pub enum Network {
29 Moonbeam,
30 Moonriver,
31 Moonbase,
32 Ethereum,
33}
34
35impl Network {
36 pub fn coin_type(&self) -> u32 {
38 match self {
39 Network::Moonbeam => 1284,
40 Network::Moonriver => 1285,
41 Network::Moonbase => 1287,
42 Network::Ethereum => 60,
43 }
44 }
45}
46
47#[derive(Debug, Clone, Parser)]
48pub struct GenerateAccountKey {
49 #[clap(long, short = 'w')]
51 w12: bool,
52
53 #[clap(long, short = 'm')]
55 mnemonic: Option<String>,
56
57 #[clap(long = "account-index", short = 'a')]
59 account_index: Option<u32>,
60
61 #[clap(long, short = 'n', default_value = "moonbeam")]
63 pub network: Network,
64}
65
66impl GenerateAccountKey {
67 pub fn run(&self) {
68 let mnemonic = if let Some(phrase) = &self.mnemonic {
70 Mnemonic::from_phrase(phrase, Language::English).expect("invalid mnemonic")
71 } else {
72 match self.w12 {
73 true => Mnemonic::new(MnemonicType::Words12, Language::English),
74 false => Mnemonic::new(MnemonicType::Words24, Language::English),
75 }
76 };
77
78 let seed = Seed::new(&mnemonic, "");
80 let derivation_path = format!(
82 "m/44'/{}'/0'/0/{}",
83 self.network.coin_type(),
84 self.account_index.unwrap_or(0)
85 );
86 let private_key = if let Some(private_key) =
87 derivation_path.parse().ok().and_then(|derivation_path| {
88 let extended = ExtendedPrivateKey::<Secp256k1SecretKey>::derive_from_path(
89 &seed,
90 &derivation_path,
91 )
92 .expect("invalid extended private key");
93 Some(extended.private_key().0)
94 }) {
95 private_key
96 } else {
97 panic!("invalid extended private key");
98 };
99
100 let public_key = PublicKey::from_secret_key(&private_key);
102
103 let signer: account::EthereumSigner = public_key.into();
105 let address = signer.into_account();
106
107 println!("Address: {:?}", address);
108 println!("Mnemonic: {}", mnemonic.phrase());
109 println!("Private Key: {:?}", H256::from(private_key.serialize()));
110 println!("Path: {}", derivation_path);
111 }
112}
113
114pub struct Secp256k1PublicKey(pub PublicKey);
116pub struct Secp256k1SecretKey(pub SecretKey);
118
119impl PublicKeyT for Secp256k1PublicKey {
120 fn from_bytes(bytes: PublicKeyBytes) -> Result<Self, Bip32Error> {
121 let public = PublicKey::parse_compressed(&bytes).map_err(|_| return Bip32Error::Decode)?;
122 Ok(Self(public))
123 }
124
125 fn to_bytes(&self) -> PublicKeyBytes {
126 self.0.serialize_compressed()
127 }
128
129 fn derive_child(&self, other: PrivateKeyBytes) -> Result<Self, Bip32Error> {
130 let mut child = self.0.clone();
131 let secret = SecretKey::parse(&other).map_err(|_| return Bip32Error::Decode)?;
132 let _ = child.tweak_add_assign(&secret);
133 Ok(Self(child))
134 }
135}
136
137impl PrivateKeyT for Secp256k1SecretKey {
138 type PublicKey = Secp256k1PublicKey;
139
140 fn from_bytes(bytes: &PrivateKeyBytes) -> Result<Self, Bip32Error> {
141 let secret = SecretKey::parse(&bytes).map_err(|_| return Bip32Error::Decode)?;
142 Ok(Self(secret))
143 }
144
145 fn to_bytes(&self) -> PrivateKeyBytes {
146 self.0.serialize()
147 }
148
149 fn derive_child(&self, other: PrivateKeyBytes) -> Result<Self, Bip32Error> {
150 let mut child = self.0.clone();
151 let secret = SecretKey::parse(&other).map_err(|_| return Bip32Error::Decode)?;
152 let _ = child.tweak_add_assign(&secret);
153 Ok(Self(child))
154 }
155
156 fn public_key(&self) -> Self::PublicKey {
157 Secp256k1PublicKey(PublicKey::from_secret_key(&self.0))
158 }
159}