Skip to content

refactor(scripts): use dfx --system-canisters instead of manual NNS setup#630

Open
aterga wants to merge 7 commits intomainfrom
arshavir/use-dfx-system-canisters
Open

refactor(scripts): use dfx --system-canisters instead of manual NNS setup#630
aterga wants to merge 7 commits intomainfrom
arshavir/use-dfx-system-canisters

Conversation

@aterga
Copy link
Copy Markdown
Contributor

@aterga aterga commented Apr 8, 2026

Summary

  • Replace manual installation of system canisters (ICP ledger, ICP index, CMC, Internet Identity) with dfx start --system-canisters, which bootstraps them automatically via PocketIC
  • Bump dfx from 0.25.0 to 0.30.2
  • Remove ~110 lines of install/uninstall/setup functions from orbit script, add ~15-line post-bootstrap helper for ICP transfer and CMC subnet configuration
  • Remove Python/cbor2/crc32 CI dependencies that were only needed for native replica CBOR parsing

Test plan

  • CI deployment-test passes (PocketIC + --system-canisters)
  • CI deployment-test-replica passes (was native replica, now also PocketIC since dfx 0.27.0 removed the native replica)
  • CI prod-deployment-test passes
  • CI e2e-tests passes
  • Integration tests unaffected (separate PocketIC setup via with_icp_features)
  • Verify dfx ledger transfer --identity anonymous successfully credits ICP to current user

🤖 Generated with Claude Code

… NNS setup

Replace manual installation of system canisters (ICP ledger, ICP index,
CMC, Internet Identity) with dfx 0.30.2's --system-canisters flag, which
bootstraps them automatically via PocketIC at well-known NNS canister IDs.

- Bump dfx from 0.25.0 to 0.30.2
- Remove ~110 lines of install/uninstall/setup functions from orbit script
- Add setup_system_canisters_post() for ICP transfer and CMC subnet config
- Update CI workflows to use --system-canisters
- Remove Python/cbor2/crc32 CI dependencies (only needed for native replica)
- Update README and getting-started docs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@aterga aterga requested a review from a team as a code owner April 8, 2026 15:41
aterga and others added 4 commits April 8, 2026 18:07
dfx requires the wasm field for type: "custom" canister definitions,
even when the canisters are bootstrapped by --system-canisters and
won't be deployed via dfx.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
dfx 0.30.2 adds JSDoc comments to generated TypeScript declaration
files from candid documentation comments. No structural changes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…k_list

With --system-canisters, the CMC is configured with the real governance
canister, so only it can call set_authorized_subnetwork_list. Use dfx's
--sender flag to impersonate the governance canister (supported on PocketIC).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
dfx 0.30.2 renamed --sender to --impersonate for canister call.
Upgrade icx-asset from 0.21.0 to 0.29.0 for asset canister compatibility.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Refactors the local dev/CI bootstrapping flow to rely on dfx start --system-canisters (PocketIC-managed system canisters) instead of manually installing NNS/system canisters, and updates docs/CI accordingly.

Changes:

  • Switch local startup commands to dfx start --system-canisters in docs, scripts, and CI.
  • Simplify the orbit --init flow by removing manual system-canister install logic and adding a small post-bootstrap helper (ICP transfer + CMC subnet authorization).
  • Bump dfx version and refresh generated Candid TS types / tool versions.

Reviewed changes

Copilot reviewed 7 out of 9 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
orbit Removes manual NNS/system-canister setup and adds setup_system_canisters_post to finalize PocketIC --system-canisters bootstrap.
dfx.json Drops the cmc canister entry and bumps dfx to 0.30.2.
.github/workflows/tests.yaml Updates CI to start with --system-canisters and removes Python/cbor2/crc32 steps.
README.md Updates local dev instructions to use dfx start --system-canisters.
docs/src/content/docs/developers/getting-started.md Updates the dfx start command to --system-canisters.
package.json Updates e2e deploy script to start dfx with --system-canisters.
scripts/utils.sh Bumps icx-asset install version.
apps/wallet/src/generated/**.did.d.ts Regenerated TS declarations with expanded JSDoc/comments.
Comments suppressed due to low confidence (1)

docs/src/content/docs/developers/getting-started.md:69

  • Step 4 says "Start the Internet Computer replica in the background", but the command shown does not use --background, and --system-canisters starts PocketIC rather than the native replica. Also, the subsequent dfx deploy will attempt to deploy all canisters in dfx.json (including icp_ledger/icp_index/internet_identity), which is likely not the intended local-dev flow now that system canisters are bootstrapped automatically. Consider updating this step to mention PocketIC and to use dfx start --background ... plus ./orbit --init (as in the root README) instead of dfx deploy.
## Step 4: Start the Local Development Server

1. Start the Internet Computer replica in the background:

   ```bash
   dfx start --clean --system-canisters --host 127.0.0.1:4943
  1. Deploy the canisters to the local replica:

    dfx deploy
</details>



---

💡 <a href="/dfinity/orbit/new/main?filename=.github/instructions/*.instructions.md" class="Link--inTextBlock" target="_blank" rel="noopener noreferrer">Add Copilot custom instructions</a> for smarter, more guided reviews. <a href="https://docs.github.com/en/copilot/customizing-copilot/adding-repository-custom-instructions-for-github-copilot" class="Link--inTextBlock" target="_blank" rel="noopener noreferrer">Learn how to get started</a>.

Comment on lines +111 to +112
TOPO="$(curl -s http://localhost:4943/_/topology)"
SUBNET_IDS="$(echo $TOPO | jq -r '.subnet_configs | to_entries | map(select(.value.subnet_kind == "Application"))[] | .key' | sed "s/\(.*\)/principal\\\"\1\\\";/")"
Copy link

Copilot AI Apr 13, 2026

Choose a reason for hiding this comment

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

setup_system_canisters_post hard-codes http://localhost:4943 and assumes PocketIC is immediately ready. In CI (and locally when dfx start --background was just launched), the topology endpoint may not be available yet, causing curl/jq to fail under set -e. Consider deriving the base URL from get_replica_url, using curl -f (and quoting "$TOPO"), and adding a small retry/wait loop (and/or validating SUBNET_IDS is non-empty) before calling set_authorized_subnetwork_list.

Suggested change
TOPO="$(curl -s http://localhost:4943/_/topology)"
SUBNET_IDS="$(echo $TOPO | jq -r '.subnet_configs | to_entries | map(select(.value.subnet_kind == "Application"))[] | .key' | sed "s/\(.*\)/principal\\\"\1\\\";/")"
REPLICA_URL="$(get_replica_url)"
TOPOLOGY_URL="${REPLICA_URL%/}/_/topology"
TOPO=""
for _ in {1..10}; do
if TOPO="$(curl -fsS "$TOPOLOGY_URL")"; then
break
fi
sleep 1
done
if [ -z "$TOPO" ]; then
echo "Failed to fetch topology from $TOPOLOGY_URL" >&2
return 1
fi
SUBNET_IDS="$(printf '%s' "$TOPO" | jq -r '.subnet_configs | to_entries | map(select(.value.subnet_kind == "Application"))[] | .key' | sed 's/\(.*\)/principal\"\1\";/')"
if [ -z "$SUBNET_IDS" ]; then
echo "No application subnet IDs found in topology from $TOPOLOGY_URL" >&2
return 1
fi

Copilot uses AI. Check for mistakes.
Comment on lines +99 to +116
function setup_system_canisters_post() {
# Transfer ICP from anonymous to current user.
# --system-canisters gives the anonymous identity 1 Billion ICP;
# the current identity needs ICP for canister operations.
dfx ledger transfer --identity anonymous \
--amount 10000 \
"$(dfx ledger account-id)" \
--memo 0

# Configure CMC authorized subnet list for canister creation.
# The CMC only allows the governance canister to set authorized subnets,
# so we use --impersonate to impersonate it (supported on PocketIC).
TOPO="$(curl -s http://localhost:4943/_/topology)"
SUBNET_IDS="$(echo $TOPO | jq -r '.subnet_configs | to_entries | map(select(.value.subnet_kind == "Application"))[] | .key' | sed "s/\(.*\)/principal\\\"\1\\\";/")"
dfx canister call rkp4c-7iaaa-aaaaa-aaaca-cai set_authorized_subnetwork_list "(record {
who=null;
subnets=vec {$SUBNET_IDS};
})
"
}

function uninstall_icp_ledger() {
dfx canister delete icp_ledger -y >/dev/null 2>&1 || true
}

function install_icp_ledger() {
if [ "$MINTER_IDENTITY_NAME" == "$WHOAMI" ]; then
echo "You can't run this script as the minter identity. Please run it as a different identity."
exit 1
fi

if ! dfx identity list | grep -q $MINTER_IDENTITY_NAME; then
dfx identity new $MINTER_IDENTITY_NAME --storage-mode plaintext
fi

dfx deploy --specified-id $CANISTER_ID_ICP_LEDGER icp_ledger --argument "
(variant {
Init = record {
minting_account = \"$(dfx ledger account-id --identity $MINTER_IDENTITY_NAME)\";
initial_values = vec {
record {
\"$(dfx ledger account-id)\";
record {
e8s = 1_000_000_000_000 : nat64;
};
};
};
send_whitelist = vec {};
transfer_fee = opt record {
e8s = 10_000 : nat64;
};
token_symbol = opt \"ICP\";
token_name = opt \"Internet Computer\";
}
})
"
}

function setup_icp_ledger() {
uninstall_icp_ledger
install_icp_ledger
}

function uninstall_icp_index() {
dfx canister delete icp_index -y >/dev/null 2>&1 || true
}

function install_icp_index() {
dfx deploy icp_index --specified-id $CANISTER_ID_ICP_INDEX --argument "(record {ledger_id = principal \"$CANISTER_ID_ICP_LEDGER\"})"
}

function setup_icp_index() {
uninstall_icp_index
install_icp_index
}

function uninstall_internet_identity() {
dfx canister delete internet_identity -y >/dev/null 2>&1 || true
}

function install_internet_identity() {
dfx deploy --specified-id $CANISTER_ID_INTERNET_IDENTITY internet_identity
}

function setup_internet_identity() {
uninstall_internet_identity
install_internet_identity
})" --impersonate rrkah-fqaaa-aaaaa-aaaaq-cai
Copy link

Copilot AI Apr 13, 2026

Choose a reason for hiding this comment

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

This function performs a ledger transfer and a privileged CMC call using well-known mainnet canister IDs, but it doesn't enforce that the active dfx network is local/PocketIC. If a user has DFX_NETWORK set to a non-local network, the script will attempt to interact with real canisters (and --impersonate will fail unpredictably). Consider explicitly passing --network local for these calls, or add a guard that aborts unless the network is local.

Copilot uses AI. Check for mistakes.
dfx start --clean --system-canisters --host 127.0.0.1:4943
```

Note that the local replica should be stopped using `dfx stop` rather than by CTRL^C.
Copy link

Copilot AI Apr 13, 2026

Choose a reason for hiding this comment

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

This section now instructs starting PocketIC, but the next sentence still refers to "the local replica". Consider updating the wording to "PocketIC" (or "dfx" process) for consistency with the new --system-canisters guidance.

Suggested change
Note that the local replica should be stopped using `dfx stop` rather than by CTRL^C.
Note that PocketIC should be stopped using `dfx stop` rather than by CTRL^C.

Copilot uses AI. Check for mistakes.
@aterga aterga force-pushed the arshavir/use-dfx-system-canisters branch from 63337c5 to 410d78d Compare April 14, 2026 11:07
The --system-canisters flag deploys a bundled II version whose UI
differs from the release-2025-08-29 version the e2e tests expect.
Re-deploy the project's pinned II after bootstrap so the captcha-based
registration flow is available for e2e tests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@aterga aterga force-pushed the arshavir/use-dfx-system-canisters branch from 410d78d to d2bd528 Compare April 14, 2026 11:30
…d frontend

The upgrade mode preserves the stable memory and frontend assets from
the system-bootstrapped II, which doesn't have the captcha-based
registration UI that the e2e tests expect. Using reinstall does a clean
install with the project's pinned II wasm.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@aterga aterga requested a review from sea-snake April 14, 2026 17:18
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.

2 participants