use crate::errors::{
JUNO_ERROR_CANISTER_CREATE_FAILED, JUNO_ERROR_CANISTER_INSTALL_CODE_FAILED,
JUNO_ERROR_CYCLES_DEPOSIT_BALANCE_LOW, JUNO_ERROR_CYCLES_DEPOSIT_FAILED,
JUNO_ERROR_SEGMENT_DELETE_FAILED, JUNO_ERROR_SEGMENT_STOP_FAILED,
};
use crate::mgmt::settings::{create_canister_cycles, create_canister_settings};
use crate::mgmt::types::ic::{CreateCanisterInitSettingsArg, WasmArg};
use crate::types::interface::DepositCyclesArgs;
use candid::Principal;
use ic_cdk::api::canister_cycle_balance;
use ic_cdk::call::CallResult;
use ic_cdk::management_canister::{
create_canister_with_extra_cycles, delete_canister, deposit_cycles as ic_deposit_cycles,
install_code as ic_install_code, stop_canister, update_settings, CanisterId,
CanisterInstallMode, CanisterSettings, CreateCanisterArgs, DeleteCanisterArgs,
DepositCyclesArgs as MgmtDepositCyclesArgs, InstallCodeArgs, StopCanisterArgs,
UpdateSettingsArgs,
};
pub async fn create_and_install_canister_with_ic_mgmt(
create_settings_arg: &CreateCanisterInitSettingsArg,
wasm_arg: &WasmArg,
cycles: u128,
) -> Result<Principal, String> {
let canister_id = create_canister_with_ic_mgmt(create_settings_arg, cycles).await?;
install_code(canister_id, wasm_arg, CanisterInstallMode::Install)
.await
.map_err(|_| JUNO_ERROR_CANISTER_INSTALL_CODE_FAILED.to_string())?;
Ok(canister_id)
}
pub async fn create_canister_with_ic_mgmt(
create_settings_arg: &CreateCanisterInitSettingsArg,
cycles: u128,
) -> Result<Principal, String> {
let create_result = create_canister_with_extra_cycles(
&CreateCanisterArgs {
settings: create_canister_settings(create_settings_arg),
},
create_canister_cycles(cycles),
)
.await;
let result = create_result.map_err(|err| {
format!(
"{} ({})",
JUNO_ERROR_CANISTER_CREATE_FAILED,
&err.to_string()
)
})?;
Ok(result.canister_id)
}
pub async fn install_code(
canister_id: Principal,
WasmArg { wasm, install_arg }: &WasmArg,
mode: CanisterInstallMode,
) -> CallResult<()> {
let arg = InstallCodeArgs {
mode,
canister_id,
wasm_module: wasm.clone(),
arg: install_arg.clone(),
};
ic_install_code(&arg).await
}
pub async fn update_canister_controllers(
canister_id: Principal,
controllers: Vec<Principal>,
) -> CallResult<()> {
let arg = UpdateSettingsArgs {
canister_id,
settings: CanisterSettings {
controllers: Some(controllers),
compute_allocation: None,
memory_allocation: None,
freezing_threshold: None,
reserved_cycles_limit: None,
log_visibility: None,
wasm_memory_limit: None,
wasm_memory_threshold: None,
environment_variables: None,
},
};
update_settings(&arg).await
}
pub async fn deposit_cycles(
DepositCyclesArgs {
destination_id,
cycles,
}: DepositCyclesArgs,
) -> Result<(), String> {
let balance = canister_cycle_balance();
if balance < cycles {
return Err(format!(
"{JUNO_ERROR_CYCLES_DEPOSIT_BALANCE_LOW} (balance {balance}, {cycles} to deposit)"
));
}
let result = ic_deposit_cycles(
&MgmtDepositCyclesArgs {
canister_id: destination_id,
},
cycles,
)
.await;
match result {
Err(err) => Err(format!(
"{} ({})",
JUNO_ERROR_CYCLES_DEPOSIT_FAILED,
&err.to_string()
)),
Ok(_) => Ok(()),
}
}
pub async fn stop_segment(canister_id: CanisterId) -> Result<(), String> {
let result = stop_canister(&StopCanisterArgs { canister_id }).await;
match result {
Err(err) => Err(format!(
"{} ({})",
JUNO_ERROR_SEGMENT_STOP_FAILED,
&err.to_string()
)),
Ok(_) => Ok(()),
}
}
pub async fn delete_segment(canister_id: CanisterId) -> Result<(), String> {
let result = delete_canister(&DeleteCanisterArgs { canister_id }).await;
match result {
Err(err) => Err(format!(
"{} ({})",
JUNO_ERROR_SEGMENT_DELETE_FAILED,
&err.to_string()
)),
Ok(_) => Ok(()),
}
}