Update quick start and add chat app guide

This commit is contained in:
fryorcraken.eth 2023-03-02 11:10:51 +11:00
parent 4d14e68d58
commit 858f2dc611
No known key found for this signature in database
GPG Key ID: A82ED75A8DFC50A4
2 changed files with 361 additions and 35 deletions

View File

@ -0,0 +1,279 @@
---
title: Build a Chat App
date: 2023-03-01T14:00:00+10:00
weight: 1
---
# Build a Chat App
In this guide you will learn how to receive and send messages using Waku by building an app from scratch.
If you want to learn how to add Waku to an existing app, check the [/quick_start] guide.
This guide is kept succinct on purpose, check out the other [guides](/docs/guides) to learn more.
## 1. Setup Project
Setup a new npm package:
```shell
mkdir waku-app
cd waku-app
npm init
```
Hit `<enter>` for all questions.
## 2. Setup Webserver
Use the `serve` package as a webserver
```shell
npm i -D serve
```
Add a `start` script to the `package.json` file:
```json
{
"scripts": {
"start": "serve ."
}
}
```
Finally, create empty files for your project:
```shell
touch index.html index.js
```
## 3. HTML Button and Text Box
In `index.html`, add a button, text box and `div` for messages to have a basic chat app.
Also, import the `index.js` file.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
<title>JS-Waku Quick Start App</title>
</head>
<body>
<label for="textInput">Message text</label>
<input id="textInput" placeholder="Type your message here" type="text"/>
<button disabled id="send" type="button">
Send message using Light Push
</button>
<br/>
<div id="messages"></div>
<script src="./index.js" type="module"></script>
</body>
</html>
```
## 4. Access HTML Element
{{< hint info >}}
From now, all changes needs to be done in the `index.js` file.
{{< /hint >}}
Initialize variables to easily modify the HTML content:
```js
const sendButton = document.getElementById("send")
const messagesDiv = document.getElementById("messages")
const textInput = document.getElementById("textInput")
```
## 5. Start a Waku Node
Create and start a Waku Node:
```js
import {createLightNode} from "https://unpkg.com/@waku/create@0.0.6/bundle/index.js"
const waku = await createLightNode({defaultBootstrap: true})
await waku.start()
```
{{< hint info >}}
The `defaultBootstrap` option enables your Waku node to connect to set a pre-defined nodes.
This can be modified in the future.
{{< /hint >}}
## 6. Wait to be connected
The Waku node needs to first connect to bootstrap nodes to establish a connection.
To wait for this, use the `waitForRemotePeer` function:
```js
import * as waku from "https://unpkg.com/@waku/core@0.0.10/bundle/index.js"
await waku.waitForRemotePeer(wakuNode)
```
## 7. Define a Content Topic
The `contentTopic` is a metadata `string` that allows categorization of messages on the Waku network.
Depending on your use case, you can either create one (or several) new `contentTopic`(s).
See [How to Choose a Content Topic](/docs/guides/01_choose_content_topic/) for more details.
For now, let's use `/js-waku-examples/1/chat/utf8` for this guide.
Note that we will be encoding our payload using `utf-8`. Note that Protobuf is recommended for production usage.
```js
const contentTopic = `/js-waku-examples/1/chat/utf8`
```
## 8. Create a Decoder
Waku offers several encryption protocols,
a decoder enables you to specify what content topic to use and how to decrypt messages.
Create a decoder for plain text decoding (no encryption), for the chose content topic:
```js
const decoder = waku.createDecoder(contentTopic)
```
## 9. Render Incoming Messages
Let's store incoming messages in an array and create a function to render them in the `messages` div:
```js
const updateMessages = (msgs, div) => {
div.innerHTML = "<ul>"
msgs.forEach((msg) => (div.innerHTML += "<li>" + msg + "</li>"))
div.innerHTML += "</ul>"
};
const messages = []
```
## 10. Listen for Incoming Messages
Messages sent over the network are `Waku Message`s.
You can check the wire format here: https://rfc.vac.dev/spec/14/#wire-format
The interface for a plain text decoder is [`DecodedMessage`](https://js.waku.org/classes/_waku_core.DecodedMessage.html).
For now, we will just use the `payload` field.
It is a byte array field you can use to encode any data you want.
We will use it to store messages as `utf-8`.
Listen to messages using the decoder and add them to the `messages` div upon reception:
```ts
wakuNode.filter.subscribe([decoder], (message) => {
const str = utils.bytesToUtf8(message.payload)
messages.push(str)
updateMessages(messages, messagesDiv);
})
```
## 11. Send Messages
Finally, create a plain text encoder and setup the `send` button to send messages.
The users will be able to enter the message using the `textInput` div.
Once done, we can enable the `send` button.
```ts
const encoder = waku.createEncoder(contentTopic)
sendButton.onclick = async () => {
const text = textInput.value;
await wakuNode.lightPush.push(encoder, {
payload: utils.utf8ToBytes(text),
});
textInput.value = null;
};
sendButton.disabled = false
```
### 12. Run the App
You can now start a local webserver to run the app:
```shell
npm start
```
Click on the link the console (http://localhost:3000/) and send a message!
You can open your app in several tabs to see messages being sent around.
## Conclusion
Congratulations for building your first Waku app.
See below the complete files:
`index.html`:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
<title>JS-Waku Quick Start App</title>
</head>
<body>
<label for="textInput">Message text</label>
<input id="textInput" placeholder="Type your message here" type="text"/>
<button disabled id="send" type="button">
Send message using Light Push
</button>
<br/>
<div id="messages"></div>
<script src="./index.js" type="module"></script>
</body>
</html>
```
`index.js`
```js
import {createLightNode} from "https://unpkg.com/@waku/create@0.0.6/bundle/index.js"
import * as waku from "https://unpkg.com/@waku/core@0.0.10/bundle/index.js"
import * as utils from "https://unpkg.com/@waku/byte-utils@0.0.2/bundle/index.js"
const sendButton = document.getElementById("send")
const messagesDiv = document.getElementById("messages")
const textInput = document.getElementById("textInput")
const wakuNode = await createLightNode({defaultBootstrap: true})
await wakuNode.start()
await waku.waitForRemotePeer(wakuNode)
const contentTopic = `/js-waku-examples/1/chat/utf8`
const decoder = waku.createDecoder(contentTopic)
const updateMessages = (msgs, div) => {
div.innerHTML = "<ul>"
msgs.forEach((msg) => (div.innerHTML += "<li>" + msg + "</li>"))
div.innerHTML += "</ul>"
};
const messages = []
wakuNode.filter.subscribe([decoder], (message) => {
const str = utils.bytesToUtf8(message.payload)
messages.push(str)
updateMessages(messages, messagesDiv);
})
const encoder = waku.createEncoder(contentTopic)
sendButton.onclick = async () => {
const text = textInput.value;
await wakuNode.lightPush.push(encoder, {
payload: utils.utf8ToBytes(text),
});
textInput.value = null;
};
sendButton.disabled = false
```

View File

@ -6,61 +6,108 @@ weight: 20
# Quick Start
In this section you will learn how to receive and send messages using Waku Relay.
In this guide you will learn how to add Waku to an **existing** JavaScript project.
A more in depth guide for Waku Relay can be found [here](/docs/guides/02_relay_receive_send_messages/).
If you want to build a Waku app from scratch, check out the [Build a Chat App](/docs/guides/chat_app/) guide.
## Install
This guide is kept succinct on purpose, check out other [guides](/docs/guides/) to learn more.
Install the `js-waku` package:
## 1. Install Waku Libraries
```shell
npm install js-waku
# or with yarn
yarn add js-waku
npm i @waku/core @waku/create
```
### Start a waku node
## 2. Start a Waku Node
```ts
import { Waku } from "js-waku";
Create and start a Waku Node:
const waku = await Waku.create({ bootstrap: { default: true } });
```js
import {createLightNode} from "@waku/create"
const waku = await createLightNode({defaultBootstrap: true})
await waku.start()
```
### Listen for messages
{{< hint info >}}
The `defaultBootstrap` option enables your Waku node to connect to set a pre-defined nodes.
This can be modified in the future.
{{< /hint >}}
The `contentTopic` is a metadata `string` that allows categorization of messages on the waku network.
Depending on your use case, you can either create one (or several) new `contentTopic`(s)
or look at the [RFCs](https://rfc.vac.dev/) and use an existing `contentTopic`.
## 3. Wait to be connected
The Waku node needs to first connect to bootstrap nodes to establish a connection.
To wait for this, use the `waitForRemotePeer` function:
```js
import * as waku from "@waku/core"
await waku.waitForRemotePeer(wakuNode)
```
## 4. Define a Content Topic
The `contentTopic` is a metadata `string` that allows categorization of messages on the Waku network.
Depending on your use case, you can either create one (or several) new `contentTopic`(s).
See [How to Choose a Content Topic](/docs/guides/01_choose_content_topic/) for more details.
For example, if you were to use a new `contentTopic` such as `/my-cool-app/1/my-use-case/proto`,
here is how to listen to new messages received via [Waku v2 Relay](https://rfc.vac.dev/spec/11/):
For now, let's use `/quick-start/1/message/utf8` for this guide.
Note that we will be encoding our payload using `utf-8`.
Note that Protobuf is recommended for production usage.
```ts
waku.relay.addObserver(
(msg) => {
console.log("Message received:", msg.payloadAsUtf8);
},
["/my-cool-app/1/my-use-case/proto"]
);
```js
const contentTopic = `/quick-start/1/message/utf8`
```
### Send messages
## 5. Create a Decoder
Messages are wrapped in a `WakuMessage` envelop.
Waku offers several encryption protocols,
a decoder enables you to specify what content topic to use and how to decrypt messages.
```ts
import { WakuMessage } from "js-waku";
Create a decoder for plain text decoding (no encryption), for the chose content topic:
const msg = await WakuMessage.fromUtf8String(
"Here is a message!",
"/my-cool-app/1/my-use-case/proto"
);
await waku.relay.send(msg);
```js
const decoder = waku.createDecoder(contentTopic)
```
### Building an app
## 6. Listen for Incoming Messages
Check out the [ReactJS Waku Relay guide](/docs/guides/07_reactjs_relay/) to learn how you can use the code above in a React app.
Messages sent over the network are `Waku Message`s.
You can check the wire format here: https://rfc.vac.dev/spec/14/#wire-format
The interface for a plain text decoder is [`DecodedMessage`](https://js.waku.org/classes/_waku_core.DecodedMessage.html).
For now, we will just use the `payload` field.
It is a byte array field you can use to encode any data you want.
We will use it to store messages as `utf-8`.
Listen to messages using the decoder:
```ts
wakuNode.filter.subscribe([decoder], (message) => {
const str = utils.bytesToUtf8(message.payload)
// str is a string, render it in your app anyway you wish
})
```
## 7. Send Messages
Finally, create a `sendMessage` function that will send messages over Waku:
```ts
const encoder = waku.createEncoder(contentTopic)
const sendMessage = async (textMsg) => {
await wakuNode.lightPush.push(encoder, {
payload: utils.utf8ToBytes(textMsg),
});
};
```
You can use `sendMessage` in your app to send messages.
## Conclusion
You have added decentralized communication features to your app!
Check out other [guides](/docs/guides/) to learn more or join us on [Discord](https://discord.gg/Nrac59MfSX).