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.
This commit is contained in:
fryorcraken.eth 2022-09-02 14:08:44 +10:00
parent fa4c9ed042
commit 491062154b
No known key found for this signature in database
GPG Key ID: A82ED75A8DFC50A4
5 changed files with 65 additions and 30 deletions

View File

@ -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.

View File

@ -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<void>);
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;

View File

@ -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<string>("");
const [activeButton, setActiveButton] = useState<boolean>(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 (
<TextComposer

View File

@ -1,4 +1,4 @@
import { WakuMessage } from "js-waku";
import { PushResponse, WakuMessage } from "js-waku";
import { ChatContentTopic } from "./App";
import ChatList from "./ChatList";
import MessageInput from "./MessageInput";
@ -18,24 +18,22 @@ export default function Room(props: Props) {
const { waku } = useWaku();
const [storePeers, setStorePeers] = useState(0);
const [relayPeers, setRelayPeers] = useState(0);
useEffect(() => {
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" }}
>
<TitleBar
leftIcons={[`Peers: ${relayPeers} relay ${storePeers} store.`]}
leftIcons={[
`Peers: ${lightPushPeers} light push, ${filterPeers} filter, ${storePeers} store.`,
]}
title="Waku v2 chat app"
/>
<ChatList messages={props.messages} />
@ -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<void>
messageSender: (msg: WakuMessage) => Promise<PushResponse | null>
) {
if (message.startsWith("/")) {
commandHandler(message);
@ -83,6 +83,6 @@ async function handleMessage(
ChatContentTopic,
{ timestamp }
);
return messageSender(wakuMsg);
await messageSender(wakuMsg);
}
}

View File

@ -59,6 +59,6 @@ export class ChatMessage {
return "";
}
return Buffer.from(this.proto.payload).toString("utf-8");
return utils.bytesToUtf8(this.proto.payload);
}
}