Skip to main content

ic_query/cloud_engine/
mod.rs

1//! Native CloudEngine control-plane report models, adapters, builders, and renderers.
2
3#[cfg(feature = "cloud-engine-host")]
4mod build;
5mod model;
6#[cfg(feature = "cloud-engine-host")]
7mod source;
8mod text;
9#[cfg(feature = "cloud-engine-host")]
10mod wire;
11
12#[cfg(feature = "cloud-engine-host")]
13use crate::runtime::RuntimeError;
14#[cfg(feature = "cloud-engine-host")]
15use thiserror::Error as ThisError;
16
17#[cfg(feature = "cloud-engine-host")]
18pub use build::{
19    build_cloud_engine_operator_report, build_cloud_engine_operator_report_with_source,
20    build_cloud_engine_prices_report, build_cloud_engine_prices_report_with_source,
21};
22pub use model::{
23    CloudEngineNodeType, CloudEngineOperatorReport, CloudEnginePriceRow, CloudEnginePricesReport,
24    CloudEngineReportContext,
25};
26#[cfg(feature = "cloud-engine-host")]
27pub use model::{CloudEngineOperatorSourceData, CloudEnginePricesSourceData};
28#[cfg(feature = "cloud-engine-host")]
29pub use source::{CloudEngineSource, CloudEngineSourceRequest, LiveCloudEngineSource};
30pub use text::{cloud_engine_operator_report_text, cloud_engine_prices_report_text};
31
32/// Mainnet CloudEngine control-plane registry canister principal.
33pub const MAINNET_CLOUD_ENGINE_CANISTER_ID: &str = "q6cfj-fyaaa-aaaar-qb77q-cai";
34
35/// Default replica endpoint used for live CloudEngine control-plane queries.
36pub const DEFAULT_CLOUD_ENGINE_SOURCE_ENDPOINT: &str = "https://icp-api.io";
37
38/// Maximum marketplace rows accepted from one live response.
39pub const MAX_CLOUD_ENGINE_PRICE_ROWS: usize = 1_000;
40
41/// Maximum claimed domains accepted from one engine operator.
42pub const MAX_CLOUD_ENGINE_DOMAINS: usize = 100;
43
44/// Maximum decimal digits accepted for one marketplace cycle amount.
45pub const MAX_CLOUD_ENGINE_CYCLE_DECIMAL_DIGITS: usize = 256;
46
47#[cfg(feature = "cloud-engine-host")]
48const CLOUD_ENGINE_REPORT_SCHEMA_VERSION: u32 = 1;
49#[cfg(feature = "cloud-engine-host")]
50const CLOUD_ENGINE_AUTHORITY: &str = "cloud_engine_control_plane_canister";
51
52///
53/// CloudEngineHostError
54///
55/// Failure while collecting or validating one live CloudEngine report.
56///
57
58#[cfg(feature = "cloud-engine-host")]
59#[derive(Debug, ThisError)]
60pub enum CloudEngineHostError {
61    /// The requested network is not the supported mainnet identity.
62    #[error(
63        "`icq cloud-engine` supports only the mainnet `ic` network\n\nThese reports query the mainnet CloudEngine control-plane canister.\n\nTry:\n  icq --network ic cloud-engine prices"
64    )]
65    UnsupportedNetwork {
66        /// Rejected network identity.
67        network: String,
68    },
69
70    /// A requested principal is invalid.
71    #[error("invalid {field}: {reason}")]
72    InvalidPrincipal {
73        /// Principal field being parsed.
74        field: &'static str,
75        /// Principal parsing failure.
76        reason: String,
77    },
78
79    /// The IC agent could not be constructed for the requested endpoint.
80    #[error("failed to build IC agent for {endpoint}: {reason}")]
81    AgentBuild {
82        /// Endpoint used to build the agent.
83        endpoint: String,
84        /// Agent construction failure.
85        reason: String,
86    },
87
88    /// The built-in CloudEngine control-plane principal could not be parsed.
89    #[error("invalid built-in CloudEngine canister principal: {reason}")]
90    CanisterId {
91        /// Principal parsing failure.
92        reason: String,
93    },
94
95    /// A CloudEngine control-plane query failed.
96    #[error("CloudEngine agent call {method} failed: {reason}")]
97    AgentCall {
98        /// Canister method being queried.
99        method: &'static str,
100        /// Agent call failure.
101        reason: String,
102    },
103
104    /// A CloudEngine query argument could not be Candid encoded.
105    #[error("failed to encode Candid {message}: {reason}")]
106    CandidEncode {
107        /// Candid request type.
108        message: &'static str,
109        /// Encoding failure.
110        reason: String,
111    },
112
113    /// A CloudEngine response could not be Candid decoded.
114    #[error("failed to decode Candid {message}: {reason}")]
115    CandidDecode {
116        /// Candid response type.
117        message: &'static str,
118        /// Decoding failure.
119        reason: String,
120    },
121
122    /// A custom CloudEngine source returned inconsistent or excessive data.
123    #[error("invalid CloudEngine source data: {reason}")]
124    InvalidSourceData {
125        /// Deterministic source-contract failure.
126        reason: String,
127    },
128
129    /// The synchronous host runtime could not execute the live query.
130    #[error(transparent)]
131    Runtime(#[from] RuntimeError),
132}
133
134#[cfg(feature = "cloud-engine-host")]
135fn enforce_mainnet_network(network: &str) -> Result<(), CloudEngineHostError> {
136    crate::network::enforce_mainnet_network_with(network, |network| {
137        CloudEngineHostError::UnsupportedNetwork { network }
138    })
139}
140
141#[cfg(all(test, feature = "cloud-engine-host"))]
142mod tests;