Skip to content

akup/multicanister

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

74 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ICR (internet computer registry) - Monorepo Multicanister Orchestration Project

Project helps to deploy and orchestrate multicanister environment for IC.

This monorepo provides a comprehensive multicanister orchestration framework for the Internet Computer: it bundles a TypeScript-based Pocket IC Core Service that wraps Pocket IC exposes REST endpoints to upload, list, and manage WASM binaries with full metadata (branch, tag, commit, hash, and corruption state), and an ICR CLI tool that leverages DFX to build canisters, calculate SHA-256 checksums, and automate fresh installs, upgrades, or reinstallations via the Pocket IC Core API. Together, these components enable robust version tracking, integrity validation, and seamless deployment workflows for complex multi-canister applications.

Pocket IC Core Service

It uses 'core' word because multicanister orchestration framework consists of core canisters and environment, that are specified at core.json and environment.json. Core canisters are:

  • registry-factory - it contains registry of deployed canisters and orchestrate them taking care of scaling by sharding and replicating. Moreover it provides routing framework that helps canisters to communicate in a location transparancy style: canisters should know only service names, but not the canisterId to communicate.
  • internet-identity - is default ii canister
  • candid ui - is a default CandidUI Canister that helps to rapidly test deployed canisters with a simple UI

Pocket IC Core Service helps to manage core canisters, that are deployed to a wrapped Pocket IC. All other canisters that are listed in environment.json will be managed and deployed via registry-factory, that is part of the core canisters.

This workflow makes seemless inhouse development and production environments.

Installation

Install pnpm

npm i pnpm -g
pnpm install

Load submodules

Before you start to develop load submodules:

git submodule sync
git submodule update --init --recursive

Install PocketIc

According to instruction for your platform https://github.com/dfinity/pocketic

Add it to your .profile

export POCKET_IC_BIN="$PATH_TO_DOWNLOADED_BIN/pocket-ic"

and source it

Then you can run in terminal in any folder:

$POCKET_IC_BIN --help

Also it uses pic-js modified to use live mode. This changes are subject for PR. It is referenced by gitsubmodule picjs.

Install ic-wasm

Copy latest ic-wasm release from https://github.com/dfinity/ic-wasm/releases to your ~/bin/ic-wasm. Make it executable:

chmod +x ~/bin/ic-wasm

and add ~/bin to your path.

Check it is already in you path:

echo $PATH | grep -o "$HOME/bin"

if not add it to your ~/.profile:

export PATH="$HOME/bin:$PATH"

and apply it:

source ~/.profile

On mac give permissions to run to didc at your System settings->Confidentaility and security->Security

Check it is installed:

ic-wasm --version

Install didc

Copy latest didc release from https://github.com/dfinity/candid/releases to your ~/bin/didc. Make it executable and it to your path as you've done with ic-wasm.

Check it is installed:

didc --version

Install wasm-opt

It is needed to build Candid submodule. Just install node version globally:

npm install -g wasm-opt

Project structure

|- canisters           - here are all canisters (core and applications that should be deployed by core)
|- innerDfxProjects    - here we reference dfx tooling canisters that are needed in core deployment
|- typescript
| |- _eslint-config    - turborepo default eslint configs (referenced by other projects)
| |- _prettier-config  - turborepo default prettier configs (referenced by other projects)
| |- _eslint-config    - turborepo default typescript configs (referenced by other projects)
| |- icr-cli           - Command line tool to build canisters and upload to remote PIC and factories
| |- pic               - Clone of Pic JS with some upgrades (extending during development) not merged yet to @dfinity/pic
| |- pocket-ic-core    - Wrapper around PIC, helps to manage core canisters via http interface and runs the PIC
|- libs                - contains old project templates (unused and will be cleared)

Submodules

innerDfxProjects folder contains Candid submodule that is configured to sparse tools/ui folder. So only CandidUI Canister is cloned.

Important Note: It will fail to build unless you remove or comment out the candid patch in your root Cargo.toml. For example:

# [patch.crates-io.candid]
# path = "../../rust/candid"

picjs folder contains pic-js modified to use live mode. This changes are subject for PR.

During build ICR CLI tool will go throwgh all folders to find dfx.json files, all of them will be applyed in the build from folder leafs, to the root. Core canisters can be used from inner dfx projects, so submodules can be added and deployed as part of core or environment like it is done with CandidUI Canister.

Declarative Canister Initialization

For canisters that require initialization arguments (like SNS canisters), you can specify them directly in dfx.json using the init_args field. The ICR CLI tool will automatically encode these arguments using didc before deployment.

To handle dependencies between canisters (e.g., sns_root needing the ID of sns_governance), you can use placeholders in the init_args string. The CLI will resolve these placeholders with the actual canister IDs during deployment.

Placeholder Format: {{canisterId:role_name}} where role_name is the key from core.json.

Example dfx.json:

{
  "canisters": {
    "sns_root": {
      "type": "custom",
      "candid": "canisters/sns/did/sns-root-canister.wasm.did",
      "wasm": "canisters/sns/sns-root-canister.wasm",
      "init_args": "(record { governance_canister_id = principal \"{{canisterId:sns_governance}}\"; ledger_canister_id = principal \"{{canisterId:sns_ledger}}\"; })"
    },
    "sns_governance": {
      "type": "custom",
      "candid": "canisters/sns/did/sns-governance-canister.wasm.did",
      "wasm": "canisters/sns/sns-governance-canister.wasm"
    },
    "sns_ledger": {
        "type": "custom",
        "candid": "canisters/sns/did/ic-icrc1-ledger.wasm.did",
        "wasm": "canisters/sns/ic-icrc1-ledger.wasm"
    }
  }
}

Build SNS canisters

Compile the SNS canisters (governance, root, swap, ICRC-1 ledger/index) and write their .wasm and .did files exactly to the paths declared in dfx.json.

pnpm run sns:build

During development you can build a subset:

SNS_SET=sns_governance,sns_root,sns_ledger pnpm run sns:build

How it works: sources are taken from the local ./ic submodule; WASM is optionally optimized with ic-wasm shrink (set NO_SHRINK=1 to skip).

Starting the Services

Before start follow instructions of preparing Pocket IC Core Service and ICR CLI

You can start services for development from the root folder. First start the Pocket IC Core service locally, or deploy it to your clowd according to instructions

pnpm dev-pocket-ic-core

Then you can start ICR CLI and point it to your Core Service (--pics, --pocket-server option or in POCKET_IC_CORE_URL environment varable)

Default POCKET_IC_CORE_URL is contained at .\typescript\icr-cli\.env

pnpm dev-icr-cli

It will build and upload to PIC canisters according to .\core.json

By default Pocket IC core starts PIC gateway on 4944 port. You can access canisters at

http://localhost:4944/?canisterId=${your_canister_id}

For example if you start with default core.json, you will see following log of pnpm dev-icr-cli:

{
  candid_ui: {
    canisterIds: [ '$candid_ui_canister_id' ],
    wasmHash: 'b07c0258fad470be5e364ebf28e3ad5c7a59d8bf0e5820481fa8c3cc6c6cb565',
    branch: 'main',
    tag: 'latest',
    commit: 'latest',
    corrupted: false
  },
  factory: {
    canisterIds: [ '$factory_canister_id' ],
    wasmHash: '0eaefbc57820879f2af89452f5a7e812cfa47522d8b03329bd6197c80dcce33b',
    branch: 'main',
    tag: 'latest',
    commit: 'latest',
    corrupted: false
  }
}

Just use $candid_ui_canister_id to access default candid ui: http://localhost:4944/?canisterId=${candid_ui_canister_id}

Developing factory and icr-cli

As factory can.did changes during development, you should update declarations at typescript/icr-cli/src/declarations/factory. It could be done simply by running from typescript/icr-cli folder:

npm run gen-factory-idl

It will replace factory.did.js factory.did.d.ts based on can.did file specified at dfx.json for factory (canisters/factory/can.did)

factoryService at typescript/icr-cli/src/services utilizes this declarations and is also subject to change on factory interface updates.

About

No description, website, or topics provided.

Resources

License

Stars

5 stars

Watchers

1 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors