js-waku/guides/relay-receive-send-messages.md

228 lines
5.9 KiB
Markdown
Raw Normal View History

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({ bootstrap: true });
2021-07-28 02:20:43 +00:00
```
2021-07-28 02:37:05 +00:00
Passing the `bootstrap` option will connect your node to predefined Waku nodes.
If you want to bootstrap to your own nodes, you can pass an array of multiaddresses instead:
2021-07-28 02:37:05 +00:00
```js
import { Waku } from 'js-waku';
2021-07-28 02:37:05 +00:00
const wakuNode = await Waku.create({
bootstrap: [
'/dns4/node-01.ac-cn-hongkong-c.wakuv2.test.statusim.net/tcp/443/wss/p2p/16Uiu2HAkvWiyFsgRhuJEb9JfjYxEkoHLgnUQmr1N5mKWnYjxYRVm',
'/dns4/node-01.do-ams3.wakuv2.test.statusim.net/tcp/443/wss/p2p/16Uiu2HAmPLe7Mzm8TsYUubgCAW1aJoeFScxrLj8ppHFivPo97bUZ'
]
});
```
2021-07-28 02:37:05 +00:00
# Wait to be connected
When using the `bootstrap` option, it may take some times to connect to other peers.
To ensure that you have relay peers available to send and receive messages,
use the following function:
```js
await waku.waitForConnectedPeer();
2021-07-28 02:37:05 +00:00
```
2021-07-28 02:45:41 +00:00
The returned Promise will resolve once you are connected to a Waku Relay peer.
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.
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.
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
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();
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);
```