Skip to content

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.

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:

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.

Candid options are represented as a union of the inner option type and null:

Candid
type MyType = opt text;
TypeScript
type MyType = string | null;

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";
}
Candid
type MyType = opt opt text;
type MyType2 = opt opt opt text;
TypeScript
type MyType = Some<string | null> | None;
type MyType2 = Some<Some<string | null> | None> | None;
Candid
type A = B;
type B = opt A;
TypeScript
type A = B;
type B = Some<A> | None

Record fields that have an option type are optional fields in the TypeScript type:

Candid
type MyType = record {
my_field : opt text;
}
TypeScript
type MyType = {
my_field?: string;
};

Candid variants without type parameters are represented as TypeScript enums:

Candid
type MyType = variant {
A;
B;
}
TypeScript
enum MyType {
A,
B,
}

Variants that contain types in their fields are represented as TypeScript unions:

Candid
type MyType = variant {
A : text;
B;
C : record {
my_field : text;
};
}
TypeScript
type MyType =
| { __kind__: "A"; A: string }
| { __kind__: "B"; B: null }
| { __kind__: "C"; C: { my_field: string } };

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:

Candid
hello_world.did
service : {
greet : (name : text) -> (text);
};
TypeScript
hello_world.ts
interface helloWorldInterface = {
greet: (name: string) => Promise<string>;
};

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:

Candid
hello_world.did
service : {
greet : (name : text) -> (text);
};
TypeScript
hello_world.ts
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.

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.

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.

This file is used in TypeScript projects to type the Candid JS bindings generated in declarations/<service-name>.did.js. The exported types are:

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:

Candid
hello_world.did
service : {
greet : (text) -> (text);
};
TypeScript
declarations/hello_world.did.d.ts
import type { ActorMethod } from '@icp-sdk/core/agent';
import type { IDL } from '@icp-sdk/core/candid';
import type { Principal } from '@icp-sdk/core/principal';
export interface _SERVICE { 'greet' : ActorMethod<[string], string> }
export declare const idlFactory: IDL.InterfaceFactory;
export declare const init: (args: { IDL: typeof IDL }) => IDL.Type[];

You can use it to type the Actor instance with the methods of the service declared in the .did file:

import { type _SERVICE, idlFactory } from "./bindings/hello_world/declarations/hello_world.did";
const actor = Actor.createActor<_SERVICE>( idlFactory, {
canisterId: "your-canister-id",
});
const greeting = await actor.greet("World"); // greet method is now available on the actor instance and typed
console.log(greeting);

Additionally, all the types used in the service class are exported as well:

Candid
hello_world.did
type GreetArgs = record {
name : text;
};
service : {
greet : (GreetArgs) -> (text);
};
TypeScript
declarations/hello_world.did.d.ts
import type { ActorMethod } from '@icp-sdk/core/agent';
import type { IDL } from '@icp-sdk/core/candid';
import type { Principal } from '@icp-sdk/core/principal';
export interface GreetArgs { 'name' : string } // <- exported type
export interface _SERVICE { 'greet' : ActorMethod<[GreetArgs], string> }
export declare const idlFactory: IDL.InterfaceFactory;
export declare const init: (args: { IDL: typeof IDL }) => IDL.Type[];

The function signature is:

const idlFactory: IDL.InterfaceFactory;

See IDL.InterfaceFactory.

The function signature is:

const init: (args: { IDL: typeof IDL }) => IDL.Type[];

See IDL.Type.

Note: This type is only exported if the output.declarations.rootExports option is set to true.

The type signature is:

const idlService: IDL.ServiceClass;

See IDL.ServiceClass.

Note: This type is only exported if the output.declarations.rootExports option is set to true.

The type signature is:

const idlInitArgs: IDL.Type[];

See IDL.Type.

This file contains the actual Candid JS bindings, that allow encoding and decoding JS objects to and from Candid. This file exports two functions:

Typically passed to the Actor.createActor function:

import { idlFactory } from "./bindings/hello_world/declarations/hello_world.did";
const actor = Actor.createActor(idlFactory, {
canisterId: "your-canister-id",
});

Used to type the initialization arguments of the service.

You can use the output.declarations.rootExports option to control whether to export the root types in the declarations JS file.

Note: This type is only exported if the output.declarations.rootExports option is set to true.

This type is the same service class that the idlFactory function returns.

Additionally, if the output.declarations.rootExports option is set to true, all the types used in the service class are exported as constants from the declarations JS file.

Example:

Candid
hello_world.did
type GreetArgs = record {
name : text;
};
service : {
greet : (GreetArgs) -> (text);
};
TypeScript
declarations/hello_world.did.js
import { IDL } from '@icp-sdk/core/candid';
export const GreetArgs = IDL.Record({ 'name' : IDL.Text });
export const idlService = IDL.Service({
'greet' : IDL.Func([GreetArgs], [IDL.Text], []),
});
export const idlInitArgs = [];
export const idlFactory = ({ IDL }) => {
const GreetArgs = IDL.Record({ 'name' : IDL.Text });
return IDL.Service({ 'greet' : IDL.Func([GreetArgs], [IDL.Text], []) });
};
export const init = ({ IDL }) => { return []; };

Note: This type is only exported if the output.declarations.rootExports option is set to true.

This type is the same types that the init function returns.

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.