Invoice Canister now supports ICRC1 standard


I recently finished worked on the RFPS BNT-2 Invoice Canister bounty which was merged earlier this week into the official examples repo. The major change is support for the ICRC1 token standard which is implemented with a generic variant type called SupportedToken that should also easily support other standards as well as by simply adding the associated canister specific types, adapting methods and actor supertypes.

With the introduction of ICRC1 and this SupportedToken type, it also made it possible to uniformly make the external calls to the token ledger canisters so that adding support for new tokens should be a simple matter of adding the corresponding cases in the relevant switches that invoke SupportedToken when choosing which token kind is being processed.

While I did not get around to implementing E2E encryption of an invoice record’s metadata or using CertifiedData, there is now rudimentary access control in the form of a mutable list of those who are allowed to create invoices to which the proceeds or payments are scoped. There’s also basic refund functionality though it is more accurate to consider it “payment recovery” as it’s only useful for refunding partial payments or payments made after payment has been completed.

It may also be of interest that the zx library is used to start up and configure the local replica showing things like how it is possible to use Javascript to dynamically deploy canisters from the command line (here’s an included example of its console output). There’s also a lot of unit testing as well as E2E testing implemented with Vitetest; I’ve found the identity.js Kyle originally introduced particularly useful when added to a new npm project configured as “type”:“module” for prototyping integration in other dfx projects (esm ftw). The motoko-seller-client has also been updated to allow the user to select between paying between ICP and ICRC1 as well as recover and display the timestamp from the ULID that is now used as an invoice’s id.

Also note that the textual ICRC1 account encoding will need to be updated, however it’s only this file. This was just finalized by the Ledger and Tokenization Working Group, and I’ll push PR updating it as soon as it becomes available.

There’s a lot of documentation. You can start in the readme or DesignDoc or invoice.did.

There are certain things I would have liked to make simpler: such as reusing external canister calls with async*/await*; or only using ICRC1 as ICP mainnet ledger supports the standard (which would setup the implementation of SupportedToken to be better parameterized); or correctly demonstrating using snapshots for TDD (strongly encouraged); there’s also room for adding ckBtc and SNS integration examples, but I’m hoping this can prove helpful without being too imposing on the developer looking to integrate payment processing in their Internet Computer canister dapp.