JavaScript implementation of Waku v2 https://js.waku.org
Go to file
Franck Royer 0d38e80497
Merge pull request #287 from status-im/wait-for-connected-peer
Added `Waku.waitForConnectedPeer` helper
2021-09-02 16:28:14 +10:00
.github Rename Eth-DM to Eth-PM 2021-08-17 16:06:46 +10:00
.vscode Format json files 2021-05-04 10:49:14 +10:00
examples Added `Waku.waitForConnectedPeer` helper 2021-09-02 15:46:23 +10:00
guides Added `Waku.waitForConnectedPeer` helper 2021-09-02 15:46:23 +10:00
nim-waku@e2c0141edc Upgrade nim-waku submodule to v0.5 2021-07-26 11:32:50 +10:00
proto/waku/v2 Rename all `pubsubTopic` occurrences to `pubSubTopic` 2021-08-20 10:13:02 +10:00
src Added `Waku.waitForConnectedPeer` helper 2021-09-02 15:46:23 +10:00
.cspell.json Add word 2021-08-30 15:13:03 +10:00
.editorconfig Initial commit 2021-03-05 09:34:01 +11:00
.eslintrc.json Exclude test files from build 2021-05-11 14:05:12 +10:00
.gitignore Fix TextDecoder error in tests 2021-08-02 10:45:11 +10:00
.gitmodules Re-add nim-waku submodule 2021-03-19 11:23:34 +11:00
.mocharc.json Move mocha --exit to config file 2021-05-05 09:59:32 +10:00
.prettierignore Use waku messages over waku relay 2021-03-10 16:22:49 +11:00
CHANGELOG.md Added `Waku.waitForConnectedPeer` helper 2021-09-02 15:46:23 +10:00
CONTRIBUTING.md Mention fast-check 2021-07-15 10:36:25 +10:00
LICENSE-APACHE-v2 Apply MIT or Apache V2.0 License 2021-04-28 21:27:26 +10:00
LICENSE-MIT Apply MIT or Apache V2.0 License 2021-04-28 21:27:26 +10:00
README.md Promote dedicated symmetric key generation API 2021-09-02 15:09:31 +10:00
buf.gen.yaml Implement chat message protobuf to support nick and time handles 2021-04-01 11:01:15 +11:00
buf.yaml Use waku messages over waku relay 2021-03-10 16:22:49 +11:00
karma.conf.js Merge karma tsconfig in karma conf 2021-07-15 11:10:19 +10:00
netlify.toml Add netlify config 2021-05-11 10:50:58 +10:00
package-lock.json Run build with NodeJS 16 2021-08-26 13:02:09 +10:00
package.json Remove stub types definition 2021-08-20 14:08:52 +10:00
tsconfig.dev.json Exclude test files from build 2021-05-11 14:05:12 +10:00
tsconfig.json Set sourceMap instead of inline 2021-07-14 11:56:49 +10:00
tsconfig.module.json Exclude test files from build 2021-05-11 14:05:12 +10:00

README.md

NPM

GitHub Action Discord chat

js-waku

A JavaScript implementation of the Waku v2 protocol.

Documentation

In the section below you can find explanations for the main API.

We also have guides available and code examples.

You can read the latest main branch documentation at https://status-im.github.io/js-waku/docs/.

Docs can also be generated locally using:

npm install
npm run doc

Usage

Install js-waku package:

npm install js-waku

Start a waku node

import { Waku } from 'js-waku';

const waku = await Waku.create({ bootstrap: true });

Listen for messages

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 and use an existing contentTopic. See the Waku v2 Topic Usage Recommendations 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:

waku.relay.addObserver((msg) => {
  console.log("Message received:", msg.payloadAsUtf8)
}, ["/my-cool-app/1/my-use-case/proto"]);

The examples chat apps currently use content topic "/toy-chat/2/huilong/proto".

Send messages

There are two ways to send messages:

Waku Relay

Waku Relay is the most decentralized option, peer receiving your messages are unlikely to know whether you are the originator or simply forwarding them. However, it does not give you any delivery information.

import { WakuMessage } from 'js-waku';

const msg = await WakuMessage.fromUtf8String("Here is a message!", "/my-cool-app/1/my-use-case/proto")
await waku.relay.send(msg);

Waku Light Push

Waku Light Push gives you confirmation that the light push server node has received your message. However, it means that said node knows you are the originator of the message. It cannot guarantee that the node will forward the message.

const ack = await waku.lightPush.push(message);
if (!ack?.isSuccess) {
  // Message was not sent
}

Retrieve archived messages

The Waku v2 Store protocol enables more permanent nodes to store messages received via relay and ephemeral clients to retrieve them (e.g. mobile phone resuming connectivity). The protocol implements pagination meaning that it may take several queries to retrieve all messages.

Query a waku store peer to check historical messages:

// Process messages once they are all retrieved
const messages = await waku.store.queryHistory(['/my-cool-app/1/my-use-case/proto']);
messages.forEach((msg) => {
  console.log('Message retrieved:', msg.payloadAsUtf8);
});

// Or, pass a callback function to be executed as pages are received:
waku.store.queryHistory(['/my-cool-app/1/my-use-case/proto'], {
  callback: (messages) => {
    messages.forEach((msg) => {
      console.log('Message retrieved:', msg.payloadAsUtf8);
    });
  }
});

Encryption & Signature

With js-waku, you can:

  • Encrypt messages over the wire using public/private key pair (asymmetric encryption),
  • Encrypt messages over the wire using a unique key to both encrypt and decrypt (symmetric encryption),
  • Sign and verify your waku messages (must use encryption, compatible with both symmetric and asymmetric).

Cryptographic Libraries

A quick note on the cryptographic libraries used as it is a not a straightforward affair:

Create new keys

Asymmetric private keys and symmetric keys are expected to be 32 bytes arrays.

import { generatePrivateKey, generateSymmetricKey, getPublicKey } from 'js-waku';

// Asymmetric
const privateKey = generatePrivateKey();
const publicKey = getPublicKey(privateKey);

// Symmetric
const symKey = generateSymmetricKey();

Encrypt Waku Messages

To encrypt your waku messages, simply pass the encryption key when creating it:

import { WakuMessage } from "js-waku";

// Asymmetric
const message1 = await WakuMessage.fromBytes(payload, myAppContentTopic, {
  encPublicKey: publicKey,
});

// Symmetric
const message2 = await WakuMessage.fromBytes(payload, myAppContentTopic, {
  symKey: symKey,
});

Decrypt Waku Messages

Waku Relay

If you expect to receive encrypted messages then simply add private decryption key(s) to WakuRelay. Waku Relay will attempt to decrypt incoming messages with each keys, both for symmetric and asymmetric encryption. Messages that are successfully decrypted (or received in clear) will be passed to the observers, other messages will be omitted.

// Asymmetric
waku.relay.addDecryptionKey(privateKey);

// Symmetric
waku.relay.addDecryptionKey(symKey);

// Then add the observer
waku.relay.addObserver(callback, [contentTopic]);

Keys can be removed using WakuMessage.deleteDecryptionKey.

Waku Store
const messages = await waku.store.queryHistory([], {
  decryptionKeys: [privateKey, symKey]
});

Similarly to relay, only decrypted or clear messages will be returned.

Sign Waku Messages

As per version 1`s specs, signatures are only included in encrypted messages. In the case where your app does not need encryption then you could use symmetric encryption with a trivial key, I intend to dig more on the subject and come back with recommendation and examples.

Signature keys can be generated the same way asymmetric keys for encryption are:

import { generatePrivateKey, getPublicKey, WakuMessage } from 'js-waku';

const signPrivateKey = generatePrivateKey();

// Asymmetric Encryption
const message1 = await WakuMessage.fromBytes(payload, myAppContentTopic, {
  encPublicKey: recipientPublicKey,
  sigPrivKey: signPrivateKey
});

// Symmetric Encryption
const message2 = await WakuMessage.fromBytes(payload, myAppContentTopic, {
  encPublicKey: symKey,
  sigPrivKey: signPrivateKey
});

Verify Waku Message signatures

Two fields are available on WakuMessage regarding signatures:

  • signaturePublicKey: If the message is signed, it holds the public key of the signature,
  • signature: If the message is signed, it holds the actual signature.

Thus, if you expect messages to be signed by Alice, you can simply compare WakuMessage.signaturePublicKey with Alice's public key. As comparing hex string can lead to issues (is the 0x prefix present?), simply use helper function equalByteArrays.

import { equalByteArrays } from 'js-waku/lib/utils';

const sigPubKey = wakuMessage.signaturePublicKey;

const isSignedByAlice = sigPubKey && equalByteArrays(sigPubKey, alicePublicKey);

Changelog

Release changelog can be found here.

Bugs, Questions & Features

If you encounter any bug or would like to propose new features, feel free to open an issue.

To get help, join #dappconnect-support on Vac Discord or Telegram.

For more general discussion and latest news, join #dappconnect on Vac Discord or Telegram.

Waku Protocol Support

You can track progress on the project board.

  • ✔: Supported
  • 🚧: Implementation in progress
  • : Support is not planned
Spec Implementation Status
6/WAKU1
7/WAKU-DATA
8/WAKU-MAIL
9/WAKU-RPC
10/WAKU2 🚧
11/WAKU2-RELAY
12/WAKU2-FILTER
13/WAKU2-STORE ✔ (querying node only)
14/WAKU2-MESSAGE
15/WAKU2-BRIDGE
16/WAKU2-RPC
17/WAKU2-RLNRELAY
18/WAKU2-SWAP
19/WAKU2-LIGHTPUSH

Contributing

See CONTRIBUTING.md.

License

Licensed and distributed under either of

or

at your option. These files may not be copied, modified, or distributed except according to those terms.