canic_core/ops/ic/
mod.rs

1//! Ops layer: approved execution surface and coordination boundary.
2//!
3//! The `ops` layer defines the **sanctioned capabilities** that higher layers
4//! (workflow, API, macros) are allowed to use. It sits between application logic
5//! and low-level infrastructure, providing a stable execution façade.
6//!
7//! Responsibilities:
8//! - Expose approved primitives and subsystems (IC access, runtime context,
9//!   metrics, logging, registries).
10//! - Add cross-cutting concerns such as metrics, logging, and normalization.
11//! - Aggregate infra errors into ops-scoped error types.
12//!
13//! Non-responsibilities:
14//! - No business policy or workflow orchestration.
15//! - No domain decisions or lifecycle management.
16//!
17//! Infra interaction:
18//! - `infra` owns **raw mechanical implementations** (IC calls, encoding,
19//!   decoding, management canister interactions).
20//! - `ops` may either wrap infra or call the CDK directly when the CDK API
21//!   already represents the desired primitive (e.g. ambient runtime context).
22//!
23//! Naming conventions:
24//! - Plain nouns (e.g. `Call`, `Runtime`, `Env`) represent approved execution
25//!   primitives.
26//! - `*Ops` types represent orchestration or aggregation roles (typically error
27//!   or coordination objects), not primitives themselves.
28
29pub mod call;
30pub mod http;
31pub mod icrc;
32pub mod ledger;
33pub mod mgmt;
34pub mod network;
35pub mod nns;
36pub mod signature;
37pub mod xrc;
38
39pub use cdk::types::{Cycles, TC};
40
41use crate::{
42    Error, ThisError,
43    cdk::{self, types::Principal},
44    infra,
45    ops::OpsError,
46};
47
48///
49/// IcOpsError
50///
51
52#[derive(Debug, ThisError)]
53pub enum IcOpsError {
54    #[error(transparent)]
55    Infra(#[from] infra::InfraError),
56
57    #[error(transparent)]
58    CallOps(#[from] call::CallError),
59
60    #[error(transparent)]
61    HttpOps(#[from] http::HttpOpsError),
62
63    #[error(transparent)]
64    LedgerOps(#[from] ledger::LedgerOpsError),
65
66    #[error(transparent)]
67    XrcOps(#[from] xrc::XrcOpsError),
68}
69
70impl From<IcOpsError> for Error {
71    fn from(err: IcOpsError) -> Self {
72        OpsError::from(err).into()
73    }
74}
75
76///
77/// IcOps
78/// Ambient IC execution primitives
79///
80
81pub struct IcOps;
82
83impl IcOps {
84    /// Return the current canister principal.
85    #[must_use]
86    pub fn canister_self() -> Principal {
87        cdk::api::canister_self()
88    }
89
90    /// Return the current caller principal.
91    #[must_use]
92    pub fn msg_caller() -> Principal {
93        cdk::api::msg_caller()
94    }
95
96    /// Return the current UNIX epoch time in seconds.
97    #[must_use]
98    pub fn now_secs() -> u64 {
99        cdk::utils::time::now_secs()
100    }
101
102    /// Return the current UNIX epoch time in milliseconds.
103    #[must_use]
104    pub fn now_millis() -> u64 {
105        cdk::utils::time::now_millis()
106    }
107
108    /// Return the current UNIX epoch time in microseconds.
109    #[must_use]
110    pub fn now_micros() -> u64 {
111        cdk::utils::time::now_micros()
112    }
113
114    /// Return the current UNIX epoch time in nanoseconds.
115    #[must_use]
116    pub fn now_nanos() -> u64 {
117        cdk::utils::time::now_nanos()
118    }
119
120    /// Trap the canister with the provided message.
121    pub fn trap(message: &str) -> ! {
122        cdk::api::trap(message)
123    }
124
125    /// Print a line to the IC debug output.
126    pub fn println(message: &str) {
127        cdk::println!("{message}");
128    }
129
130    /// Spawn a task on the IC runtime.
131    pub fn spawn<F>(future: F)
132    where
133        F: Future<Output = ()> + 'static,
134    {
135        cdk::futures::spawn(future);
136    }
137}