reliable-channels.md
1 --- 2 title: Send and Receive Messages in a Reliable Channel 3 hide_table_of_contents: true 4 displayed_sidebar: build 5 --- 6 7 Learn how to send and receive messages with a convenient SDK that provide various reliable functionalities out-of-the-box. 8 9 :::warning 10 This is an experimental feature and has a number of [limitations](https://github.com/waku-org/js-waku/pull/2526). 11 ::: 12 13 ## Import Waku SDK 14 15 ```shell 16 npm install @waku/sdk@latest 17 ``` 18 19 Or using a CDN, note this is an ESM package so `type="module"` is needed. 20 21 ```html 22 <script type="module"> 23 import { 24 createLightNode, 25 ReliableChannel 26 } from 'https://unpkg.com/@waku/sdk@latest/bundle/index.js'; 27 28 // Your code here 29 30 </script> 31 ``` 32 33 ## Create a Waku node 34 35 Use the `createLightNode()` function to create a [Light Node](/learn/glossary#light-node) and interact with the Waku Network: 36 37 ```js 38 import { createLightNode } from "@waku/sdk"; 39 40 // Create a Light Node 41 const node = await createLightNode({ defaultBootstrap: true }); 42 ``` 43 44 :::info 45 When the `defaultBootstrap` parameter is set to `true`, your node will be bootstrapped using the [default bootstrap method](/build/javascript/configure-discovery#default-bootstrap-method). Have a look at the [Bootstrap Nodes and Discover Peers](/build/javascript/configure-discovery) guide to learn more methods to bootstrap nodes. 46 ::: 47 48 ## Create encoders and decoders 49 50 Choose a [content topic](/learn/concepts/content-topics) for your application and create a message `encoder` and `decoder`: 51 52 ```js 53 import { createEncoder, createDecoder } from "@waku/sdk"; 54 55 // Choose a content topic 56 const ct = "/my-app/1/messages/proto"; 57 58 // Create a message encoder and decoder 59 const encoder = node.createEncoder({ contentTopic: ct }); 60 const decoder = node.createDecoder({ contentTopic: ct }); 61 ``` 62 63 You can also use [`@waku/message-encryption`](/build/javascript/message-encryption) to encrypt and decrypt messages using Waku libraries. 64 65 :::info 66 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. 67 ::: 68 69 ## Listen for connection status 70 71 The Waku node will emit `health` events to help you know whether the node is connected to the network. 72 This can be useful to give feedback to the user, or stop some action (e.g. sending messages) when offline: 73 74 ```js 75 import { HealthStatus } from "@waku/sdk"; 76 77 node.events.addEventListener("waku:health", (event) => { 78 const health = event.detail; 79 80 if (health === HealthStatus.SufficientlyHealthy) { 81 // Show to the user they are connected 82 } else if (status === HealthStatus.MinimallyHealthy) { 83 // Maybe put some clue to the user that while we are connected, 84 // there may be issues sending or receiving messages 85 } else { 86 // Show to the user they are disconnected from the network 87 } 88 }); 89 ``` 90 91 ## Create a reliable channel 92 93 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 94 messages within a given channel. 95 96 ```js 97 const channelName = "channel-number-15" 98 ``` 99 100 Finally, each participant need to identify themselves for reliability purposes, so they can confirm _others_ have received their messages. 101 102 It is up to you how to generate an id. Every participant **must** have a different id. 103 104 ```js 105 const senderId = generateRandomStringId(); 106 ``` 107 108 You can now create a reliable channel: 109 110 ```js 111 import { ReliableChannel } from "@waku/sdk"; 112 113 const reliableChannel = await ReliableChannel.create(node, channelName, senderId, encoder, decoder) 114 ``` 115 116 The channel will automatically start the Waku node and fetch messages. 117 118 ## Create a message structure 119 120 Create your application's message structure using [Protobufjs](https://github.com/protobufjs/protobuf.js#usage): 121 122 ```js 123 import protobuf from "protobufjs"; 124 125 // Create a message structure using Protobuf 126 const DataPacket = new protobuf.Type("DataPacket") 127 .add(new protobuf.Field("timestamp", 1, "uint64")) 128 .add(new protobuf.Field("sender", 2, "string")) 129 .add(new protobuf.Field("message", 3, "string")); 130 ``` 131 132 :::info 133 Have a look at the [Protobuf installation](/build/javascript/#message-structure) guide for adding the `protobufjs` package to your project. 134 ::: 135 136 ## Listen to incoming messages 137 138 The reliable channel will emit incoming messages. To process them, simply add a listener: 139 140 ```js 141 reliableChannel.addEventListener("message-received", (event) => { 142 const wakuMessage = event.detail; 143 144 // decode your payload using the protobuf object previously created 145 const { timestamp, sender, message } = DataPacket.decode(wakuMessage.payload); 146 147 // ... process the message as you wish 148 }) 149 ``` 150 151 ## Send messages 152 153 To send messages in the reliable channel, encode the message in a payload. 154 155 ```js 156 // Create a new message object 157 const protoMessage = DataPacket.create({ 158 timestamp: Date.now(), 159 sender: "Alice", 160 message: "Hello, World!", 161 }); 162 163 // Serialise the message using Protobuf 164 const serialisedMessage = DataPacket.encode(protoMessage).finish(); 165 ``` 166 167 Then, send the message and setup listeners so you can know when the message: 168 - has been sent 169 - has been acknowledged by other participants in the channel 170 - has encountered an error 171 172 ```js 173 // Send the message, and get the id to track events 174 const messageId = reliableChannel.send(payload); 175 176 reliableChannel.addEventListener("sending-message-irrecoverable-error", (event) => { 177 if (messageId === event.detail.messageId) { 178 console.error('Failed to send message:', event.detail.error); 179 // Show an error to the user 180 } 181 }) 182 183 reliableChannel.addEventListener("message-sent", (event) => { 184 if (messageId === event.detail) { 185 // Message sent, show '✔' to the user, etc 186 } 187 }) 188 189 reliableChannel.addEventListener("message-acknowledged", (event) => { 190 if (messageId === event.detail) { 191 // Message acknowledged by other participants, show '✔✔' to the user, etc 192 } 193 }) 194 ``` 195 196 :::tip Congratulations! 197 You have successfully sent and received messages over the Waku Network using our reliable protocols such as Scalable Data Sync (SDS) and P2P Reliability. 198 :::