Update quick start and add chat app guide
This commit is contained in:
parent
4d14e68d58
commit
858f2dc611
|
@ -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
|
||||
```
|
|
@ -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).
|
||||
|
|
Loading…
Reference in New Issue