Skip to content

refactor(motoko): canister: import + --actor-env-alias for inter-canister calls (pub-sub, parallel_calls) - #1452

Merged
marc0olo merged 3 commits into
masterfrom
motoko-actor-env-alias-tier1
Jul 27, 2026
Merged

refactor(motoko): canister: import + --actor-env-alias for inter-canister calls (pub-sub, parallel_calls)#1452
marc0olo merged 3 commits into
masterfrom
motoko-actor-env-alias-tier1

Conversation

@marc0olo

Copy link
Copy Markdown
Member

What

Migrates the two intra-project Motoko examples that make inter-canister calls — parallel_calls and pub-sub — to the typed canister:<name> import backed by moc's --actor-env-alias flag, replacing hand-written actor types + Runtime.envVar + actor(id).

This is the pattern we want to advertise going forward: the target canister's .did supplies the interface (no actor type in Motoko), while the principal stays runtime-resolved from PUBLIC_CANISTER_ID:<name>.

Changes

For each caller (callercallee, subscriberpublisher):

  • Import the target by nameimport Callee "canister:callee" / import Publisher "canister:publisher". The hand-written CalleeActor / PublisherActor types and the Runtime.envVar + actor(id) helpers are gone.
  • Commit the target's Candid interfacecallee/callee.did, publisher/publisher.did, generated via mops generate candid <name>.
  • Wire the import in mops.toml--actor-env-alias <alias> PUBLIC_CANISTER_ID:<name> <did-path> on the caller. Per-canister args replace the global [moc].args, so the global flags (--default-persistent-actors, -W=...) are repeated. Added candid = ... on the target canister so its emitted interface is checked against the committed .did.
  • READMEs — new "How the <target> is resolved" section describing the build/deploy/runtime split, plus an "Updating the Candid interface" note pointing to mops generate candid <name> (matches PR docs(motoko): align Candid regeneration to mops generate candid backend #1450's convention).

Build-time vs runtime (verified against the compiled Wasm)

  • Build (moc): the .did gives the import its static type; the Wasm embeds only the env-var name + the IC env-var syscalls (ic0.env_var_*) — no principal. The build is told no principal and no target environment, so the same Wasm artifact runs in every environment.
  • Deploy (icp-cli): sets the canister env var PUBLIC_CANISTER_ID:<name> to the target's principal — auto-injected for project canisters, overridable per-environment in icp.yaml.
  • Runtime: the canister reads that env var and binds the reference at install/upgrade (verified: the env-var read is reachable only from canister_init/canister_post_upgrade/destabilization, not the update methods), then reuses the principal.

Testing

  • mops build succeeds for both examples, including against the regenerated .did files.
  • Deployed both to a local network: pub-sub's test.sh passes all 4 tests (registration + async callback delivery); parallel_calls sequential/parallel calls succeed.

🤖 Generated with Claude Code

…canister calls

Migrate the two intra-project Motoko examples that make inter-canister
calls to the typed `canister:<name>` import backed by moc's
`--actor-env-alias` flag, instead of hand-written actor types plus
`Runtime.envVar` + `actor(id)`.

For each caller:
- import the target by name (`import Callee "canister:callee"`,
  `import Publisher "canister:publisher"`);
- commit the target's Candid interface (`callee/callee.did`,
  `publisher/publisher.did`), generated via `mops generate candid <name>`;
- wire the import in mops.toml with
  `--actor-env-alias <alias> PUBLIC_CANISTER_ID:<name> <did-path>`
  (per-canister args replace the global [moc].args, so the global flags
  are repeated), and add `candid = ...` to the target canister so its
  emitted interface is checked against the committed .did.

The .did now supplies the interface, so no actor type is declared in
Motoko. The principal is still resolved from PUBLIC_CANISTER_ID:<name>,
but at install/upgrade time from the canister environment variable — no
principal is compiled into the Wasm, so the same artifact runs in every
environment.

READMEs gain a "How the <target> is resolved" section describing the
build/deploy/runtime split and an "Updating the Candid interface" note
pointing to `mops generate candid <name>`.

Verified: both examples build with `mops build`; deployed locally and
`test.sh` passes for pub-sub and the sequential/parallel calls succeed
for parallel_calls.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@marc0olo
marc0olo requested review from a team as code owners July 27, 2026 18:31
…aller in PocketIC test

The multi-subnet test set PUBLIC_CANISTER_ID:callee after installing the
caller. That worked while the caller read the variable lazily per call via
Runtime.envVar, but with the `canister:callee` import + --actor-env-alias the
variable is bound at canister init — installing the caller with it unset traps
("envvar `PUBLIC_CANISTER_ID:callee` not set").

Create both canisters first, install the callee, set the caller's environment
variable, then install the caller. Verified locally: 90/90 sequential and
90/90 parallel calls succeed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors the Motoko pub-sub and parallel_calls examples to use typed canister:<name> imports wired via moc --actor-env-alias, replacing manual Runtime.envVar + actor(id) plumbing and committing the target canisters’ Candid interfaces for compile-time typing.

Changes:

  • Migrated inter-canister references to import <X> "canister:<x>" in the call-site canisters (subscriber, caller).
  • Added committed .did files for the target canisters and configured mops.toml to type imports via --actor-env-alias and to check emitted Candid against the committed .did.
  • Updated READMEs and the multi_subnet PocketIC harness to reflect the new “resolve-at-init from env var” binding model.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
motoko/pub-sub/subscriber/app.mo Replaces runtime actor construction with typed canister:publisher import and direct calls.
motoko/pub-sub/README.md Documents the new typed import + --actor-env-alias resolution model and Candid regeneration command.
motoko/pub-sub/publisher/publisher.did Adds committed publisher Candid interface used to type the subscriber’s import.
motoko/pub-sub/mops.toml Adds candid = ... for publisher and per-canister args for subscriber with --actor-env-alias.
motoko/parallel_calls/README.md Documents the new typed import + --actor-env-alias resolution model and Candid regeneration command.
motoko/parallel_calls/multi_subnet/src/main.rs Adjusts PocketIC install/settings order so env var is set before caller install/init binding.
motoko/parallel_calls/mops.toml Adds per-canister args for caller with --actor-env-alias and candid = ... for callee.
motoko/parallel_calls/caller/app.mo Replaces runtime actor construction with typed canister:callee import and direct calls.
motoko/parallel_calls/callee/callee.did Adds committed callee Candid interface used to type the caller’s import.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread motoko/pub-sub/README.md Outdated
…l-flow diagram

`subscriber.updateCount` returns () (Candid `func -> () oneway`), so it is a
fire-and-forget message with no awaitable reply. Labeling it "async callback"
conflated asynchronous message delivery with an async return type and
contradicted the code comment. Address Copilot review feedback.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@marc0olo
marc0olo merged commit db0ca74 into master Jul 27, 2026
10 checks passed
@marc0olo
marc0olo deleted the motoko-actor-env-alias-tier1 branch July 27, 2026 19:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants