cast/cmd/wallet/
list.rs
1use clap::Parser;
2use eyre::Result;
3use std::env;
4
5use foundry_common::{fs, sh_err, sh_println};
6use foundry_config::Config;
7use foundry_wallets::multi_wallet::MultiWalletOptsBuilder;
8
9#[derive(Clone, Debug, Parser)]
11pub struct ListArgs {
12 #[arg(long, default_missing_value = "", num_args(0..=1))]
15 dir: Option<String>,
16
17 #[arg(long, short, group = "hw-wallets")]
19 ledger: bool,
20
21 #[arg(long, short, group = "hw-wallets")]
23 trezor: bool,
24
25 #[arg(long, hide = !cfg!(feature = "aws-kms"))]
27 aws: bool,
28
29 #[arg(long, hide = !cfg!(feature = "gcp-kms"))]
31 gcp: bool,
32
33 #[arg(long, group = "hw-wallets")]
35 all: bool,
36
37 #[arg(long, short, default_value = "3", requires = "hw-wallets")]
39 max_senders: Option<usize>,
40}
41
42impl ListArgs {
43 pub async fn run(self) -> Result<()> {
44 if self.dir.is_some() ||
46 self.all ||
47 (!self.ledger && !self.trezor && !self.aws && !self.gcp)
48 {
49 let _ = self.list_local_senders();
50 }
51
52 let list_opts = MultiWalletOptsBuilder::default()
54 .ledger(self.ledger || self.all)
55 .mnemonic_indexes(Some(vec![0]))
56 .trezor(self.trezor || self.all)
57 .aws(self.aws || self.all)
58 .gcp(self.gcp || (self.all && gcp_env_vars_set()))
59 .interactives(0)
60 .build()
61 .expect("build multi wallet");
62
63 macro_rules! list_senders {
65 ($signers:expr, $label:literal) => {
66 match $signers.await {
67 Ok(signers) => {
68 for signer in signers.unwrap_or_default().iter() {
69 signer
70 .available_senders(self.max_senders.unwrap())
71 .await?
72 .iter()
73 .for_each(|sender| {
74 let _ = sh_println!("{} ({})", sender, $label);
75 })
76 }
77 }
78 Err(e) => {
79 if !self.all {
80 sh_err!("{}", e)?;
81 }
82 }
83 }
84 };
85 }
86
87 list_senders!(list_opts.ledgers(), "Ledger");
88 list_senders!(list_opts.trezors(), "Trezor");
89 list_senders!(list_opts.aws_signers(), "AWS");
90
91 Ok(())
92 }
93
94 fn list_local_senders(&self) -> Result<()> {
95 let keystore_path = self.dir.clone().unwrap_or_default();
96 let keystore_dir = if keystore_path.is_empty() {
97 let default_dir = Config::foundry_keystores_dir().unwrap();
99 fs::create_dir_all(&default_dir)?;
100 default_dir
101 } else {
102 dunce::canonicalize(keystore_path)?
103 };
104
105 for entry in std::fs::read_dir(keystore_dir)? {
107 let path = entry?.path();
108 if path.is_file() {
109 if let Some(file_name) = path.file_name() {
110 if let Some(name) = file_name.to_str() {
111 sh_println!("{name} (Local)")?;
112 }
113 }
114 }
115 }
116
117 Ok(())
118 }
119}
120
121fn gcp_env_vars_set() -> bool {
122 let required_vars =
123 ["GCP_PROJECT_ID", "GCP_LOCATION", "GCP_KEY_RING", "GCP_KEY_NAME", "GCP_KEY_VERSION"];
124
125 required_vars.iter().all(|&var| env::var(var).is_ok())
126}