Transfer icp from user account to specific account


i would like to implement a backend canister func (motoko) for func caller(user) to transfer ICP to one specific account to purchase the service provided by my cansiter
i didnt find any sample code related to this. All sample codes are about the canister self or the canister owner to transfer ICP to target account or using dfx to call ledger func to transfer
The ledger transfer function can not set ‘from’ account, but only subaccount. seems it is impossible to do in cansiter due to no approve(). Shall I implement it in frontend to let user directly call NNS ledger to transfer after login? I havnt tried this. please advise how or any alternative solution. Thanks.

u can only do that from user’s frontend.
The user will click a pay function or something
then the backend will give to him the account that he’s supposed to pay to
The user then will transfer ICP to that account he just received from backend
Hope this helps.

1 Like

Correct, at least until we have ICRC-2. Only an account’s owner can initiate transfers

1 Like

any timeline ICRC-2 available. thx

We have a library here for that purpose:

It is for any ICRC-1 token and doesn’t require icrc-2. Nor does it require the user to handle and notify the service about transaction ids. It is purely balance based. The user pays to a subaccount of the service where the subaccount id is the principal of the user. And then calls notify() on the service and the service will pick up the deposit and credit the user. It handles withdrawal of unused credit, too.

Unfortunately it is not well documented and there’s no frontend code to support it. It was just made to try out the icrc-1 interface.

ICRC-2 should be put up to an NNS vote within 2-3 weeks, after which implementation will start. I wouldn’t expect it sooner than in 2 months. Also, the team that will work on this currently is very overloaded with outstanding work, so this may get pushed back a bit

thanks. does it work?
As @Severin said, only an account’s owner can initiate transfer. i believe the owner of any transfer call
in cansiter func wont be the func caller. so, currently no way to do it in backend canister for my needs.

Sorry, no, it doesn’t provide a pull/approve. You have to implement it in the frontend as @kayicp said. But with icrc-2/approve you also have to do something in the frontend, namely opening the approval and setting the amount. That’s the same amount of work for the frontend as making a deposit. The library is just there to make tracking deposits, credit, used and unused balances easier. And your backend can internally execute notify() automatically as part of the call that your user makes to the backend service, so no need to make a separate call to a notify() function. All in all, you still have to do something in the frontend, just less and it simplifies things.

Appreciated for explanation.

Hi, I would love to ask a question regarding this.
lets say the canister name is “comp”, and comp has users(callers).
In my code, i call the transfer function from the ledger to transfer icp.

Once the frontend integrates the function and a user(caller) transfers the token, will it work??
Since the args doesn’t take the from field.
or Will the ledger canister assume its the comp canister thats calling the function and not the caller??
How can I go about it??
Since we want users to be able to deposit their icp and withdraw anytime.


public type TransferArg = {
    to : Account;
    fee : ?Nat;
    memo : ?Blob;
    from_subaccount : ?Blob;
    created_at_time : ?Nat64;
    amount : Nat;