Skip to content

Commit 5893e85

Browse files
author
Hans Larsen
committed
feat: add canister query command
1 parent 0be1a56 commit 5893e85

File tree

2 files changed

+79
-1
lines changed

2 files changed

+79
-1
lines changed

dfx/src/commands/canister/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,16 @@ use clap::{App, ArgMatches, SubCommand};
55

66
mod call;
77
mod install;
8+
mod query;
89

910
fn builtins<T>() -> Vec<CliCommand<T>>
1011
where
1112
T: ClientEnv + ProjectConfigEnv,
1213
{
1314
vec![
14-
CliCommand::new(install::construct(), install::exec),
1515
CliCommand::new(call::construct(), call::exec),
16+
CliCommand::new(install::construct(), install::exec),
17+
CliCommand::new(query::construct(), query::exec),
1618
]
1719
}
1820

dfx/src/commands/canister/query.rs

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
use crate::lib::api_client::{query, Blob, CanisterQueryCall, QueryResponseReply, ReadResponse};
2+
use crate::lib::env::ClientEnv;
3+
use crate::lib::error::{DfxError, DfxResult};
4+
use clap::{App, Arg, ArgMatches, SubCommand};
5+
use tokio::runtime::Runtime;
6+
7+
fn is_number(v: String) -> Result<(), String> {
8+
v.parse::<u64>()
9+
.map_err(|_| String::from("The value must be a number."))
10+
.map(|_| ())
11+
}
12+
13+
pub fn construct() -> App<'static, 'static> {
14+
SubCommand::with_name("query")
15+
.about("Query a canister.")
16+
.arg(
17+
Arg::with_name("canister")
18+
.takes_value(true)
19+
.help("The canister ID (a number) to query.")
20+
.required(true)
21+
.validator(is_number),
22+
)
23+
.arg(
24+
Arg::with_name("method_name")
25+
.help("The query method name file to use.")
26+
.required(true),
27+
)
28+
.arg(
29+
Arg::with_name("arguments")
30+
.help("Arguments to pass to the method.")
31+
.takes_value(true)
32+
.multiple(true),
33+
)
34+
}
35+
36+
pub fn exec<T>(env: &T, args: &ArgMatches<'_>) -> DfxResult
37+
where
38+
T: ClientEnv,
39+
{
40+
// Read the config.
41+
let canister_id = args.value_of("canister").unwrap().parse::<u64>()?;
42+
let method_name = args.value_of("method_name").unwrap();
43+
let arguments: Option<Vec<&str>> = args.values_of("arguments").map(|args| args.collect());
44+
45+
let client = env.get_client();
46+
let install = query(
47+
client,
48+
CanisterQueryCall {
49+
canister_id,
50+
method_name: method_name.to_owned(),
51+
arg: arguments
52+
.map(|args| Blob(Vec::from(args[0])))
53+
.unwrap_or_else(|| Blob(vec![])),
54+
},
55+
);
56+
57+
let mut runtime = Runtime::new().expect("Unable to create a runtime");
58+
match runtime.block_on(install) {
59+
Ok(ReadResponse::Pending) => {
60+
println!("Pending");
61+
Ok(())
62+
}
63+
Ok(ReadResponse::Replied {
64+
reply: QueryResponseReply { arg: Blob(blob) },
65+
}) => {
66+
println!("{}", String::from_utf8_lossy(&blob));
67+
Ok(())
68+
}
69+
Ok(ReadResponse::Rejected {
70+
reject_code,
71+
reject_message,
72+
}) => Err(DfxError::ClientError(reject_code, reject_message)),
73+
Ok(ReadResponse::Unknown) => Err(DfxError::Unknown("Unknown response".to_owned())),
74+
Err(x) => Err(DfxError::from(x)),
75+
}
76+
}

0 commit comments

Comments
 (0)