mirror of
https://github.com/logos-messaging/docs.waku.org.git
synced 2026-01-03 21:33:05 +00:00
1 line
12 KiB
JavaScript
1 line
12 KiB
JavaScript
"use strict";(self.webpackChunkwaku_guide=self.webpackChunkwaku_guide||[]).push([[9557],{18765:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>d,contentTitle:()=>o,default:()=>h,frontMatter:()=>i,metadata:()=>a,toc:()=>l});const a=JSON.parse('{"id":"guides/js-waku/reliable-channels","title":"Send and Receive Messages in a Reliable Channel","description":"Learn how to send and receive messages with a convenient SDK that provide various reliable functionalities out-of-the-box.","source":"@site/docs/guides/js-waku/reliable-channels.md","sourceDirName":"guides/js-waku","slug":"/guides/js-waku/reliable-channels","permalink":"/guides/js-waku/reliable-channels","draft":false,"unlisted":false,"editUrl":"https://github.com/waku-org/docs.waku.org/tree/develop/docs/guides/js-waku/reliable-channels.md","tags":[],"version":"current","lastUpdatedAt":null,"frontMatter":{"title":"Send and Receive Messages in a Reliable Channel","hide_table_of_contents":true},"sidebar":"guides","previous":{"title":"JavaScript Waku SDK","permalink":"/guides/js-waku/"},"next":{"title":"Send and Receive Messages Using Light Push and Filter","permalink":"/guides/js-waku/light-send-receive"}}');var t=s(74848),r=s(28453);const i={title:"Send and Receive Messages in a Reliable Channel",hide_table_of_contents:!0},o=void 0,d={},l=[{value:"Import Waku SDK",id:"import-waku-sdk",level:2},{value:"Create a Waku node",id:"create-a-waku-node",level:2},{value:"Create encoders and decoders",id:"create-encoders-and-decoders",level:2},{value:"Listen for connection status",id:"listen-for-connection-status",level:2},{value:"Create a reliable channel",id:"create-a-reliable-channel",level:2},{value:"Create a message structure",id:"create-a-message-structure",level:2},{value:"Listen to incoming messages",id:"listen-to-incoming-messages",level:2},{value:"Send messages",id:"send-messages",level:2}];function c(e){const n={a:"a",admonition:"admonition",code:"code",em:"em",h2:"h2",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,r.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.p,{children:"Learn how to send and receive messages with a convenient SDK that provide various reliable functionalities out-of-the-box."}),"\n",(0,t.jsx)(n.admonition,{type:"warning",children:(0,t.jsxs)(n.p,{children:["This is an experimental feature and has a number of ",(0,t.jsx)(n.a,{href:"https://github.com/waku-org/js-waku/pull/2526",children:"limitations"}),"."]})}),"\n",(0,t.jsx)(n.h2,{id:"import-waku-sdk",children:"Import Waku SDK"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"npm install @waku/sdk@latest\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Or using a CDN, note this is an ESM package so ",(0,t.jsx)(n.code,{children:'type="module"'})," is needed."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-html",children:"<script type=\"module\">\n import {\n createLightNode,\n ReliableChannel\n } from 'https://unpkg.com/@waku/sdk@latest/bundle/index.js';\n\n // Your code here\n \n<\/script>\n"})}),"\n",(0,t.jsx)(n.h2,{id:"create-a-waku-node",children:"Create a Waku node"}),"\n",(0,t.jsxs)(n.p,{children:["Use the ",(0,t.jsx)(n.code,{children:"createLightNode()"})," function to create a ",(0,t.jsx)(n.a,{href:"/learn/glossary#light-node",children:"Light Node"})," and interact with the Waku Network:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",children:'import { createLightNode } from "@waku/sdk";\n\n// Create a Light Node\nconst node = await createLightNode({ defaultBootstrap: true });\n'})}),"\n",(0,t.jsx)(n.admonition,{type:"info",children:(0,t.jsxs)(n.p,{children:["When the ",(0,t.jsx)(n.code,{children:"defaultBootstrap"})," parameter is set to ",(0,t.jsx)(n.code,{children:"true"}),", your node will be bootstrapped using the ",(0,t.jsx)(n.a,{href:"/guides/js-waku/configure-discovery#default-bootstrap-method",children:"default bootstrap method"}),". Have a look at the ",(0,t.jsx)(n.a,{href:"/guides/js-waku/configure-discovery",children:"Bootstrap Nodes and Discover Peers"})," guide to learn more methods to bootstrap nodes."]})}),"\n",(0,t.jsx)(n.h2,{id:"create-encoders-and-decoders",children:"Create encoders and decoders"}),"\n",(0,t.jsxs)(n.p,{children:["Choose a ",(0,t.jsx)(n.a,{href:"/learn/concepts/content-topics",children:"content topic"})," for your application and create a message ",(0,t.jsx)(n.code,{children:"encoder"})," and ",(0,t.jsx)(n.code,{children:"decoder"}),":"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",children:'import { createEncoder, createDecoder } from "@waku/sdk";\n\n// Choose a content topic\nconst ct = "/my-app/1/messages/proto";\n\n// Create a message encoder and decoder\nconst encoder = node.createEncoder({ contentTopic: ct });\nconst decoder = node.createDecoder({ contentTopic: ct });\n'})}),"\n",(0,t.jsxs)(n.p,{children:["You can also use ",(0,t.jsx)(n.a,{href:"/guides/js-waku/message-encryption",children:(0,t.jsx)(n.code,{children:"@waku/message-encryption"})})," to encrypt and decrypt messages using Waku libraries."]}),"\n",(0,t.jsx)(n.admonition,{type:"info",children:(0,t.jsx)(n.p,{children:"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."})}),"\n",(0,t.jsx)(n.h2,{id:"listen-for-connection-status",children:"Listen for connection status"}),"\n",(0,t.jsxs)(n.p,{children:["The Waku node will emit ",(0,t.jsx)(n.code,{children:"health"})," events to help you know whether the node is connected to the network.\nThis can be useful to give feedback to the user, or stop some action (e.g. sending messages) when offline:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",children:'import { HealthStatus } from "@waku/sdk";\n\nnode.events.addEventListener("waku:health", (event) => {\n const health = event.detail;\n \n if (health === HealthStatus.SufficientlyHealthy) {\n // Show to the user they are connected\n } else if (status === HealthStatus.MinimallyHealthy) {\n // Maybe put some clue to the user that while we are connected,\n // there may be issues sending or receiving messages\n } else {\n // Show to the user they are disconnected from the network\n }\n});\n'})}),"\n",(0,t.jsx)(n.h2,{id:"create-a-reliable-channel",children:"Create a reliable channel"}),"\n",(0,t.jsx)(n.p,{children:"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\nmessages within a given channel."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",children:'const channelName = "channel-number-15"\n'})}),"\n",(0,t.jsxs)(n.p,{children:["Finally, each participant need to identify themselves for reliability purposes, so they can confirm ",(0,t.jsx)(n.em,{children:"others"})," have received their messages."]}),"\n",(0,t.jsxs)(n.p,{children:["It is up to you how to generate an id. Every participant ",(0,t.jsx)(n.strong,{children:"must"})," have a different id."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",children:"const senderId = generateRandomStringId();\n"})}),"\n",(0,t.jsx)(n.p,{children:"You can now create a reliable channel:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",children:'import { ReliableChannel } from "@waku/sdk";\n\nconst reliableChannel = await ReliableChannel.create(node, channelName, senderId, encoder, decoder)\n'})}),"\n",(0,t.jsx)(n.p,{children:"The channel will automatically start the Waku node and fetch messages."}),"\n",(0,t.jsx)(n.h2,{id:"create-a-message-structure",children:"Create a message structure"}),"\n",(0,t.jsxs)(n.p,{children:["Create your application's message structure using ",(0,t.jsx)(n.a,{href:"https://github.com/protobufjs/protobuf.js#usage",children:"Protobufjs"}),":"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",children:'import protobuf from "protobufjs";\n\n// Create a message structure using Protobuf\nconst DataPacket = new protobuf.Type("DataPacket")\n .add(new protobuf.Field("timestamp", 1, "uint64"))\n .add(new protobuf.Field("sender", 2, "string"))\n .add(new protobuf.Field("message", 3, "string"));\n'})}),"\n",(0,t.jsx)(n.admonition,{type:"info",children:(0,t.jsxs)(n.p,{children:["Have a look at the ",(0,t.jsx)(n.a,{href:"/guides/js-waku/#message-structure",children:"Protobuf installation"})," guide for adding the ",(0,t.jsx)(n.code,{children:"protobufjs"})," package to your project."]})}),"\n",(0,t.jsx)(n.h2,{id:"listen-to-incoming-messages",children:"Listen to incoming messages"}),"\n",(0,t.jsx)(n.p,{children:"The reliable channel will emit incoming messages. To process them, simply add a listener:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",children:'reliableChannel.addEventListener("message-received", (event) => {\n const wakuMessage = event.detail;\n \n // decode your payload using the protobuf object previously created\n const { timestamp, sender, message } = DataPacket.decode(wakuMessage.payload);\n \n // ... process the message as you wish\n})\n'})}),"\n",(0,t.jsx)(n.h2,{id:"send-messages",children:"Send messages"}),"\n",(0,t.jsx)(n.p,{children:"To send messages in the reliable channel, encode the message in a payload."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",children:'// Create a new message object\nconst protoMessage = DataPacket.create({\n timestamp: Date.now(),\n sender: "Alice",\n message: "Hello, World!",\n});\n\n// Serialise the message using Protobuf\nconst serialisedMessage = DataPacket.encode(protoMessage).finish();\n'})}),"\n",(0,t.jsx)(n.p,{children:"Then, send the message and setup listeners so you can know when the message:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"has been sent"}),"\n",(0,t.jsx)(n.li,{children:"has been acknowledged by other participants in the channel"}),"\n",(0,t.jsx)(n.li,{children:"has encountered an error"}),"\n"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-js",children:"// Send the message, and get the id to track events\nconst messageId = reliableChannel.send(payload);\n \nreliableChannel.addEventListener(\"sending-message-irrecoverable-error\", (event) => {\n if (messageId === event.detail.messageId) {\n console.error('Failed to send message:', event.detail.error);\n // Show an error to the user\n }\n})\n\nreliableChannel.addEventListener(\"message-sent\", (event) => {\n if (messageId === event.detail) {\n // Message sent, show '\u2714' to the user, etc\n }\n})\n\nreliableChannel.addEventListener(\"message-acknowledged\", (event) => {\n if (messageId === event.detail) {\n // Message acknowledged by other participants, show '\u2714\u2714' to the user, etc\n }\n})\n"})}),"\n",(0,t.jsx)(n.admonition,{title:"Congratulations!",type:"tip",children:(0,t.jsx)(n.p,{children:"You have successfully sent and received messages over the Waku Network using our reliable protocols such as Scalable Data Sync (SDS) and P2P Reliability."})})]})}function h(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(c,{...e})}):c(e)}},28453:(e,n,s)=>{s.d(n,{R:()=>i,x:()=>o});var a=s(96540);const t={},r=a.createContext(t);function i(e){const n=a.useContext(r);return a.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:i(e.components),a.createElement(r.Provider,{value:n},e.children)}}}]); |