Skip to main content

canic_core/api/rpc/
mod.rs

1use crate::{
2    cdk::{candid::CandidType, types::Principal},
3    dto::{
4        capability::{
5            NonrootCyclesCapabilityEnvelopeV1, NonrootCyclesCapabilityResponseV1,
6            RootCapabilityEnvelopeV1, RootCapabilityResponseV1,
7        },
8        error::Error,
9        rpc::{
10            CreateCanisterParent, CreateCanisterResponse, CyclesResponse, UpgradeCanisterResponse,
11        },
12    },
13    ids::CanisterRole,
14    workflow::rpc::{capability, request::RpcRequestWorkflow},
15};
16
17///
18/// RpcApi
19///
20/// Public, user-callable wrappers for Canic's internal RPC workflows.
21///
22/// These functions:
23/// - form part of the public API surface
24/// - are safe to call from downstream canister `lib.rs` code
25/// - return [`Error`] suitable for IC boundaries
26///
27/// Internally, they delegate to workflow-level RPC implementations,
28/// preserving the layering:
29///
30///   user canister -> api -> workflow -> ops -> infra
31///
32/// Workflow returns internal [`InternalError`]; conversion to [`Error`]
33/// happens exclusively at this API boundary.
34///
35
36pub struct RpcApi;
37
38impl RpcApi {
39    /// Compute the canonical root capability hash used for proof binding.
40    pub fn root_capability_hash(
41        target_canister: Principal,
42        capability_version: u16,
43        capability: &crate::dto::rpc::Request,
44    ) -> Result<[u8; 32], Error> {
45        capability::root_capability_hash(target_canister, capability_version, capability)
46    }
47
48    /// Dispatch the full root capability envelope verifier/orchestrator path.
49    pub async fn response_capability_v1_root(
50        envelope: RootCapabilityEnvelopeV1,
51    ) -> Result<RootCapabilityResponseV1, Error> {
52        capability::response_capability_v1_root(envelope)
53            .await
54            .map_err(Error::from)
55    }
56
57    /// Dispatch the non-root structural cycles capability path.
58    pub async fn response_capability_v1_nonroot(
59        envelope: NonrootCyclesCapabilityEnvelopeV1,
60    ) -> Result<NonrootCyclesCapabilityResponseV1, Error> {
61        capability::response_capability_v1_nonroot(envelope)
62            .await
63            .map_err(Error::from)
64    }
65
66    pub async fn create_canister_request<A>(
67        canister_role: &CanisterRole,
68        parent: CreateCanisterParent,
69        extra: Option<A>,
70    ) -> Result<CreateCanisterResponse, Error>
71    where
72        A: CandidType + Send + Sync,
73    {
74        RpcRequestWorkflow::create_canister_request(canister_role, parent, extra)
75            .await
76            .map_err(Error::from)
77    }
78
79    pub async fn upgrade_canister_request(
80        canister_pid: Principal,
81    ) -> Result<UpgradeCanisterResponse, Error> {
82        RpcRequestWorkflow::upgrade_canister_request(canister_pid)
83            .await
84            .map_err(Error::from)
85    }
86
87    pub async fn request_cycles(cycles: u128) -> Result<CyclesResponse, Error> {
88        RpcRequestWorkflow::request_cycles(cycles)
89            .await
90            .map_err(Error::from)
91    }
92
93    pub async fn response_capability_v1(
94        envelope: RootCapabilityEnvelopeV1,
95    ) -> Result<RootCapabilityResponseV1, Error> {
96        capability::response_capability_v1_root(envelope)
97            .await
98            .map_err(Error::from)
99    }
100}