22
33pub mod vanity;
44
5+ use std:: path:: Path ;
6+
57use crate :: {
68 cmd:: { cast:: wallet:: vanity:: VanityArgs , Cmd } ,
7- opts:: Wallet ,
9+ opts:: { RawWallet , Wallet } ,
810} ;
911use cast:: SimpleCast ;
1012use clap:: Parser ;
@@ -14,6 +16,9 @@ use ethers::{
1416 types:: { transaction:: eip712:: TypedData , Address , Signature } ,
1517} ;
1618use eyre:: Context ;
19+ use foundry_common:: fs;
20+ use foundry_config:: Config ;
21+ use yansi:: Paint ;
1722
1823/// CLI arguments for `cast wallet`.
1924#[ derive( Debug , Parser ) ]
@@ -98,6 +103,19 @@ pub enum WalletSubcommands {
98103 #[ clap( long, short) ]
99104 address : Address ,
100105 } ,
106+ /// Import a private key into an encrypted keystore.
107+ #[ clap( visible_alias = "i" ) ]
108+ Import {
109+ #[ clap( help = "The name for the account in the keystore." , value_name = "ACCOUNT_NAME" ) ]
110+ account_name : String ,
111+ #[ clap( long, short) ]
112+ keystore_dir : Option < String > ,
113+ #[ clap( flatten) ]
114+ raw_wallet_options : RawWallet ,
115+ } ,
116+ /// List all the accounts in the keystore default directory
117+ #[ clap( visible_alias = "ls" ) ]
118+ List ,
101119}
102120
103121impl WalletSubcommands {
@@ -137,7 +155,10 @@ impl WalletSubcommands {
137155 }
138156 WalletSubcommands :: Address { wallet, private_key_override } => {
139157 let wallet = private_key_override
140- . map ( |pk| Wallet { private_key : Some ( pk) , ..Default :: default ( ) } )
158+ . map ( |pk| Wallet {
159+ raw : RawWallet { private_key : Some ( pk) , ..Default :: default ( ) } ,
160+ ..Default :: default ( )
161+ } )
141162 . unwrap_or ( wallet)
142163 . signer ( 0 )
143164 . await ?;
@@ -170,6 +191,90 @@ impl WalletSubcommands {
170191 }
171192 }
172193 }
194+ WalletSubcommands :: Import { account_name, keystore_dir, raw_wallet_options } => {
195+ // Set up keystore directory
196+ let dir = if let Some ( path) = keystore_dir {
197+ Path :: new ( & path) . to_path_buf ( )
198+ } else {
199+ Config :: foundry_keystores_dir ( ) . ok_or_else ( || {
200+ eyre:: eyre!( "Could not find the default keystore directory." )
201+ } ) ?
202+ } ;
203+
204+ fs:: create_dir_all ( & dir) ?;
205+
206+ // check if account exists already
207+ let keystore_path = Path :: new ( & dir) . join ( & account_name) ;
208+ if keystore_path. exists ( ) {
209+ eyre:: bail!( "Keystore file already exists at {}" , keystore_path. display( ) ) ;
210+ }
211+
212+ // get wallet
213+ let wallet: Wallet = raw_wallet_options. into ( ) ;
214+ let wallet = wallet. try_resolve_local_wallet ( ) ?. ok_or_else ( || {
215+ eyre:: eyre!(
216+ "\
217+ Did you set a private key or mnemonic?
218+ Run `cast wallet import --help` and use the corresponding CLI
219+ flag to set your key via:
220+ --private-key, --mnemonic-path or --interactive."
221+ )
222+ } ) ?;
223+
224+ let private_key = wallet. signer ( ) . to_bytes ( ) ;
225+ let password = rpassword:: prompt_password ( "Enter password: " ) ?;
226+
227+ let mut rng = thread_rng ( ) ;
228+ eth_keystore:: encrypt_key (
229+ & dir,
230+ & mut rng,
231+ private_key,
232+ & password,
233+ Some ( & account_name) ,
234+ ) ?;
235+ let address = wallet. address ( ) ;
236+ let success_message = format ! (
237+ "`{}` keystore was saved successfully. Address: {}" ,
238+ & account_name, address,
239+ ) ;
240+ println ! ( "{}" , Paint :: green( success_message) ) ;
241+ }
242+ WalletSubcommands :: List => {
243+ let default_keystore_dir = Config :: foundry_keystores_dir ( )
244+ . ok_or_else ( || eyre:: eyre!( "Could not find the default keystore directory." ) ) ?;
245+ // Create the keystore directory if it doesn't exist
246+ fs:: create_dir_all ( & default_keystore_dir) ?;
247+ // List all files in keystore directory
248+ let keystore_files: Result < Vec < _ > , eyre:: Report > =
249+ std:: fs:: read_dir ( & default_keystore_dir)
250+ . wrap_err ( "Failed to read the directory" ) ?
251+ . filter_map ( |entry| match entry {
252+ Ok ( entry) => {
253+ let path = entry. path ( ) ;
254+ if path. is_file ( ) && path. extension ( ) . is_none ( ) {
255+ Some ( Ok ( path) )
256+ } else {
257+ None
258+ }
259+ }
260+ Err ( e) => Some ( Err ( e. into ( ) ) ) ,
261+ } )
262+ . collect :: < Result < Vec < _ > , eyre:: Report > > ( ) ;
263+ // Print the names of the keystore files
264+ match keystore_files {
265+ Ok ( files) => {
266+ // Print the names of the keystore files
267+ for file in files {
268+ if let Some ( file_name) = file. file_name ( ) {
269+ if let Some ( name) = file_name. to_str ( ) {
270+ println ! ( "{}" , name) ;
271+ }
272+ }
273+ }
274+ }
275+ Err ( e) => return Err ( e) ,
276+ }
277+ }
173278 } ;
174279
175280 Ok ( ( ) )
0 commit comments