2021-05-13 06:49:29 +00:00
# js-waku
2021-03-04 22:34:01 +00:00
2021-05-12 03:18:37 +00:00
A JavaScript implementation of the [Waku v2 protocol ](https://rfc.vac.dev/spec/10/ ).
2021-03-15 03:35:10 +00:00
2021-05-12 03:18:37 +00:00
## Usage
2021-05-10 06:52:53 +00:00
2021-05-13 06:49:29 +00:00
Install `js-waku` package:
2021-05-12 03:18:37 +00:00
```shell
2021-05-13 06:49:29 +00:00
npm install js-waku
2021-05-12 03:18:37 +00:00
```
2021-07-16 01:10:29 +00:00
### Start a waku node
2021-05-12 03:18:37 +00:00
2021-07-16 01:10:29 +00:00
```ts
2021-05-13 06:49:29 +00:00
import { Waku } from 'js-waku';
2021-05-12 03:18:37 +00:00
const waku = await Waku.create();
```
2021-07-16 01:10:29 +00:00
### Connect to a new peer
2021-05-12 03:18:37 +00:00
2021-07-16 01:10:29 +00:00
```ts
2021-05-13 01:51:39 +00:00
// Directly dial a new peer
2021-05-14 03:56:00 +00:00
await waku.dial('/dns4/node-01.do-ams3.wakuv2.test.statusim.net/tcp/443/wss/p2p/16Uiu2HAmPLe7Mzm8TsYUubgCAW1aJoeFScxrLj8ppHFivPo97bUZ');
2021-05-13 01:51:39 +00:00
// Or, add peer to address book so it auto dials in the background
2021-05-13 01:47:03 +00:00
waku.addPeerToAddressBook(
'16Uiu2HAmPLe7Mzm8TsYUubgCAW1aJoeFScxrLj8ppHFivPo97bUZ',
2021-05-14 03:56:00 +00:00
['/dns4/node-01.do-ams3.wakuv2.test.statusim.net/tcp/443/wss']
2021-05-12 03:18:37 +00:00
);
```
2021-05-15 10:42:54 +00:00
You can also use `getStatusFleetNodes` to connect to nodes run by Status:
2021-07-16 01:10:29 +00:00
```ts
2021-05-15 10:42:54 +00:00
import { getStatusFleetNodes } from 'js-waku';
2021-07-16 01:10:29 +00:00
getStatusFleetNodes().then((nodes) => {
nodes.forEach((addr) => {
waku.dial(addr);
});
});
2021-05-15 10:42:54 +00:00
```
2021-07-16 01:10:29 +00:00
### Listen for messages
2021-05-12 03:18:37 +00:00
The `contentTopic` is a metadata `string` that allows categorization of messages on the waku network.
2021-05-14 05:58:09 +00:00
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` .
2021-06-01 06:07:44 +00:00
See the [Waku v2 Topic Usage Recommendations ](https://rfc.vac.dev/spec/23/ ) for more details.
2021-05-12 03:18:37 +00:00
2021-06-01 06:07:44 +00:00
For example, if you were to use a new `contentTopic` such as `/my-cool-app/1/my-use-case/proto` ,
2021-05-14 05:58:09 +00:00
here is how to listen to new messages received via [Waku v2 Relay ](https://rfc.vac.dev/spec/11/ ):
2021-05-12 03:18:37 +00:00
2021-07-16 01:10:29 +00:00
```ts
2021-05-12 03:18:37 +00:00
waku.relay.addObserver((msg) => {
console.log("Message received:", msg.payloadAsUtf8)
2021-06-01 06:07:44 +00:00
}, ["/my-cool-app/1/my-use-case/proto"]);
2021-05-12 03:18:37 +00:00
```
2021-06-01 05:27:14 +00:00
The examples chat apps currently use content topic `"/toy-chat/2/huilong/proto"` .
2021-05-14 05:58:09 +00:00
2021-07-16 01:10:29 +00:00
### Send messages
There are two ways to send messages:
#### Waku Relay
2021-07-16 01:26:37 +00:00
[Waku Relay ](https://rfc.vac.dev/spec/11/ ) is the most decentralized option,
2021-07-16 01:10:29 +00:00
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.
2021-05-12 03:18:37 +00:00
2021-07-16 01:10:29 +00:00
```ts
2021-05-13 06:49:29 +00:00
import { WakuMessage } from 'js-waku';
2021-05-12 03:18:37 +00:00
2021-07-28 01:19:24 +00:00
const msg = await WakuMessage.fromUtf8String("Here is a message!", "/my-cool-app/1/my-use-case/proto")
2021-05-12 03:18:37 +00:00
await waku.relay.send(msg);
```
2021-07-16 01:10:29 +00:00
#### Waku Light Push
[Waku Light Push ](https://rfc.vac.dev/spec/19/ ) 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.
```ts
const ack = await waku.lightPush.push(message);
if (!ack?.isSuccess) {
// Message was not sent
}
```
### Retrieve archived messages
The [Waku v2 Store protocol ](https://rfc.vac.dev/spec/13/ ) enables more permanent nodes to store messages received via relay
and ephemeral clients to retrieve them (e.g. mobile phone resuming connectivity).
2021-05-12 03:18:37 +00:00
The protocol implements pagination meaning that it may take several queries to retrieve all messages.
Query a waku store peer to check historical messages:
2021-07-16 01:10:29 +00:00
```ts
// Process messages once they are all retrieved
const messages = await waku.store.queryHistory({ contentTopics: ["/my-cool-app/1/my-use-case/proto"] });
2021-05-12 03:18:37 +00:00
messages.forEach((msg) => {
console.log("Message retrieved:", msg.payloadAsUtf8)
})
// Or, pass a callback function to be executed as pages are received:
2021-07-15 05:02:16 +00:00
waku.store.queryHistory({
2021-07-16 01:10:29 +00:00
contentTopics: ["/my-cool-app/1/my-use-case/proto"],
2021-07-15 05:02:16 +00:00
callback: (messages) => {
messages.forEach((msg) => {
console.log("Message retrieved:", msg.payloadAsUtf8);
});
}
2021-05-12 03:18:37 +00:00
});
```
2021-07-16 02:19:06 +00:00
### Encryption & Signature
2021-07-16 01:17:11 +00:00
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).
2021-07-16 02:19:06 +00:00
#### Cryptographic Libraries
2021-07-16 01:17:11 +00:00
A quick note on the cryptographic libraries used as it is a not a straightforward affair:
2021-07-16 01:22:48 +00:00
- Asymmetric encryption:
Uses [ecies-geth ](https://github.com/cyrildever/ecies-geth/ )
which in turns uses [SubtleCrypto ](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto ) Web API (browser),
[secp256k1 ](https://www.npmjs.com/package/secp256k1 ) (native binding for node)
or [elliptic ](https://www.npmjs.com/package/elliptic ) (pure JS if none of the other libraries are available).
- Symmetric encryption:
Uses [SubtleCrypto ](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto ) Web API (browser)
or [NodeJS' crypto ](https://nodejs.org/api/crypto.html ) module.
2021-07-16 01:17:11 +00:00
### Create new keys
Asymmetric private keys and symmetric keys are expected to be 32 bytes arrays.
```ts
import { generatePrivateKey, getPublicKey } from 'js-waku';
// Asymmetric
const privateKey = generatePrivateKey();
const publicKey = getPublicKey(privateKey);
// Symmetric
const symKey = generatePrivateKey();
```
2021-07-16 02:19:06 +00:00
#### Encrypt Waku Messages
2021-07-16 01:17:11 +00:00
To encrypt your waku messages, simply pass the encryption key when creating it:
```ts
2021-07-28 01:19:24 +00:00
import { WakuMessage } from "js-waku";
2021-07-16 01:17:11 +00:00
// Asymmetric
2021-07-28 01:19:24 +00:00
const message1 = await WakuMessage.fromBytes(payload, myAppContentTopic, {
encPublicKey: publicKey,
});
2021-07-16 01:17:11 +00:00
// Symmetric
2021-07-28 01:19:24 +00:00
const message2 = await WakuMessage.fromBytes(payload, myAppContentTopic, {
symKey: symKey,
});
2021-07-16 01:17:11 +00:00
```
2021-07-16 02:19:06 +00:00
#### Decrypt Waku Messages
2021-07-16 01:17:11 +00:00
2021-07-16 02:19:06 +00:00
##### Waku Relay
2021-07-16 01:17:11 +00:00
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.
2021-07-16 01:26:37 +00:00
Messages that are successfully decrypted (or received in clear) will be passed to the observers, other messages will be omitted.
2021-07-16 01:17:11 +00:00
```ts
// 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` .
2021-07-16 02:19:06 +00:00
##### Waku Store
2021-07-16 01:17:11 +00:00
```ts
const messages = await waku.store.queryHistory({
contentTopics: [],
decryptionKeys: [privateKey, symKey],
});
```
Similarly to relay, only decrypted or clear messages will be returned.
2021-07-16 02:19:06 +00:00
#### Sign Waku Messages
2021-07-16 01:17:11 +00:00
As per version 1`s [specs ](https://rfc.vac.dev/spec/26/ ), 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 ](https://github.com/status-im/js-waku/issues/74#issuecomment-880440186 ) and come back with recommendation and examples.
Signature keys can be generated the same way asymmetric keys for encryption are:
```ts
2021-07-28 01:19:24 +00:00
import { generatePrivateKey, getPublicKey, WakuMessage } from "js-waku";
2021-07-16 01:17:11 +00:00
const signPrivateKey = generatePrivateKey();
// Asymmetric Encryption
2021-07-28 01:19:24 +00:00
const message1 = await WakuMessage.fromBytes(payload, myAppContentTopic, {
encPublicKey: recipientPublicKey,
sigPrivKey: signPrivateKey,
});
2021-07-16 01:17:11 +00:00
// Symmetric Encryption
2021-07-28 01:19:24 +00:00
const message2 = await WakuMessage.fromBytes(payload, myAppContentTopic, {
encPublicKey: symKey,
sigPrivKey: signPrivateKey,
});
2021-07-16 01:17:11 +00:00
```
2021-07-16 02:19:06 +00:00
#### Verify Waku Message signatures
2021-07-16 01:17:11 +00:00
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` .
```ts
import { equalByteArrays } from 'js-waku/lib/utils';
const sigPubKey = wakuMessage.signaturePublicKey;
const isSignedByAlice = sigPubKey & & equalByteArrays(sigPubKey, alicePublicKey);
```
2021-07-16 01:10:29 +00:00
## More documentation
2021-05-12 03:18:37 +00:00
Find more [examples ](#examples ) below
2021-05-13 06:49:29 +00:00
or checkout the latest `main` branch documentation at [https://status-im.github.io/js-waku/docs/ ](https://status-im.github.io/js-waku/docs/ ).
2021-05-10 06:52:53 +00:00
Docs can also be generated locally using:
```shell
npm install
npm run doc
```
2021-05-15 10:59:52 +00:00
## Changelog
Release changelog can be found [here ](https://github.com/status-im/js-waku/blob/main/CHANGELOG.md ).
2021-04-09 01:55:41 +00:00
## Waku Protocol Support
2021-05-13 06:49:29 +00:00
You can track progress on the [project board ](https://github.com/status-im/js-waku/projects/1 ).
2021-04-13 00:56:13 +00:00
2021-04-09 01:55:41 +00:00
- ✔: Supported
- 🚧: Implementation in progress
- ⛔: Support is not planned
| Spec | Implementation Status |
| ---- | -------------- |
|[6/WAKU1](https://rfc.vac.dev/spec/6)|⛔|
|[7/WAKU-DATA](https://rfc.vac.dev/spec/7)|⛔|
|[8/WAKU-MAIL](https://rfc.vac.dev/spec/8)|⛔|
|[9/WAKU-RPC](https://rfc.vac.dev/spec/9)|⛔|
|[10/WAKU2](https://rfc.vac.dev/spec/10)|🚧|
|[11/WAKU2-RELAY](https://rfc.vac.dev/spec/11)|✔|
|[12/WAKU2-FILTER](https://rfc.vac.dev/spec/12)||
2021-04-20 00:24:03 +00:00
|[13/WAKU2-STORE](https://rfc.vac.dev/spec/13)|✔ (querying node only)|
2021-04-09 01:55:41 +00:00
|[14/WAKU2-MESSAGE](https://rfc.vac.dev/spec/14)|✔|
|[15/WAKU2-BRIDGE](https://rfc.vac.dev/spec/15)||
|[16/WAKU2-RPC](https://rfc.vac.dev/spec/16)|⛔|
|[17/WAKU2-RLNRELAY](https://rfc.vac.dev/spec/17)||
|[18/WAKU2-SWAP](https://rfc.vac.dev/spec/18)||
2021-05-19 01:00:43 +00:00
|[19/WAKU2-LIGHTPUSH](https://rfc.vac.dev/spec/19/)|✔|
2021-04-09 01:55:41 +00:00
2021-04-13 00:56:13 +00:00
## Bugs, Questions & Features
2021-04-01 00:09:51 +00:00
2021-05-13 06:49:29 +00:00
If you encounter any bug or would like to propose new features, feel free to [open an issue ](https://github.com/status-im/js-waku/issues/new/ ).
2021-04-13 00:56:13 +00:00
2021-07-28 06:59:42 +00:00
To get help, join #dappconnect -support on [Vac Discord ](https://discord.gg/j5pGbn7MHZ ) or [Telegram ](https://t.me/dappconnectsupport ).
For more general discussion and latest news, join #dappconnect on [Vac Discord ](https://discord.gg/9DgykdmpZ6 ) or [Telegram ](https://t.me/dappconnect ).
2021-04-01 00:09:51 +00:00
## Examples
2021-04-27 23:53:33 +00:00
## Web Chat App (ReactJS)
2021-05-12 03:18:37 +00:00
A ReactJS chat app is provided as a showcase of the library used in the browser.
2021-06-01 06:10:03 +00:00
It implements [Waku v2 Toy Chat ](https://rfc.vac.dev/spec/22/ ) protocol.
A deployed version is available at https://status-im.github.io/js-waku/.
2021-04-27 23:53:33 +00:00
2021-05-13 06:49:29 +00:00
Find the code in the [examples folder ](https://github.com/status-im/js-waku/tree/main/examples/web-chat ).
2021-05-12 03:18:37 +00:00
2021-04-27 23:53:33 +00:00
To run a development version locally, do:
```shell
2021-05-13 06:49:29 +00:00
git clone https://github.com/status-im/js-waku/ ; cd js-waku
npm install # Install dependencies for js-waku
npm run build # Build js-waku
2021-05-05 04:57:46 +00:00
cd examples/web-chat
2021-05-03 06:34:52 +00:00
npm install # Install dependencies for the web app
2021-05-13 06:49:29 +00:00
npm run start # Start development server to serve the web app on http://localhost:3000/js-waku
2021-04-27 23:53:33 +00:00
```
2021-05-03 06:34:52 +00:00
Use `/help` to see the available commands.
2021-04-27 23:53:33 +00:00
## CLI Chat App (NodeJS)
2021-04-01 00:09:51 +00:00
A node chat app is provided as a working example of the library.
2021-06-01 06:10:03 +00:00
It implements [Waku v2 Toy Chat ](https://rfc.vac.dev/spec/22/ ) protocol.
2021-05-12 03:18:37 +00:00
2021-05-13 06:49:29 +00:00
Find the code in the [examples folder ](https://github.com/status-im/js-waku/tree/main/examples/cli-chat ).
2021-05-12 03:18:37 +00:00
2021-04-23 06:33:53 +00:00
To run the chat app, first ensure you have [Node.js ](https://nodejs.org/en/ ) v14 or above:
```shell
node --version
```
Then, install and run:
2021-04-01 00:09:51 +00:00
```shell
2021-05-13 06:49:29 +00:00
git clone https://github.com/status-im/js-waku/ ; cd js-waku
npm install # Install dependencies for js-waku
npm run build # Build js-waku
2021-05-04 05:12:36 +00:00
cd examples/cli-chat
npm install # Install dependencies for the cli app
2021-05-14 03:23:44 +00:00
npm run start -- --autoDial
2021-04-01 00:09:51 +00:00
```
2021-04-23 06:33:53 +00:00
You can also specify an optional `listenAddr` parameter (.e.g `--listenAddr /ip4/0.0.0.0/tcp/7777/ws` ).
2021-04-01 04:46:14 +00:00
This is only useful if you want a remote node to dial to your chat app,
it is not necessary in normal usage when you just connect to the fleet.
2021-03-15 05:22:26 +00:00
2021-06-21 05:48:56 +00:00
## Ethereum Direct Message
A PoC implementation of [20/ETH-DM ](https://rfc.vac.dev/spec/20/ ).
Ethereum Direct Message, or Eth-DM, is a protocol that allows sending encrypted message to a recipient,
only knowing their Ethereum Address.
This is protocol has been created to demonstrated how encryption and signature could be added to messages
sent over the Waku v2 network.
The `main` branch's HEAD is deployed on GitHub Pages at https://status-im.github.io/js-waku/eth-dm/.
To run a development version locally, do:
```shell
git clone https://github.com/status-im/js-waku/ ; cd js-waku
npm install # Install dependencies for js-waku
npm run build # Build js-waku
cd examples/eth-dm
npm install # Install dependencies for the web app
npm run start # Start development server to serve the web app on http://localhost:3000/js-waku/eth-dm
```
2021-03-15 05:22:26 +00:00
## Contributing
2021-04-29 05:22:49 +00:00
See [CONTRIBUTING.md ](./CONTRIBUTING.md ).
2021-04-28 06:29:43 +00:00
## License
Licensed and distributed under either of
* MIT license: [LICENSE-MIT ](LICENSE-MIT ) or http://opensource.org/licenses/MIT
or
* Apache License, Version 2.0, ([LICENSE-APACHE-v2](LICENSE-APACHE-v2) or http://www.apache.org/licenses/LICENSE-2.0)
at your option. These files may not be copied, modified, or distributed except according to those terms.