2021-07-30 02:04:15 +00:00
|
|
|
# Receive and Send Messages Using Waku Relay
|
2021-07-28 02:20:43 +00:00
|
|
|
|
2021-07-28 05:13:33 +00:00
|
|
|
Waku Relay is a gossip protocol that enables you to send and receive messages.
|
2021-07-28 02:20:43 +00:00
|
|
|
You can find Waku Relay's specifications on [Vac RFC](https://rfc.vac.dev/spec/11/).
|
|
|
|
|
|
|
|
Before starting, you need to choose a _Content Topic_ for your dApp.
|
2021-07-30 02:04:15 +00:00
|
|
|
Check out the [how to choose a content topic guide](choose-content-topic.md) to learn more about content topics.
|
2021-07-28 02:20:43 +00:00
|
|
|
|
2021-08-02 02:00:28 +00:00
|
|
|
For this guide, we are using a single content topic: `/relay-guide/1/chat/proto`.
|
2021-07-28 02:20:43 +00:00
|
|
|
|
|
|
|
# Installation
|
|
|
|
|
|
|
|
You can install [js-waku](https://npmjs.com/package/js-waku) using your favorite package manager:
|
|
|
|
|
|
|
|
```shell
|
|
|
|
npm install js-waku
|
|
|
|
```
|
|
|
|
|
2021-07-30 02:04:15 +00:00
|
|
|
# Create Waku Instance
|
2021-07-28 02:20:43 +00:00
|
|
|
|
|
|
|
In order to interact with the Waku network, you first need a Waku instance:
|
|
|
|
|
|
|
|
```js
|
|
|
|
import { Waku } from 'js-waku';
|
|
|
|
|
|
|
|
const wakuNode = await Waku.create();
|
|
|
|
```
|
2021-07-28 02:37:05 +00:00
|
|
|
|
2021-07-30 02:04:15 +00:00
|
|
|
# Connect to Other Peers
|
2021-07-28 02:37:05 +00:00
|
|
|
|
|
|
|
The Waku instance needs to connect to other peers to communicate with the network.
|
|
|
|
You are free to choose any method to bootstrap and DappConnect will ship with new methods in the future.
|
|
|
|
|
|
|
|
For now, the easiest way is to connect to Status' Waku fleet:
|
|
|
|
|
|
|
|
```js
|
2021-08-09 06:25:10 +00:00
|
|
|
import { getBootstrapNodes } from 'js-waku';
|
|
|
|
|
|
|
|
const nodes = await getBootstrapNodes();
|
|
|
|
await Promise.all(nodes.map((addr) => waku.dial(addr)));
|
2021-07-28 02:37:05 +00:00
|
|
|
```
|
2021-07-28 02:45:41 +00:00
|
|
|
|
2021-07-28 03:07:41 +00:00
|
|
|
# Receive messages
|
|
|
|
|
2021-07-28 05:19:52 +00:00
|
|
|
To watch messages for your app, you need to register an observer on relay for your app's content topic:
|
2021-07-28 03:07:41 +00:00
|
|
|
|
|
|
|
```js
|
|
|
|
const processIncomingMessage = (wakuMessage) => {
|
2021-07-28 05:12:37 +00:00
|
|
|
console.log(`Message Received: ${wakuMessage.payloadAsUtf8}`);
|
2021-07-28 03:07:41 +00:00
|
|
|
};
|
|
|
|
|
2021-07-28 05:12:37 +00:00
|
|
|
waku.relay.addObserver(processIncomingMessage, ['/relay-guide/1/chat/proto']);
|
2021-07-28 03:07:41 +00:00
|
|
|
```
|
|
|
|
|
2021-07-30 02:04:15 +00:00
|
|
|
# Send Messages
|
2021-07-28 02:45:41 +00:00
|
|
|
|
2021-07-28 03:07:41 +00:00
|
|
|
You are now ready to send messages.
|
2021-07-28 02:45:41 +00:00
|
|
|
Let's start by sending simple strings as messages.
|
|
|
|
|
2021-07-28 03:07:41 +00:00
|
|
|
To send a message, you need to wrap the message in a `WakuMessage`.
|
|
|
|
When using a basic string payload, you can use the `WakuMessage.fromUtf8String` helper:
|
2021-07-28 02:45:41 +00:00
|
|
|
|
|
|
|
```js
|
|
|
|
import { WakuMessage } from 'js-waku';
|
|
|
|
|
2021-07-28 05:12:37 +00:00
|
|
|
const wakuMessage = await WakuMessage.fromUtf8String('Here is a message', `/relay-guide/1/chat/proto`);
|
2021-07-28 02:45:41 +00:00
|
|
|
```
|
|
|
|
|
2021-07-28 03:07:41 +00:00
|
|
|
Then, use the `relay` module to send the message to our peers,
|
2021-07-28 02:45:41 +00:00
|
|
|
the message will then be relayed to the rest of the network thanks to Waku Relay:
|
|
|
|
|
|
|
|
```js
|
2021-07-28 05:12:37 +00:00
|
|
|
await waku.relay.send(wakuMessage);
|
|
|
|
```
|
|
|
|
|
2021-07-30 02:04:15 +00:00
|
|
|
# Use Protobuf
|
2021-07-28 05:12:37 +00:00
|
|
|
|
|
|
|
Sending strings as messages in unlikely to cover your dApps needs.
|
|
|
|
|
2021-08-09 04:03:07 +00:00
|
|
|
Waku v2 protocols use [protobuf](https://developers.google.com/protocol-buffers/) [by default](https://rfc.vac.dev/spec/10/).
|
|
|
|
|
|
|
|
Let's review how you can use protobuf to include structured objects in Waku Messages.
|
|
|
|
|
|
|
|
First, define a data structure.
|
2021-07-28 05:12:37 +00:00
|
|
|
For this guide, we will use a simple chat message that contains a timestamp and text:
|
|
|
|
|
|
|
|
```js
|
|
|
|
{
|
|
|
|
timestamp: Date;
|
|
|
|
text: string;
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
2021-07-28 05:19:52 +00:00
|
|
|
To encode and decode protobuf payloads, you can use the [protons](https://www.npmjs.com/package/protons) package.
|
2021-07-28 05:12:37 +00:00
|
|
|
|
2021-07-30 02:04:15 +00:00
|
|
|
## Install Protobuf Library
|
2021-07-28 02:45:41 +00:00
|
|
|
|
2021-08-02 02:26:07 +00:00
|
|
|
First, install protons:
|
2021-07-28 02:45:41 +00:00
|
|
|
|
2021-07-28 05:12:37 +00:00
|
|
|
```shell
|
|
|
|
npm install protons
|
|
|
|
```
|
|
|
|
|
|
|
|
## Protobuf Definition
|
|
|
|
|
|
|
|
Then define the simple chat message:
|
|
|
|
|
|
|
|
```js
|
|
|
|
import protons from 'protons';
|
|
|
|
|
|
|
|
const proto = protons(`
|
|
|
|
message SimpleChatMessage {
|
2021-08-05 03:07:45 +00:00
|
|
|
uint64 timestamp = 1;
|
2021-07-28 05:12:37 +00:00
|
|
|
string text = 2;
|
|
|
|
}
|
|
|
|
`);
|
|
|
|
```
|
|
|
|
|
2021-08-02 02:26:07 +00:00
|
|
|
You can learn about protobuf message definitions here:
|
2021-07-28 05:12:37 +00:00
|
|
|
[Protocol Buffers Language Guide](https://developers.google.com/protocol-buffers/docs/proto).
|
|
|
|
|
2021-07-30 02:04:15 +00:00
|
|
|
## Encode Messages
|
2021-07-28 05:12:37 +00:00
|
|
|
|
2021-07-28 05:19:52 +00:00
|
|
|
Instead of wrapping an utf-8 string in a Waku Message,
|
|
|
|
you are going to wrap a protobuf payload.
|
2021-07-28 05:12:37 +00:00
|
|
|
|
2021-07-28 05:19:52 +00:00
|
|
|
First, encode the object:
|
2021-07-28 05:12:37 +00:00
|
|
|
|
|
|
|
```js
|
|
|
|
const payload = proto.SimpleChatMessage.encode({
|
|
|
|
timestamp: Date.now(),
|
|
|
|
text: 'Here is a message'
|
|
|
|
});
|
|
|
|
```
|
|
|
|
|
|
|
|
Then, wrap it in a Waku Message:
|
|
|
|
|
|
|
|
```js
|
|
|
|
const wakuMessage = await WakuMessage.fromBytes(payload, ContentTopic);
|
|
|
|
```
|
|
|
|
|
|
|
|
Now, you can send the message over Waku Relay the same way than before:
|
|
|
|
|
|
|
|
```js
|
2021-07-28 03:07:41 +00:00
|
|
|
await waku.relay.send(wakuMessage);
|
2021-07-28 02:45:41 +00:00
|
|
|
```
|
|
|
|
|
2021-07-30 02:04:15 +00:00
|
|
|
## Decode Messages
|
2021-07-28 05:12:37 +00:00
|
|
|
|
|
|
|
To decode the messages received over Waku Relay,
|
|
|
|
you need to extract the protobuf payload and decode it using `protons`.
|
|
|
|
|
|
|
|
```js
|
|
|
|
const processIncomingMessage = (wakuMessage) => {
|
|
|
|
// No need to attempt to decode a message if the payload is absent
|
|
|
|
if (!wakuMessage.payload) return;
|
|
|
|
|
|
|
|
const { timestamp, text } = proto.SimpleChatMessage.decode(
|
|
|
|
wakuMessage.payload
|
|
|
|
);
|
|
|
|
|
|
|
|
console.log(`Message Received: ${text}, sent at ${timestamp.toString()}`);
|
|
|
|
};
|
|
|
|
```
|
|
|
|
|
2021-07-28 05:19:52 +00:00
|
|
|
Like before, add this callback as an observer to Waku Relay:
|
2021-07-28 05:12:37 +00:00
|
|
|
|
|
|
|
```js
|
|
|
|
waku.relay.addObserver(processIncomingMessage, ['/relay-guide/1/chat/proto']);
|
|
|
|
```
|
|
|
|
|
2021-07-28 03:07:41 +00:00
|
|
|
# Conclusion
|
|
|
|
|
|
|
|
That is it! Now, you know how to send and receive messages over Waku using the Waku Relay protocol.
|
|
|
|
|
2021-07-30 03:55:43 +00:00
|
|
|
Feel free to check out other [guides](menu.md) or [examples](/examples/examples.md).
|
2021-07-28 03:07:41 +00:00
|
|
|
|
|
|
|
Here is the final code:
|
2021-07-28 02:45:41 +00:00
|
|
|
|
|
|
|
```js
|
2021-08-09 06:25:10 +00:00
|
|
|
import { getBootstrapNodes, Waku, WakuMessage } from 'js-waku';
|
2021-07-28 05:12:37 +00:00
|
|
|
import protons from 'protons';
|
|
|
|
|
|
|
|
const proto = protons(`
|
|
|
|
message SimpleChatMessage {
|
2021-08-05 03:07:45 +00:00
|
|
|
uint64 timestamp = 1;
|
2021-07-28 05:12:37 +00:00
|
|
|
string text = 2;
|
|
|
|
}
|
|
|
|
`);
|
2021-07-28 02:45:41 +00:00
|
|
|
|
|
|
|
const wakuNode = await Waku.create();
|
|
|
|
|
2021-08-09 06:25:10 +00:00
|
|
|
const nodes = await getBootstrapNodes();
|
2021-07-28 02:45:41 +00:00
|
|
|
await Promise.all(nodes.map((addr) => waku.dial(addr)));
|
|
|
|
|
2021-07-28 03:07:41 +00:00
|
|
|
const processIncomingMessage = (wakuMessage) => {
|
2021-07-28 05:12:37 +00:00
|
|
|
// No need to attempt to decode a message if the payload is absent
|
|
|
|
if (!wakuMessage.payload) return;
|
|
|
|
|
|
|
|
const { timestamp, text } = proto.SimpleChatMessage.decode(
|
|
|
|
wakuMessage.payload
|
|
|
|
);
|
|
|
|
|
|
|
|
console.log(`Message Received: ${text}, sent at ${timestamp.toString()}`);
|
2021-07-28 03:07:41 +00:00
|
|
|
};
|
2021-07-28 02:45:41 +00:00
|
|
|
|
2021-07-28 03:07:41 +00:00
|
|
|
waku.relay.addObserver(processIncomingMessage, ['/relay-guide/1/chat/proto']);
|
2021-07-28 02:45:41 +00:00
|
|
|
|
2021-07-28 05:12:37 +00:00
|
|
|
const payload = proto.SimpleChatMessage.encode({
|
|
|
|
timestamp: Date.now(),
|
|
|
|
text: 'Here is a message'
|
|
|
|
});
|
|
|
|
const wakuMessage = await WakuMessage.fromBytes(payload, ContentTopic);
|
2021-07-28 03:07:41 +00:00
|
|
|
await waku.relay.send(wakuMessage);
|
|
|
|
```
|