Working with Multiple Publishers in a Shared Stream

The core architecture of Somnia Data Streams decouples data schemas from publishers. This allows multiple different accounts (or devices) to publish data using the same schema. The data conforms to the same data structure, regardless of who published it.

This model is perfect for multi-source data scenarios, such as:

  • Multi-User Chat: Multiple users sending messages under the same chatMessage schema.

  • IoT (Internet of Things): Hundreds of sensors submitting data under the same telemetry schema.

  • Gaming: All players in a game publishing their positions and scores under the same playerUpdate schema.

In this tutorial, we will demonstrate how to build an "aggregator" application that collects and merges data from two different "devices" (two separate wallet accounts) publishing to the same "telemetry" schema.

Prerequisites

  • Node.js 20+

  • @somnia-chain/streams and viem libraries installed

  • An RPC_URL for access to the Somnia Testnet

  • Two (2) funded Somnia Testnet wallets for publishing data.

What You’ll Build

In this tutorial, we will build two main components:

  1. A Publisher Script that simulates two different wallets sending data to the same telemetry schema.

  2. An Aggregator Script that fetches all data from a specified list of publishers, merges them into a single list, and sorts them by timestamp.

Project Setup

Create a new directory for your application and install the necessary packages.

Create a tsconfig.json file in your project root:

Configure Environment Variables

Create a .env file in your project root. For this tutorial, we will need two different private keys.

circle-info

IMPORTANT: Never expose private keys in client-side (browser) code or public repositories. The scripts in this tutorial are intended to be run server-side.

Chain and Client Configuration

Create a folder named src/lib and set up your chain.ts and clients.ts files.

src/lib/chain.ts

src/lib/clients.ts

Define the Shared Schema

Let's define the common schema that all publishers will use.

src/lib/schema.ts

Create the Publisher Script

Now, let's create a script that simulates how two different publishers will send data to this schema. This script will take which publisher to use as a command-line argument.

src/scripts/publishData.ts

To run this script:

Add the following scripts to your package.json file:

Now, open two different terminals and send data from each:

Repeat this a few times to build up a dataset from both publishers.

Create the Aggregator Script

Now that we have published our data, we can write the "aggregator" script that collects, merges, and sorts all data from these two (or more) publishers.

src/scripts/aggregateData.ts

To run this script:

Add the script to your package.json file:

And run it:

Conclusion

In this tutorial, you learned how to manage a multi-publisher architecture with Somnia Data Streams.

  • Publisher Side: The logic remained unchanged. Each publisher independently published its data using its wallet and the sdk.streams.set() method.

  • Aggregator Side: This is where the main logic came in.

    1. We maintained a list of publishers we were interested in.

    2. We fetched the data for each publisher separately using the getAllPublisherDataForSchema method.

    3. We combined the incoming data into a single array (allRecords.push(...)).

    4. Finally, we sorted all the data on the client-side to display them in a meaningful order (e.g., by timestamp).

This pattern can be scaled to support any number of publishers and provides a robust foundation for building decentralized, multi-source applications.

Last updated