1use candid::{
2 utils::{encode_args, ArgumentEncoder},
3 CandidType, Decode, Principal,
4};
5use ic_agent::{Agent, Identity};
6use ic_oss_types::format_error;
7use std::sync::Arc;
8
9pub async fn build_agent(host: &str, identity: Arc<dyn Identity>) -> Result<Agent, String> {
10 let agent = Agent::builder()
11 .with_url(host)
12 .with_arc_identity(identity)
13 .with_verify_query_signatures(false);
14
15 let agent = if host.starts_with("https://") {
16 agent
17 .with_background_dynamic_routing()
18 .build()
19 .map_err(format_error)?
20 } else {
21 agent.build().map_err(format_error)?
22 };
23
24 if host.starts_with("http://") {
25 let _ = agent.fetch_root_key().await;
27 }
28
29 Ok(agent)
30}
31
32pub async fn update_call<In, Out>(
33 agent: &Agent,
34 canister_id: &Principal,
35 method_name: &str,
36 args: In,
37) -> Result<Out, String>
38where
39 In: ArgumentEncoder + Send,
40 Out: CandidType + for<'a> candid::Deserialize<'a>,
41{
42 let input = encode_args(args).map_err(format_error)?;
43 let res = agent
44 .update(canister_id, method_name)
45 .with_arg(input)
46 .call_and_wait()
47 .await
48 .map_err(format_error)?;
49 let output = Decode!(res.as_slice(), Out).map_err(format_error)?;
50 Ok(output)
51}
52
53pub async fn query_call<In, Out>(
54 agent: &Agent,
55 canister_id: &Principal,
56 method_name: &str,
57 args: In,
58) -> Result<Out, String>
59where
60 In: ArgumentEncoder + Send,
61 Out: CandidType + for<'a> candid::Deserialize<'a>,
62{
63 let input = encode_args(args).map_err(format_error)?;
64 let res = agent
65 .query(canister_id, method_name)
66 .with_arg(input)
67 .call()
68 .await
69 .map_err(format_error)?;
70 let output = Decode!(res.as_slice(), Out).map_err(format_error)?;
71 Ok(output)
72}