1use alloy::primitives::Address;
2use clap::{ArgGroup, Parser, Subcommand};
3use rust_bls_bn254::{
4 CHINESE_SIMPLIFIED_WORD_LIST, CHINESE_TRADITIONAL_WORD_LIST, CZECH_WORD_LIST,
5 ENGLISH_WORD_LIST, ITALIAN_WORD_LIST, KOREAN_WORD_LIST, PORTUGUESE_WORD_LIST,
6 SPANISH_WORD_LIST,
7};
8#[derive(Parser, Debug)]
9#[command(
10 about = "Eigenlayer CLI tools",
11 long_about = "Tools used for AVS development purpose"
12)]
13pub struct Args {
14 #[command(subcommand)]
15 pub command: Commands,
16}
17
18#[derive(Subcommand, Debug)]
19pub enum Commands {
20 #[command(
21 about = "Given an initial contract address, which can be either a registry coordinator or service manager address,
22outputs addresses for all relevant Eigenlayer and AVS contracts within the network",
23 name = "egnaddrs",
24 group(
25 ArgGroup::new("manager_or_coordinator")
26 .required(true)
27 .args(&["service_manager", "registry_coordinator"]),
28 )
29 )]
30 EigenAddress {
31 #[arg(
32 long,
33 help = "ServiceManager contract address",
34 group = "manager_or_coordinator"
35 )]
36 service_manager: Option<Address>,
37
38 #[arg(
39 long,
40 help = "BLSRegistryCoordinatorWithIndices contract address",
41 group = "manager_or_coordinator"
42 )]
43 registry_coordinator: Option<Address>,
44
45 #[arg(long, help = "rpc url", default_value = "http://localhost:8545")]
46 rpc_url: String,
47 },
48
49 #[command(about = "EigenLayer CLI Key tools", name = "egnkey")]
50 EigenKey {
51 #[command(subcommand)]
52 subcommand: EigenKeyCommand,
53 },
54}
55
56#[derive(Subcommand, Debug)]
57pub enum EigenKeyCommand {
58 #[command(
59 about = "Generate keys for testing purpose.
60This command creates ecdsa or bls key pair for testing purposes. It generates
61all the relevant files for reading the key and decrypts it and also gets
62you the private keys in plaintext.
63
64It creates the following artifacts based on arguments
65- passwords.txt - contains all passwords to decrypt keys
66- private_key_hex.txt - will create plaintext private keys
67- keys/* - create all the encrypted json files in this folder",
68 alias = "g"
69 )]
70 Generate {
71 #[arg(long, help = "key type to create (ecdsa or bls)")]
72 #[clap(value_enum)]
73 key_type: KeyType,
74
75 #[arg(long, help = "number of keys to create", default_value = "1")]
76 num_keys: u32,
77
78 #[arg(long, help = "folder to store keys")]
79 output_dir: Option<String>,
80 },
81
82 #[command(
83 about = "Given a private key, output its associated operatorId (hash of bn254 G1 pubkey).",
84 alias = "d"
85 )]
86 DeriveOperatorId {
87 #[arg(
88 long,
89 help = "(bn254) private key from which to derive operatorId from"
90 )]
91 private_key: String,
92 },
93
94 #[command(
95 about = "Stores an ecdsa key to a file, in web3 secret storage format.",
96 alias = "c"
97 )]
98 ConvertECDSA {
99 #[arg(long, help = "private key to store (in hex)")]
100 private_key: String,
101
102 #[arg(long, help = "file to store key")]
103 output_file: Option<String>,
104
105 #[arg(long, help = "password to encrypt key")]
106 password: Option<String>,
107 },
108
109 #[command(
110 about = "Using Pbkfd2 / scrypt encryption to secure the bls key.",
111 alias = "b"
112 )]
113 BlsConvert {
114 #[arg(long, help = "Bls keystore type (pbkdf2 or scrypt)")]
115 #[clap(value_enum)]
116 key_type: BlsKeystoreType,
117
118 #[arg(long, help = "bls key to encrypt in hex")]
119 secret_key: String,
120
121 #[arg(long, help = "file path to store key")]
122 output_path: String,
123
124 #[arg(long, help = "password to encrypt key(default is empty string)")]
125 password: Option<String>,
126 },
127 #[command(about = "Create a new mnemonic from default word lists", alias = "md")]
128 CreateNewMnemonicFromDefaultWordList {
129 #[arg(long, help = "Mnemonic language select")]
130 #[clap(value_enum)]
131 language: MnemonicLanguage,
132 },
133 #[command(
134 about = "Create a new mnemonic from given word list at path",
135 alias = "mp"
136 )]
137 CreateNewMnemonicFromPath {
138 #[arg(long, help = "Mnemonic language select")]
139 #[clap(value_enum)]
140 language: MnemonicLanguage,
141 #[arg(long, help = "Path to a the directory where lists are stored)")]
142 path: String,
143 },
144}
145
146#[derive(clap::ValueEnum, Debug, Clone)]
147pub enum KeyType {
148 Ecdsa,
149 Bls,
150}
151
152#[derive(clap::ValueEnum, Debug, Clone)]
153pub enum BlsKeystoreType {
154 Pbkdf2,
155 Scrypt,
156}
157
158#[derive(clap::ValueEnum, Debug, Clone)]
159pub enum MnemonicLanguage {
160 English,
161 ChineseSimplified,
162 ChineseTraditional,
163 Italian,
164 Czech,
165 Korean,
166 Portuguese,
167 Spanish,
168}
169
170impl MnemonicLanguage {
171 pub fn try_from(&self) -> (&str, &str) {
172 match self {
173 MnemonicLanguage::English => ("english", ENGLISH_WORD_LIST),
174 MnemonicLanguage::ChineseSimplified => {
175 ("chinese_simplified", CHINESE_SIMPLIFIED_WORD_LIST)
176 }
177 MnemonicLanguage::ChineseTraditional => {
178 ("chinese_traditional", CHINESE_TRADITIONAL_WORD_LIST)
179 }
180 MnemonicLanguage::Italian => ("italian", ITALIAN_WORD_LIST),
181 MnemonicLanguage::Czech => ("czech", CZECH_WORD_LIST),
182 MnemonicLanguage::Korean => ("korean", KOREAN_WORD_LIST),
183 MnemonicLanguage::Portuguese => ("portuguese", PORTUGUESE_WORD_LIST),
184 MnemonicLanguage::Spanish => ("spanish", SPANISH_WORD_LIST),
185 }
186 }
187}