ERC20-like token on Canton with Typescript backend

I’m working on a relatively simple use case: implementing a TypeScript CLI to deploy an ERC20-like token on Canton and facilitate transfers between three parties. Ideally:

  • Parties should not see each other’s balances.
  • Transfers should be processed as long as the transferred amounts do not exceed available balances.

Current Progress

I started with the Daml/Script tutorial and made the following modifications:

  • Added a third party (Charlie) alongside Alice and Bob.
  • Extended the Daml code to allow transfers of arbitrary amounts using split.

Next Steps

  • Update Transfer.daml to:
    • Create the parties (Alice, Bob, Charlie).
    • Deploy the required smart contracts: AccountFactory, TokenFactory, HoldingFactory, individual accounts, and Instrument (ERC-20 token).
  • Run daml.start, which will:
    • Execute the script, creating parties and deploying infrastructure contracts.
  • Enable CLI commands to:
    • Issue new tokens to any party.
    • Transfer tokens between parties.
    • Retrieve balances (only visible to the account owner).

Questions

  • Is this approach feasible in Canton? Specifically, can the CLI integrate with Canton using the @daml/ledger JavaScript module? The documentation mainly references its use in React, but I assume it can also be used in a backend.
  • How should I reference the smart contracts deployed by the initialization script? My initial thought is to store references in variables and invoke their choices for minting, transferring, and reading balances. Is this the right approach, or is there a better way?

Is this approach feasible in Canton? Specifically, can the CLI integrate with Canton using the @daml/ledger JavaScript module? The documentation mainly references its use in React, but I assume it can also be used in a backend.

You can use @daml/ledger JavaScript library to send commands to the ledger. This library is intended for use in frontends. It can be used in a backend, however for production applications this is not recommended. In particular, ledger reads in production applications should be implemented by querying the PQS.

How should I reference the smart contracts deployed by the initialization script? My initial thought is to store references in variables and invoke their choices for minting, transferring, and reading balances. Is this the right approach, or is there a better way?

The best way to reference the smart contracts you need to interact with in a backend is by querying the ledger. In a production application you should query the PQS (see the answer to the previous question). In a PoC you may use the query method of the @daml/ledger library. For instruments, accounts and the holding factory you can also use Contract Keys (e.g. fetching ContractId of an instrument using fetchByKey function of @daml/ledger library).
If you use Daml Script to initialize the ledger, then you simply cannot pass any reference values from a Daml Script to a backend application. If you initialize the ledger using say @daml/ledger library in your backend application, then you could store references in variables. However, this is not recommended for several reasons. There may be other applications submitting commands to the ledger, which could result in the stale references in your backend. If your backend is restarted, then the values of the variables will be lost and you’ll have no choice but to query the ledger for the reference data you need.

1 Like