1use candid::{CandidType, Principal, decode_one, encode_args, utils::ArgumentEncoder};
2use serde::de::DeserializeOwned;
3
4use super::{Pic, PicCallError};
5
6impl Pic {
7 pub fn update_call<T, A>(
9 &self,
10 canister_id: Principal,
11 method: &str,
12 args: A,
13 ) -> Result<T, PicCallError>
14 where
15 T: CandidType + DeserializeOwned,
16 A: ArgumentEncoder,
17 {
18 self.update_call_as(canister_id, Principal::anonymous(), method, args)
19 }
20
21 pub fn update_call_as<T, A>(
23 &self,
24 canister_id: Principal,
25 caller: Principal,
26 method: &str,
27 args: A,
28 ) -> Result<T, PicCallError>
29 where
30 T: CandidType + DeserializeOwned,
31 A: ArgumentEncoder,
32 {
33 let bytes = encode_call_args(args)?;
34 let result = self
35 .inner
36 .update_call(canister_id, caller, method, bytes)
37 .map_err(|err| {
38 PicCallError::new(format!(
39 "pocket_ic update_call failed (canister={canister_id}, method={method}): {err}"
40 ))
41 })?;
42
43 decode_call_result(&result)
44 }
45
46 pub fn query_call<T, A>(
48 &self,
49 canister_id: Principal,
50 method: &str,
51 args: A,
52 ) -> Result<T, PicCallError>
53 where
54 T: CandidType + DeserializeOwned,
55 A: ArgumentEncoder,
56 {
57 self.query_call_as(canister_id, Principal::anonymous(), method, args)
58 }
59
60 pub fn query_call_as<T, A>(
62 &self,
63 canister_id: Principal,
64 caller: Principal,
65 method: &str,
66 args: A,
67 ) -> Result<T, PicCallError>
68 where
69 T: CandidType + DeserializeOwned,
70 A: ArgumentEncoder,
71 {
72 let bytes = encode_call_args(args)?;
73 let result = self
74 .inner
75 .query_call(canister_id, caller, method, bytes)
76 .map_err(|err| {
77 PicCallError::new(format!(
78 "pocket_ic query_call failed (canister={canister_id}, method={method}): {err}"
79 ))
80 })?;
81
82 decode_call_result(&result)
83 }
84
85 pub fn tick_n(&self, times: usize) {
87 for _ in 0..times {
88 self.tick();
89 }
90 }
91}
92
93fn encode_call_args<A>(args: A) -> Result<Vec<u8>, PicCallError>
94where
95 A: ArgumentEncoder,
96{
97 encode_args(args).map_err(|err| PicCallError::new(format!("encode_args failed: {err}")))
98}
99
100fn decode_call_result<T>(result: &[u8]) -> Result<T, PicCallError>
101where
102 T: CandidType + DeserializeOwned,
103{
104 decode_one(result).map_err(|err| PicCallError::new(format!("decode_one failed: {err}")))
105}