2021-08-12 15:15:56 +10:00

222 lines
5.6 KiB
TypeScript

import '@ethersproject/shims';
import React, { useEffect, useState } from 'react';
import './App.css';
import { Waku } from 'js-waku';
import { Signer } from '@ethersproject/abstract-signer';
import { KeyPair } from './crypto';
import { Message } from './messaging/Messages';
import 'fontsource-roboto';
import { AppBar, IconButton, Toolbar, Typography } from '@material-ui/core';
import KeyPairHandling from './key_pair_handling/KeyPairHandling';
import {
createMuiTheme,
ThemeProvider,
makeStyles,
} from '@material-ui/core/styles';
import { teal, purple, green } from '@material-ui/core/colors';
import WifiIcon from '@material-ui/icons/Wifi';
import BroadcastPublicKey from './BroadcastPublicKey';
import Messaging from './messaging/Messaging';
import {
DirectMessageContentTopic,
handleDirectMessage,
handlePublicKeyMessage,
initWaku,
PublicKeyContentTopic,
} from './waku';
import ConnectWallet from './ConnectWallet';
const theme = createMuiTheme({
palette: {
primary: {
main: purple[500],
},
secondary: {
main: teal[600],
},
},
});
const useStyles = makeStyles({
root: {
textAlign: 'center',
display: 'flex',
flexDirection: 'column',
minHeight: '100vh',
},
appBar: {
// height: '200p',
},
container: {
display: 'flex',
flex: 1,
},
main: {
flex: 1,
margin: '10px',
},
wakuStatus: {
marginRight: theme.spacing(2),
},
title: {
flexGrow: 1,
},
peers: {},
});
function App() {
const [waku, setWaku] = useState<Waku>();
const [signer, setSigner] = useState<Signer>();
const [EncryptionKeyPair, setEncryptionKeyPair] = useState<
KeyPair | undefined
>();
const [publicKeys, setPublicKeys] = useState<Map<string, Uint8Array>>(
new Map()
);
const [messages, setMessages] = useState<Message[]>([]);
const [address, setAddress] = useState<string>();
const classes = useStyles();
// Waku initialization
useEffect(() => {
if (waku) return;
initWaku()
.then((_waku) => {
console.log('waku: ready');
setWaku(_waku);
})
.catch((e) => {
console.error('Failed to initiate Waku', e);
});
}, [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 (!EncryptionKeyPair) return;
waku.relay.addDecryptionKey(EncryptionKeyPair.privateKey);
return function cleanUp() {
if (!waku) return;
if (!EncryptionKeyPair) return;
waku.relay.deleteDecryptionKey(EncryptionKeyPair.privateKey);
};
}, [waku, EncryptionKeyPair]);
useEffect(() => {
if (!waku) return;
if (!EncryptionKeyPair) return;
if (!address) return;
const observerDirectMessage = handleDirectMessage.bind(
{},
setMessages,
address
);
waku.relay.addObserver(observerDirectMessage, [DirectMessageContentTopic]);
return function cleanUp() {
if (!waku) return;
if (!observerDirectMessage) return;
waku.relay.deleteObserver(observerDirectMessage, [
DirectMessageContentTopic,
]);
};
}, [waku, address, EncryptionKeyPair]);
let relayPeers = 0;
let lightPushPeers = 0;
if (waku) {
relayPeers = waku.relay.getPeers().size;
lightPushPeers = waku.lightPush.peers.length;
}
let addressDisplay = '';
if (address) {
addressDisplay =
address.substr(0, 6) + '...' + address.substr(address.length - 4, 4);
}
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
color={waku ? undefined : 'disabled'}
style={waku ? { color: green[500] } : {}}
/>
</IconButton>
<Typography className={classes.peers} aria-label="connected-peers">
Peers: {relayPeers} relay, {lightPushPeers} light push
</Typography>
<Typography variant="h6" className={classes.title}>
Ethereum Direct Message
</Typography>
<Typography>{addressDisplay}</Typography>
</Toolbar>
</AppBar>
<div className={classes.container}>
<main className={classes.main}>
<fieldset>
<legend>Wallet</legend>
<ConnectWallet setAddress={setAddress} setSigner={setSigner} />
</fieldset>
<fieldset>
<legend>Encryption Key Pair</legend>
<KeyPairHandling
encryptionKeyPair={EncryptionKeyPair}
setEncryptionKeyPair={setEncryptionKeyPair}
/>
<BroadcastPublicKey
signer={signer}
EncryptionKeyPair={EncryptionKeyPair}
waku={waku}
/>
</fieldset>
<fieldset>
<legend>Messaging</legend>
<Messaging
recipients={publicKeys}
waku={waku}
messages={messages}
/>
</fieldset>
</main>
</div>
</div>
</ThemeProvider>
);
}
export default App;