canic_core/api/ic/
mod.rs

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