Skip to main content

canic_core/api/rpc/
mod.rs

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