ic_oss/
agent.rs

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        // ignore errors
26        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}