Can't do cross-canister call in init function

It looks like there is a workaround for this limitation. Just discovered it.

You can use ic-cron library to schedule a task inside init() function and then immediately process that task in the first ever heartbeat of your canister.

implement_cron!();

#[derive(CandidType, Deserialize)]
pub enum CronTaskType {
    Init(Principal);
};

#[init]
fn init(external_canister: Principal) {
    cron_enqueue(
        CronTaskType::Init(external_canister), 
       
        // these options represent an immediate one-time task
        SchedulingOptions {
            delay_nano: 0,
            interval_nano: 0,
            iterations: Iterations::Exact(1),
        }
    );
}

#[heartbeat]
fn tick() {
    for task in cron_ready_tasks() {
        let task_type: CronTaskType = task.get_payload().expect("get_payload failed");

        match task_type {
            CronTaskType::Init(external_canister) => {
                spawn(async move {
                    call(external_canister, "test", ()).await
                });
            }
        };
    }
}
4 Likes