Generate actor type declarations (dfx generate) without creating a canister first

Some of the canisters I create are generated dynamically, meaning that I am not creating all of them at the onset of my application running. However, I would like to have the candid type declarations available to my front-end without having to create a canister (as I am only going to then delete this canister afterwards).

The error that I currently receive when attempting to generate actor declarations without creating a canister is:

Error: Failed to determine id for canister 'test'.
Caused by: Failed to determine id for canister 'test'.
Cannot find canister id. Please issue 'dfx canister create test'.


This is because dfx generate tries to make things easy and uses this template, using the canister name and requiring the canisterId (environment variable) in order to bake a ready-to-go actor for you on the frontend.

This comment in the sdk repo details this exact “forced creation”, saying

“This is just to display an error if trying to generate before creating the canister.”

On line 7 of the generated file, we have

// CANISTER_ID is replaced by webpack based on node environment
export const canisterId = process.env.TEST_CANISTER_ID;

and then at the end of the file we have the fully-baked actor

/**
 * A ready-to-use agent for the test canister
 * @type {import("@dfinity/agent").ActorSubclass<import("./test.did.js")._SERVICE>}
 */
  export const test = createActor(canisterId);

I would like to be able to generate declaration files for my front-end without having deployed an actor, and hence it would be great to have a way of running dfx generate to product an index.js file that does NOT have the lines of code mentioned above :point_up: (lines 6-7) and lines (34-38) includes, thus removing the dependency on requiring the canisterId and that a canister be created for that actor.

While the aforementioned features of the generate command are great for a newcomer to the IC, they become more restrictive when building more dynamic, multi-canister applications, or even when wanting to import your application canister id(s) through a different method or environment variable.

A potential solution would be to add a flag like --headless, that allows the developer to generate declarations for an actor (that is defined in the dfx.json) without requiring that a canister be deployed for that actor. This would then still be backwards-compatible with the existing repositories and hello world examples.

Then I can run dfx generate --headless (for all of my actors), or dfx generate --headless test for one of my actors (my test actor).

4 Likes

I actually already have a ticket assigned to me that covers this scenario. I’ll try to loop you in on the review to make sure it really covers your case.

3 Likes

Looking forward to seeing that in dfx.

In the meantime, with some help from @infu I put together a script that does the following 3 steps (note I’ve inserted “test” for the actor name, and <copy_target> as a fill in the blank in step 3).

  1. Create the declarations folder for my actor:
    mkdir -p src/declarations/test

  2. Generate the IDL using the moc tool:
    $(dfx cache show)/moc --idl $(vessel sources 2>>/dev/null) src/test/Test.mo -o src/declarations/test/test.did

    Note: (The 2>>dev/null is optional, this just pipes the [INFO] output of installing package dependencies to /dev/null).

  3. Copy the declarations where I need them
    rm -rf <copy_target> && cp -r src/declarations <copy_target>
4 Likes

Hey just checking in on this, I was also reading through this similar post -

…which seems to have a Rust-specific solution and was wondering if this could be generalized.

No progress, sorry. I got drawn away to more urgent matters. It’s still on my plate but it’s hard to find the time.

IIRC (it’s been almost 2 months since I last looked at it) it shouldn’t be too hard to generalise, but with Motoko there was some way the code panicked, which would require some more investigation into what the Motoko compiler expects as arguments. Thank you for linking it to this thread!

For reference, it looks like this is the open GitHub issue

Those reading this thread - go upvote this issue if this feature is important to you.

Thanks for making progress on this @Severin

Tagging @saikatdas0790 as I know he’s also interested in this feature.

1 Like

Is this still being worked on?

This got lost in the stream of other things, thanks for bringing it up again. I detailed an approach to the solution in this PR comment, and I’ll try again to get this prioritised soon. Feel free to ping this every so often, totally after the saying “The squeaky wheel gets the grease”.

Note to future self: ticket

3 Likes

This will be fully resolved with this PR

4 Likes