Merge pull request #256 from waku-org/chore/bump-web-chat

feat(web-chat): show more details about discovered & connected peers
This commit is contained in:
Danish Arora 2023-08-03 13:14:05 +05:30 committed by GitHub
commit 11eaec74cc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 1616 additions and 689 deletions

File diff suppressed because it is too large Load Diff

View File

@ -4,12 +4,14 @@
"private": true, "private": true,
"homepage": "/web-chat", "homepage": "/web-chat",
"dependencies": { "dependencies": {
"@multiformats/multiaddr": "11.0.7", "@libp2p/bootstrap": "^8.0.0",
"@waku/react": "^0.0.4-fe5b4c4",
"@waku/dns-discovery": "^0.0.15", "@waku/dns-discovery": "^0.0.15",
"@waku/interfaces": "^0.0.16", "@waku/interfaces": "^0.0.17",
"@waku/peer-exchange": "^0.0.14", "@waku/peer-exchange": "^0.0.15",
"@waku/react": "0.0.3-7aeb24a", "@livechat/ui-kit": "^0.5.0-24",
"@waku/sdk": "^0.0.17", "@multiformats/multiaddr": "12.1.5",
"@waku/sdk": "^0.0.18",
"process": "^0.11.10", "process": "^0.11.10",
"protons-runtime": "^3.1.0", "protons-runtime": "^3.1.0",
"react": "^17.0.2", "react": "^17.0.2",

View File

@ -17,8 +17,15 @@ export default function Room(props: Props) {
const { encoder } = useContentPair(); const { encoder } = useContentPair();
const { push: onPush } = useLightPush({ node, encoder }); const { push: onPush } = useLightPush({ node, encoder });
const { bootstrapPeers, peerExchangePeers } = useNodePeers(node); const {
const { storePeers, filterPeers, lightPushPeers } = usePeers({ node }); connectedBootstrapPeers,
connectedPeerExchangePeers,
discoveredBootstrapPeers,
discoveredPeerExchangePeers,
} = useNodePeers(node);
const { allConnected, storePeers, filterPeers, lightPushPeers } = usePeers({
node,
});
const onSend = async (text: string) => { const onSend = async (text: string) => {
if (!onPush || !text) { if (!onPush || !text) {
@ -40,18 +47,39 @@ export default function Room(props: Props) {
} }
}; };
const allConnectedLength = orZero(allConnected?.length);
const lightPushPeersLength = orZero(lightPushPeers?.length); const lightPushPeersLength = orZero(lightPushPeers?.length);
const filterPeersLength = orZero(filterPeers?.length); const filterPeersLength = orZero(filterPeers?.length);
const storePeersLength = orZero(storePeers?.length); const storePeersLength = orZero(storePeers?.length);
const peersMessage = `Peers: ${lightPushPeersLength} light push, ${filterPeersLength} filter, ${storePeersLength} store.`;
const bootstrapPeersMessage = `Bootstrap (DNS Discovery): ${bootstrapPeers.size}, Peer exchange: ${peerExchangePeers.size}. `;
return ( return (
<div className="h-screen flex flex-col"> <div className="h-screen flex flex-col">
<div className="flex justify-between items-center bg-gray-800 text-white p-4"> <div className="flex justify-between items-center bg-gray-800 text-white p-4">
<div>{peersMessage}</div> <div>
<div>{bootstrapPeersMessage} View console for more details.</div> <div>Peers Connected: {allConnectedLength}</div>
<div className="mt-2">Store: {storePeersLength}</div>
<div>Filter: {filterPeersLength}</div>
<div>Light Push: {lightPushPeersLength}</div>
</div>
<div>Waku v2 Web Chat</div>
<div>
<div className="mt-2">
Peers Discovered:{" "}
{discoveredBootstrapPeers.size + discoveredPeerExchangePeers.size}
</div>
<div>
Bootstrap: {discoveredBootstrapPeers.size} Peer Exchange:{" "}
{discoveredPeerExchangePeers.size}
</div>
<div className="mt-2">
Peers Connected:{" "}
{connectedBootstrapPeers.size + connectedPeerExchangePeers.size}
</div>
<div>
Bootstrap: {connectedBootstrapPeers.size} Peer Exchange:{" "}
{connectedPeerExchangePeers.size}
</div>
</div>
</div> </div>
<ChatList messages={props.messages} /> <ChatList messages={props.messages} />
<MessageInput hasLightPushPeers={!!lightPushPeers} sendMessage={onSend} /> <MessageInput hasLightPushPeers={!!lightPushPeers} sendMessage={onSend} />

View File

@ -1,8 +1,15 @@
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { generate } from "server-name-generator"; import { generate } from "server-name-generator";
import { Message } from "./Message"; import { Message } from "./Message";
import type { PeerId } from "@libp2p/interface-peer-id";
import type { Peer } from "@libp2p/interface-peer-store"; import type { Peer } from "@libp2p/interface-peer-store";
import type { LightNode, StoreQueryOptions, Waku } from "@waku/interfaces"; import {
EPeersByDiscoveryEvents,
LightNode,
StoreQueryOptions,
Waku,
Tags,
} from "@waku/interfaces";
import type { waku } from "@waku/sdk"; import type { waku } from "@waku/sdk";
import { useFilterMessages, useStoreMessages } from "@waku/react"; import { useFilterMessages, useStoreMessages } from "@waku/react";
@ -59,42 +66,100 @@ export const useMessages = (params: UseMessagesParams): UseMessagesResult => {
// can be safely ignored // can be safely ignored
// this is for experiments on waku side around new discovery options // this is for experiments on waku side around new discovery options
export const useNodePeers = (node: undefined | LightNode) => { export const useNodePeers = (node: undefined | LightNode) => {
const [bootstrapPeers, setBootstrapPeers] = useState(new Set<string>()); const [discoveredBootstrapPeers, setBootstrapPeers] = useState<Set<PeerId>>(
const [peerExchangePeers, setPeerExchangePeers] = useState(new Set<string>()); new Set()
);
const [connectedBootstrapPeers, setConnectedBootstrapPeers] = useState<
Set<PeerId>
>(new Set());
const [discoveredPeerExchangePeers, setPeerExchangePeers] = useState<
Set<PeerId>
>(new Set());
const [connectedPeerExchangePeers, setConnectedPeerExchangePeers] = useState<
Set<PeerId>
>(new Set());
useEffect(() => { useEffect(() => {
if (!node) return; if (!node) return;
const listener = async (evt: any) => { const handleDiscoveryBootstrap = (event: CustomEvent<PeerId>) => {
const { peerId } = evt.detail; setBootstrapPeers((peers) => new Set([...peers, event.detail]));
const tags = Array.from(
(await node.libp2p.peerStore.get(peerId)).tags.keys()
);
if (tags.includes("peer-exchange")) {
setPeerExchangePeers((peers) => new Set(peers).add(peerId.toString()));
} else {
setBootstrapPeers((peers) => new Set(peers).add(peerId.toString()));
}
}; };
// Update store peer when new peer connected & identified const handleConnectBootstrap = (event: CustomEvent<PeerId>) => {
node.libp2p.addEventListener("peer:identify", listener); setConnectedBootstrapPeers((peers) => new Set([...peers, event.detail]));
};
const handleDiscoveryPeerExchange = (event: CustomEvent<PeerId>) => {
setPeerExchangePeers((peers) => new Set([...peers, event.detail]));
};
const handleConnectPeerExchange = (event: CustomEvent<PeerId>) => {
setConnectedPeerExchangePeers(
(peers) => new Set([...peers, event.detail])
);
};
const initHookData = async () => {
const { CONNECTED, DISCOVERED } =
await node.connectionManager.getPeersByDiscovery();
setConnectedBootstrapPeers(
new Set(CONNECTED[Tags.BOOTSTRAP].map((p) => p.id))
);
setConnectedPeerExchangePeers(
new Set(CONNECTED[Tags.PEER_EXCHANGE].map((p) => p.id))
);
setBootstrapPeers(new Set(DISCOVERED[Tags.BOOTSTRAP].map((p) => p.id)));
setPeerExchangePeers(
new Set(DISCOVERED[Tags.PEER_EXCHANGE].map((p) => p.id))
);
node.connectionManager.addEventListener(
EPeersByDiscoveryEvents.PEER_DISCOVERY_BOOTSTRAP,
handleDiscoveryBootstrap
);
node.connectionManager.addEventListener(
EPeersByDiscoveryEvents.PEER_CONNECT_BOOTSTRAP,
handleConnectBootstrap
);
node.connectionManager.addEventListener(
EPeersByDiscoveryEvents.PEER_DISCOVERY_PEER_EXCHANGE,
handleDiscoveryPeerExchange
);
node.connectionManager.addEventListener(
EPeersByDiscoveryEvents.PEER_CONNECT_PEER_EXCHANGE,
handleConnectPeerExchange
);
};
initHookData();
return () => { return () => {
node.libp2p.removeEventListener("peer:identify", listener); node.connectionManager.removeEventListener(
EPeersByDiscoveryEvents.PEER_DISCOVERY_BOOTSTRAP,
handleDiscoveryBootstrap
);
node.connectionManager.removeEventListener(
EPeersByDiscoveryEvents.PEER_CONNECT_BOOTSTRAP,
handleConnectBootstrap
);
node.connectionManager.removeEventListener(
EPeersByDiscoveryEvents.PEER_DISCOVERY_PEER_EXCHANGE,
handleDiscoveryPeerExchange
);
node.connectionManager.removeEventListener(
EPeersByDiscoveryEvents.PEER_CONNECT_PEER_EXCHANGE,
handleConnectPeerExchange
);
}; };
}, [node]); }, [node]);
useEffect(() => {
console.log("Bootstrap Peers:");
console.table(bootstrapPeers);
console.log("Peer Exchange Peers:");
console.table(peerExchangePeers);
}, [bootstrapPeers, peerExchangePeers]);
return { return {
bootstrapPeers, discoveredBootstrapPeers,
peerExchangePeers, connectedBootstrapPeers,
discoveredPeerExchangePeers,
connectedPeerExchangePeers,
}; };
}; };
@ -103,9 +168,10 @@ type UsePeersParams = {
}; };
type UsePeersResults = { type UsePeersResults = {
storePeers?: undefined | Peer[]; allConnected?: PeerId[];
filterPeers?: undefined | Peer[]; storePeers?: PeerId[];
lightPushPeers?: undefined | Peer[]; filterPeers?: PeerId[];
lightPushPeers?: PeerId[];
}; };
/** /**
@ -120,22 +186,24 @@ export const usePeers = (params: UsePeersParams): UsePeersResults => {
const { node } = params; const { node } = params;
const [peers, setPeers] = React.useState<UsePeersResults>({}); const [peers, setPeers] = React.useState<UsePeersResults>({});
React.useEffect(() => { useEffect(() => {
if (!node) { if (!node) {
return; return;
} }
const listener = async (_event?: any) => { const listener = async () => {
const peers = await Promise.all([ const peers = await Promise.all([
node?.libp2p.getConnections().map((c) => c.remotePeer),
handleCatch(node?.store?.peers()), handleCatch(node?.store?.peers()),
handleCatch(node?.filter?.peers()), handleCatch(node?.filter?.peers()),
handleCatch(node?.lightPush?.peers()), handleCatch(node?.lightPush?.peers()),
]); ]);
setPeers({ setPeers({
storePeers: peers[0], allConnected: peers[0],
filterPeers: peers[1], storePeers: peers[1]?.map((p) => p.id),
lightPushPeers: peers[2], filterPeers: peers[2]?.map((p) => p.id),
lightPushPeers: peers[3]?.map((p) => p.id),
}); });
}; };

View File

@ -11,7 +11,7 @@ import { CONTENT_TOPIC, PROTOCOLS } from "./config";
const NODE_OPTIONS = { const NODE_OPTIONS = {
libp2p: { libp2p: {
peerDiscovery: [ peerDiscovery: [
wakuDnsDiscovery([enrTree.TEST], { wakuDnsDiscovery([enrTree.PROD], {
store: 1, store: 1,
filter: 2, filter: 2,
lightPush: 2, lightPush: 2,