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