Merge branch 'master' of github.com:waku-org/js-waku-examples into weboko/create-waku-imp
This commit is contained in:
parent
5da4ca1751
commit
9ab90ef7d2
|
@ -9,10 +9,10 @@
|
||||||
"@material-ui/core": "^4.12.4",
|
"@material-ui/core": "^4.12.4",
|
||||||
"@material-ui/icons": "^4.11.3",
|
"@material-ui/icons": "^4.11.3",
|
||||||
"@waku/byte-utils": "0.0.2",
|
"@waku/byte-utils": "0.0.2",
|
||||||
"@waku/core": "0.0.6",
|
"@waku/core": "^0.0.8",
|
||||||
"@waku/create": "0.0.4",
|
"@waku/create": "^0.0.6",
|
||||||
"@waku/interfaces": "0.0.5",
|
"@waku/interfaces": "^0.0.6",
|
||||||
"@waku/message-encryption": "0.0.4",
|
"@waku/message-encryption": "^0.0.7",
|
||||||
"ethers": "5.7.1",
|
"ethers": "5.7.1",
|
||||||
"fontsource-roboto": "^4.0.0",
|
"fontsource-roboto": "^4.0.0",
|
||||||
"protobufjs": "^7.1.2",
|
"protobufjs": "^7.1.2",
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -2,8 +2,9 @@ import "@ethersproject/shims";
|
||||||
|
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import "./App.css";
|
import "./App.css";
|
||||||
import type { WakuPrivacy } from "@waku/interfaces";
|
import type { RelayNode, IDecoder } from "@waku/interfaces";
|
||||||
import { AsymDecoder, SymDecoder } from "@waku/message-encryption";
|
import { createDecoder as createSymmetricDecoder } from "@waku/message-encryption/symmetric";
|
||||||
|
import { createDecoder, DecodedMessage } from "@waku/message-encryption/ecies";
|
||||||
import { KeyPair, PublicKeyMessageEncryptionKey } from "./crypto";
|
import { KeyPair, PublicKeyMessageEncryptionKey } from "./crypto";
|
||||||
import { Message } from "./messaging/Messages";
|
import { Message } from "./messaging/Messages";
|
||||||
import "fontsource-roboto";
|
import "fontsource-roboto";
|
||||||
|
@ -67,13 +68,13 @@ const useStyles = makeStyles({
|
||||||
});
|
});
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
const [waku, setWaku] = useState<WakuPrivacy>();
|
const [waku, setWaku] = useState<RelayNode>();
|
||||||
const [provider, setProvider] = useState<Web3Provider>();
|
const [provider, setProvider] = useState<Web3Provider>();
|
||||||
const [encryptionKeyPair, setEncryptionKeyPair] = useState<
|
const [encryptionKeyPair, setEncryptionKeyPair] = useState<
|
||||||
KeyPair | undefined
|
KeyPair | undefined
|
||||||
>();
|
>();
|
||||||
const [privateMessageDecoder, setPrivateMessageDecoder] =
|
const [privateMessageDecoder, setPrivateMessageDecoder] =
|
||||||
useState<AsymDecoder>();
|
useState<IDecoder<DecodedMessage>>();
|
||||||
const [publicKeys, setPublicKeys] = useState<Map<string, Uint8Array>>(
|
const [publicKeys, setPublicKeys] = useState<Map<string, Uint8Array>>(
|
||||||
new Map()
|
new Map()
|
||||||
);
|
);
|
||||||
|
@ -109,7 +110,7 @@ function App() {
|
||||||
setPublicKeys
|
setPublicKeys
|
||||||
);
|
);
|
||||||
|
|
||||||
const publicKeyMessageDecoder = new SymDecoder(
|
const publicKeyMessageDecoder = createSymmetricDecoder(
|
||||||
PublicKeyContentTopic,
|
PublicKeyContentTopic,
|
||||||
PublicKeyMessageEncryptionKey
|
PublicKeyMessageEncryptionKey
|
||||||
);
|
);
|
||||||
|
@ -134,7 +135,7 @@ function App() {
|
||||||
if (!encryptionKeyPair) return;
|
if (!encryptionKeyPair) return;
|
||||||
|
|
||||||
setPrivateMessageDecoder(
|
setPrivateMessageDecoder(
|
||||||
new AsymDecoder(PrivateMessageContentTopic, encryptionKeyPair.privateKey)
|
createDecoder(PrivateMessageContentTopic, encryptionKeyPair.privateKey)
|
||||||
);
|
);
|
||||||
}, [encryptionKeyPair]);
|
}, [encryptionKeyPair]);
|
||||||
|
|
||||||
|
|
|
@ -6,14 +6,14 @@ import {
|
||||||
PublicKeyMessageEncryptionKey,
|
PublicKeyMessageEncryptionKey,
|
||||||
} from "./crypto";
|
} from "./crypto";
|
||||||
import { PublicKeyMessage } from "./messaging/wire";
|
import { PublicKeyMessage } from "./messaging/wire";
|
||||||
import type { WakuPrivacy } from "@waku/interfaces";
|
import type { RelayNode } from "@waku/interfaces";
|
||||||
import { SymEncoder } from "@waku/message-encryption";
|
import { createEncoder } from "@waku/message-encryption/symmetric";
|
||||||
import { PublicKeyContentTopic } from "./waku";
|
import { PublicKeyContentTopic } from "./waku";
|
||||||
import type { TypedDataSigner } from "@ethersproject/abstract-signer";
|
import type { TypedDataSigner } from "@ethersproject/abstract-signer";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
encryptionKeyPair: KeyPair | undefined;
|
encryptionKeyPair: KeyPair | undefined;
|
||||||
waku: WakuPrivacy | undefined;
|
waku: RelayNode | undefined;
|
||||||
address: string | undefined;
|
address: string | undefined;
|
||||||
signer: TypedDataSigner | undefined;
|
signer: TypedDataSigner | undefined;
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ export default function BroadcastPublicKey({
|
||||||
})();
|
})();
|
||||||
const payload = _publicKeyMessage.encode();
|
const payload = _publicKeyMessage.encode();
|
||||||
|
|
||||||
const publicKeyMessageEncoder = new SymEncoder(
|
const publicKeyMessageEncoder = createEncoder(
|
||||||
PublicKeyContentTopic,
|
PublicKeyContentTopic,
|
||||||
PublicKeyMessageEncryptionKey
|
PublicKeyMessageEncryptionKey
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import Messages, { Message } from "./Messages";
|
import Messages, { Message } from "./Messages";
|
||||||
import type { WakuPrivacy } from "@waku/interfaces";
|
import type { RelayNode } from "@waku/interfaces";
|
||||||
import SendMessage from "./SendMessage";
|
import SendMessage from "./SendMessage";
|
||||||
import { makeStyles } from "@material-ui/core";
|
import { makeStyles } from "@material-ui/core";
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ const useStyles = makeStyles({
|
||||||
});
|
});
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
waku: WakuPrivacy | undefined;
|
waku: RelayNode | undefined;
|
||||||
recipients: Map<string, Uint8Array>;
|
recipients: Map<string, Uint8Array>;
|
||||||
messages: Message[];
|
messages: Message[];
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,8 +7,8 @@ import {
|
||||||
TextField,
|
TextField,
|
||||||
} from "@material-ui/core";
|
} from "@material-ui/core";
|
||||||
import React, { ChangeEvent, useState, KeyboardEvent } from "react";
|
import React, { ChangeEvent, useState, KeyboardEvent } from "react";
|
||||||
import type { WakuPrivacy } from "@waku/interfaces";
|
import type { RelayNode } from "@waku/interfaces";
|
||||||
import { AsymEncoder } from "@waku/message-encryption";
|
import { createEncoder } from "@waku/message-encryption/ecies";
|
||||||
import { PrivateMessage } from "./wire";
|
import { PrivateMessage } from "./wire";
|
||||||
import { PrivateMessageContentTopic } from "../waku";
|
import { PrivateMessageContentTopic } from "../waku";
|
||||||
import { hexToBytes } from "@waku/byte-utils";
|
import { hexToBytes } from "@waku/byte-utils";
|
||||||
|
@ -24,7 +24,7 @@ const useStyles = makeStyles((theme) => ({
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
waku: WakuPrivacy | undefined;
|
waku: RelayNode | undefined;
|
||||||
// address, public key
|
// address, public key
|
||||||
recipients: Map<string, Uint8Array>;
|
recipients: Map<string, Uint8Array>;
|
||||||
}
|
}
|
||||||
|
@ -106,7 +106,7 @@ export default function SendMessage({ waku, recipients }: Props) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function sendMessage(
|
async function sendMessage(
|
||||||
waku: WakuPrivacy,
|
waku: RelayNode,
|
||||||
recipientAddress: string,
|
recipientAddress: string,
|
||||||
recipientPublicKey: Uint8Array,
|
recipientPublicKey: Uint8Array,
|
||||||
message: string,
|
message: string,
|
||||||
|
@ -118,10 +118,7 @@ async function sendMessage(
|
||||||
});
|
});
|
||||||
const payload = privateMessage.encode();
|
const payload = privateMessage.encode();
|
||||||
|
|
||||||
const encoder = new AsymEncoder(
|
const encoder = createEncoder(PrivateMessageContentTopic, recipientPublicKey);
|
||||||
PrivateMessageContentTopic,
|
|
||||||
recipientPublicKey
|
|
||||||
);
|
|
||||||
|
|
||||||
console.log("pushing");
|
console.log("pushing");
|
||||||
const res = await waku.relay.send(encoder, { payload });
|
const res = await waku.relay.send(encoder, { payload });
|
||||||
|
|
|
@ -1,19 +1,20 @@
|
||||||
import { Dispatch, SetStateAction } from "react";
|
import { Dispatch, SetStateAction } from "react";
|
||||||
import type { Message as WakuMessage, WakuPrivacy } from "@waku/interfaces";
|
import type { RelayNode } from "@waku/interfaces";
|
||||||
import { Protocols } from "@waku/interfaces";
|
import { Protocols } from "@waku/interfaces";
|
||||||
import { PrivateMessage, PublicKeyMessage } from "./messaging/wire";
|
import { PrivateMessage, PublicKeyMessage } from "./messaging/wire";
|
||||||
import { validatePublicKeyMessage } from "./crypto";
|
import { validatePublicKeyMessage } from "./crypto";
|
||||||
import { Message } from "./messaging/Messages";
|
import { Message } from "./messaging/Messages";
|
||||||
import { equals } from "uint8arrays/equals";
|
import { equals } from "uint8arrays/equals";
|
||||||
import { waitForRemotePeer } from "@waku/core/lib/wait_for_remote_peer";
|
import { waitForRemotePeer } from "@waku/core";
|
||||||
import { createPrivacyNode } from "@waku/create";
|
import { createRelayNode } from "@waku/create";
|
||||||
import { bytesToHex, hexToBytes } from "@waku/byte-utils";
|
import { bytesToHex, hexToBytes } from "@waku/byte-utils";
|
||||||
|
import type { DecodedMessage } from "@waku/message-encryption";
|
||||||
|
|
||||||
export const PublicKeyContentTopic = "/eth-pm/1/public-key/proto";
|
export const PublicKeyContentTopic = "/eth-pm/1/public-key/proto";
|
||||||
export const PrivateMessageContentTopic = "/eth-pm/1/private-message/proto";
|
export const PrivateMessageContentTopic = "/eth-pm/1/private-message/proto";
|
||||||
|
|
||||||
export async function initWaku(): Promise<WakuPrivacy> {
|
export async function initWaku(): Promise<RelayNode> {
|
||||||
const waku = await createPrivacyNode({ defaultBootstrap: true });
|
const waku = await createRelayNode({ defaultBootstrap: true });
|
||||||
await waku.start();
|
await waku.start();
|
||||||
await waitForRemotePeer(waku, [Protocols.Relay]);
|
await waitForRemotePeer(waku, [Protocols.Relay]);
|
||||||
|
|
||||||
|
@ -23,7 +24,7 @@ export async function initWaku(): Promise<WakuPrivacy> {
|
||||||
export function handlePublicKeyMessage(
|
export function handlePublicKeyMessage(
|
||||||
myAddress: string | undefined,
|
myAddress: string | undefined,
|
||||||
setter: Dispatch<SetStateAction<Map<string, Uint8Array>>>,
|
setter: Dispatch<SetStateAction<Map<string, Uint8Array>>>,
|
||||||
msg: WakuMessage
|
msg: DecodedMessage
|
||||||
) {
|
) {
|
||||||
console.log("Public Key Message received:", msg);
|
console.log("Public Key Message received:", msg);
|
||||||
if (!msg.payload) return;
|
if (!msg.payload) return;
|
||||||
|
@ -49,7 +50,7 @@ export function handlePublicKeyMessage(
|
||||||
export async function handlePrivateMessage(
|
export async function handlePrivateMessage(
|
||||||
setter: Dispatch<SetStateAction<Message[]>>,
|
setter: Dispatch<SetStateAction<Message[]>>,
|
||||||
address: string,
|
address: string,
|
||||||
wakuMsg: WakuMessage
|
wakuMsg: DecodedMessage
|
||||||
) {
|
) {
|
||||||
console.log("Private Message received:", wakuMsg);
|
console.log("Private Message received:", wakuMsg);
|
||||||
if (!wakuMsg.payload) return;
|
if (!wakuMsg.payload) return;
|
||||||
|
|
|
@ -1,164 +1,171 @@
|
||||||
import * as utils from "https://unpkg.com/@waku/byte-utils@0.0.2/bundle/index.js";
|
import * as utils from "https://unpkg.com/@waku/byte-utils@0.0.2/bundle/index.js";
|
||||||
import * as wakuCreate from "https://unpkg.com/@waku/create@0.0.4/bundle/index.js";
|
import * as wakuCreate from "https://unpkg.com/@waku/create@0.0.5/bundle/index.js";
|
||||||
import { waitForRemotePeer } from "https://unpkg.com/@waku/core@0.0.6/bundle/lib/wait_for_remote_peer.js";
|
import {
|
||||||
import * as wakuMessage from "https://unpkg.com/@waku/core@0.0.6/bundle/lib/waku_message/version_0.js";
|
waitForRemotePeer,
|
||||||
|
createDecoder,
|
||||||
|
createEncoder,
|
||||||
|
} from "https://unpkg.com/@waku/core@0.0.7/bundle/index.js";
|
||||||
|
|
||||||
const MULTI_ADDR = "/dns4/node-01.ac-cn-hongkong-c.wakuv2.test.statusim.net/tcp/443/wss/p2p/16Uiu2HAkvWiyFsgRhuJEb9JfjYxEkoHLgnUQmr1N5mKWnYjxYRVm";
|
const MULTI_ADDR =
|
||||||
|
"/dns4/node-01.ac-cn-hongkong-c.wakuv2.test.statusim.net/tcp/443/wss/p2p/16Uiu2HAkvWiyFsgRhuJEb9JfjYxEkoHLgnUQmr1N5mKWnYjxYRVm";
|
||||||
const CONTENT_TOPIC = "/toy-chat/2/huilong/proto";
|
const CONTENT_TOPIC = "/toy-chat/2/huilong/proto";
|
||||||
const PROTOCOLS = ["filter", "lightpush"];
|
const PROTOCOLS = ["filter", "lightpush"];
|
||||||
|
|
||||||
const ui = initUI();
|
const ui = initUI();
|
||||||
runApp(ui).catch((err) => {
|
runApp(ui).catch((err) => {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
ui.setStatus(`error: ${err.message}`, "error");
|
ui.setStatus(`error: ${err.message}`, "error");
|
||||||
});
|
});
|
||||||
|
|
||||||
async function runApp(ui) {
|
async function runApp(ui) {
|
||||||
ui.setStatus("connecting...", "progress");
|
ui.setStatus("connecting...", "progress");
|
||||||
|
|
||||||
const { info, sendMessage, unsubscribeFromMessages } = await initWakuContext({
|
const { info, sendMessage, unsubscribeFromMessages } = await initWakuContext({
|
||||||
protocols: PROTOCOLS,
|
protocols: PROTOCOLS,
|
||||||
multiAddr: MULTI_ADDR,
|
multiAddr: MULTI_ADDR,
|
||||||
contentTopic: CONTENT_TOPIC,
|
contentTopic: CONTENT_TOPIC,
|
||||||
onMessageReceived: ui.renderMessage,
|
onMessageReceived: ui.renderMessage,
|
||||||
});
|
});
|
||||||
|
|
||||||
ui.setStatus("connected", "success");
|
ui.setStatus("connected", "success");
|
||||||
|
|
||||||
ui.setLocalPeer(info.localPeerId);
|
ui.setLocalPeer(info.localPeerId);
|
||||||
ui.setRemotePeer(info.remotePeerIds);
|
ui.setRemotePeer(info.remotePeerIds);
|
||||||
ui.setRemoteMultiAddr(info.multiAddr);
|
ui.setRemoteMultiAddr(info.multiAddr);
|
||||||
ui.setContentTopic(info.contentTopic);
|
ui.setContentTopic(info.contentTopic);
|
||||||
|
|
||||||
ui.onSendMessage(sendMessage);
|
ui.onSendMessage(sendMessage);
|
||||||
|
|
||||||
ui.onExit(async () => {
|
ui.onExit(async () => {
|
||||||
ui.setStatus("disconnecting...", "progress");
|
ui.setStatus("disconnecting...", "progress");
|
||||||
await unsubscribeFromMessages();
|
await unsubscribeFromMessages();
|
||||||
ui.setStatus("disconnected", "terminated");
|
ui.setStatus("disconnected", "terminated");
|
||||||
ui.resetMessages();
|
ui.resetMessages();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function initWakuContext({
|
async function initWakuContext({
|
||||||
multiAddr,
|
multiAddr,
|
||||||
protocols,
|
protocols,
|
||||||
contentTopic,
|
contentTopic,
|
||||||
onMessageReceived,
|
onMessageReceived,
|
||||||
}) {
|
}) {
|
||||||
const Decoder = new wakuMessage.DecoderV0(contentTopic);
|
const Decoder = createDecoder(contentTopic);
|
||||||
const Encoder = new wakuMessage.EncoderV0(contentTopic);
|
const Encoder = createEncoder(contentTopic);
|
||||||
|
|
||||||
const ChatMessage = new protobuf.Type("ChatMessage")
|
const ChatMessage = new protobuf.Type("ChatMessage")
|
||||||
.add(new protobuf.Field("timestamp", 1, "uint64"))
|
.add(new protobuf.Field("timestamp", 1, "uint64"))
|
||||||
.add(new protobuf.Field("nick", 2, "string"))
|
.add(new protobuf.Field("nick", 2, "string"))
|
||||||
.add(new protobuf.Field("text", 3, "bytes"));
|
.add(new protobuf.Field("text", 3, "bytes"));
|
||||||
|
|
||||||
const node = await wakuCreate.createLightNode({ defaultBootstrap: true });
|
const node = await wakuCreate.createLightNode({ defaultBootstrap: true });
|
||||||
|
|
||||||
await node.start();
|
await node.start();
|
||||||
await waitForRemotePeer(node, protocols);
|
await waitForRemotePeer(node, protocols);
|
||||||
|
|
||||||
// Set a filter by using Decoder for a given ContentTopic
|
// Set a filter by using Decoder for a given ContentTopic
|
||||||
const unsubscribeFromMessages = await node.filter.subscribe([Decoder], (wakuMessage) => {
|
const unsubscribeFromMessages = await node.filter.subscribe(
|
||||||
const messageObj = ChatMessage.decode(wakuMessage.payload);
|
[Decoder],
|
||||||
onMessageReceived({
|
(wakuMessage) => {
|
||||||
...messageObj,
|
const messageObj = ChatMessage.decode(wakuMessage.payload);
|
||||||
text: utils.bytesToUtf8(messageObj.text),
|
onMessageReceived({
|
||||||
});
|
...messageObj,
|
||||||
});
|
text: utils.bytesToUtf8(messageObj.text),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
const localPeerId = node.libp2p.peerId.toString();
|
const localPeerId = node.libp2p.peerId.toString();
|
||||||
|
|
||||||
const remotePeers = await node.libp2p.peerStore.all();
|
const remotePeers = await node.libp2p.peerStore.all();
|
||||||
const remotePeerIds = remotePeers.map(peer => peer.id.toString());
|
const remotePeerIds = remotePeers.map((peer) => peer.id.toString());
|
||||||
|
|
||||||
return {
|
return {
|
||||||
unsubscribeFromMessages,
|
unsubscribeFromMessages,
|
||||||
info: {
|
info: {
|
||||||
multiAddr,
|
multiAddr,
|
||||||
contentTopic,
|
contentTopic,
|
||||||
localPeerId,
|
localPeerId,
|
||||||
remotePeerIds,
|
remotePeerIds,
|
||||||
},
|
},
|
||||||
sendMessage: async ({ text, nick }) => {
|
sendMessage: async ({ text, nick }) => {
|
||||||
if (!text || !nick) {
|
if (!text || !nick) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const protoMessage = ChatMessage.create({
|
const protoMessage = ChatMessage.create({
|
||||||
nick,
|
nick,
|
||||||
timestamp: Date.now(),
|
timestamp: Date.now(),
|
||||||
text: utils.utf8ToBytes(text),
|
text: utils.utf8ToBytes(text),
|
||||||
});
|
});
|
||||||
|
|
||||||
await node.lightPush.push(Encoder, {
|
await node.lightPush.push(Encoder, {
|
||||||
payload: ChatMessage.encode(protoMessage).finish(),
|
payload: ChatMessage.encode(protoMessage).finish(),
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// UI adapter
|
// UI adapter
|
||||||
function initUI() {
|
function initUI() {
|
||||||
const exitButton = document.getElementById("exit");
|
const exitButton = document.getElementById("exit");
|
||||||
const sendButton = document.getElementById("send");
|
const sendButton = document.getElementById("send");
|
||||||
|
|
||||||
const statusBlock = document.getElementById("status");
|
const statusBlock = document.getElementById("status");
|
||||||
const localPeerBlock = document.getElementById("localPeerId");
|
const localPeerBlock = document.getElementById("localPeerId");
|
||||||
const remotePeerId = document.getElementById("remotePeerId");
|
const remotePeerId = document.getElementById("remotePeerId");
|
||||||
const remoteMultiAddr = document.getElementById("remoteMultiAddr");
|
const remoteMultiAddr = document.getElementById("remoteMultiAddr");
|
||||||
const contentTopicBlock = document.getElementById("contentTopic");
|
const contentTopicBlock = document.getElementById("contentTopic");
|
||||||
|
|
||||||
const messagesBlock = document.getElementById("messages");
|
const messagesBlock = document.getElementById("messages");
|
||||||
|
|
||||||
const nickText = document.getElementById("nickText");
|
const nickText = document.getElementById("nickText");
|
||||||
const messageText = document.getElementById("messageText");
|
const messageText = document.getElementById("messageText");
|
||||||
|
|
||||||
return {
|
return {
|
||||||
// UI events
|
// UI events
|
||||||
onExit: (cb) => {
|
onExit: (cb) => {
|
||||||
exitButton.addEventListener("click", cb);
|
exitButton.addEventListener("click", cb);
|
||||||
},
|
},
|
||||||
onSendMessage: (cb) => {
|
onSendMessage: (cb) => {
|
||||||
sendButton.addEventListener("click", async () => {
|
sendButton.addEventListener("click", async () => {
|
||||||
await cb({
|
await cb({
|
||||||
nick: nickText.value,
|
nick: nickText.value,
|
||||||
text: messageText.value,
|
text: messageText.value,
|
||||||
});
|
});
|
||||||
messageText.value = "";
|
messageText.value = "";
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
// UI renderers
|
// UI renderers
|
||||||
setStatus: (value, className) => {
|
setStatus: (value, className) => {
|
||||||
statusBlock.innerHTML = `<span class=${className || ""}>${value}</span>`;
|
statusBlock.innerHTML = `<span class=${className || ""}>${value}</span>`;
|
||||||
},
|
},
|
||||||
setLocalPeer: (id) => {
|
setLocalPeer: (id) => {
|
||||||
localPeerBlock.innerText = id.toString();
|
localPeerBlock.innerText = id.toString();
|
||||||
},
|
},
|
||||||
setRemotePeer: (ids) => {
|
setRemotePeer: (ids) => {
|
||||||
remotePeerId.innerText = ids.join("\n");
|
remotePeerId.innerText = ids.join("\n");
|
||||||
},
|
},
|
||||||
setRemoteMultiAddr: (multiAddr) => {
|
setRemoteMultiAddr: (multiAddr) => {
|
||||||
remoteMultiAddr.innerText = multiAddr.toString();
|
remoteMultiAddr.innerText = multiAddr.toString();
|
||||||
},
|
},
|
||||||
setContentTopic: (topic) => {
|
setContentTopic: (topic) => {
|
||||||
contentTopicBlock.innerText = topic.toString();
|
contentTopicBlock.innerText = topic.toString();
|
||||||
},
|
},
|
||||||
renderMessage: (messageObj) => {
|
renderMessage: (messageObj) => {
|
||||||
const { nick, text, timestamp } = messageObj;
|
const { nick, text, timestamp } = messageObj;
|
||||||
const date = new Date(timestamp);
|
const date = new Date(timestamp);
|
||||||
|
|
||||||
// WARNING: XSS vulnerable
|
// WARNING: XSS vulnerable
|
||||||
messagesBlock.innerHTML += `
|
messagesBlock.innerHTML += `
|
||||||
<div class="message">
|
<div class="message">
|
||||||
<p>${nick} <span>(${date.toDateString()})</span>:</p>
|
<p>${nick} <span>(${date.toDateString()})</span>:</p>
|
||||||
<p>${text}</p>
|
<p>${text}</p>
|
||||||
<div>
|
<div>
|
||||||
`;
|
`;
|
||||||
},
|
},
|
||||||
resetMessages: () => {
|
resetMessages: () => {
|
||||||
messagesBlock.innerHTML = "";
|
messagesBlock.innerHTML = "";
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,12 +39,12 @@
|
||||||
|
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import * as utils from "https://unpkg.com/@waku/byte-utils@0.0.2/bundle/index.js";
|
import * as utils from "https://unpkg.com/@waku/byte-utils@0.0.2/bundle/index.js";
|
||||||
import { createLightNode } from "https://unpkg.com/@waku/create@0.0.4/bundle/index.js";
|
import { createLightNode } from "https://unpkg.com/@waku/create@0.0.5/bundle/index.js";
|
||||||
import { waitForRemotePeer } from "https://unpkg.com/@waku/core@0.0.6/bundle/lib/wait_for_remote_peer.js";
|
|
||||||
import {
|
import {
|
||||||
EncoderV0,
|
waitForRemotePeer,
|
||||||
DecoderV0,
|
createEncoder,
|
||||||
} from "https://unpkg.com/@waku/core@0.0.6/bundle/lib/waku_message/version_0.js";
|
createDecoder,
|
||||||
|
} from "https://unpkg.com/@waku/core@0.0.7/bundle/index.js";
|
||||||
|
|
||||||
const peerIdDiv = document.getElementById("peer-id");
|
const peerIdDiv = document.getElementById("peer-id");
|
||||||
const remotePeerIdDiv = document.getElementById("remote-peer-id");
|
const remotePeerIdDiv = document.getElementById("remote-peer-id");
|
||||||
|
@ -58,8 +58,8 @@
|
||||||
const sendButton = document.getElementById("sendButton");
|
const sendButton = document.getElementById("sendButton");
|
||||||
|
|
||||||
const ContentTopic = "/js-waku-examples/1/chat/utf8";
|
const ContentTopic = "/js-waku-examples/1/chat/utf8";
|
||||||
const decoder = new DecoderV0(ContentTopic);
|
const decoder = createDecoder(ContentTopic);
|
||||||
const encoder = new EncoderV0(ContentTopic);
|
const encoder = createEncoder(ContentTopic);
|
||||||
let messages = [];
|
let messages = [];
|
||||||
let unsubscribe;
|
let unsubscribe;
|
||||||
|
|
||||||
|
|
|
@ -34,12 +34,12 @@
|
||||||
bytesToUtf8,
|
bytesToUtf8,
|
||||||
utf8ToBytes,
|
utf8ToBytes,
|
||||||
} from "https://unpkg.com/@waku/byte-utils@0.0.2/bundle/index.js";
|
} from "https://unpkg.com/@waku/byte-utils@0.0.2/bundle/index.js";
|
||||||
import { createPrivacyNode } from "https://unpkg.com/@waku/create@0.0.4/bundle/index.js";
|
import { createRelayNode } from "https://unpkg.com/@waku/create@0.0.5/bundle/index.js";
|
||||||
import { waitForRemotePeer } from "https://unpkg.com/@waku/core@0.0.6/bundle/lib/wait_for_remote_peer.js";
|
|
||||||
import {
|
import {
|
||||||
DecoderV0,
|
waitForRemotePeer,
|
||||||
EncoderV0,
|
createDecoder,
|
||||||
} from "https://unpkg.com/@waku/core@0.0.6/bundle/lib/waku_message/version_0.js";
|
createEncoder,
|
||||||
|
} from "https://unpkg.com/@waku/core@0.0.7/bundle/index.js";
|
||||||
|
|
||||||
const statusDiv = document.getElementById("status");
|
const statusDiv = document.getElementById("status");
|
||||||
const messagesDiv = document.getElementById("messages");
|
const messagesDiv = document.getElementById("messages");
|
||||||
|
@ -55,8 +55,8 @@
|
||||||
|
|
||||||
// Prepare encoder and decoder, `V0` for clear text messages.
|
// Prepare encoder and decoder, `V0` for clear text messages.
|
||||||
|
|
||||||
const encoder = new EncoderV0(contentTopic);
|
const encoder = createEncoder(contentTopic);
|
||||||
const decoder = new DecoderV0(contentTopic);
|
const decoder = createDecoder(contentTopic);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
statusDiv.innerHTML = "<p>Starting</p>";
|
statusDiv.innerHTML = "<p>Starting</p>";
|
||||||
|
@ -66,7 +66,7 @@
|
||||||
// We are currently working on migrating this method to DNS Discovery.
|
// We are currently working on migrating this method to DNS Discovery.
|
||||||
//
|
//
|
||||||
// https://js.waku.org/functions/lib_create_waku.createPrivacyNode.html
|
// https://js.waku.org/functions/lib_create_waku.createPrivacyNode.html
|
||||||
const waku = await createPrivacyNode({ defaultBootstrap: true });
|
const waku = await createRelayNode({ defaultBootstrap: true });
|
||||||
await waku.start();
|
await waku.start();
|
||||||
|
|
||||||
// Add a hook to process all incoming messages on a specified content topic.
|
// Add a hook to process all incoming messages on a specified content topic.
|
||||||
|
|
|
@ -44,29 +44,33 @@
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="w50">
|
<div class="w50">
|
||||||
<h4>You can either generate new credentials:</h4>
|
<h4>Generate new, or import existing, credentials from wallet:</h4>
|
||||||
<button disabled id="generate-credentials" type="button">
|
|
||||||
Generate RLN Credentials
|
|
||||||
</button>
|
|
||||||
<br />
|
<br />
|
||||||
|
<div id="import-from-wallet">
|
||||||
|
<button id="import-from-wallet-button" type="button">
|
||||||
|
Generate RLN Credentials
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
<br />
|
<br />
|
||||||
<button disabled id="register-button" type="button">
|
<button disabled id="register-button" type="button">
|
||||||
Register Credentials in Contract
|
Register Credentials in Contract
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="w50">
|
<div class="w50">
|
||||||
<h4>Or import existing ones:</h4>
|
<h4>Import existing credentials manually:</h4>
|
||||||
<label for="membership-id"
|
<div>
|
||||||
>Membership ID (your index in the RLN smart contract):</label
|
<label for="membership-id"
|
||||||
>
|
>Membership ID (your index in the RLN smart contract):</label
|
||||||
<input id="membership-id" name="membership-id" type="text" />
|
>
|
||||||
<label for="id-key">RLN Identity Key (hex string):</label>
|
<input id="membership-id" name="membership-id" type="text" />
|
||||||
<input id="id-key" name="id-key" type="text" />
|
<label for="id-key">RLN Identity Key (hex string):</label>
|
||||||
<label for="commitment-key">RLN Commitment Key (hex string):</label>
|
<input id="id-key" name="id-key" type="text" />
|
||||||
<input id="commitment-key" name="commitment-key" type="text" />
|
<label for="commitment-key">RLN Commitment Key (hex string):</label>
|
||||||
<button disabled id="import-button" type="button">
|
<input id="commitment-key" name="commitment-key" type="text" />
|
||||||
Import RLN Credentials
|
<button disabled id="import-manually-button" type="button">
|
||||||
</button>
|
Import RLN Credentials
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row rcenter mu1">
|
<div class="row rcenter mu1">
|
||||||
|
@ -140,7 +144,7 @@
|
||||||
MembershipKey,
|
MembershipKey,
|
||||||
RLNDecoder,
|
RLNDecoder,
|
||||||
RLNEncoder,
|
RLNEncoder,
|
||||||
} from "https://unpkg.com/@waku/rln@0.0.12-6875952/bundle/index.js";
|
} from "https://unpkg.com/@waku/rln@0.0.13/bundle/index.js";
|
||||||
|
|
||||||
import { ethers } from "https://unpkg.com/ethers@5.7.2/dist/ethers.esm.min.js";
|
import { ethers } from "https://unpkg.com/ethers@5.7.2/dist/ethers.esm.min.js";
|
||||||
|
|
||||||
|
@ -158,14 +162,14 @@
|
||||||
);
|
);
|
||||||
|
|
||||||
// Credentials Elements
|
// Credentials Elements
|
||||||
const generateCredsButton = document.getElementById(
|
|
||||||
"generate-credentials"
|
|
||||||
);
|
|
||||||
|
|
||||||
const membershipIdInput = document.getElementById("membership-id");
|
const membershipIdInput = document.getElementById("membership-id");
|
||||||
const identityKeyInput = document.getElementById("id-key");
|
const identityKeyInput = document.getElementById("id-key");
|
||||||
const commitmentKeyInput = document.getElementById("commitment-key");
|
const commitmentKeyInput = document.getElementById("commitment-key");
|
||||||
const importButton = document.getElementById("import-button");
|
const importManually = document.getElementById("import-manually-button");
|
||||||
|
const importFromWalletButton = document.getElementById(
|
||||||
|
"import-from-wallet-button"
|
||||||
|
);
|
||||||
|
|
||||||
const idDiv = document.getElementById("id");
|
const idDiv = document.getElementById("id");
|
||||||
const keyDiv = document.getElementById("key");
|
const keyDiv = document.getElementById("key");
|
||||||
|
@ -193,9 +197,14 @@
|
||||||
node,
|
node,
|
||||||
nodeConnected,
|
nodeConnected,
|
||||||
rlnInstance;
|
rlnInstance;
|
||||||
|
|
||||||
|
const allMemberships = [];
|
||||||
let retrievedRLNEvents = false;
|
let retrievedRLNEvents = false;
|
||||||
const rlnInstancePromise = create();
|
const rlnInstancePromise = create();
|
||||||
|
|
||||||
|
const DEFAULT_SIGNATURE_MESSAGE =
|
||||||
|
"The signature of this message will be used to generate your RLN credentials. Anyone accessing it may send messages on your behalf, please only share with the RLN dApp";
|
||||||
|
|
||||||
// Load zero-kit WASM blob.
|
// Load zero-kit WASM blob.
|
||||||
|
|
||||||
statusSpan.innerText = "WASM Blob download in progress...";
|
statusSpan.innerText = "WASM Blob download in progress...";
|
||||||
|
@ -232,15 +241,13 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
generateCredsButton.disabled = !rlnInstance;
|
|
||||||
|
|
||||||
registerButton.disabled = !(
|
registerButton.disabled = !(
|
||||||
membershipKey &&
|
membershipKey &&
|
||||||
retrievedRLNEvents &&
|
retrievedRLNEvents &&
|
||||||
!membershipId
|
!membershipId
|
||||||
);
|
);
|
||||||
|
|
||||||
importButton.disabled = !(
|
importManually.disabled = !(
|
||||||
membershipIdInput.value &&
|
membershipIdInput.value &&
|
||||||
identityKeyInput.value &&
|
identityKeyInput.value &&
|
||||||
commitmentKeyInput.value
|
commitmentKeyInput.value
|
||||||
|
@ -258,16 +265,11 @@
|
||||||
|
|
||||||
// Blockchain
|
// Blockchain
|
||||||
|
|
||||||
generateCredsButton.onclick = () => {
|
|
||||||
membershipKey = rlnInstance.generateMembershipKey();
|
|
||||||
updateFields();
|
|
||||||
};
|
|
||||||
|
|
||||||
membershipIdInput.onchange = updateFields;
|
membershipIdInput.onchange = updateFields;
|
||||||
identityKeyInput.onchange = updateFields;
|
identityKeyInput.onchange = updateFields;
|
||||||
commitmentKeyInput.onchange = updateFields;
|
commitmentKeyInput.onchange = updateFields;
|
||||||
|
|
||||||
importButton.onclick = () => {
|
importManually.onclick = () => {
|
||||||
const idKey = utils.hexToBytes(identityKeyInput.value);
|
const idKey = utils.hexToBytes(identityKeyInput.value);
|
||||||
const idCommitment = utils.hexToBytes(commitmentKeyInput.value);
|
const idCommitment = utils.hexToBytes(commitmentKeyInput.value);
|
||||||
membershipKey = new MembershipKey(idKey, idCommitment);
|
membershipKey = new MembershipKey(idKey, idCommitment);
|
||||||
|
@ -275,6 +277,26 @@
|
||||||
updateFields();
|
updateFields();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
importFromWalletButton.onclick = async () => {
|
||||||
|
const signer = provider.getSigner();
|
||||||
|
|
||||||
|
const signature = await signer.signMessage(signatureMessage);
|
||||||
|
|
||||||
|
membershipKey = await rlnInstance.generateSeededMembershipKey(
|
||||||
|
signature
|
||||||
|
);
|
||||||
|
|
||||||
|
const idCommitment = ethers.utils.hexlify(membershipKey.IDCommitment);
|
||||||
|
|
||||||
|
allMemberships.forEach((m) => {
|
||||||
|
if (m.pubkey._hex === idCommitment) {
|
||||||
|
membershipId = m.index.toString();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
updateFields();
|
||||||
|
};
|
||||||
|
|
||||||
const checkChain = async (chainId) => {
|
const checkChain = async (chainId) => {
|
||||||
retrieveRLNDetailsButton.disabled = retrievedRLNEvents || chainId !== 5;
|
retrieveRLNDetailsButton.disabled = retrievedRLNEvents || chainId !== 5;
|
||||||
registerButton.disabled = !(chainId === 5 && retrievedRLNEvents);
|
registerButton.disabled = !(chainId === 5 && retrievedRLNEvents);
|
||||||
|
@ -303,6 +325,8 @@
|
||||||
|
|
||||||
const handleMembership = (pubkey, index) => {
|
const handleMembership = (pubkey, index) => {
|
||||||
try {
|
try {
|
||||||
|
allMemberships.push({ pubkey, index });
|
||||||
|
|
||||||
const idCommitment = ethers.utils.zeroPad(
|
const idCommitment = ethers.utils.zeroPad(
|
||||||
ethers.utils.arrayify(pubkey),
|
ethers.utils.arrayify(pubkey),
|
||||||
32
|
32
|
||||||
|
@ -337,6 +361,8 @@
|
||||||
setAccounts(accounts);
|
setAccounts(accounts);
|
||||||
const network = await provider.getNetwork();
|
const network = await provider.getNetwork();
|
||||||
checkChain(network.chainId);
|
checkChain(network.chainId);
|
||||||
|
|
||||||
|
importFromWalletButton.disabled = false;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log("No web3 provider available", e);
|
console.log("No web3 provider available", e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,13 +14,13 @@
|
||||||
import {
|
import {
|
||||||
defaultLibp2p,
|
defaultLibp2p,
|
||||||
defaultPeerDiscovery,
|
defaultPeerDiscovery,
|
||||||
} from "https://unpkg.com/@waku/create@0.0.4/bundle/index.js";
|
} from "https://unpkg.com/@waku/create@0.0.5/bundle/index.js";
|
||||||
import { waitForRemotePeer } from "https://unpkg.com/@waku/core@0.0.6/bundle/lib/wait_for_remote_peer.js";
|
|
||||||
import {
|
import {
|
||||||
wakuStore,
|
wakuStore,
|
||||||
WakuNode,
|
WakuNode,
|
||||||
} from "https://unpkg.com/@waku/core@0.0.6/bundle/index.js";
|
waitForRemotePeer,
|
||||||
import { DecoderV0 } from "https://unpkg.com/@waku/core@0.0.6/bundle/lib/waku_message/version_0.js";
|
createDecoder,
|
||||||
|
} from "https://unpkg.com/@waku/core@0.0.7/bundle/index.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This example demonstrates how to use the js-waku minified bundle
|
* This example demonstrates how to use the js-waku minified bundle
|
||||||
|
@ -56,7 +56,7 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
await node.store.queryOrderedCallback(
|
await node.store.queryOrderedCallback(
|
||||||
[new DecoderV0("/relay-ping/1/ping/null")],
|
[createDecoder("/relay-ping/1/ping/null")],
|
||||||
callback,
|
callback,
|
||||||
{ pageDirection: "backward" }
|
{ pageDirection: "backward" }
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in New Issue