Skip to content

Commit 1cf5222

Browse files
zerosnacksrplusq
authored andcommitted
feat: add global --json flag (foundry-rs#9244)
* add global json --flag * finish port to shell::is_json * fix test * update message * very strange stalling bug, fixed by assignment? * remove jobs -j shorthand clashing with global json flag * fix test after -j change * fix doctests * temporarily disable junit conflict, revert -j as --json shorthand * tag --color, --quiet as conflicting with --json * update tests to be aware of global args to avoid `Argument or group quiet specified in conflicts_with* for junit does not exist` error * fix missed test * make sure tests throw on non-matching command * use --format-json in command to show alias works
1 parent a62fcaf commit 1cf5222

File tree

21 files changed

+192
-208
lines changed

21 files changed

+192
-208
lines changed

crates/cast/bin/args.rs

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -369,10 +369,6 @@ pub enum CastSubcommand {
369369
#[arg(long, env = "CAST_FULL_BLOCK")]
370370
full: bool,
371371

372-
/// Print the block as JSON.
373-
#[arg(long, short, help_heading = "Display options")]
374-
json: bool,
375-
376372
#[command(flatten)]
377373
rpc: RpcOpts,
378374
},
@@ -464,10 +460,6 @@ pub enum CastSubcommand {
464460
#[arg(long, conflicts_with = "field")]
465461
raw: bool,
466462

467-
/// Print as JSON.
468-
#[arg(long, short, help_heading = "Display options")]
469-
json: bool,
470-
471463
#[command(flatten)]
472464
rpc: RpcOpts,
473465
},
@@ -489,10 +481,6 @@ pub enum CastSubcommand {
489481
#[arg(id = "async", long = "async", env = "CAST_ASYNC", alias = "cast-async")]
490482
cast_async: bool,
491483

492-
/// Print as JSON.
493-
#[arg(long, short, help_heading = "Display options")]
494-
json: bool,
495-
496484
#[command(flatten)]
497485
rpc: RpcOpts,
498486
},
@@ -530,10 +518,6 @@ pub enum CastSubcommand {
530518

531519
/// The ABI-encoded calldata.
532520
calldata: String,
533-
534-
/// Print the decoded calldata as JSON.
535-
#[arg(long, short, help_heading = "Display options")]
536-
json: bool,
537521
},
538522

539523
/// Decode ABI-encoded string.
@@ -543,10 +527,6 @@ pub enum CastSubcommand {
543527
StringDecode {
544528
/// The ABI-encoded string.
545529
data: String,
546-
547-
/// Print the decoded string as JSON.
548-
#[arg(long, short, help_heading = "Display options")]
549-
json: bool,
550530
},
551531

552532
/// Decode ABI-encoded input or output data.
@@ -565,10 +545,6 @@ pub enum CastSubcommand {
565545
/// Whether to decode the input or output data.
566546
#[arg(long, short, help_heading = "Decode input data instead of output data")]
567547
input: bool,
568-
569-
/// Print the decoded calldata as JSON.
570-
#[arg(long, short, help_heading = "Display options")]
571-
json: bool,
572548
},
573549

574550
/// ABI encode the given function argument, excluding the selector.
@@ -655,10 +631,6 @@ pub enum CastSubcommand {
655631
FourByteDecode {
656632
/// The ABI-encoded calldata.
657633
calldata: Option<String>,
658-
659-
/// Print the decoded calldata as JSON.
660-
#[arg(long, short, help_heading = "Display options")]
661-
json: bool,
662634
},
663635

664636
/// Get the event signature for a given topic 0 from https://openchain.xyz.

crates/cast/bin/cmd/access_list.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,6 @@ pub struct AccessListArgs {
3535
#[arg(long, short = 'B')]
3636
block: Option<BlockId>,
3737

38-
/// Print the access list as JSON.
39-
#[arg(long, short, help_heading = "Display options")]
40-
json: bool,
41-
4238
#[command(flatten)]
4339
tx: TransactionOpts,
4440

@@ -48,7 +44,7 @@ pub struct AccessListArgs {
4844

4945
impl AccessListArgs {
5046
pub async fn run(self) -> Result<()> {
51-
let Self { to, sig, args, tx, eth, block, json: to_json } = self;
47+
let Self { to, sig, args, tx, eth, block } = self;
5248

5349
let config = Config::from(&eth);
5450
let provider = utils::get_provider(&config)?;
@@ -65,7 +61,7 @@ impl AccessListArgs {
6561

6662
let cast = Cast::new(&provider);
6763

68-
let access_list: String = cast.access_list(&tx, block, to_json).await?;
64+
let access_list: String = cast.access_list(&tx, block).await?;
6965

7066
sh_println!("{access_list}")?;
7167

crates/cast/bin/cmd/call.rs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,6 @@ pub struct CallArgs {
6969
#[arg(long, short)]
7070
block: Option<BlockId>,
7171

72-
/// Print the decoded output as JSON.
73-
#[arg(long, short, help_heading = "Display options")]
74-
json: bool,
75-
7672
/// Enable Alphanet features.
7773
#[arg(long, alias = "odyssey")]
7874
pub alphanet: bool,
@@ -131,7 +127,6 @@ impl CallArgs {
131127
decode_internal,
132128
labels,
133129
data,
134-
json,
135130
..
136131
} = self;
137132

@@ -205,7 +200,7 @@ impl CallArgs {
205200
return Ok(());
206201
}
207202

208-
sh_println!("{}", Cast::new(provider).call(&tx, func.as_ref(), block, json).await?)?;
203+
sh_println!("{}", Cast::new(provider).call(&tx, func.as_ref(), block).await?)?;
209204

210205
Ok(())
211206
}

crates/cast/bin/cmd/interface.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use clap::Parser;
44
use eyre::{Context, Result};
55
use foundry_block_explorers::Client;
66
use foundry_cli::opts::EtherscanOpts;
7-
use foundry_common::{compile::ProjectCompiler, fs};
7+
use foundry_common::{compile::ProjectCompiler, fs, shell};
88
use foundry_compilers::{info::ContractInfo, utils::canonicalize};
99
use foundry_config::{load_config_with_root, try_find_project_root, Config};
1010
use itertools::Itertools;
@@ -44,17 +44,13 @@ pub struct InterfaceArgs {
4444
)]
4545
output: Option<PathBuf>,
4646

47-
/// If specified, the interface will be output as JSON rather than Solidity.
48-
#[arg(long, short)]
49-
json: bool,
50-
5147
#[command(flatten)]
5248
etherscan: EtherscanOpts,
5349
}
5450

5551
impl InterfaceArgs {
5652
pub async fn run(self) -> Result<()> {
57-
let Self { contract, name, pragma, output: output_location, etherscan, json } = self;
53+
let Self { contract, name, pragma, output: output_location, etherscan } = self;
5854

5955
// Determine if the target contract is an ABI file, a local contract or an Ethereum address.
6056
let abis = if Path::new(&contract).is_file() &&
@@ -75,7 +71,7 @@ impl InterfaceArgs {
7571
let interfaces = get_interfaces(abis)?;
7672

7773
// Print result or write to file.
78-
let res = if json {
74+
let res = if shell::is_json() {
7975
// Format as JSON.
8076
interfaces.iter().map(|iface| &iface.json_abi).format("\n").to_string()
8177
} else {

crates/cast/bin/cmd/logs.rs

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -49,26 +49,14 @@ pub struct LogsArgs {
4949
#[arg(long)]
5050
subscribe: bool,
5151

52-
/// Print the logs as JSON.s
53-
#[arg(long, short, help_heading = "Display options")]
54-
json: bool,
55-
5652
#[command(flatten)]
5753
eth: EthereumOpts,
5854
}
5955

6056
impl LogsArgs {
6157
pub async fn run(self) -> Result<()> {
62-
let Self {
63-
from_block,
64-
to_block,
65-
address,
66-
sig_or_topic,
67-
topics_or_args,
68-
subscribe,
69-
json,
70-
eth,
71-
} = self;
58+
let Self { from_block, to_block, address, sig_or_topic, topics_or_args, subscribe, eth } =
59+
self;
7260

7361
let config = Config::from(&eth);
7462
let provider = utils::get_provider(&config)?;
@@ -88,7 +76,7 @@ impl LogsArgs {
8876
let filter = build_filter(from_block, to_block, address, sig_or_topic, topics_or_args)?;
8977

9078
if !subscribe {
91-
let logs = cast.filter_logs(filter, json).await?;
79+
let logs = cast.filter_logs(filter).await?;
9280
sh_println!("{logs}")?;
9381
return Ok(())
9482
}
@@ -102,7 +90,7 @@ impl LogsArgs {
10290
.await?;
10391
let cast = Cast::new(&provider);
10492
let mut stdout = io::stdout();
105-
cast.subscribe(filter, &mut stdout, json).await?;
93+
cast.subscribe(filter, &mut stdout).await?;
10694

10795
Ok(())
10896
}

crates/cast/bin/cmd/send.rs

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,6 @@ pub struct SendTxArgs {
4141
#[arg(long, default_value = "1")]
4242
confirmations: u64,
4343

44-
/// Print the transaction receipt as JSON.
45-
#[arg(long, short, help_heading = "Display options")]
46-
json: bool,
47-
4844
#[command(subcommand)]
4945
command: Option<SendTxSubcommands>,
5046

@@ -100,7 +96,6 @@ impl SendTxArgs {
10096
mut args,
10197
tx,
10298
confirmations,
103-
json: to_json,
10499
command,
105100
unlocked,
106101
path,
@@ -161,7 +156,7 @@ impl SendTxArgs {
161156

162157
let (tx, _) = builder.build(config.sender).await?;
163158

164-
cast_send(provider, tx, cast_async, confirmations, timeout, to_json).await
159+
cast_send(provider, tx, cast_async, confirmations, timeout).await
165160
// Case 2:
166161
// An option to use a local signer was provided.
167162
// If we cannot successfully instantiate a local signer, then we will assume we don't have
@@ -227,7 +222,7 @@ impl SendTxArgs {
227222
.wallet(wallet)
228223
.on_provider(&provider);
229224

230-
cast_send(provider, tx, cast_async, confirmations, timeout, to_json).await
225+
cast_send(provider, tx, cast_async, confirmations, timeout).await
231226
}
232227
}
233228
}
@@ -238,7 +233,6 @@ async fn cast_send<P: Provider<T, AnyNetwork>, T: Transport + Clone>(
238233
cast_async: bool,
239234
confs: u64,
240235
timeout: u64,
241-
to_json: bool,
242236
) -> Result<()> {
243237
let cast = Cast::new(provider);
244238
let pending_tx = cast.send(tx).await?;
@@ -248,9 +242,8 @@ async fn cast_send<P: Provider<T, AnyNetwork>, T: Transport + Clone>(
248242
if cast_async {
249243
sh_println!("{tx_hash:#x}")?;
250244
} else {
251-
let receipt = cast
252-
.receipt(format!("{tx_hash:#x}"), None, confs, Some(timeout), false, to_json)
253-
.await?;
245+
let receipt =
246+
cast.receipt(format!("{tx_hash:#x}"), None, confs, Some(timeout), false).await?;
254247
sh_println!("{receipt}")?;
255248
}
256249

crates/cast/bin/cmd/wallet/mod.rs

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use cast::revm::primitives::Authorization;
1111
use clap::Parser;
1212
use eyre::{Context, Result};
1313
use foundry_cli::{opts::RpcOpts, utils};
14-
use foundry_common::{fs, sh_println};
14+
use foundry_common::{fs, sh_println, shell};
1515
use foundry_config::Config;
1616
use foundry_wallets::{RawWalletOpts, WalletOpts, WalletSigner};
1717
use rand::thread_rng;
@@ -49,10 +49,6 @@ pub enum WalletSubcommands {
4949
/// Number of wallets to generate.
5050
#[arg(long, short, default_value = "1")]
5151
number: u32,
52-
53-
/// Output generated wallets as JSON.
54-
#[arg(long, short, default_value = "false")]
55-
json: bool,
5652
},
5753

5854
/// Generates a random BIP39 mnemonic phrase
@@ -69,10 +65,6 @@ pub enum WalletSubcommands {
6965
/// Entropy to use for the mnemonic
7066
#[arg(long, short, conflicts_with = "words")]
7167
entropy: Option<String>,
72-
73-
/// Output generated mnemonic phrase and accounts as JSON.
74-
#[arg(long, short, default_value = "false")]
75-
json: bool,
7668
},
7769

7870
/// Generate a vanity address.
@@ -219,10 +211,10 @@ pub enum WalletSubcommands {
219211
impl WalletSubcommands {
220212
pub async fn run(self) -> Result<()> {
221213
match self {
222-
Self::New { path, unsafe_password, number, json, .. } => {
214+
Self::New { path, unsafe_password, number, .. } => {
223215
let mut rng = thread_rng();
224216

225-
let mut json_values = if json { Some(vec![]) } else { None };
217+
let mut json_values = if shell::is_json() { Some(vec![]) } else { None };
226218
if let Some(path) = path {
227219
let path = match dunce::canonicalize(path.clone()) {
228220
Ok(path) => path,
@@ -294,7 +286,7 @@ impl WalletSubcommands {
294286
}
295287
}
296288
}
297-
Self::NewMnemonic { words, accounts, entropy, json } => {
289+
Self::NewMnemonic { words, accounts, entropy } => {
298290
let phrase = if let Some(entropy) = entropy {
299291
let entropy = Entropy::from_slice(hex::decode(entropy)?)?;
300292
Mnemonic::<English>::new_from_entropy(entropy).to_phrase()
@@ -303,7 +295,9 @@ impl WalletSubcommands {
303295
Mnemonic::<English>::new_with_count(&mut rng, words)?.to_phrase()
304296
};
305297

306-
if !json {
298+
let format_json = shell::is_json();
299+
300+
if !format_json {
307301
sh_println!("{}", "Generating mnemonic from provided entropy...".yellow())?;
308302
}
309303

@@ -315,7 +309,7 @@ impl WalletSubcommands {
315309
let wallets =
316310
wallets.into_iter().map(|b| b.build()).collect::<Result<Vec<_>, _>>()?;
317311

318-
if !json {
312+
if !format_json {
319313
sh_println!("{}", "Successfully generated a new mnemonic.".green())?;
320314
sh_println!("Phrase:\n{phrase}")?;
321315
sh_println!("\nAccounts:")?;
@@ -324,7 +318,7 @@ impl WalletSubcommands {
324318
let mut accounts = json!([]);
325319
for (i, wallet) in wallets.iter().enumerate() {
326320
let private_key = hex::encode(wallet.credential().to_bytes());
327-
if json {
321+
if format_json {
328322
accounts.as_array_mut().unwrap().push(json!({
329323
"address": format!("{}", wallet.address()),
330324
"private_key": format!("0x{}", private_key),
@@ -336,7 +330,7 @@ impl WalletSubcommands {
336330
}
337331
}
338332

339-
if json {
333+
if format_json {
340334
let obj = json!({
341335
"mnemonic": phrase,
342336
"accounts": accounts,

0 commit comments

Comments
 (0)