canic_host/canister_ready/
mod.rs1use crate::{
8 icp::{IcpCli, IcpCommandError, IcpJsonResponseError, decode_json_result_response},
9 icp_config::IcpConfigError,
10 protocol_binding::ResolvedProtocolBinding,
11 replica_query::{self, ReplicaQueryError},
12};
13use candid::{CandidType, Deserialize};
14use canic_core::{dto::role::RoleOverviewResponse, protocol::CANIC_PUBLIC_STATUS};
15use std::path::Path;
16use thiserror::Error as ThisError;
17
18const ICP_JSON_OUTPUT: &str = "json";
19
20#[derive(CandidType, Deserialize)]
21enum RoleStatusResponse {
22 Overview(RoleOverviewResponse),
23}
24
25#[derive(Debug, ThisError)]
30pub enum CanisterReadyQueryError {
31 #[error(transparent)]
32 IcpConfig(#[from] IcpConfigError),
33
34 #[error(transparent)]
35 Icp(#[from] IcpCommandError),
36
37 #[error(transparent)]
38 Replica(#[from] ReplicaQueryError),
39
40 #[error(transparent)]
41 Response(#[from] IcpJsonResponseError),
42}
43
44pub fn query_canister_ready(
46 icp: &IcpCli,
47 canister_id: &str,
48 environment: &str,
49 icp_root: Option<&Path>,
50 binding: &ResolvedProtocolBinding,
51) -> Result<bool, CanisterReadyQueryError> {
52 if replica_query::uses_local_replica_transport(Some(environment), icp_root)? {
53 return query_local_canister_ready(environment, canister_id, icp_root).map_err(Into::into);
54 }
55
56 query_canister_ready_with_icp(icp, canister_id, binding)
57}
58
59pub fn query_local_canister_ready(
61 environment: &str,
62 canister_id: &str,
63 icp_root: Option<&Path>,
64) -> Result<bool, ReplicaQueryError> {
65 replica_query::query_ready(
66 Some(environment),
67 canister_id,
68 CANIC_PUBLIC_STATUS,
69 icp_root,
70 )
71}
72
73fn query_canister_ready_with_icp(
74 icp: &IcpCli,
75 canister_id: &str,
76 binding: &ResolvedProtocolBinding,
77) -> Result<bool, CanisterReadyQueryError> {
78 let output = icp.canister_query_arg_output_with_candid(
79 canister_id,
80 CANIC_PUBLIC_STATUS,
81 "(variant { Overview })",
82 Some(ICP_JSON_OUTPUT),
83 Some(&binding.candid_path),
84 )?;
85 let response = decode_json_result_response::<RoleStatusResponse>(&output)?;
86 let RoleStatusResponse::Overview(response) = response;
87 Ok(response.bootstrap.ready)
88}