use crate::{
call::{AsyncCall, SyncCall},
Canister,
};
use ic_agent::{export::Principal, Agent};
use ic_management_canister_types::{
CanisterIdRecord, DeleteCanisterSnapshotArgs, LoadCanisterSnapshotArgs,
ProvisionalTopUpCanisterArgs, ReadCanisterSnapshotDataArgs, ReadCanisterSnapshotMetadataArgs,
TakeCanisterSnapshotArgs, UploadCanisterSnapshotDataArgs, UploadCanisterSnapshotMetadataArgs,
UploadChunkArgs,
};
pub use ic_management_canister_types::{
CanisterLogFilter, CanisterLogRecord, CanisterMetadataArgs, CanisterMetadataResult,
CanisterStatusResult, CanisterStatusType, CanisterTimer, ChunkHash, DefiniteCanisterSettings,
FetchCanisterLogsArgs, FetchCanisterLogsResult, LogVisibility, MemoryMetrics,
OnLowWasmMemoryHookStatus, QueryStats, ReadCanisterSnapshotDataResult,
ReadCanisterSnapshotMetadataResult, RenameCanisterRecord, RenameToRecord, Snapshot,
SnapshotDataKind, SnapshotDataOffset, SnapshotMetadataGlobal, SnapshotSource,
StoredChunksResult, UploadCanisterSnapshotMetadataResult, UploadChunkResult,
};
use std::{convert::AsRef, ops::Deref};
use strum_macros::{AsRefStr, Display, EnumString};
pub mod attributes;
pub mod builders;
#[doc(inline)]
pub use builders::{
CreateCanisterBuilder, InstallBuilder, InstallChunkedCodeBuilder, InstallCodeBuilder,
UpdateSettingsBuilder,
};
#[derive(Debug, Clone)]
pub struct ManagementCanister<'agent>(Canister<'agent>);
impl<'agent> Deref for ManagementCanister<'agent> {
type Target = Canister<'agent>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[derive(AsRefStr, Debug, EnumString, Display)]
#[strum(serialize_all = "snake_case")]
pub enum MgmtMethod {
CreateCanister,
InstallCode,
StartCanister,
StopCanister,
CanisterStatus,
DeleteCanister,
DepositCycles,
RawRand,
ProvisionalCreateCanisterWithCycles,
ProvisionalTopUpCanister,
UninstallCode,
UpdateSettings,
UploadChunk,
ClearChunkStore,
StoredChunks,
InstallChunkedCode,
FetchCanisterLogs,
TakeCanisterSnapshot,
LoadCanisterSnapshot,
ListCanisterSnapshots,
DeleteCanisterSnapshot,
ReadCanisterSnapshotMetadata,
ReadCanisterSnapshotData,
UploadCanisterSnapshotMetadata,
UploadCanisterSnapshotData,
EcdsaPublicKey,
SignWithEcdsa,
BitcoinGetBalance,
BitcoinGetUtxos,
BitcoinSendTransaction,
BitcoinGetCurrentFeePercentiles,
BitcoinGetBlockHeaders,
NodeMetricsHistory,
CanisterInfo,
CanisterMetadata,
}
impl<'agent> ManagementCanister<'agent> {
pub fn create(agent: &'agent Agent) -> Self {
Self(
Canister::builder()
.with_agent(agent)
.with_canister_id(Principal::management_canister())
.build()
.unwrap(),
)
}
pub fn from_canister(canister: Canister<'agent>) -> Self {
Self(canister)
}
}
#[doc(hidden)]
#[deprecated(since = "0.42.0", note = "Please use CanisterStatusResult instead")]
pub type StatusCallResult = CanisterStatusResult;
#[doc(hidden)]
#[deprecated(since = "0.42.0", note = "Please use CanisterStatusType instead")]
pub type CanisterStatus = CanisterStatusType;
#[doc(hidden)]
#[deprecated(since = "0.42.0", note = "Please use FetchCanisterLogsResult instead")]
pub type FetchCanisterLogsResponse = FetchCanisterLogsResult;
#[doc(hidden)]
#[deprecated(since = "0.42.0", note = "Please use StoredChunksResult instead")]
pub type StoreChunksResult = StoredChunksResult;
#[doc(hidden)]
#[deprecated(
since = "0.42.0",
note = "Please use ReadCanisterSnapshotMetadataResult instead"
)]
pub type SnapshotMetadata = ReadCanisterSnapshotMetadataResult;
#[doc(hidden)]
#[deprecated(
since = "0.42.0",
note = "Please use ReadCanisterSnapshotDataResult instead"
)]
pub type SnapshotDataResult = ReadCanisterSnapshotDataResult;
#[doc(hidden)]
#[deprecated(
since = "0.42.0",
note = "Please use UploadCanisterSnapshotMetadataResult instead"
)]
pub type CanisterSnapshotId = UploadCanisterSnapshotMetadataResult;
impl<'agent> ManagementCanister<'agent> {
pub fn canister_status(
&self,
canister_id: &Principal,
) -> impl 'agent + AsyncCall<Value = (CanisterStatusResult,)> {
self.update(MgmtMethod::CanisterStatus.as_ref())
.with_arg(CanisterIdRecord {
canister_id: *canister_id,
})
.with_effective_canister_id(canister_id.to_owned())
.build()
.map(|result: (CanisterStatusResult,)| (result.0,))
}
pub fn create_canister<'canister>(&'canister self) -> CreateCanisterBuilder<'agent, 'canister> {
CreateCanisterBuilder::builder(self)
}
pub fn deposit_cycles(&self, canister_id: &Principal) -> impl 'agent + AsyncCall<Value = ()> {
self.update(MgmtMethod::DepositCycles.as_ref())
.with_arg(CanisterIdRecord {
canister_id: *canister_id,
})
.with_effective_canister_id(canister_id.to_owned())
.build()
}
pub fn delete_canister(&self, canister_id: &Principal) -> impl 'agent + AsyncCall<Value = ()> {
self.update(MgmtMethod::DeleteCanister.as_ref())
.with_arg(CanisterIdRecord {
canister_id: *canister_id,
})
.with_effective_canister_id(canister_id.to_owned())
.build()
}
pub fn provisional_top_up_canister(
&self,
canister_id: &Principal,
top_up_args: &ProvisionalTopUpCanisterArgs,
) -> impl 'agent + AsyncCall<Value = ()> {
self.update(MgmtMethod::ProvisionalTopUpCanister.as_ref())
.with_arg(top_up_args)
.with_effective_canister_id(canister_id.to_owned())
.build()
}
pub fn raw_rand(&self) -> impl 'agent + AsyncCall<Value = (Vec<u8>,)> {
self.update(MgmtMethod::RawRand.as_ref())
.build()
.map(|result: (Vec<u8>,)| (result.0,))
}
pub fn start_canister(&self, canister_id: &Principal) -> impl 'agent + AsyncCall<Value = ()> {
self.update(MgmtMethod::StartCanister.as_ref())
.with_arg(CanisterIdRecord {
canister_id: *canister_id,
})
.with_effective_canister_id(canister_id.to_owned())
.build()
}
pub fn stop_canister(&self, canister_id: &Principal) -> impl 'agent + AsyncCall<Value = ()> {
self.update(MgmtMethod::StopCanister.as_ref())
.with_arg(CanisterIdRecord {
canister_id: *canister_id,
})
.with_effective_canister_id(canister_id.to_owned())
.build()
}
pub fn uninstall_code(&self, canister_id: &Principal) -> impl 'agent + AsyncCall<Value = ()> {
self.update(MgmtMethod::UninstallCode.as_ref())
.with_arg(CanisterIdRecord {
canister_id: *canister_id,
})
.with_effective_canister_id(canister_id.to_owned())
.build()
}
pub fn install_code<'canister>(
&'canister self,
canister_id: &Principal,
wasm: &'canister [u8],
) -> InstallCodeBuilder<'agent, 'canister> {
InstallCodeBuilder::builder(self, canister_id, wasm)
}
pub fn update_settings<'canister>(
&'canister self,
canister_id: &Principal,
) -> UpdateSettingsBuilder<'agent, 'canister> {
UpdateSettingsBuilder::builder(self, canister_id)
}
pub fn upload_chunk(
&self,
canister_id: &Principal,
upload_chunk_args: &UploadChunkArgs,
) -> impl 'agent + AsyncCall<Value = (UploadChunkResult,)> {
self.update(MgmtMethod::UploadChunk.as_ref())
.with_arg(upload_chunk_args)
.with_effective_canister_id(*canister_id)
.build()
}
pub fn clear_chunk_store(
&self,
canister_id: &Principal,
) -> impl 'agent + AsyncCall<Value = ()> {
self.update(MgmtMethod::ClearChunkStore.as_ref())
.with_arg(CanisterIdRecord {
canister_id: *canister_id,
})
.with_effective_canister_id(*canister_id)
.build()
}
pub fn stored_chunks(
&self,
canister_id: &Principal,
) -> impl 'agent + AsyncCall<Value = (StoredChunksResult,)> {
self.update(MgmtMethod::StoredChunks.as_ref())
.with_arg(CanisterIdRecord {
canister_id: *canister_id,
})
.with_effective_canister_id(*canister_id)
.build()
}
pub fn install_chunked_code<'canister>(
&'canister self,
canister_id: &Principal,
wasm_module_hash: &[u8],
) -> InstallChunkedCodeBuilder<'agent, 'canister> {
InstallChunkedCodeBuilder::builder(self, *canister_id, wasm_module_hash)
}
pub fn install<'canister: 'builder, 'builder>(
&'canister self,
canister_id: &Principal,
wasm: &'builder [u8],
) -> InstallBuilder<'agent, 'canister, 'builder> {
InstallBuilder::builder(self, canister_id, wasm)
}
pub fn fetch_canister_logs(
&self,
args: &FetchCanisterLogsArgs,
) -> impl 'agent + SyncCall<Value = (FetchCanisterLogsResult,)> {
self.query(MgmtMethod::FetchCanisterLogs.as_ref())
.with_arg(args)
.with_effective_canister_id(args.canister_id)
.build()
}
pub fn take_canister_snapshot(
&self,
take_args: &TakeCanisterSnapshotArgs,
) -> impl 'agent + AsyncCall<Value = (Snapshot,)> {
let args = TakeCanisterSnapshotArgs {
sender_canister_version: None,
..take_args.clone()
};
self.update(MgmtMethod::TakeCanisterSnapshot.as_ref())
.with_arg(args)
.with_effective_canister_id(take_args.canister_id)
.build()
}
pub fn load_canister_snapshot(
&self,
load_args: &LoadCanisterSnapshotArgs,
) -> impl 'agent + AsyncCall<Value = ()> {
let args = LoadCanisterSnapshotArgs {
sender_canister_version: None,
..load_args.clone()
};
self.update(MgmtMethod::LoadCanisterSnapshot.as_ref())
.with_arg(args)
.with_effective_canister_id(load_args.canister_id)
.build()
}
pub fn list_canister_snapshots(
&self,
canister_id: &Principal,
) -> impl 'agent + AsyncCall<Value = (Vec<Snapshot>,)> {
self.update(MgmtMethod::ListCanisterSnapshots.as_ref())
.with_arg(CanisterIdRecord {
canister_id: *canister_id,
})
.with_effective_canister_id(*canister_id)
.build()
}
pub fn delete_canister_snapshot(
&self,
delete_args: &DeleteCanisterSnapshotArgs,
) -> impl 'agent + AsyncCall<Value = ()> {
self.update(MgmtMethod::DeleteCanisterSnapshot.as_ref())
.with_arg(delete_args)
.with_effective_canister_id(delete_args.canister_id)
.build()
}
pub fn read_canister_snapshot_metadata(
&self,
metadata_args: &ReadCanisterSnapshotMetadataArgs,
) -> impl 'agent + AsyncCall<Value = (ReadCanisterSnapshotMetadataResult,)> {
self.update(MgmtMethod::ReadCanisterSnapshotMetadata.as_ref())
.with_arg(metadata_args)
.with_effective_canister_id(metadata_args.canister_id)
.build()
}
pub fn read_canister_snapshot_data(
&self,
data_args: &ReadCanisterSnapshotDataArgs,
) -> impl 'agent + AsyncCall<Value = (ReadCanisterSnapshotDataResult,)> {
self.update(MgmtMethod::ReadCanisterSnapshotData.as_ref())
.with_arg(data_args)
.with_effective_canister_id(data_args.canister_id)
.build()
}
pub fn upload_canister_snapshot_metadata(
&self,
metadata_args: &UploadCanisterSnapshotMetadataArgs,
) -> impl 'agent + AsyncCall<Value = (UploadCanisterSnapshotMetadataResult,)> {
self.update(MgmtMethod::UploadCanisterSnapshotMetadata.as_ref())
.with_arg(metadata_args)
.with_effective_canister_id(metadata_args.canister_id)
.build()
}
pub fn upload_canister_snapshot_data(
&self,
data_args: &UploadCanisterSnapshotDataArgs,
) -> impl 'agent + AsyncCall<Value = ()> {
self.update(MgmtMethod::UploadCanisterSnapshotData.as_ref())
.with_arg(data_args)
.with_effective_canister_id(data_args.canister_id)
.build()
}
pub fn canister_metadata(
&self,
args: &CanisterMetadataArgs,
) -> impl 'agent + SyncCall<Value = (CanisterMetadataResult,)> {
self.query(MgmtMethod::CanisterMetadata.as_ref())
.with_arg(args)
.with_effective_canister_id(args.canister_id)
.build()
}
}