canic_core/ops/rpc/
mod.rs1mod request;
2mod response;
3
4pub use request::*;
5pub use response::*;
6
7use crate::{
8 Error, ThisError,
9 cdk::candid::CandidType,
10 ops::{OpsError, ic::call::Call, storage::env::EnvOps},
11};
12use serde::de::DeserializeOwned;
13
14pub trait Rpc {
20 type Response: CandidType + DeserializeOwned;
21
22 fn into_request(self) -> Request;
23 fn try_from_response(resp: Response) -> Result<Self::Response, RequestOpsError>;
24}
25
26#[derive(Debug, ThisError)]
31pub enum RpcOpsError {
32 #[error("cannot find the root canister")]
33 RootNotFound,
34
35 #[error(transparent)]
36 RequestOpsError(#[from] request::RequestOpsError),
37}
38
39impl From<RpcOpsError> for Error {
40 fn from(err: RpcOpsError) -> Self {
41 OpsError::from(err).into()
42 }
43}
44
45async fn execute_rpc<R: Rpc>(rpc: R) -> Result<R::Response, Error> {
47 let root_pid = EnvOps::try_get_root_pid().map_err(|_| RpcOpsError::RootNotFound)?;
48
49 let call_response = Call::unbounded_wait(root_pid, "canic_response")
50 .with_arg(rpc.into_request())
51 .await?;
52
53 let response = call_response.candid::<Result<Response, Error>>()??;
54
55 R::try_from_response(response)
56 .map_err(RpcOpsError::from)
57 .map_err(Error::from)
58}