Send and Receive Messages in a Reliable Channel
Learn how to send and receive messages with a convenient SDK that provide various reliable functionalities out-of-the-box.
This is an experimental feature and has a number of limitations.
Import Waku SDK
npm install @waku/sdk@latest
Or using a CDN, note this is an ESM package so type="module"
is needed.
<script type="module">
import {
createLightNode,
ReliableChannel
} from 'https://unpkg.com/@waku/sdk@latest/bundle/index.js';
// Your code here
</script>
Create a Waku node
Use the createLightNode()
function to create a Light Node and interact with the Waku Network:
import { createLightNode } from "@waku/sdk";
// Create a Light Node
const node = await createLightNode({ defaultBootstrap: true });
When the defaultBootstrap
parameter is set to true
, your node will be bootstrapped using the default bootstrap method. Have a look at the Bootstrap Nodes and Discover Peers guide to learn more methods to bootstrap nodes.
Create encoders and decoders
Choose a content topic for your application and create a message encoder
and decoder
:
import { createEncoder, createDecoder } from "@waku/sdk";
// Choose a content topic
const ct = "/my-app/1/messages/proto";
// Create a message encoder and decoder
const encoder = node.createEncoder({ contentTopic: ct });
const decoder = node.createDecoder({ contentTopic: ct });
You can also use @waku/message-encryption
to encrypt and decrypt messages using Waku libraries.
In this example, users send and receive messages on a shared content topic. However, real applications may have users broadcasting messages while others listen or only have 1:1 exchanges. Waku supports all these use cases.
Listen for connection status
The Waku node will emit health
events to help you know whether the node is connected to the network.
This can be useful to give feedback to the user, or stop some action (e.g. sending messages) when offline:
import { HealthStatus } from "@waku/sdk";
node.events.addEventListener("waku:health", (event) => {
const health = event.detail;
if (health === HealthStatus.SufficientlyHealthy) {
// Show to the user they are connected
} else if (status === HealthStatus.MinimallyHealthy) {
// Maybe put some clue to the user that while we are connected,
// there may be issues sending or receiving messages
} else {
// Show to the user they are disconnected from the network
}
});
Create a reliable channel
You need to choose a channel name: it acts as an identifier to the conversation, participants will try to ensure they all have the same messages within a given channel.
const channelName = "channel-number-15"
Finally, each participant need to identify themselves for reliability purposes, so they can confirm others have received their messages.
It is up to you how to generate an id. Every participant must have a different id.
const senderId = generateRandomStringId();
You can now create a reliable channel:
import { ReliableChannel } from "@waku/sdk";
const reliableChannel = await ReliableChannel.create(node, channelName, senderId, encoder, decoder)
The channel will automatically start the Waku node and fetch messages.
Create a message structure
Create your application's message structure using Protobufjs:
import protobuf from "protobufjs";
// Create a message structure using Protobuf
const DataPacket = new protobuf.Type("DataPacket")
.add(new protobuf.Field("timestamp", 1, "uint64"))
.add(new protobuf.Field("sender", 2, "string"))
.add(new protobuf.Field("message", 3, "string"));
Have a look at the Protobuf installation guide for adding the protobufjs
package to your project.
Listen to incoming messages
The reliable channel will emit incoming messages. To process them, simply add a listener:
reliableChannel.addEventListener("message-received", (event) => {
const wakuMessage = event.detail;
// decode your payload using the protobuf object previously created
const { timestamp, sender, message } = DataPacket.decode(wakuMessage.payload);
// ... process the message as you wish
})
Send messages
To send messages in the reliable channel, encode the message in a payload.
// Create a new message object
const protoMessage = DataPacket.create({
timestamp: Date.now(),
sender: "Alice",
message: "Hello, World!",
});
// Serialise the message using Protobuf
const serialisedMessage = DataPacket.encode(protoMessage).finish();
Then, send the message and setup listeners so you can know when the message:
- has been sent
- has been acknowledged by other participants in the channel
- has encountered an error
// Send the message, and get the id to track events
const messageId = reliableChannel.send(payload);
reliableChannel.addEventListener("sending-message-irrecoverable-error", (event) => {
if (messageId === event.detail.messageId) {
console.error('Failed to send message:', event.detail.error);
// Show an error to the user
}
})
reliableChannel.addEventListener("message-sent", (event) => {
if (messageId === event.detail) {
// Message sent, show '✔' to the user, etc
}
})
reliableChannel.addEventListener("message-acknowledged", (event) => {
if (messageId === event.detail) {
// Message acknowledged by other participants, show '✔✔' to the user, etc
}
})
You have successfully sent and received messages over the Waku Network using our reliable protocols such as Scalable Data Sync (SDS) and P2P Reliability.