Insufficient funds error

Hi,

I have a getBalance method as follows:

getBalance details
public shared ({ caller }) func getBalance() : async Text {
    let account : AccountIdentifier = await IcpLedger.account_identifier({ owner = caller; subaccount = null});
    let accountBalanceArgs : AccountBalanceArgs = { account };
    let balance = await IcpLedger.account_balance(accountBalanceArgs);
    return "Balance: " # Nat64.toText(balance.e8s);
};

Calling it from the terminal, I get

(“Balance: 10000000000”)

Then I have an initBalance method as follows:

initBalance details
public shared ({ caller }) func initBalance() : async Result.Result<IcpLedger.BlockIndex, Text> {
        let me : AccountIdentifier = await IcpLedger.account_identifier({ owner = Principal.fromText("6qx4h-7o65n-z7e5h-m6pmk-yhkmp-isl3g-sv7xp-5eg2b-k7pib-g5iwv-3qe"); subaccount = null});
        let meTransferArgs : IcpLedger.TransferArgs = {
            memo = 1;
            amount = {e8s = 1_000_000_000};
            fee = {e8s = 10_000};
            to = me;
            from_subaccount = null;
            created_at_time = null;
        };

        try {
            let transferResult : IcpLedger.TransferResult = await IcpLedger.transfer(meTransferArgs);
            switch (transferResult) {
                case (#Err(e)) {
                    return #err("Couldn't transfer funds: " # debug_show (e));
                };
                case (#Ok(blockIndex)) { 
                    return #ok(blockIndex) 
                };
            };
        } catch (error) {
            return #err("Reject message: " # Error.message(error));
        };
    };

Basically it’s a simple transfer, but I get the following response:

(
variant {
err = “Couldn't transfer funds: #InsufficientFunds({balance = {e8s = 0}})”
},
)

How come??

Thanks

Can you share the transfer method. It could be youre transferring from the wrong owner or subaccount

getBalance returns the amount of tokens the caller owns. initBalance attempts to transfer from the canister’s balance

@cosmasken I’m using

import IcpLedger "canister:icp_ledger";

where icp_ledger is the ICP ledger canister.

@Severin that would indeed make sense. How can I transfer from the caller from a canister ?
EDIT: Hmm… You’re going to say you can’t transfer on behalf or another account, unless using ICRC2, right? So I have to use icrc2_approve, then icrc2_transfer ?

Transfer to the canister first then subaccount of the canister

Correct, you need to call icrc2_approve from the user, and then use icrc2_transfer_from from the canister

Thanks a lot @Severin! I still have a few doubts which I’ve grouped in another thread if you want to chime in :wink:

I’m in a Typescript frontend canister and I have an AuthClient that is authorized by InternetIdentity.
How do I icrc2_approve form that user ?