Merge branch 'master' of github.com:waku-org/js-waku-examples into weboko/create-waku-imp

This commit is contained in:
weboko 2022-12-21 21:22:23 +01:00
parent 5da4ca1751
commit 9ab90ef7d2
No known key found for this signature in database
12 changed files with 7206 additions and 1091 deletions

View File

@ -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

View File

@ -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]);

View File

@ -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
); );

View File

@ -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[];
} }

View File

@ -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 });

View File

@ -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;

View File

@ -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 = "";
}, },
}; };
} }

View File

@ -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;

View File

@ -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.

View File

@ -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);
} }

View File

@ -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" }
); );