Use the JavaScript Code Generator

The command daml codegen js generates JavaScript (and TypeScript) that can be used in conjunction with the JavaScript Client Libraries for interacting with a Daml ledger via the HTTP JSON API.

Inputs to the command are DAR files. Outputs are JavaScript packages with TypeScript typings containing metadata and types for all Daml packages included in the DAR files.

The generated packages use the library @daml/types.

Generate and Use Code

In outline, the command to generate JavaScript and TypeScript typings from Daml is daml codegen js -o OUTDIR DAR where DAR is the path to a DAR file (generated via daml build) and OUTDIR is a directory where you want the artifacts to be written.

Here’s a complete example on a project built from the standard “skeleton” template.

1daml new my-proj --template skeleton # Create a new project based off the skeleton template
2cd my-proj # Enter the newly created project directory
3daml build  # Compile the project's Daml files into a DAR
4daml codegen js -o daml.js .daml/dist/my-proj-0.0.1.dar # Generate JavaScript packages in the daml.js directory
  • On execution of these commands:
    • The directory my-proj/daml.js contains generated JavaScript packages with TypeScript typings;
    • The files are arranged into directories;
    • One of those directories will be named my-proj-0.0.1 and will contain the definitions corresponding to the Daml files in the project;
    • For example, daml.js/my-proj-0.0.1/lib/index.js provides access to the definitions for daml/Main.daml;
    • The remaining directories correspond to modules of the Daml standard library;
    • Those directories have numeric names (the names are hashes of the Daml-LF package they are derived from).

To get a quickstart idea of how to use what has been generated, you may wish to jump to the Templates and choices section and return to the reference material that follows as needed.

Primitive Daml Types: @daml/types

To understand the TypeScript typings produced by the code generator, it is helpful to keep in mind this quick review of the TypeScript equivalents of the primitive Daml types provided by @daml/types.


  • Template<T extends object, K = unknown>
  • Choice<T extends object, C, R, K = unknown>


Daml TypeScript TypeScript definition
() Unit {}
Bool Bool boolean
Int Int string
Decimal Decimal string
Numeric ν Numeric string
Text Text string
Time Time string
Party Party string
[τ] List<τ> τ[]
Date Date string
ContractId τ ContractId<τ> string
Optional τ Optional<τ> null | (null extends τ ? [] | [Exclude<τ, null>] : τ)
TextMap τ TextMap<τ> { [key: string]: τ }
(τ₁, τ₂) Tuple₂<τ₁, τ₂> {_1: τ₁; _2: τ₂}


The types given in the “TypeScript” column are defined in @daml/types.


For n-tuples where n ≥ 3, representation is analogous with the pair case (the last line of the table).


The TypeScript types Time, Decimal, Numeric and Int all alias to string. These choices relate to the avoidance of precision loss under serialization over the json-api.


The TypeScript definition of type Optional<τ> in the above table might look complicated. It accounts for differences in the encoding of optional values when nested versus when they are not (i.e. “top-level”). For example, null and "foo" are two possible values of Optional<Text> whereas, [] and ["foo"] are two possible values of type Optional<Optional<Text>> (null is another possible value, [null] is not).

Daml to TypeScript Mappings

The mappings from Daml to TypeScript are best explained by example.


In Daml, we might model a person like this.

1data Person =
2  Person with
3    name: Text
4    party: Party
5    age: Int

Given the above definition, the generated TypeScript code will be as follows.

1type Person = {
2  name: string;
3  party: daml.Party;
4  age: daml.Int;


This is a Daml type for a language of additive expressions.

1data Expr a =
2    Lit a
3  | Var Text
4  | Add (Expr a, Expr a)

In TypeScript, it is represented as a discriminated union.

1type Expr<a> =
2  |  { tag: 'Lit'; value: a }
3  |  { tag: 'Var'; value: string }
4  |  { tag: 'Add'; value: {_1: Expr<a>, _2: Expr<a>} }


Let’s slightly modify the Expr a type of the last section into the following.

1data Expr a =
2    Lit a
3  | Var Text
4  | Add {lhs: Expr a, rhs: Expr a}

Compared to the earlier definition, the Add case is now in terms of a record with fields lhs and rhs. This renders in TypeScript like so.

 1type Expr<a> =
 2  |  { tag: 'Lit2'; value: a }
 3  |  { tag: 'Var2'; value: string }
 4  |  { tag: 'Add'; value: Expr.Add<a> }
 6namespace Expr {
 7  type Add<a> = {
 8    lhs: Expr<a>;
 9    rhs: Expr<a>;
10  }

The thing to note is how the definition of the Add case has given rise to a record type definition Expr.Add.


Given a Daml enumeration like this,

1data Color = Red | Blue | Yellow

the generated TypeScript will consist of a type declaration and the definition of an associated companion object.

1type Color = 'Red' | 'Blue' | 'Yellow'
3const Color = {
4  Red: 'Red',
5  Blue: 'Blue',
6  Yellow: 'Yellow',
7  keys: ['Red','Blue','Yellow'],
8} as const;

Templates and Choices

Here is a Daml template of a basic ‘IOU’ contract.

 1template Iou
 2  with
 3    issuer: Party
 4    owner: Party
 5    currency: Text
 6    amount: Decimal
 7  where
 8    signatory issuer
 9    choice Transfer: ContractId Iou
10      with
11        newOwner: Party
12      controller owner
13      do
14        create this with owner = newOwner

The daml codegen js command generates types for each of the choices defined on the template as well as the template itself.

 1type Transfer = {
 2  newOwner: daml.Party;
 5type Iou = {
 6  issuer: daml.Party;
 7  owner: daml.Party;
 8  currency: string;
 9  amount: daml.Numeric;

Each template results in the generation of a companion object. Here, is a schematic of the one generated from the Iou template [2].

1const Iou: daml.Template<Iou, undefined> & {
2  Archive: daml.Choice<Iou, DA_Internal_Template.Archive, {}, undefined>;
3  Transfer: daml.Choice<Iou, Transfer, daml.ContractId<Iou>, undefined>;
4} = {
5  /* ... */
[2]The undefined type parameter captures the fact that Iou has no contract key.

The exact details of these companion objects are not important - think of them as representing “metadata”.

What is important is the use of the companion objects when creating contracts and exercising choices using the @daml/ledger package. The following code snippet demonstrates their usage.

 1import Ledger from  '@daml/ledger';
 2import {Iou, Transfer} from /* ... */;
 4const ledger = new Ledger(/* ... */);
 6// Contract creation; Bank issues Alice a USD $1MM IOU.
 8const iouDetails: Iou = {
 9  issuer: 'Chase',
10  owner: 'Alice',
11  currency: 'USD',
12  amount: 1000000.0,
14const aliceIouCreateEvent = await ledger.create(Iou, iouDetails);
15const aliceIouContractId = aliceIouCreateEvent.contractId;
17// Choice execution; Alice transfers ownership of the IOU to Bob.
19const transferDetails: Transfer = {
20  newOwner: 'Bob',
22const [bobIouContractId, _] = await ledger.exercise(Transfer, aliceIouContractId, transferDetails);

Observe on line 14, the first argument to create is the Iou companion object and on line 22, the first argument to exercise is the Transfer companion object.