Skip to main content

bity_ic_utils/
env.rs

1//! Environment-related utilities for Internet Computer canisters.
2
3use bity_ic_canister_time::now_nanos;
4use bity_ic_types::BuildVersion;
5use bity_ic_types::{CanisterId, Cycles, TimestampMillis, TimestampNanos};
6use candid::{CandidType, Principal};
7use serde::{Deserialize, Serialize};
8
9/// Represents the environment configuration of a canister.
10#[derive(Default, CandidType, Serialize, Deserialize, Clone)]
11pub struct CanisterEnv {
12    /// Whether the canister is running in test mode
13    test_mode: bool,
14    /// The build version of the canister
15    version: BuildVersion,
16    /// The Git commit hash of the canister's code
17    commit_hash: String,
18}
19
20/// Trait for accessing canister environment information.
21pub trait Environment {
22    /// Returns the current time in nanoseconds
23    fn now_nanos(&self) -> TimestampNanos;
24    /// Returns the caller's principal
25    fn caller(&self) -> Principal;
26    /// Returns the canister's own ID
27    fn canister_id(&self) -> CanisterId;
28    /// Returns the current cycle balance
29    fn cycles_balance(&self) -> Cycles;
30
31    fn now(&self) -> TimestampMillis {
32        self.now_nanos() / 1_000_000
33    }
34
35    fn cycles_balance_in_tc(&self) -> f64 {
36        (self.cycles_balance() as f64) / 1_000_000_000_000.0
37    }
38}
39
40impl CanisterEnv {
41    pub fn new(test_mode: bool, version: BuildVersion, commit_hash: String) -> Self {
42        Self {
43            test_mode,
44            version,
45            commit_hash,
46        }
47    }
48
49    pub fn is_test_mode(&self) -> bool {
50        self.test_mode
51    }
52
53    pub fn version(&self) -> BuildVersion {
54        self.version
55    }
56
57    pub fn set_version(&mut self, version: BuildVersion) {
58        self.version = version;
59    }
60
61    pub fn commit_hash(&self) -> &str {
62        &self.commit_hash
63    }
64
65    pub fn set_commit_hash(&mut self, commit_hash: String) {
66        self.commit_hash = commit_hash;
67    }
68}
69
70impl Environment for CanisterEnv {
71    fn now_nanos(&self) -> TimestampNanos {
72        now_nanos()
73    }
74
75    #[cfg(target_arch = "wasm32")]
76    fn caller(&self) -> Principal {
77        ic_cdk::caller()
78    }
79    #[cfg(not(target_arch = "wasm32"))]
80    fn caller(&self) -> Principal {
81        Principal::anonymous()
82    }
83
84    #[cfg(target_arch = "wasm32")]
85    fn canister_id(&self) -> CanisterId {
86        ic_cdk::id()
87    }
88    #[cfg(not(target_arch = "wasm32"))]
89    fn canister_id(&self) -> CanisterId {
90        Principal::anonymous()
91    }
92
93    #[cfg(target_arch = "wasm32")]
94    fn cycles_balance(&self) -> Cycles {
95        ic_cdk::api::canister_balance().into()
96    }
97    #[cfg(not(target_arch = "wasm32"))]
98    fn cycles_balance(&self) -> Cycles {
99        0
100    }
101}