From 858f2dc61152614aef61e18f98b5a95bd2f17314 Mon Sep 17 00:00:00 2001 From: "fryorcraken.eth" Date: Thu, 2 Mar 2023 11:10:51 +1100 Subject: [PATCH] Update quick start and add chat app guide --- content/docs/guides/chat_app.md | 279 ++++++++++++++++++++++++++++++++ content/docs/quick_start.md | 117 ++++++++++---- 2 files changed, 361 insertions(+), 35 deletions(-) create mode 100644 content/docs/guides/chat_app.md diff --git a/content/docs/guides/chat_app.md b/content/docs/guides/chat_app.md new file mode 100644 index 0000000..65358c3 --- /dev/null +++ b/content/docs/guides/chat_app.md @@ -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 `` 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 + + + + + + JS-Waku Quick Start App + + + + + +
+
+ + + +``` + +## 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 = "" +}; + +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 + + + + + + JS-Waku Quick Start App + + + + + +
+
+ + + +``` + +`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 = "" +}; + +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 +``` diff --git a/content/docs/quick_start.md b/content/docs/quick_start.md index 86c9a7d..94b7e43 100644 --- a/content/docs/quick_start.md +++ b/content/docs/quick_start.md @@ -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).