1pub mod http;
2pub mod signature;
3
4use crate::{
5 Error, PublicError,
6 cdk::{candid::CandidType, types::Principal},
7 dto::canister::CanisterStatusView,
8 log::Topic,
9 ops::ic::{call::CallOps, mgmt::MgmtOps},
10};
11use serde::de::DeserializeOwned;
12
13pub enum CallWait {
18 Bounded,
19 Unbounded,
20}
21
22pub struct CallBuilder {
27 pid: Principal,
28 method: String,
29 wait: CallWait,
30}
31
32impl CallBuilder {
33 #[must_use]
34 pub const fn bounded(mut self) -> Self {
35 self.wait = CallWait::Bounded;
36 self
37 }
38
39 #[must_use]
40 pub const fn unbounded(mut self) -> Self {
41 self.wait = CallWait::Unbounded;
42 self
43 }
44
45 pub async fn with_arg<R, A>(self, arg: A) -> Result<R, PublicError>
46 where
47 R: CandidType + DeserializeOwned,
48 A: CandidType,
49 {
50 let call = match self.wait {
51 CallWait::Bounded => CallOps::bounded_wait(self.pid, &self.method),
52 CallWait::Unbounded => CallOps::unbounded_wait(self.pid, &self.method),
53 };
54
55 let response = call
56 .try_with_arg(arg)
57 .map_err(|e| map_internal_error(Error::from(e)))?
58 .execute()
59 .await
60 .map_err(|e| map_internal_error(Error::from(e)))?;
61
62 response
63 .candid::<R>()
64 .map_err(|e| map_internal_error(Error::from(e)))
65 }
66}
67
68pub async fn canister_status(pid: Principal) -> Result<CanisterStatusView, PublicError> {
69 MgmtOps::canister_status(pid)
70 .await
71 .map_err(map_internal_error)
72}
73
74fn map_internal_error(err: Error) -> PublicError {
75 crate::log!(Topic::Rpc, Error, "api.ic failed: {err:?}");
77 PublicError::from(err)
78}