Created
November 9, 2019 00:53
-
-
Save PaulRBerg/7e9901caa11a34f8ece59c368f18d8bb to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { useCallback, useEffect, useRef, useState } from "react"; | |
import Jazzicon from "jazzicon"; | |
import styled, { useTheme } from "styled-components"; | |
import typy from "typy"; | |
import { Activity, User } from "react-feather"; | |
import { darken } from "polished"; | |
import { ethers } from "ethers"; | |
import { shortenAddress } from "@sablier/utils"; | |
import { useTranslation } from "react-i18next"; | |
import { Connectors, useWeb3Context } from "web3-react"; | |
import Spinner from "../Spinner"; | |
import WalletModal from "../../modals/WalletModal"; | |
import { useENSName } from "../../hooks"; | |
import { useModalManager } from "../../contexts/Application"; | |
const { Connector } = Connectors; | |
const Web3StatusWrapper = styled.div` | |
${props => props.theme.flexRowNoWrap}; | |
align-items: center; | |
border-bottom-right-radius: 1.25rem; | |
border-top-right-radius: 1.25rem; | |
flex-grow: 1; | |
justify-content: center; | |
padding: 0.5rem; | |
user-select: none; | |
`; | |
const Label = styled.span` | |
margin-left: 0.25rem; | |
margin-right: 0.25rem; | |
overflow: hidden; | |
text-overflow: ellipsis; | |
white-space: nowrap; | |
`; | |
const Web3StatusErrorWrapper = styled(Web3StatusWrapper)` | |
background-color: ${props => props.theme.pastelRed}; | |
border: 1px solid ${props => props.theme.pastelRed}; | |
color: ${props => props.theme.white}; | |
font-weight: 500; | |
&:hover, | |
&:focus { | |
background-color: ${props => darken(0.1, props.theme.pastelRed)}; | |
} | |
`; | |
const NetworkIcon = styled(Activity)` | |
height: 1rem; | |
margin-left: 0.25rem; | |
margin-right: 0.5rem; | |
width: 1rem; | |
`; | |
const Web3StatusConnect = styled(Web3StatusWrapper)` | |
font-weight: 500; | |
`; | |
const UserIcon = styled(User)` | |
height: 0.875rem; | |
width: 0.875rem; | |
`; | |
const Web3StatusConnected = styled(Web3StatusWrapper)` | |
background-color: ${props => props.theme.transparent}; | |
color: ${props => props.theme.darkGunmetalBlack}; | |
font-weight: 400; | |
`; | |
const IdenticonWrapper = styled.div` | |
background-color: ${props => props.theme.silverSandGray}; | |
border-radius: 1.125rem; | |
height: 1rem; | |
width: 1rem; | |
`; | |
export default function Web3Status() { | |
const theme = useTheme(); | |
const { account, active, connectorName, setConnector } = useWeb3Context(); | |
const { toggleWalletModal } = useModalManager(); | |
const { t } = useTranslation(); | |
const ENSName = useENSName(account); | |
const identiconRef = useRef(); | |
const [walletError, setWalletError] = useState(undefined); | |
async function onClick() { | |
if (walletError) { | |
toggleWalletModal(); | |
} else if (connectorName === "Network" && (window.ethereum || window.web3)) { | |
try { | |
await setConnector("Injected", { suppressAndThrowErrors: true }); | |
} catch (error) { | |
if (error.code === Connector.errorCodes.UNSUPPORTED_NETWORK) { | |
setWalletError(error); | |
} | |
} | |
} else { | |
toggleWalletModal(); | |
} | |
} | |
const tryToActivateInjected = useCallback(async () => { | |
const library = new ethers.providers.Web3Provider(window.ethereum); | |
// If calling enable won't pop an approve modal, then try to activate injected... | |
try { | |
const accounts = await library.listAccounts(); | |
if (accounts.length >= 1) { | |
await setConnector("Injected", { suppressAndThrowErrors: true }); | |
setWalletError(undefined); | |
} | |
} catch (error) { | |
// ...and if the error is that they're on the wrong network, display it, otherwise eat it | |
if (error.code === Connector.errorCodes.UNSUPPORTED_NETWORK) { | |
setWalletError(error); | |
} | |
} | |
}, [setConnector]); | |
// Janky logic to detect log{ins,outs}... | |
useEffect(() => { | |
const { ethereum } = window; | |
if (typy(ethereum).isFalsy) { | |
return undefined; | |
} | |
// Poll to check the accounts array, and if it's ever 0 i.e. the user logged out, update the connector | |
if (connectorName === "Injected") { | |
const accountPoll = setInterval(async () => { | |
const library = new ethers.providers.Web3Provider(ethereum); | |
try { | |
const accounts = await library.listAccounts(); | |
if (accounts.length === 0) { | |
setConnector("Network"); | |
} | |
// eslint-disable-next-line no-empty | |
} catch {} | |
}, 750); | |
return () => { | |
clearInterval(accountPoll); | |
}; | |
} else if ( | |
/* If the network or the account changes, check whether this has been caused by a new injected connector */ | |
connectorName === "Network" && | |
typy(ethereum, "on").isTruthy && | |
typy(ethereum, "removeListener").isTruthy | |
) { | |
ethereum.on("networkChanged", tryToActivateInjected); | |
ethereum.on("accountsChanged", tryToActivateInjected); | |
return () => { | |
if (typy(ethereum, "removeListener").isTruthy) { | |
ethereum.removeListener("networkChanged", tryToActivateInjected); | |
ethereum.removeListener("accountsChanged", tryToActivateInjected); | |
} | |
}; | |
} | |
return undefined; | |
}, [connectorName, setConnector, tryToActivateInjected]); | |
/* Generate the Jazzicon only when the account changes */ | |
useEffect(() => { | |
if (identiconRef.current) { | |
identiconRef.current.innerHTML = ""; | |
if (account) { | |
identiconRef.current.appendChild(Jazzicon(16, parseInt(account.slice(2, 10), 16))); | |
} | |
} | |
}, [account, walletError]); | |
function renderWebStatus() { | |
if (typy(walletError).isTruthy) { | |
/* This is ok because we're guaranteed that the error is a wrong network error */ | |
return ( | |
<Web3StatusErrorWrapper onClick={onClick}> | |
<NetworkIcon color={theme.white} /> | |
<Label> | |
{t("wrong")} {t("network")} | |
</Label> | |
</Web3StatusErrorWrapper> | |
); | |
} else if (typy(account).isFalsy) { | |
return ( | |
<Web3StatusConnect onClick={onClick}> | |
<UserIcon color={theme.darkGunmetalBlack} /> | |
<Label>{t("signIn")}</Label> | |
</Web3StatusConnect> | |
); | |
} else { | |
return ( | |
<Web3StatusConnected onClick={onClick}> | |
<IdenticonWrapper ref={identiconRef} /> | |
<Label>{ENSName || shortenAddress(account)}</Label> | |
</Web3StatusConnected> | |
); | |
} | |
} | |
if (active) { | |
return ( | |
<> | |
{renderWebStatus()} | |
<WalletModal error={walletError} /> | |
</> | |
); | |
} else { | |
return ( | |
<Web3StatusWrapper> | |
<Spinner color={theme.darkGunmetalBlack} delay={400} size={16} /> | |
</Web3StatusWrapper> | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment