canic_core/interface/ic/
mod.rs1pub mod call;
5pub mod canister;
6pub mod cycles;
7pub mod helper;
8pub mod icp;
9pub mod network;
10pub mod sns;
11pub mod timer;
12
13pub use helper::*;
14
15use crate::{
16 Error,
17 cdk::mgmt::{
18 self, CanisterInstallMode, CanisterStatusArgs, CanisterStatusResult, DeleteCanisterArgs,
19 DepositCyclesArgs, InstallCodeArgs, UninstallCodeArgs, WasmModule,
20 },
21 env::nns::NNS_REGISTRY_CANISTER,
22 interface::prelude::*,
23 log,
24 log::Topic,
25 model::metrics::{SystemMetricKind, SystemMetrics},
26 spec::nns::{GetSubnetForCanisterRequest, GetSubnetForCanisterResponse},
27};
28use candid::{CandidType, Principal, decode_one, encode_args, utils::ArgumentEncoder};
29
30pub async fn canister_status(canister_pid: Principal) -> Result<CanisterStatusResult, Error> {
36 let args = CanisterStatusArgs {
37 canister_id: canister_pid,
38 };
39
40 let status = mgmt::canister_status(&args).await.map_err(Error::from)?;
41 SystemMetrics::increment(SystemMetricKind::CanisterStatus);
42
43 Ok(status)
44}
45
46#[must_use]
52pub fn canister_cycle_balance() -> Cycles {
53 crate::cdk::api::canister_cycle_balance().into()
54}
55
56pub async fn deposit_cycles(canister_pid: Principal, cycles: u128) -> Result<(), Error> {
58 let args = DepositCyclesArgs {
59 canister_id: canister_pid,
60 };
61 mgmt::deposit_cycles(&args, cycles)
62 .await
63 .map_err(Error::from)?;
64
65 SystemMetrics::increment(SystemMetricKind::DepositCycles);
66
67 Ok(())
68}
69
70pub async fn get_cycles(canister_pid: Principal) -> Result<Cycles, Error> {
72 let status = canister_status(canister_pid).await?;
73
74 Ok(status.cycles.into())
75}
76
77pub async fn get_current_subnet_pid() -> Result<Option<Principal>, Error> {
83 let request = GetSubnetForCanisterRequest::new(canister_self());
84
85 let subnet_id_opt = Call::unbounded_wait(*NNS_REGISTRY_CANISTER, "get_subnet_for_canister")
86 .with_arg(request)
87 .await?
88 .candid::<GetSubnetForCanisterResponse>()?
89 .map_err(Error::CallFailed)?
90 .subnet_id;
91
92 if let Some(subnet_id) = subnet_id_opt {
93 log!(Topic::Topology, Info, "get_current_subnet_pid: {subnet_id}");
94 } else {
95 log!(Topic::Topology, Warn, "get_current_subnet_pid: not found");
96 }
97
98 Ok(subnet_id_opt)
99}
100
101pub async fn install_code<T: ArgumentEncoder>(
107 mode: CanisterInstallMode,
108 canister_pid: Principal,
109 wasm: &[u8],
110 args: T,
111) -> Result<(), Error> {
112 let arg = encode_args(args)?;
113 let install_args = InstallCodeArgs {
114 mode,
115 canister_id: canister_pid,
116 wasm_module: WasmModule::from(wasm),
117 arg,
118 };
119
120 mgmt::install_code(&install_args)
121 .await
122 .map_err(Error::from)?;
123
124 let metric_kind = match mode {
125 CanisterInstallMode::Install => SystemMetricKind::InstallCode,
126 CanisterInstallMode::Reinstall => SystemMetricKind::ReinstallCode,
127 CanisterInstallMode::Upgrade(_) => SystemMetricKind::UpgradeCode,
128 };
129 SystemMetrics::increment(metric_kind);
130
131 Ok(())
132}
133
134pub async fn uninstall_code(canister_pid: Principal) -> Result<(), Error> {
136 let args = UninstallCodeArgs {
137 canister_id: canister_pid,
138 };
139
140 mgmt::uninstall_code(&args).await.map_err(Error::from)?;
141 SystemMetrics::increment(SystemMetricKind::UninstallCode);
142
143 Ok(())
144}
145
146pub async fn delete_canister(canister_pid: Principal) -> Result<(), Error> {
148 let args = DeleteCanisterArgs {
149 canister_id: canister_pid,
150 };
151
152 mgmt::delete_canister(&args).await.map_err(Error::from)?;
153 SystemMetrics::increment(SystemMetricKind::DeleteCanister);
154
155 Ok(())
156}
157
158pub async fn call_and_decode<T: CandidType + for<'de> candid::Deserialize<'de>>(
164 pid: Principal,
165 method: &str,
166 arg: impl CandidType,
167) -> Result<T, Error> {
168 let response = Call::unbounded_wait(pid, method)
169 .with_arg(arg)
170 .await
171 .map_err(Error::from)?;
172
173 decode_one(&response).map_err(Error::from)
174}