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}