From 8dfa55096c0bc50aad8f7b7d8ff206a4cb081096 Mon Sep 17 00:00:00 2001 From: Sasha Date: Sun, 3 Dec 2023 00:25:59 +0100 Subject: [PATCH] add basic menu, metamask guard --- src/app/components/Menu.tsx | 12 ++++++++++++ src/app/keystore/page.tsx | 16 +++++++++++++--- src/app/layout.tsx | 6 +++++- src/app/page.tsx | 3 +-- src/hooks/useContract.ts | 6 +++--- src/hooks/useKeystore.ts | 2 +- src/services/rln.ts | 35 ++++++++++++++++++++++++----------- 7 files changed, 59 insertions(+), 21 deletions(-) create mode 100644 src/app/components/Menu.tsx diff --git a/src/app/components/Menu.tsx b/src/app/components/Menu.tsx new file mode 100644 index 0000000..ea06295 --- /dev/null +++ b/src/app/components/Menu.tsx @@ -0,0 +1,12 @@ +import Link from "next/link"; +import { Block } from "@/components/Block"; + +export const Menu: React.FunctionComponent<{}> = () => { + return ( + +

{">"}

+

Chat

+

Keystore

+
+ ); +}; diff --git a/src/app/keystore/page.tsx b/src/app/keystore/page.tsx index f0cf2fe..b2c4796 100644 --- a/src/app/keystore/page.tsx +++ b/src/app/keystore/page.tsx @@ -7,10 +7,20 @@ import { Status } from "@/components/Status"; import { useStore } from "@/hooks"; export default function KeystorePage() { - const { onWalletConnect } = useWallet(); - const { appStatus, wallet } = useStore(); + const { onWalletConnect } = useWallet(); + const { appStatus, wallet } = useStore(); + + if (typeof window !== "undefined" && !window?.ethereum) { + return ( +
+
+

Seems you don't have MetaMask installed. Please, install and reload the page.

+
+ ); + } + return ( -
+
{wallet &&

Wallet connected: {wallet}

} diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 43fdb4d..c678653 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,6 +1,7 @@ import type { Metadata } from "next"; import { Inter } from "next/font/google"; import "./globals.css"; +import { Menu } from "@/app/components/Menu"; const inter = Inter({ subsets: ["latin"] }); @@ -16,7 +17,10 @@ export default function RootLayout({ }) { return ( - {children} + + + {children} + ); } diff --git a/src/app/page.tsx b/src/app/page.tsx index 4be0bc2..5d3db45 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -4,7 +4,6 @@ import { Waku } from "@/app/components/Waku"; import { useWaku } from "@/hooks"; import { DebugInfo } from "@/services/waku"; -export const dynamic = "force-static"; export default function Home() { const { onSend, @@ -15,7 +14,7 @@ export default function Home() { } = useWaku(); return ( -
+
diff --git a/src/hooks/useContract.ts b/src/hooks/useContract.ts index d066900..70a27b4 100644 --- a/src/hooks/useContract.ts +++ b/src/hooks/useContract.ts @@ -12,16 +12,16 @@ export const useContract = (): UseContractResult => { const onFetchContract = React.useCallback(async () => { const fetchAccounts = new Promise(async (resolve) => { - if (!rln) { + if (!rln || !rln?.ethProvider) { console.log("Cannot fetch wallet, not provider found."); resolve(); return; } try { - const accounts = await rln.ethProvider.send("eth_requestAccounts", []); + const accounts = await rln?.ethProvider.send("eth_requestAccounts", []); setEthAccount(accounts[0] || ""); - const network = await rln.ethProvider.getNetwork(); + const network = await rln?.ethProvider.getNetwork(); setChainID(network.chainId); } catch (error) { console.error("Failed to connect to account: ", error); diff --git a/src/hooks/useKeystore.ts b/src/hooks/useKeystore.ts index d56e8fa..b84a468 100644 --- a/src/hooks/useKeystore.ts +++ b/src/hooks/useKeystore.ts @@ -25,7 +25,7 @@ export const useKeystore = (): UseKeystoreResult => { return; } - const signer = rln.ethProvider.getSigner(); + const signer = rln?.ethProvider.getSigner(); const signature = await signer.signMessage( `${SIGNATURE_MESSAGE}. Nonce: ${randomNumber()}` ); diff --git a/src/services/rln.ts b/src/services/rln.ts index 487b034..20259f9 100644 --- a/src/services/rln.ts +++ b/src/services/rln.ts @@ -37,7 +37,7 @@ type IRLN = { export class RLN implements IRLN { private readonly emitter = new EventTarget(); - public readonly ethProvider: ethers.providers.Web3Provider; + public ethProvider: ethers.providers.Web3Provider | undefined; public rlnInstance: undefined | RLNInstance; public rlnContract: undefined | RLNContract; @@ -47,14 +47,6 @@ export class RLN implements IRLN { private initializing = false; public constructor() { - const ethereum = - window.ethereum as unknown as ethers.providers.ExternalProvider; - if (!isBrowserProviderValid(ethereum)) { - throw Error( - "Invalid Ethereum provider present on the page. Check if MetaMask is connected." - ); - } - this.ethProvider = new ethers.providers.Web3Provider(ethereum, "any"); this.keystore = this.initKeystore(); } @@ -64,6 +56,8 @@ export class RLN implements IRLN { } this.initializing = true; + + this.initProvider(); await this.initRLNWasm(); // emit keystore keys once app is ready @@ -73,6 +67,21 @@ export class RLN implements IRLN { this.initializing = false; } + private initProvider() { + if (typeof window === "undefined") { + return; + } + + const ethereum = + window.ethereum as unknown as ethers.providers.ExternalProvider; + if (!isBrowserProviderValid(ethereum)) { + throw Error( + "Invalid Ethereum provider present on the page. Check if MetaMask is connected." + ); + } + this.ethProvider = new ethers.providers.Web3Provider(ethereum, "any"); + } + private async initRLNWasm(): Promise { this.emitStatusEvent(StatusEventPayload.WASM_LOADING); try { @@ -89,7 +98,7 @@ export class RLN implements IRLN { } public async initRLNContract(rlnInstance: RLNInstance): Promise { - if (this.rlnContract) { + if (this.rlnContract || !this.ethProvider) { return; } @@ -110,8 +119,12 @@ export class RLN implements IRLN { private initKeystore(): Keystore { const localKeystoreString = localStorage.getItem("keystore"); + if (!localKeystoreString) { + return Keystore.create(); + } + try { - return Keystore.fromString(localKeystoreString || ""); + return Keystore.fromString(localKeystoreString || "") || Keystore.create(); } catch(error) { return Keystore.create(); }