Bindings Structure
The tool writes the files in the specified output directory with the following structure. Assuming you have a <service-name>.did
file, <service-name>
is used for the generated files.
Note: The generated code imports elements from
@icp-sdk/core
. You must install it, see js.icp.build/core.
<service-name>.ts
Section titled “<service-name>.ts”This file contains the TypeScript wrapper for the Candid JS bindings generated in declarations/<service-name>.did.js
. It offers a more idiomatic and type-safe TypeScript interface over the Candid JS bindings.
Set the output.actor.disabled
option to true
to skip generating this file.
The generated file exposes:
- The types, that is the TypeScript representation of the Candid types.
- The
<service-name>Interface
type, that is the TypeScript interface for the service. - The
<service-name>
class, that is the TypeScript class for the service. - The
createActor
function, that creates a new instance of the actor.
This section contains the TypeScript representation of the Candid types. It contains all the types that are defined as Candid types in the .did
file. To make the generated types more idiomatic, some types are transformed into more TypeScript-friendly types.
Options
Section titled “Options”Candid options are represented as a union of the inner option type and null
:
type MyType = opt text;
type MyType = string | null;
Nested/Recursive Options
Section titled “Nested/Recursive Options”Nested or recursive options are represented as union of the Some
and None
types, where Some
and None
are defined as:
interface Some<T> { __kind__: "Some"; value: T;}interface None { __kind__: "None";}
Nested
Section titled “Nested”type MyType = opt opt text;type MyType2 = opt opt opt text;
type MyType = Some<string | null> | None;type MyType2 = Some<Some<string | null> | None> | None;
Recursive
Section titled “Recursive”type A = B;type B = opt A;
type A = B;type B = Some<A> | None
Record Fields with Options
Section titled “Record Fields with Options”Record fields that have an option type are optional fields in the TypeScript type:
type MyType = record { my_field : opt text;}
type MyType = { my_field?: string;};
Variants
Section titled “Variants”Candid variants without type parameters are represented as TypeScript enums:
type MyType = variant { A; B;}
enum MyType { A, B,}
Variants with Types
Section titled “Variants with Types”Variants that contain types in their fields are represented as TypeScript unions:
type MyType = variant { A : text; B; C : record { my_field : text; };}
type MyType = | { __kind__: "A"; A: string } | { __kind__: "B"; B: null } | { __kind__: "C"; C: { my_field: string } };
<service-name>Interface
type
Section titled “<service-name>Interface type”This type is the TypeScript interface for the service. It contains all the methods that are defined in the Candid service in the .did
file.
For example, a Candid service will be represented as:
service : () -> { greet : (name : text) -> text;};
interface helloWorldInterface = { greet: (name: string) => Promise<string>;};
<service-name>
class
Section titled “<service-name> class”This class implements the <service-name>Interface
type. It can be instantiated with the createActor
function.
For example, a Candid service will be represented as:
service : () -> { greet : (name : text) -> text;};
class HelloWorld implements helloWorldInterface { constructor( private actor: ActorSubclass<_SERVICE>, ) {} async greet(arg0: string): Promise<string> { const result = await this.actor.greet(arg0); return result; }}
Where the _SERVICE
type is imported from the declarations/<service-name>.did.d.ts
file and the ActorSubclass
type is imported from the @icp-sdk/core/agent
module.
createActor
function
Section titled “createActor function”Creates an instance of the <service-name>
class.
Here’s an example of how to use the generated client:
import { createActor } from "./bindings/hello_world";
const actor = createActor("your-canister-id");const greeting = await actor.greet("World");
The signature of the createActor
function is:
interface CreateActorOptions { agent?: Agent; agentOptions?: HttpAgentOptions; actorOptions?: ActorConfig;}
function createActor(canisterId: string, options: CreateActorOptions = {}): <service-name>Interface;
If both the agent
and agentOptions
are provided, the agentOptions
will be ignored and the agent
will be used. Otherwise, a new HttpAgent
will be created using the agentOptions
if provided.
If provided, the actorOptions
will be passed to the Actor.createActor
function. Otherwise, the default options will be used.
declarations/
Section titled “declarations/”This folder contains the actual Candid JS bindings. It generates the same bindings that the dfx generate
command was generating.
See the Migrating page for more information on how to migrate from dfx generate
.
declarations/<service-name>.did.d.ts
Section titled “declarations/<service-name>.did.d.ts”This file is used in TypeScript projects to type the Candid JS bindings generated in declarations/<service-name>.did.js
.
declarations/<service-name>.did.js
Section titled “declarations/<service-name>.did.js”This file contains the actual Candid JS bindings, that allow encoding and decoding JS objects to and from Candid.
Optional files
Section titled “Optional files”<service-name>.d.ts
Section titled “<service-name>.d.ts”This file contains the same TypeScript types as <service-name>.ts
. It is typically used to add to LLMs’ contexts’ to give knowledge about what types are available in the service. Set the output.actor.interfaceFile
option to true
to generate this file.