diff --git a/src/console/src/factory/mission_control.rs b/src/console/src/factory/mission_control.rs index c4a90487a..464215e87 100644 --- a/src/console/src/factory/mission_control.rs +++ b/src/console/src/factory/mission_control.rs @@ -11,8 +11,8 @@ use crate::types::ledger::Fee; use candid::{Nat, Principal}; use junobuild_shared::constants::shared::CREATE_MISSION_CONTROL_CYCLES; use junobuild_shared::ic::api::id; -use junobuild_shared::mgmt::cmc::create_canister_install_code_with_cmc; -use junobuild_shared::mgmt::ic::create_canister_install_code; +use junobuild_shared::mgmt::cmc::create_and_install_canister_with_cmc; +use junobuild_shared::mgmt::ic::create_and_install_canister_with_ic_mgmt; use junobuild_shared::mgmt::types::cmc::SubnetId; use junobuild_shared::mgmt::types::ic::CreateCanisterInitSettingsArg; use junobuild_shared::types::interface::CreateMissionControlArgs; @@ -69,7 +69,7 @@ async fn create_mission_control_wasm( }; let mission_control_id = if let Some(subnet_id) = subnet_id { - create_canister_install_code_with_cmc( + create_and_install_canister_with_cmc( &create_settings_arg, &wasm_arg, CREATE_MISSION_CONTROL_CYCLES, @@ -77,7 +77,7 @@ async fn create_mission_control_wasm( ) .await } else { - create_canister_install_code( + create_and_install_canister_with_ic_mgmt( &create_settings_arg, &wasm_arg, CREATE_MISSION_CONTROL_CYCLES, diff --git a/src/console/src/factory/orbiter.rs b/src/console/src/factory/orbiter.rs index b8bd177e3..57f6952d8 100644 --- a/src/console/src/factory/orbiter.rs +++ b/src/console/src/factory/orbiter.rs @@ -12,8 +12,8 @@ use crate::types::state::{Segment, SegmentKey, StorableSegmentKind}; use candid::{Nat, Principal}; use junobuild_shared::constants::shared::CREATE_ORBITER_CYCLES; use junobuild_shared::ic::api::id; -use junobuild_shared::mgmt::cmc::create_canister_install_code_with_cmc; -use junobuild_shared::mgmt::ic::create_canister_install_code; +use junobuild_shared::mgmt::cmc::create_and_install_canister_with_cmc; +use junobuild_shared::mgmt::ic::create_and_install_canister_with_ic_mgmt; use junobuild_shared::mgmt::types::cmc::SubnetId; use junobuild_shared::mgmt::types::ic::CreateCanisterInitSettingsArg; use junobuild_shared::types::interface::CreateOrbiterArgs; @@ -57,7 +57,7 @@ async fn create_orbiter_wasm( }; let result = if let Some(subnet_id) = subnet_id { - create_canister_install_code_with_cmc( + create_and_install_canister_with_cmc( &create_settings_arg, &wasm_arg, CREATE_ORBITER_CYCLES, @@ -65,7 +65,12 @@ async fn create_orbiter_wasm( ) .await } else { - create_canister_install_code(&create_settings_arg, &wasm_arg, CREATE_ORBITER_CYCLES).await + create_and_install_canister_with_ic_mgmt( + &create_settings_arg, + &wasm_arg, + CREATE_ORBITER_CYCLES, + ) + .await }; match result { diff --git a/src/console/src/factory/satellite.rs b/src/console/src/factory/satellite.rs index f12489a63..fc16e249f 100644 --- a/src/console/src/factory/satellite.rs +++ b/src/console/src/factory/satellite.rs @@ -12,8 +12,8 @@ use crate::types::state::{Segment, SegmentKey, StorableSegmentKind}; use candid::{Nat, Principal}; use junobuild_shared::constants::shared::CREATE_SATELLITE_CYCLES; use junobuild_shared::ic::api::id; -use junobuild_shared::mgmt::cmc::create_canister_install_code_with_cmc; -use junobuild_shared::mgmt::ic::create_canister_install_code; +use junobuild_shared::mgmt::cmc::create_and_install_canister_with_cmc; +use junobuild_shared::mgmt::ic::create_and_install_canister_with_ic_mgmt; use junobuild_shared::mgmt::types::cmc::SubnetId; use junobuild_shared::mgmt::types::ic::CreateCanisterInitSettingsArg; use junobuild_shared::types::interface::{CreateSatelliteArgs, InitStorageArgs}; @@ -63,7 +63,7 @@ async fn create_satellite_wasm( }; let result = if let Some(subnet_id) = subnet_id { - create_canister_install_code_with_cmc( + create_and_install_canister_with_cmc( &create_settings_arg, &wasm_arg, CREATE_SATELLITE_CYCLES, @@ -71,7 +71,12 @@ async fn create_satellite_wasm( ) .await } else { - create_canister_install_code(&create_settings_arg, &wasm_arg, CREATE_SATELLITE_CYCLES).await + create_and_install_canister_with_ic_mgmt( + &create_settings_arg, + &wasm_arg, + CREATE_SATELLITE_CYCLES, + ) + .await }; match result { diff --git a/src/libs/shared/src/mgmt/cmc.rs b/src/libs/shared/src/mgmt/cmc.rs index d98ef9b44..9f1878c97 100644 --- a/src/libs/shared/src/mgmt/cmc.rs +++ b/src/libs/shared/src/mgmt/cmc.rs @@ -91,11 +91,39 @@ fn convert_principal_to_sub_account(principal_id: &[u8]) -> Subaccount { /// # Returns /// - `Ok(Principal)`: On success, returns the `Principal` ID of the newly created canister. /// - `Err(String)`: On failure, returns an error message. -pub async fn create_canister_install_code_with_cmc( +pub async fn create_and_install_canister_with_cmc( create_settings_arg: &CreateCanisterInitSettingsArg, wasm_arg: &WasmArg, cycles: u128, subnet_id: &SubnetId, +) -> Result { + let canister_id = create_canister_with_cmc(create_settings_arg, cycles, subnet_id).await?; + + install_code(canister_id, wasm_arg, CanisterInstallMode::Install) + .await + .map_err(|_| JUNO_ERROR_CMC_INSTALL_CODE_FAILED.to_string())?; + + Ok(canister_id) +} + +/// Creates a new canister on a specific subnet using the Cycles Minting Canister (CMC). +/// +/// # Arguments +/// - `create_settings_arg`: Initial settings for the canister (controllers, compute allocation, etc.) +/// - `cycles`: The number of cycles to deposit into the new canister +/// - `subnet_id`: The ID of the subnet where the canister should be created +/// +/// # Returns +/// - `Ok(Principal)`: On success, returns the Principal ID of the newly created canister +/// - `Err(String)`: On failure, returns an error message describing what went wrong +/// +/// # Errors +/// - CMC call failures (network issues, invalid arguments, etc.) +/// - CMC canister creation failures (insufficient cycles, subnet unavailable, etc.) +pub async fn create_canister_with_cmc( + create_settings_arg: &CreateCanisterInitSettingsArg, + cycles: u128, + subnet_id: &SubnetId, ) -> Result { let cmc = Principal::from_text(CMC).unwrap(); @@ -111,22 +139,12 @@ pub async fn create_canister_install_code_with_cmc( .await .decode_candid::(); - match result { - Err(error) => Err(format!( - "{} ({})", - JUNO_ERROR_CMC_CALL_CREATE_CANISTER_FAILED, &error - )), - Ok(result) => match result { - Err(err) => Err(format!("{JUNO_ERROR_CMC_CREATE_CANISTER_FAILED} ({err})")), - Ok(canister_id) => { - let install = - install_code(canister_id, wasm_arg, CanisterInstallMode::Install).await; - - match install { - Err(_) => Err(JUNO_ERROR_CMC_INSTALL_CODE_FAILED.to_string()), - Ok(_) => Ok(canister_id), - } - } - }, - } + result + .map_err(|error| { + format!( + "{} ({})", + JUNO_ERROR_CMC_CALL_CREATE_CANISTER_FAILED, &error + ) + })? + .map_err(|err| format!("{JUNO_ERROR_CMC_CREATE_CANISTER_FAILED} ({err})")) } diff --git a/src/libs/shared/src/mgmt/ic.rs b/src/libs/shared/src/mgmt/ic.rs index cb23dd9ef..d78f35155 100644 --- a/src/libs/shared/src/mgmt/ic.rs +++ b/src/libs/shared/src/mgmt/ic.rs @@ -27,12 +27,38 @@ use ic_cdk::management_canister::{ /// # Returns /// - `Ok(Principal)`: On success, returns the `Principal` ID of the newly created canister. /// - `Err(String)`: On failure, returns an error message. -pub async fn create_canister_install_code( +pub async fn create_and_install_canister_with_ic_mgmt( create_settings_arg: &CreateCanisterInitSettingsArg, wasm_arg: &WasmArg, cycles: u128, ) -> Result { - let record = create_canister_with_extra_cycles( + 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) +} + +/// Creates a new canister using the IC management canister. +/// +/// # Arguments +/// - `create_settings_arg`: Initial settings for the canister (controllers, compute allocation, etc.) +/// - `cycles`: The number of cycles to deposit into the new canister +/// +/// # Returns +/// - `Ok(Principal)`: On success, returns the Principal ID of the newly created canister +/// - `Err(String)`: On failure, returns an error message describing what went wrong +/// +/// # Errors +/// - Management canister call failures (network issues, invalid arguments, etc.) +/// - Canister creation failures (insufficient cycles, etc.) +pub async fn create_canister_with_ic_mgmt( + create_settings_arg: &CreateCanisterInitSettingsArg, + cycles: u128, +) -> Result { + let create_result = create_canister_with_extra_cycles( &CreateCanisterArgs { settings: create_canister_settings(create_settings_arg), }, @@ -40,23 +66,15 @@ pub async fn create_canister_install_code( ) .await; - match record { - Err(err) => Err(format!( + let result = create_result.map_err(|err| { + format!( "{} ({})", JUNO_ERROR_CANISTER_CREATE_FAILED, &err.to_string() - )), - Ok(record) => { - let canister_id = record.canister_id; + ) + })?; - let install = install_code(canister_id, wasm_arg, CanisterInstallMode::Install).await; - - match install { - Err(_) => Err(JUNO_ERROR_CANISTER_INSTALL_CODE_FAILED.to_string()), - Ok(_) => Ok(canister_id), - } - } - } + Ok(result.canister_id) } /// Asynchronously installs code on a specified canister.