Skip to main content

canic_testkit/pic/
calls.rs

1use candid::{CandidType, Principal, decode_one, encode_args, utils::ArgumentEncoder};
2use canic::Error;
3use serde::de::DeserializeOwned;
4
5use super::Pic;
6
7impl Pic {
8    /// Generic update call helper (serializes args + decodes result).
9    pub fn update_call<T, A>(
10        &self,
11        canister_id: Principal,
12        method: &str,
13        args: A,
14    ) -> Result<T, Error>
15    where
16        T: CandidType + DeserializeOwned,
17        A: ArgumentEncoder,
18    {
19        let bytes: Vec<u8> = encode_args(args)
20            .map_err(|err| Error::internal(format!("encode_args failed: {err}")))?;
21        let result = self
22            .inner
23            .update_call(canister_id, Principal::anonymous(), method, bytes)
24            .map_err(|err| {
25                Error::internal(format!(
26                    "pocket_ic update_call failed (canister={canister_id}, method={method}): {err}"
27                ))
28            })?;
29
30        decode_one(&result).map_err(|err| Error::internal(format!("decode_one failed: {err}")))
31    }
32
33    /// Generic update call helper with an explicit caller principal.
34    pub fn update_call_as<T, A>(
35        &self,
36        canister_id: Principal,
37        caller: Principal,
38        method: &str,
39        args: A,
40    ) -> Result<T, Error>
41    where
42        T: CandidType + DeserializeOwned,
43        A: ArgumentEncoder,
44    {
45        let bytes: Vec<u8> = encode_args(args)
46            .map_err(|err| Error::internal(format!("encode_args failed: {err}")))?;
47        let result = self
48            .inner
49            .update_call(canister_id, caller, method, bytes)
50            .map_err(|err| {
51                Error::internal(format!(
52                    "pocket_ic update_call failed (canister={canister_id}, method={method}): {err}"
53                ))
54            })?;
55
56        decode_one(&result).map_err(|err| Error::internal(format!("decode_one failed: {err}")))
57    }
58
59    /// Generic query call helper.
60    pub fn query_call<T, A>(
61        &self,
62        canister_id: Principal,
63        method: &str,
64        args: A,
65    ) -> Result<T, Error>
66    where
67        T: CandidType + DeserializeOwned,
68        A: ArgumentEncoder,
69    {
70        let bytes: Vec<u8> = encode_args(args)
71            .map_err(|err| Error::internal(format!("encode_args failed: {err}")))?;
72        let result = self
73            .inner
74            .query_call(canister_id, Principal::anonymous(), method, bytes)
75            .map_err(|err| {
76                Error::internal(format!(
77                    "pocket_ic query_call failed (canister={canister_id}, method={method}): {err}"
78                ))
79            })?;
80
81        decode_one(&result).map_err(|err| Error::internal(format!("decode_one failed: {err}")))
82    }
83
84    /// Generic query call helper with an explicit caller principal.
85    pub fn query_call_as<T, A>(
86        &self,
87        canister_id: Principal,
88        caller: Principal,
89        method: &str,
90        args: A,
91    ) -> Result<T, Error>
92    where
93        T: CandidType + DeserializeOwned,
94        A: ArgumentEncoder,
95    {
96        let bytes: Vec<u8> = encode_args(args)
97            .map_err(|err| Error::internal(format!("encode_args failed: {err}")))?;
98        let result = self
99            .inner
100            .query_call(canister_id, caller, method, bytes)
101            .map_err(|err| {
102                Error::internal(format!(
103                    "pocket_ic query_call failed (canister={canister_id}, method={method}): {err}"
104                ))
105            })?;
106
107        decode_one(&result).map_err(|err| Error::internal(format!("decode_one failed: {err}")))
108    }
109
110    /// Advance PocketIC by a fixed number of ticks.
111    pub fn tick_n(&self, times: usize) {
112        for _ in 0..times {
113            self.tick();
114        }
115    }
116}