Skip to content
This repository has been archived by the owner on Dec 17, 2021. It is now read-only.

Change network detection to Web3Context #98

Open
wants to merge 7 commits into
base: staging
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 13 additions & 11 deletions packages/react-app/components/cards/MediaCard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,10 @@ function MediaCard({
secondaryActionOnClick,
secondaryAction,
privateProfile,
dRecruitContract,
}) {
const [decryptedData, setDecryptedData] = useState();
const [canView, setCanView] = useState(false);
const context = useContext(Web3Context);
useEffect(() => {
let isValidRecipient = false;
(async () => {
Expand All @@ -71,7 +71,7 @@ function MediaCard({

const handleRequestPrivateProfileUnlock = async () => {
try {
const tx = await dRecruitContract.request(privateProfile.tokenId, {
const tx = await context.writeContracts.DRecruitV1.request(privateProfile.tokenId, {
value: ethers.utils.parseEther("0.01"),
});
toast({
Expand Down Expand Up @@ -192,15 +192,17 @@ function MediaCard({
</Stack>
</Box>
)}
<Button
disabled={canView}
w={"full"}
mt={8}
// TODO: get dev main address
onClick={handleRequestPrivateProfileUnlock}
>
{canView ? "✔️ Information already unlocked" : primaryAction}
</Button>
{context.rightNetwork && (
<Button
disabled={canView}
w={"full"}
mt={8}
// TODO: get dev main address
onClick={handleRequestPrivateProfileUnlock}
>
{canView ? "✔️ Information already unlocked" : primaryAction}
</Button>
)}
</Box>
</Box>
);
Expand Down
59 changes: 58 additions & 1 deletion packages/react-app/helpers/Web3Context.js
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -268,7 +269,7 @@ export function Web3Provider({ children, network = "localhost", DEBUG = false, N
const networkLocal = NETWORK(localChainId);
if (selectedChainId === 1337 && localChainId === 31337) {
networkDisplay = (
<div style={{ zIndex: 2, position: "absolute", right: 0, top: 60, padding: 16 }}>
<div style={{ zIndex: 10, position: "absolute", right: 0, top: 80, padding: 16 }}>
<Alert
message="⚠️ Wrong Network ID"
description={
Expand All @@ -283,6 +284,61 @@ export function Web3Provider({ children, network = "localhost", DEBUG = false, N
/>
</div>
);
} else {
networkDisplay = (
<div style={{ zIndex: 10, position: "absolute", right: 0, top: 80, padding: 16 }}>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use the Chakra alert dialog component instead: you can incorporate this here: https://github.com/moonshotcollective/drecruit/blob/staging/packages/react-app/pages/index.js#L48

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@QEDK I'm changing this to use the AlertDialog, but I think that it's not want we want. The AlertDialog is a modal, blocking the access to the site. We want just tell the user that the network selected is wrong but allow the user to see the site and the profiles. Please, let me know what you think.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@damianmarti This is intentional, but if you think it should be closable, it is trivial to implement it using <AlertDialogCloseButton /> however, it should be a blocking option which means that the user has to interact with the modal to make it close (so no implementation to automatically close should be added).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@QEDK I understand from my chats with @Cali93 that we want that the site can be viewed even if the user is not in the right network. If we want this, I think that we shouldn't use a modal alert dialog for this. I think we should use just a Chakra alert.

Copy link
Member

@QEDK QEDK Dec 1, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@damianmarti Once the alert dialog is dismissed, the UI will be accessible again (using local provider). Essentially for someone who does not want to switch networks the flow is same except there's no annoying alert left over, if they attempt to connect to the wrong network again, the alert dialog triggers again, so it's consistent and there's no UI remnant, that's the intent here. To clarify, I have no issue with adding a close button to the alert dialog, so that's good with me :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok! Thanks!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@QEDK I made this change and fixed the chainChanged callback (the network provider was not changed before). I tested it changing from the right network to a wrong one, back and forth, and it seem to be working fine now. The action "Request Contact Information" is shown or hidden when you go from the right network to a wrong one. Please review it and let me know if something is wrong.

<Alert
message="⚠️ Wrong Network"
description={
<div>
You have <b>{networkSelected && networkSelected.name}</b> selected and you need to be on{" "}
<Button
onClick={async () => {
const ethereum = window.ethereum;
const data = [
{
chainId: "0x" + targetNetwork.chainId.toString(16),
chainName: targetNetwork.name,
nativeCurrency: targetNetwork.nativeCurrency,
rpcUrls: [targetNetwork.rpcUrl],
blockExplorerUrls: [targetNetwork.blockExplorer],
},
];
console.log("data", data);

let switchTx;
// https://docs.metamask.io/guide/rpc-api.html#other-rpc-methods
try {
switchTx = await ethereum.request({
method: "wallet_switchEthereumChain",
params: [{ chainId: data[0].chainId }],
});
} catch (switchError) {
// not checking specific error code, because maybe we're not using MetaMask
try {
switchTx = await ethereum.request({
method: "wallet_addEthereumChain",
params: data,
});
} catch (addError) {
// handle "add" error
}
}

if (switchTx) {
console.log(switchTx);
}
}}
>
<b>{networkLocal && networkLocal.name}</b>
</Button>
</div>
}
type="error"
closable={false}
/>
</div>
);
}
} else {
networkDisplay = (
Expand Down Expand Up @@ -410,6 +466,7 @@ export function Web3Provider({ children, network = "localhost", DEBUG = false, N
loadWeb3Modal,
logoutOfWeb3Modal,
contractConfig,
rightNetwork,
};

return <Web3Context.Provider value={providerProps}>{children}</Web3Context.Provider>;
Expand Down
84 changes: 5 additions & 79 deletions packages/react-app/pages/index.js
Original file line number Diff line number Diff line change
@@ -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";
Expand All @@ -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([]);
Expand All @@ -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 [store, setStore] = useState();
const [prevNote, setPrevNote] = useState("");

Expand All @@ -118,11 +67,9 @@ 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);
setDRecruitContract(contract);
const contract = context.readContracts.DRecruitV1;
const lastTokenId = await contract.tokenId();
const tokenIds = [...Array(parseInt(lastTokenId, 10)).keys()];
const tokenURIs = await Promise.all(tokenIds.map(async id => contract.uri(id)));
Expand All @@ -140,7 +87,7 @@ function Home() {
);
setDeveloperProfiles(devProfiles);
} catch (error) {
setIsAlertOpen(true);
console.log(error);
}
}
};
Expand Down Expand Up @@ -170,26 +117,7 @@ function Home() {

return (
<Layout>
<AlertDialog isOpen={isAlertOpen} leastDestructiveRef={cancelRef}>
<AlertDialogOverlay>
<AlertDialogContent>
<AlertDialogHeader fontSize="lg" fontWeight="bold">
Switch network
</AlertDialogHeader>

<AlertDialogBody>
To use this app you must switch to the {context.targetNetwork.name} network.
</AlertDialogBody>

<AlertDialogFooter>
<Button ref={cancelRef} onClick={onAlertClose} colorScheme="blue">
Switch
</Button>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialogOverlay>
</AlertDialog>
<HomeActions contract={dRecruitContract} mySelf={context.self} />
<HomeActions contract={context.writeContracts.DRecruitV1} mySelf={context.self} />
<Input type="search" placeholder="Search" onChange={e => setSearchTerm(e.target.value)} />
{isSearching && <div>Searching ...</div>}
<Heading>Found developers:</Heading>
Expand Down Expand Up @@ -225,7 +153,6 @@ function Home() {
date={`Birthdate: ${basicProfile.birthDate}`}
primaryAction="Request contact information"
secondaryAction="View contact information"
dRecruitContract={dRecruitContract}
hasWebAccount={!!webAccounts}
privateProfile={privateProfile}
/>
Expand Down Expand Up @@ -271,7 +198,6 @@ function Home() {
date={`Birthdate: ${basicProfile.birthDate}`}
primaryAction="Request contact information"
secondaryAction="View contact information"
dRecruitContract={dRecruitContract}
hasWebAccount={!!webAccounts}
privateProfile={privateProfile}
/>
Expand Down