From 491062154bfe988fc2d6cf60f0be7dacbfcc8f30 Mon Sep 17 00:00:00 2001 From: "fryorcraken.eth" Date: Fri, 2 Sep 2022 14:08:44 +1000 Subject: [PATCH] feat: use filter+light push instead of relay The node already leaks IP by using store. There would be some advantages to use relay to send messages but not as much as if only relay was used. --- web-chat/README.md | 3 ++- web-chat/src/App.tsx | 34 ++++++++++++++++++++++++++++------ web-chat/src/MessageInput.tsx | 22 +++++++++++++++++----- web-chat/src/Room.tsx | 34 +++++++++++++++++----------------- web-chat/src/chat_message.ts | 2 +- 5 files changed, 65 insertions(+), 30 deletions(-) diff --git a/web-chat/README.md b/web-chat/README.md index 63cf102..6011a69 100644 --- a/web-chat/README.md +++ b/web-chat/README.md @@ -4,7 +4,8 @@ - Group chat - React/TypeScript -- Waku Relay +- Waku Filter +- Waku Light Push - Waku Store A ReactJS chat app is provided as a showcase of the library used in the browser. diff --git a/web-chat/src/App.tsx b/web-chat/src/App.tsx index 1edf749..802e582 100644 --- a/web-chat/src/App.tsx +++ b/web-chat/src/App.tsx @@ -121,7 +121,7 @@ export default function App() { // Let's retrieve previous messages before listening to new messages if (!historicalMessagesRetrieved) return; - const handleRelayMessage = (wakuMsg: WakuMessage) => { + const handleIncomingMessage = (wakuMsg: WakuMessage) => { console.log("Message received: ", wakuMsg); const msg = Message.fromWakuMessage(wakuMsg); if (msg) { @@ -129,10 +129,26 @@ export default function App() { } }; - waku.relay.addObserver(handleRelayMessage, [ChatContentTopic]); + let unsubscribe: undefined | (() => Promise); + waku.filter.subscribe(handleIncomingMessage, [ChatContentTopic]).then( + (_unsubscribe) => { + console.log("subscribed to ", ChatContentTopic); + unsubscribe = _unsubscribe; + }, + (e) => { + console.error("Failed to subscribe", e); + } + ); return function cleanUp() { - waku?.relay.deleteObserver(handleRelayMessage, [ChatContentTopic]); + if (!waku) return; + if (typeof unsubscribe === "undefined") return; + unsubscribe().then( + () => { + console.log("unsubscribed to ", ChatContentTopic); + }, + (e) => console.error("Failed to unsubscribe", e) + ); }; }, [waku, historicalMessagesRetrieved]); @@ -141,7 +157,11 @@ export default function App() { if (historicalMessagesRetrieved) return; const retrieveMessages = async () => { - await waitForRemotePeer(waku, [Protocols.Relay, Protocols.Store]); + await waitForRemotePeer(waku, [ + Protocols.Store, + Protocols.Filter, + Protocols.LightPush, + ]); console.log(`Retrieving archived messages`); try { @@ -186,7 +206,9 @@ export default function App() { async function initWaku(setter: (waku: Waku) => void) { try { + // TODO: Remove this declaration once there are optional in js-waku const wakuRelay = new WakuRelay({ emitSelf: true }); + const libp2p = await defaultLibp2p(wakuRelay, { peerDiscovery: [ new PeerDiscoveryStaticPeers( @@ -196,7 +218,6 @@ async function initWaku(setter: (waku: Waku) => void) { }); const wakuStore = new WakuStore(libp2p); - // TODO: Remove these two declarations once there are optional in js-waku const wakuLightPush = new WakuLightPush(libp2p); const wakuFilter = new WakuFilter(libp2p); @@ -211,7 +232,8 @@ async function initWaku(setter: (waku: Waku) => void) { function selectFleetEnv() { // Works with react-scripts - if (process?.env?.NODE_ENV === "development") { + // TODO: Re-enable the switch once nwaku v0.12 is deployed + if (true || process?.env?.NODE_ENV === "development") { return Fleet.Test; } else { return Fleet.Prod; diff --git a/web-chat/src/MessageInput.tsx b/web-chat/src/MessageInput.tsx index 72c2c53..386bab3 100644 --- a/web-chat/src/MessageInput.tsx +++ b/web-chat/src/MessageInput.tsx @@ -1,4 +1,4 @@ -import { ChangeEvent, KeyboardEvent, useState } from "react"; +import { ChangeEvent, KeyboardEvent, useEffect, useState } from "react"; import { useWaku } from "./WakuContext"; import { TextInput, @@ -15,6 +15,7 @@ interface Props { export default function MessageInput(props: Props) { const [inputText, setInputText] = useState(""); + const [activeButton, setActiveButton] = useState(false); const { waku } = useWaku(); const sendMessage = async () => { @@ -39,10 +40,21 @@ export default function MessageInput(props: Props) { } }; - // Enable the button if there are relay peers available or the user is sending a command - const activeButton = - (waku && waku.relay.getMeshPeers().length !== 0) || - inputText.startsWith("/"); + // Enable the button if there are peers available or the user is sending a command + useEffect(() => { + if (inputText.startsWith("/")) { + setActiveButton(true); + } else if (waku) { + (async () => { + const peers = await waku.lightPush.peers(); + if (!!peers) { + setActiveButton(true); + } else { + setActiveButton(false); + } + })(); + } + }, [activeButton, inputText, waku]); return ( { - if (!waku) return; - - // Update relay peer count on heartbeat - waku.relay.addEventListener("gossipsub:heartbeat", () => { - setRelayPeers(waku.relay.getMeshPeers().length); - }); - }, [waku]); + const [filterPeers, setFilterPeers] = useState(0); + const [lightPushPeers, setLightPushPeers] = useState(0); useEffect(() => { if (!waku) return; // Update store peer when new peer connected & identified waku.libp2p.peerStore.addEventListener("change:protocols", async () => { - const peers = await waku.store.peers(); - setStorePeers(peers.length); + const storePeers = await waku.store.peers(); + setStorePeers(storePeers.length); + + const filterPeers = await waku.filter.peers(); + setFilterPeers(filterPeers.length); + + const lightPushPeers = await waku.lightPush.peers(); + setLightPushPeers(lightPushPeers.length); }); }, [waku]); @@ -45,7 +43,9 @@ export default function Room(props: Props) { style={{ height: "98vh", display: "flex", flexDirection: "column" }} > @@ -57,7 +57,7 @@ export default function Room(props: Props) { messageToSend, props.nick, props.commandHandler, - waku.relay.send.bind(waku.relay) + waku.lightPush.push.bind(waku.lightPush) ); } : undefined @@ -71,7 +71,7 @@ async function handleMessage( message: string, nick: string, commandHandler: (cmd: string) => void, - messageSender: (msg: WakuMessage) => Promise + messageSender: (msg: WakuMessage) => Promise ) { if (message.startsWith("/")) { commandHandler(message); @@ -83,6 +83,6 @@ async function handleMessage( ChatContentTopic, { timestamp } ); - return messageSender(wakuMsg); + await messageSender(wakuMsg); } } diff --git a/web-chat/src/chat_message.ts b/web-chat/src/chat_message.ts index 82bba96..7250c71 100644 --- a/web-chat/src/chat_message.ts +++ b/web-chat/src/chat_message.ts @@ -59,6 +59,6 @@ export class ChatMessage { return ""; } - return Buffer.from(this.proto.payload).toString("utf-8"); + return utils.bytesToUtf8(this.proto.payload); } }