diff --git a/CHANGELOG.md b/CHANGELOG.md index 84ae53c1a8..e5d2da8846 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,8 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Changed +- **Breaking**: The `WakuMessage` APIs have been changed to move `contentTopic` out of the optional parameters. + ### Removed - Examples (web-chat): Remove broken `/fleet` command. +- **Breaking**: Removed `DefaultContentTopic` as developers must choose a content topic for their app; + recommendations for content topic can be found at https://rfc.vac.dev/spec/23/. ## [0.9.0] - 2021-07-26 diff --git a/README.md b/README.md index ef426d12ff..4e40a1681d 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,7 @@ However, it does not give you any delivery information. ```ts import { WakuMessage } from 'js-waku'; -const msg = await WakuMessage.fromUtf8String("Here is a message!", { contentTopic: "/my-cool-app/1/my-use-case/proto" }) +const msg = await WakuMessage.fromUtf8String("Here is a message!", "/my-cool-app/1/my-use-case/proto") await waku.relay.send(msg); ``` @@ -157,19 +157,18 @@ const symKey = generatePrivateKey(); To encrypt your waku messages, simply pass the encryption key when creating it: ```ts -import { WakuMessage } from 'js-waku'; +import { WakuMessage } from "js-waku"; // Asymmetric -const message = await WakuMessage.fromBytes(payload, { - contentTopic: myAppContentTopic, - encPublicKey: publicKey, - }); +const message1 = await WakuMessage.fromBytes(payload, myAppContentTopic, { + encPublicKey: publicKey, +}); // Symmetric -const message = await WakuMessage.fromBytes(payload, { - contentTopic: myAppContentTopic, - symKey: symKey, - }); +const message2 = await WakuMessage.fromBytes(payload, myAppContentTopic, { + symKey: symKey, +}); + ``` #### Decrypt Waku Messages @@ -212,23 +211,22 @@ In the case where your app does not need encryption then you could use symmetric Signature keys can be generated the same way asymmetric keys for encryption are: ```ts -import { generatePrivateKey, getPublicKey, WakuMessage } from 'js-waku'; +import { generatePrivateKey, getPublicKey, WakuMessage } from "js-waku"; const signPrivateKey = generatePrivateKey(); // Asymmetric Encryption -const message = await WakuMessage.fromBytes(payload, { - contentTopic: myAppContentTopic, - encPublicKey: recipientPublicKey, - sigPrivKey: signPrivateKey - }); +const message1 = await WakuMessage.fromBytes(payload, myAppContentTopic, { + encPublicKey: recipientPublicKey, + sigPrivKey: signPrivateKey, +}); // Symmetric Encryption -const message = await WakuMessage.fromBytes(payload, { - contentTopic: myAppContentTopic, - encPublicKey: symKey, - sigPrivKey: signPrivateKey - }); +const message2 = await WakuMessage.fromBytes(payload, myAppContentTopic, { + encPublicKey: symKey, + sigPrivKey: signPrivateKey, +}); + ``` #### Verify Waku Message signatures diff --git a/src/lib/waku.ts b/src/lib/waku.ts index 5369e4a0c0..49c813cd5b 100644 --- a/src/lib/waku.ts +++ b/src/lib/waku.ts @@ -246,9 +246,9 @@ export class Waku { if (relayPeriodSecs !== 0) { this.relayKeepAliveTimers[peerIdStr] = setInterval(() => { - WakuMessage.fromBytes(new Uint8Array(), { - contentTopic: RelayPingContentTopic, - }).then((wakuMsg) => this.relay.send(wakuMsg)); + WakuMessage.fromBytes(new Uint8Array(), RelayPingContentTopic).then( + (wakuMsg) => this.relay.send(wakuMsg) + ); }, relayPeriodSecs * 1000); } } diff --git a/src/lib/waku_light_push/index.spec.ts b/src/lib/waku_light_push/index.spec.ts index f653db86a6..fa7b7f110a 100644 --- a/src/lib/waku_light_push/index.spec.ts +++ b/src/lib/waku_light_push/index.spec.ts @@ -8,6 +8,8 @@ import { delay } from '../delay'; import { Waku } from '../waku'; import { WakuMessage } from '../waku_message'; +const TestContentTopic = '/test/1/waku-light-push/utf8'; + describe('Waku Light Push', () => { let waku: Waku; let nimWaku: NimWaku; @@ -35,7 +37,10 @@ describe('Waku Light Push', () => { }); const messageText = 'Light Push works!'; - const message = await WakuMessage.fromUtf8String(messageText); + const message = await WakuMessage.fromUtf8String( + messageText, + TestContentTopic + ); const pushResponse = await waku.lightPush.push(message); expect(pushResponse?.isSuccess).to.be.true; @@ -75,7 +80,10 @@ describe('Waku Light Push', () => { const nimPeerId = await nimWaku.getPeerId(); const messageText = 'Light Push works!'; - const message = await WakuMessage.fromUtf8String(messageText); + const message = await WakuMessage.fromUtf8String( + messageText, + TestContentTopic + ); const pushResponse = await waku.lightPush.push(message, { peerId: nimPeerId, diff --git a/src/lib/waku_message/index.browser.spec.ts b/src/lib/waku_message/index.browser.spec.ts index ffb76e6a78..0b8bf5c540 100644 --- a/src/lib/waku_message/index.browser.spec.ts +++ b/src/lib/waku_message/index.browser.spec.ts @@ -5,11 +5,13 @@ import { getPublicKey } from './version_1'; import { WakuMessage } from './index'; +const TestContentTopic = '/test/1/waku-message/utf8'; + describe('Waku Message: Browser & Node', function () { it('Waku message round trip binary serialization [clear]', async function () { await fc.assert( fc.asyncProperty(fc.string(), async (s) => { - const msg = await WakuMessage.fromUtf8String(s); + const msg = await WakuMessage.fromUtf8String(s, TestContentTopic); const binary = msg.encode(); const actual = await WakuMessage.decode(binary); @@ -21,7 +23,7 @@ describe('Waku Message: Browser & Node', function () { it('Payload to utf-8', async function () { await fc.assert( fc.asyncProperty(fc.string(), async (s) => { - const msg = await WakuMessage.fromUtf8String(s); + const msg = await WakuMessage.fromUtf8String(s, TestContentTopic); const utf8 = msg.payloadAsUtf8; return utf8 === s; @@ -37,7 +39,7 @@ describe('Waku Message: Browser & Node', function () { async (payload, privKey) => { const publicKey = getPublicKey(privKey); - const msg = await WakuMessage.fromBytes(payload, { + const msg = await WakuMessage.fromBytes(payload, TestContentTopic, { encPublicKey: publicKey, }); @@ -60,7 +62,7 @@ describe('Waku Message: Browser & Node', function () { const sigPubKey = getPublicKey(sigPrivKey); const encPubKey = getPublicKey(encPrivKey); - const msg = await WakuMessage.fromBytes(payload, { + const msg = await WakuMessage.fromBytes(payload, TestContentTopic, { encPublicKey: encPubKey, sigPrivKey: sigPrivKey, }); @@ -81,7 +83,7 @@ describe('Waku Message: Browser & Node', function () { fc.uint8Array({ minLength: 1 }), fc.uint8Array({ minLength: 32, maxLength: 32 }), async (payload, key) => { - const msg = await WakuMessage.fromBytes(payload, { + const msg = await WakuMessage.fromBytes(payload, TestContentTopic, { symKey: key, }); @@ -103,7 +105,7 @@ describe('Waku Message: Browser & Node', function () { async (payload, sigPrivKey, symKey) => { const sigPubKey = getPublicKey(sigPrivKey); - const msg = await WakuMessage.fromBytes(payload, { + const msg = await WakuMessage.fromBytes(payload, TestContentTopic, { symKey: symKey, sigPrivKey: sigPrivKey, }); diff --git a/src/lib/waku_message/index.spec.ts b/src/lib/waku_message/index.spec.ts index 77c2c36bff..7cb6a6ae79 100644 --- a/src/lib/waku_message/index.spec.ts +++ b/src/lib/waku_message/index.spec.ts @@ -16,10 +16,12 @@ import { Waku } from '../waku'; import { generatePrivateKey, getPublicKey } from './version_1'; -import { DefaultContentTopic, WakuMessage } from './index'; +import { WakuMessage } from './index'; const dbg = debug('waku:test:message'); +const TestContentTopic = '/test/1/waku-message/utf8'; + describe('Waku Message: Node only', function () { describe('Interop: Nim', function () { let waku: Waku; @@ -56,7 +58,7 @@ describe('Waku Message: Node only', function () { const messageText = 'Here is an encrypted message.'; const message: WakuRelayMessage = { - contentTopic: DefaultContentTopic, + contentTopic: TestContentTopic, payload: Buffer.from(messageText, 'utf-8').toString('hex'), }; @@ -89,9 +91,13 @@ describe('Waku Message: Node only', function () { const publicKey = hexToBuf(keyPair.publicKey); const messageText = 'This is a message I am going to encrypt'; - const message = await WakuMessage.fromUtf8String(messageText, { - encPublicKey: publicKey, - }); + const message = await WakuMessage.fromUtf8String( + messageText, + TestContentTopic, + { + encPublicKey: publicKey, + } + ); await waku.relay.send(message); @@ -112,7 +118,7 @@ describe('Waku Message: Node only', function () { const messageText = 'Here is a message encrypted in a symmetric manner.'; const message: WakuRelayMessage = { - contentTopic: DefaultContentTopic, + contentTopic: TestContentTopic, payload: Buffer.from(messageText, 'utf-8').toString('hex'), }; @@ -143,9 +149,13 @@ describe('Waku Message: Node only', function () { const messageText = 'This is a message I am going to encrypt with a symmetric key'; - const message = await WakuMessage.fromUtf8String(messageText, { - symKey: symKey, - }); + const message = await WakuMessage.fromUtf8String( + messageText, + TestContentTopic, + { + symKey: symKey, + } + ); await waku.relay.send(message); diff --git a/src/lib/waku_message/index.ts b/src/lib/waku_message/index.ts index 5de1e73a7c..1f3289fcc9 100644 --- a/src/lib/waku_message/index.ts +++ b/src/lib/waku_message/index.ts @@ -9,16 +9,10 @@ import * as proto from '../../proto/waku/v2/message'; import * as version_1 from './version_1'; -export const DefaultContentTopic = '/waku/2/default-content/proto'; const DefaultVersion = 0; const dbg = debug('waku:message'); export interface Options { - /** - * Content topic to set on the message, defaults to {@link DefaultContentTopic} - * if not passed. - */ - contentTopic?: string; /** * Timestamp to set on the message, defaults to now if not passed. */ @@ -54,10 +48,11 @@ export class WakuMessage { */ static async fromUtf8String( utf8: string, + contentTopic: string, opts?: Options ): Promise { const payload = Buffer.from(utf8, 'utf-8'); - return WakuMessage.fromBytes(payload, opts); + return WakuMessage.fromBytes(payload, contentTopic, opts); } /** @@ -74,13 +69,13 @@ export class WakuMessage { */ static async fromBytes( payload: Uint8Array, + contentTopic: string, opts?: Options ): Promise { - const { timestamp, contentTopic, encPublicKey, symKey, sigPrivKey } = - Object.assign( - { timestamp: new Date(), contentTopic: DefaultContentTopic }, - opts ? opts : {} - ); + const { timestamp, encPublicKey, symKey, sigPrivKey } = Object.assign( + { timestamp: new Date() }, + opts ? opts : {} + ); let _payload = payload; let version = DefaultVersion; diff --git a/src/lib/waku_relay/index.spec.ts b/src/lib/waku_relay/index.spec.ts index d9c0c9eb15..cd1fdd6153 100644 --- a/src/lib/waku_relay/index.spec.ts +++ b/src/lib/waku_relay/index.spec.ts @@ -18,6 +18,8 @@ import { DefaultPubsubTopic } from './index'; const log = debug('waku:test'); +const TestContentTopic = '/test/1/waku-relay/utf8'; + describe('Waku Relay', () => { describe('js only', () => { afterEach(function () { @@ -81,9 +83,13 @@ describe('Waku Relay', () => { const messageText = 'JS to JS communication works'; const messageTimestamp = new Date('1995-12-17T03:24:00'); - const message = await WakuMessage.fromUtf8String(messageText, { - timestamp: messageTimestamp, - }); + const message = await WakuMessage.fromUtf8String( + messageText, + TestContentTopic, + { + timestamp: messageTimestamp, + } + ); const receivedMsgPromise: Promise = new Promise( (resolve) => { @@ -108,12 +114,14 @@ describe('Waku Relay', () => { const fooMessageText = 'Published on content topic foo'; const barMessageText = 'Published on content topic bar'; - const fooMessage = await WakuMessage.fromUtf8String(fooMessageText, { - contentTopic: 'foo', - }); - const barMessage = await WakuMessage.fromUtf8String(barMessageText, { - contentTopic: 'bar', - }); + const fooMessage = await WakuMessage.fromUtf8String( + fooMessageText, + 'foo' + ); + const barMessage = await WakuMessage.fromUtf8String( + barMessageText, + 'bar' + ); const receivedBarMsgPromise: Promise = new Promise( (resolve) => { @@ -148,9 +156,10 @@ describe('Waku Relay', () => { const messageText = 'Published on content topic with added then deleted observer'; - const message = await WakuMessage.fromUtf8String(messageText, { - contentTopic: 'added-then-deleted-observer', - }); + const message = await WakuMessage.fromUtf8String( + messageText, + 'added-then-deleted-observer' + ); // The promise **fails** if we receive a message on this observer. const receivedMsgPromise: Promise = new Promise( @@ -207,7 +216,10 @@ describe('Waku Relay', () => { ]); const messageText = 'Communicating using a custom pubsub topic'; - const message = await WakuMessage.fromUtf8String(messageText); + const message = await WakuMessage.fromUtf8String( + messageText, + TestContentTopic + ); const waku2ReceivedMsgPromise: Promise = new Promise( (resolve) => { @@ -278,7 +290,10 @@ describe('Waku Relay', () => { this.timeout(5000); const messageText = 'This is a message'; - const message = await WakuMessage.fromUtf8String(messageText); + const message = await WakuMessage.fromUtf8String( + messageText, + TestContentTopic + ); await waku.relay.send(message); @@ -297,7 +312,10 @@ describe('Waku Relay', () => { it('Nim publishes to js', async function () { this.timeout(5000); const messageText = 'Here is another message.'; - const message = await WakuMessage.fromUtf8String(messageText); + const message = await WakuMessage.fromUtf8String( + messageText, + TestContentTopic + ); const receivedMsgPromise: Promise = new Promise( (resolve) => { @@ -363,7 +381,10 @@ describe('Waku Relay', () => { this.timeout(30000); const messageText = 'This is a message'; - const message = await WakuMessage.fromUtf8String(messageText); + const message = await WakuMessage.fromUtf8String( + messageText, + TestContentTopic + ); await delay(1000); await waku.relay.send(message); @@ -384,7 +405,10 @@ describe('Waku Relay', () => { await delay(200); const messageText = 'Here is another message.'; - const message = await WakuMessage.fromUtf8String(messageText); + const message = await WakuMessage.fromUtf8String( + messageText, + TestContentTopic + ); const receivedMsgPromise: Promise = new Promise( (resolve) => { @@ -466,7 +490,10 @@ describe('Waku Relay', () => { ).to.be.false; const msgStr = 'Hello there!'; - const message = await WakuMessage.fromUtf8String(msgStr); + const message = await WakuMessage.fromUtf8String( + msgStr, + TestContentTopic + ); const waku2ReceivedMsgPromise: Promise = new Promise( (resolve) => { diff --git a/src/lib/waku_store/index.spec.ts b/src/lib/waku_store/index.spec.ts index 79a6d9436e..53cc942b34 100644 --- a/src/lib/waku_store/index.spec.ts +++ b/src/lib/waku_store/index.spec.ts @@ -12,13 +12,15 @@ import { } from '../../test_utils'; import { delay } from '../delay'; import { Waku } from '../waku'; -import { DefaultContentTopic, WakuMessage } from '../waku_message'; +import { WakuMessage } from '../waku_message'; import { generatePrivateKey, getPublicKey } from '../waku_message/version_1'; import { Direction } from './history_rpc'; const dbg = debug('waku:test:store'); +const TestContentTopic = '/test/1/waku-store/utf8'; + describe('Waku Store', () => { let waku: Waku; let nimWaku: NimWaku; @@ -37,7 +39,7 @@ describe('Waku Store', () => { for (let i = 0; i < 2; i++) { expect( await nimWaku.sendMessage( - await WakuMessage.fromUtf8String(`Message ${i}`) + await WakuMessage.fromUtf8String(`Message ${i}`, TestContentTopic) ) ).to.be.true; } @@ -73,7 +75,7 @@ describe('Waku Store', () => { for (let i = 0; i < 15; i++) { expect( await nimWaku.sendMessage( - await WakuMessage.fromUtf8String(`Message ${i}`) + await WakuMessage.fromUtf8String(`Message ${i}`, TestContentTopic) ) ).to.be.true; } @@ -90,7 +92,7 @@ describe('Waku Store', () => { }); const messages = await waku.store.queryHistory({ - contentTopics: [DefaultContentTopic], + contentTopics: [], direction: Direction.FORWARD, }); @@ -114,7 +116,7 @@ describe('Waku Store', () => { for (let i = 0; i < 2; i++) { expect( await nimWaku.sendMessage( - await WakuMessage.fromUtf8String(`Message ${i}`), + await WakuMessage.fromUtf8String(`Message ${i}`, TestContentTopic), customPubSubTopic ) ).to.be.true; @@ -171,14 +173,22 @@ describe('Waku Store', () => { clearMessage, otherEncMessage, ] = await Promise.all([ - WakuMessage.fromUtf8String(encryptedAsymmetricMessageText, { - encPublicKey: publicKey, - }), - WakuMessage.fromUtf8String(encryptedSymmetricMessageText, { - symKey: symKey, - }), - WakuMessage.fromUtf8String(clearMessageText), - WakuMessage.fromUtf8String(otherEncMessageText, { + WakuMessage.fromUtf8String( + encryptedAsymmetricMessageText, + TestContentTopic, + { + encPublicKey: publicKey, + } + ), + WakuMessage.fromUtf8String( + encryptedSymmetricMessageText, + TestContentTopic, + { + symKey: symKey, + } + ), + WakuMessage.fromUtf8String(clearMessageText, TestContentTopic), + WakuMessage.fromUtf8String(otherEncMessageText, TestContentTopic, { encPublicKey: getPublicKey(generatePrivateKey()), }), ]);