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