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