# Calling ICP ledger canister methods: backend or frontend?

**URL:** <https://forum.dfinity.org/t/calling-icp-ledger-canister-methods-backend-or-frontend/31643>\
**Category:** Developers\
**Created:** [June 7, 2024, 3:29pm UTC](https://forum.dfinity.org/t/calling-icp-ledger-canister-methods-backend-or-frontend/31643 "2024-06-07T15:29:20Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![marcpp](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/marcpp/32/14921_2.png) [@marcpp](https://forum.dfinity.org/u/marcpp)\
**Post date:** [June 7, 2024, 3:29pm UTC](https://forum.dfinity.org/t/calling-icp-ledger-canister-methods-backend-or-frontend/31643/1 "2024-06-07T15:29:20Z")

</div>

This is probably going to sound stupid, but where should I be calling ICP ledger methods from?

Calling them from the backend (via intercanister calls) sounds most secure. But if so, how does that work? If an authenticated user clicks on a “Pay with ICP” button, which calls my backend, which in turn calls the ICP ledger canister, at what point does the user authorize the ICP transfer from the frontend?

Also, if anyone got any insights on [this other question](https://forum.dfinity.org/t/local-replica-of-ledger-canister-throwing-insufficient-funds-error-even-though-the-canister-has-funds/10700/13), I’d be most appreciative! 🙏

Cheers!

---

<div class="post-metadata">

**Author:** ![anon74414410](https://avatars.discourse-cdn.com/v4/letter/a/85f322/32.png) [@anon74414410](https://forum.dfinity.org/u/anon74414410)\
**Post date:** [June 7, 2024, 4:44pm UTC](https://forum.dfinity.org/t/calling-icp-ledger-canister-methods-backend-or-frontend/31643/2 "2024-06-07T16:44:49Z")

</div>

It depends on your application! If users are holding their own crypto in a wallet, many of them will prefer to hold their own funds. “Not your keys, not your crypto” is an adage that many people believe in, and will be reluctant to let a smart contract hold their tokens for them, particularly without high transparency, reproducible builds, and blackhole or dao control of the contract.

---

<div class="post-metadata">

**Author:** ![marcpp](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/marcpp/32/14921_2.png) [@marcpp](https://forum.dfinity.org/u/marcpp)\
**Post date:** [June 7, 2024, 5:02pm UTC](https://forum.dfinity.org/t/calling-icp-ledger-canister-methods-backend-or-frontend/31643/3 "2024-06-07T17:02:26Z")

</div>

It’s a dapp, so no tokens held by the app!  
React frontend, motoko backend, both in separate canisters. Users log in with their Internet Identity.

What is your opinion in this case?

---

<div class="post-metadata">

**Author:** ![asjn3e](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/asjn3e/32/22792_2.png) [@asjn3e](https://forum.dfinity.org/u/asjn3e)\
**Post date:** [June 7, 2024, 6:25pm UTC](https://forum.dfinity.org/t/calling-icp-ledger-canister-methods-backend-or-frontend/31643/4 "2024-06-07T18:25:25Z")

</div>

I suggest you call the approve function of ICP ledger and pass your canister id, so you can transfer funds from user wallet to your canister by calling the ledger from your canister.  
So the flew would be like  
1=\> you call the approve function of ICP ledger from your frontend  
2=\> you call the transfer\_from function from you canister to transfer the ICP.

---

<div class="post-metadata">

**Author:** ![marcpp](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/marcpp/32/14921_2.png) [@marcpp](https://forum.dfinity.org/u/marcpp)\
**Post date:** [June 8, 2024, 6:12pm UTC](https://forum.dfinity.org/t/calling-icp-ledger-canister-methods-backend-or-frontend/31643/5 "2024-06-08T18:12:02Z")

</div>

`icrc2_transfer` could be called periodically from the backend once I have the approval, so that makes sense, thanks.

But about `approve`: how would you call it from the frontend? Would you use the [@dfinity/ledger-icrc](https://github.com/dfinity/ic-js/tree/main/packages/ledger-icrc) library?

I tried using it like so (basically copy/pasted from [this example](https://github.com/dfinity/ic-js/tree/main/packages/ledger-icrc#usage)):

```auto
const agent = await createAgent({
  identity,
  //host: HOST,
});

const { metadata } = IcrcLedgerCanister.create({
  agent,
  canisterId: process.env.CANISTER_ID_ICP_LEDGER,
});

const accountIdentifier = AccountIdentifier.fromPrincipal({
  principal: Principal.fromText(principal),
  //subAccount: principalSubaccount
});

const data = await metadata({});
console.log(data);

```

but got a `Invalid certificate: Signature verification failed` error.  
Any idea what that’s about ?

---

<div class="post-metadata">

**Author:** ![asjn3e](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/asjn3e/32/22792_2.png) [@asjn3e](https://forum.dfinity.org/u/asjn3e)\
**Post date:** [June 9, 2024, 7:46am UTC](https://forum.dfinity.org/t/calling-icp-ledger-canister-methods-backend-or-frontend/31643/6 "2024-06-09T07:46:55Z")

</div>

You can use agaent/js library to make calls to any canister on icp from you frontend.  
Just to mention if you want to call the approve function you should do it with an identity from a wallet or etc, you can also call the function with anonymous identity but i dont think it makes much sense. So if you go through icp wallet documentations you will get some clarity of how to make calls to icp ledger with the principal of that wallet.
