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:
parent
fa4c9ed042
commit
491062154b
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,6 +59,6 @@ export class ChatMessage {
|
|||
return "";
|
||||
}
|
||||
|
||||
return Buffer.from(this.proto.payload).toString("utf-8");
|
||||
return utils.bytesToUtf8(this.proto.payload);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue