# Set up your project · Event-driven multi-chain dapps with ICMF · Learn Chromia

> Have the following prerequisites ready before you begin:

Source: https://chromia.com/learn/icmf-course/setup/

Event-driven multi-chain dapps with ICMFLesson 2 of 7

1. [01Event-driven multi-chain dapps with ICMF](https://chromia.com/learn/icmf-course/introduction/)
2. [02Set up your project](https://chromia.com/learn/icmf-course/setup/)
3. [03Define messages](https://chromia.com/learn/icmf-course/defining-messages/)
4. [04Order chain (send message)](https://chromia.com/learn/icmf-course/order-chain/)
5. [05Delivery chain (receive message)](https://chromia.com/learn/icmf-course/delivery-chain/)
6. [06The factory chain: sending and receiving](https://chromia.com/learn/icmf-course/factory-chain/)
7. [07Test the dapp](https://chromia.com/learn/icmf-course/manual-testing/)

[Learn](https://chromia.com/learn/)[Event-driven multi-chain dapps with ICMF](https://chromia.com/learn/icmf-course/)

02 / 07Advanced

# Set up your project

Have the following prerequisites ready before you begin:

Set up PostgreSQL database

## Set up PostgreSQL database

Rell needs PostgreSQL 16.3. Without it, the IDE still works, but you can't run a node. You can run a console or a remote postchain app without a database.

Rell expects these database settings by default:

* database: `postchain`
* user: `postchain`
* password: `postchain`

## Install

1. Install Homebrew by following the [Homebrew installation guide](https://brew.sh/).
2. Install PostgreSQL:

   shell

   ```
   brew install postgresql@16
   brew services start postgresql@16
   createuser -s postgres
   ```
3. Create and configure the database:

   plsql

   ```nolines
   psql -U postgres -c "CREATE DATABASE postchain WITH TEMPLATE = template0 LC_COLLATE = 'C.UTF-8' LC_CTYPE = 'C.UTF-8' ENCODING 'UTF-8';" -c "CREATE ROLE postchain LOGIN ENCRYPTED PASSWORD 'postchain'; GRANT ALL ON DATABASE postchain TO postchain;"
   ```

   note

   A "peer authentication failed" error means you need to switch the authentication method from `peer` to `md5`. Make this change in the `pg_hba.conf` file of your `psql` database.

1. Install PostgreSQL:

   bash

   ```nolines
   sudo apt install postgresql-16
   ```
2. Create and configure the database:

   bash

   ```nolines
   sudo -u postgres psql -c "CREATE DATABASE postchain WITH TEMPLATE = template0 LC_COLLATE = 'C.UTF-8' LC_CTYPE = 'C.UTF-8' ENCODING 'UTF-8';" -c "CREATE ROLE postchain LOGIN ENCRYPTED PASSWORD 'postchain'; GRANT ALL ON DATABASE postchain TO postchain;"
   ```

1. Install Docker by following the [Docker installation guide](https://docs.docker.com/engine/install/).
2. Create and configure the database:

   dockerfile

   ```nolines
   docker run --name postgres -e POSTGRES_USER=postchain -e POSTGRES_PASSWORD=postchain -p 5432:5432 -d postgres:16.3-alpine3.20
   ```

   note

   The Alpine image of PostgreSQL ships with the right collation settings out of the box. You can also set them explicitly through an environment variable:

   bash

   ```nolines
   POSTGRES_INITDB_ARGS="--lc-collate=C.UTF-8 --lc-ctype=C.UTF-8 --encoding=UTF-8"
   ```

1. Get the PostgreSQL installer from the [PostgreSQL download page](https://www.postgresql.org/download/windows/).
2. Run the installer, then add the PostgreSQL folder that holds the binaries to your environment variables. In the Command Prompt (CMD), run the command below. Point it at the correct binaries path and substitute the real version number for the `<version>` placeholder:

   shell

   ```nolines
   setx POSTGRESQL "C:\Program Files\PostgreSQL\<version>\bin"
   ```
3. Close and reopen the Command Prompt (CMD) so the new environment variables take effect. Then run these two commands, one after the other, to set up the database:

   plsql

   ```nolines
   psql -U postgres -c "CREATE DATABASE postchain WITH TEMPLATE = template0 LC_COLLATE = 'en_US.UTF-8' LC_CTYPE = 'en_US.UTF-8' ENCODING 'UTF-8';"
   psql -U postgres -c "CREATE ROLE postchain LOGIN ENCRYPTED PASSWORD 'postchain'; GRANT ALL ON DATABASE postchain TO postchain;"
   ```

   note

   Some Windows versions produce permission errors or end up with a broken PostgreSQL installation. If you hit these problems, install Docker and run PostgreSQL in a container instead.

Install Chromia CLI

## Install Chromia CLI

Follow these steps to install or update the [Chromia CLI](https://gitlab.com/chromaway/core-tools/chromia-cli).

## Prerequisite

Confirm the following first:

* **PostgreSQL database**: Follow [Set up PostgreSQL database](https://docs.chromia.com/get-started/installation/#set-up-postgresql-database).
* **RELL\_JAVA environment**: Chromia CLI needs a Java runtime, version 21 or later. The package managers handle this for you, so no manual setup is required. To choose which Java runtime runs Chromia CLI, set the RELL\_JAVA environment variable to the location of a valid Java installation.

## Installation

Install Chromia CLI through a package manager, or download it from [Chromia CLI Packages](https://gitlab.com/chromaway/core-tools/chromia-cli/-/packages).

On macOS, install Chromia CLI (`chr`) as follows:

1. Install Homebrew if you don't have it yet:

   bash

   ```nolines
   /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
   ```
2. Register the Chromia repository with Homebrew:

   bash

   ```nolines
   brew tap chromia/core https://gitlab.com/chromaway/core-tools/homebrew-chromia.git
   ```
3. Install Chromia CLI:

   bash

   ```nolines
   brew install chromia/core/chr
   ```

   info

   To pin a particular Chromia CLI version, run:

   shell

   ```
   brew install chromia/core/chr@<version>
   brew unlink chr
   brew link chr@<version>
   ```

   To see which versions exist, run `brew search chr`.
4. Confirm the installation by printing the version:

   bash

   ```nolines
   chr --version
   ```

On Linux or WSL (Windows Subsystem for Linux), install Chromia CLI (`chr`) as follows:

1. Fetch the public key for Chromia's `apt-repo` and add it to your system's trusted keyrings:

   bash

   ```nolines
   curl -fsSL https://apt.chromia.com/chromia.gpg | sudo tee /usr/share/keyrings/chromia.gpg
   ```
2. Add the Chromia repository to your package sources:

   bash

   ```nolines
   echo "deb [arch=amd64 signed-by=/usr/share/keyrings/chromia.gpg] https://apt.chromia.com stable main" | sudo tee /etc/apt/sources.list.d/chromia.list
   ```
3. Refresh your package sources:

   bash

   ```nolines
   sudo apt-get update
   ```

   info

   If you set up `apt.chromia.com` before Chromia CLI version `0.16.0`, run this command so the repository can be updated:

   bash

   ```nolines
   sudo apt-get --allow-releaseinfo-change update
   ```
4. After the update finishes, install Chromia CLI:

   bash

   ```nolines
   sudo apt-get install chr
   ```
5. Confirm the installation by printing the version:

   bash

   ```nolines
   chr --version
   ```

On Windows, install Chromia CLI (`chr`) with [Scoop](https://scoop.sh/) as follows:

1. If you don't have Scoop, open PowerShell as Administrator and run:

   powershell

   ```nolines
   iwr -useb get.scoop.sh | iex
   ```
2. Add the Chromia bucket to Scoop:

   powershell

   ```nolines
   scoop bucket add chromia https://gitlab.com/chromaway/core-tools/scoop-chromia/
   ```
3. Add the Java bucket to Scoop:

   powershell

   ```nolines
   scoop bucket add java
   ```

   With this bucket in place, Scoop can fetch openjdk21, which chromia-cli requires during installation.
4. Install Chromia CLI:

   powershell

   ```nolines
   scoop install chr
   ```
5. Confirm the installation by printing the version:

   powershell

   ```nolines
   chr --version
   ```

## Updating Chromia CLI

Get the newest Chromia CLI from the [packages page](https://gitlab.com/chromaway/core-tools/chromia-cli/-/packages). If you installed it with a package manager, update it with the matching command:

shell

```nolines
brew update
brew upgrade chr
```

shell

```nolines
sudo apt-get update
sudo apt-get install chr
```

shell

```nolines
scoop update
scoop update chr
```

## Docker

With Docker, you can run an isolated Linux container that already includes the Chromia CLI. You still need the [PostgreSQL database](https://docs.chromia.com/get-started/installation/#set-up-postgresql-database) set up.

The published images require Docker to be installed and configured on your host. The Docker documentation explains how to [install Docker](https://docs.docker.com/get-docker/) on Windows, Mac, and Linux.

### Start the Docker container with Chromia CLI pre-installed

To run the latest Chromia CLI, call `docker run` with the CLI image name followed by `chr`.

shell

```nolines
docker run --rm -v $(pwd):/usr/app registry.gitlab.com/chromaway/core-tools/chromia-cli/chr:<latest version> chr
```

Windows Command Prompt Users

Windows Command Prompt (cmd) doesn't understand the `$(pwd)` syntax. Use one of these instead:

* **PowerShell**: `$(Get-Location)` or `$(pwd)`
* **Command Prompt**: `%CD%`

**Command Prompt example:**

cmd

```nolines
docker run --rm -v %CD%:/usr/app registry.gitlab.com/chromaway/core-tools/chromia-cli/chr:<latest version> chr
```

note

Set up your `chromia.yml` file for your platform:

* **Mac**: Set `database:host` to `host.docker.internal`.
* **Windows**: Set `database:host` to `host.docker.internal` (Docker Desktop). If the node still cannot reach your database, try `172.17.0.1`, the default Docker bridge address on Linux.
* **Linux**: Pass `--network=host` to your Docker commands.

Without these settings, Chromia CLI can't reach the PostgreSQL instance.

To update or remove the Docker image, consult the [Docker command line reference](https://docs.docker.com/engine/reference/commandline/docker/).

bash

```
#!/bin/bash

# Allocate a pseudo-TTY one when run in interactive mode
if [ -t 0 ] && [ -t 1 ] ; then TTY="--tty"; else TTY=""; fi

docker run \
  # Sets the network to host to not need to change the database hostname (linux only)
  --network=host \
  # Set timezone based on system settings (linux only)
  -e TZ=$(cat /etc/timezone) \
  # Sets process ownership to current user
  --user $(id -u):$(id -g) \
  --mount type=bind,source="/etc/passwd",target=/etc/passwd,readonly \
  --mount type=bind,source="/etc/group",target=/etc/group,readonly \
  # Configures ssh-agent (only needed if chr install is called on non-public repositores)
  -e SSH_AUTH_SOCK=$SSH_AUTH_SOCK \
  --volume "$SSH_AUTH_SOCK:$SSH_AUTH_SOCK" \
  --mount type=bind,source="${HOME}/.ssh",target=${HOME}/.ssh,readonly \
  --mount type=bind,source="${HOME}/.config/jgit",target=${HOME}/.config/jgit \
  # Mounts current folder into the container (Use `Get-Location` on PowerShell)
  --mount type=bind,source="$(pwd)",target=/usr/app \
  --interactive ${TTY} \
  --rm \
  registry.gitlab.com/chromaway/core-tools/chromia-cli/chr:${CHR_VERSION:-latest} chr "$@"
```

Windows Command Prompt Users

The bash script above relies on `$(pwd)`, which Windows Command Prompt can't interpret. On Windows:

* **PowerShell**: Run the script unchanged.
* **Command Prompt**: In the mount command, swap `$(pwd)` for `%CD%`.

**Mount line adjusted for Command Prompt:**

cmd

```nolines
--mount type=bind,source="%CD%",target=/usr/app \
```

Start by creating the project for your blockchain app:

1. Generate a new project from the template with the Chromia CLI:

shell

```nolines
chr create-rell-dapp order-system-example --template=plain
```

shell

```nolines
cd order-system-example
```

2. Add the ICMF library configuration below to the generated `chromia.yml` file:

chromia.yml

```
libs:
  icmf:
    registry: https://gitlab.com/chromaway/core/directory-chain
    path: src/lib/icmf
    tagOrBranch: 1.90.1
    rid: x"B56524EE85B679371EAB1A069B03BE6A3E94F36993DEA900747BA5BAE8B99122"
```

3. Download the library with the following command. The library lets your blockchains send messages to and receive messages from each other:

shell

```nolines
chr install
```

4. Put the definitions below at the top of `chromia.yml`. They simplify configuring chains for messaging:

chromia.yml

```
definitions:
  - &sender # Configuration for a chain that sends messages
    gtx:
      modules:
        - "net.postchain.d1.icmf.IcmfSenderGTXModule"
  - &receiver # Base configuration for a chain that receives messages
    gtx:
      modules:
        - "net.postchain.d1.icmf.IcmfReceiverGTXModule"
    sync_ext:
      - "net.postchain.d1.icmf.IcmfReceiverSynchronizationInfrastructureExtension"
  - &sender_receiver # Base configuration for a chain that will both send and receive messages
    gtx:
      modules:
        - "net.postchain.d1.icmf.IcmfSenderGTXModule"
        - "net.postchain.d1.icmf.IcmfReceiverGTXModule"
    sync_ext:
      - "net.postchain.d1.icmf.IcmfReceiverSynchronizationInfrastructureExtension"
```

This defines an array of three elements, each tied to an anchor: `&sender`, `&receiver`, and `&sender_receiver`. Each anchor holds a configuration that a chain uses depending on whether it sends messages, receives them, or does both.

For reference, here are the project structure and the complete `chromia.yml` after these changes. Compare them against your own files:

Project structure

text

```
order-system-example/ 
├── build/ 
├── src/ 
│   ├── lib/ 
│   ├── test/ 
│   └── main.rell 
├── .gitignore 
└── chromia.yml
```

Final version of the `chromia.yml` file

chromia.yml

```
definitions:
  - &sender # Configuration for a chain that sends messages
    gtx:
      modules:
        - "net.postchain.d1.icmf.IcmfSenderGTXModule"
  - &receiver # Base configuration for a chain that receives messages
    gtx:
      modules:
        - "net.postchain.d1.icmf.IcmfReceiverGTXModule"
    sync_ext:
      - "net.postchain.d1.icmf.IcmfReceiverSynchronizationInfrastructureExtension"
  - &sender_receiver # Base configuration for a chain that will both send and receive messages
    gtx:
      modules:
        - "net.postchain.d1.icmf.IcmfSenderGTXModule"
        - "net.postchain.d1.icmf.IcmfReceiverGTXModule"
    sync_ext:
      - "net.postchain.d1.icmf.IcmfReceiverSynchronizationInfrastructureExtension"
blockchains:
  order-system-example:
    module: main
compile:
  rellVersion: 0.14.9
database:
  schema: schema_order_system_example
test:
  modules:
    - test
libs:
  icmf:
    registry: https://gitlab.com/chromaway/core/directory-chain
    path: src/messaging/icmf
    tagOrBranch: 1.29.0
    rid: x"19D6BC28D527E6D2239843608486A84F44EDCD244E253616F13D1C65893F35F6"
```

Written for this site from Chromia’s public course. Code samples are the course’s own.

[← Previous**Event-driven multi-chain dapps with ICMF**](https://chromia.com/learn/icmf-course/introduction/)[Next →**Define messages**](https://chromia.com/learn/icmf-course/defining-messages/)

On this page

* [Install](#install)
* [Prerequisite](#prerequisite)
* [Installation](#installation)
* [Updating Chromia CLI](#updating-chromia-cli)
* [Docker](#docker)
