Skip to content

Commit

Permalink
Change how params are parsed in cast rpc
Browse files Browse the repository at this point in the history
Params are parsed as a JSON first and fallback to string.
In addition --direct-params was added to handle non-array params

Signed-off-by: Julian Popescu <[email protected]>
  • Loading branch information
jpopesculian committed Jun 21, 2022
1 parent 10c52cd commit 1d293f8
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 21 deletions.
32 changes: 17 additions & 15 deletions cli/src/cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -680,23 +680,25 @@ async fn main() -> eyre::Result<()> {
generate(shell, &mut Opts::command(), "cast", &mut std::io::stdout())
}
Subcommands::Run(cmd) => cmd.run()?,
Subcommands::Rpc { rpc_url, method, params } => {
Subcommands::Rpc { rpc_url, direct_params, method, params } => {
let rpc_url = consume_config_rpc_url(rpc_url);
let provider = Provider::try_from(rpc_url)?;
let params = params
.into_iter()
.map(|param| {
if let Some(param) = param.strip_prefix(':') {
if param.starts_with(':') {
Ok(serde_json::Value::String(param.to_string()))
} else {
serde_json::from_str::<serde_json::Value>(param)
}
} else {
Ok(serde_json::Value::String(param))
}
})
.collect::<Result<Vec<_>, _>>()?;
let params = if direct_params {
if params.len() != 1 {
eyre::bail!(r#"Expected exactly one argument for "params""#);
}
let param = params.into_iter().next().unwrap();
serde_json::from_str(&param).unwrap_or(serde_json::Value::String(param))
} else {
serde_json::Value::Array(
params
.into_iter()
.map(|param| {
serde_json::from_str(&param).unwrap_or(serde_json::Value::String(param))
})
.collect(),
)
};
println!("{}", Cast::new(provider).rpc(&method, params).await?);
}
};
Expand Down
19 changes: 15 additions & 4 deletions cli/src/opts/cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -828,18 +828,29 @@ If an address is specified, then the ABI is fetched from Etherscan."#,
Rpc {
#[clap(short, long, env = "ETH_RPC_URL", value_name = "URL")]
rpc_url: Option<String>,
#[clap(
short,
long,
help = "Do not put parameters in an array",
long_help = r#"Do not put parameters in an array
If --direct-params is passed the first PARAM will be taken as the value of "params". For example:
rpc --direct-params eth_getBlockByNumber '["0x123", false]'
=> {"method": "eth_getBlockByNumber", "params": ["0x123", false] ... }"#
)]
direct_params: bool,
#[clap(value_name = "METHOD", help = "RPC method name")]
method: String,
#[clap(
value_name = "PARAMS",
help = "RPC parameters",
long_help = r#"RPC parameters
Parameters are interpreted as strings. If you wish to pass a JSON value you can prepend the value with a ':'. To start a string with a ':' prepend with '::'. For example:
Parameters are interpreted as JSON and then fall back to string. For example:
request doThing 123 => {"method": "doThing", "params": ["123"] ... }
request doThing :123 => {"method": "doThing", "params": [123] ... }
request doThing ::123 => {"method": "doThing", "params": [":123"] ... }"#
rpc eth_getBlockByNumber 0x123 false
=> {"method": "eth_getBlockByNumber", "params": ["0x123", false] ... }"#
)]
params: Vec<String>,
},
Expand Down
21 changes: 19 additions & 2 deletions cli/tests/it/cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,25 @@ casttest!(cast_rpc_no_args, |_: TestProject, mut cmd: TestCommand| {
casttest!(cast_rpc_with_args, |_: TestProject, mut cmd: TestCommand| {
let eth_rpc_url = next_http_rpc_endpoint();

// Call `cast rpc eth_getBlockByNumber 0x123 :false`
cmd.args(["rpc", "--rpc-url", eth_rpc_url.as_str(), "eth_getBlockByNumber", "0x123", ":false"]);
// Call `cast rpc eth_getBlockByNumber 0x123 false`
cmd.args(["rpc", "--rpc-url", eth_rpc_url.as_str(), "eth_getBlockByNumber", "0x123", "false"]);
let output = cmd.stdout_lossy();
assert!(output.contains(r#""number":"0x123""#), "{}", output);
});

// test for cast_rpc with direct params
casttest!(cast_rpc_direct_params, |_: TestProject, mut cmd: TestCommand| {
let eth_rpc_url = next_http_rpc_endpoint();

// Call `cast rpc --direct-params eth_getBlockByNumber '["0x123", false]'`
cmd.args([
"rpc",
"--rpc-url",
eth_rpc_url.as_str(),
"--direct-params",
"eth_getBlockByNumber",
r#"["0x123", false]"#,
]);
let output = cmd.stdout_lossy();
assert!(output.contains(r#""number":"0x123""#), "{}", output);
});

0 comments on commit 1d293f8

Please sign in to comment.