How to upgrade canister by canister_id and wasm file

i want to upgrade the canister created by code, dfx deploy is not working, any way to resolve it?

Any answers ? :thinking: :thinking: :thinking:

Got the same question. I tried following but hit the error Cannot find canister <canister_id>

dfx canister --network ic --no-wallet install <canister_id> --all --mode reinstall

still uses the rust agent which dfx uses but it works last time I check:

use ic_agent::{
    Agent, 
    ic_types::Principal, 
    identity::{Identity, BasicIdentity},
    agent::http_transport::ReqwestHttpReplicaV2Transport
};
use ic_utils::interfaces::ManagementCanister;
use ic_utils::interfaces::management_canister::builders::InstallMode;
use ic_utils::call::AsyncCall;
use ring::signature::Ed25519KeyPair;
use candid::{Encode,Decode,CandidType,};
use std::{time::Duration};
use std::{
    fs::File,
};
use std::io::Read;
use garcon::Delay;
use tokio::runtime::Runtime;


fn waiter_with_timeout(duration: Duration) -> Delay {
    Delay::builder().timeout(duration).build()
}
fn expiry_duration() -> Duration {
    // 5 minutes is max ingress timeout
    Duration::from_secs(60 * 5)
}

async fn put_code_on_the_canister(can_id: &Principal, agent: &Agent, filename: &str, mode: InstallMode, canister_init_raw_put_bytes: Vec<u8>) {
    let mut f = File::open(filename).unwrap();
    let mut wasmmodbytes: Vec<u8> = Vec::<u8>::new();
    println!("wasm_bytes_len: {:?}", f.read_to_end(&mut wasmmodbytes).unwrap() );
    let management = ManagementCanister::create(&agent);
    println!("{:?}",
        management.install_code(can_id, wasmmodbytes.as_slice())
            .with_mode(mode)
            .with_raw_arg(canister_init_raw_put_bytes) 
            .call_and_wait(waiter_with_timeout(expiry_duration()))
            .await.unwrap()
    );
}

fn main() {
    let can_id = Principal::from_text("the-canister-principal").unwrap();

    let sk: [u8; 32] = [put 32 bytes here];
    let pub_key: [u8; 32] = [put 32 bytes here];
    let caller: BasicIdentity = BasicIdentity::from_key_pair(
        Ed25519KeyPair::from_seed_and_public_key(
            &sk,
            &pub_key
        ).unwrap()
    );
    let agent: Agent = Agent::builder()
        .with_transport(ReqwestHttpReplicaV2Transport::create("https://ic0.app").unwrap())
        .with_identity(caller)
        .build().unwrap();
    agent.set_root_key(vec![48, 129, 130, 48, 29, 6, 13, 43, 6, 1, 4, 1, 130, 220, 124, 5, 3, 1, 2, 1, 6, 12, 43, 6, 1, 4, 1, 130, 220, 124, 5, 3, 2, 1, 3, 97, 0, 129, 76, 14, 110, 199, 31, 171, 88, 59, 8, 189, 129, 55, 60, 37, 92, 60, 55, 27, 46, 132, 134, 60, 152, 164, 241, 224, 139, 116, 35, 93, 20, 251, 93, 156, 12, 213, 70, 217, 104, 95, 145, 58, 12, 11, 44, 197, 52, 21, 131, 191, 75, 67, 146, 228, 103, 219, 150, 214, 91, 155, 180, 203, 113, 113, 18, 248, 71, 46, 13, 90, 77, 20, 80, 95, 253, 116, 132, 176, 18, 145, 9, 28, 95, 135, 185, 136, 131, 70, 63, 152, 9, 26, 11, 170, 174]).unwrap();

    let rt = Runtime::new().unwrap();
    rt.block_on(async {

        put_code_on_the_canister(
            &can_id, 
            &agent, 
            "/path/for/the/wasm/canister.wasm", 
            InstallMode::Upgrade, 
            Vec::<u8>::new()
        ).await;

    });
}


2 Likes

Thanks a lot for the share! Ultimately I definitely have to automate the task in any case, therefore your script is really interesting

1 Like

Thanks for your answer, but how to got the “sk” and “pub_key” from my identity? I‘m not familiar with rust and motoko.