Cross Canister Calls Not Serialising Principal Correctly
blutooth opened this issue · comments
counter.rs
#[derive(CandidType, Deserialize)]
struct OwnerResult {
canister_id: candid::Principal,
}
#[query]
fn owner() -> OwnerResult{
unsafe {
OwnerResult{
canister_id: candid::Principal::management_canister()
}
}
}
service : {
"owner": () -> (OwnerResult) query;
}
In another file, I can't just return CounterCanister::owner().await.0.canister_id:
It's expecting principal to be a vec of bytes, rather than a principal. The following code below compiles but then returns an error at runtime...
service : {
"owner": () -> (principal) query;
}
#[import(canister = "counter_rs")]
struct CounterCanister;
#[query]
async fn owner() -> candid::Principal {
let b = CounterCanister::owner().await.0;
let (a,): (candid::Principal,) = decode_args(&b.canister_id).unwrap();
a
}
Are there any workarounds currently?
I believe the root cause of the error is that you're trying to interpret bytes of a Principal as if it was a Candid message containing a single value: a principal. This sounds like the same thing, but it's not: a candid message has additional structure (type table, number of items in the message, etc.), principal is just bytes.
I'm not sure what the exact type of CounterCanister::owner().await.0
in your case, but calling Principal::from_slice
should solve your problem, something like
let a = candid::Principal::from_slice(&b.canister_id);
@blutooth, I'm closing this issue, for now. Please reopen it if my advice above didn't help you.