Skip to main content

Canister declarations

The DFX auto-generated bindings for canisters had some issues in versions of DFX lower than 0.16.0 that made the developer experience with PicJS less than ideal. If you are using DFX v0.16.0 or higher then you can ignore this guide.

There are four files generated by DFX for a canister. To use a counter canister as an example:

  • counter.did.js - Exports the canister's Candid as a JavaScript object. The idlFactory and init exports in this file are not included in the counter.did.d.ts file.

    export const idlFactory = ({ IDL }) => {
    const Counter = IDL.Service({
    // redacted...
    });
    return Counter;
    };

    export const init = ({ IDL }) => {
    return [IDL.Nat];
    };
  • counter.did.d.ts - Exports the canister's Candid as a TypeScript interface. This file is missing the idlFactory and init exports that are present in the counter.did.js file.

    import type { Principal } from '@dfinity/principal';
    import type { ActorMethod } from '@dfinity/agent';

    export interface Counter {
    // redacted...
    }

    export interface _SERVICE extends Counter {}
  • index.d.ts - Exports TypeScript interfaces for actor creation utilities. This file re-exports the idlFactory, but not the init declarations from clock.did.ts.

    import type {
    ActorSubclass,
    HttpAgentOptions,
    ActorConfig,
    Agent,
    } from '@dfinity/agent';
    import type { Principal } from '@dfinity/principal';
    import type { IDL } from '@dfinity/candid';

    import { _SERVICE } from './counter.did';

    export declare const idlFactory: IDL.InterfaceFactory;
    export declare const canisterId: string;

    export declare interface CreateActorOptions {
    // redacted...
    }

    export declare const createActor: (
    canisterId: string | Principal,
    options?: CreateActorOptions,
    ) => ActorSubclass<_SERVICE>;

    export declare const counter: ActorSubclass<_SERVICE>;
  • index.js - Exports TypeScript interfaces for actor creation utilities. This file re-exports the idlFactory, but not the init declarations from clock.did.js and also exports an auto-created canister actor which will throw exceptions outside of the browser due to window.location missing.

    import { Actor, HttpAgent } from '@dfinity/agent';

    import { idlFactory } from './counter.did.js';
    export { idlFactory } from './counter.did.js';

    export const canisterId =
    process.env.CANISTER_ID_COUNTER || process.env.COUNTER_CANISTER_ID;

    export const createActor = (canisterId, options = {}) => {
    // redacted...
    };

    export const counter = createActor(canisterId);

To summarize the problems:

  • index.js and index.d.ts are missing the init export and also export an auto-created actor that breaks outside of the browser.
  • counter.did.js and counter.did.d.ts are missing the init and idlFactory exports.

Fixes for these issues are already merged into Candid, but they need to be released and included in DFX before we can leverage them. To work around these issues for now, we can add two new files to export the missing items:

  • index.js

    export { idlFactory, init } from '../../declarations/counter.did';
  • index.d.ts

    import { IDL } from '@dfinity/candid';
    import { Actor } from '@hadronous/pic';
    import { _SERVICE } from '../../declarations/counter.did';

    export declare const idlFactory: IDL.InterfaceFactory;
    export declare const init: ({ IDL }: { IDL: IDL }) => IDL.Type[];