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,
12 replica_query::ReplicaQueryError,
13};
14use canic_contracts::{
15 dto::wire::projection::overview::RoleStatusResponse, protocol::CANIC_PUBLIC_STATUS,
16};
17use std::path::Path;
18use thiserror::Error as ThisError;
19
20const ICP_JSON_OUTPUT: &str = "json";
21
22#[derive(Debug, ThisError)]
27pub enum CanisterReadyQueryError {
28 #[error(transparent)]
29 IcpConfig(#[from] IcpConfigError),
30
31 #[error(transparent)]
32 Icp(#[from] IcpCommandError),
33
34 #[error(transparent)]
35 Replica(#[from] ReplicaQueryError),
36
37 #[error(transparent)]
38 Response(#[from] IcpJsonResponseError),
39}
40
41pub fn query_canister_ready(
43 icp: &IcpCli,
44 canister_id: &str,
45 environment: &str,
46 icp_root: Option<&Path>,
47 binding: &ResolvedProtocolBinding,
48) -> Result<bool, CanisterReadyQueryError> {
49 if replica_query::uses_local_replica_transport(Some(environment), icp_root)? {
50 return query_local_canister_ready(environment, canister_id, icp_root).map_err(Into::into);
51 }
52
53 query_canister_ready_with_icp(icp, canister_id, binding)
54}
55
56pub fn query_local_canister_ready(
58 environment: &str,
59 canister_id: &str,
60 icp_root: Option<&Path>,
61) -> Result<bool, ReplicaQueryError> {
62 replica_query::query_ready(
63 Some(environment),
64 canister_id,
65 CANIC_PUBLIC_STATUS,
66 icp_root,
67 )
68}
69
70fn query_canister_ready_with_icp(
71 icp: &IcpCli,
72 canister_id: &str,
73 binding: &ResolvedProtocolBinding,
74) -> Result<bool, CanisterReadyQueryError> {
75 let output = icp.canister_query_arg_output_with_candid(
76 canister_id,
77 CANIC_PUBLIC_STATUS,
78 "(variant { Overview })",
79 Some(ICP_JSON_OUTPUT),
80 Some(&binding.candid_path),
81 )?;
82 let response = decode_json_result_response::<RoleStatusResponse>(&output)?;
83 let RoleStatusResponse::Overview(response) = response;
84 Ok(response.bootstrap.ready)
85}