Skip to main content

canic_host/subnet_registry/
mod.rs

1use crate::{
2    icp::{IcpCli, IcpCommandError},
3    replica_query::{self, ReplicaQueryError},
4};
5use std::{error::Error, fmt, path::Path};
6
7const CANIC_SUBNET_REGISTRY_METHOD: &str = "canic_subnet_registry";
8const ICP_JSON_OUTPUT: &str = "json";
9
10///
11/// SubnetRegistryQuery
12///
13
14#[derive(Clone, Debug, Eq, PartialEq)]
15pub struct SubnetRegistryQuery {
16    pub source: SubnetRegistryQuerySource,
17    pub registry_json: String,
18}
19
20///
21/// SubnetRegistryQuerySource
22///
23
24#[derive(Clone, Copy, Debug, Eq, PartialEq)]
25pub enum SubnetRegistryQuerySource {
26    LocalReplica,
27    IcpCli,
28}
29
30///
31/// SubnetRegistryQueryError
32///
33
34#[derive(Debug)]
35pub enum SubnetRegistryQueryError {
36    Replica(ReplicaQueryError),
37    Icp(IcpCommandError),
38}
39
40impl fmt::Display for SubnetRegistryQueryError {
41    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
42        match self {
43            Self::Replica(err) => write!(formatter, "{err}"),
44            Self::Icp(err) => write!(formatter, "{err}"),
45        }
46    }
47}
48
49impl Error for SubnetRegistryQueryError {
50    fn source(&self) -> Option<&(dyn Error + 'static)> {
51        match self {
52            Self::Replica(err) => Some(err),
53            Self::Icp(err) => Some(err),
54        }
55    }
56}
57
58impl From<ReplicaQueryError> for SubnetRegistryQueryError {
59    fn from(err: ReplicaQueryError) -> Self {
60        Self::Replica(err)
61    }
62}
63
64impl From<IcpCommandError> for SubnetRegistryQueryError {
65    fn from(err: IcpCommandError) -> Self {
66        Self::Icp(err)
67    }
68}
69
70/// Query `canic_subnet_registry`, using the local replica API for local targets.
71pub fn query_subnet_registry_json(
72    icp: &IcpCli,
73    root: &str,
74    network: &str,
75    icp_root: Option<&Path>,
76    candid_path: Option<&Path>,
77) -> Result<SubnetRegistryQuery, SubnetRegistryQueryError> {
78    if replica_query::should_use_local_replica_query(Some(network)) {
79        return query_local_subnet_registry_json(root, network, icp_root);
80    }
81
82    let registry_json = icp.canister_query_output_with_candid(
83        root,
84        CANIC_SUBNET_REGISTRY_METHOD,
85        Some(ICP_JSON_OUTPUT),
86        candid_path,
87    )?;
88    Ok(SubnetRegistryQuery {
89        source: SubnetRegistryQuerySource::IcpCli,
90        registry_json,
91    })
92}
93
94fn query_local_subnet_registry_json(
95    root: &str,
96    network: &str,
97    icp_root: Option<&Path>,
98) -> Result<SubnetRegistryQuery, SubnetRegistryQueryError> {
99    let registry_json = icp_root.map_or_else(
100        || replica_query::query_subnet_registry_json(Some(network), root),
101        |root_path| {
102            replica_query::query_subnet_registry_json_from_root(Some(network), root, root_path)
103        },
104    )?;
105    Ok(SubnetRegistryQuery {
106        source: SubnetRegistryQuerySource::LocalReplica,
107        registry_json,
108    })
109}