canic_core/infra/ic/
mod.rs

1//! IC-related infra helpers.
2//!
3//! This module groups low-level IC concerns (management canister calls, ICC call
4//! wrappers, HTTP outcalls, timers) under a single namespace to keep `infra/`
5//! navigable.
6
7pub mod call;
8pub mod cmc;
9pub mod http;
10pub mod ledger;
11pub mod mgmt;
12pub mod signature;
13
14pub use mgmt::*;
15
16use crate::{Error, ThisError, infra::InfraError};
17
18///
19/// IcInfraError
20///
21
22#[derive(Debug, ThisError)]
23pub enum IcInfraError {
24    #[error(transparent)]
25    SignatureInfraError(#[from] signature::SignatureOpsError),
26}
27
28impl From<IcInfraError> for Error {
29    fn from(err: IcInfraError) -> Self {
30        InfraError::from(err).into()
31    }
32}
33
34///
35/// Network
36/// Identifies the environment the canister believes it runs in.
37///
38
39#[derive(Clone, Copy, Debug, Eq, PartialEq)]
40pub enum Network {
41    Ic,
42    Local,
43}
44
45impl Network {
46    #[must_use]
47    pub const fn as_str(self) -> &'static str {
48        match self {
49            Self::Ic => "ic",
50            Self::Local => "local",
51        }
52    }
53}
54
55impl core::fmt::Display for Network {
56    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
57        f.write_str(self.as_str())
58    }
59}
60
61///
62/// build_network_from_dfx_network
63/// Pure helper for `build_network()`, exposed for testing and reuse.
64///
65
66#[must_use]
67pub fn build_network_from_dfx_network(dfx_network: Option<&'static str>) -> Option<Network> {
68    match dfx_network {
69        Some("local") => Some(Network::Local),
70        Some("ic") => Some(Network::Ic),
71
72        _ => None,
73    }
74}
75
76///
77/// build_network
78/// Returns the network inferred at *build time* from `DFX_NETWORK`.
79/// This value is baked into the Wasm and does not reflect runtime state.
80///
81/// ChatGPT 5.2 Final, Precise Verdict
82///
83/// ✅ Yes, this works exactly as you say
84/// ✅ It is valid IC/Wasm code
85/// ❌ It is not runtime detection
86/// ⚠️ The danger is semantic, not technical
87/// ✅ Safe if treated as a build-time constant
88/// ❌ Dangerous if treated as authoritative runtime truth
89///
90
91#[must_use]
92pub fn build_network() -> Option<Network> {
93    build_network_from_dfx_network(option_env!("DFX_NETWORK"))
94}
95
96///
97/// TESTS
98///
99
100#[cfg(test)]
101mod tests {
102    use super::*;
103
104    #[test]
105    fn build_network_from_dfx_network_parses_ic() {
106        assert_eq!(
107            build_network_from_dfx_network(Some("ic")),
108            Some(Network::Ic)
109        );
110    }
111
112    #[test]
113    fn build_network_from_dfx_network_parses_local() {
114        assert_eq!(
115            build_network_from_dfx_network(Some("local")),
116            Some(Network::Local)
117        );
118    }
119
120    #[test]
121    fn build_network_from_dfx_network_rejects_unknown() {
122        assert_eq!(build_network_from_dfx_network(Some("nope")), None);
123    }
124
125    #[test]
126    fn build_network_from_dfx_network_handles_missing() {
127        assert_eq!(build_network_from_dfx_network(None), None);
128    }
129}