diff --git a/docs/guides/js-waku/index.md b/docs/guides/js-waku/index.md index 193d6af..bb61d83 100644 --- a/docs/guides/js-waku/index.md +++ b/docs/guides/js-waku/index.md @@ -85,17 +85,18 @@ import "https://cdn.jsdelivr.net/npm/protobufjs@latest/dist/protobuf.min.js"; Have a look at the quick start guide and comprehensive tutorials to learn how to build applications using `@waku/sdk`: -| Guide | Description | -| - | - | +| Guide | Description | +|---------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| [Send and Receive Messages in a Reliable Channel](/guides/js-waku/reliable-channels) | Learn how to send and receive messages with a convenient SDK that provide various reliable functionalities out-of-the-box. | | [Send and Receive Messages Using Light Push and Filter](/guides/js-waku/light-send-receive) | Learn how to send and receive messages on light nodes using the [Light Push](/learn/concepts/protocols#light-push) and [Filter](/learn/concepts/protocols#filter) protocols | -| [Retrieve Messages Using Store Protocol](/guides/js-waku/store-retrieve-messages) | Learn how to retrieve and filter historical messages on light nodes using the [Store protocol](/learn/concepts/protocols#store) | -| [Encrypt, Decrypt, and Sign Your Messages](/guides/js-waku/message-encryption) | Learn how to use the [@waku/message-encryption](https://www.npmjs.com/package/@waku/message-encryption) package to encrypt, decrypt, and sign your messages | -| [Build React DApps Using @waku/react](/guides/js-waku/use-waku-react) | Learn how to use the [@waku/react](https://www.npmjs.com/package/@waku/react) package seamlessly integrate `@waku/sdk` into a React application | -| [Scaffold DApps Using @waku/create-app](/guides/js-waku/use-waku-create-app) | Learn how to use the [@waku/create-app](https://www.npmjs.com/package/@waku/create-app) package to bootstrap your next `@waku/sdk` project from various example templates | -| [Bootstrap Nodes and Discover Peers](/guides/js-waku/configure-discovery) | Learn how to bootstrap your node using [Static Peers](/learn/concepts/static-peers) and discover peers using [DNS Discovery](/learn/concepts/dns-discovery) | -| [Run @waku/sdk in a NodeJS Application](/guides/js-waku/run-waku-nodejs) | Learn our suggested approach for using the `@waku/sdk` package within a NodeJS application | -| [Debug Your Waku DApp and WebSocket](/guides/js-waku/debug-waku-dapp) | Learn how to troubleshoot your Waku DApp using debug logs and check [WebSocket](/learn/concepts/transports) connections in [nwaku](/guides/nwaku/run-node) | -| [Manage Your Filter Subscriptions](/guides/js-waku/manage-filter) | Learn how to manage [filter subscriptions](/learn/concepts/protocols#filter) and handle node disconnections in your application | +| [Retrieve Messages Using Store Protocol](/guides/js-waku/store-retrieve-messages) | Learn how to retrieve and filter historical messages on light nodes using the [Store protocol](/learn/concepts/protocols#store) | +| [Encrypt, Decrypt, and Sign Your Messages](/guides/js-waku/message-encryption) | Learn how to use the [@waku/message-encryption](https://www.npmjs.com/package/@waku/message-encryption) package to encrypt, decrypt, and sign your messages | +| [Build React DApps Using @waku/react](/guides/js-waku/use-waku-react) | Learn how to use the [@waku/react](https://www.npmjs.com/package/@waku/react) package seamlessly integrate `@waku/sdk` into a React application | +| [Scaffold DApps Using @waku/create-app](/guides/js-waku/use-waku-create-app) | Learn how to use the [@waku/create-app](https://www.npmjs.com/package/@waku/create-app) package to bootstrap your next `@waku/sdk` project from various example templates | +| [Bootstrap Nodes and Discover Peers](/guides/js-waku/configure-discovery) | Learn how to bootstrap your node using [Static Peers](/learn/concepts/static-peers) and discover peers using [DNS Discovery](/learn/concepts/dns-discovery) | +| [Run @waku/sdk in a NodeJS Application](/guides/js-waku/run-waku-nodejs) | Learn our suggested approach for using the `@waku/sdk` package within a NodeJS application | +| [Debug Your Waku DApp and WebSocket](/guides/js-waku/debug-waku-dapp) | Learn how to troubleshoot your Waku DApp using debug logs and check [WebSocket](/learn/concepts/transports) connections in [nwaku](/guides/nwaku/run-node) | +| [Manage Your Filter Subscriptions](/guides/js-waku/manage-filter) | Learn how to manage [filter subscriptions](/learn/concepts/protocols#filter) and handle node disconnections in your application | :::tip Until [node incentivisation](/learn/research#prevention-of-denial-of-service-dos-and-node-incentivisation) is in place, you should [operate extra nodes](/#run-a-waku-node) alongside the ones provided by the Waku Network. When running a node, we recommend using the [DNS Discovery and Static Peers](/guides/js-waku/configure-discovery#configure-dns-discovery-and-static-peers) configuration to connect to both the Waku Network and your node. diff --git a/docs/guides/js-waku/reliable-channels.md b/docs/guides/js-waku/reliable-channels.md new file mode 100644 index 0000000..ae914b9 --- /dev/null +++ b/docs/guides/js-waku/reliable-channels.md @@ -0,0 +1,197 @@ +--- +title: Send and Receive Messages in a Reliable Channel +hide_table_of_contents: true +--- + +Learn how to send and receive messages with a convenient SDK that provide various reliable functionalities out-of-the-box. + +:::warning +This is an experimental feature and has a number of [limitations](https://github.com/waku-org/js-waku/pull/2526). +::: + +## Import Waku SDK + +```shell +npm install @waku/sdk@latest +``` + +Or using a CDN, note this is an ESM package so `type="module"` is needed. + +```html + +``` + +## Create a Waku node + +Use the `createLightNode()` function to create a [Light Node](/learn/glossary#light-node) and interact with the Waku Network: + +```js +import { createLightNode } from "@waku/sdk"; + +// Create a Light Node +const node = await createLightNode({ defaultBootstrap: true }); +``` + +:::info +When the `defaultBootstrap` parameter is set to `true`, your node will be bootstrapped using the [default bootstrap method](/guides/js-waku/configure-discovery#default-bootstrap-method). Have a look at the [Bootstrap Nodes and Discover Peers](/guides/js-waku/configure-discovery) guide to learn more methods to bootstrap nodes. +::: + +## Create encoders and decoders + +Choose a [content topic](/learn/concepts/content-topics) for your application and create a message `encoder` and `decoder`: + +```js +import { createEncoder, createDecoder } from "@waku/sdk"; + +// Choose a content topic +const ct = "/my-app/1/messages/proto"; + +// Create a message encoder and decoder +const encoder = node.createEncoder({ contentTopic: ct }); +const decoder = node.createDecoder({ contentTopic: ct }); +``` + +You can also use [`@waku/message-encryption`](/guides/js-waku/message-encryption) to encrypt and decrypt messages using Waku libraries. + +:::info +In this example, users send and receive messages on a shared content topic. However, real applications may have users broadcasting messages while others listen or only have 1:1 exchanges. Waku supports all these use cases. +::: + +## Listen for connection status + +The Waku node will emit `health` events to help you know whether the node is connected to the network. +This can be useful to give feedback to the user, or stop some action (e.g. sending messages) when offline: + +```js +import { HealthStatus } from "@waku/sdk"; + +node.events.addEventListener("waku:health", (event) => { + const health = event.detail; + + if (health === HealthStatus.SufficientlyHealthy) { + // Show to the user they are connected + } else if (status === HealthStatus.MinimallyHealthy) { + // Maybe put some clue to the user that while we are connected, + // there may be issues sending or receiving messages + } else { + // Show to the user they are disconnected from the network + } +}); +``` + +## Create a reliable channel + +You need to choose a channel name: it acts as an identifier to the conversation, participants will try to ensure they all have the same +messages within a given channel. + +```js +const channelName = "channel-number-15" +``` + +Finally, each participant need to identify themselves for reliability purposes, so they can confirm _others_ have received their messages. + +It is up to you how to generate an id. Every participant **must** have a different id. + +```js +const senderId = generateRandomStringId(); +``` + +You can now create a reliable channel: + +```js +import { ReliableChannel } from "@waku/sdk"; + +const reliableChannel = await ReliableChannel.create(node, channelName, senderId, encoder, decoder) +``` + +The channel will automatically start the Waku node and fetch messages. + +## Create a message structure + +Create your application's message structure using [Protobufjs](https://github.com/protobufjs/protobuf.js#usage): + +```js +import protobuf from "protobufjs"; + +// Create a message structure using Protobuf +const DataPacket = new protobuf.Type("DataPacket") + .add(new protobuf.Field("timestamp", 1, "uint64")) + .add(new protobuf.Field("sender", 2, "string")) + .add(new protobuf.Field("message", 3, "string")); +``` + +:::info +Have a look at the [Protobuf installation](/guides/js-waku/#message-structure) guide for adding the `protobufjs` package to your project. +::: + +## Listen to incoming messages + +The reliable channel will emit incoming messages. To process them, simply add a listener: + +```js +reliableChannel.addEventListener("message-received", (event) => { + const wakuMessage = event.detail; + + // decode your payload using the protobuf object previously created + const { timestamp, sender, message } = DataPacket.decode(wakuMessage.payload); + + // ... process the message as you wish +}) +``` + +## Send messages + +To send messages in the reliable channel, encode the message in a payload. + +```js +// Create a new message object +const protoMessage = DataPacket.create({ + timestamp: Date.now(), + sender: "Alice", + message: "Hello, World!", +}); + +// Serialise the message using Protobuf +const serialisedMessage = DataPacket.encode(protoMessage).finish(); +``` + +Then, send the message and setup listeners so you can know when the message: +- has been sent +- has been acknowledged by other participants in the channel +- has encountered an error + +```js +// Send the message, and get the id to track events +const messageId = reliableChannel.send(payload); + +reliableChannel.addEventListener("sending-message-irrecoverable-error", (event) => { + if (messageId === event.detail.messageId) { + console.error('Failed to send message:', event.detail.error); + // Show an error to the user + } +}) + +reliableChannel.addEventListener("message-sent", (event) => { + if (messageId === event.detail) { + // Message sent, show '✔' to the user, etc + } +}) + +reliableChannel.addEventListener("message-acknowledged", (event) => { + if (messageId === event.detail) { + // Message acknowledged by other participants, show '✔✔' to the user, etc + } +}) +``` + +:::tip Congratulations! +You have successfully sent and received messages over the Waku Network using our reliable protocols such as Scalable Data Sync (SDS) and P2P Reliability. +::: \ No newline at end of file diff --git a/sidebars.js b/sidebars.js index 040d1fe..2007aa3 100644 --- a/sidebars.js +++ b/sidebars.js @@ -39,6 +39,7 @@ const sidebars = { id: "guides/js-waku/index", }, items: [ + "guides/js-waku/reliable-channels", "guides/js-waku/light-send-receive", "guides/js-waku/store-retrieve-messages", "guides/js-waku/message-encryption",