canic-core 0.110.35

Canic — a canister orchestration and management toolkit for the Internet Computer
Documentation
//! Module: infra::ic::mgmt::status_settings
//!
//! Responsibility: perform raw Canister-history, status and settings management calls.
//! Does not own: status policy, deployment orchestration, or public DTO shaping.
//! Boundary: extends `MgmtInfra` with status and settings effects.

use crate::{
    cdk::candid::Principal,
    infra::ic::{
        IcInfraError,
        call::{Call, CallBuilder, CallResult},
    },
};

use super::{
    MgmtInfra,
    types::{
        InfraCanisterIdRecord, InfraCanisterInfoArgs, InfraCanisterInfoResult,
        InfraCanisterStatusResult, InfraUpdateSettingsArgs,
    },
};

impl MgmtInfra {
    /// Observe the latest history entry through a replicated management call.
    pub async fn canister_history(canister_pid: Principal) -> Result<CallResult, IcInfraError> {
        Call::bounded_wait(Principal::management_canister(), "canister_info")
            .with_arg(InfraCanisterInfoArgs {
                canister_id: canister_pid,
                num_requested_changes: Some(1),
            })?
            .execute()
            .await
    }

    /// Read one canister's monotonic management-history change count.
    pub async fn canister_history_total_changes(
        canister_pid: Principal,
    ) -> Result<u64, IcInfraError> {
        let args = InfraCanisterInfoArgs {
            canister_id: canister_pid,
            num_requested_changes: None,
        };
        let response = Call::bounded_wait(Principal::management_canister(), "canister_info")
            .with_arg(args)?
            .execute()
            .await?;
        let (info,): (InfraCanisterInfoResult,) = response.candid_tuple()?;
        Ok(info.total_num_changes)
    }

    /// Query the management canister for a canister's status.
    pub async fn canister_status(
        canister_pid: Principal,
    ) -> Result<InfraCanisterStatusResult, IcInfraError> {
        let response = canister_status_call(canister_pid)?.execute().await?;
        let (status,): (InfraCanisterStatusResult,) = response.candid_tuple()?;

        Ok(status)
    }

    /// Quote the same encoded status call without scheduling an outbound effect.
    pub fn canister_status_call_cost(canister_pid: Principal) -> Result<u128, IcInfraError> {
        Ok(canister_status_call(canister_pid)?.cost())
    }

    /// Update canister settings through the management canister.
    pub async fn update_settings(args: &InfraUpdateSettingsArgs) -> Result<(), IcInfraError> {
        Call::unbounded_wait(Principal::management_canister(), "update_settings")
            .with_arg(args.clone())?
            .execute()
            .await?;

        Ok(())
    }
}

fn canister_status_call(canister_pid: Principal) -> Result<CallBuilder<'static>, IcInfraError> {
    Call::bounded_wait(Principal::management_canister(), "canister_status").with_arg(
        InfraCanisterIdRecord {
            canister_id: canister_pid,
        },
    )
}