156 lines
3.8 KiB
TypeScript
Raw Normal View History

2021-08-12 15:26:06 +10:00
import {
FormControl,
InputLabel,
makeStyles,
MenuItem,
Select,
TextField,
2022-02-04 14:12:00 +11:00
} from "@material-ui/core";
import React, { ChangeEvent, useState, KeyboardEvent } from "react";
import { Waku, WakuMessage } from "js-waku";
2022-02-14 10:50:02 +11:00
import { bytesToHex, hexToBytes } from "js-waku/lib/utils";
2022-02-04 14:12:00 +11:00
import { PrivateMessage } from "./wire";
import { PrivateMessageContentTopic } from "../waku";
import * as sigUtil from "eth-sig-util";
2021-08-12 15:26:06 +10:00
const useStyles = makeStyles((theme) => ({
formControl: {
margin: theme.spacing(1),
minWidth: 120,
},
selectEmpty: {
marginTop: theme.spacing(2),
},
}));
export interface Props {
waku: Waku | undefined;
// address, public key
recipients: Map<string, Uint8Array>;
}
export default function SendMessage({ waku, recipients }: Props) {
const classes = useStyles();
2022-02-04 14:12:00 +11:00
const [recipient, setRecipient] = useState<string>("");
2021-08-12 15:26:06 +10:00
const [message, setMessage] = useState<string>();
const handleRecipientChange = (
event: ChangeEvent<{ name?: string; value: unknown }>
) => {
setRecipient(event.target.value as string);
};
const handleMessageChange = (event: ChangeEvent<HTMLInputElement>) => {
setMessage(event.target.value);
};
const items = Array.from(recipients.keys()).map((recipient) => {
return (
<MenuItem key={recipient} value={recipient}>
{recipient}
</MenuItem>
);
});
const keyDownHandler = async (event: KeyboardEvent<HTMLInputElement>) => {
if (
2022-02-04 14:12:00 +11:00
event.key === "Enter" &&
2021-08-12 15:26:06 +10:00
!event.altKey &&
!event.ctrlKey &&
!event.shiftKey
) {
if (!waku) return;
if (!recipient) return;
if (!message) return;
const publicKey = recipients.get(recipient);
if (!publicKey) return;
sendMessage(waku, recipient, publicKey, message, (res) => {
if (res) {
2022-02-04 14:12:00 +11:00
console.log("callback called with", res);
setMessage("");
2021-08-12 15:26:06 +10:00
}
});
}
};
return (
<div
style={{
2022-02-04 14:12:00 +11:00
display: "flex",
alignItems: "center",
flexWrap: "wrap",
2021-08-12 15:26:06 +10:00
}}
>
<FormControl className={classes.formControl}>
<InputLabel id="select-recipient-label">Recipient</InputLabel>
<Select
labelId="select-recipient"
id="select-recipient"
value={recipient}
onChange={handleRecipientChange}
>
{items}
</Select>
</FormControl>
<TextField
id="message-input"
label="Message"
variant="filled"
onChange={handleMessageChange}
onKeyDown={keyDownHandler}
value={message}
/>
</div>
);
}
async function encodeEncryptedWakuMessage(
message: string,
publicKey: Uint8Array,
address: string
): Promise<WakuMessage> {
2021-08-17 16:35:08 +10:00
const privateMessage = new PrivateMessage({
2022-02-14 10:50:02 +11:00
toAddress: hexToBytes(address),
2021-08-12 15:26:06 +10:00
message: message,
});
2021-08-17 16:35:08 +10:00
const payload = privateMessage.encode();
const encObj = sigUtil.encrypt(
2022-02-04 14:12:00 +11:00
Buffer.from(publicKey).toString("base64"),
2022-02-14 10:50:02 +11:00
{ data: bytesToHex(payload) },
2022-02-04 14:12:00 +11:00
"x25519-xsalsa20-poly1305"
);
2022-02-04 14:12:00 +11:00
const encryptedPayload = Buffer.from(JSON.stringify(encObj), "utf8");
2021-08-17 16:35:08 +10:00
return WakuMessage.fromBytes(encryptedPayload, PrivateMessageContentTopic);
2021-08-12 15:26:06 +10:00
}
function sendMessage(
waku: Waku,
recipientAddress: string,
recipientPublicKey: Uint8Array,
message: string,
callback: (res: boolean) => void
) {
encodeEncryptedWakuMessage(message, recipientPublicKey, recipientAddress)
.then((msg) => {
2022-02-04 14:12:00 +11:00
console.log("pushing");
2021-08-12 15:26:06 +10:00
waku.lightPush
.push(msg)
.then((res) => {
2022-02-04 14:12:00 +11:00
console.log("Message sent", res);
2021-08-12 15:26:06 +10:00
callback(res ? res.isSuccess : false);
})
.catch((e) => {
2022-02-04 14:12:00 +11:00
console.error("Failed to send message", e);
2021-08-12 15:26:06 +10:00
callback(false);
});
})
.catch((e) => {
2022-02-04 14:12:00 +11:00
console.error("Cannot encode & encrypt message", e);
2021-08-12 15:26:06 +10:00
callback(false);
});
}