1use crate::{
6 call::{AsyncCall, SyncCall},
7 Canister,
8};
9use ic_agent::{export::Principal, Agent};
10use ic_management_canister_types::{
11 CanisterIdRecord, DeleteCanisterSnapshotArgs, LoadCanisterSnapshotArgs,
12 ProvisionalTopUpCanisterArgs, ReadCanisterSnapshotDataArgs, ReadCanisterSnapshotMetadataArgs,
13 TakeCanisterSnapshotArgs, UploadCanisterSnapshotDataArgs, UploadCanisterSnapshotMetadataArgs,
14 UploadChunkArgs,
15};
16pub use ic_management_canister_types::{
18 CanisterLogFilter, CanisterLogRecord, CanisterMetadataArgs, CanisterMetadataResult,
19 CanisterStatusResult, CanisterStatusType, CanisterTimer, ChunkHash, DefiniteCanisterSettings,
20 FetchCanisterLogsArgs, FetchCanisterLogsResult, LogVisibility, MemoryMetrics,
21 OnLowWasmMemoryHookStatus, QueryStats, ReadCanisterSnapshotDataResult,
22 ReadCanisterSnapshotMetadataResult, RenameCanisterRecord, RenameToRecord, Snapshot,
23 SnapshotDataKind, SnapshotDataOffset, SnapshotMetadataGlobal, SnapshotSource,
24 StoredChunksResult, UploadCanisterSnapshotMetadataResult, UploadChunkResult,
25};
26use std::{convert::AsRef, ops::Deref};
27use strum_macros::{AsRefStr, Display, EnumString};
28
29pub mod attributes;
30pub mod builders;
31
32#[doc(inline)]
33pub use builders::{
34 CreateCanisterBuilder, InstallBuilder, InstallChunkedCodeBuilder, InstallCodeBuilder,
35 UpdateSettingsBuilder,
36};
37
38#[derive(Debug, Clone)]
40pub struct ManagementCanister<'agent>(Canister<'agent>);
41
42impl<'agent> Deref for ManagementCanister<'agent> {
43 type Target = Canister<'agent>;
44 fn deref(&self) -> &Self::Target {
45 &self.0
46 }
47}
48
49#[derive(AsRefStr, Debug, EnumString, Display)]
51#[strum(serialize_all = "snake_case")]
52pub enum MgmtMethod {
53 CreateCanister,
55 InstallCode,
57 StartCanister,
59 StopCanister,
61 CanisterStatus,
63 DeleteCanister,
65 DepositCycles,
67 RawRand,
69 ProvisionalCreateCanisterWithCycles,
71 ProvisionalTopUpCanister,
73 UninstallCode,
75 UpdateSettings,
77 UploadChunk,
79 ClearChunkStore,
81 StoredChunks,
83 InstallChunkedCode,
85 FetchCanisterLogs,
87 TakeCanisterSnapshot,
89 LoadCanisterSnapshot,
91 ListCanisterSnapshots,
93 DeleteCanisterSnapshot,
95 ReadCanisterSnapshotMetadata,
97 ReadCanisterSnapshotData,
99 UploadCanisterSnapshotMetadata,
101 UploadCanisterSnapshotData,
103 EcdsaPublicKey,
105 SignWithEcdsa,
107 BitcoinGetBalance,
109 BitcoinGetUtxos,
111 BitcoinSendTransaction,
113 BitcoinGetCurrentFeePercentiles,
115 BitcoinGetBlockHeaders,
117 NodeMetricsHistory,
119 CanisterInfo,
121 CanisterMetadata,
123}
124
125impl<'agent> ManagementCanister<'agent> {
126 pub fn create(agent: &'agent Agent) -> Self {
128 Self(
129 Canister::builder()
130 .with_agent(agent)
131 .with_canister_id(Principal::management_canister())
132 .build()
133 .unwrap(),
134 )
135 }
136
137 pub fn from_canister(canister: Canister<'agent>) -> Self {
139 Self(canister)
140 }
141}
142
143#[doc(hidden)]
144#[deprecated(since = "0.42.0", note = "Please use CanisterStatusResult instead")]
145pub type StatusCallResult = CanisterStatusResult;
146
147#[doc(hidden)]
148#[deprecated(since = "0.42.0", note = "Please use CanisterStatusType instead")]
149pub type CanisterStatus = CanisterStatusType;
150
151#[doc(hidden)]
152#[deprecated(since = "0.42.0", note = "Please use FetchCanisterLogsResult instead")]
153pub type FetchCanisterLogsResponse = FetchCanisterLogsResult;
154
155#[doc(hidden)]
156#[deprecated(since = "0.42.0", note = "Please use StoredChunksResult instead")]
157pub type StoreChunksResult = StoredChunksResult;
158
159#[doc(hidden)]
160#[deprecated(
161 since = "0.42.0",
162 note = "Please use ReadCanisterSnapshotMetadataResult instead"
163)]
164pub type SnapshotMetadata = ReadCanisterSnapshotMetadataResult;
165
166#[doc(hidden)]
167#[deprecated(
168 since = "0.42.0",
169 note = "Please use ReadCanisterSnapshotDataResult instead"
170)]
171pub type SnapshotDataResult = ReadCanisterSnapshotDataResult;
172
173#[doc(hidden)]
174#[deprecated(
175 since = "0.42.0",
176 note = "Please use UploadCanisterSnapshotMetadataResult instead"
177)]
178pub type CanisterSnapshotId = UploadCanisterSnapshotMetadataResult;
179
180impl<'agent> ManagementCanister<'agent> {
181 pub fn canister_status(
183 &self,
184 canister_id: &Principal,
185 ) -> impl 'agent + AsyncCall<Value = (CanisterStatusResult,)> {
186 self.update(MgmtMethod::CanisterStatus.as_ref())
187 .with_arg(CanisterIdRecord {
188 canister_id: *canister_id,
189 })
190 .with_effective_canister_id(canister_id.to_owned())
191 .build()
192 .map(|result: (CanisterStatusResult,)| (result.0,))
193 }
194
195 pub fn create_canister<'canister>(&'canister self) -> CreateCanisterBuilder<'agent, 'canister> {
197 CreateCanisterBuilder::builder(self)
198 }
199
200 pub fn deposit_cycles(&self, canister_id: &Principal) -> impl 'agent + AsyncCall<Value = ()> {
203 self.update(MgmtMethod::DepositCycles.as_ref())
204 .with_arg(CanisterIdRecord {
205 canister_id: *canister_id,
206 })
207 .with_effective_canister_id(canister_id.to_owned())
208 .build()
209 }
210
211 pub fn delete_canister(&self, canister_id: &Principal) -> impl 'agent + AsyncCall<Value = ()> {
213 self.update(MgmtMethod::DeleteCanister.as_ref())
214 .with_arg(CanisterIdRecord {
215 canister_id: *canister_id,
216 })
217 .with_effective_canister_id(canister_id.to_owned())
218 .build()
219 }
220
221 pub fn provisional_top_up_canister(
226 &self,
227 canister_id: &Principal,
228 top_up_args: &ProvisionalTopUpCanisterArgs,
229 ) -> impl 'agent + AsyncCall<Value = ()> {
230 self.update(MgmtMethod::ProvisionalTopUpCanister.as_ref())
231 .with_arg(top_up_args)
232 .with_effective_canister_id(canister_id.to_owned())
233 .build()
234 }
235
236 pub fn raw_rand(&self) -> impl 'agent + AsyncCall<Value = (Vec<u8>,)> {
240 self.update(MgmtMethod::RawRand.as_ref())
241 .build()
242 .map(|result: (Vec<u8>,)| (result.0,))
243 }
244
245 pub fn start_canister(&self, canister_id: &Principal) -> impl 'agent + AsyncCall<Value = ()> {
247 self.update(MgmtMethod::StartCanister.as_ref())
248 .with_arg(CanisterIdRecord {
249 canister_id: *canister_id,
250 })
251 .with_effective_canister_id(canister_id.to_owned())
252 .build()
253 }
254
255 pub fn stop_canister(&self, canister_id: &Principal) -> impl 'agent + AsyncCall<Value = ()> {
257 self.update(MgmtMethod::StopCanister.as_ref())
258 .with_arg(CanisterIdRecord {
259 canister_id: *canister_id,
260 })
261 .with_effective_canister_id(canister_id.to_owned())
262 .build()
263 }
264
265 pub fn uninstall_code(&self, canister_id: &Principal) -> impl 'agent + AsyncCall<Value = ()> {
273 self.update(MgmtMethod::UninstallCode.as_ref())
274 .with_arg(CanisterIdRecord {
275 canister_id: *canister_id,
276 })
277 .with_effective_canister_id(canister_id.to_owned())
278 .build()
279 }
280
281 pub fn install_code<'canister>(
283 &'canister self,
284 canister_id: &Principal,
285 wasm: &'canister [u8],
286 ) -> InstallCodeBuilder<'agent, 'canister> {
287 InstallCodeBuilder::builder(self, canister_id, wasm)
288 }
289
290 pub fn update_settings<'canister>(
292 &'canister self,
293 canister_id: &Principal,
294 ) -> UpdateSettingsBuilder<'agent, 'canister> {
295 UpdateSettingsBuilder::builder(self, canister_id)
296 }
297
298 pub fn upload_chunk(
300 &self,
301 canister_id: &Principal,
302 upload_chunk_args: &UploadChunkArgs,
303 ) -> impl 'agent + AsyncCall<Value = (UploadChunkResult,)> {
304 self.update(MgmtMethod::UploadChunk.as_ref())
305 .with_arg(upload_chunk_args)
306 .with_effective_canister_id(*canister_id)
307 .build()
308 }
309
310 pub fn clear_chunk_store(
312 &self,
313 canister_id: &Principal,
314 ) -> impl 'agent + AsyncCall<Value = ()> {
315 self.update(MgmtMethod::ClearChunkStore.as_ref())
316 .with_arg(CanisterIdRecord {
317 canister_id: *canister_id,
318 })
319 .with_effective_canister_id(*canister_id)
320 .build()
321 }
322
323 pub fn stored_chunks(
325 &self,
326 canister_id: &Principal,
327 ) -> impl 'agent + AsyncCall<Value = (StoredChunksResult,)> {
328 self.update(MgmtMethod::StoredChunks.as_ref())
329 .with_arg(CanisterIdRecord {
330 canister_id: *canister_id,
331 })
332 .with_effective_canister_id(*canister_id)
333 .build()
334 }
335
336 pub fn install_chunked_code<'canister>(
338 &'canister self,
339 canister_id: &Principal,
340 wasm_module_hash: &[u8],
341 ) -> InstallChunkedCodeBuilder<'agent, 'canister> {
342 InstallChunkedCodeBuilder::builder(self, *canister_id, wasm_module_hash)
343 }
344
345 pub fn install<'canister: 'builder, 'builder>(
351 &'canister self,
352 canister_id: &Principal,
353 wasm: &'builder [u8],
354 ) -> InstallBuilder<'agent, 'canister, 'builder> {
355 InstallBuilder::builder(self, canister_id, wasm)
356 }
357
358 pub fn fetch_canister_logs(
360 &self,
361 args: &FetchCanisterLogsArgs,
362 ) -> impl 'agent + SyncCall<Value = (FetchCanisterLogsResult,)> {
363 self.query(MgmtMethod::FetchCanisterLogs.as_ref())
364 .with_arg(args)
365 .with_effective_canister_id(args.canister_id)
366 .build()
367 }
368
369 pub fn take_canister_snapshot(
373 &self,
374 take_args: &TakeCanisterSnapshotArgs,
375 ) -> impl 'agent + AsyncCall<Value = (Snapshot,)> {
376 let args = TakeCanisterSnapshotArgs {
377 sender_canister_version: None,
378 ..take_args.clone()
379 };
380 self.update(MgmtMethod::TakeCanisterSnapshot.as_ref())
381 .with_arg(args)
382 .with_effective_canister_id(take_args.canister_id)
383 .build()
384 }
385
386 pub fn load_canister_snapshot(
390 &self,
391 load_args: &LoadCanisterSnapshotArgs,
392 ) -> impl 'agent + AsyncCall<Value = ()> {
393 let args = LoadCanisterSnapshotArgs {
394 sender_canister_version: None,
395 ..load_args.clone()
396 };
397 self.update(MgmtMethod::LoadCanisterSnapshot.as_ref())
398 .with_arg(args)
399 .with_effective_canister_id(load_args.canister_id)
400 .build()
401 }
402
403 pub fn list_canister_snapshots(
405 &self,
406 canister_id: &Principal,
407 ) -> impl 'agent + AsyncCall<Value = (Vec<Snapshot>,)> {
408 self.update(MgmtMethod::ListCanisterSnapshots.as_ref())
409 .with_arg(CanisterIdRecord {
410 canister_id: *canister_id,
411 })
412 .with_effective_canister_id(*canister_id)
413 .build()
414 }
415
416 pub fn delete_canister_snapshot(
418 &self,
419 delete_args: &DeleteCanisterSnapshotArgs,
420 ) -> impl 'agent + AsyncCall<Value = ()> {
421 self.update(MgmtMethod::DeleteCanisterSnapshot.as_ref())
422 .with_arg(delete_args)
423 .with_effective_canister_id(delete_args.canister_id)
424 .build()
425 }
426
427 pub fn read_canister_snapshot_metadata(
429 &self,
430 metadata_args: &ReadCanisterSnapshotMetadataArgs,
431 ) -> impl 'agent + AsyncCall<Value = (ReadCanisterSnapshotMetadataResult,)> {
432 self.update(MgmtMethod::ReadCanisterSnapshotMetadata.as_ref())
433 .with_arg(metadata_args)
434 .with_effective_canister_id(metadata_args.canister_id)
435 .build()
436 }
437
438 pub fn read_canister_snapshot_data(
440 &self,
441 data_args: &ReadCanisterSnapshotDataArgs,
442 ) -> impl 'agent + AsyncCall<Value = (ReadCanisterSnapshotDataResult,)> {
443 self.update(MgmtMethod::ReadCanisterSnapshotData.as_ref())
444 .with_arg(data_args)
445 .with_effective_canister_id(data_args.canister_id)
446 .build()
447 }
448
449 pub fn upload_canister_snapshot_metadata(
451 &self,
452 metadata_args: &UploadCanisterSnapshotMetadataArgs,
453 ) -> impl 'agent + AsyncCall<Value = (UploadCanisterSnapshotMetadataResult,)> {
454 self.update(MgmtMethod::UploadCanisterSnapshotMetadata.as_ref())
455 .with_arg(metadata_args)
456 .with_effective_canister_id(metadata_args.canister_id)
457 .build()
458 }
459
460 pub fn upload_canister_snapshot_data(
462 &self,
463 data_args: &UploadCanisterSnapshotDataArgs,
464 ) -> impl 'agent + AsyncCall<Value = ()> {
465 self.update(MgmtMethod::UploadCanisterSnapshotData.as_ref())
466 .with_arg(data_args)
467 .with_effective_canister_id(data_args.canister_id)
468 .build()
469 }
470
471 pub fn canister_metadata(
473 &self,
474 args: &CanisterMetadataArgs,
475 ) -> impl 'agent + SyncCall<Value = (CanisterMetadataResult,)> {
476 self.query(MgmtMethod::CanisterMetadata.as_ref())
477 .with_arg(args)
478 .with_effective_canister_id(args.canister_id)
479 .build()
480 }
481}