Payments - Invoice Canister Design Review

Hello! I have a question about the canister. Is it possible to send ICP from one wallet to another using a canister? As in Ethereum

Yes, this canister will allow you to transfer ICP from one canister to another. We will also support ETH once that is available.

1 Like

Is there a method similar to transferFrom?

Thanks for the interface, which data structure would you recommend to store the invoices ?

1 Like

I’ll provide Rust and Motoko examples, but it can be as simple as a [Invoice]. You may want to optimize for lookups by caller, or metadata in the Details, though, so it ultimately will depend on your use case

Is there a method similar to transferFrom as in Ethereum?

No, I’m not adding support for holding multiple balances in the Invoice canister. My design goal is to be more like Stripe than like Ethereum


Thanks for the answer!

Under rated statement.


You mentioned this could be a centralized service with an SNS…what about if it become a system canister of the NNS?

If we could have atomic ICP/SNS/Ledger transactions (sending these tokens with update calls), I imagine the need for this infrastructure would disappear. I wonder then if it would make sense to have it come under the control of the NNS until we can send ledger tokens in update calls atomically.

Of course this idea is dependent on DFINITY committing to implement the sending of ledger tokens in update calls. This would be an amazing DX and I hope it will be considered.

1 Like

Once the BTC integration is done, the financial integrations team will take over the invoice canister, and that’s when they would decide whether to make it a system service


I don’t get how this is different then the ledger canister right now when you say there needs to be protection against double spending. Can’t we already send ICP tokens from principal ID’s already with the ledger canister in Motoko? Otherwise, how is plug and stoic wallet doing it?

Of course this idea is dependent on DFINITY committing to implement the sending of ledger tokens in update calls. This would be an amazing DX and I hope it will be considered.

Why can we not currently send ledger tokens in update calls? Isn’t that just calling the transfer method on the ICP ledger canister?

The pattern that I’ve been using is for the client to transfer tokens to the dapp account and then claim the payment by sending the block/transaction number to the dapp. The dapp confirms the payment and deposits credit to the clients account.

I think the pattern people want is for a transaction to be charged with tokens like on ethereum. You can put tokens in your .buy() function and the dapp can take them or not. Like how cycles work but with the ability for a client to do it. Currently only canisters can send cycles. The issue is that handling all tokens is hard. Eth had to add erc20 to generalize the payment patterns and they lost the native send functionality.

This seems like an easy problem to solve with crypto. Just let the client create a signed withdraw receipt that the remote app can cash(like a check). You have to get fancy to avoid replay, and some data would likely have to be added to the ledger, but I’m confident that all the crypto engineers at DFINITY could figure it out.

And yes, intercanister query would speed things up.

1 Like

So, as it stands, there is no way for a canister to subscribe to the ICP ledger, to be notified of incoming payments? I need the payment receipt functionality for a grant of ours that just got approved. We were under the impression that this was already implemented.


I’ve been struggling with implementing this exact functionality. Has there been any updates on this @kpeacock? Also, your personal site has been super helpful in learning IC development, so thank you.

How exactly would that allow for atomic transactions, I’m not completely following on this? Are system services on each subnet and could work for each canister on that subnet atomically?

Generally, I don’t fully understand if or why not cross-canister transactions on the same subnet are not atomic?

Did you figure out a solution? Is a AWS lambda call not sufficient?

Well, we’ll go with the idiomatic, although highly limited solution. I don’t really understand why it even works. Because the dfx_notify call by the user is still an inter-canister call and according to my understanding, is just as insecure as directly calling from within the initial transfer call, but maybe I’m missing something here.
I have no idea about AWS lambda, but I’d rather not rely on AWS. I’ll just bite the bullet on this one.

It seems like everybody can call the create_invoice function including the anonymous principal.

Would it be an idea to:

  1. Let the actor have an optional parameter of an allowlist of principals who can create an invoices to prevent somebody malicious from filling up the canister with junk invoices.

  2. Have somebody explicitly confirm through a parameter in the create_invoice canister that they meant to pass the anonymous principal to prevent mistakes.

I’d be happy to help out with a pull request if you agree with these changes