canic_core/ops/rpc/
request.rs1use super::{Rpc, RpcOpsError};
2use crate::{
3 Error, ThisError,
4 dto::rpc::{
5 CreateCanisterParent, CreateCanisterRequest, CreateCanisterResponse, CyclesRequest,
6 CyclesResponse, Request, Response, UpgradeCanisterRequest, UpgradeCanisterResponse,
7 },
8 ops::{prelude::*, runtime::env::EnvOps},
9};
10use candid::encode_one;
11
12#[derive(Debug, ThisError)]
18pub enum RequestOpsError {
19 #[error("canister role {0} not found")]
20 CanisterRoleNotFound(CanisterRole),
21
22 #[error("child canister {0} not found")]
23 ChildNotFound(Principal),
24
25 #[error("invalid response type")]
26 InvalidResponseType,
27
28 #[error("create_canister: missing new pid")]
29 MissingNewCanisterPid,
30
31 #[error("canister {0} is not a child of caller {1}")]
32 NotChildOfCaller(Principal, Principal),
33
34 #[error("canister {0}'s parent was not found")]
35 ParentNotFound(Principal),
36}
37
38impl From<RequestOpsError> for Error {
39 fn from(err: RequestOpsError) -> Self {
40 RpcOpsError::from(err).into()
41 }
42}
43
44pub async fn create_canister_request<A>(
49 canister_role: &CanisterRole,
50 parent: CreateCanisterParent,
51 extra: Option<A>,
52) -> Result<CreateCanisterResponse, Error>
53where
54 A: CandidType + Send + Sync,
55{
56 let extra_arg = extra.map(encode_one).transpose()?;
57
58 super::execute_rpc(CreateCanisterRpc {
59 canister_role: canister_role.clone(),
60 parent,
61 extra_arg,
62 })
63 .await
64}
65
66pub struct CreateCanisterRpc {
71 pub canister_role: CanisterRole,
72 pub parent: CreateCanisterParent,
73 pub extra_arg: Option<Vec<u8>>,
74}
75
76impl Rpc for CreateCanisterRpc {
77 type Response = CreateCanisterResponse;
78
79 fn into_request(self) -> Request {
80 Request::CreateCanister(CreateCanisterRequest {
81 canister_role: self.canister_role,
82 parent: self.parent,
83 extra_arg: self.extra_arg,
84 })
85 }
86
87 fn try_from_response(resp: Response) -> Result<Self::Response, RequestOpsError> {
88 match resp {
89 Response::CreateCanister(r) => Ok(r),
90 _ => Err(RequestOpsError::InvalidResponseType),
91 }
92 }
93}
94
95pub async fn upgrade_canister_request(
101 canister_pid: Principal,
102) -> Result<UpgradeCanisterResponse, Error> {
103 super::execute_rpc(UpgradeCanisterRpc { canister_pid }).await
104}
105
106pub struct UpgradeCanisterRpc {
107 pub canister_pid: Principal,
108}
109
110impl Rpc for UpgradeCanisterRpc {
111 type Response = UpgradeCanisterResponse;
112
113 fn into_request(self) -> Request {
114 Request::UpgradeCanister(UpgradeCanisterRequest {
115 canister_pid: self.canister_pid,
116 })
117 }
118
119 fn try_from_response(resp: Response) -> Result<Self::Response, RequestOpsError> {
120 match resp {
121 Response::UpgradeCanister(r) => Ok(r),
122 _ => Err(RequestOpsError::InvalidResponseType),
123 }
124 }
125}
126
127pub async fn cycles_request(cycles: u128) -> Result<CyclesResponse, Error> {
133 EnvOps::deny_root()?;
134
135 super::execute_rpc(CyclesRpc { cycles }).await
136}
137
138pub struct CyclesRpc {
139 pub cycles: u128,
140}
141
142impl Rpc for CyclesRpc {
143 type Response = CyclesResponse;
144
145 fn into_request(self) -> Request {
146 Request::Cycles(CyclesRequest {
147 cycles: self.cycles,
148 })
149 }
150
151 fn try_from_response(resp: Response) -> Result<Self::Response, RequestOpsError> {
152 match resp {
153 Response::Cycles(r) => Ok(r),
154 _ => Err(RequestOpsError::InvalidResponseType),
155 }
156 }
157}