From ff292f37ba86d09f0dee6372932fb84e91d41e1e Mon Sep 17 00:00:00 2001 From: "fryorcraken.eth" Date: Sun, 11 Sep 2022 00:57:10 +1000 Subject: [PATCH] test: fix typing of JSON RPC response Ref: https://github.com/status-im/nwaku/issues/1139 --- CHANGELOG.md | 1 + src/lib/waku_light_push/index.node.spec.ts | 16 +++-- src/lib/waku_message/index.node.spec.ts | 11 ++-- src/lib/waku_relay/index.node.spec.ts | 20 ++++--- src/lib/waku_store/index.node.spec.ts | 46 +++++++------- src/test_utils/nwaku.ts | 70 +++++++++++++++------- 6 files changed, 104 insertions(+), 60 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f769a5967..7c324acd59 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `addPeerToAddressBook` is now async. - API Docs moved to https://js.waku.org/ +- test: fix typing for nwaku JSON RPC responses. ## [0.26.0] - 2022-09-08 diff --git a/src/lib/waku_light_push/index.node.spec.ts b/src/lib/waku_light_push/index.node.spec.ts index 5a435e5b4c..f0c16013f9 100644 --- a/src/lib/waku_light_push/index.node.spec.ts +++ b/src/lib/waku_light_push/index.node.spec.ts @@ -1,10 +1,16 @@ import { expect } from "chai"; import debug from "debug"; -import { makeLogFileName, NOISE_KEY_1, Nwaku } from "../../test_utils"; +import { + makeLogFileName, + MessageRpcResponse, + NOISE_KEY_1, + Nwaku, +} from "../../test_utils"; import { delay } from "../../test_utils/delay"; import { createFullNode } from "../create_waku"; import type { WakuFull } from "../interfaces"; +import { bytesToUtf8 } from "../utils"; import { waitForRemotePeer } from "../wait_for_remote_peer"; import { Protocols } from "../waku"; import { WakuMessage } from "../waku_message"; @@ -44,7 +50,7 @@ describe("Waku Light Push [node only]", () => { const pushResponse = await waku.lightPush.push(message); expect(pushResponse?.isSuccess).to.be.true; - let msgs: WakuMessage[] = []; + let msgs: MessageRpcResponse[] = []; while (msgs.length === 0) { await delay(200); @@ -53,7 +59,7 @@ describe("Waku Light Push [node only]", () => { expect(msgs[0].contentTopic).to.equal(message.contentTopic); expect(msgs[0].version).to.equal(message.version); - expect(msgs[0].payloadAsUtf8).to.equal(messageText); + expect(bytesToUtf8(new Uint8Array(msgs[0].payload))).to.equal(messageText); }); it("Push on custom pubsub topic", async function () { @@ -88,7 +94,7 @@ describe("Waku Light Push [node only]", () => { log("Ack received", pushResponse); expect(pushResponse?.isSuccess).to.be.true; - let msgs: WakuMessage[] = []; + let msgs: MessageRpcResponse[] = []; log("Waiting for message to show in nwaku"); while (msgs.length === 0) { @@ -98,6 +104,6 @@ describe("Waku Light Push [node only]", () => { expect(msgs[0].contentTopic).to.equal(message.contentTopic); expect(msgs[0].version).to.equal(message.version); - expect(msgs[0].payloadAsUtf8).to.equal(messageText); + expect(bytesToUtf8(new Uint8Array(msgs[0].payload))!).to.equal(messageText); }); }); diff --git a/src/lib/waku_message/index.node.spec.ts b/src/lib/waku_message/index.node.spec.ts index 6fb5f705db..8bb35a3502 100644 --- a/src/lib/waku_message/index.node.spec.ts +++ b/src/lib/waku_message/index.node.spec.ts @@ -3,9 +3,10 @@ import debug from "debug"; import { makeLogFileName, + MessageRpcQuery, + MessageRpcResponseHex, NOISE_KEY_1, Nwaku, - WakuRelayMessage, } from "../../test_utils"; import { delay } from "../../test_utils/delay"; import { createPrivacyNode } from "../create_waku"; @@ -61,7 +62,7 @@ describe("Waku Message [node only]", function () { this.timeout(5000); const messageText = "Here is an encrypted message."; - const message: WakuRelayMessage = { + const message: MessageRpcQuery = { contentTopic: TestContentTopic, payload: bytesToHex(utf8ToBytes(messageText)), }; @@ -111,7 +112,7 @@ describe("Waku Message [node only]", function () { log("Send message over relay"); await waku.relay.send(message); - let msgs: WakuRelayMessage[] = []; + let msgs: MessageRpcResponseHex[] = []; while (msgs.length === 0) { log("Wait for message to be seen by nwaku"); @@ -128,7 +129,7 @@ describe("Waku Message [node only]", function () { this.timeout(5000); const messageText = "Here is a message encrypted in a symmetric manner."; - const message: WakuRelayMessage = { + const message: MessageRpcQuery = { contentTopic: TestContentTopic, payload: bytesToHex(utf8ToBytes(messageText)), }; @@ -175,7 +176,7 @@ describe("Waku Message [node only]", function () { log("Sending message over relay"); await waku.relay.send(message); - let msgs: WakuRelayMessage[] = []; + let msgs: MessageRpcResponseHex[] = []; while (msgs.length === 0) { await delay(200); diff --git a/src/lib/waku_relay/index.node.spec.ts b/src/lib/waku_relay/index.node.spec.ts index 905a7a33c0..8f9f7319ba 100644 --- a/src/lib/waku_relay/index.node.spec.ts +++ b/src/lib/waku_relay/index.node.spec.ts @@ -4,6 +4,7 @@ import debug from "debug"; import { makeLogFileName, + MessageRpcResponse, NOISE_KEY_1, NOISE_KEY_2, NOISE_KEY_3, @@ -18,6 +19,7 @@ import { getPublicKey, } from "../crypto"; import type { WakuPrivacy } from "../interfaces"; +import { bytesToUtf8, utf8ToBytes } from "../utils"; import { waitForRemotePeer } from "../wait_for_remote_peer"; import { Protocols } from "../waku"; import { DecryptionMethod, WakuMessage } from "../waku_message"; @@ -385,7 +387,7 @@ describe("Waku Relay [node only]", () => { await delay(1000); await waku.relay.send(message); - let msgs: WakuMessage[] = []; + let msgs: MessageRpcResponse[] = []; while (msgs.length === 0) { console.log("Waiting for messages"); @@ -395,17 +397,19 @@ describe("Waku Relay [node only]", () => { expect(msgs[0].contentTopic).to.equal(message.contentTopic); expect(msgs[0].version).to.equal(message.version); - expect(msgs[0].payloadAsUtf8).to.equal(messageText); + expect(bytesToUtf8(new Uint8Array(msgs[0].payload))).to.equal( + messageText + ); }); it("Nwaku publishes", async function () { await delay(200); const messageText = "Here is another message."; - const message = await WakuMessage.fromUtf8String( - messageText, - TestContentTopic - ); + const message = { + payload: utf8ToBytes(messageText), + contentTopic: TestContentTopic, + }; const receivedMsgPromise: Promise = new Promise( (resolve) => { @@ -413,12 +417,12 @@ describe("Waku Relay [node only]", () => { } ); - await nwaku.sendMessage(Nwaku.toWakuRelayMessage(message)); + await nwaku.sendMessage(Nwaku.toMessageRpcQuery(message)); const receivedMsg = await receivedMsgPromise; expect(receivedMsg.contentTopic).to.eq(message.contentTopic); - expect(receivedMsg.version).to.eq(message.version); + expect(receivedMsg.version).to.eq(0); expect(receivedMsg.payloadAsUtf8).to.eq(messageText); }); diff --git a/src/lib/waku_store/index.node.spec.ts b/src/lib/waku_store/index.node.spec.ts index 6ba5841977..7b4195285a 100644 --- a/src/lib/waku_store/index.node.spec.ts +++ b/src/lib/waku_store/index.node.spec.ts @@ -14,6 +14,7 @@ import { getPublicKey, } from "../crypto"; import type { WakuFull } from "../interfaces"; +import { utf8ToBytes } from "../utils"; import { waitForRemotePeer } from "../wait_for_remote_peer"; import { Protocols } from "../waku"; import { DecryptionMethod, WakuMessage } from "../waku_message"; @@ -42,9 +43,10 @@ describe("Waku Store", () => { for (let i = 0; i < 2; i++) { expect( await nwaku.sendMessage( - Nwaku.toWakuRelayMessage( - await WakuMessage.fromUtf8String(`Message ${i}`, TestContentTopic) - ) + Nwaku.toMessageRpcQuery({ + payload: utf8ToBytes(`Message ${i}`), + contentTopic: TestContentTopic, + }) ) ).to.be.true; } @@ -75,9 +77,10 @@ describe("Waku Store", () => { for (let i = 0; i < totalMsgs; i++) { expect( await nwaku.sendMessage( - Nwaku.toWakuRelayMessage( - await WakuMessage.fromUtf8String(`Message ${i}`, TestContentTopic) - ) + Nwaku.toMessageRpcQuery({ + payload: utf8ToBytes(`Message ${i}`), + contentTopic: TestContentTopic, + }) ) ).to.be.true; } @@ -115,9 +118,10 @@ describe("Waku Store", () => { for (let i = 0; i < availMsgs; i++) { expect( await nwaku.sendMessage( - Nwaku.toWakuRelayMessage( - await WakuMessage.fromUtf8String(`Message ${i}`, TestContentTopic) - ) + Nwaku.toMessageRpcQuery({ + payload: utf8ToBytes(`Message ${i}`), + contentTopic: TestContentTopic, + }) ) ).to.be.true; } @@ -152,9 +156,10 @@ describe("Waku Store", () => { for (let i = 0; i < 15; i++) { expect( await nwaku.sendMessage( - Nwaku.toWakuRelayMessage( - await WakuMessage.fromUtf8String(`Message ${i}`, TestContentTopic) - ) + Nwaku.toMessageRpcQuery({ + payload: utf8ToBytes(`Message ${i}`), + contentTopic: TestContentTopic, + }) ) ).to.be.true; } @@ -194,9 +199,10 @@ describe("Waku Store", () => { for (let i = 0; i < 2; i++) { expect( await nwaku.sendMessage( - Nwaku.toWakuRelayMessage( - await WakuMessage.fromUtf8String(`Message ${i}`, TestContentTopic) - ), + Nwaku.toMessageRpcQuery({ + payload: utf8ToBytes(`Message ${i}`), + contentTopic: TestContentTopic, + }), customPubSubTopic ) ).to.be.true; @@ -449,11 +455,11 @@ describe("Waku Store", () => { for (let i = 0; i < 2; i++) { expect( await nwaku.sendMessage( - Nwaku.toWakuRelayMessage( - await WakuMessage.fromUtf8String(`Message ${i}`, TestContentTopic, { - timestamp: messageTimestamps[i], - }) - ) + Nwaku.toMessageRpcQuery({ + payload: utf8ToBytes(`Message ${i}`), + contentTopic: TestContentTopic, + timestamp: messageTimestamps[i], + }) ) ).to.be.true; } diff --git a/src/test_utils/nwaku.ts b/src/test_utils/nwaku.ts index 5f731bb6b6..3027963bb5 100644 --- a/src/test_utils/nwaku.ts +++ b/src/test_utils/nwaku.ts @@ -14,8 +14,6 @@ import portfinder from "portfinder"; import { DefaultPubSubTopic } from "../lib/constants"; import { bytesToHex, hexToBytes } from "../lib/utils"; -import { WakuMessage } from "../lib/waku_message"; -import * as proto from "../proto/message"; import { existsAsync, mkdirAsync, openAsync } from "./async_fs"; import { delay } from "./delay"; @@ -34,6 +32,14 @@ const NODE_READY_LOG_LINE = "Node setup complete"; const LOG_DIR = "./log"; +const OneMillion = BigInt(1_000_000); + +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore +BigInt.prototype.toJSON = function toJSON() { + return Number(this); +}; + export interface Args { staticnode?: string; nat?: "none"; @@ -71,10 +77,24 @@ export interface KeyPair { publicKey: string; } -export interface WakuRelayMessage { +export interface MessageRpcQuery { payload: string; // Hex encoded data string without `0x` prefix. contentTopic?: string; - timestamp?: number; // Unix epoch time in nanoseconds as a 64-bits integer value. + timestamp?: bigint; // Unix epoch time in nanoseconds as a 64-bits integer value. +} + +export interface MessageRpcResponse { + payload: number[]; + contentTopic?: string; + version?: number; + timestamp?: bigint; // Unix epoch time in nanoseconds as a 64-bits integer value. +} + +export interface MessageRpcResponseHex { + payload: string; + contentTopic?: string; + version?: number; + timestamp?: bigint; // Unix epoch time in nanoseconds as a 64-bits integer value. } export class Nwaku { @@ -89,14 +109,18 @@ export class Nwaku { * Convert a [[WakuMessage]] to a [[WakuRelayMessage]]. The latter is used * by the nwaku JSON-RPC API. */ - static toWakuRelayMessage(message: WakuMessage): WakuRelayMessage { + static toMessageRpcQuery(message: { + payload: Uint8Array; + contentTopic: string; + timestamp?: Date; + }): MessageRpcQuery { if (!message.payload) { throw "Attempting to convert empty message"; } let timestamp; - if (message.proto.timestamp) { - timestamp = Number.parseInt(message.proto.timestamp.toString(10)); + if (message.timestamp) { + timestamp = BigInt(message.timestamp.valueOf()) * OneMillion; } return { @@ -216,11 +240,15 @@ export class Nwaku { } async sendMessage( - message: WakuRelayMessage, + message: MessageRpcQuery, pubSubTopic: string = DefaultPubSubTopic ): Promise { this.checkProcess(); + if (typeof message.timestamp === "undefined") { + message.timestamp = BigInt(new Date().valueOf()) * OneMillion; + } + return this.rpcCall("post_waku_v2_relay_v1_message", [ pubSubTopic, message, @@ -229,22 +257,20 @@ export class Nwaku { async messages( pubsubTopic: string = DefaultPubSubTopic - ): Promise { + ): Promise { this.checkProcess(); - const isDefined = (msg: WakuMessage | undefined): msg is WakuMessage => { + const isDefined = ( + msg: MessageRpcResponse | undefined + ): msg is MessageRpcResponse => { return !!msg; }; - const protoMsgs = await this.rpcCall( + const msgs = await this.rpcCall( "get_waku_v2_relay_v1_messages", [pubsubTopic] ); - const msgs = await Promise.all( - protoMsgs.map(async (protoMsg) => await WakuMessage.decodeProto(protoMsg)) - ); - return msgs.filter(isDefined); } @@ -267,7 +293,7 @@ export class Nwaku { } async postAsymmetricMessage( - message: WakuRelayMessage, + message: MessageRpcQuery, publicKey: Uint8Array, pubSubTopic?: string ): Promise { @@ -287,10 +313,10 @@ export class Nwaku { async getAsymmetricMessages( privateKey: Uint8Array, pubSubTopic?: string - ): Promise { + ): Promise { this.checkProcess(); - return await this.rpcCall( + return await this.rpcCall( "get_waku_v2_private_v1_asymmetric_messages", [ pubSubTopic ? pubSubTopic : DefaultPubSubTopic, @@ -309,7 +335,7 @@ export class Nwaku { } async postSymmetricMessage( - message: WakuRelayMessage, + message: MessageRpcQuery, symKey: Uint8Array, pubSubTopic?: string ): Promise { @@ -329,10 +355,10 @@ export class Nwaku { async getSymmetricMessages( symKey: Uint8Array, pubSubTopic?: string - ): Promise { + ): Promise { this.checkProcess(); - return await this.rpcCall( + return await this.rpcCall( "get_waku_v2_private_v1_symmetric_messages", [ pubSubTopic ? pubSubTopic : DefaultPubSubTopic, @@ -387,7 +413,7 @@ export class Nwaku { headers: new Headers({ "Content-Type": "application/json" }), }); const json = await res.json(); - log(`RPC Response: `, res, json); + log(`RPC Response: `, res, JSON.stringify(json)); return json.result; }