diff --git a/packages/react-app/components/WrongNetworkAlertDialog.jsx b/packages/react-app/components/WrongNetworkAlertDialog.jsx new file mode 100644 index 0000000..1f26da1 --- /dev/null +++ b/packages/react-app/components/WrongNetworkAlertDialog.jsx @@ -0,0 +1,90 @@ +import React, { useContext, useEffect, useState } from "react"; +import { + Button, + AlertDialog, + AlertDialogBody, + AlertDialogFooter, + AlertDialogHeader, + AlertDialogContent, + AlertDialogOverlay, +} from "@chakra-ui/react"; + +import { Web3Context } from "../helpers/Web3Context"; + +function WrongNetworkAlertDialog() { + const [isAlertOpen, setIsAlertOpen] = useState(false); + const context = useContext(Web3Context); + const cancelRef = React.useRef(); + + useEffect(() => { + if (context) { + setIsAlertOpen(!context.rightNetwork); + } + }, [context && context.rightNetwork]); + + const onNetworkSwitch = async () => { + const data = [ + { + chainId: "0x" + context.targetNetwork.chainId.toString(16), + chainName: context.targetNetwork.name, + nativeCurrency: context.targetNetwork.nativeCurrency, + rpcUrls: [context.targetNetwork.rpcUrl], + blockExplorerUrls: [context.targetNetwork.blockExplorer], + }, + ]; + try { + await ethereum.request({ + method: "wallet_switchEthereumChain", + params: [{ chainId: data[0].chainId }], + }); + setIsAlertOpen(false); + } catch (switchError) { + // This error code indicates that the chain has not been added to MetaMask. + if (switchError.code === 4902) { + try { + await ethereum.request({ + method: "wallet_addEthereumChain", + params: data, + }); + setIsAlertOpen(false); + } catch (addError) { + console.log(addError); + } + } + // handle other "switch" errors + } + }; + + return ( + + + + + Switch network + + + + To use this app you must switch to the {context.targetNetwork.name} network. + + + + + + + + + + ); +} + +export default WrongNetworkAlertDialog; diff --git a/packages/react-app/components/cards/MediaCard.jsx b/packages/react-app/components/cards/MediaCard.jsx index 067b0d1..bb1802e 100644 --- a/packages/react-app/components/cards/MediaCard.jsx +++ b/packages/react-app/components/cards/MediaCard.jsx @@ -56,7 +56,6 @@ function MediaCard({ secondaryActionOnClick, secondaryAction, privateProfile, - dRecruitContract, tokenContract, tokenMetadata, }) { @@ -68,6 +67,7 @@ function MediaCard({ const [currAllowance, setCurrAllowance] = useState(); const [unlimitedAllowanceWanted, setUnlimitedAllowanceWanted] = useState(true); const context = useContext(Web3Context); + const dRecruitContract = context.writeContracts.DRecruitV1; const toast = useToast(); @@ -175,12 +175,14 @@ function MediaCard({ useEffect(() => { async function exec() { - const weiStakeAmount = ethers.utils.parseEther(debouncedStakeAmount); - const allowance = await tokenContract.allowance(context.address, dRecruitContract.address); - if (allowance.lt(weiStakeAmount)) { - setApprovalState("NOT_ENOUGH"); - } else { - setApprovalState("ENOUGH"); + if (context.rightNetwork) { + const weiStakeAmount = ethers.utils.parseEther(debouncedStakeAmount); + const allowance = await tokenContract.allowance(context.address, dRecruitContract.address); + if (allowance.lt(weiStakeAmount)) { + setApprovalState("NOT_ENOUGH"); + } else { + setApprovalState("ENOUGH"); + } } } if (debouncedStakeAmount) { @@ -197,8 +199,10 @@ function MediaCard({ useEffect(() => { async function exec() { - const allowance = await tokenContract.allowance(context.address, dRecruitContract.address); - setCurrAllowance(allowance); + if (context.rightNetwork) { + const allowance = await tokenContract.allowance(context.address, dRecruitContract.address); + setCurrAllowance(allowance); + } } exec(); }, [isOpen]); @@ -345,15 +349,17 @@ function MediaCard({ )} - + {context.rightNetwork && ( + + )} diff --git a/packages/react-app/helpers/Web3Context.js b/packages/react-app/helpers/Web3Context.js index b0fbc15..97be51d 100644 --- a/packages/react-app/helpers/Web3Context.js +++ b/packages/react-app/helpers/Web3Context.js @@ -188,6 +188,7 @@ export function Web3Provider({ children, network = "localhost", DEBUG = false, N const localChainId = localProvider && localProvider._network && localProvider._network.chainId; const selectedChainId = userSigner && userSigner.provider && userSigner.provider._network && userSigner.provider._network.chainId; + const rightNetwork = localChainId == selectedChainId; // For more hooks, check out 🔗eth-hooks at: https://www.npmjs.com/package/eth-hooks @@ -268,7 +269,7 @@ export function Web3Provider({ children, network = "localhost", DEBUG = false, N const networkLocal = NETWORK(localChainId); if (selectedChainId === 1337 && localChainId === 31337) { networkDisplay = ( -
+
{ console.log(`chain changed to ${chainId}! updating providers`); - setInjectedProvider(provider); + setInjectedProvider(new ethers.providers.Web3Provider(connection)); }); connection.on("accountsChanged", newAccounts => { @@ -348,13 +352,13 @@ export function Web3Provider({ children, network = "localhost", DEBUG = false, N connection.on("disconnect", (code, reason) => { logoutOfWeb3Modal(); }); - }, [setInjectedProvider]); + }, [setInjectedProvider, rightNetwork]); useEffect(() => { if (web3Modal && web3Modal.cachedProvider) { loadWeb3Modal(); } - }, [web3Modal]); + }, [loadWeb3Modal]); let faucetHint = ""; const faucetAvailable = localProvider && localProvider.connection && targetNetwork.name.indexOf("local") !== -1; @@ -410,6 +414,7 @@ export function Web3Provider({ children, network = "localhost", DEBUG = false, N loadWeb3Modal, logoutOfWeb3Modal, contractConfig, + rightNetwork, }; return {children}; diff --git a/packages/react-app/pages/_app.js b/packages/react-app/pages/_app.js index 8ae1a52..6c67aaf 100644 --- a/packages/react-app/pages/_app.js +++ b/packages/react-app/pages/_app.js @@ -3,10 +3,11 @@ import "antd/dist/antd.css"; import Head from "next/head"; import Link from "next/link"; import { ChakraProvider } from "@chakra-ui/react"; -import React, { useEffect, useRef, useState } from "react"; +import React, { useContext, useEffect, useRef, useState } from "react"; import { ThemeSwitcherProvider } from "react-css-theme-switcher"; import { Header } from "../components"; import DevUI from "../components/DevUI"; +import WrongNetworkAlertDialog from "../components/WrongNetworkAlertDialog"; import { Web3Provider } from "../helpers/Web3Context"; import "../styles/index.css"; @@ -59,6 +60,7 @@ function MyApp({ Component, pageProps }) { + diff --git a/packages/react-app/pages/index.js b/packages/react-app/pages/index.js index 76e29a1..f7e0b0b 100644 --- a/packages/react-app/pages/index.js +++ b/packages/react-app/pages/index.js @@ -1,23 +1,7 @@ import React, { useCallback, useContext, useEffect, useState } from "react"; import { Core } from "@self.id/core"; import axios from "axios"; -import { - Button, - Code, - HStack, - InputGroup, - InputLeftElement, - Box, - Heading, - SimpleGrid, - VStack, - AlertDialog, - AlertDialogBody, - AlertDialogFooter, - AlertDialogHeader, - AlertDialogContent, - AlertDialogOverlay, -} from "@chakra-ui/react"; +import { Button, Code, HStack, InputGroup, InputLeftElement, Box, Heading, SimpleGrid, VStack } from "@chakra-ui/react"; import { Web3Context } from "../helpers/Web3Context"; import { CeramicClient } from "@ceramicnetwork/http-client"; import { ModelManager } from "@glazed/devtools"; @@ -44,40 +28,6 @@ import { IPFS_GATEWAY } from "../constants"; function Home() { const context = useContext(Web3Context); - const [isAlertOpen, setIsAlertOpen] = React.useState(false); - const onAlertClose = async () => { - const data = [ - { - chainId: "0x" + context.targetNetwork.chainId.toString(16), - chainName: context.targetNetwork.name, - nativeCurrency: context.targetNetwork.nativeCurrency, - rpcUrls: [context.targetNetwork.rpcUrl], - blockExplorerUrls: [context.targetNetwork.blockExplorer], - }, - ]; - try { - await ethereum.request({ - method: "wallet_switchEthereumChain", - params: [{ chainId: data[0].chainId }], - }); - setIsAlertOpen(false); - } catch (switchError) { - // This error code indicates that the chain has not been added to MetaMask. - if (switchError.code === 4902) { - try { - await ethereum.request({ - method: "wallet_addEthereumChain", - params: data, - }); - setIsAlertOpen(false); - } catch (addError) { - console.log(addError); - } - } - // handle other "switch" errors - } - }; - const cancelRef = React.useRef(); const [inputEmail, setInputEmail] = useState(""); const [recipients, setRecipients] = useState([]); const [developerProfiles, setDeveloperProfiles] = useState([]); @@ -94,7 +44,6 @@ function Home() { // The goal is to only have the API call fire when user stops typing ... // ... so that we aren't hitting our API rapidly. const debouncedSearchTerm = useDebounce(searchTerm, 500); - const [dRecruitContract, setDRecruitContract] = useState(); const [tokenContract, setTokenContract] = useState(); const [tokenMetadata, setTokenMetadata] = useState({ name: null, symbol: null }); const [store, setStore] = useState(); @@ -120,22 +69,34 @@ function Home() { ); const init = async () => { - if (context.injectedProvider && context.injectedProvider.getSigner()) { + if (context.localProvider) { try { - const signer = context.injectedProvider.getSigner(); - const contract = await loadDRecruitV1Contract(context.targetNetwork, signer); - const tokenAddress = await contract.token(); - const tokenContract = await loadTokenContract(tokenAddress, signer); - setDRecruitContract(contract); - setTokenContract(tokenContract); - const tokenName = await tokenContract.name(); - const tokenSymbol = await tokenContract.symbol(); - setTokenMetadata({ name: tokenName, symbol: tokenSymbol }); + const contract = context.readContracts.DRecruitV1; + if (!contract) { + console.log("Contract DRecruitV1 not loaded yet"); + return; + } + if (context.rightNetwork && context.injectedProvider && context.injectedProvider.getSigner()) { + const signer = context.injectedProvider.getSigner(); + const tokenAddress = await contract.token(); + const tokenContract = await loadTokenContract(tokenAddress, signer); + setTokenContract(tokenContract); + const tokenName = await tokenContract.name(); + const tokenSymbol = await tokenContract.symbol(); + setTokenMetadata({ name: tokenName, symbol: tokenSymbol }); + } const lastTokenId = await contract.tokenId(); + console.log("LLLLLlastTokenId: ", lastTokenId); const tokenIds = [...Array(parseInt(lastTokenId, 10)).keys()]; const tokenURIs = await Promise.all(tokenIds.map(async id => contract.uri(id))); + console.log("LLLLLtokenURIs: ", tokenURIs); const developersDID = [...new Set(tokenURIs.map(uri => getDidFromTokenURI(uri).did))]; + console.log("LLLLLdevelopersDID: ", developersDID); const core = ceramicCoreFactory(); + const basicProfile1 = await core.get("basicProfile", developersDID[0]); + console.log("LLLLLLbasicProfile1: ", basicProfile1); + const publicProfile1 = await core.get("publicProfile", developersDID[0]); + console.log("LLLLLLpublicProfile1: ", publicProfile1); const devProfiles = await Promise.all( developersDID.map(async did => ({ did, @@ -146,10 +107,10 @@ function Home() { privateProfile: await core.get("privateProfile", did), })), ); + console.log("devProfiles: ", devProfiles); setDeveloperProfiles(devProfiles); } catch (error) { console.log({ error }); - setIsAlertOpen(true); } } }; @@ -175,30 +136,11 @@ function Home() { useEffect(() => { init(); - }, [context.injectedProvider]); + }, [context.readContracts.DRecruitV1, context.injectedProvider]); return ( - - - - - Switch network - - - - To use this app you must switch to the {context.targetNetwork.name} network. - - - - - - - - - + setSearchTerm(e.target.value)} /> {isSearching &&
Searching ...
} Found developers: @@ -234,7 +176,6 @@ function Home() { date={`Birthdate: ${basicProfile.birthDate}`} primaryAction="Request contact information" secondaryAction="View contact information" - dRecruitContract={dRecruitContract} hasWebAccount={!!webAccounts} privateProfile={privateProfile} tokenContract={tokenContract} @@ -282,7 +223,6 @@ function Home() { date={`Birthdate: ${basicProfile.birthDate}`} primaryAction="Request contact information" secondaryAction="View contact information" - dRecruitContract={dRecruitContract} hasWebAccount={!!webAccounts} privateProfile={privateProfile} tokenContract={tokenContract}