ICRC1 transfer error "InsufficientFunds" and balance 0

Hello to everyone. I am using de ckBTC ledger and minter canister, not my own deployed ones. I can create a principal id unique for users and send me ckBTC in mainnet from nns.ic0.app and it works. The problem is in transfer.

I tried to do the transfer_from but that’s not work and also I read about issues using icrc2 and icrc1 together. so I read and understand that to use the icrc1_transfer method I need to set the identity in the Actor creation, so I develop a function to create custom actor for each transfer petitions in my app.

So I receive the same parameters and create the identity, and i check that getting the principal id for that identity and that is all ok. But when i try to transfer, I receive this error “InsufficientFunds: { balance { ‘0’ } }” but when I call to icrc1_balance_of with the same address the response is 2000 so I am realy confused here.

Can anyone explain this to me? I am forgotten something?

Yeah sure im going to send you a message to a suspicious not official channel in telegram instead of receive a response here

A few things that I can think of:

  • The principal that you are using the call function is a different principal that you are using to get the icrc1_balance_of.
  • The token ledger canister that you are calling icrc1_balance_of is different from the token ledger canister that you are trying to do icrc1_transfer on.

And where it is supposed to be defined the token? I only want to use ckBtc, and I transfer it. The balance request response me with satoshi values. Where can i define it in my transfer method?

Do you have any open-source code? Are you using the command line or the Candid UI or something else to test?

I can send you here what I am doing. I am using the candid file from the ckbtc ledger and the ckbtc minter. Using dfx generate and using the Actor created in the index file of each one.

Then I use a minterService to connect controller to actor, and use this flow to create Principal and return his Id, then get the balance and then the transfer:

GENERATE CKBTC ADDRESS

    const newUuid = uuidv4.v4();
    const { uniqueValue, uuid } = req.body;

    const encryptedValue = `${uniqueValue}${uuid || newUuid}`;

    const address: string = await minterService.getCkBtcAddress(encryptedValue);

MINTER SERVICE FUNCTION

 const identity = identityService.createIdentity(uniqueValue);
      const principal: Principal = identity.getPrincipal();
      const address = principal.toText();

Then I query for balance

GET BALANCE

    const decryptedAddress = decrypt(address); //I RETURN IT ENCRYPTED IN THE GET ADDRESS ENDPOINT, THIS WORKS PERFECT
    const principal: Principal = Principal.fromText(decryptedAddress);

    const satoshiBalance: number = await ledgerService.getBalance({ owner: principal, subaccount: [] });

    const ckbtcBalance = satoshiBalance / 100000000;

GET BALANCE FUNCTION

      const balance = await ledger.icrc1_balance_of(payload);

this works fine, it returns 2000n what is the amount i sent before from NNS wallet

TRASNFER


      const { transferPayload, from } = payload;
      const { uuid, uniqueValue } = from; //THIS ARE THE SAME VALUE I GET IN CREATE ADDRESS, AND I USE HERE TO CREATE ANOTHER ACTOR WITH THE IDENTITY FOR THIS ACCOUNT SETTED
      const customLedger = this.ledgerCustomAgent(uuid, uniqueValue);
      const identity: Identity = identityService.createIdentity(`${uniqueValue}${uuid}`);

      const hasBalance = await customLedger.icrc1_balance_of({ owner: identity.getPrincipal(), subaccount: [] });

      const transfer = await customLedger.icrc1_transfer(transferPayload)

THE CREATE CUSTOM AGENT:

    const canisterId = config.ledger.id;

    const identity: Identity = identityService.createIdentity(`${uniqueValue}${uuid}`);
    const agentOptions = {
      identity,
    };

    return createActor(canisterId, { agent: undefined, agentOptions });

If you need something else let me know pls. Otherwise, if you want, i can send you a copy of the repository without sensitive information

with this code it works, i have an encrypt in a wrong place.

1 Like