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 InternalError,
43 cdk::{self, types::Principal},
44 infra,
45 ops::OpsError,
46};
47use thiserror::Error as ThisError;
48
49///
50/// IcOpsError
51///
52
53#[derive(Debug, ThisError)]
54pub enum IcOpsError {
55 #[error(transparent)]
56 Infra(#[from] infra::InfraError),
57
58 #[error(transparent)]
59 CallOps(#[from] call::CallError),
60
61 #[error(transparent)]
62 HttpOps(#[from] http::HttpOpsError),
63
64 #[error(transparent)]
65 LedgerOps(#[from] ledger::LedgerOpsError),
66
67 #[error(transparent)]
68 XrcOps(#[from] xrc::XrcOpsError),
69}
70
71impl From<IcOpsError> for InternalError {
72 fn from(err: IcOpsError) -> Self {
73 OpsError::from(err).into()
74 }
75}
76
77///
78/// IcOps
79/// Ambient IC execution primitives
80///
81
82pub struct IcOps;
83
84impl IcOps {
85 /// Return the current canister principal.
86 #[must_use]
87 pub fn canister_self() -> Principal {
88 cdk::api::canister_self()
89 }
90
91 /// Return the current caller principal.
92 #[must_use]
93 pub fn msg_caller() -> Principal {
94 cdk::api::msg_caller()
95 }
96
97 /// Return the current UNIX epoch time in seconds.
98 #[must_use]
99 pub fn now_secs() -> u64 {
100 cdk::utils::time::now_secs()
101 }
102
103 /// Return the current UNIX epoch time in milliseconds.
104 #[must_use]
105 pub fn now_millis() -> u64 {
106 cdk::utils::time::now_millis()
107 }
108
109 /// Return the current UNIX epoch time in microseconds.
110 #[must_use]
111 pub fn now_micros() -> u64 {
112 cdk::utils::time::now_micros()
113 }
114
115 /// Return the current UNIX epoch time in nanoseconds.
116 #[must_use]
117 pub fn now_nanos() -> u64 {
118 cdk::utils::time::now_nanos()
119 }
120
121 /// Trap the canister with the provided message.
122 pub fn trap(message: &str) -> ! {
123 cdk::api::trap(message)
124 }
125
126 /// Print a line to the IC debug output.
127 pub fn println(message: &str) {
128 cdk::println!("{message}");
129 }
130
131 /// Spawn a task on the IC runtime.
132 pub fn spawn<F>(future: F)
133 where
134 F: Future<Output = ()> + 'static,
135 {
136 cdk::futures::spawn(future);
137 }
138}