Skip to main content

canic_host/icp/
model.rs

1use std::path::PathBuf;
2
3use serde::{Deserialize, Serialize};
4
5pub(super) const LOCAL_ICP_TARGET: &str = "local";
6pub(super) const REQUIRED_ICP_CLI_VERSION: &str = "1.5.0";
7pub(super) const ICP_CLI_SUPPORTED_VERSION_RANGE: &str = ">=1.5.0, <2.0.0";
8
9/// Direct local replica endpoint used when ICP project state is unavailable.
10///
11#[derive(Clone, Debug, Eq, PartialEq)]
12pub struct LocalReplicaTarget {
13    /// Exact selected local environment; another environment must use its own network authority.
14    pub environment: String,
15    pub url: String,
16    pub root_key: String,
17}
18
19///
20/// IcpRawOutput
21///
22
23#[derive(Clone, Debug, Eq, PartialEq)]
24pub struct IcpRawOutput {
25    pub success: bool,
26    pub status: String,
27    pub stdout: Vec<u8>,
28    pub stderr: Vec<u8>,
29}
30
31///
32/// IcpCli
33///
34
35#[derive(Clone, Debug)]
36pub struct IcpCli {
37    pub(super) remote_calls: std::sync::Arc<std::sync::atomic::AtomicU64>,
38    pub(super) executable: String,
39    pub(super) environment: Option<String>,
40    pub(super) cwd: Option<PathBuf>,
41    pub(super) local_replica: Option<LocalReplicaTarget>,
42    pub(super) inherited_fd: Option<i32>,
43    pub(super) identity_password_file: Option<PathBuf>,
44    pub(super) selected_identity: std::sync::Arc<std::sync::OnceLock<String>>,
45    pub(super) compatible_version: std::sync::Arc<std::sync::Mutex<Option<String>>>,
46}
47
48///
49/// IcpCliVersion
50///
51#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
52pub(super) struct IcpCliVersion {
53    pub(super) major: u64,
54    pub(super) minor: u64,
55    pub(super) patch: u64,
56}
57
58///
59/// IcpSnapshot
60///
61
62#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
63pub struct IcpSnapshot {
64    pub snapshot_id: String,
65    pub taken_at_timestamp: Option<u64>,
66    pub total_size_bytes: Option<u64>,
67}
68
69///
70/// IcpCanisterStatusReport
71///
72
73#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
74pub struct IcpCanisterStatusReport {
75    #[serde(default, rename = "version", alias = "canister_version")]
76    pub canister_version: Option<u64>,
77    #[serde(default, rename = "controllers")]
78    pub public_controllers: Option<Vec<String>>,
79    pub id: String,
80    pub name: Option<String>,
81    pub status: Option<String>,
82    pub settings: Option<IcpCanisterStatusSettings>,
83    pub module_hash: Option<String>,
84    pub memory_size: Option<String>,
85    pub cycles: Option<String>,
86    pub reserved_cycles: Option<String>,
87    pub idle_cycles_burned_per_day: Option<String>,
88    pub query_stats: Option<IcpCanisterQueryStats>,
89}
90
91///
92/// IcpCanisterStatusSettings
93///
94
95#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
96pub struct IcpCanisterStatusSettings {
97    #[serde(default)]
98    pub controllers: Vec<String>,
99    pub compute_allocation: Option<String>,
100    pub memory_allocation: Option<String>,
101    pub freezing_threshold: Option<String>,
102    pub reserved_cycles_limit: Option<String>,
103    pub wasm_memory_limit: Option<String>,
104    pub wasm_memory_threshold: Option<String>,
105    pub log_memory_limit: Option<String>,
106    pub log_visibility: Option<IcpCanisterVisibility>,
107    pub snapshot_visibility: Option<IcpCanisterVisibility>,
108    pub status_visibility: Option<IcpCanisterVisibility>,
109}
110
111/// Transport context identity excludes informational counters.
112#[derive(Eq, PartialEq)]
113struct IcpCommandIdentity<'a> {
114    executable: &'a str,
115    environment: Option<&'a str>,
116    cwd: Option<&'a std::path::Path>,
117    local_replica: Option<&'a LocalReplicaTarget>,
118    inherited_fd: Option<i32>,
119    identity_password_file: Option<&'a std::path::Path>,
120    selected_identity: Option<&'a str>,
121}
122
123impl IcpCli {
124    fn command_identity(&self) -> IcpCommandIdentity<'_> {
125        IcpCommandIdentity {
126            executable: &self.executable,
127            environment: self.environment.as_deref(),
128            cwd: self.cwd.as_deref(),
129            local_replica: self.local_replica.as_ref(),
130            inherited_fd: self.inherited_fd,
131            identity_password_file: self.identity_password_file.as_deref(),
132            selected_identity: self.selected_identity.get().map(String::as_str),
133        }
134    }
135}
136
137impl PartialEq for IcpCli {
138    fn eq(&self, other: &Self) -> bool {
139        self.command_identity() == other.command_identity()
140    }
141}
142impl Eq for IcpCli {}
143///
144/// IcpCanisterVisibility
145///
146/// Visibility of one management observation surface; this grants no controller authority.
147///
148
149#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
150#[serde(tag = "type", content = "value", deny_unknown_fields)]
151pub enum IcpCanisterVisibility {
152    AllowedViewers(Vec<candid::Principal>),
153    Controllers,
154    Public,
155}
156
157///
158/// IcpCanisterQueryStats
159///
160/// Cumulative query counters preserving ICP's numeric text without narrowing.
161///
162
163#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
164pub struct IcpCanisterQueryStats {
165    pub num_calls_total: String,
166    pub num_instructions_total: String,
167    pub request_payload_bytes_total: String,
168    pub response_payload_bytes_total: String,
169}