Holochain Upgrade 0.4 → 0.5

For existing hApps that are currently using Holochain 0.4, here’s the guide to get you upgraded to 0.5.

The biggest change in Holochain 0.5 is kitsune2, a new wire protocol implementation promises better gossip performance. Kitsune2 is incompatible with the wire protocols used in Holochain 0.4 and prior, so conductors running 0.5 won’t be able to communicate with conductors running earlier releases.

Quick instructions

To upgrade your hApp written for Holochain 0.5, follow these steps:

  1. Update your flake.nix to use the 0.5 version of Holochain. This involves changing the version numbers of two packages. (Depending on the age of your project, you might also need to make extra changes to make it look like the one below.)

     {
       description = "Flake for Holochain app development";
       inputs = {
    -    holonix.url = "github:holochain/holonix?ref=main-0.4";
    +    holonix.url = "github:holochain/holonix?ref=main-0.5";
         nixpkgs.follows = "holonix/nixpkgs";
         flake-parts.follows = "holonix/flake-parts";
    -    playground.url = "github:darksoil-studio/holochain-playground?ref=main-0.4";
    +    playground.url = "github:darksoil-studio/holochain-playground?ref=main-0.5";
       };
       outputs = inputs@{ flake-parts, ... }: flake-parts.lib.mkFlake { inherit inputs; } {
         systems = builtins.attrNames inputs.holonix.devShells;
         perSystem = { inputs', pkgs, ... }: {
           formatter = pkgs.nixpkgs-fmt;
           devShells.default = pkgs.mkShell {
             inputsFrom = [ inputs'.holonix.devShells.default ];
             packages = (with pkgs; [
               nodejs_20
               binaryen
               inputs'.playground.packages.hc-playground
             ]);
             shellHook = ''
               export PS1='\[\033[1;34m\][holonix:\w]\$\[\033[0m\] '
             '';
           };
         };
       };
     }
    

    This will take effect later when you enter a new Nix shell. It’s important to update your Nix flake lockfile at this point, to ensure you benefit from the cache we provide:

    nix flake update && git add flake.nix && nix develop
    
  2. Update your root package.json file with the new package versions, along with a change to accommodate Playground being bundled with Holonix and the local network services being supplied by a new binary:

     {
         "name": "movies-dev",
         "private": true,
         "workspaces": [
             "ui",
             "tests"
         ],
         "scripts": {
             "start": "AGENTS=${AGENTS:-2} BOOTSTRAP_PORT=$(get-port) SIGNAL_PORT=$(get-port) npm run network",
             "network": "hc sandbox clean && npm run build:happ && UI_PORT=$(get-port) concurrently \"npm run start --workspace ui\" \"npm run launch:happ\" \"hc playground\"",
             "test": "npm run build:zomes && hc app pack workdir --recursive && npm run test --workspace tests",
             "launch:happ": "hc-spin -n $AGENTS --ui-port $UI_PORT workdir/movies5.happ",
             "start:tauri": "AGENTS=${AGENTS:-2} BOOTSTRAP_PORT=$(get-port) npm run network:tauri",
    -        "network:tauri": "hc sandbox clean && npm run build:happ && UI_PORT=$(get-port) concurrently \"npm run start --workspace ui\" \"npm run launch:tauri\" \"holochain-playground\"",
    +        "network:tauri": "hc sandbox clean && npm run build:happ && UI_PORT=$(get-port) concurrently \"npm run start --workspace ui\" \"npm run launch:tauri\" \"hc playground\"",
    -        "launch:tauri": "concurrently \"hc run-local-services --bootstrap-port $BOOTSTRAP_PORT --signal-port $SIGNAL_PORT\" \"echo pass | RUST_LOG=warn hc launch --piped -n $AGENTS workdir/movies5.happ --ui-port $UI_PORT network --bootstrap http://127.0.0.1:\"$BOOTSTRAP_PORT\" webrtc ws://127.0.0.1:\"$SIGNAL_PORT\"\"",
    +        "launch:tauri": "concurrently \"kitsune2-bootstrap-srv --listen \"127.0.0.1:$BOOTSTRAP_PORT\"\" \"echo pass | RUST_LOG=warn hc launch --piped -n $AGENTS workdir/movies5.happ --ui-port $UI_PORT network --bootstrap http://127.0.0.1:\"$BOOTSTRAP_PORT\" webrtc ws://127.0.0.1:\"$BOOTSTRAP_PORT\"\"",
             "package": "npm run build:happ && npm run package --workspace ui && hc web-app pack workdir --recursive",
             "build:happ": "npm run build:zomes && hc app pack workdir --recursive",
             "build:zomes": "cargo build --release --target wasm32-unknown-unknown"
         },
         "devDependencies": {
    -        "@holochain-playground/cli": "^0.300.0-rc.0",
    -        "@holochain/hc-spin": "^0.400.1",
    +        "@holochain/hc-spin": "^0.500.1",
             "concurrently": "^6.5.1",
             "get-port-cli": "^3.0.0"
         },
         "engines": {
             "node": ">=16.0.0"
         },
         "hcScaffold": {
             "template": "svelte" // This might be different for your app
         }
     }
    
  3. Update your project’s package dependencies (see below).

  4. Follow the breaking change update instructions below to get your code working again.

  5. Try running your tests:

    npm test
    

    and starting the application:

    npm start
    
  6. Be aware of some changes that won’t break your app but may affect its runtime behavior. Read the guide at the bottom.

Update your package dependencies

Rust

Update the hdk and hdi version strings in the project’s root Cargo.toml file:

 [workspace.dependencies]
-hdi = "=0.5.2"
-hdk = "=0.4.2"
+hdi = "=0.6.1" # Pick a later patch version of these libraries if you prefer.
+hdk = "=0.5.1"

The latest version numbers of these libraries can be found on crates.io: hdi, hdk.

Once you’ve updated your Cargo.toml you need to update your Cargo.lock and check whether your project can still build. To do this in one step you can run:

cargo build

(Optional) Update other Rust dependencies

Running a Cargo build, like suggested above, will update as few dependencies as it can. This is good for stability because it’s just making the changes you asked for. However, sometimes you do need to update other dependencies to resolve build issues.

This section is marked as optional because it’s possible that new dependencies could introduce new issues as well as fixing existing conflicts or problems. To make it possible to roll back this change, it might be a good idea to commit the changes you’ve made so far to source control. Then you can run:

cargo update

This will update your Cargo.lock with the latest versions of all libraries that the constraints in your Cargo.toml files will allow. Now you should try building your project again to see if that has resolved your issue.

JavaScript

If you’ve created your hApp using our scaffolding tool, you should be able to follow these instructions. If you’ve created your own project folder layout, adapt these instructions to fit.

Tryorama tests

Edit your project’s tests/package.json file:

   "dependencies": {
     // some dependencies
-    "@holochain/client": "^0.18.1",
-    "@holochain/tryorama": "^0.17.1",
+    "@holochain/client": "^0.19.0",
+    "@holochain/tryorama": "^0.18.0",
     // more dependencies
   },

UI

You’ll update the UI package dependencies similarly to the test package. Edit ui/package.json:

   "dependencies": {
-    "@holochain/client": "^0.18.1",
+    "@holochain/client": "^0.19.0",
     // more dependencies
   },

Then in your project’s root folder, run your package manager’s update command to update the lockfile and install new package versions for your command-line tools, tests, and UI. Use the command that matches your chosen package manager. For example, if you’re using npm:

npm install

Update your application code

Enums in the conductor APIs are serialized differently

The admin and app APIs have changed their serialization of enum variants with values: the value is now in its own field, and enum variant names have been normalized to snake_case. For instance, if you subscribe to signals in a JavaScript-based front end, a signal payload may have previously looked like this:

{
    "App": {
        "cell_id": ["hC0kKUej3Mcu+40AjNGcaID2sQA6uAUcc9hmJV9XIdwUJUE", "hCAkhy0q54imKYjEpFdLTncbqAaCEGK3LCE+7HIA0kGIvTw"], 
        "zome_name": "movies",
        "payload": "hey it's a signal"
    }
}

but would now look like this:

{
    "type": "app",
    "value": {
        "cell_id": ["hC0kKUej3Mcu+40AjNGcaID2sQA6uAUcc9hmJV9XIdwUJUE", "hCAkhy0q54imKYjEpFdLTncbqAaCEGK3LCE+7HIA0kGIvTw"], 
        "zome_name": "movies",
        "payload": "hey it's a signal"
    }
}

This change happens in many places; we recommend that you run the TypeScript compiler against your UI and tests and look for errors. In the Holonix dev shell, run:

npx tsc -p ui/tsconfig.json
npx tsc -p tests/tsconfig.json

and look for messages that look similar to error TS2322: Type X is not assignable to type Y.

This won’t catch all errors; you may discover some at runtime. Look for usage of the following types and functions in particular:

origin_time and quantum_time are removed

With the new kitsune2 wire protocol, origin_time and quantum_time are no longer used. You may find these optional fields anywhere integrity modifiers are used:

AgentInfo::agent_latest_pubkey behind feature flag

When you call agent_info from a coordinator zome, the agent_latest_pubkey field in the return value is now hidden behind the unstable-dpki feature flag and scheduled to be removed in 0.6. Anywhere you use this field, use agent_initial_pubkey instead:

 use hdk::prelude::*;

 fn get_my_agent_id() -> ExternResult<AgentPubKey> {
-    Ok(agent_info()?.agent_latest_pubkey)
+    Ok(agent_info()?.agent_initial_pubkey)
 }

DNA lineage behind feature flag

Features related to DNA lineage are now hidden behind an unstable-migration feature flag. If you don’t plan to use this, remove the lineage line from your dna.yaml file:

 # ...
-lineage:
-  - "hC0kKUej3Mcu+40AjNGcaID2sQA6uAUcc9hmJV9XIdwUJUE" 
-  - "hCAkhy0q54imKYjEpFdLTncbqAaCEGK3LCE+7HIA0kGIvTw" 
 # ...

The GetCompatibleCells endpoint in the admin API is also hidden behind this flag.

If you want to use these features, build a custom Holochain binary with unstable-migration enabled. Note that support for the endpoint has been removed from the JavaScript client.

AppBundleSource::Bundle removed

Note: This only applies if you’re building a runtime or using Tryorama’s Conductor.prototype.installApp method. The Bundle option (deprecated in 0.4.2) is now removed from AppBundleSource. If you need to pass bundle bytes to the admin API’s InstallApp endpoint, use AppBundleSource::Bytes (introduced in 0.4.2) and pass the bytes of an entire hApp bundle file instead.

hc run-local-services replaced with kitsune2-bootstrap-srv

The old bootstrap and signal server have been combined into one binary called kitsune2-bootstrap-srv, which is provided in the Holonix dev environment for any new scaffolded hApps. To update an existing hApp, edit its flake.nix file to include the binary and optionally update its package.json file to use it if you use the Tauri-based launcher. Locally running hApp instances using hc-spin and hc-launch will now use the new binary.

disableCloneCell, enableCloneCell, and deleteCloneCell signatures changed

The object that you pass to the JS client’s AppWebsocket.prototype.disableCloneCell, AppWebsocket.prototype.enableCloneCell, and AdminWebsocket.prototype.deleteCloneCell methods has changed; now you need to explicitly specify whether the identifier is a clone ID or DNA hash using the new enum serialization format.

 let cellClonedByRoleName = client.createCloneCell({
-    clone_cell_id: "chat.1"
+    clone_cell_id: {
+        type: "clone_id",
+        value: "chat.1"
+   }
 });
 let dnaHash = decodeHashFromBase64("hC0kKUej3Mcu+40AjNGcaID2sQA6uAUcc9hmJV9XIdwUJUE"); 
 let cellClonedByDnaHash = client.createCloneCell({
-    clone_cell_id: dnaHash
+    clone_cell_id: {
+        type: "dna_hash",
+        value: dnaHash
+    }
 });

Timestamps moved to holochain_timestamp

The Timestamp type used all over the HDK and in scaffolded entry types has been moved to a new crate called holochain_timestamp. This type has historically been made available transitively through hdi::prelude and hdk::prelude, so you shouldn’t need to make any code changes unless you reference the kitsune_p2p_timestamp crate explicitly in any of your Cargo.toml files or code:

 # ...
 [dependencies]
-kitsune_p2p_timestamp = "0.4.2"
+holochain_timestamp = "0.5.1"
-use kitsune_p2p_timestamp::Timestamp;
+use holochain_timestamp::Timestamp;

 fn get_time() -> ExternResult<Timestamp> {
     sys_time()
 }

App API’s NetworkInfo removed

The NetworkInfo endpoint of the app API has been removed, which means the AppWebsocket.networkInfo method has also been removed. You can get some network info from the DumpNetworkMetrics and DumpNetworkStats endpoints, which are now exposed on the app API.

Networking section of conductor config changed

Note: This only applies if you’re using persistent conductor configs. The network section of conductor-config.yaml files has changed. We recommend that you generate a new conductor config using hc sandbox, then compare it against your existing conductor config to see what changes need to be made. You can find available config keys in the NetworkConfig documentation.

Admin API’s AgentInfo return value changed

Note: This is an advanced feature that you’ll only encounter if you’re building a custom runtime that tries to get diagnostic data. The return value of the AgentInfo endpoint in the admin API has changed. Currently it outputs a vector of JSON-serialized kitsune2_api::AgentInfoSigned values.

Subtle changes

The following changes don’t break Holochain’s APIs or require updates to your code, but they may require you to reassess whether your hApp will work as expected:

It looks like you are using Internet Explorer. While the basic content is available, this is no longer a supported browser by the manufacturer, and no attention is being given to having IE work well here.