# Delivery chain (receive message) · Event-driven multi-chain dapps with ICMF · Learn Chromia

> The delivery chain has two responsibilities. It tracks which orders need delivering, and it copes with messages that arrive out of order, for example when a…

Source: https://chromia.com/learn/icmf-course/delivery-chain/

Event-driven multi-chain dapps with ICMFLesson 5 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/)

05 / 07Advanced

# Delivery chain (receive message)

The delivery chain has two responsibilities. It tracks which orders need delivering, and it copes with messages that arrive out of order, for example when a shipment is marked ready before it has been created. In practice this would not occur, but the example handles the case anyway.

In the `src/delivery_chain` directory, add a module file named `module.rell` containing this definition:

src/delivery\_chain/module.rell

```nolines
module;
```

In `src/delivery_chain/entities.rell`, define an enum for the three states an order can be in: created, dispatched, and delivered.

src/delivery\_chain/entities.rell

```
enum shipping_state {
    CREATED,
    DISPATCHED,
    DELIVERED
}

entity delivery {
    key order_id: integer;
    index customer_id: integer;
    shipping_address: text;
    mutable shipping_state;
}

// orders that can be dispatched but have not yet been created
entity pending_delivery {
    key order_id: integer;
}
```

To mark a shipment as delivered, add a new operation to `src/delivery_chain/operations.rell`:

src/delivery\_chain/operations.rell

```
operation accept_delivery(order_id: integer) {
    require(delivery @ { order_id }.shipping_state == shipping_state.DISPATCHED, "Order must be dispatched before it can be completed");
    update delivery @ { order_id } ( shipping_state = shipping_state.DELIVERED);
}
```

To read the current delivery status, add a matching query to `src/delivery_chain/queries.rell`:



src/delivery\_chain/queries.rell

```
query get_delivery_details(order_id: integer) = delivery @* { order_id } ($.to_struct());

query list_deliveries() = delivery @* {} ($.to_struct());
```

## Receiving a message

Before the new blockchain can receive messages, you need to configure it and reference the `receiver` defined in the Introduction section. In `chromia.yml`, add the following `delivery_chain` entry under the `blockchains` property:

chromia.yml

```
blockchains:
  # ↓↓↓ Add this code snippet ↓↓↓
  delivery_chain:
    module: delivery_chain
    config:
      <<: *receiver
      icmf:
        receiver:
          local:
            - topic: "L_delivery"
              brid: null
            - topic: "L_shipment_ready"
              brid: null
  # ↑↑↑ Add this code snippet ↑↑↑
```

This configuration subscribes the dapp to the `L_delivery` and `L_shipment_ready` topics defined in the dapp code. The `brid` field identifies the chain that produces the topic. Because the dapp is not yet deployed to a network, set it to `null` for now.

info

A `null` value is accepted only for local testing. On a real network, deploy the producer chain first so you have its `brid` to enter here.

Two message types need handling, so add these imports to `src/delivery_chain/module.rell`:

src/delivery\_chain/module.rell

```nolines
import messages. { topic.*, msg };
import lib.icmf.receiver.{ receive_icmf_message };
```

Then, in `functions.rell`, define a `receive_icmf_message` extension:

src/delivery\_chain/functions.rell

```
@extend(receive_icmf_message)
function (sender: byte_array, topic: text, body: gtv) {
    when (topic) {
        NEW_DELIVERY -> handle_new_delivery(msg.delivery_details.from_gtv(body));
        SHIPMENT_READY -> handle_shipment_ready(msg.shipment_ready.from_gtv(body));
        else -> log("Message type %s not handled".format(topic));
    }
}

function handle_new_delivery(msg: msg.delivery_details) {
    val state = pending_delivery @? { msg.order_id } (shipping_state.DISPATCHED) ?: shipping_state.CREATED;
    create delivery(
        order_id = msg.order_id,
        customer_id = msg.customer_id,
        shipping_address = msg.shipping_address,
        shipping_state = state
    );
    delete pending_delivery @? { msg.order_id };
}

function handle_shipment_ready(msg: msg.shipment_ready) {
    if (not exists(delivery @? { .order_id == msg.order_id })) {
        create pending_delivery ( msg.order_id );
    } else {
        update delivery @ { .order_id == msg.order_id } ( shipping_state = shipping_state.DISPATCHED );
    }
}
```

The extension inspects the message topic and branches on it. For a topic it does not handle, it fails the operation, which stops block building because the configuration is wrong. Each of the two supported message types either creates or updates entities so the delivery is recorded with the correct state.

## Testing

Testing the delivery chain requires extra configuration in `chromia.yml`. Under the `delivery_chain` section, add a `test` property with the required details.



chromia.yml

```
blockchains:
  delivery_chain:
    # ↓↓↓ Add this code snippet ↓↓↓
    test:
      modules:
        - test.delivery_chain_test
    # ↑↑↑ Add this code snippet ↑↑↑
```

Next, write a test that emits events through the ICMF test utilities and checks that the expected shipment orders and states are created. Create `delivery_chain_test.rell` in `src/test` with the following code:

src/test/delivery\_chain\_test.rell

```
@test module;

import delivery_chain.{ delivery, accept_delivery, shipping_state };
import messages.{ msg, topic };
import lib.icmf.test.{ test_icmf_message };

function test_make_delivery() {
    rell.test.tx().op(
            test_icmf_message(
                x"",
                topic.NEW_DELIVERY,
                msg.delivery_details(
                    order_id = 1,
                    customer_id = 10,
                    shipping_address = "MyStreet 101"
                )
                    .to_gtv()
            )
        )
        .run();
    assert_equals(delivery @ { .order_id == 1 }.shipping_state, shipping_state.CREATED);
    rell.test.tx().op(accept_delivery(1)).run_must_fail("must be dispatched before");
    rell.test.tx().op(
            test_icmf_message(
                x"",
                topic.SHIPMENT_READY,
                msg.shipment_ready(order_id = 1)
                    .to_gtv()
            )
        )
        .run();
    assert_equals(delivery @ { .order_id == 1 }.shipping_state, shipping_state.DISPATCHED);
    rell.test.tx().op(accept_delivery(1)).run();
}
```

Run `chr test` and confirm the results.

bash

```
Running tests for chain: delivery_chain
TEST: order_chain_test:test_make_delivery
OK: order_chain_test:test_make_order (0,837s)

------------------------------------------------------------
TEST RESULTS:

OK delivery_chain_test:delivery_make_order

SUMMARY: 0 FAILED / 1 PASSED / 1 TOTAL (0,837s)
```

For reference, here are the project structure and the full `chromia.yml` after these changes. Use them to check your work at this point in the course:

Project structure

text

```
order-system-example/
├── build/
├── src/
│   ├── delivery_chain/
│   │   ├── entities.rell
│   │   ├── functions.rell
│   │   ├── module.rell
│   │   ├── operations.rell
│   │   └── queries.rell
│   ├── lib/
│   ├── order_chain/
│   │   ├── entities.rell
│   │   ├── functions.rell
│   │   ├── module.rell
│   │   ├── operations.rell
│   │   └── queries.rell
│   ├── test/
│   │   ├── delivery_chain_test.rell
│   │   └── order_chain_test.rell
│   └── messages.rell 
├── .gitignore
└── chromia.yml
```

Final version of the `chromia.yml`

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_chain:
    module: order_chain
    config:
      <<: *sender
    test:
      modules:
        - test.order_chain_test
  delivery_chain:
    module: delivery_chain
    config:
      <<: *receiver
      icmf:
        receiver:
          local:
            - topic: "L_delivery"
              brid: null
            - topic: "L_shipment_ready"
              brid: null
    test:
      modules:
        - test.delivery_chain_test
compile:
  rellVersion: 0.14.9
database:
  schema: schema_order_system_example
libs:
  icmf:
    registry: https://gitlab.com/chromaway/core/directory-chain
    path: src/lib/icmf
    tagOrBranch: 1.90.1
    rid: x"B56524EE85B679371EAB1A069B03BE6A3E94F36993DEA900747BA5BAE8B99122"
```

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

[← Previous**Order chain (send message)**](https://chromia.com/learn/icmf-course/order-chain/)[Next →**The factory chain: sending and receiving**](https://chromia.com/learn/icmf-course/factory-chain/)

On this page

* [Receiving a message](#receiving-a-message)
* [Testing](#testing)
