I’m working on a project that involves querying the Blackhole canister to get the cycles balance of another canister in Rust. However, I’m encountering an issue when I try to query the Blackhole canister. The error only occurs when I pass a canister ID that has the Blackhole as a controller. When I pass a canister ID that isn’t controlled by the Blackhole, I get the expected error response.
Error Message:
(variant {Err=record {variant {CanisterError}; "failed to decode canister response as (cycles_assessment_manager::cycles_assessment_manager::CanisterStatusResponse,): Fail to decode argument 0 from table0 to record {
status : variant { Stopped; Stopping; Running };
memory_size : nat;
cycles : nat;
settings : record {
freezing_threshold : nat;
controllers : vec principal;
memory_allocation : nat;
compute_allocation : nat;
};
module_hash : opt vec nat8;
}"}})
Method:
Here is the get_canister_status
method that I’m using to query the Blackhole canister:
#[derive(CandidType, Deserialize, Debug)]
struct CanisterStatusResponse {
status: CanisterStatus,
memory_size: Nat,
cycles: Nat,
settings: CanisterSettings,
module_hash: Option<Vec<u8>>,
}
#[derive(CandidType, Deserialize, Debug)]
enum CanisterStatus {
Running,
Stopping,
Stopped,
}
#[derive(CandidType, Deserialize, Debug)]
struct CanisterSettings {
controllers: Vec<Principal>,
compute_allocation: Nat,
memory_allocation: Nat,
freezing_threshold: Nat,
}
#[derive(candid::CandidType, candid::Deserialize, Debug)]
struct CanisterStatusRequest {
canister_id: Principal,
}
#[update]
async fn get_canister_status(canister_id: Principal) -> CallResult<Vec<u64>> {
let black_hole_canister_id = Principal::from_text("e3mmv-5qaaa-aaaah-aadma-cai").unwrap();
let request = CanisterStatusRequest {
canister_id: canister_id,
};
let status_result: CallResult<(CanisterStatusResponse,)> =
call(black_hole_canister_id, "canister_status", (request,)).await;
ic_cdk::print(format!("Raw response: {:?}", status_result));
match status_result {
Ok((canister_status,)) => {
ic_cdk::print(format!("Decoded response: {:?}", canister_status));
Ok(canister_status.cycles.0.to_u64_digits())
}
Err((rejection_code, message)) => {
if message.contains("InvalidResponse") {
Err((rejection_code, "Received an invalid response from the blackhole canister".to_string()))
} else {
Err((rejection_code, message))
}
}
}
}
Steps to Reproduce:
- Deploy the
cycles_assessment_manager
canister. - Call the
get_canister_status
method with a canister ID that has the Blackhole as a controller. - Observe the error message.
Additional Information:
- The error only occurs when I pass a canister ID that has the Blackhole as a controller.
- When I pass a canister ID that isn’t controlled by the Blackhole, I get the expected error response.
- I am using ic_cdk version 0.11.0
Question:
What could be causing this decoding error, and how can I resolve it?