232 lines
5.9 KiB
TypeScript
Raw Normal View History

2022-02-04 14:12:00 +11:00
import "@ethersproject/shims";
import React, { useEffect, useState } from "react";
import "./App.css";
import { Waku } from "js-waku";
import { Message } from "./messaging/Messages";
import "fontsource-roboto";
import { AppBar, IconButton, Toolbar, Typography } from "@material-ui/core";
2021-08-12 15:26:06 +10:00
import {
createMuiTheme,
ThemeProvider,
makeStyles,
2022-02-04 14:12:00 +11:00
} from "@material-ui/core/styles";
import { lightBlue, orange, teal } from "@material-ui/core/colors";
import WifiIcon from "@material-ui/icons/Wifi";
import BroadcastPublicKey from "./BroadcastPublicKey";
import Messaging from "./messaging/Messaging";
2021-08-12 15:26:06 +10:00
import {
2021-08-17 16:35:08 +10:00
PrivateMessageContentTopic,
handlePrivateMessage,
2021-08-12 15:26:06 +10:00
handlePublicKeyMessage,
initWaku,
PublicKeyContentTopic,
2022-02-04 14:12:00 +11:00
} from "./waku";
import { Web3Provider } from "@ethersproject/providers/src.ts/web3-provider";
import GetEncryptionPublicKey from "./GetEncryptionPublicKey";
import ConnectWallet from "./ConnectWallet";
2021-08-12 15:26:06 +10:00
const theme = createMuiTheme({
palette: {
primary: {
main: orange[500],
2021-08-12 15:26:06 +10:00
},
secondary: {
main: lightBlue[600],
2021-08-12 15:26:06 +10:00
},
},
});
const useStyles = makeStyles({
root: {
2022-02-04 14:12:00 +11:00
textAlign: "center",
display: "flex",
flexDirection: "column",
minHeight: "100vh",
2021-08-12 15:26:06 +10:00
},
appBar: {
// height: '200p',
},
container: {
2022-02-04 14:12:00 +11:00
display: "flex",
2021-08-12 15:26:06 +10:00
flex: 1,
},
main: {
flex: 1,
2022-02-04 14:12:00 +11:00
margin: "10px",
2021-08-12 15:26:06 +10:00
},
wakuStatus: {
marginRight: theme.spacing(2),
},
title: {
flexGrow: 1,
},
peers: {},
});
function App() {
const [waku, setWaku] = useState<Waku>();
const [provider, setProvider] = useState<Web3Provider>();
const [encPublicKey, setEncPublicKey] = useState<Uint8Array>();
2021-08-12 15:26:06 +10:00
const [publicKeys, setPublicKeys] = useState<Map<string, Uint8Array>>(
new Map()
);
const [messages, setMessages] = useState<Message[]>([]);
const [address, setAddress] = useState<string>();
2021-08-12 15:07:27 +10:00
const [peerStats, setPeerStats] = useState<{
relayPeers: number;
lightPushPeers: number;
}>({
relayPeers: 0,
lightPushPeers: 0,
});
2021-08-12 15:26:06 +10:00
const classes = useStyles();
// Waku initialization
useEffect(() => {
if (waku) return;
initWaku()
.then((_waku) => {
2022-02-04 14:12:00 +11:00
console.log("waku: ready");
2021-08-12 15:26:06 +10:00
setWaku(_waku);
})
.catch((e) => {
2022-02-04 14:12:00 +11:00
console.error("Failed to initiate Waku", e);
2021-08-12 15:26:06 +10:00
});
}, [waku]);
useEffect(() => {
if (!waku) return;
const observerPublicKeyMessage = handlePublicKeyMessage.bind(
{},
address,
setPublicKeys
);
waku.relay.addObserver(observerPublicKeyMessage, [PublicKeyContentTopic]);
return function cleanUp() {
if (!waku) return;
waku.relay.deleteObserver(observerPublicKeyMessage, [
PublicKeyContentTopic,
]);
};
}, [waku, address]);
useEffect(() => {
if (!waku) return;
if (!address) return;
if (!provider?.provider?.request) return;
2021-08-12 15:26:06 +10:00
2021-08-17 16:35:08 +10:00
const observerPrivateMessage = handlePrivateMessage.bind(
2021-08-12 15:26:06 +10:00
{},
setMessages,
address,
provider.provider.request
2021-08-12 15:26:06 +10:00
);
2021-08-17 16:35:08 +10:00
waku.relay.addObserver(observerPrivateMessage, [
PrivateMessageContentTopic,
]);
2021-08-12 15:26:06 +10:00
return function cleanUp() {
if (!waku) return;
2021-08-17 16:35:08 +10:00
if (!observerPrivateMessage) return;
waku.relay.deleteObserver(observerPrivateMessage, [
PrivateMessageContentTopic,
2021-08-12 15:26:06 +10:00
]);
};
}, [waku, address, provider?.provider?.request]);
2021-08-12 15:26:06 +10:00
2021-08-12 15:07:27 +10:00
useEffect(() => {
if (!waku) return;
const interval = setInterval(async () => {
let lightPushPeers = 0;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
for await (const _peer of waku.store.peers) {
lightPushPeers++;
}
2021-08-12 15:07:27 +10:00
setPeerStats({
relayPeers: waku.relay.getPeers().size,
lightPushPeers,
2021-08-12 15:07:27 +10:00
});
}, 1000);
return () => clearInterval(interval);
}, [waku]);
2021-08-12 15:26:06 +10:00
2022-02-04 14:12:00 +11:00
let addressDisplay = "";
2021-08-12 15:26:06 +10:00
if (address) {
addressDisplay =
2022-02-04 14:12:00 +11:00
address.substr(0, 6) + "..." + address.substr(address.length - 4, 4);
2021-08-12 15:26:06 +10:00
}
return (
<ThemeProvider theme={theme}>
<div className={classes.root}>
<AppBar className={classes.appBar} position="static">
<Toolbar>
<IconButton
edge="start"
className={classes.wakuStatus}
aria-label="waku-status"
>
<WifiIcon
2022-02-04 14:12:00 +11:00
color={waku ? undefined : "disabled"}
style={waku ? { color: teal[500] } : {}}
2021-08-12 15:26:06 +10:00
/>
</IconButton>
<Typography className={classes.peers} aria-label="connected-peers">
2022-02-04 14:12:00 +11:00
Peers: {peerStats.relayPeers} relay, {peerStats.lightPushPeers}{" "}
2021-08-12 15:07:27 +10:00
light push
2021-08-12 15:26:06 +10:00
</Typography>
<Typography variant="h6" className={classes.title}>
2021-08-17 16:35:08 +10:00
Ethereum Private Message with Wallet Encryption
2021-08-12 15:26:06 +10:00
</Typography>
<Typography>{addressDisplay}</Typography>
</Toolbar>
</AppBar>
<div className={classes.container}>
<main className={classes.main}>
<fieldset>
<legend>Wallet</legend>
<ConnectWallet
setProvider={setProvider}
setAddress={setAddress}
/>
2021-08-12 15:26:06 +10:00
</fieldset>
<fieldset>
<legend>Encryption Keys</legend>
<GetEncryptionPublicKey
setEncPublicKey={setEncPublicKey}
providerRequest={provider?.provider?.request}
address={address}
2021-08-12 15:26:06 +10:00
/>
<BroadcastPublicKey
address={address}
encryptionPublicKey={encPublicKey}
2021-08-12 15:26:06 +10:00
waku={waku}
2021-08-12 16:36:28 +10:00
providerRequest={provider?.provider?.request}
2021-08-12 15:26:06 +10:00
/>
</fieldset>
<fieldset>
<legend>Messaging</legend>
<Messaging
recipients={publicKeys}
waku={waku}
messages={messages}
/>
</fieldset>
</main>
</div>
</div>
</ThemeProvider>
);
}
export default App;