Failed to deserialize idl blob: Invalid data

Hii there!

I have been stuck at this bug for a long time now, please I’ll love to get help. Here is my code:

pub async fn check_balance(account: String) -> Result<BalanceResponse> {
    let account_identifier = AccountIdentifier::from_hex(&account).map_err(|e| e.to_string())?;

    let balance_args = AccountBalanceArgs {
        account: account_identifier,
    };

    match ic_cdk::api::call::call::<(AccountBalanceArgs,), (Tokens,)>(
        Principal::from_text(ICP_LEDGER_CANISTER_ID).unwrap(),
        "account_balance_dfx",
        (balance_args,),
    )
    .await
    .map_err(|e| e.1)
    {
        Ok((icpts,)) => {
            // Log the balance in e8s (the smallest unit of ICP)
            ic_cdk::println!("Received balance: {} e8s", icpts.e8s());

            Ok(BalanceResponse {
                balance: icpts.e8s(),
                error: None,
            })
        }
        Err(e) => {
            // Log the error
            ic_cdk::println!("Error fetching balance: {:?}", e);

            Ok(BalanceResponse {
                balance: 0,
                error: Some(e),
            })
        }
    }
}

My error: [Canister bd3sg-teaaa-aaaaa-qaaba-cai] Error fetching balance: “Fail to decode argument 0 from table0 to record { account : text }”
Error deserializing blob 0x4449444c036b02bc8a0101c5fed201716c029cbab69c0278c897a79907026e71010000000000000000000001424661696c20746f206465636f646520617267756d656e7420302066726f6d207461626c653020746f207265636f7264207b206163636f756e74203a2074657874207d
Error: Failed to deserialize idl blob: Invalid data.
Caused by: input: 4449444c036b02bc8a0101c5fed201716c029cbab69c0278c897a79907026e710100_00000000000000000001424661696c20746f206465636f646520617267756d656e7420302066726f6d207461626c653020746f207265636f7264207b206163636f756e74203a2074657874207d
table: type BalanceRequest = record { account : text }
type BalanceResponse = record { balance : nat64; error : opt text }
type Transaction = record {
to : text;
from : text;
created_at : nat64;
narration : text;
amount : nat64;
}
type TransferRequest = record { to : text; amount : nat64 }
type TransferResponse = record { block_index : opt nat64; error : opt text }
type Wallet = record {
updated_at : nat64;
balance : nat64;
transaction : vec Transaction;
created_at : nat64;
user_id : text;
address : text;
}
type table0 = variant { 17_724 : table1; 3_456_837 : text }
type table1 = record { 596_483_356 : nat64; 1_932_118_984 : table2 }
type table2 = opt text
wire_type: variant { 17_724 : table1; 3_456_837 : text }, expect_type: record { balance : nat64; error : opt text }
Caused by: Fail to decode argument 0 from table0 to record { balance : nat64; error : opt text }
Caused by: Subtyping error: Type mismatch at /home/runner/.cargo/registry/src/index.crates.io-6f17d22bba15001f/candid-0.10.8/src/de.rs:994

Also, I have tried logging the account_identifier and it logs the exact account identifier I inputed. Thank you.

This is my candid service

 check_icp_balance: (text) -> (BalanceResponse) query;
type BalanceRequest = record {
  account: text; // Account identifier
};

I think the main issue here is that you are expecting the wrong result type, it should be something like ic_cdk::api::call::call::<Result<(Tokens,), (RejectionCode, String)>>

(or CallResult<(Tokens,)> from the ic-cdk crate.

But maybe easier is using the ic_ledger_types crate which has a account_balance method.

also not sure if the AccountIdentifier is going to work like that, this is what i use to convert a principal to AccountIdentifier

use ic_ledger_types::{AccountIdentifier, DEFAULT_SUBACCOUNT};

pub fn principal_to_account_identifier(principal: Principal) -> AccountIdentifier {
    AccountIdentifier::new(&principal, &DEFAULT_SUBACCOUNT)
}
1 Like

Thank you very much @rem.codes . Let me update my code based on your solution.

1 Like