diff --git a/package.json b/package.json index ce201c7ad..432c27e7c 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,7 @@ "dependencies": { "@apollo/client": "^3.7.0", "@arbitrum/sdk": "3.0.0-beta.12", + "@coinbase/wallet-sdk": "^3.3.0", "@popperjs/core": "^2.9.3", "@reach/dialog": "^0.17.0", "@reach/portal": "^0.17.0", @@ -46,12 +47,17 @@ "@types/react-helmet": "^6.1.5", "@uniswap/smart-order-router": "^2.9.3", "@uniswap/token-lists": "^1.0.0-beta.27", + "@walletconnect/ethereum-provider": "^1.7.5", + "@web3-react/coinbase-wallet": "8.0.34-beta.0", + "@web3-react/core": "8.0.35-beta.0", + "@web3-react/eip1193": "8.0.26-beta.0", + "@web3-react/empty": "8.0.20-beta.0", + "@web3-react/metamask": "8.0.28-beta.0", + "@web3-react/network": "8.0.27-beta.0", + "@web3-react/types": "8.0.20-beta.0", + "@web3-react/url": "8.0.25-beta.0", + "@web3-react/walletconnect": "8.0.36-beta.0", "@uniswap/v3-periphery": "1.4.1", - "@web3-react/core": "^6.1.9", - "@web3-react/injected-connector": "^6.0.7", - "@web3-react/network-connector": "^6.2.9", - "@web3-react/walletconnect-connector": "^6.2.13", - "@web3-react/walletlink-connector": "^6.2.14", "ajv": "^8.11.0", "ajv-formats": "^2.1.1", "aos": "^2.3.4", diff --git a/src/assets/images/coinbase.svg b/src/assets/images/wallets/coinbase.svg similarity index 100% rename from src/assets/images/coinbase.svg rename to src/assets/images/wallets/coinbase.svg diff --git a/src/assets/images/metamask.png b/src/assets/images/wallets/metamask.png similarity index 100% rename from src/assets/images/metamask.png rename to src/assets/images/wallets/metamask.png diff --git a/src/assets/images/wallet-connect.svg b/src/assets/images/wallets/wallet-connect.svg similarity index 100% rename from src/assets/images/wallet-connect.svg rename to src/assets/images/wallets/wallet-connect.svg diff --git a/src/components/AddTokenButton/AddTokenButton.tsx b/src/components/AddTokenButton/AddTokenButton.tsx index e672cb279..a37615139 100644 --- a/src/components/AddTokenButton/AddTokenButton.tsx +++ b/src/components/AddTokenButton/AddTokenButton.tsx @@ -3,11 +3,11 @@ import { SWPR } from '@swapr/sdk' import { useCallback, useMemo } from 'react' import swprLogo from '../../assets/images/swpr-logo.png' -import { useActiveWeb3React } from '../../hooks' +import { useWeb3ReactCore } from '../../hooks/useWeb3ReactCore' import { AddSWPRToMetamaskButton } from '../Button' export const AddTokenButton = ({ active }: { active?: boolean }) => { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const swpr = useMemo(() => (chainId ? SWPR[chainId] : undefined), [chainId]) diff --git a/src/components/ButtonConnect/index.tsx b/src/components/ButtonConnect/index.tsx index 8553bb97e..6c1d23221 100644 --- a/src/components/ButtonConnect/index.tsx +++ b/src/components/ButtonConnect/index.tsx @@ -1,4 +1,4 @@ -import { useUnsupportedChainIdError } from '../../hooks' +import { useWeb3ReactCore } from '../../hooks/useWeb3ReactCore' import { ApplicationModal } from '../../state/application/actions' import { useModalOpen, @@ -8,11 +8,11 @@ import { import { ButtonPrimary } from '../Button' export const ButtonConnect = () => { + const { isActiveChainSupported } = useWeb3ReactCore() const toggleWalletSwitcherPopover = useWalletSwitcherPopoverToggle() const toggleNetworkSwitcherPopover = useNetworkSwitcherPopoverToggle() const networkSwitcherPopoverOpen = useModalOpen(ApplicationModal.NETWORK_SWITCHER) - const unsupportedChainIdError = useUnsupportedChainIdError() - const isSwitchNetwork = networkSwitcherPopoverOpen || unsupportedChainIdError + const isSwitchNetwork = networkSwitcherPopoverOpen || !isActiveChainSupported return ( { if (!account) onConnectWallet() - else if (!correctNetwork && connector instanceof InjectedConnector) onSwitchToArbitrum() + else if (!correctNetwork && (connector instanceof MetaMask || connector instanceof CoinbaseWallet)) + onSwitchToArbitrum() else if (isOldSwaprLp) { const anchor = document.createElement('a') Object.assign(anchor, { diff --git a/src/components/Claim/ConvertFlow/index.tsx b/src/components/Claim/ConvertFlow/index.tsx index b8d48e9ff..76f7953a5 100644 --- a/src/components/Claim/ConvertFlow/index.tsx +++ b/src/components/Claim/ConvertFlow/index.tsx @@ -3,9 +3,9 @@ import { SWPR_CONVERTER_ADDRESS, TokenAmount } from '@swapr/sdk' import { useCallback } from 'react' import styled from 'styled-components' -import { useActiveWeb3React } from '../../../hooks' import { useConvertSwprCallback } from '../../../hooks/swpr/useConvertSwprCallback' import { ApprovalState, useApproveCallback } from '../../../hooks/useApproveCallback' +import { useWeb3ReactCore } from '../../../hooks/useWeb3ReactCore' import { useTransactionAdder } from '../../../state/transactions/hooks' import { ButtonPrimary } from '../../Button' import { AutoColumn } from '../../Column' @@ -23,7 +23,7 @@ interface ConvertFlowProps { } export function ConvertFlow({ oldSwprBalance, disabled, onError }: ConvertFlowProps) { - const { chainId, account } = useActiveWeb3React() + const { chainId, account } = useWeb3ReactCore() const addTransaction = useTransactionAdder() //chainId will be one of 1,4,100,137,42161,421611 or undefined const spender = SWPR_CONVERTER_ADDRESS[chainId!] diff --git a/src/components/CurrencyInputPanel/CurrencyInputPanel.component.tsx b/src/components/CurrencyInputPanel/CurrencyInputPanel.component.tsx index fce101e42..804f676e6 100644 --- a/src/components/CurrencyInputPanel/CurrencyInputPanel.component.tsx +++ b/src/components/CurrencyInputPanel/CurrencyInputPanel.component.tsx @@ -2,7 +2,7 @@ import { Currency } from '@swapr/sdk' import { useCallback, useEffect, useMemo, useState } from 'react' -import { useActiveWeb3React } from '../../hooks' +import { useWeb3ReactCore } from '../../hooks/useWeb3ReactCore' import { useCurrencyBalance } from '../../state/wallet/hooks' import { TYPE } from '../../theme' import { normalizeInputValue } from '../../utils' @@ -56,7 +56,7 @@ export const CurrencyInputPanelComponent = ({ const [isOpen, setIsOpen] = useState(false) const [focused, setFocused] = useState(false) const [localValue, setLocalValue] = useState(value) - const { account } = useActiveWeb3React() + const { account } = useWeb3ReactCore() const [isMaxAmount, setIsMaxAmount] = useState(false) const selectedCurrencyBalance = useCurrencyBalance(account ?? undefined, currency ?? undefined) diff --git a/src/components/CurrencyInputPanel/CurrencyUserBalance.tsx b/src/components/CurrencyInputPanel/CurrencyUserBalance.tsx index eed8d1c5e..9fd95cd9e 100644 --- a/src/components/CurrencyInputPanel/CurrencyUserBalance.tsx +++ b/src/components/CurrencyInputPanel/CurrencyUserBalance.tsx @@ -3,7 +3,7 @@ import { _10000 } from '@swapr/sdk' import { Trans } from 'react-i18next' import { useTheme } from 'styled-components' -import { useActiveWeb3React } from '../../hooks' +import { useWeb3ReactCore } from '../../hooks/useWeb3ReactCore' import { TYPE } from '../../theme' import { limitNumberOfDecimalPlaces } from '../../utils/prices' import { UnderlinedSmallText, UppercaseHelper } from './CurrencyInputPanel.styles' @@ -18,7 +18,7 @@ export const CurrencyUserBalance = ({ customBalanceText, onMax, }: CurrencyUserBalanceProps) => { - const { account } = useActiveWeb3React() + const { account } = useWeb3ReactCore() const theme = useTheme() if (!account) return null diff --git a/src/components/CurrencyLogo/CurrencyLogo.container.tsx b/src/components/CurrencyLogo/CurrencyLogo.container.tsx index ef3f44dcd..427ceb8a5 100644 --- a/src/components/CurrencyLogo/CurrencyLogo.container.tsx +++ b/src/components/CurrencyLogo/CurrencyLogo.container.tsx @@ -5,8 +5,8 @@ import { useMemo } from 'react' import carrotListLogoUrl from '../../assets/images/carrot.png' import DXDLogo from '../../assets/images/dxd.svg' import SWPRLogo from '../../assets/images/swpr-logo.png' -import { useActiveWeb3React } from '../../hooks' import useHttpLocations from '../../hooks/useHttpLocations' +import { useWeb3ReactCore } from '../../hooks/useWeb3ReactCore' import { useBridgeTokenInfo } from '../../services/EcoBridge/EcoBridge.hooks' import { useTokenInfoFromActiveListOnCurrentChain } from '../../state/lists/hooks' import { WrappedTokenInfo } from '../../state/lists/wrapped-token-info' @@ -20,7 +20,7 @@ export const CurrencyLogo = ({ currencyWrapperSource = CurrencyWrapperSource.SWAP, ...componentProps }: CurrencyLogoContainerProps) => { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const selectedChainId = chainIdOverride || chainId const swapWrappedTokenInfo = useTokenInfoFromActiveListOnCurrentChain(currency) diff --git a/src/components/Header/Balances.tsx b/src/components/Header/Balances.tsx index a864ef274..5145aa7c2 100644 --- a/src/components/Header/Balances.tsx +++ b/src/components/Header/Balances.tsx @@ -4,8 +4,8 @@ import { useMemo } from 'react' import Skeleton from 'react-loading-skeleton' import styled from 'styled-components' -import { useActiveWeb3React, useUnsupportedChainIdError } from '../../hooks' import { useNativeCurrency } from '../../hooks/useNativeCurrency' +import { useWeb3ReactCore } from '../../hooks/useWeb3ReactCore' import { useToggleShowClaimPopup } from '../../state/application/hooks' import { useNativeCurrencyBalance, useTokenBalance } from '../../state/wallet/hooks' import { Amount } from './styled' @@ -55,8 +55,7 @@ const StyledBalanacesWrapper = styled.div( export function Balances() { const toggleClaimPopup = useToggleShowClaimPopup() const nativeCurrency = useNativeCurrency() - const isUnsupportedChainIdError = useUnsupportedChainIdError() - const { account, chainId } = useActiveWeb3React() + const { account, chainId } = useWeb3ReactCore() const userNativeCurrencyBalance = useNativeCurrencyBalance() const accountOrUndefined = useMemo(() => account || undefined, [account]) const newSwpr = useMemo(() => (chainId ? SWPR[chainId] : undefined), [chainId]) @@ -71,30 +70,26 @@ export function Balances() { return ( - {!isUnsupportedChainIdError && ( - <> - - {userNativeCurrencyBalance ? ( - `${ - userNativeCurrencyBalance.greaterThan(new Fraction('10000')) - ? numberFormater.format(parseInt(userNativeCurrencyBalance.toFixed(2))) - : userNativeCurrencyBalance.toFixed(3) - } ${nativeCurrency.symbol}` - ) : ( - - )} - - {!networkWithoutSWPR && ( - - {newSwprBalance - ? newSwprBalance.greaterThan(new Fraction('10000')) - ? numberFormater.format(parseInt(newSwprBalance.toFixed(3))) - : newSwprBalance.toFixed(3) - : '0.000'}{' '} - SWPR - - )} - + + {userNativeCurrencyBalance ? ( + `${ + userNativeCurrencyBalance.greaterThan(new Fraction('10000')) + ? numberFormater.format(parseInt(userNativeCurrencyBalance.toFixed(2))) + : userNativeCurrencyBalance.toFixed(3) + } ${nativeCurrency.symbol}` + ) : ( + + )} + + {!networkWithoutSWPR && ( + + {newSwprBalance + ? newSwprBalance.greaterThan(new Fraction('10000')) + ? numberFormater.format(parseInt(newSwprBalance.toFixed(3))) + : newSwprBalance.toFixed(3) + : '0.000'}{' '} + SWPR + )} ) diff --git a/src/components/Header/Polling.tsx b/src/components/Header/Polling.tsx index 92f102fec..c9d0a4453 100644 --- a/src/components/Header/Polling.tsx +++ b/src/components/Header/Polling.tsx @@ -1,7 +1,7 @@ import { useEffect, useState } from 'react' import styled, { keyframes } from 'styled-components' -import { useActiveWeb3React } from '../../hooks' +import { useWeb3ReactCore } from '../../hooks/useWeb3ReactCore' import { useBlockNumber } from '../../state/application/hooks' import { ExternalLink, TYPE } from '../../theme' import { getExplorerLink } from '../../utils' @@ -63,7 +63,7 @@ const Spinner = styled.div` ` export default function Polling() { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const blockNumber = useBlockNumber() diff --git a/src/components/Header/index.tsx b/src/components/Header/index.tsx index 5dd0f5027..d3372dd76 100644 --- a/src/components/Header/index.tsx +++ b/src/components/Header/index.tsx @@ -8,10 +8,10 @@ import { Flex, Text } from 'rebass' import styled from 'styled-components' import { ReactComponent as GasInfoSvg } from '../../assets/images/gas-info.svg' -import { useActiveWeb3React, useUnsupportedChainIdError } from '../../hooks' import { useSwaprSinglelSidedStakeCampaigns } from '../../hooks/singleSidedStakeCampaigns/useSwaprSingleSidedStakeCampaigns' import { useGasInfo } from '../../hooks/useGasInfo' import { useLiquidityMiningCampaignPosition } from '../../hooks/useLiquidityMiningCampaignPosition' +import { useWeb3ReactCore } from '../../hooks/useWeb3ReactCore' import { ApplicationModal } from '../../state/application/actions' import { useModalOpen, useToggleShowClaimPopup, useToggleShowExpeditionsPopup } from '../../state/application/hooks' import { useDarkModeManager } from '../../state/user/hooks' @@ -198,7 +198,7 @@ const StyledChevron = styled(ChevronUp)<{ open: boolean }>` ` function Header() { - const { account, chainId } = useActiveWeb3React() + const { account, chainId, isActiveChainSupported } = useWeb3ReactCore() const { t } = useTranslation('common') const [isGasInfoOpen, setIsGasInfoOpen] = useState(false) @@ -213,8 +213,6 @@ function Header() { const newSwpr = useMemo(() => (chainId ? SWPR[chainId] : undefined), [chainId]) const newSwprBalance = useTokenBalance(accountOrUndefined, newSwpr) const isUnsupportedNetworkModal = useModalOpen(ApplicationModal.UNSUPPORTED_NETWORK) - const isUnsupportedChainIdError = useUnsupportedChainIdError() - const networkWithoutSWPR = !newSwpr const onScrollHander = () => { @@ -296,7 +294,7 @@ function Header() { - {account && ( + {account && isActiveChainSupported && ( <> ✨ Expeditions @@ -305,14 +303,14 @@ function Header() { )} - {isUnsupportedChainIdError && ( + {!isActiveChainSupported && ( {'UNSUPPORTED NETWORK'} )} {gas.normal !== 0.0 && ( - setIsGasInfoOpen(!isGasInfoOpen)} hide={!account || isUnsupportedChainIdError}> + setIsGasInfoOpen(!isGasInfoOpen)} hide={!account || !isActiveChainSupported}> {gas.normal} diff --git a/src/components/Header/swpr-info/index.tsx b/src/components/Header/swpr-info/index.tsx index 6d4b93183..249df132b 100644 --- a/src/components/Header/swpr-info/index.tsx +++ b/src/components/Header/swpr-info/index.tsx @@ -3,7 +3,7 @@ import { TokenAmount } from '@swapr/sdk' import Skeleton from 'react-loading-skeleton' import styled from 'styled-components' -import { useActiveWeb3React } from '../../../hooks' +import { useWeb3ReactCore } from '../../../hooks/useWeb3ReactCore' import { HeaderButton } from '../HeaderButton' import { Amount } from '../styled' @@ -24,10 +24,9 @@ interface SwprInfoProps { } export function SwprInfo({ onToggleClaimPopup, newSwprBalance, hasActiveCampaigns }: SwprInfoProps) { - const { account } = useActiveWeb3React() - + const { account, isActiveChainSupported } = useWeb3ReactCore() return ( - + {!account ? ( '0.000' diff --git a/src/components/LiquidityMining/Create/Steps/PairAndReward/AssetSelector/index.tsx b/src/components/LiquidityMining/Create/Steps/PairAndReward/AssetSelector/index.tsx index 669f98e8c..c8d094c15 100644 --- a/src/components/LiquidityMining/Create/Steps/PairAndReward/AssetSelector/index.tsx +++ b/src/components/LiquidityMining/Create/Steps/PairAndReward/AssetSelector/index.tsx @@ -4,9 +4,9 @@ import { useEffect, useMemo, useState } from 'react' import { Box, Flex } from 'rebass' import styled from 'styled-components' -import { useActiveWeb3React } from '../../../../../../hooks' import { ApprovalState, useApproveCallback } from '../../../../../../hooks/useApproveCallback' import { useStakingRewardsDistributionFactoryContract } from '../../../../../../hooks/useContract' +import { useWeb3ReactCore } from '../../../../../../hooks/useWeb3ReactCore' import { Actions, ActionType, CampaignType } from '../../../../../../pages/LiquidityMining/Create' import { useTokenBalance } from '../../../../../../state/wallet/hooks' import { CloseIcon, TYPE } from '../../../../../../theme' @@ -82,7 +82,7 @@ export default function AssetSelector({ rawAmount, setRewardsObject, }: AssetSelectorProps) { - const { account } = useActiveWeb3React() + const { account } = useWeb3ReactCore() const userBalance = useTokenBalance(account || undefined, currency0 !== null ? currency0 : undefined) const [assetTitle, setAssetTitle] = useState(null) diff --git a/src/components/LiquidityMining/Create/Steps/PreviewAndCreate/index.tsx b/src/components/LiquidityMining/Create/Steps/PreviewAndCreate/index.tsx index 24e517ab7..683dac97c 100644 --- a/src/components/LiquidityMining/Create/Steps/PreviewAndCreate/index.tsx +++ b/src/components/LiquidityMining/Create/Steps/PreviewAndCreate/index.tsx @@ -11,8 +11,8 @@ import { useEffect, useState } from 'react' import { Box, Flex } from 'rebass' import styled from 'styled-components' -import { useActiveWeb3React } from '../../../../../hooks' import { useNativeCurrencyUSDPrice } from '../../../../../hooks/useNativeCurrencyUSDPrice' +import { useWeb3ReactCore } from '../../../../../hooks/useWeb3ReactCore' import { getStakedAmountUSD } from '../../../../../utils/liquidityMining' import { ButtonPrimary } from '../../../../Button' import { CampaignCard } from '../../../../Pool/PairsList/CampaignCard' @@ -76,7 +76,7 @@ export default function PreviewAndCreate({ setSimulatedPrice, simulatedPrice, }: PreviewProps) { - const { account } = useActiveWeb3React() + const { account } = useWeb3ReactCore() const [areButtonsDisabled, setAreButtonsDisabled] = useState(false) const { loading: loadingNativeCurrencyUsdPrice, nativeCurrencyUSDPrice } = useNativeCurrencyUSDPrice() useEffect(() => { diff --git a/src/components/ModalViews/index.tsx b/src/components/ModalViews/index.tsx index feb99da72..8ee8c3530 100644 --- a/src/components/ModalViews/index.tsx +++ b/src/components/ModalViews/index.tsx @@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next' import styled, { useTheme } from 'styled-components' import Circle from '../../assets/images/blue-loader.svg' -import { useActiveWeb3React } from '../../hooks' +import { useWeb3ReactCore } from '../../hooks/useWeb3ReactCore' import { CloseIcon, CustomLightSpinner, TYPE } from '../../theme' import { ExternalLink } from '../../theme/components' import { getExplorerLink } from '../../utils' @@ -47,7 +47,7 @@ export function SubmittedView({ hash: string | undefined }) { const theme = useTheme() - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const { t } = useTranslation('common') return ( diff --git a/src/components/NetworkSwitcher/NetworkSwitcher.component.tsx b/src/components/NetworkSwitcher/NetworkSwitcher.component.tsx index 1c037f504..587b4102a 100644 --- a/src/components/NetworkSwitcher/NetworkSwitcher.component.tsx +++ b/src/components/NetworkSwitcher/NetworkSwitcher.component.tsx @@ -1,7 +1,7 @@ import { useRef } from 'react' -import { useActiveWeb3React } from '../../hooks' import { useOnClickOutside } from '../../hooks/useOnClickOutside' +import { useWeb3ReactCore } from '../../hooks/useWeb3ReactCore' import { ApplicationModal } from '../../state/application/actions' import { useModalOpen, useWalletSwitcherPopoverToggle } from '../../state/application/hooks' import { ChangeWalletButton, NetworkTagRow, OptionGrid, StyledPopover } from './NetworkSwitcher.styles' @@ -18,7 +18,7 @@ export const NetworkSwitcher = ({ showWalletConnector = true, }: NetworkSwitcherProps) => { const popoverRef = useRef(null) - const { account, chainId } = useActiveWeb3React() + const { account, chainId } = useWeb3ReactCore() const ethereumOptionPopoverOpen = useModalOpen(ApplicationModal.ETHEREUM_OPTION) const toggleWalletSwitcherPopover = useWalletSwitcherPopoverToggle() diff --git a/src/components/NetworkSwitcherPopover/index.tsx b/src/components/NetworkSwitcherPopover/index.tsx index d61f8ba84..e437166d2 100644 --- a/src/components/NetworkSwitcherPopover/index.tsx +++ b/src/components/NetworkSwitcherPopover/index.tsx @@ -3,8 +3,9 @@ import { ChainId } from '@swapr/sdk' import { Placement } from '@popperjs/core' import React, { ReactNode } from 'react' -import { useActiveWeb3React, useUnsupportedChainIdError } from '../../hooks' +import { isChainSupportedByConnector } from '../../connectors/utils' import { useNetworkSwitch } from '../../hooks/useNetworkSwitch' +import { useWeb3ReactCore } from '../../hooks/useWeb3ReactCore' import { ApplicationModal } from '../../state/application/actions' import { useCloseModals, useModalOpen } from '../../state/application/hooks' import { createNetworksList } from '../../utils/networksList' @@ -18,19 +19,13 @@ interface NetworkSwitcherPopoverProps { export default function NetworkSwitcherPopover({ children, modal, placement }: NetworkSwitcherPopoverProps) { const closeModals = useCloseModals() - const { connector, chainId: activeChainId, account } = useActiveWeb3React() + const { connector, chainId: activeChainId, account } = useWeb3ReactCore() const networkSwitcherPopoverOpen = useModalOpen(modal) - const unsupportedChainIdError = useUnsupportedChainIdError() - const { selectNetwork } = useNetworkSwitch({ - onSelectNetworkCallback: closeModals, - }) + const isNetworkDisabled = (chainId: ChainId) => + activeChainId === chainId || !isChainSupportedByConnector(connector, chainId) - const isNetworkDisabled = (chainId: ChainId) => { - return ( - connector?.supportedChainIds?.indexOf(chainId) === -1 || (!unsupportedChainIdError && activeChainId === chainId) - ) - } + const { selectNetwork } = useNetworkSwitch() const networkList = createNetworksList({ networkOptionsPreset, diff --git a/src/components/NetworkUnsupportedPopover/index.tsx b/src/components/NetworkUnsupportedPopover/index.tsx index ead2126d9..c21bf6c87 100644 --- a/src/components/NetworkUnsupportedPopover/index.tsx +++ b/src/components/NetworkUnsupportedPopover/index.tsx @@ -17,7 +17,6 @@ interface UnsupportedNetworkPopoverProps { export function UnsupportedNetworkPopover({ children, show }: UnsupportedNetworkPopoverProps) { const closeModals = useCloseModals() const popoverRef = useRef(null) - useOnClickOutside(popoverRef, show ? closeModals : undefined) return ( diff --git a/src/components/NetworkWarningModal/index.tsx b/src/components/NetworkWarningModal/index.tsx index f83193fa5..9f58b1bc7 100644 --- a/src/components/NetworkWarningModal/index.tsx +++ b/src/components/NetworkWarningModal/index.tsx @@ -1,16 +1,14 @@ import { useCallback, useEffect, useState } from 'react' import { isMobile } from 'react-device-detect' import { AlertTriangle } from 'react-feather' -import { useLocation, useNavigate } from 'react-router-dom' import styled from 'styled-components' import { NETWORK_DETAIL } from '../../constants' -import { useActiveWeb3React } from '../../hooks' -import { unavailableRedirect } from '../../hooks/useNetworkSwitch' +import { useNetworkSwitch } from '../../hooks/useNetworkSwitch' import { useTargetedChainIdFromUrl } from '../../hooks/useTargetedChainIdFromUrl' +import { useWeb3ReactCore } from '../../hooks/useWeb3ReactCore' import { useIsSwitchingToCorrectChain } from '../../state/multi-chain-links/hooks' import { TYPE } from '../../theme' -import { switchOrAddNetwork } from '../../utils' import { ButtonPrimary } from '../Button' import { AutoColumn } from '../Column' import Modal from '../Modal' @@ -34,14 +32,12 @@ const StyledWarningIcon = styled(AlertTriangle)` ` export default function NetworkWarningModal() { - const { chainId, account } = useActiveWeb3React() + const { chainId, account } = useWeb3ReactCore() const urlLoadedChainId = useTargetedChainIdFromUrl() const switchingToCorrectChain = useIsSwitchingToCorrectChain() - const navigate = useNavigate() - const { pathname } = useLocation() + const { selectNetwork } = useNetworkSwitch() const [open, setOpen] = useState(false) - useEffect(() => { setOpen(!!account && !!chainId && !!urlLoadedChainId && !!switchingToCorrectChain) }, [account, chainId, switchingToCorrectChain, urlLoadedChainId]) @@ -50,10 +46,8 @@ export default function NetworkWarningModal() { const handleAddClick = useCallback(async () => { if (!urlLoadedChainId) return - const result = await switchOrAddNetwork(NETWORK_DETAIL[urlLoadedChainId], account || undefined) - // success scenario - user accepts the change on the popup window - if (result === null) unavailableRedirect(urlLoadedChainId, navigate, pathname) - }, [urlLoadedChainId, account, navigate, pathname]) + selectNetwork(urlLoadedChainId) + }, [urlLoadedChainId, selectNetwork]) return ( @@ -95,7 +89,7 @@ export default function NetworkWarningModal() { > To add/switch to the requested network, click the button below. - Add + Add or switch )} diff --git a/src/components/Pool/LiquidityMiningCampaignView/Information/index.tsx b/src/components/Pool/LiquidityMiningCampaignView/Information/index.tsx index b65a01430..206153d66 100644 --- a/src/components/Pool/LiquidityMiningCampaignView/Information/index.tsx +++ b/src/components/Pool/LiquidityMiningCampaignView/Information/index.tsx @@ -9,8 +9,8 @@ import Skeleton from 'react-loading-skeleton' import { Box, Flex, Text } from 'rebass' import styled from 'styled-components' -import { useActiveWeb3React } from '../../../../hooks' import { useNativeCurrencyUSDPrice } from '../../../../hooks/useNativeCurrencyUSDPrice' +import { useWeb3ReactCore } from '../../../../hooks/useWeb3ReactCore' import { ExternalLink, TYPE } from '../../../../theme' import { unwrappedToken } from '../../../../utils/wrappedCurrency' import { CarrotButton } from '../../../Button' @@ -184,7 +184,7 @@ function Information({ containsKpiToken, showUSDValue, }: InformationProps) { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const { loading: loadingNativeCurrencyUSDPrice, nativeCurrencyUSDPrice } = useNativeCurrencyUSDPrice() const [upcoming, setUpcoming] = useState(false) diff --git a/src/components/Pool/LiquidityMiningCampaignView/StakeCard/index.tsx b/src/components/Pool/LiquidityMiningCampaignView/StakeCard/index.tsx index 9d6ddf2d8..d1291365f 100644 --- a/src/components/Pool/LiquidityMiningCampaignView/StakeCard/index.tsx +++ b/src/components/Pool/LiquidityMiningCampaignView/StakeCard/index.tsx @@ -11,10 +11,10 @@ import Skeleton from 'react-loading-skeleton' import { Box, Flex } from 'rebass' import styled from 'styled-components' -import { useActiveWeb3React } from '../../../../hooks' import { useLiquidityMiningActionCallbacks } from '../../../../hooks/useLiquidityMiningActionCallbacks' import { useLiquidityMiningCampaignPosition } from '../../../../hooks/useLiquidityMiningCampaignPosition' import { useLpTokensUnderlyingAssets } from '../../../../hooks/useLpTokensUnderlyingAssets' +import { useWeb3ReactCore } from '../../../../hooks/useWeb3ReactCore' import { useTransactionAdder } from '../../../../state/transactions/hooks' import { useTokenBalance } from '../../../../state/wallet/hooks' import { TYPE } from '../../../../theme' @@ -119,7 +119,7 @@ export default function StakeCard({ isSingleSided, targetedPairOrToken: targetedPairOrSingleToken, }: FullPositionCardProps) { - const { account } = useActiveWeb3React() + const { account } = useWeb3ReactCore() const stakableTokenBalance = useTokenBalance( account || undefined, isSingleSided ? targetedPairOrSingleToken : targetedPairOrSingleToken.liquidityToken diff --git a/src/components/Pool/LiquidityMiningCampaignView/index.tsx b/src/components/Pool/LiquidityMiningCampaignView/index.tsx index dc5a8147e..d9430f5b3 100644 --- a/src/components/Pool/LiquidityMiningCampaignView/index.tsx +++ b/src/components/Pool/LiquidityMiningCampaignView/index.tsx @@ -5,8 +5,8 @@ import { ChevronLeft, Repeat } from 'react-feather' import { usePrevious } from 'react-use' import styled from 'styled-components' -import { useActiveWeb3React } from '../../../hooks' import { useRouter } from '../../../hooks/useRouter' +import { useWeb3ReactCore } from '../../../hooks/useWeb3ReactCore' import { useIsSwitchingToCorrectChain } from '../../../state/multi-chain-links/hooks' import { DarkCard } from '../../Card' import { AutoColumn } from '../../Column' @@ -61,7 +61,7 @@ interface PairViewProps { function LiquidityMiningCampaignView({ campaign, containsKpiToken, isSingleSidedStake }: PairViewProps) { const { navigate } = useRouter() - const { chainId, account } = useActiveWeb3React() + const { chainId, account } = useWeb3ReactCore() const previousChainId = usePrevious(chainId) const switchingToCorrectChain = useIsSwitchingToCorrectChain() diff --git a/src/components/Pool/ListFilter/index.tsx b/src/components/Pool/ListFilter/index.tsx index 0687ec878..63f8438ee 100644 --- a/src/components/Pool/ListFilter/index.tsx +++ b/src/components/Pool/ListFilter/index.tsx @@ -1,8 +1,8 @@ -import { useWeb3React } from '@web3-react/core' import { ChangeEvent, useCallback } from 'react' import { Box, Flex } from 'rebass' import styled from 'styled-components' +import { useWeb3ReactCore } from '../../../hooks/useWeb3ReactCore' import Radio from '../../Radio' export enum PairsFilterType { @@ -24,7 +24,7 @@ interface ListFilterProps { } export default function ListFilter({ disabled, filter, onFilterChange }: ListFilterProps) { - const { account } = useWeb3React() + const { account } = useWeb3ReactCore() const handleFilterRadioChange = useCallback( (event: ChangeEvent) => { diff --git a/src/components/Pool/PairView/PoolStats/PoolStats.tsx b/src/components/Pool/PairView/PoolStats/PoolStats.tsx index e60a70d0c..517c25396 100644 --- a/src/components/Pool/PairView/PoolStats/PoolStats.tsx +++ b/src/components/Pool/PairView/PoolStats/PoolStats.tsx @@ -5,11 +5,11 @@ import { useTranslation } from 'react-i18next' import { usePrevious } from 'react-use' import { Box, Flex, Text } from 'rebass' -import { useActiveWeb3React } from '../../../../hooks' import { useBestAPY } from '../../../../hooks/useBestAPY' import { usePairCampaignIndicatorAndLiquidityUSD } from '../../../../hooks/usePairCampaignIndicatorAndLiquidityUSD' import { usePair24hVolumeUSD } from '../../../../hooks/usePairVolume24hUSD' import { useRouter } from '../../../../hooks/useRouter' +import { useWeb3ReactCore } from '../../../../hooks/useWeb3ReactCore' import { useIsSwitchingToCorrectChain } from '../../../../state/multi-chain-links/hooks' import { BlurBox } from '../../../../ui/StyledElements/BlurBox' import { formatCurrencyAmount } from '../../../../utils' @@ -24,7 +24,7 @@ interface PairViewProps { export function PoolStats({ pair }: PairViewProps) { const { navigate } = useRouter() - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const previousChainId = usePrevious(chainId) const { volume24hUSD } = usePair24hVolumeUSD(pair?.liquidityToken.address) const { liquidityUSD } = usePairCampaignIndicatorAndLiquidityUSD(pair) diff --git a/src/components/Pool/PairView/UserLiquidity/UserLiquidity.tsx b/src/components/Pool/PairView/UserLiquidity/UserLiquidity.tsx index b28014060..b0389f76b 100644 --- a/src/components/Pool/PairView/UserLiquidity/UserLiquidity.tsx +++ b/src/components/Pool/PairView/UserLiquidity/UserLiquidity.tsx @@ -6,7 +6,7 @@ import { Box, Flex, Text } from 'rebass' import styled from 'styled-components' import { useTotalSupply } from '../../../../data/TotalSupply' -import { useActiveWeb3React } from '../../../../hooks' +import { useWeb3ReactCore } from '../../../../hooks/useWeb3ReactCore' import { useTokenBalance } from '../../../../state/wallet/hooks' import { BlurBox } from '../../../../ui/StyledElements/BlurBox' import { getAccountAnalyticsLink } from '../../../../utils' @@ -26,7 +26,7 @@ interface UserLiquidityProps { } export function UserLiquidity({ pair }: UserLiquidityProps) { - const { account, chainId } = useActiveWeb3React() + const { account, chainId } = useWeb3ReactCore() const currency0 = unwrappedToken(pair?.token0) const currency1 = unwrappedToken(pair?.token1) const userPoolBalance = useTokenBalance(account ?? undefined, pair?.liquidityToken) diff --git a/src/components/Pool/PairsList/PairsList.tsx b/src/components/Pool/PairsList/PairsList.tsx index 9e44ad98c..405f7a9a5 100644 --- a/src/components/Pool/PairsList/PairsList.tsx +++ b/src/components/Pool/PairsList/PairsList.tsx @@ -6,13 +6,13 @@ import { Link } from 'react-router-dom' import { Box, Flex, Text } from 'rebass' import styled from 'styled-components' -import { useActiveWeb3React } from '../../../hooks' import { useSWPRToken } from '../../../hooks/swpr/useSWPRToken' import { AggregatedPairs } from '../../../hooks/useAllPairsWithLiquidityAndMaximumApyAndStakingIndicator' import { useIsMobileByMedia } from '../../../hooks/useIsMobileByMedia' import { useNativeCurrencyUSDPrice } from '../../../hooks/useNativeCurrencyUSDPrice' import { usePage } from '../../../hooks/usePage' import { useResponsiveItemsPerPage } from '../../../hooks/useResponsiveItemsPerPage' +import { useWeb3ReactCore } from '../../../hooks/useWeb3ReactCore' import { BlurBox } from '../../../ui/StyledElements/BlurBox' import { ListLayout } from '../../../ui/StyledElements/ListLayout' import { TableHeader } from '../../../ui/StyledElements/TableHeader' @@ -35,7 +35,7 @@ interface PairsListProps { } export function PairsList({ aggregatedPairs, loading, filter, singleSidedStake }: PairsListProps) { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const [page, setPage] = useState(1) const responsiveItemsPerPage = useResponsiveItemsPerPage() const itemsPage = usePage(aggregatedPairs, responsiveItemsPerPage, page, 0) diff --git a/src/components/Popups/TransactionPopup.tsx b/src/components/Popups/TransactionPopup.tsx index 318fb0a85..962a341ad 100644 --- a/src/components/Popups/TransactionPopup.tsx +++ b/src/components/Popups/TransactionPopup.tsx @@ -4,7 +4,7 @@ import { AlertCircle, CheckCircle } from 'react-feather' import { useTranslation } from 'react-i18next' import styled, { useTheme } from 'styled-components' -import { useActiveWeb3React } from '../../hooks' +import { useWeb3ReactCore } from '../../hooks/useWeb3ReactCore' import { PopupContent } from '../../state/application/actions' import { SwapProtocol } from '../../state/transactions/reducer' import { TYPE } from '../../theme' @@ -19,7 +19,7 @@ const RowNoFlex = styled(AutoRow)` ` export function TransactionPopup({ hash, success, summary, swapProtocol }: PopupContent) { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const { t } = useTranslation('common') const theme = useTheme() diff --git a/src/components/PositionCard/index.tsx b/src/components/PositionCard/index.tsx index 719f0b45d..219e8c27c 100644 --- a/src/components/PositionCard/index.tsx +++ b/src/components/PositionCard/index.tsx @@ -8,8 +8,8 @@ import { Box, Flex } from 'rebass' import styled from 'styled-components' import { useTotalSupply } from '../../data/TotalSupply' -import { useActiveWeb3React } from '../../hooks' import { useIsMobileByMedia } from '../../hooks/useIsMobileByMedia' +import { useWeb3ReactCore } from '../../hooks/useWeb3ReactCore' import { useTokenBalance } from '../../state/wallet/hooks' import { ExternalLink, TYPE } from '../../theme' import { getAccountAnalyticsLink } from '../../utils' @@ -51,7 +51,7 @@ interface MinimalPositionCardProps { } export function MinimalPositionCard({ pair, showUnwrapped = false, border }: MinimalPositionCardProps) { - const { account } = useActiveWeb3React() + const { account } = useWeb3ReactCore() const currency0 = showUnwrapped ? pair.token0 : unwrappedToken(pair.token0) const currency1 = showUnwrapped ? pair.token1 : unwrappedToken(pair.token1) @@ -193,7 +193,7 @@ interface FullPositionCardProps { } export default function FullPositionCard({ pair, border }: FullPositionCardProps) { - const { account, chainId } = useActiveWeb3React() + const { account, chainId } = useWeb3ReactCore() const currency0 = unwrappedToken(pair?.token0) const currency1 = unwrappedToken(pair?.token1) diff --git a/src/components/Routing/RouteCheck.tsx b/src/components/Routing/RouteCheck.tsx index ac5a53274..2a390b6f8 100644 --- a/src/components/Routing/RouteCheck.tsx +++ b/src/components/Routing/RouteCheck.tsx @@ -1,6 +1,6 @@ import { ChainId } from '@swapr/sdk' -import { useActiveWeb3React } from '../../hooks' +import { useWeb3ReactCore } from '../../hooks/useWeb3ReactCore' import { chainSupportsSWPR } from '../../utils/chainSupportsSWPR' import { BaseRedirect } from './BaseRedirect' @@ -8,7 +8,7 @@ import { BaseRedirect } from './BaseRedirect' * A Route that is only accessible if all features available: Swapr core contract are deployed on the chain */ export function RouteCheck({ element }: { element: JSX.Element }) { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() // If all features are available, render the route if (chainSupportsSWPR(chainId) || ChainId.ARBITRUM_GOERLI === chainId) { // FIXME: fix this if's condition once SWPR is on Arb Goerli diff --git a/src/components/SearchModal/CurrencyList/CurrencyList.component.tsx b/src/components/SearchModal/CurrencyList/CurrencyList.component.tsx index f6a818e41..ffec00cdb 100644 --- a/src/components/SearchModal/CurrencyList/CurrencyList.component.tsx +++ b/src/components/SearchModal/CurrencyList/CurrencyList.component.tsx @@ -8,8 +8,8 @@ import { Box, Flex, Text } from 'rebass' import { useTheme } from 'styled-components' import TokenListLogo from '../../../assets/images/tokenlist.svg' -import { useActiveWeb3React } from '../../../hooks' import { useIsUserAddedToken } from '../../../hooks/Tokens' +import { useWeb3ReactCore } from '../../../hooks/useWeb3ReactCore' import { WrappedTokenInfo } from '../../../state/lists/wrapped-token-info' import { useAddUserToken, useRemoveUserAddedToken } from '../../../state/user/hooks' import { useCurrencyBalances } from '../../../state/wallet/hooks' @@ -41,7 +41,7 @@ const CurrencyRow = ({ selectedTokenList, hideBalance, }: CurrencyRowProps) => { - const { account, chainId } = useActiveWeb3React() + const { account, chainId } = useWeb3ReactCore() const isOnSelectedList = isTokenOnList(selectedTokenList, currency) const customAdded = useIsUserAddedToken(currency) @@ -130,7 +130,7 @@ export const CurrencyList = ({ selectedTokenList, hideBalance, }: CurrencyListProps) => { - const { account } = useActiveWeb3React() + const { account } = useWeb3ReactCore() const [hasBreakLine, setHasBreakLine] = useState(false) const itemData = useMemo(() => { if (otherListTokens && otherListTokens?.length > 0) { diff --git a/src/components/SearchModal/CurrencySearch/CurrencySearch.component.tsx b/src/components/SearchModal/CurrencySearch/CurrencySearch.component.tsx index 3172aa5e1..6c1d21b1e 100644 --- a/src/components/SearchModal/CurrencySearch/CurrencySearch.component.tsx +++ b/src/components/SearchModal/CurrencySearch/CurrencySearch.component.tsx @@ -16,11 +16,11 @@ import { useTranslation } from 'react-i18next' import { FixedSizeList } from 'react-window' import { useTheme } from 'styled-components' -import { useActiveWeb3React } from '../../../hooks' import { useSearchInactiveTokenLists } from '../../../hooks/Tokens' import { useNativeCurrency } from '../../../hooks/useNativeCurrency' import { useOnClickOutside } from '../../../hooks/useOnClickOutside' import useToggle from '../../../hooks/useToggle' +import { useWeb3ReactCore } from '../../../hooks/useWeb3ReactCore' import { TYPE } from '../../../theme' import { isAddress } from '../../../utils' import { ButtonDark2 } from '../../Button' @@ -49,7 +49,7 @@ export const CurrencySearch = ({ isOutputPanel, }: CurrencySearchProps) => { const { t } = useTranslation('common') - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const theme = useTheme() const { allTokens, diff --git a/src/components/SearchModal/ImportList/ImportList.component.tsx b/src/components/SearchModal/ImportList/ImportList.component.tsx index 1a514c59a..f51f7e220 100644 --- a/src/components/SearchModal/ImportList/ImportList.component.tsx +++ b/src/components/SearchModal/ImportList/ImportList.component.tsx @@ -2,8 +2,8 @@ import { useCallback, useContext, useState } from 'react' import { useDispatch } from 'react-redux' import { Text } from 'rebass' -import { useActiveWeb3React } from '../../../hooks' import { useFetchListCallback } from '../../../hooks/useFetchListCallback' +import { useWeb3ReactCore } from '../../../hooks/useWeb3ReactCore' import { AppDispatch } from '../../../state' import { enableList, removeList } from '../../../state/lists/actions' import { useAllLists } from '../../../state/lists/hooks' @@ -21,7 +21,7 @@ import { ImportListProps } from './ImportList.types' export function ImportList({ onBack, onDismiss }: ImportListProps) { const { listURL: listURI, importList: list, setModalView } = useContext(CurrencySearchModalContext) - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const dispatch = useDispatch() const lists = useAllLists() diff --git a/src/components/SearchModal/ManageLists/ManageLists.hooks.ts b/src/components/SearchModal/ManageLists/ManageLists.hooks.ts index 121f103a4..71a2104c5 100644 --- a/src/components/SearchModal/ManageLists/ManageLists.hooks.ts +++ b/src/components/SearchModal/ManageLists/ManageLists.hooks.ts @@ -5,9 +5,9 @@ import { useDispatch, useSelector } from 'react-redux' import { useToggle } from 'react-use' import { UNSUPPORTED_LIST_URLS } from '../../../constants/lists' -import { useActiveWeb3React } from '../../../hooks' import { useFetchListCallback } from '../../../hooks/useFetchListCallback' import { useOnClickOutside } from '../../../hooks/useOnClickOutside' +import { useWeb3ReactCore } from '../../../hooks/useWeb3ReactCore' import { useActiveListsHandlers, useBridgeSupportedLists } from '../../../services/EcoBridge/EcoBridge.hooks' import { AppDispatch, AppState } from '../../../state' import { acceptListUpdate, disableList, enableList, removeList } from '../../../state/lists/actions' @@ -161,7 +161,7 @@ export const useListRow = ({ listUrl }: ListRowProps) => { handleAcceptListUpdate: handleAcceptListUpdateRaw, } = useContext(ListRowContext) - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const { current: list, pendingUpdate: pending } = listsByUrl[listUrl] const tokensAmountInCurrentChain = useMemo(() => { diff --git a/src/components/SearchModal/ManageTokens/ManageTokens.component.tsx b/src/components/SearchModal/ManageTokens/ManageTokens.component.tsx index 02f0a1467..478ff46f6 100644 --- a/src/components/SearchModal/ManageTokens/ManageTokens.component.tsx +++ b/src/components/SearchModal/ManageTokens/ManageTokens.component.tsx @@ -4,8 +4,8 @@ import { ChangeEvent, RefObject, useCallback, useMemo, useRef, useState } from ' import { Box, Flex } from 'rebass' import { useTheme } from 'styled-components' -import { useActiveWeb3React } from '../../../hooks' import { useToken } from '../../../hooks/Tokens' +import { useWeb3ReactCore } from '../../../hooks/useWeb3ReactCore' import { useRemoveUserAddedToken, useUserAddedTokens } from '../../../state/user/hooks' import { ExternalLink, TYPE } from '../../../theme' import { getExplorerLink, isAddress } from '../../../utils' @@ -20,7 +20,7 @@ import { Footer, TrashIcon, Wrapper } from './ManageTokens.styles' import { ManageTokensProps } from './ManageTokens.types' export const ManageTokens = ({ setModalView, setImportToken }: ManageTokensProps) => { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const [searchQuery, setSearchQuery] = useState('') const theme = useTheme() diff --git a/src/components/SearchModal/PairList/PairList.tsx b/src/components/SearchModal/PairList/PairList.tsx index c4f16c323..46bb5ec7f 100644 --- a/src/components/SearchModal/PairList/PairList.tsx +++ b/src/components/SearchModal/PairList/PairList.tsx @@ -6,9 +6,9 @@ import AutoSizer from 'react-virtualized-auto-sizer' import { FixedSizeList } from 'react-window' import { Box, Flex, Text } from 'rebass' -import { useActiveWeb3React } from '../../../hooks' import { useIsUserAddedPair } from '../../../hooks/Tokens' import { useAllPairs } from '../../../hooks/useAllPairs' +import { useWeb3ReactCore } from '../../../hooks/useWeb3ReactCore' import { usePairAdder, usePairRemover } from '../../../state/user/hooks' import { isPairOnList } from '../../../utils' import { unwrappedToken } from '../../../utils/wrappedCurrency' @@ -35,7 +35,7 @@ function pairKey(index: number, data: Pair[]) { } const PairRow = ({ pair, onSelect, isSelected, style }: PairRowProps) => { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const { pairs: allPairs } = useAllPairs() const isOnSelectedList = isPairOnList(allPairs, pair) const customAdded = useIsUserAddedPair(pair) diff --git a/src/components/SearchModal/utils/sorting.ts b/src/components/SearchModal/utils/sorting.ts index 7fe7eca61..6da891e62 100644 --- a/src/components/SearchModal/utils/sorting.ts +++ b/src/components/SearchModal/utils/sorting.ts @@ -2,7 +2,7 @@ import { Pair, Token, TokenAmount } from '@swapr/sdk' import { useMemo } from 'react' -import { useActiveWeb3React } from '../../../hooks' +import { useWeb3ReactCore } from '../../../hooks/useWeb3ReactCore' import { toDXSwapLiquidityToken, useTrackedTokenPairs } from '../../../state/user/hooks' import { useAllTokenBalances, useTokenBalances } from '../../../state/wallet/hooks' @@ -80,7 +80,7 @@ export const useTokenComparator = (inverted: boolean): ((tokenA: Token, tokenB: } export function usePairsComparator(inverted: boolean): (pairA: Pair, pairB: Pair) => number { - const { account } = useActiveWeb3React() + const { account } = useWeb3ReactCore() const trackedTokenPairs = useTrackedTokenPairs() const balances = useTokenBalances( account || undefined, diff --git a/src/components/Swap/AdvancedSwapDetailsDropdown.tsx b/src/components/Swap/AdvancedSwapDetailsDropdown.tsx index 8083ddb05..306f5d2fd 100644 --- a/src/components/Swap/AdvancedSwapDetailsDropdown.tsx +++ b/src/components/Swap/AdvancedSwapDetailsDropdown.tsx @@ -6,7 +6,7 @@ import { Settings } from 'react-feather' import { Box, Flex } from 'rebass' import styled from 'styled-components' -import { useActiveWeb3React } from '../../hooks' +import { useWeb3ReactCore } from '../../hooks/useWeb3ReactCore' import { MainnetGasPrice } from '../../state/application/actions' import { useMainnetGasPrices, useToggleSettingsMenu } from '../../state/application/hooks' import { useMultihopManager, useUserPreferredGasPrice } from '../../state/user/hooks' @@ -83,7 +83,7 @@ export default function AdvancedSwapDetailsDropdown({ allPlatformTrades, onSelectedPlatformChange, }: AdvancedSwapDetailsDropdownProps) { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const [userPreferredMainnetGasPrice, setUserPreferredMainnetGasPrice] = useUserPreferredGasPrice() const [multihopEnabled, toggleMultihop] = useMultihopManager() const toggleSettingsMenu = useToggleSettingsMenu() diff --git a/src/components/Swap/SwapButtons/SwapButton.tsx b/src/components/Swap/SwapButtons/SwapButton.tsx index 7af0d1faf..6ba12ec84 100644 --- a/src/components/Swap/SwapButtons/SwapButton.tsx +++ b/src/components/Swap/SwapButtons/SwapButton.tsx @@ -1,10 +1,9 @@ -import { ChainId } from '@swapr/sdk' - import { useTranslation } from 'react-i18next' import { Flex, Text } from 'rebass' import { ButtonProps } from 'rebass/styled-components' import styled, { css } from 'styled-components' +import { isChainSupportedByConnector } from '../../../connectors/utils' import { PRICE_IMPACT_HIGH, PRICE_IMPACT_MEDIUM, @@ -12,7 +11,7 @@ import { RoutablePlatformKeysByNetwork, SWAP_INPUT_ERRORS, } from '../../../constants' -import { useActiveWeb3React } from '../../../hooks' +import { useWeb3ReactCore } from '../../../hooks/useWeb3ReactCore' import { shuffle } from '../../../utils/shuffleArray' import { ButtonPrimary } from '../../Button' @@ -141,11 +140,11 @@ export const SwapButton = ({ export const SwapLoadingButton = () => { const { t } = useTranslation('swap') - const { chainId } = useActiveWeb3React() - const routablePlatforms = chainId - ? RoutablePlatformKeysByNetwork[chainId] - : RoutablePlatformKeysByNetwork[ChainId.MAINNET] - + const { connector, chainId } = useWeb3ReactCore() + const routablePlatforms = + chainId && isChainSupportedByConnector(connector, chainId) + ? RoutablePlatformKeysByNetwork[chainId] + : RoutablePlatformKeysByNetwork[1] return ( {t('button.findingBestPrice')} diff --git a/src/components/Swap/SwapButtons/SwapButtons.tsx b/src/components/Swap/SwapButtons/SwapButtons.tsx index aae6e4a19..af093e683 100644 --- a/src/components/Swap/SwapButtons/SwapButtons.tsx +++ b/src/components/Swap/SwapButtons/SwapButtons.tsx @@ -4,8 +4,8 @@ import { Dispatch, SetStateAction, useCallback, useEffect } from 'react' import { useTranslation } from 'react-i18next' import { PRICE_IMPACT_HIGH, PRICE_IMPACT_MEDIUM, ROUTABLE_PLATFORM_STYLE } from '../../../constants' -import { useActiveWeb3React } from '../../../hooks' import { ApprovalState } from '../../../hooks/useApproveCallback' +import { useWeb3ReactCore } from '../../../hooks/useWeb3ReactCore' import { WrapState, WrapType } from '../../../hooks/useWrapCallback' import { SwapData } from '../../../pages/Swap/Swapbox/Swapbox' import { Field } from '../../../state/swap/types' @@ -68,7 +68,7 @@ export function SwapButtons({ wrapState, setWrapState, }: SwapButtonsProps) { - const { account } = useActiveWeb3React() + const { account, isActiveChainSupported } = useWeb3ReactCore() const isExpertMode = useIsExpertMode() const { t } = useTranslation('swap') @@ -115,7 +115,7 @@ export function SwapButtons({ return } - if (!account) { + if (!account || !isActiveChainSupported) { return } diff --git a/src/components/TokenWarningModal/index.tsx b/src/components/TokenWarningModal/index.tsx index 34be6106c..06e24a14f 100644 --- a/src/components/TokenWarningModal/index.tsx +++ b/src/components/TokenWarningModal/index.tsx @@ -7,7 +7,7 @@ import { AlertCircle, AlertTriangle } from 'react-feather' import { useTranslation } from 'react-i18next' import styled, { useTheme } from 'styled-components' -import { useActiveWeb3React } from '../../hooks' +import { useWeb3ReactCore } from '../../hooks/useWeb3ReactCore' import { ExternalLink, TYPE } from '../../theme' import { getExplorerLink, shortenAddress } from '../../utils' import { ButtonError } from '../Button' @@ -57,7 +57,7 @@ interface TokenWarningCardProps { export function TokenWarningCard({ token, list }: TokenWarningCardProps) { const theme = useTheme() const { t } = useTranslation('common') - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() if (!token) return null diff --git a/src/components/TransactionConfirmationModal/index.tsx b/src/components/TransactionConfirmationModal/index.tsx index c4f9f5797..7805f552f 100644 --- a/src/components/TransactionConfirmationModal/index.tsx +++ b/src/components/TransactionConfirmationModal/index.tsx @@ -6,7 +6,7 @@ import { Text } from 'rebass' import styled, { useTheme } from 'styled-components' import Circle from '../../assets/images/blue-loader.svg' -import { useActiveWeb3React } from '../../hooks' +import { useWeb3ReactCore } from '../../hooks/useWeb3ReactCore' import { CloseIcon, CustomLightSpinner, ExternalLink, TYPE } from '../../theme' import { getExplorerLink, getGnosisProtocolExplorerOrderLink } from '../../utils' import { ButtonPrimary } from '../Button' @@ -184,7 +184,7 @@ export default function TransactionConfirmationModal({ content, trade, }: ConfirmationModalProps) { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() if (!chainId) return null diff --git a/src/components/TransactionSettings/index.tsx b/src/components/TransactionSettings/index.tsx index 6334ed610..ba5869c28 100644 --- a/src/components/TransactionSettings/index.tsx +++ b/src/components/TransactionSettings/index.tsx @@ -3,7 +3,7 @@ import { ChainId } from '@swapr/sdk' import { useCallback, useEffect, useState } from 'react' import { AlertTriangle } from 'react-feather' -import { useActiveWeb3React } from '../../hooks' +import { useWeb3ReactCore } from '../../hooks/useWeb3ReactCore' import { MainnetGasPrice } from '../../state/application/actions' import { TYPE } from '../../theme' import { AutoColumn } from '../Column' @@ -132,7 +132,7 @@ export const TransactionSettings = ({ multihop, onMultihopChange, }: TransactionSettingsProps) => { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const formattedRawSlippage = (rawSlippage / 100).toFixed(2) const [slippageInput, setSlippageInput] = useState(formattedRawSlippage) diff --git a/src/components/WalletModal/PendingView.tsx b/src/components/WalletModal/PendingView.tsx index a28d2cf30..200f97698 100644 --- a/src/components/WalletModal/PendingView.tsx +++ b/src/components/WalletModal/PendingView.tsx @@ -1,12 +1,13 @@ -import { AbstractConnector } from '@web3-react/abstract-connector' +import { Connector } from '@web3-react/types' import { Box, Flex } from 'rebass' import styled from 'styled-components' -import { injected } from '../../connectors' +import { getConnection } from '../../connectors/utils' import { SUPPORTED_WALLETS } from '../../constants' import { TYPE } from '../../theme' import { ButtonPrimary } from '../Button' import { Loader } from '../Loader' +import { ConnectorProps } from '../WalletSwitcher/WalletOption.types' const PendingSection = styled.div` ${({ theme }) => theme.flexColumnNoWrap}; @@ -52,44 +53,26 @@ const LoadingWrapper = styled.div` export default function PendingView({ connector, error = false, - setPendingError, tryActivation, }: { - connector?: AbstractConnector + connector: Connector error?: boolean - setPendingError: (error: boolean) => void - tryActivation: (connector: AbstractConnector) => void -}) { - const isMetamask = window?.ethereum?.isMetaMask +} & Pick) { + const { name, logo } = SUPPORTED_WALLETS[getConnection(connector).type] return ( - {Object.keys(SUPPORTED_WALLETS).map(key => { - const option = SUPPORTED_WALLETS[key] - if (option.connector === connector) { - if (option.connector === injected) { - if (isMetamask && option.name !== 'MetaMask') { - return null - } - if (!isMetamask && option.name === 'MetaMask') { - return null - } - } - return ( - - - logo - - - - {option.name} - - - - ) - } - return null - })} + + + logo + + + + {name} + + + + {error ? ( @@ -107,7 +90,6 @@ export default function PendingView({ { - setPendingError(false) connector && tryActivation(connector) }} > diff --git a/src/components/WalletModal/index.tsx b/src/components/WalletModal/index.tsx index 22b864124..f8ada51b4 100644 --- a/src/components/WalletModal/index.tsx +++ b/src/components/WalletModal/index.tsx @@ -1,18 +1,17 @@ -import { AbstractConnector } from '@web3-react/abstract-connector' -import { useWeb3React } from '@web3-react/core' -import { useCallback, useEffect } from 'react' -import { AlertTriangle } from 'react-feather' +import { useEffect } from 'react' +import { useSelector } from 'react-redux' import { usePrevious } from 'react-use' import styled from 'styled-components' import { ReactComponent as DxDaoBanner } from '../../assets/images/DxDaoProductBanner.svg' import { ReactComponent as Close } from '../../assets/images/x.svg' -import { useUnsupportedChainIdError } from '../../hooks' -import { useWalletSwitcherPopoverToggle } from '../../state/application/hooks' +import { getConnection } from '../../connectors/utils' +import { useWeb3ReactCore } from '../../hooks/useWeb3ReactCore' +import { AppState } from '../../state' +import { ApplicationModal } from '../../state/application/actions' +import { useCloseModals, useModalOpen, useWalletSwitcherPopoverToggle } from '../../state/application/hooks' import { TYPE } from '../../theme' import Modal from '../Modal' -import { AutoRow } from '../Row' -import { ModalView } from '../Web3Status' import PendingView from './PendingView' const CloseIcon = styled.div` position: absolute; @@ -27,10 +26,6 @@ const CloseColor = styled(Close)` color: ${({ theme }) => theme.text3}; ` -const StyledWarningIcon = styled(AlertTriangle)` - stroke: ${({ theme }) => theme.text3}; -` - const Wrapper = styled.div` ${({ theme }) => theme.flexColumnNoWrap} margin: 0; @@ -98,116 +93,64 @@ const HoverText = styled.div` } ` -interface WalletModalProps { - modal: ModalView | null - setModal: (modal: ModalView | null) => void - tryActivation: (connector: AbstractConnector | undefined) => void - pendingError: boolean | undefined - setPendingError: (value: boolean) => void - pendingWallet: AbstractConnector | undefined -} - -export default function WalletModal({ - modal, - setModal, - tryActivation, - pendingError, - setPendingError, - pendingWallet, -}: WalletModalProps) { - const { active, account, connector, error } = useWeb3React() - - const closeModal = useCallback(() => setModal(null), [setModal]) - - const isModalVisible = modal !== null +export default function WalletModal() { + const { account, connector, isActive, connectorError, tryActivation } = useWeb3ReactCore() + const isConnectorError = !!connectorError const previousAccount = usePrevious(account) + const previousConnector = usePrevious(connector) - // close on connection, when logged out before - useEffect(() => { - if (account && !previousAccount && isModalVisible) { - closeModal() - } - }, [account, previousAccount, closeModal, isModalVisible]) - - // close on wallet change - useEffect(() => { - if (account && previousAccount && previousAccount !== account && isModalVisible) { - closeModal() - } - }, [account, previousAccount, closeModal, isModalVisible]) - - const activePrevious = usePrevious(active) - const connectorPrevious = usePrevious(connector) - useEffect(() => { - if (!!modal && ((active && !activePrevious) || (connector && connector !== connectorPrevious && !error))) { - setModal(null) - } - }, [setModal, active, error, connector, modal, activePrevious, connectorPrevious]) - + const isWalletPendingModalOpen = useModalOpen(ApplicationModal.WALLET_PENDING) + const { pending, selected } = useSelector((state: AppState) => state.user.connector) + const pendingConnector = pending ? getConnection(pending).connector : undefined + const closeModal = useCloseModals() const toggleWalletSwitcherPopover = useWalletSwitcherPopoverToggle() const onBackButtonClick = () => { - setPendingError(false) - setModal(null) + closeModal() toggleWalletSwitcherPopover() } - const unsupportedChainIdError = useUnsupportedChainIdError() - function getModalContent() { - if (error) { - return ( - - - - - - - - - {unsupportedChainIdError ? 'Wrong Network' : 'Error connecting'} - - - - - -
- {unsupportedChainIdError - ? 'Please connect to the appropriate network.' - : 'Error connecting. Try refreshing the page.'} -
-
-
-
- ) + // close pending wallet modal + useEffect(() => { + if ( + isWalletPendingModalOpen && + (pending === selected || + (account && !previousAccount) || + (previousAccount && previousAccount !== account) || + (connector && connector !== previousConnector && !isConnectorError)) + ) { + closeModal() } + }, [ + account, + previousAccount, + closeModal, + isWalletPendingModalOpen, + pending, + selected, + isActive, + connector, + previousConnector, + isConnectorError, + ]) + function getModalContent() { return ( - {modal !== ModalView.Account ? ( - - - - Back - - - - ) : ( - - - Connect to a wallet + + + + Back - - )} + + - + {pendingConnector && ( + + )} @@ -217,7 +160,7 @@ export default function WalletModal({ } return ( - + {getModalContent()} ) diff --git a/src/components/WalletSwitcher/WalletOption.tsx b/src/components/WalletSwitcher/WalletOption.tsx new file mode 100644 index 000000000..117a957dd --- /dev/null +++ b/src/components/WalletSwitcher/WalletOption.tsx @@ -0,0 +1,98 @@ +import { Connector } from '@web3-react/types' +import React from 'react' +import styled from 'styled-components' + +import { ConnectorType, SUPPORTED_WALLETS } from '../../constants' +import { StyledConnectedIcon } from '../../utils' +import { ConnectorProps } from './WalletOption.types' + +const ListIconWrapper = styled.div<{ isActive?: boolean }>` + display: inline-flex; + justify-content: space-evenly; + align-items: center; + width: 20px; + height: 20px; + margin-right: ${props => (props.isActive ? '34px' : '8px')}; + + img { + max-width: 100%; + } +` + +const ListItem = styled.li` + & + & { + margin-top: 20px; + margin-bottom: 20px; + } +` + +const ListButton = styled.button` + display: flex; + align-items: center; + padding: 0; + font-weight: 700; + font-size: 12px; + line-height: 15px; + text-align: center; + letter-spacing: 0.08em; + text-transform: uppercase; + white-space: nowrap; + color: ${({ theme }) => theme.text2}; + background: none; + border: 0; + outline: none; + cursor: pointer; + padding: 0 22px; + + &:disabled { + cursor: not-allowed; + filter: grayscale(90%); + opacity: 0.6; + } +` + +interface OptionProps { + id: ConnectorType + connector: Connector + isActive: boolean + isWalletDetected?: boolean +} + +export const WalletOption = ({ + id, + connector, + isActive, + isWalletDetected, + tryActivation, +}: OptionProps & Pick) => { + const { logo, link, name } = SUPPORTED_WALLETS[id] + + if (!isWalletDetected && link) { + return ( + + + + {name + + INSTALL {name} + + + ) + } + + return ( + + { + tryActivation(connector) + }} + > + + {isActive && } + {name + + {name} + + + ) +} diff --git a/src/components/WalletSwitcher/WalletOption.types.ts b/src/components/WalletSwitcher/WalletOption.types.ts new file mode 100644 index 000000000..299b48b96 --- /dev/null +++ b/src/components/WalletSwitcher/WalletOption.types.ts @@ -0,0 +1,6 @@ +import { Connector } from '@web3-react/types' + +export type ConnectorProps = { + tryActivation: (connector: Connector) => void + tryDeactivation: (connector: Connector, account: string | undefined) => void +} diff --git a/src/components/WalletSwitcher/Wallets/CoinbaseWalletConnector.tsx b/src/components/WalletSwitcher/Wallets/CoinbaseWalletConnector.tsx new file mode 100644 index 000000000..8db27b428 --- /dev/null +++ b/src/components/WalletSwitcher/Wallets/CoinbaseWalletConnector.tsx @@ -0,0 +1,19 @@ +import { coinbaseWallet, coinbaseWalletHooks } from '../../../connectors' +import { ConnectorType } from '../../../constants' +import { useWeb3ReactCore } from '../../../hooks/useWeb3ReactCore' +import { WalletOption } from '../WalletOption' +import { ConnectorProps } from '../WalletOption.types' + +export const CoinbaseWalletConnector = ({ tryActivation }: Pick) => { + const { connector: activeConnector } = useWeb3ReactCore() + const isActive = coinbaseWalletHooks.useIsActive() && activeConnector === coinbaseWallet + + return ( + + ) +} diff --git a/src/components/WalletSwitcher/Wallets/MetaMaskConnector.tsx b/src/components/WalletSwitcher/Wallets/MetaMaskConnector.tsx new file mode 100644 index 000000000..c25ac6e7d --- /dev/null +++ b/src/components/WalletSwitcher/Wallets/MetaMaskConnector.tsx @@ -0,0 +1,22 @@ +import { metaMask, metaMaskHooks } from '../../../connectors' +import { getIsInjected, getIsMetaMask } from '../../../connectors/utils' +import { ConnectorType } from '../../../constants' +import { useWeb3ReactCore } from '../../../hooks/useWeb3ReactCore' +import { WalletOption } from '../WalletOption' +import { ConnectorProps } from '../WalletOption.types' + +export const MetaMaskConnector = ({ tryActivation }: Pick) => { + const { connector: activeConnector } = useWeb3ReactCore() + const isWalletDetected = getIsInjected() && getIsMetaMask() + const isActive = metaMaskHooks.useIsActive() && activeConnector === metaMask + + return ( + + ) +} diff --git a/src/components/WalletSwitcher/Wallets/WalletConnectConnector.tsx b/src/components/WalletSwitcher/Wallets/WalletConnectConnector.tsx new file mode 100644 index 000000000..093feb502 --- /dev/null +++ b/src/components/WalletSwitcher/Wallets/WalletConnectConnector.tsx @@ -0,0 +1,19 @@ +import { walletConnect, walletConnectHooks } from '../../../connectors' +import { ConnectorType } from '../../../constants' +import { useWeb3ReactCore } from '../../../hooks/useWeb3ReactCore' +import { WalletOption } from '../WalletOption' +import { ConnectorProps } from '../WalletOption.types' + +export const WalletConnectConnector = ({ tryActivation }: Pick) => { + const { connector: activeConnector } = useWeb3ReactCore() + const isActive = walletConnectHooks.useIsActive() && activeConnector === walletConnect + + return ( + + ) +} diff --git a/src/components/Web3Provider/index.tsx b/src/components/Web3Provider/index.tsx new file mode 100644 index 000000000..05c1d0fdb --- /dev/null +++ b/src/components/Web3Provider/index.tsx @@ -0,0 +1,22 @@ +import { Web3ReactHooks, Web3ReactProvider } from '@web3-react/core' +import { Connector } from '@web3-react/types' +import { FC, PropsWithChildren, useMemo } from 'react' + +import { Connection } from '../../connectors' +import { getConnectionName } from '../../connectors/utils' +import useEagerlyConnect from '../../hooks/useEagerlyConnect' +import useOrderedConnections from '../../hooks/useOrderedConnections' + +export const Web3Provider: FC = ({ children }) => { + useEagerlyConnect() + const connections = useOrderedConnections() + const connectors: [Connector, Web3ReactHooks][] = connections.map(({ hooks, connector }) => [connector, hooks]) + + const key = useMemo(() => connections.map(({ type }: Connection) => getConnectionName(type)).join('-'), [connections]) + + return ( + + {children} + + ) +} diff --git a/src/components/Web3ReactManager/index.tsx b/src/components/Web3ReactManager/index.tsx deleted file mode 100644 index 41fd0a23b..000000000 --- a/src/components/Web3ReactManager/index.tsx +++ /dev/null @@ -1,81 +0,0 @@ -import { useWeb3React } from '@web3-react/core' -import { useEffect, useState } from 'react' -import { useTranslation } from 'react-i18next' -import styled from 'styled-components' - -import { network } from '../../connectors' -import { NetworkContextName } from '../../constants' -import { useEagerConnect, useInactiveListener } from '../../hooks' -import { useTargetedChainIdFromUrl } from '../../hooks/useTargetedChainIdFromUrl' -import { Loader } from '../Loader' - -const MessageWrapper = styled.div` - display: flex; - align-items: center; - justify-content: center; - height: 20rem; -` - -const Message = styled.h2` - color: ${({ theme }) => theme.secondary1}; -` - -export default function Web3ReactManager({ children }: { children: JSX.Element }) { - const { t } = useTranslation('common') - const { active } = useWeb3React() - const { active: networkActive, error: networkError, activate: activateNetwork } = useWeb3React(NetworkContextName) - const targetedChainId = useTargetedChainIdFromUrl() - - // try to eagerly connect to an injected provider, if it exists and has granted access already - const triedEager = useEagerConnect() - - // after eagerly trying injected, if the network connect ever isn't active or in an error state, activate itd - useEffect(() => { - if (triedEager && !networkActive && !networkError && !active) { - if (targetedChainId && network.supportedChainIds && network.supportedChainIds.indexOf(targetedChainId) >= 0) { - network.changeChainId(targetedChainId) - } - activateNetwork(network) - } - }, [triedEager, networkActive, networkError, activateNetwork, active, targetedChainId]) - - // when there's no account connected, react to logins (broadly speaking) on the injected provider, if it exists - useInactiveListener(!triedEager) - - // handle delayed loader state - const [showLoader, setShowLoader] = useState(false) - useEffect(() => { - const timeout = setTimeout(() => { - setShowLoader(true) - }, 600) - - return () => { - clearTimeout(timeout) - } - }, []) - - // on page load, do nothing until we've tried to connect to the injected connector - if (!triedEager) { - return null - } - - // if the account context isn't active, and there's an error on the network context, it's an irrecoverable error - if (!active && networkError) { - return ( - - {t('unknownError')} - - ) - } - - // if neither context is active, spin - if (!active && !networkActive) { - return showLoader ? ( - - - - ) : null - } - - return children -} diff --git a/src/components/Web3Status/AccountStatus.tsx b/src/components/Web3Status/AccountStatus.tsx index a9441058c..732cf8a4a 100644 --- a/src/components/Web3Status/AccountStatus.tsx +++ b/src/components/Web3Status/AccountStatus.tsx @@ -1,7 +1,9 @@ import { ChainId } from '@swapr/sdk' -import { AbstractConnector } from '@web3-react/abstract-connector' -import { InjectedConnector } from '@web3-react/injected-connector' +import { CoinbaseWallet } from '@web3-react/coinbase-wallet' +import { MetaMask } from '@web3-react/metamask' +import { Connector } from '@web3-react/types' +import { WalletConnect } from '@web3-react/walletconnect' import { useEffect, useState } from 'react' import { Text } from 'rebass' import styled from 'styled-components' @@ -12,8 +14,6 @@ import EthereumLogo from '../../assets/images/ethereum-logo.svg' import GnosisLogo from '../../assets/images/gnosis-chain-logo.svg' import OptimismLogo from '../../assets/images/optimism-logo.svg' import PolygonMaticLogo from '../../assets/images/polygon-matic-logo.svg' -import { CustomNetworkConnector } from '../../connectors/CustomNetworkConnector' -import { CustomWalletLinkConnector } from '../../connectors/CustomWalletLinkConnector' import { ENSAvatarData } from '../../hooks/useENSAvatar' import { ApplicationModal } from '../../state/application/actions' import { useNetworkSwitcherPopoverToggle } from '../../state/application/hooks' @@ -140,7 +140,7 @@ interface AccountStatusProps { ENSName?: string avatar?: ENSAvatarData account: string | undefined | null - connector: AbstractConnector | undefined + connector: Connector | undefined networkConnectorChainId: ChainId | undefined onAddressClick: () => void } @@ -160,10 +160,7 @@ export function AccountStatus({ useEffect(() => { setNetworkSwitchingActive( - connector instanceof CustomNetworkConnector || - connector instanceof InjectedConnector || - connector instanceof CustomWalletLinkConnector || - connector instanceof AbstractConnector + connector instanceof MetaMask || connector instanceof CoinbaseWallet || connector instanceof WalletConnect ) }, [connector]) diff --git a/src/components/Web3Status/ConnectWalletPopover.tsx b/src/components/Web3Status/ConnectWalletPopover.tsx index fe0ef7ab6..e4f3bef2d 100644 --- a/src/components/Web3Status/ConnectWalletPopover.tsx +++ b/src/components/Web3Status/ConnectWalletPopover.tsx @@ -1,17 +1,16 @@ -import { AbstractConnector } from '@web3-react/abstract-connector' -import { useWeb3React } from '@web3-react/core' import { ReactNode, useRef } from 'react' -import { isMobile } from 'react-device-detect' import styled from 'styled-components' -import MetamaskIcon from '../../assets/images/metamask.png' -import { injected } from '../../connectors' -import { SUPPORTED_WALLETS } from '../../constants' import { useOnClickOutside } from '../../hooks/useOnClickOutside' +import { useWeb3ReactCore } from '../../hooks/useWeb3ReactCore' import { ApplicationModal } from '../../state/application/actions' import { useCloseModals, useModalOpen } from '../../state/application/hooks' import { StyledConnectedIcon } from '../../utils' import Popover from '../Popover' +import { ConnectorProps } from '../WalletSwitcher/WalletOption.types' +import { CoinbaseWalletConnector } from '../WalletSwitcher/Wallets/CoinbaseWalletConnector' +import { MetaMaskConnector } from '../WalletSwitcher/Wallets/MetaMaskConnector' +import { WalletConnectConnector } from '../WalletSwitcher/Wallets/WalletConnectConnector' const Wrapper = styled.div` width: 100%; @@ -98,12 +97,11 @@ const StyledPopover = styled(Popover)<{ isActive?: boolean }>` ` interface ConnectWalletProps { - tryActivation: (connector: AbstractConnector | undefined) => void children: ReactNode } -export const ConnectWalletPopover = ({ tryActivation, children }: ConnectWalletProps) => { - const { connector, active, deactivate } = useWeb3React() +export const ConnectWalletPopover = ({ children }: ConnectWalletProps & ConnectorProps) => { + const { connector, isActive, account, tryActivation, tryDeactivation } = useWeb3ReactCore() const popoverRef = useRef(null) const walletSwitcherPopoverOpen = useModalOpen(ApplicationModal.WALLET_SWITCHER) const closeModals = useCloseModals() @@ -111,91 +109,22 @@ export const ConnectWalletPopover = ({ tryActivation, children }: ConnectWalletP if (walletSwitcherPopoverOpen) closeModals() }) - function getOptions() { - const isMetamask = window.ethereum && window.ethereum.isMetaMask - return Object.keys(SUPPORTED_WALLETS).map(key => { - const option = SUPPORTED_WALLETS[key] - // check for mobile options - if (isMobile) { - if (option.mobile) { - return ( - { - closeModals() - option.connector !== connector && !option.href && tryActivation(option.connector) - }} - icon={option.iconName} - isActive={option.connector && option.connector === connector} - /> - ) - } - return null - } - - // overwrite injected when needed - if (option.connector === injected) { - // don't show injected if there's no injected provider - if (!(window.web3 || window.ethereum) || ((window.web3 || window.ethereum) && !isMetamask)) { - if (option.name === 'MetaMask') { - return ( - - ) - } else { - return null //dont want to return install twice - } - } - // don't return metamask if injected provider isn't metamask - else if (option.name === 'MetaMask' && !isMetamask) { - return null - } - // likewise for generic - else if (option.name === 'Injected' && isMetamask) { - return null - } - } - - // return rest of options - return ( - !isMobile && - !option.mobileOnly && ( - { - closeModals() - option.connector !== connector && !option.href && tryActivation(option.connector) - }} - name={option.name} - icon={option.iconName} - isActive={option.connector && option.connector === connector} - /> - ) - ) - }) - } - return ( - {getOptions()} - {active && Disconnect Wallet} + + + + + {isActive && ( + tryDeactivation(connector, account)}>Disconnect Wallet + )} } show={walletSwitcherPopoverOpen} - isActive={active} + isActive={isActive} placement="bottom-end" > {children} diff --git a/src/components/Web3Status/index.tsx b/src/components/Web3Status/index.tsx index 36539aa37..551adc961 100644 --- a/src/components/Web3Status/index.tsx +++ b/src/components/Web3Status/index.tsx @@ -1,20 +1,14 @@ -import { AbstractConnector } from '@web3-react/abstract-connector' -import { UnsupportedChainIdError, useWeb3React } from '@web3-react/core' -import { WalletConnectConnector } from '@web3-react/walletconnect-connector' -import React, { useCallback, useEffect, useMemo, useState } from 'react' +import { useCallback, useEffect, useMemo } from 'react' import { useTranslation } from 'react-i18next' import { useNavigate } from 'react-router-dom' import styled from 'styled-components' -import { NetworkContextName } from '../../constants' -import { useActiveWeb3React, useUnsupportedChainIdError } from '../../hooks' import { useENSAvatar } from '../../hooks/useENSAvatar' -import { useENSName } from '../../hooks/useENSName' import { useIsMobileByMedia } from '../../hooks/useIsMobileByMedia' +import { useWeb3ReactCore } from '../../hooks/useWeb3ReactCore' import { ApplicationModal } from '../../state/application/actions' import { useCloseModals, - useModalOpen, useNetworkSwitcherPopoverToggle, useOpenModal, useWalletSwitcherPopoverToggle, @@ -71,20 +65,18 @@ function newTransactionsFirst(a: TransactionDetails, b: TransactionDetails) { return b.addedTime - a.addedTime } -export enum ModalView { - Pending, - Account, -} - export default function Web3Status() { - const { active, activate, account, error } = useWeb3React() - const { chainId: networkConnectorChainId, connector: activeConnector } = useActiveWeb3React() - const contextNetwork = useWeb3React(NetworkContextName) - const navigate = useNavigate() - - const { ENSName } = useENSName(account ?? undefined) + const { account, connector, chainId, ENSName, isActiveChainSupported, tryActivation, tryDeactivation } = + useWeb3ReactCore() const { avatar: ensAvatar } = useENSAvatar(ENSName) const allTransactions = useAllSwapTransactions() + const navigate = useNavigate() + const { t } = useTranslation('common') + const toggleNetworkSwitcherPopover = useNetworkSwitcherPopoverToggle() + const openUnsupportedNetworkModal = useOpenModal(ApplicationModal.UNSUPPORTED_NETWORK) + const toggleWalletSwitcherPopover = useWalletSwitcherPopoverToggle() + const mobileByMedia = useIsMobileByMedia() + const closeModals = useCloseModals() const pending = useMemo(() => { const txs = Object.values(allTransactions) @@ -94,107 +86,48 @@ export default function Web3Status() { .map(tx => tx.hash) }, [allTransactions]) - const [modal, setModal] = useState(null) - - const [pendingError, setPendingError] = useState() - const [pendingWallet, setPendingWallet] = useState() - - const toggleNetworkSwitcherPopover = useNetworkSwitcherPopoverToggle() - const openUnsupportedNetworkModal = useOpenModal(ApplicationModal.UNSUPPORTED_NETWORK) - - const tryActivation = async (connector: AbstractConnector | undefined) => { - setPendingWallet(connector) - setModal(ModalView.Pending) - - // if the connector is walletconnect and the user has already tried to connect, manually reset the connector - // eslint-disable-next-line - // @ts-ignore - if (connector instanceof WalletConnectConnector && connector.walletConnectProvider?.wc?.uri) { - connector.walletConnectProvider = undefined - } - - connector && - activate(connector, undefined, true).catch(error => { - if (error instanceof UnsupportedChainIdError) { - activate(connector) - } else { - setPendingError(true) - } - }) - } - - const toggleWalletSwitcherPopover = useWalletSwitcherPopoverToggle() - const { t } = useTranslation('common') - const mobileByMedia = useIsMobileByMedia() - const [isUnsupportedNetwork, setUnsupportedNetwork] = useState(false) - const isUnsupportedNetworkModal = useModalOpen(ApplicationModal.UNSUPPORTED_NETWORK) - const closeModals = useCloseModals() - - const unsupportedChainIdError = useUnsupportedChainIdError() - useEffect(() => { - if (!isUnsupportedNetworkModal && !isUnsupportedNetwork && unsupportedChainIdError) { - setUnsupportedNetwork(true) + if (!isActiveChainSupported) { openUnsupportedNetworkModal() - } else if (!isUnsupportedNetworkModal && isUnsupportedNetwork && !unsupportedChainIdError) { - setUnsupportedNetwork(false) - } else if (isUnsupportedNetworkModal && !unsupportedChainIdError) { + } else { closeModals() } - }, [ - isUnsupportedNetwork, - openUnsupportedNetworkModal, - isUnsupportedNetworkModal, - unsupportedChainIdError, - closeModals, - ]) + }, [closeModals, isActiveChainSupported, openUnsupportedNetworkModal]) const clickHandler = useCallback(() => { toggleNetworkSwitcherPopover() }, [toggleNetworkSwitcherPopover]) - if (!contextNetwork.active && !active) { - return null - } - if (error) { - return ( - - - Switch network - - - - ) - } - return ( <> - + - {networkConnectorChainId && !account && ( + {!account && ( )} - navigate('/account')} - avatar={ensAvatar ?? undefined} - /> + {isActiveChainSupported ? ( + navigate('/account')} + avatar={ensAvatar ?? undefined} + /> + ) : ( + + + Switch network + + + + )} - + ) } diff --git a/src/connectors/CustomNetworkConnector.ts b/src/connectors/CustomNetworkConnector.ts deleted file mode 100644 index 82d0002a3..000000000 --- a/src/connectors/CustomNetworkConnector.ts +++ /dev/null @@ -1,146 +0,0 @@ -import { AbstractConnector } from '@web3-react/abstract-connector' -// eslint-disable-next-line import/named -import { ConnectorUpdate } from '@web3-react/types' -import invariant from 'tiny-invariant' - -import { NetworkDetails } from '../constants' - -// taken from ethers.js, compatible interface with web3 provider -type AsyncSendable = { - isMetaMask?: boolean - host?: string - path?: string - sendAsync?: (request: any, callback: (error: any, response: any) => void) => void - send?: (request: any, callback: (error: any, response: any) => void) => void -} - -export class RequestError extends Error { - constructor(message: string, public code: number, public data?: unknown) { - super() - this.name = this.constructor.name - this.message = message - } -} - -class CustomMiniRpcProvider implements AsyncSendable { - public readonly isMetaMask: false = false - public readonly chainId: number - public readonly url: string - public readonly host: string - public readonly path: string - - constructor(chainId: number, url: string) { - this.chainId = chainId - this.url = url - const parsed = new URL(url) - this.host = parsed.host - this.path = parsed.pathname - } - - public readonly sendAsync = ( - request: { jsonrpc: '2.0'; id: number | string | null; method: string; params?: unknown[] }, - callback: (error: any, response: any) => void - ): void => { - this.request(request.method, request.params) - .then(result => callback(null, { jsonrpc: '2.0', id: request.id, result })) - .catch(error => callback(error, null)) - } - - public readonly request = async ( - method: string | { method: string; params?: unknown[] }, - params?: unknown[] - ): Promise => { - if (typeof method !== 'string') { - params = (method as any).params - method = method.method - } - - const response = await fetch(this.url, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - jsonrpc: '2.0', - id: 1, - method, - params, - }), - }) - if (!response.ok) throw new RequestError(`${response.status}: ${response.statusText}`, -32000) - const body = await response.json() - if ('error' in body) { - throw new RequestError(body?.error?.message, body?.error?.code, body?.error?.data) - } else if ('result' in body) { - return body.result - } else { - throw new RequestError(`Received unexpected JSON-RPC response to ${method} request.`, -32000, body) - } - } -} - -interface NetworkConnectorArguments { - urls: { [chainId: number]: string } - defaultChainId?: number -} - -export class CustomNetworkConnector extends AbstractConnector { - private readonly providers: { [chainId: number]: CustomMiniRpcProvider } - private currentChainId: number - - constructor({ urls, defaultChainId }: NetworkConnectorArguments) { - invariant(defaultChainId || Object.keys(urls).length === 1, 'defaultChainId is a required argument with >1 url') - super({ supportedChainIds: Object.keys(urls).map((k): number => Number(k)) }) - - this.currentChainId = defaultChainId || Number(Object.keys(urls)[0]) - this.providers = Object.keys(urls).reduce<{ [chainId: number]: CustomMiniRpcProvider }>((accumulator, chainId) => { - accumulator[Number(chainId)] = new CustomMiniRpcProvider(Number(chainId), urls[Number(chainId)]) - return accumulator - }, {}) - } - - public get provider(): CustomMiniRpcProvider { - return this.providers[this.currentChainId] - } - - public async activate(): Promise { - return { provider: this.providers[this.currentChainId], chainId: this.currentChainId, account: null } - } - - public async getProvider(): Promise { - return this.providers[this.currentChainId] - } - - public async getChainId(): Promise { - return this.currentChainId - } - - public async getAccount(): Promise { - return null - } - - public deactivate() { - return - } - - public changeChainId(chainId: number) { - invariant(Object.keys(this.providers).includes(chainId.toString()), `No url found for chainId ${chainId}`) - this.currentChainId = chainId - this.emitUpdate({ provider: this.providers[this.currentChainId], chainId }) - } - - public switchUnsupportedNetwork(networkDetails?: NetworkDetails) { - if (!window.ethereum || !window.ethereum.request || !window.ethereum.isMetaMask || !networkDetails) - return Promise.reject() - return window.ethereum - .request({ - method: 'wallet_switchEthereumChain', - params: [{ chainId: networkDetails.chainId }], - }) - .catch(error => { - if (error.code !== 4902) { - console.error('error switching to chain id', networkDetails.chainId, error) - } - }) - } -} diff --git a/src/connectors/CustomWalletConnectConnector.ts b/src/connectors/CustomWalletConnectConnector.ts deleted file mode 100644 index 3f535f548..000000000 --- a/src/connectors/CustomWalletConnectConnector.ts +++ /dev/null @@ -1,121 +0,0 @@ -// largely taken from https://github.com/NoahZinsmeister/web3-react/blob/v6/packages/walletconnect-connector/src/index.ts -// Updated to always be in sync with network connector's chain id - -import { IWalletConnectProviderOptions } from '@walletconnect/types' -import { AbstractConnector } from '@web3-react/abstract-connector' -import { ConnectorUpdate } from '@web3-react/types' - -import { network } from '.' - -export const URI_AVAILABLE = 'URI_AVAILABLE' - -export interface WalletConnectConnectorArguments extends IWalletConnectProviderOptions { - supportedChainIds?: number[] -} - -export class UserRejectedRequestError extends Error { - public constructor() { - super() - this.name = this.constructor.name - this.message = 'The user rejected the request.' - } -} - -function getSupportedChains({ supportedChainIds, rpc }: WalletConnectConnectorArguments): number[] | undefined { - if (supportedChainIds) { - return supportedChainIds - } - - return rpc ? Object.keys(rpc).map(k => Number(k)) : undefined -} - -export class CustomWalletConnectConnector extends AbstractConnector { - private readonly config: WalletConnectConnectorArguments - - public walletConnectProvider?: any - - constructor(config: WalletConnectConnectorArguments) { - super({ supportedChainIds: getSupportedChains(config) }) - - this.config = config - - this.changeChainId = this.changeChainId.bind(this) - this.handleAccountsChanged = this.handleAccountsChanged.bind(this) - this.handleDisconnect = this.handleDisconnect.bind(this) - } - - public changeChainId(chainId: number | string): void { - this.emitUpdate({ chainId }) - } - - private handleAccountsChanged(accounts: string[]): void { - this.emitUpdate({ account: accounts[0] }) - } - - private handleDisconnect(): void { - this.emitDeactivate() - // we have to do this because of a @walletconnect/web3-provider bug - if (this.walletConnectProvider) { - this.walletConnectProvider.stop() - this.walletConnectProvider.removeListener('chainChanged', this.changeChainId) - this.walletConnectProvider.removeListener('accountsChanged', this.handleAccountsChanged) - this.walletConnectProvider = undefined - } - - this.emitDeactivate() - } - - public async activate(): Promise { - const WalletConnectProvider = await import('@walletconnect/web3-provider').then(m => m?.default ?? m) - this.walletConnectProvider = new WalletConnectProvider(this.config) - - // ensure that the uri is going to be available, and emit an event if there's a new uri - if (!this.walletConnectProvider.wc.connected) { - await this.walletConnectProvider.wc.createSession({ chainId: await network.getChainId() }) - this.emit(URI_AVAILABLE, this.walletConnectProvider.wc.uri) - } - - const account = await this.walletConnectProvider - .enable() - .then((accounts: string[]): string => accounts[0]) - .catch((error: Error): void => { - // TODO ideally this would be a better check - if (error.message === 'User closed modal') { - throw new UserRejectedRequestError() - } - - throw error - }) - - this.walletConnectProvider.on('chainChanged', this.changeChainId) - this.walletConnectProvider.on('disconnect', this.handleDisconnect) - this.walletConnectProvider.on('accountsChanged', this.handleAccountsChanged) - - return { provider: this.walletConnectProvider, account } - } - - public async getProvider(): Promise { - return this.walletConnectProvider - } - - public async getChainId(): Promise { - return this.walletConnectProvider.send('eth_chainId') - } - - public async getAccount(): Promise { - return this.walletConnectProvider.send('eth_accounts').then((accounts: string[]): string => accounts[0]) - } - - public deactivate() { - if (this.walletConnectProvider) { - this.walletConnectProvider.stop() - this.walletConnectProvider.removeListener('chainChanged', this.changeChainId) - this.walletConnectProvider.removeListener('disconnect', this.handleDisconnect) - this.walletConnectProvider.removeListener('accountsChanged', this.handleAccountsChanged) - } - } - - public async close() { - await this.walletConnectProvider?.close() - } -} diff --git a/src/connectors/CustomWalletLinkConnector.ts b/src/connectors/CustomWalletLinkConnector.ts deleted file mode 100644 index 490b3f500..000000000 --- a/src/connectors/CustomWalletLinkConnector.ts +++ /dev/null @@ -1,118 +0,0 @@ -// largely taken from https://github.com/NoahZinsmeister/web3-react/blob/v6/packages/walletlink-connector/src/index.ts -// Updated to always be in sync with network connector's chain id - -import { AbstractConnector } from '@web3-react/abstract-connector' -import { ConnectorUpdate } from '@web3-react/types' - -import { NetworkDetails } from '../constants' - -const CHAIN_ID = 1 - -interface WalletLinkConnectorArguments { - url: string - appName: string - appLogoUrl?: string - darkMode?: boolean - supportedChainIds?: number[] -} - -export class CustomWalletLinkConnector extends AbstractConnector { - private readonly url: string - private readonly appName: string - private readonly appLogoUrl?: string - private readonly darkMode: boolean - - public walletLink: any - public provider: any - - constructor({ url, appName, appLogoUrl, darkMode, supportedChainIds }: WalletLinkConnectorArguments) { - super({ supportedChainIds: supportedChainIds }) - - this.url = url - this.appName = appName - this.appLogoUrl = appLogoUrl - this.darkMode = darkMode || false - - this.handleChainChanged = this.handleChainChanged.bind(this) - this.handleAccountsChanged = this.handleAccountsChanged.bind(this) - } - - public async activate(): Promise { - if (window.ethereum && window.ethereum.isCoinbaseWallet === true) { - // user is in the dapp browser on Coinbase Wallet - this.provider = window.ethereum - } else if (!this.walletLink) { - const WalletLink = await import('walletlink').then(m => m?.default ?? m) - this.walletLink = new WalletLink({ - appName: this.appName, - darkMode: this.darkMode, - ...(this.appLogoUrl ? { appLogoUrl: this.appLogoUrl } : {}), - }) - this.provider = this.walletLink.makeWeb3Provider(this.url, CHAIN_ID) - } - - const accounts = await this.provider.request({ - method: 'eth_requestAccounts', - }) - const account = accounts[0] - - this.provider.on('chainChanged', this.handleChainChanged) - this.provider.on('accountsChanged', this.handleAccountsChanged) - - return { provider: this.provider, account: account } - } - - public async getProvider(): Promise { - return this.provider - } - - public async getChainId(): Promise { - return this.provider.chainId - } - - public async getAccount(): Promise { - const accounts = await this.provider.request({ - method: 'eth_requestAccounts', - }) - return accounts[0] - } - - public deactivate() { - this.provider.removeListener('chainChanged', this.handleChainChanged) - this.provider.removeListener('accountsChanged', this.handleAccountsChanged) - } - - public async close() { - this.provider.close() - this.emitDeactivate() - } - - public changeChainId(networkDetails: NetworkDetails, account?: string | undefined) { - return this.provider - .request({ - method: 'wallet_switchEthereumChain', - params: [{ chainId: networkDetails.chainId }], - }) - .catch((error: any) => { - if (error.code !== 4902) { - console.error('error switching to chain id', networkDetails.chainId, error) - } - this.provider - .request({ - method: 'wallet_addEthereumChain', - params: [{ ...networkDetails }, account], - }) - .catch((error: any) => { - console.error('error adding chain with id', networkDetails.chainId, error) - }) - }) - } - - private handleChainChanged(chainId: number | string): void { - this.emitUpdate({ chainId: chainId }) - } - - private handleAccountsChanged(accounts: string[]): void { - this.emitUpdate({ account: accounts[0] }) - } -} diff --git a/src/connectors/index.ts b/src/connectors/index.ts index 667d3e1e4..df78236f8 100644 --- a/src/connectors/index.ts +++ b/src/connectors/index.ts @@ -1,82 +1,98 @@ import { ChainId } from '@swapr/sdk' -import { InjectedConnector } from '@web3-react/injected-connector' -import { providers } from 'ethers' +import { CoinbaseWallet } from '@web3-react/coinbase-wallet' +import { initializeConnector, Web3ReactHooks } from '@web3-react/core' +import { MetaMask } from '@web3-react/metamask' +import { Network } from '@web3-react/network' +import { Connector } from '@web3-react/types' +import { WalletConnect } from '@web3-react/walletconnect' -import swprLogo from '../assets/images/swpr-logo.png' -import getLibrary from '../utils/getLibrary' -import { CustomNetworkConnector } from './CustomNetworkConnector' -import { CustomWalletConnectConnector } from './CustomWalletConnectConnector' -import { CustomWalletLinkConnector } from './CustomWalletLinkConnector' +import SWAPR_LOGO from './../assets/images/swapr.svg' +import { ConnectorType, RPC_URLS } from './../constants' -export const INFURA_PROJECT_ID = '0ebf4dd05d6740f482938b8a80860d13' +export interface Connection { + connector: Connector + hooks: Web3ReactHooks + type: ConnectorType +} + +function onError(error: Error) { + console.debug(`web3-react error: ${error}`) +} -export const network = new CustomNetworkConnector({ - urls: { - [ChainId.MAINNET]: `https://mainnet.infura.io/v3/${INFURA_PROJECT_ID}`, - [ChainId.XDAI]: 'https://rpc.gnosischain.com/', - [ChainId.ARBITRUM_ONE]: 'https://arb1.arbitrum.io/rpc', - [ChainId.POLYGON]: 'https://polygon-rpc.com/', - [ChainId.ARBITRUM_GOERLI]: 'https://goerli-rollup.arbitrum.io/rpc', - [ChainId.OPTIMISM_MAINNET]: 'https://mainnet.optimism.io', - [ChainId.OPTIMISM_GOERLI]: 'https://goerli.optimism.io', - [ChainId.BSC_MAINNET]: 'https://bsc-dataseed.binance.org/', - }, - defaultChainId: ChainId.MAINNET, -}) +// Network +export const [web3Network, web3NetworkHooks] = initializeConnector( + actions => + new Network({ + actions, + urlMap: RPC_URLS, + defaultChainId: ChainId.MAINNET, + }) +) -export const injected = new InjectedConnector({ - supportedChainIds: [ - ChainId.MAINNET, - ChainId.RINKEBY, - ChainId.ARBITRUM_ONE, - ChainId.ARBITRUM_RINKEBY, - ChainId.XDAI, - ChainId.POLYGON, - ChainId.ARBITRUM_GOERLI, - ChainId.GOERLI, - ChainId.OPTIMISM_MAINNET, - ChainId.OPTIMISM_GOERLI, - ChainId.BSC_MAINNET, - ], -}) +export const networkConnection: Connection = { + connector: web3Network, + hooks: web3NetworkHooks, + type: ConnectorType.NETWORK, +} -// mainnet only -export const walletConnect = new CustomWalletConnectConnector({ - rpc: { - [ChainId.BSC_MAINNET]: 'https://bsc-dataseed.binance.org/', - [ChainId.OPTIMISM_MAINNET]: 'https://mainnet.optimism.io', - [ChainId.POLYGON]: 'https://polygon-rpc.com', - [ChainId.ARBITRUM_ONE]: 'https://arb1.arbitrum.io/rpc', - [ChainId.XDAI]: 'https://rpc.gnosischain.com/', - [ChainId.MAINNET]: `https://mainnet.infura.io/v3/${INFURA_PROJECT_ID}`, - }, - bridge: 'https://bridge.walletconnect.org', - qrcode: true, - pollingInterval: 15000, -}) +// MetaMask +export const [metaMask, metaMaskHooks] = initializeConnector(actions => new MetaMask({ actions, onError })) -let networkLibrary: providers.Web3Provider | undefined -export function getNetworkLibrary(): providers.Web3Provider { - return (networkLibrary = networkLibrary ?? getLibrary(network.provider)) +export const metaMaskConnection: Connection = { + connector: metaMask, + hooks: metaMaskHooks, + type: ConnectorType.METAMASK, } -// walletLink implements Metamask's RPC and should respond to most it's methods: window.ethereum.isMetaMask === true -// More info: https://github.com/walletlink/walletlink -export const walletLink = new CustomWalletLinkConnector({ - url: `https://mainnet.infura.io/v3/${INFURA_PROJECT_ID}`, - appName: 'Swapr', - appLogoUrl: swprLogo, - supportedChainIds: [ - ChainId.MAINNET, - ChainId.RINKEBY, - ChainId.ARBITRUM_ONE, - ChainId.ARBITRUM_RINKEBY, - ChainId.XDAI, - ChainId.POLYGON, - ChainId.ARBITRUM_GOERLI, - ChainId.OPTIMISM_MAINNET, - ChainId.OPTIMISM_GOERLI, - ChainId.BSC_MAINNET, - ], -}) +//Wallet Connect +export const [walletConnect, walletConnectHooks] = initializeConnector( + actions => + new WalletConnect({ + actions, + options: { + rpc: RPC_URLS, + }, + onError, + }) +) + +export const walletConnectConnection: Connection = { + connector: walletConnect, + hooks: walletConnectHooks, + type: ConnectorType.WALLET_CONNECT, +} + +// Coinbase +export const [coinbaseWallet, coinbaseWalletHooks] = initializeConnector( + actions => + new CoinbaseWallet({ + actions, + options: { + url: RPC_URLS[ChainId.MAINNET], + appName: 'Swapr', + appLogoUrl: SWAPR_LOGO, + }, + onError, + }) +) + +export const coinbaseWalletConnection: Connection = { + connector: coinbaseWallet, + hooks: coinbaseWalletHooks, + type: ConnectorType.COINBASE, +} + +export const CONNECTIONS: Connection[] = [ + metaMaskConnection, + coinbaseWalletConnection, + walletConnectConnection, + networkConnection, +] + +export const connectors: [Connector, Web3ReactHooks][] = [ + [metaMask, metaMaskHooks], + [walletConnect, walletConnectHooks], + [coinbaseWallet, coinbaseWalletHooks], + [web3Network, web3NetworkHooks], +] diff --git a/src/connectors/utils.ts b/src/connectors/utils.ts new file mode 100644 index 000000000..965a62848 --- /dev/null +++ b/src/connectors/utils.ts @@ -0,0 +1,53 @@ +import { ChainId } from '@swapr/sdk' + +import { Connector } from '@web3-react/types' + +import { ConnectorType, SUPPORTED_NETWORKS, SUPPORTED_WALLETS } from './../constants' + +import { + coinbaseWalletConnection, + CONNECTIONS, + metaMaskConnection, + networkConnection, + walletConnectConnection, +} from './index' + +export const getIsInjected = () => Boolean(window.ethereum) + +export const getIsMetaMask = () => !!window.ethereum?.isMetaMask + +export const getIsCoinbaseWallet = () => + !!(window.ethereum?.isCoinbaseWallet || window.ethereum?.selectedProvider?.isCoinbaseWallet) + +export const getConnection = (connector: Connector | ConnectorType) => { + if (connector instanceof Connector) { + const connection = CONNECTIONS.find(connection => connection.connector === connector) + if (!connection) { + throw Error('unsupported connector') + } + return connection + } + + switch (connector) { + case ConnectorType.METAMASK: + return metaMaskConnection + case ConnectorType.COINBASE: + return coinbaseWalletConnection + case ConnectorType.WALLET_CONNECT: + return walletConnectConnection + case ConnectorType.NETWORK: + return networkConnection + } +} + +export const getConnectionName = (connector: ConnectorType) => SUPPORTED_WALLETS[connector].name + +export const isChainSupportedByConnector = (connector: Connector | ConnectorType, chainId: ChainId | undefined) => { + if (!chainId) return false + if (connector instanceof Connector) { + const connectorType = getConnection(connector).type + return SUPPORTED_NETWORKS[connectorType].includes(chainId) + } + + return SUPPORTED_NETWORKS[connector].includes(chainId) +} diff --git a/src/constants/index.tsx b/src/constants/index.tsx index ec4d491ff..a238257b9 100644 --- a/src/constants/index.tsx +++ b/src/constants/index.tsx @@ -20,14 +20,11 @@ import { WXDAI, } from '@swapr/sdk' -import { AbstractConnector } from '@web3-react/abstract-connector' import { providers } from 'ethers' import { ReactNode } from 'react' -import RightArrow from '../assets/images/arrow-right.svg' import BaoswapLogo from '../assets/images/baoswap-logo.png' import PancakeSwapLogo from '../assets/images/bunny-mono.png' -import Coinbase from '../assets/images/coinbase.svg' import CoWLogo from '../assets/images/cow-protocol.svg' import CurveLogo from '../assets/images/curve-logo.png' import DFYNLogo from '../assets/images/dfyn-logo.svg' @@ -35,15 +32,16 @@ import HoneyswapLogo from '../assets/images/honeyswap-logo.svg' import LevinswapLogo from '../assets/images/levinswap-logo.svg' import SwaprLogo from '../assets/images/logo.svg' import ZeroXLogo from '../assets/images/logos/ZeroX.svg' -import Metamask from '../assets/images/metamask.png' import QuickswapLogo from '../assets/images/quickswap-logo.png' import SushiswapNewLogo from '../assets/images/sushiswap-new-logo.svg' import UniswapLogo from '../assets/images/uniswap-logo.svg' -import WalletConnect from '../assets/images/wallet-connect.svg' -import { injected, walletConnect, walletLink } from '../connectors' +import CoinbaseWalletLogo from '../assets/images/wallets/coinbase.svg' +import MetaMaskLogo from '../assets/images/wallets/metamask.png' +import WalletConnectLogo from '../assets/images/wallets/wallet-connect.svg' export const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000' export const SOCKET_NATIVE_TOKEN_ADDRESS = '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee' +export const INFURA_PROJECT_ID = '0ebf4dd05d6740f482938b8a80860d13' // a list of tokens by chain type ChainTokenList = { @@ -243,61 +241,82 @@ export const PINNED_PAIRS: { [DAI[ChainId.MAINNET], USDT[ChainId.MAINNET]], ], } - +export const MAINNET_PROVIDER = new providers.JsonRpcProvider(`https://mainnet.infura.io/v3/${INFURA_PROJECT_ID}`) export const ARBITRUM_ONE_PROVIDER = new providers.JsonRpcProvider('https://arb1.arbitrum.io/rpc') +export enum ConnectorType { + METAMASK = 'METAMASK', + COINBASE = 'COINBASE', + WALLET_CONNECT = 'WALLET_CONNECT', + NETWORK = 'NETWORK', +} + export interface WalletInfo { - connector?: AbstractConnector name: string - iconName: string + logo: string description: string - href: string | null + link: string | null color: string - primary?: true mobile?: true mobileOnly?: true } export const SUPPORTED_WALLETS: { [key: string]: WalletInfo } = { - INJECTED: { - connector: injected, - name: 'Injected', - iconName: RightArrow, - description: 'Injected web3 provider.', - href: null, - color: '#010101', - primary: true, - }, - METAMASK: { - connector: injected, + [ConnectorType.METAMASK]: { name: 'MetaMask', - iconName: Metamask, + logo: MetaMaskLogo, description: 'Easy-to-use browser extension.', - href: null, + link: 'https://metamask.io/', color: '#E8831D', mobile: true, }, - WALLET_CONNECT: { - connector: walletConnect, + [ConnectorType.COINBASE]: { + name: 'Coinbase Wallet', + logo: CoinbaseWalletLogo, + description: 'Connect using Coinbase Wallet.', + link: null, + color: '#4196FC', + mobile: true, + }, + [ConnectorType.WALLET_CONNECT]: { name: 'WalletConnect', - iconName: WalletConnect, + logo: WalletConnectLogo, description: 'Connect to Trust Wallet, Rainbow Wallet and more...', - href: null, + link: null, color: '#4196FC', mobile: true, }, - COINBASE: { - connector: walletLink, - name: 'Coinbase Wallet', - iconName: Coinbase, - description: 'Connect using Coinbase Wallet.', - href: null, - color: '#4196FC', + [ConnectorType.NETWORK]: { + name: 'Network', + logo: '', + description: 'Web3 Network', + link: null, + color: '#000000', mobile: true, }, } -export const NetworkContextName = 'NETWORK' +export const BACKFILLABLE_WALLETS = [ConnectorType.METAMASK, ConnectorType.COINBASE, ConnectorType.WALLET_CONNECT] + +const getSupportedChainsByConnector = () => { + const CONNECTOR_SUPPORTED_NETWORKS: { [key in ConnectorType]: ChainId[] } = { + COINBASE: [], + METAMASK: [], + NETWORK: [], + WALLET_CONNECT: [], + } + + const networks = Object.values(ChainId).filter(v => typeof v !== 'string') as ChainId[] + + // note: if network is NOT supported by connector it has to be excluded + for (const connector of Object.values(ConnectorType)) { + CONNECTOR_SUPPORTED_NETWORKS[connector] = networks + } + + return CONNECTOR_SUPPORTED_NETWORKS +} + +export const SUPPORTED_NETWORKS = getSupportedChainsByConnector() // default allowed slippage, in bips export const INITIAL_ALLOWED_SLIPPAGE = 50 @@ -348,7 +367,6 @@ export interface NetworkDetails { } export interface NetworkOptionalDetails { - iconUrls?: string[] // Currently ignored. partnerChainId?: ChainId //arbitrum chainId if supported isArbitrum: boolean } @@ -488,6 +506,15 @@ export const NETWORK_DETAIL: { [chainId: number]: NetworkDetails } = { }, } +export const RPC_URLS: { [chainId: number]: string } = { + [ChainId.MAINNET]: `https://mainnet.infura.io/v3/${INFURA_PROJECT_ID}`, + [ChainId.XDAI]: 'https://rpc.gnosischain.com/', + [ChainId.ARBITRUM_ONE]: 'https://arb1.arbitrum.io/rpc', + [ChainId.POLYGON]: 'https://polygon-rpc.com/', + [ChainId.RINKEBY]: 'https://rinkeby.infura.io/v3', + [ChainId.ARBITRUM_RINKEBY]: 'https://rinkeby.arbitrum.io/rpc', +} + export const NETWORK_OPTIONAL_DETAIL: { [chainId: number]: NetworkOptionalDetails } = { diff --git a/src/data/Allowances.ts b/src/data/Allowances.ts index f82b9cc9e..813919926 100644 --- a/src/data/Allowances.ts +++ b/src/data/Allowances.ts @@ -4,9 +4,9 @@ import { BigNumber, constants } from 'ethers' import { useMemo } from 'react' import { ERC20_INTERFACE } from '../constants/abis/erc20' -import { useActiveWeb3React } from '../hooks' import { useMulticallContract, useTokenContract } from '../hooks/useContract' import { useNativeCurrency } from '../hooks/useNativeCurrency' +import { useWeb3ReactCore } from '../hooks/useWeb3ReactCore' import { useMultipleContractSingleData, useSingleCallResult, @@ -60,7 +60,7 @@ export function useTokenAllowancesForMultipleSpenders( owner?: string, spenders?: string[] ): CurrencyAmount[] | undefined { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const nativeCurrency = useNativeCurrency() const contract = useTokenContract(token?.address, false) diff --git a/src/data/Reserves.ts b/src/data/Reserves.ts index ff042c8b8..6497e8c19 100644 --- a/src/data/Reserves.ts +++ b/src/data/Reserves.ts @@ -5,9 +5,9 @@ import { Currency, Pair, TokenAmount, UniswapV2RoutablePlatform } from '@swapr/s import { BigNumber } from 'ethers' import { useMemo } from 'react' -import { useActiveWeb3React } from '../hooks' import { useToken } from '../hooks/Tokens' import { usePairContract, useTokenContract } from '../hooks/useContract' +import { useWeb3ReactCore } from '../hooks/useWeb3ReactCore' import { useFeesState } from '../state/fees/hooks' import { useMultipleContractSingleData, useSingleCallResult } from '../state/multicall/hooks' import { wrappedCurrency } from '../utils/wrappedCurrency' @@ -25,7 +25,7 @@ export function usePairs( currencies: [Currency | undefined, Currency | undefined][], platform: UniswapV2RoutablePlatform = UniswapV2RoutablePlatform.SWAPR ): [PairState, Pair | null][] { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const tokens = useMemo( () => diff --git a/src/hooks/Tokens.ts b/src/hooks/Tokens.ts index 730b87ed2..7ff133409 100644 --- a/src/hooks/Tokens.ts +++ b/src/hooks/Tokens.ts @@ -18,12 +18,11 @@ import { useUserAddedPairs, useUserAddedTokens } from '../state/user/hooks' import { isAddress } from '../utils' import { useBytes32TokenContract, useTokenContract, useWrappingToken } from './useContract' import { useNativeCurrency } from './useNativeCurrency' - -import { useActiveWeb3React } from './index' +import { useWeb3ReactCore } from './useWeb3ReactCore' // reduce token map into standard address <-> Token mapping, optionally include user added tokens function useTokensFromMap(tokenMap: TokenAddressMap, includeUserAdded: boolean): { [address: string]: Token } { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const userAddedTokens = useUserAddedTokens() return useMemo(() => { @@ -77,7 +76,7 @@ export function useUnsupportedTokens(): { [address: string]: Token } { export function useSearchInactiveTokenLists(search: string | undefined, minResults = 10): WrappedTokenInfo[] { const lists = useAllLists() const inactiveUrls = useInactiveListUrls() - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const activeTokens = useAllTokens() return useMemo(() => { if (!search || search.trim().length === 0) return [] @@ -140,7 +139,7 @@ export function parseStringOrBytes32( // null if loading // otherwise returns the token export function useToken(tokenAddress?: string): Token | undefined | null { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const tokens = useAllTokens() const nativeCurrency = useNativeCurrency() const nativeCurrencyWrapper = useWrappingToken(nativeCurrency) diff --git a/src/hooks/Trades.ts b/src/hooks/Trades.ts index 65adf1757..e95148373 100644 --- a/src/hooks/Trades.ts +++ b/src/hooks/Trades.ts @@ -11,22 +11,25 @@ import { import { useMemo } from 'react' +import { isChainSupportedByConnector } from '../connectors/utils' import { BASES_TO_CHECK_TRADES_AGAINST } from '../constants' import { PairState, usePairs } from '../data/Reserves' import { useIsMultihop, useUserSlippageTolerance } from '../state/user/hooks' import { sortTradesByExecutionPrice } from '../utils/prices' import { wrappedCurrency } from '../utils/wrappedCurrency' - -import { useActiveWeb3React } from './index' +import { useWeb3ReactCore } from './useWeb3ReactCore' function useAllCommonPairs( currencyA?: Currency, currencyB?: Currency, platform: UniswapV2RoutablePlatform = UniswapV2RoutablePlatform.SWAPR ): Pair[] { - const { chainId } = useActiveWeb3React() + const { chainId, connector } = useWeb3ReactCore() - const bases: Token[] = useMemo(() => (chainId ? BASES_TO_CHECK_TRADES_AGAINST[chainId] : []), [chainId]) + const bases: Token[] = useMemo( + () => (chainId && isChainSupportedByConnector(connector, chainId) ? BASES_TO_CHECK_TRADES_AGAINST[chainId] : []), + [chainId, connector] + ) const [tokenA, tokenB] = chainId ? [wrappedCurrency(currencyA, chainId), wrappedCurrency(currencyB, chainId)] @@ -86,7 +89,7 @@ export function useTradeExactInUniswapV2( currencyOut?: Currency, platform: UniswapV2RoutablePlatform = UniswapV2RoutablePlatform.SWAPR ): Trade | undefined { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const allowedPairs = useAllCommonPairs(currencyAmountIn?.currency, currencyOut, platform) const multihop = useIsMultihop() const userSlippageTolerance = useUserSlippageTolerance() @@ -119,7 +122,7 @@ export function useTradeExactOutUniswapV2( currencyAmountOut?: CurrencyAmount, platform: UniswapV2RoutablePlatform = UniswapV2RoutablePlatform.SWAPR ): Trade | undefined { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const allowedPairs = useAllCommonPairs(currencyIn, currencyAmountOut?.currency, platform) const multihop = useIsMultihop() const userSlippageTolerance = useUserSlippageTolerance() diff --git a/src/hooks/index.ts b/src/hooks/index.ts deleted file mode 100644 index f650b36aa..000000000 --- a/src/hooks/index.ts +++ /dev/null @@ -1,94 +0,0 @@ -import { Web3Provider } from '@ethersproject/providers' -import { ChainId } from '@swapr/sdk' - -import { UnsupportedChainIdError, useWeb3React as useWeb3ReactCore } from '@web3-react/core' -import { Web3ReactContextInterface } from '@web3-react/core/dist/types' -import { useEffect, useState } from 'react' -import { isMobile } from 'react-device-detect' - -import { injected } from '../connectors' -import { NetworkContextName } from '../constants' - -export function useActiveWeb3React(): Web3ReactContextInterface & { chainId?: ChainId } { - const context = useWeb3ReactCore() - const contextNetwork = useWeb3ReactCore(NetworkContextName) - return context.active ? context : contextNetwork -} - -export function useEagerConnect() { - const { activate, active } = useWeb3ReactCore() // specifically using useWeb3ReactCore because of what this hook does - const [tried, setTried] = useState(false) - - useEffect(() => { - injected.isAuthorized().then(isAuthorized => { - if (isAuthorized) { - activate(injected, undefined, true).catch(() => { - setTried(true) - }) - } else { - if (isMobile && window.ethereum) { - activate(injected, undefined, true).catch(() => { - setTried(true) - }) - } else { - setTried(true) - } - } - }) - }, [activate]) // intentionally only running on mount (make sure it's only mounted once :)) - - // if the connection worked, wait until we get confirmation of that to flip the flag - useEffect(() => { - if (active) { - setTried(true) - } - }, [active]) - - return tried -} - -/** - * Use for network and injected - logs user in - * and out after checking what network theyre on - */ -export function useInactiveListener(suppress = false) { - const { active, error, activate } = useWeb3ReactCore() // specifically using useWeb3React because of what this hook does - - useEffect(() => { - const { ethereum } = window - - if (ethereum && ethereum.on && !active && !error && !suppress) { - const handleChainChanged = () => { - // eat errors - activate(injected, undefined, true).catch(error => { - console.error('Failed to activate after chain changed', error) - }) - } - - const handleAccountsChanged = (accounts: string[]) => { - if (accounts.length > 0) { - // eat errors - activate(injected, undefined, true).catch(error => { - console.error('Failed to activate after accounts changed', error) - }) - } - } - - ethereum.on('chainChanged', handleChainChanged) - ethereum.on('accountsChanged', handleAccountsChanged) - - return () => { - if (ethereum.removeListener) { - ethereum.removeListener('chainChanged', handleChainChanged) - ethereum.removeListener('accountsChanged', handleAccountsChanged) - } - } - } - return undefined - }, [active, error, suppress, activate]) -} - -export function useUnsupportedChainIdError(): boolean { - const { error } = useWeb3ReactCore() - return error instanceof UnsupportedChainIdError -} diff --git a/src/hooks/singleSidedStakeCampaigns/useSingleSidedCampaign.ts b/src/hooks/singleSidedStakeCampaigns/useSingleSidedCampaign.ts index 1e6961e94..daea8979d 100644 --- a/src/hooks/singleSidedStakeCampaigns/useSingleSidedCampaign.ts +++ b/src/hooks/singleSidedStakeCampaigns/useSingleSidedCampaign.ts @@ -2,18 +2,18 @@ import { SingleSidedLiquidityMiningCampaign, Token } from '@swapr/sdk' import { useMemo } from 'react' -import { useActiveWeb3React } from '..' import { SubgraphSingleSidedStakingCampaign } from '../../apollo' import { useGetSingleSidedStakingCampaignQuery } from '../../graphql/generated/schema' import { toSingleSidedStakeCampaign } from '../../utils/liquidityMining' import { useNativeCurrency } from '../useNativeCurrency' +import { useWeb3ReactCore } from '../useWeb3ReactCore' export function useSingleSidedCampaign(campaginAddress: string): { loading: boolean singleSidedStakingCampaign: SingleSidedLiquidityMiningCampaign | undefined } { //const hardcodedShit = '0x26358e62c2eded350e311bfde51588b8383a9315' - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const nativeCurrency = useNativeCurrency() const { data, loading, error } = useGetSingleSidedStakingCampaignQuery({ variables: { diff --git a/src/hooks/singleSidedStakeCampaigns/useSwaprSingleSidedStakeCampaigns.ts b/src/hooks/singleSidedStakeCampaigns/useSwaprSingleSidedStakeCampaigns.ts index ae4014608..ba512b8e1 100644 --- a/src/hooks/singleSidedStakeCampaigns/useSwaprSingleSidedStakeCampaigns.ts +++ b/src/hooks/singleSidedStakeCampaigns/useSwaprSingleSidedStakeCampaigns.ts @@ -2,13 +2,13 @@ import { SingleSidedLiquidityMiningCampaign, Token } from '@swapr/sdk' import { useMemo } from 'react' -import { useActiveWeb3React } from '..' import { SubgraphSingleSidedStakingCampaign } from '../../apollo' import { PairsFilterType } from '../../components/Pool/ListFilter' import { useGetSingleSidedStakingCampaignsQuery } from '../../graphql/generated/schema' import { toSingleSidedStakeCampaign } from '../../utils/liquidityMining' import { useSWPRToken } from '../swpr/useSWPRToken' import { useNativeCurrency } from '../useNativeCurrency' +import { useWeb3ReactCore } from '../useWeb3ReactCore' export function useSwaprSinglelSidedStakeCampaigns( filterToken?: Token, @@ -18,7 +18,7 @@ export function useSwaprSinglelSidedStakeCampaigns( data: SingleSidedLiquidityMiningCampaign | undefined stakedAmount?: string } { - const { chainId, account } = useActiveWeb3React() + const { chainId, account } = useWeb3ReactCore() const nativeCurrency = useNativeCurrency() const subgraphAccountId = account?.toLowerCase() || '' const filterTokenAddress = filterToken?.address?.toLowerCase() diff --git a/src/hooks/swpr/useSWPRToken.ts b/src/hooks/swpr/useSWPRToken.ts index 1abf09563..064c271d4 100644 --- a/src/hooks/swpr/useSWPRToken.ts +++ b/src/hooks/swpr/useSWPRToken.ts @@ -2,10 +2,10 @@ import { SWPR, Token } from '@swapr/sdk' import { useMemo } from 'react' -import { useActiveWeb3React } from '..' +import { useWeb3ReactCore } from '../useWeb3ReactCore' export const useSWPRToken = () => { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() return useMemo(() => { const SWPRConfig = SWPR[chainId || 0] diff --git a/src/hooks/useAllLiquidityMiningCampaigns.ts b/src/hooks/useAllLiquidityMiningCampaigns.ts index 9b3d33a63..77f3a5a2b 100644 --- a/src/hooks/useAllLiquidityMiningCampaigns.ts +++ b/src/hooks/useAllLiquidityMiningCampaigns.ts @@ -18,15 +18,14 @@ import { import { useSWPRToken } from './swpr/useSWPRToken' import { useKpiTokens } from './useKpiTokens' import { useNativeCurrency } from './useNativeCurrency' - -import { useActiveWeb3React } from './index' +import { useWeb3ReactCore } from './useWeb3ReactCore' export function useAllLiquidityMiningCampaigns(pair?: Pair, dataFilter?: PairsFilterType) { const token0Address = pair?.token0?.address.toLowerCase() const token1Address = pair?.token1?.address.toLowerCase() const pairAddress = pair?.liquidityToken.address.toLowerCase() - const { chainId, account } = useActiveWeb3React() + const { chainId, account } = useWeb3ReactCore() const subgraphAccountId = account?.toLowerCase() ?? '' diff --git a/src/hooks/useAllPairs.ts b/src/hooks/useAllPairs.ts index f7128891f..696d4c685 100644 --- a/src/hooks/useAllPairs.ts +++ b/src/hooks/useAllPairs.ts @@ -4,11 +4,10 @@ import { getAddress, parseUnits } from 'ethers/lib/utils' import { useMemo } from 'react' import { useGetPairsQuery } from '../graphql/generated/schema' - -import { useActiveWeb3React } from './index' +import { useWeb3ReactCore } from './useWeb3ReactCore' export function useAllPairs(): { loading: boolean; pairs: Pair[] } { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const { loading, data, error } = useGetPairsQuery() return useMemo(() => { diff --git a/src/hooks/useAllPairsWithNonExpiredLiquidityMiningCampaignsAndLiquidityAndStakingIndicator.ts b/src/hooks/useAllPairsWithNonExpiredLiquidityMiningCampaignsAndLiquidityAndStakingIndicator.ts index ebf030b71..1c47b4576 100644 --- a/src/hooks/useAllPairsWithNonExpiredLiquidityMiningCampaignsAndLiquidityAndStakingIndicator.ts +++ b/src/hooks/useAllPairsWithNonExpiredLiquidityMiningCampaignsAndLiquidityAndStakingIndicator.ts @@ -16,8 +16,7 @@ import { } from '../utils/liquidityMining' import { useKpiTokens } from './useKpiTokens' import { useNativeCurrency } from './useNativeCurrency' - -import { useActiveWeb3React } from './index' +import { useWeb3ReactCore } from './useWeb3ReactCore' const PAGE_SIZE = 1000 @@ -81,7 +80,7 @@ export function useAllPairsWithNonExpiredLiquidityMiningCampaignsAndLiquidityAnd staked: boolean }[] } { - const { chainId, account } = useActiveWeb3React() + const { chainId, account } = useWeb3ReactCore() const tokensInCurrentChain = useAllTokensFromActiveListsOnCurrentChain() const nativeCurrency = useNativeCurrency() diff --git a/src/hooks/useApproveCallback.ts b/src/hooks/useApproveCallback.ts index 7ef699727..cdfa2b7e7 100644 --- a/src/hooks/useApproveCallback.ts +++ b/src/hooks/useApproveCallback.ts @@ -24,8 +24,7 @@ import { calculateGasMargin } from '../utils' import { computeSlippageAdjustedAmounts } from '../utils/prices' import { useTokenContract } from './useContract' import { useNativeCurrency } from './useNativeCurrency' - -import { useActiveWeb3React } from './index' +import { useWeb3ReactCore } from './useWeb3ReactCore' export enum ApprovalState { UNKNOWN, @@ -39,7 +38,7 @@ export function useApproveCallback( amountToApprove?: CurrencyAmount, spender?: string ): [ApprovalState, () => Promise] { - const { account } = useActiveWeb3React() + const { account } = useWeb3ReactCore() const token = amountToApprove instanceof TokenAmount ? amountToApprove.token : undefined const currentAllowance = useTokenAllowance(token, account ?? undefined, spender) const pendingApproval = useHasPendingApproval(token?.address, spender) @@ -116,7 +115,7 @@ export function useApproveCallback( // wraps useApproveCallback in the context of a swap export function useApproveCallbackFromTrade(trade?: Trade /* allowedSlippage = 0 */) { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const amountToApprove = useMemo(() => { if (trade) { diff --git a/src/hooks/useBestAPY.ts b/src/hooks/useBestAPY.ts index 2d7bbe841..442bd7db6 100644 --- a/src/hooks/useBestAPY.ts +++ b/src/hooks/useBestAPY.ts @@ -13,14 +13,13 @@ import { } from '../utils/liquidityMining' import { useKpiTokens } from './useKpiTokens' import { useNativeCurrency } from './useNativeCurrency' - -import { useActiveWeb3React } from '.' +import { useWeb3ReactCore } from './useWeb3ReactCore' export function useBestAPY(pair?: Pair | null): { loading: boolean bestAPY?: Percent } { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const tokensInCurrentChain = useAllTokensFromActiveListsOnCurrentChain() const nativeCurrency = useNativeCurrency() const memoizedLowerTimeLimit = useMemo(() => getLowerTimeLimit(), []) diff --git a/src/hooks/useCarrotSubgraphClient.ts b/src/hooks/useCarrotSubgraphClient.ts index 46ed5f5b9..c9ed6b83e 100644 --- a/src/hooks/useCarrotSubgraphClient.ts +++ b/src/hooks/useCarrotSubgraphClient.ts @@ -1,10 +1,9 @@ import { ApolloClient, NormalizedCacheObject } from '@apollo/client' import { carrotSubgraphClient } from '../apollo/client' - -import { useActiveWeb3React } from './index' +import { useWeb3ReactCore } from './useWeb3ReactCore' export function useCarrotSubgraphClient(): ApolloClient | undefined { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() return chainId ? carrotSubgraphClient[chainId] : undefined } diff --git a/src/hooks/useChains.ts b/src/hooks/useChains.ts index 92f19ddf6..f7ba17990 100644 --- a/src/hooks/useChains.ts +++ b/src/hooks/useChains.ts @@ -1,10 +1,9 @@ import { useMemo } from 'react' import { getChainPair } from '../utils/arbitrum' - -import { useActiveWeb3React } from './index' +import { useWeb3ReactCore } from './useWeb3ReactCore' export const useChains = () => { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() return useMemo(() => getChainPair(chainId), [chainId]) } diff --git a/src/hooks/useContract.ts b/src/hooks/useContract.ts index 08c3ed84e..6a01e8918 100644 --- a/src/hooks/useContract.ts +++ b/src/hooks/useContract.ts @@ -34,22 +34,21 @@ import WMATIC_ABI from '../constants/abis/wmatic.json' import WXDAI_ABI from '../constants/abis/wxdai.json' import { getContract, getProviderOrSigner, isAddress } from '../utils' import { useNativeCurrency } from './useNativeCurrency' - -import { useActiveWeb3React } from './index' +import { useWeb3ReactCore } from './useWeb3ReactCore' // returns null on errors function useContract(address: string | undefined, ABI: any, withSignerIfPossible = true): Contract | null { - const { library, account } = useActiveWeb3React() + const { provider, account } = useWeb3ReactCore() return useMemo(() => { - if (!address || !ABI || !library) return null + if (!address || !ABI || !provider) return null try { - return getContract(address, ABI, library, withSignerIfPossible && account ? account : undefined) + return getContract(address, ABI, provider, withSignerIfPossible && account ? account : undefined) } catch (error) { console.error('Failed to get contract', error) return null } - }, [address, ABI, library, withSignerIfPossible, account]) + }, [address, ABI, provider, withSignerIfPossible, account]) } export function useTokenContract(tokenAddress?: string, withSignerIfPossible?: boolean): Contract | null { @@ -57,7 +56,7 @@ export function useTokenContract(tokenAddress?: string, withSignerIfPossible?: b } export function useWrappingToken(currency?: Currency, chainId?: ChainId): Token | undefined { - const { chainId: activeChainId } = useActiveWeb3React() + const { chainId: activeChainId } = useWeb3ReactCore() const selectedChainId = chainId ?? activeChainId if (!selectedChainId || !currency || !Currency.isNative(currency)) return undefined @@ -65,7 +64,7 @@ export function useWrappingToken(currency?: Currency, chainId?: ChainId): Token } function useWrappingTokenAbi(token?: Token): any | undefined { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() if (!chainId) return undefined switch (token) { case WETH[chainId]: @@ -87,7 +86,7 @@ export function useNativeCurrencyWrapperContract(withSignerIfPossible?: boolean) } export function useArgentWalletDetectorContract(): Contract | null { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() return useContract( chainId === ChainId.MAINNET ? ARGENT_WALLET_DETECTOR_MAINNET_ADDRESS : undefined, ARGENT_WALLET_DETECTOR_ABI, @@ -96,7 +95,7 @@ export function useArgentWalletDetectorContract(): Contract | null { } export function useENSRegistrarContract(withSignerIfPossible?: boolean): Contract | null { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() let address: string | undefined if (chainId) { switch (chainId) { @@ -122,12 +121,12 @@ export function usePairContract(pairAddress?: string, withSignerIfPossible?: boo } export function useMulticallContract(): Contract | null { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() return useContract(chainId && MULTICALL2_ADDRESS[chainId], MULTICALL2_ABI, false) } export function useStakingRewardsDistributionFactoryContract(withSignerIfPossible?: boolean): Contract | null { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() return useContract( chainId && STAKING_REWARDS_FACTORY_ADDRESS[chainId], STAKING_REWARDS_FACTORY_ABI, @@ -143,28 +142,28 @@ export function useStakingRewardsDistributionContract( } export function useSWPRClaimerContract(): Contract | null { - const { library, chainId, account } = useActiveWeb3React() + const { provider, chainId, account } = useWeb3ReactCore() return useMemo(() => { const address = SWPR_CLAIMER_ADDRESS[ChainId.ARBITRUM_ONE] const ABI = SWPR_CLAIMER_ABI - if (!address || !isAddress(address) || address === constants.AddressZero || !ABI || !library) return null + if (!address || !isAddress(address) || address === constants.AddressZero || !ABI || !provider) return null try { return new Contract( address, ABI, account - ? (getProviderOrSigner(chainId === ChainId.ARBITRUM_ONE ? library : ARBITRUM_ONE_PROVIDER, account) as any) + ? (getProviderOrSigner(chainId === ChainId.ARBITRUM_ONE ? provider : ARBITRUM_ONE_PROVIDER, account) as any) : account ) } catch (error) { console.error('Failed to get contract', error) return null } - }, [library, chainId, account]) + }, [provider, account, chainId]) } export function useSWPRConverterContract(withSignerIfPossible?: boolean): Contract | null { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const address = useMemo(() => (chainId ? SWPR_CONVERTER_ADDRESS[chainId] : undefined), [chainId]) return useContract(address, SWPR_CONVERTER_ABI, withSignerIfPossible) } diff --git a/src/hooks/useENSAvatar.ts b/src/hooks/useENSAvatar.ts index 592535c29..ef84ac7b8 100644 --- a/src/hooks/useENSAvatar.ts +++ b/src/hooks/useENSAvatar.ts @@ -1,7 +1,8 @@ -import { useWeb3React } from '@web3-react/core' import { CID } from 'multiformats/cid' import { useEffect, useState } from 'react' +import { useWeb3ReactCore } from './useWeb3ReactCore' + const IPFS_GATEWAY = 'https://ipfs.io/ipfs/' export interface ENSAvatarData { @@ -50,7 +51,7 @@ const supportedENSChainIds = [1, 4] export function useENSAvatar(ensName?: string | null) { const [avatar, setAvatar] = useState() const [loading, setLoading] = useState(true) - const { chainId } = useWeb3React() + const { chainId } = useWeb3ReactCore() useEffect(() => { // ENS supports Mainnet and Rinkeby diff --git a/src/hooks/useEagerlyConnect.ts b/src/hooks/useEagerlyConnect.ts new file mode 100644 index 000000000..789f386d2 --- /dev/null +++ b/src/hooks/useEagerlyConnect.ts @@ -0,0 +1,37 @@ +import { Connector } from '@web3-react/types' +import { useEffect } from 'react' +import { useSelector } from 'react-redux' + +import { AppState } from '../state' +import { networkConnection } from './../connectors' +import { getConnection } from './../connectors/utils' +import { BACKFILLABLE_WALLETS } from './../constants' + +async function connect(connector: Connector) { + try { + connector.connectEagerly ? await connector.connectEagerly() : await connector.activate() + } catch (error) { + console.debug(`web3-react eager connection error: ${error}`) + } +} + +export default function useEagerlyConnect() { + const selectedConnectorBackfilled = useSelector((state: AppState) => state.user.connector.selectedBackfilled) + const selectedConnector = useSelector((state: AppState) => state.user.connector.selected) + + useEffect(() => { + connect(networkConnection.connector) + + if (selectedConnector) { + connect(getConnection(selectedConnector).connector) + return + } + + if (!selectedConnectorBackfilled) { + BACKFILLABLE_WALLETS.map(getConnection) + .map(connection => connection.connector) + .forEach(connect) + } + // The dependency list is empty so this is only run once on mount + }, []) // eslint-disable-line react-hooks/exhaustive-deps +} diff --git a/src/hooks/useFetchListCallback.ts b/src/hooks/useFetchListCallback.ts index b0ca1b4dc..1915cf171 100644 --- a/src/hooks/useFetchListCallback.ts +++ b/src/hooks/useFetchListCallback.ts @@ -8,40 +8,22 @@ import { useDispatch } from 'react-redux' import { immediateCarrotSubgraphClients } from '../apollo/client' import carrotListLogoUrl from '../assets/images/carrot.png' -import { getNetworkLibrary } from '../connectors' -import { KPI_TOKEN_CREATORS } from '../constants' +import { KPI_TOKEN_CREATORS, MAINNET_PROVIDER } from '../constants' import { AppDispatch } from '../state' import { fetchTokenList } from '../state/lists/actions' import getTokenList from '../utils/getTokenList' import resolveENSContentHash from '../utils/resolveENSContentHash' - -import { useActiveWeb3React } from './index' +import { useWeb3ReactCore } from './useWeb3ReactCore' export function useFetchListCallback(): (listUrl: string, sendDispatch?: boolean) => Promise { - const { chainId, library } = useActiveWeb3React() const dispatch = useDispatch() - const ensResolver = useCallback( - async (ensName: string) => { - if (!library || chainId !== 1) { - const networkLibrary = getNetworkLibrary() - const network = await networkLibrary.getNetwork() - if (networkLibrary && network.chainId === 1) { - return resolveENSContentHash(ensName, networkLibrary) - } - throw new Error('Could not construct mainnet ENS resolver') - } - return resolveENSContentHash(ensName, library) - }, - [chainId, library] - ) - // note: prevent dispatch if using for list search or unsupported list return useCallback( async (listUrl: string, sendDispatch = true) => { const requestId = nanoid() sendDispatch && dispatch(fetchTokenList.pending({ requestId, url: listUrl })) - return getTokenList(listUrl, ensResolver) + return getTokenList(listUrl, (ensName: string) => resolveENSContentHash(ensName, MAINNET_PROVIDER)) .then((tokenList: TokenList) => { sendDispatch && dispatch(fetchTokenList.fulfilled({ url: listUrl, tokenList, requestId })) return tokenList @@ -52,7 +34,7 @@ export function useFetchListCallback(): (listUrl: string, sendDispatch?: boolean throw error }) }, - [dispatch, ensResolver] + [dispatch] ) } @@ -75,7 +57,7 @@ interface KpiTokensQueryResult { } export function useFetchCarrotListCallback(): (sendDispatch?: boolean) => Promise { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const dispatch = useDispatch() const validCreators = useMemo( () => diff --git a/src/hooks/useGasFeesUSD.ts b/src/hooks/useGasFeesUSD.ts index 0877f2dec..eedddeb12 100644 --- a/src/hooks/useGasFeesUSD.ts +++ b/src/hooks/useGasFeesUSD.ts @@ -8,14 +8,13 @@ import { MainnetGasPrice } from '../state/application/actions' import { useMainnetGasPrices } from '../state/application/hooks' import { useUserPreferredGasPrice } from '../state/user/hooks' import { useNativeCurrencyUSDPrice } from './useNativeCurrencyUSDPrice' - -import { useActiveWeb3React } from './index' +import { useWeb3ReactCore } from './useWeb3ReactCore' export function useGasFeesUSD(gasEstimations: (BigNumber | null)[]): { loading: boolean gasFeesUSD: (CurrencyAmount | null)[] } { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const mainnetGasPrices = useMainnetGasPrices() const [preferredGasPrice] = useUserPreferredGasPrice() const { loading: loadingNativeCurrencyUSDPrice, nativeCurrencyUSDPrice } = useNativeCurrencyUSDPrice() diff --git a/src/hooks/useGasInfo.ts b/src/hooks/useGasInfo.ts index e44b11287..692fee294 100644 --- a/src/hooks/useGasInfo.ts +++ b/src/hooks/useGasInfo.ts @@ -2,9 +2,8 @@ import { ChainId } from '@swapr/sdk' import { useEffect, useState } from 'react' -import { INFURA_PROJECT_ID } from '../connectors' - -import { useActiveWeb3React } from './index' +import { INFURA_PROJECT_ID } from '../constants' +import { useWeb3ReactCore } from './useWeb3ReactCore' interface ChainGasInfo { [chainId: number]: { @@ -80,7 +79,7 @@ const defaultGasState: Gas = { * @returns Gas prices */ export function useGasInfo(): { loading: boolean; gas: Gas } { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const [loading, setLoading] = useState(true) const [gas, setGas] = useState(defaultGasState) diff --git a/src/hooks/useIsArgentWallet.ts b/src/hooks/useIsArgentWallet.ts index 8d6be7080..747ef2424 100644 --- a/src/hooks/useIsArgentWallet.ts +++ b/src/hooks/useIsArgentWallet.ts @@ -1,10 +1,9 @@ import { NEVER_RELOAD, useSingleCallResult } from '../state/multicall/hooks' import { useArgentWalletDetectorContract } from './useContract' - -import { useActiveWeb3React } from './index' +import { useWeb3ReactCore } from './useWeb3ReactCore' export default function useIsArgentWallet(): boolean { - const { account } = useActiveWeb3React() + const { account } = useWeb3ReactCore() const argentWalletDetector = useArgentWalletDetectorContract() const call = useSingleCallResult(argentWalletDetector, 'isArgentWallet', [account ?? undefined], NEVER_RELOAD) return call?.result?.[0] ?? false diff --git a/src/hooks/useKpiTokens.ts b/src/hooks/useKpiTokens.ts index d910af66f..798c9db20 100644 --- a/src/hooks/useKpiTokens.ts +++ b/src/hooks/useKpiTokens.ts @@ -9,8 +9,7 @@ import { useMemo } from 'react' import { useGetDerivedNativeCurrencyTokensQuery } from '../graphql/generated/schema' import { useNativeCurrency } from '../hooks/useNativeCurrency' import { useCarrotSubgraphClient } from './useCarrotSubgraphClient' - -import { useActiveWeb3React } from './index' +import { useWeb3ReactCore } from './useWeb3ReactCore' const KPI_TOKENS_QUERY = gql` query kpiTokens($ids: [ID!]!) { @@ -55,7 +54,7 @@ interface KpiTokensQueryResult { } export const useKpiTokens = (addresses: string[]): { loading: boolean; kpiTokens: KpiToken[] } => { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const nativeCurrency = useNativeCurrency() const carrotSubgraphClient = useCarrotSubgraphClient() diff --git a/src/hooks/useLiquidityMiningCampaign.ts b/src/hooks/useLiquidityMiningCampaign.ts index 7b2de00d7..9a9c9bded 100644 --- a/src/hooks/useLiquidityMiningCampaign.ts +++ b/src/hooks/useLiquidityMiningCampaign.ts @@ -9,15 +9,14 @@ import { toLiquidityMiningCampaign } from '../utils/liquidityMining' import { useKpiTokens } from './useKpiTokens' import { useNativeCurrency } from './useNativeCurrency' import { usePairReserveNativeCurrency } from './usePairReserveNativeCurrency' - -import { useActiveWeb3React } from './index' +import { useWeb3ReactCore } from './useWeb3ReactCore' // the id is the campaign's smart contract address export function useLiquidityMiningCampaign( targetedPair?: Pair, id?: string ): { loading: boolean; campaign: LiquidityMiningCampaign | null; containsKpiToken: boolean } { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const { loading, error, data } = useGetLiquidityMiningCampaignQuery({ variables: { liquidityMiningCampaignId: id?.toLowerCase() || '' }, }) diff --git a/src/hooks/useLiquidityMiningCampaignPosition.ts b/src/hooks/useLiquidityMiningCampaignPosition.ts index c7b4ade51..e74c3afd0 100644 --- a/src/hooks/useLiquidityMiningCampaignPosition.ts +++ b/src/hooks/useLiquidityMiningCampaignPosition.ts @@ -6,8 +6,7 @@ import { useMemo } from 'react' import { useSingleCallResult, useSingleContractMultipleData } from '../state/multicall/hooks' import { useStakingRewardsDistributionContract } from './useContract' - -import { useActiveWeb3React } from './index' +import { useWeb3ReactCore } from './useWeb3ReactCore' interface UseLiquidityMiningCampaignUserPositionHookResult { stakedTokenAmount: PricedTokenAmount | null @@ -20,7 +19,7 @@ export function useLiquidityMiningCampaignPosition( campaign?: LiquidityMiningCampaign | SingleSidedLiquidityMiningCampaign, account?: string ): UseLiquidityMiningCampaignUserPositionHookResult { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const distributionContract = useStakingRewardsDistributionContract(campaign?.address, true) diff --git a/src/hooks/useLiquidityMiningFeatureFlag.ts b/src/hooks/useLiquidityMiningFeatureFlag.ts index 80efb86ac..a6c5b7bc9 100644 --- a/src/hooks/useLiquidityMiningFeatureFlag.ts +++ b/src/hooks/useLiquidityMiningFeatureFlag.ts @@ -1,9 +1,9 @@ import { ChainId } from '@swapr/sdk' -import { useActiveWeb3React } from './index' +import { useWeb3ReactCore } from './useWeb3ReactCore' export function useLiquidityMiningFeatureFlag(): boolean { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() return ( chainId === ChainId.RINKEBY || chainId === ChainId.XDAI || diff --git a/src/hooks/useLiquidityPositions.ts b/src/hooks/useLiquidityPositions.ts index 39be71efd..82a371c47 100644 --- a/src/hooks/useLiquidityPositions.ts +++ b/src/hooks/useLiquidityPositions.ts @@ -11,8 +11,7 @@ import { useGetUserLiquidityPositionsQuery } from '../graphql/generated/schema' import { getBestApyPairCampaign, toLiquidityMiningCampaign } from '../utils/liquidityMining' import { useKpiTokens } from './useKpiTokens' import { useNativeCurrency } from './useNativeCurrency' - -import { useActiveWeb3React } from './index' +import { useWeb3ReactCore } from './useWeb3ReactCore' interface SubgraphToken { address: string symbol: string @@ -43,7 +42,7 @@ export function useLPPairs(account?: string): { containsKpiToken: boolean }[] } { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const nativeCurrency = useNativeCurrency() const memoizedLowerTimeLimit = useMemo( () => diff --git a/src/hooks/useLpTokensUnderlyingAssets.ts b/src/hooks/useLpTokensUnderlyingAssets.ts index 9066fe0f1..4d00e2248 100644 --- a/src/hooks/useLpTokensUnderlyingAssets.ts +++ b/src/hooks/useLpTokensUnderlyingAssets.ts @@ -7,14 +7,13 @@ import { useMemo } from 'react' import { useGetPairQuery } from '../graphql/generated/schema' import type { Pair as PairType } from '../graphql/generated/schema' import { useNativeCurrency } from './useNativeCurrency' - -import { useActiveWeb3React } from './index' +import { useWeb3ReactCore } from './useWeb3ReactCore' export function useLpTokensUnderlyingAssets( pair?: Pair, lpTokensBalance?: TokenAmount ): { loading: boolean; underlyingAssets?: { token0: PricedTokenAmount; token1: PricedTokenAmount } } { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const nativeCurrency = useNativeCurrency() const { data, loading, error } = useGetPairQuery({ variables: { diff --git a/src/hooks/useNativeCurrency.ts b/src/hooks/useNativeCurrency.ts index ba06d8fd5..c5310769c 100644 --- a/src/hooks/useNativeCurrency.ts +++ b/src/hooks/useNativeCurrency.ts @@ -1,9 +1,9 @@ import { ChainId, Currency } from '@swapr/sdk' -import { useActiveWeb3React } from './index' +import { useWeb3ReactCore } from './useWeb3ReactCore' export function useNativeCurrency(chainId?: ChainId): Currency { - const { chainId: activeChainId } = useActiveWeb3React() + const { chainId: activeChainId } = useWeb3ReactCore() const selectedChainId = chainId ?? activeChainId // fallback to ether if chain id is not defined if (!selectedChainId) return Currency.ETHER diff --git a/src/hooks/useNetworkSwitch.ts b/src/hooks/useNetworkSwitch.ts index 1d4c81592..ed2443234 100644 --- a/src/hooks/useNetworkSwitch.ts +++ b/src/hooks/useNetworkSwitch.ts @@ -1,51 +1,58 @@ import { ChainId, SWPR } from '@swapr/sdk' -import { InjectedConnector } from '@web3-react/injected-connector' +import { Connector } from '@web3-react/types' import { useCallback } from 'react' +import { useDispatch } from 'react-redux' import { NavigateFunction, useLocation, useNavigate } from 'react-router-dom' -import { CustomNetworkConnector } from '../connectors/CustomNetworkConnector' -import { CustomWalletConnectConnector } from '../connectors/CustomWalletConnectConnector' -import { CustomWalletLinkConnector } from '../connectors/CustomWalletLinkConnector' -import { NETWORK_DETAIL } from '../constants' -import { switchOrAddNetwork } from '../utils' +import { networkConnection, walletConnectConnection } from '../connectors' +import { getConnection, isChainSupportedByConnector } from '../connectors/utils' +import { AppDispatch } from '../state' +import { setConnectorError } from '../state/user/actions' +import { getErrorMessage } from '../utils/getErrorMessage' +import { getNetworkInfo } from '../utils/networksList' +import { useWeb3ReactCore } from './useWeb3ReactCore' -import { useActiveWeb3React, useUnsupportedChainIdError } from '.' +const switchNetwork = async (connector: Connector, chainId: ChainId) => { + if (!isChainSupportedByConnector(connector, chainId)) + throw new Error(`Chain ${chainId} not supported for connector (${typeof connector})`) -export type UseNetworkSwitchProps = { - onSelectNetworkCallback?: () => void + if (connector === walletConnectConnection.connector || connector === networkConnection.connector) { + await connector.activate(chainId) + return + } + + const { chainName, rpcUrls, nativeCurrency, blockExplorerUrls } = getNetworkInfo(chainId) + const addChainParameter = { + chainId, + chainName, + rpcUrls, + nativeCurrency, + blockExplorerUrls, + } + await connector.activate(addChainParameter) } -export const useNetworkSwitch = ({ onSelectNetworkCallback }: UseNetworkSwitchProps = {}) => { - const { connector, chainId, account } = useActiveWeb3React() - const unsupportedChainIdError = useUnsupportedChainIdError() +export const useNetworkSwitch = () => { + const { connector } = useWeb3ReactCore() + const dispatch = useDispatch() const navigate = useNavigate() const { pathname } = useLocation() const selectNetwork = useCallback( - async (optionChainId?: ChainId) => { - if (optionChainId === undefined || (optionChainId === chainId && !unsupportedChainIdError)) return - - let changeChainIdResult: unknown - if (!account && !unsupportedChainIdError && connector instanceof CustomNetworkConnector) { - connector.changeChainId(optionChainId) - unavailableRedirect(optionChainId, navigate, pathname) - } else if (!account && unsupportedChainIdError && connector instanceof CustomNetworkConnector) - changeChainIdResult = await connector.switchUnsupportedNetwork(NETWORK_DETAIL[optionChainId]) - else if (connector instanceof InjectedConnector) - changeChainIdResult = await switchOrAddNetwork(NETWORK_DETAIL[optionChainId], account || undefined) - else if (connector instanceof CustomWalletLinkConnector) - changeChainIdResult = await connector.changeChainId(NETWORK_DETAIL[optionChainId], account || undefined) - else if (connector instanceof CustomWalletConnectConnector) { - connector.changeChainId(optionChainId) - unavailableRedirect(optionChainId, navigate, pathname) + async (chainId: ChainId) => { + try { + unavailableRedirect(chainId, navigate, pathname) + await switchNetwork(connector, chainId) + dispatch(setConnectorError({ connector: getConnection(connector).type, connectorError: undefined })) + } catch (error) { + console.error('Failed to switch networks', error) + dispatch( + setConnectorError({ connector: getConnection(connector).type, connectorError: getErrorMessage(error) }) + ) } - - if (onSelectNetworkCallback) onSelectNetworkCallback() - // success scenario - user accepts the change on the popup window - if (changeChainIdResult === null) unavailableRedirect(optionChainId, navigate, pathname) }, - [account, chainId, connector, navigate, onSelectNetworkCallback, pathname, unsupportedChainIdError] + [connector, dispatch, navigate, pathname] ) return { diff --git a/src/hooks/useNewLiquidityMiningCampaign.ts b/src/hooks/useNewLiquidityMiningCampaign.ts index dddd1ee1b..b0ef183c0 100644 --- a/src/hooks/useNewLiquidityMiningCampaign.ts +++ b/src/hooks/useNewLiquidityMiningCampaign.ts @@ -15,8 +15,7 @@ import { useMemo } from 'react' import { useNativeCurrency } from './useNativeCurrency' import { useNativeCurrencyPricedTokenAmounts } from './useTokensDerivedNativeCurrency' - -import { useActiveWeb3React } from './index' +import { useWeb3ReactCore } from './useWeb3ReactCore' export function useNewLiquidityMiningCampaign( rewards: TokenAmount[], @@ -29,7 +28,7 @@ export function useNewLiquidityMiningCampaign( stakeToken?: Token, stakePair?: Pair ): LiquidityMiningCampaign | SingleSidedLiquidityMiningCampaign | null { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const nativeCurrency = useNativeCurrency() const { pricedTokenAmounts: pricedRewardAmounts } = useNativeCurrencyPricedTokenAmounts(rewards) diff --git a/src/hooks/useOrderedConnections.ts b/src/hooks/useOrderedConnections.ts new file mode 100644 index 000000000..e12af2abf --- /dev/null +++ b/src/hooks/useOrderedConnections.ts @@ -0,0 +1,24 @@ +import { useMemo } from 'react' +import { useSelector } from 'react-redux' + +import { AppState } from '../state' +import { getConnection } from './../connectors/utils' +import { BACKFILLABLE_WALLETS, ConnectorType } from './../constants' + +export default function useOrderedConnections() { + const selectedConnector = useSelector((state: AppState) => state.user.connector.selected) + return useMemo(() => { + const orderedConnectionTypes: ConnectorType[] = [] + + // Add the `selectedConnector` to the top so it's prioritized, then add the other selectable wallets. + if (selectedConnector) { + orderedConnectionTypes.push(selectedConnector) + } + orderedConnectionTypes.push(...BACKFILLABLE_WALLETS.filter(wallet => wallet !== selectedConnector)) + + // Add network connection last as it should be the fallback. + orderedConnectionTypes.push(ConnectorType.NETWORK) + + return orderedConnectionTypes.map(getConnection) + }, [selectedConnector]) +} diff --git a/src/hooks/usePairLiquidityMiningCampaigns.ts b/src/hooks/usePairLiquidityMiningCampaigns.ts index f82f30907..15a65b517 100644 --- a/src/hooks/usePairLiquidityMiningCampaigns.ts +++ b/src/hooks/usePairLiquidityMiningCampaigns.ts @@ -15,15 +15,14 @@ import { } from '../utils/liquidityMining' import { useKpiTokens } from './useKpiTokens' import { useNativeCurrency } from './useNativeCurrency' - -import { useActiveWeb3React } from '.' +import { useWeb3ReactCore } from './useWeb3ReactCore' export function usePairLiquidityMiningCampaigns(pair?: Pair): { loading: boolean miningCampaigns: { active: MiningCampaign[]; expired: MiningCampaign[] } } { const pairAddress = pair ? pair.liquidityToken.address.toLowerCase() : undefined - const { chainId, account } = useActiveWeb3React() + const { chainId, account } = useWeb3ReactCore() const subgraphAccountId = account?.toLowerCase() || '' const nativeCurrency = useNativeCurrency() const timestamp = Math.floor(Date.now() / 1000) diff --git a/src/hooks/usePairReserveNativeCurrency.ts b/src/hooks/usePairReserveNativeCurrency.ts index d8bb34472..40f8995c0 100644 --- a/src/hooks/usePairReserveNativeCurrency.ts +++ b/src/hooks/usePairReserveNativeCurrency.ts @@ -6,11 +6,10 @@ import { useMemo } from 'react' import { useGetPairQuery } from '../graphql/generated/schema' import { useNativeCurrency } from './useNativeCurrency' - -import { useActiveWeb3React } from './index' +import { useWeb3ReactCore } from './useWeb3ReactCore' export function usePairReserveNativeCurrency(pair?: Pair): { loading: boolean; reserveNativeCurrency: CurrencyAmount } { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const nativeCurrency = useNativeCurrency() const { loading, data, error } = useGetPairQuery({ diff --git a/src/hooks/usePairTokenPriceByTimestamp.ts b/src/hooks/usePairTokenPriceByTimestamp.ts index 6524c22cb..86fa83974 100644 --- a/src/hooks/usePairTokenPriceByTimestamp.ts +++ b/src/hooks/usePairTokenPriceByTimestamp.ts @@ -10,8 +10,7 @@ import { TIMEFRAME_PROPRETIES, } from '../components/Charts/chartUtils' import { wrappedCurrency } from '../utils/wrappedCurrency' - -import { useActiveWeb3React } from '.' +import { useWeb3ReactCore } from './useWeb3ReactCore' const GET_PAIR_TOKEN_PRICES_QUERY = gql` query getPairTokenPrices($pairAddress: ID, $timestamp: BigInt, $timeframe: PairTokenPriceTimeframe) { @@ -48,7 +47,7 @@ type PairTokenPriceByTimestampProps = { } export function usePairTokenPriceByTimestamp({ currency0, currency1, dateInterval }: PairTokenPriceByTimestampProps) { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const [wrappedToken1, setWrappedToken1] = useState() const [pairAddress, setPairAddress] = useState() diff --git a/src/hooks/usePairVolume24hUSD.ts b/src/hooks/usePairVolume24hUSD.ts index 7533bf7ae..e2d67b7d8 100644 --- a/src/hooks/usePairVolume24hUSD.ts +++ b/src/hooks/usePairVolume24hUSD.ts @@ -8,8 +8,8 @@ import { useMemo } from 'react' import { subgraphBlocksClients } from '../apollo/client' import { ZERO_USD } from '../constants' -import { useActiveWeb3React } from '../hooks' import { SWPRSupportedChains } from '../utils/chainSupportsSWPR' +import { useWeb3ReactCore } from './useWeb3ReactCore' const GET_BLOCK_BY_TIMESTAMP = gql` query getBlockFromTimestamp($timestamp: String!) { @@ -52,7 +52,7 @@ const PAIR_VOLUME_TILL_BLOCK = gql` ` function useBlockByTimestamp(timestamp: string) { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const { loading, data, error } = useQuery(GET_BLOCK_BY_TIMESTAMP, { client: subgraphBlocksClients[chainId as SWPRSupportedChains], diff --git a/src/hooks/useSwapCallback.ts b/src/hooks/useSwapCallback.ts index 37de9fda2..6950d1cc2 100644 --- a/src/hooks/useSwapCallback.ts +++ b/src/hooks/useSwapCallback.ts @@ -26,8 +26,7 @@ import { calculateGasMargin, isAddress, shortenAddress } from '../utils' import { limitNumberOfDecimalPlaces } from '../utils/prices' import useENS from './useENS' import useTransactionDeadline from './useTransactionDeadline' - -import { useActiveWeb3React } from './index' +import { useWeb3ReactCore } from './useWeb3ReactCore' export enum SwapCallbackState { INVALID, @@ -63,13 +62,13 @@ export function useSwapsCallArguments( allowedSlippage: number = INITIAL_ALLOWED_SLIPPAGE, // in bips recipientAddressOrName: string | null // the ENS name or address of the recipient of the trade, or null if swap should be returned to sender ): SwapCall[][] { - const { account, chainId, library } = useActiveWeb3React() + const { account, chainId, provider } = useWeb3ReactCore() const { address: recipientAddress } = useENS(recipientAddressOrName) const recipient = recipientAddressOrName === null ? account : recipientAddress const deadline = useTransactionDeadline() return useMemo(() => { - if (!trades || trades.length === 0 || !recipient || !library || !account || !chainId || !deadline) { + if (!trades || trades.length === 0 || !recipient || !provider || !account || !chainId || !deadline) { return [] } @@ -114,7 +113,7 @@ export function useSwapsCallArguments( return swapMethods.map(transactionParameters => ({ transactionParameters })) }) - }, [account, allowedSlippage, chainId, deadline, library, trades, recipient]) + }, [account, allowedSlippage, chainId, deadline, provider, trades, recipient]) } /** @@ -160,7 +159,7 @@ export function useSwapCallback({ allowedSlippage = INITIAL_ALLOWED_SLIPPAGE, recipientAddressOrName, }: UseSwapCallbackParams): UseSwapCallbackReturn { - const { account, chainId, library } = useActiveWeb3React() + const { account, chainId, provider } = useWeb3ReactCore() const mainnetGasPrices = useMainnetGasPrices() const [preferredGasPrice] = useUserPreferredGasPrice() @@ -175,7 +174,7 @@ export function useSwapCallback({ const recipient = recipientAddressOrName === null ? account : recipientAddress return useMemo(() => { - if (!trade || !library || !account || !chainId) { + if (!trade || !provider || !account || !chainId) { return { state: SwapCallbackState.INVALID, callback: null, error: 'Missing dependencies' } } if (!recipient) { @@ -191,7 +190,7 @@ export function useSwapCallback({ callback: async function onSwap(): Promise { // GPv2 trade if (trade instanceof CoWTrade) { - const signer = library.getSigner() + const signer = provider.getSigner() // Sign the order // and then submit the order to GPv2 @@ -224,7 +223,7 @@ export function useSwapCallback({ } } - return library + return provider .getSigner() .estimateGas(transactionRequest as any) .then(gasEstimate => ({ @@ -234,7 +233,7 @@ export function useSwapCallback({ .catch(gasError => { console.debug('Gas estimate failed, trying eth_call to extract error', transactionRequest, gasError) - return library + return provider .call(transactionRequest as any) .then(result => { console.debug('Unexpected successful call after failed estimate gas', call, gasError, result) @@ -287,7 +286,7 @@ export function useSwapCallback({ } } - return library + return provider .getSigner() .sendTransaction({ gasLimit: calculateGasMargin(gasEstimate), @@ -317,7 +316,7 @@ export function useSwapCallback({ } }, [ trade, - library, + provider, account, chainId, swapCalls, diff --git a/src/hooks/useSwapsGasEstimate.ts b/src/hooks/useSwapsGasEstimate.ts index 852f69a52..d234d9ff1 100644 --- a/src/hooks/useSwapsGasEstimate.ts +++ b/src/hooks/useSwapsGasEstimate.ts @@ -16,15 +16,14 @@ import { calculateGasMargin } from '../utils' import { useCurrency } from './Tokens' import useENS from './useENS' import { useSwapsCallArguments } from './useSwapCallback' - -import { useActiveWeb3React } from './index' +import { useWeb3ReactCore } from './useWeb3ReactCore' export function useSwapsGasEstimations( allowedSlippage: number = INITIAL_ALLOWED_SLIPPAGE, recipientAddressOrName: string | null, trades?: (Trade | undefined)[] ): { loading: boolean; estimations: (BigNumber | null)[][] } { - const { account, library, chainId } = useActiveWeb3React() + const { account, provider, chainId } = useWeb3ReactCore() const platformSwapCalls = useSwapsCallArguments(trades, allowedSlippage, recipientAddressOrName) const mainnetGasPrices = useMainnetGasPrices() const [preferredGasPrice] = useUserPreferredGasPrice() @@ -115,7 +114,7 @@ export function useSwapsGasEstimations( let estimatedCall = null try { estimatedCall = calculateGasMargin( - await (library as Web3Provider).estimateGas(transactionParameters as any) + await (provider as Web3Provider).estimateGas(transactionParameters as any) ) } catch (error) { console.error(error) @@ -129,15 +128,15 @@ export function useSwapsGasEstimations( } setEstimations(estimatedCalls) setLoading(false) - }, [platformSwapCalls, library, routerAllowances, trades, typedIndependentCurrencyAmount]) + }, [platformSwapCalls, provider, routerAllowances, trades, typedIndependentCurrencyAmount]) useEffect(() => { - if (!trades || trades.length === 0 || !library || !chainId || !recipient || !account || !calculateGasFees) { + if (!trades || trades.length === 0 || !provider || !chainId || !recipient || !account || !calculateGasFees) { setEstimations([]) return } updateEstimations() - }, [chainId, library, recipient, trades, updateEstimations, account, calculateGasFees]) + }, [chainId, provider, recipient, trades, updateEstimations, account, calculateGasFees]) return { loading: loading, estimations } } diff --git a/src/hooks/useTimestampFromBlock.ts b/src/hooks/useTimestampFromBlock.ts index 5cf806bab..0f668fc80 100644 --- a/src/hooks/useTimestampFromBlock.ts +++ b/src/hooks/useTimestampFromBlock.ts @@ -1,20 +1,20 @@ import { useEffect, useState } from 'react' -import { useActiveWeb3React } from './index' +import { useWeb3ReactCore } from './useWeb3ReactCore' export function useTimestampFromBlock(block: number | undefined): number | undefined { - const { library } = useActiveWeb3React() + const { provider } = useWeb3ReactCore() const [timestamp, setTimestamp] = useState() useEffect(() => { async function fetchTimestamp() { if (block) { - const blockData = await library?.getBlock(block) + const blockData = await provider?.getBlock(block) blockData && setTimestamp(blockData.timestamp) } } if (!timestamp) { fetchTimestamp() } - }, [block, library, timestamp]) + }, [block, provider, timestamp]) return timestamp } diff --git a/src/hooks/useTokenDerivedNativeCurrency.ts b/src/hooks/useTokenDerivedNativeCurrency.ts index 3618ba7e8..ca6fddd6c 100644 --- a/src/hooks/useTokenDerivedNativeCurrency.ts +++ b/src/hooks/useTokenDerivedNativeCurrency.ts @@ -6,14 +6,13 @@ import { useMemo } from 'react' import { useGetTokenQuery } from '../graphql/generated/schema' import { useNativeCurrency } from './useNativeCurrency' - -import { useActiveWeb3React } from './index' +import { useWeb3ReactCore } from './useWeb3ReactCore' export function useTokenDerivedNativeCurrency(token?: Token): { loading: boolean derivedNativeCurrency: CurrencyAmount } { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const nativeCurrency = useNativeCurrency() const { loading, data, error } = useGetTokenQuery({ variables: { tokenId: token?.address.toLowerCase() || '' } }) diff --git a/src/hooks/useTokenOrPairNativeCurrency.ts b/src/hooks/useTokenOrPairNativeCurrency.ts index 327aca71e..8c85b0aac 100644 --- a/src/hooks/useTokenOrPairNativeCurrency.ts +++ b/src/hooks/useTokenOrPairNativeCurrency.ts @@ -9,14 +9,13 @@ import { getLpTokenPrice } from '../utils/prices' import { useNativeCurrency } from './useNativeCurrency' import { usePairReserveNativeCurrency } from './usePairReserveNativeCurrency' import { useTokenDerivedNativeCurrency } from './useTokenDerivedNativeCurrency' - -import { useActiveWeb3React } from './index' +import { useWeb3ReactCore } from './useWeb3ReactCore' export function useTokenOrPairNativeCurrency(tokenOrPair?: Token | Pair): { loading: boolean derivedNativeCurrency?: Price } { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const nativeCurrency = useNativeCurrency() const isToken = tokenOrPair instanceof Token const lpTokenTotalSupply = usePairLiquidityTokenTotalSupply(tokenOrPair instanceof Pair ? tokenOrPair : undefined) diff --git a/src/hooks/useTokensDerivedNativeCurrency.ts b/src/hooks/useTokensDerivedNativeCurrency.ts index b8f3768fa..ecd9648aa 100644 --- a/src/hooks/useTokensDerivedNativeCurrency.ts +++ b/src/hooks/useTokensDerivedNativeCurrency.ts @@ -7,14 +7,13 @@ import { useMemo } from 'react' import { useGetDerivedNativeCurrencyTokensQuery } from '../graphql/generated/schema' import { useKpiTokens } from './useKpiTokens' import { useNativeCurrency } from './useNativeCurrency' - -import { useActiveWeb3React } from './index' +import { useWeb3ReactCore } from './useWeb3ReactCore' export function useNativeCurrencyPricedTokenAmounts(tokenAmounts?: TokenAmount[] | null): { loading: boolean pricedTokenAmounts: PricedTokenAmount[] } { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const nativeCurrency = useNativeCurrency() const tokenIds = useMemo(() => { return tokenAmounts ? tokenAmounts.map(tokenAmount => tokenAmount.token.address.toLowerCase()) : [] diff --git a/src/hooks/useUSDValue.ts b/src/hooks/useUSDValue.ts index e41bc289b..3e430f05f 100644 --- a/src/hooks/useUSDValue.ts +++ b/src/hooks/useUSDValue.ts @@ -21,8 +21,7 @@ import { getUSDPriceCurrencyQuote, getUSDPriceTokenQuote, toPriceInformation } f import { currencyId } from '../utils/currencyId' import { wrappedCurrencyAmount } from '../utils/wrappedCurrency' import { useTradeExactInUniswapV2 } from './Trades' - -import { useActiveWeb3React } from './index' +import { useWeb3ReactCore } from './useWeb3ReactCore' const STABLECOIN_AND_PLATFOM_BY_CHAIN: Record = { [ChainId.MAINNET]: { stablecoin: DAI[ChainId.MAINNET], platform: UniswapV2RoutablePlatform.UNISWAP }, @@ -56,7 +55,7 @@ const convertToTokenAmount = (currencyAmount: CurrencyAmount | undefined, chainI } export function useUSDPrice(tokenAmount?: TokenAmount) { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() let stablecoin: Token | undefined = undefined let platform: UniswapV2RoutablePlatform | undefined = undefined @@ -94,7 +93,7 @@ export function useUSDPrice(tokenAmount?: TokenAmount) { export function useCoingeckoUSDPrice(token?: Token, isNativeCurrency = false) { // default to MAINNET (if disconnected e.g) - const { chainId = ChainId.MAINNET } = useActiveWeb3React() + const { chainId = ChainId.MAINNET } = useWeb3ReactCore() const [price, setPrice] = useState() const [percentagePriceChange24h, setPercentagePriceChange24h] = useState() const [isIncome24h, setIsIncome24h] = useState() @@ -231,7 +230,7 @@ export function useHigherUSDValue({ inputCurrencyAmount?: CurrencyAmount outputCurrencyAmount?: CurrencyAmount }) { - const { chainId = ChainId.MAINNET } = useActiveWeb3React() + const { chainId = ChainId.MAINNET } = useWeb3ReactCore() const inputTokenAmount = convertToTokenAmount(inputCurrencyAmount, chainId) const outputTokenAmount = convertToTokenAmount(outputCurrencyAmount, chainId) diff --git a/src/hooks/useWeb3ReactCore.ts b/src/hooks/useWeb3ReactCore.ts new file mode 100644 index 000000000..fe699a404 --- /dev/null +++ b/src/hooks/useWeb3ReactCore.ts @@ -0,0 +1,82 @@ +import { ChainId } from '@swapr/sdk' + +import { useWeb3React, Web3ContextType } from '@web3-react/core' +import { Connector } from '@web3-react/types' +import { useCallback, useEffect, useState } from 'react' +import { useDispatch, useSelector } from 'react-redux' + +import { getConnection } from '../connectors/utils' +import { NETWORK_DETAIL } from '../constants' +import { AppDispatch, AppState } from '../state' +import { ApplicationModal } from '../state/application/actions' +import { useOpenModal } from '../state/application/hooks' +import { setConnectorError, updatePendingConnector, updateSelectedConnector } from '../state/user/actions' +import { getErrorMessage } from '../utils/getErrorMessage' + +type Web3ReactProps = Omit & { + chainId?: ChainId + isActiveChainSupported: boolean + connectorError: string | undefined + tryActivation: (connector: Connector) => void + tryDeactivation: (connector: Connector, account: string | undefined) => void +} + +export const useWeb3ReactCore = (): Web3ReactProps => { + const dispatch = useDispatch() + const props = useWeb3React() + const { chainId, isActive, connector } = props + const [isActiveChainSupported, setIsActiveChainSupported] = useState(true) + const openPendingWalletModal = useOpenModal(ApplicationModal.WALLET_PENDING) + + // needed to update if connected eagerly + useEffect(() => { + dispatch(updateSelectedConnector({ selectedConnector: getConnection(connector).type })) + }, [connector, dispatch]) + + useEffect(() => { + const isDefinedAndSupported = isActive && chainId ? Object.keys(NETWORK_DETAIL).includes(chainId.toString()) : false + setIsActiveChainSupported(isDefinedAndSupported) + }, [chainId, isActive]) + + const tryActivation = useCallback( + async (connector: Connector) => { + const connectorType = getConnection(connector).type + + dispatch(updatePendingConnector({ pendingConnector: connectorType })) + dispatch(setConnectorError({ connector: connectorType, connectorError: undefined })) + openPendingWalletModal() + + try { + await connector.activate() + dispatch(updateSelectedConnector({ selectedConnector: connectorType })) + } catch (error) { + console.debug(`web3-react connection error: ${error}`) + dispatch(setConnectorError({ connector: connectorType, connectorError: getErrorMessage(error) })) + } + }, + [dispatch, openPendingWalletModal] + ) + + const tryDeactivation = useCallback(async (connector: Connector, account: string | undefined) => { + if (!account) return + if (connector.deactivate) { + void connector.deactivate() + return + } + void connector.resetState() + }, []) + + const connectorError = useSelector((state: AppState) => { + const { pending } = state.user.connector + return pending ? state.user.connector.errorByType[pending] : undefined + }) + + return { + ...props, + chainId: (props.chainId as ChainId) ?? undefined, + isActiveChainSupported, + connectorError, + tryActivation, + tryDeactivation, + } +} diff --git a/src/hooks/useWrapCallback.ts b/src/hooks/useWrapCallback.ts index dd6a597a3..e8f2f1600 100644 --- a/src/hooks/useWrapCallback.ts +++ b/src/hooks/useWrapCallback.ts @@ -10,8 +10,7 @@ import { useAllSwapTransactions, useTransactionAdder } from '../state/transactio import { useCurrencyBalance } from '../state/wallet/hooks' import { useNativeCurrencyWrapperContract, useWrappingToken } from './useContract' import { useNativeCurrency } from './useNativeCurrency' - -import { useActiveWeb3React } from './index' +import { useWeb3ReactCore } from './useWeb3ReactCore' export enum WrapType { NOT_APPLICABLE, @@ -48,7 +47,7 @@ export function useWrapCallback( isGnosisTrade = false, typedValue?: string // can be also obtained from the SwapState ): UseWrapCallbackReturn { - const { chainId, account } = useActiveWeb3React() + const { chainId, account } = useWeb3ReactCore() const nativeCurrency = useNativeCurrency() const nativeCurrencyWrapperToken = useWrappingToken(nativeCurrency) const nativeCurrencyWrapperContract = useNativeCurrencyWrapperContract() diff --git a/src/index.tsx b/src/index.tsx index 865709c71..accca0ee3 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,12 +1,11 @@ import { setUseWhatChange } from '@simbathesailor/use-what-changed' -import { createWeb3ReactRoot, Web3ReactProvider } from '@web3-react/core' import { StrictMode } from 'react' import { createRoot } from 'react-dom/client' import { Provider } from 'react-redux' import { HashRouter } from 'react-router-dom' import { AnalyticsProvider } from './analytics' -import { NetworkContextName } from './constants' +import { Web3Provider } from './components/Web3Provider' import './i18n' import App from './pages/App' import { EcoBridgeProvider } from './services/EcoBridge/EcoBridgeProvider' @@ -19,7 +18,6 @@ import MulticallUpdater from './state/multicall/updater' import TransactionUpdater from './state/transactions/updater' import UserUpdater from './state/user/updater' import ThemeProvider, { FixedGlobalStyle, ThemedGlobalStyle } from './theme' -import getLibrary from './utils/getLibrary' import './theme/fonts.css' // Add Content Security Policy nonce to the scripts @@ -30,8 +28,6 @@ setUseWhatChange({ active: process.env.NODE_ENV === 'development', }) -const Web3ProviderNetwork = createWeb3ReactRoot(NetworkContextName) - if ('ethereum' in window) { ;(window.ethereum as any).autoRefreshOnNetworkChange = false } @@ -60,22 +56,20 @@ root.render( - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + ) diff --git a/src/lib/eco-router/hooks.ts b/src/lib/eco-router/hooks.ts index 8e5e3e9b3..a32335c13 100644 --- a/src/lib/eco-router/hooks.ts +++ b/src/lib/eco-router/hooks.ts @@ -4,7 +4,7 @@ import { useEffect, useState } from 'react' // Eco Router modules // Web3 hooks -import { useActiveWeb3React } from '../../hooks' +import { useWeb3ReactCore } from '../../hooks/useWeb3ReactCore' import { useIsMultihop, useUserSlippageTolerance } from '../../state/user/hooks' import { getExactIn, getExactOut } from './api' // Types @@ -24,7 +24,7 @@ export function useEcoRouterExactIn(currencyAmountIn?: CurrencyAmount, currencyO // Errors const [errors, setErrors] = useState([]) // Chain Id - const { chainId, account, library } = useActiveWeb3React() + const { chainId, account, provider } = useWeb3ReactCore() // Uniswap V2 Trade option: using multi-hop option const uniswapV2IsMultihop = useIsMultihop() // Used to trigger computing trade route @@ -36,7 +36,7 @@ export function useEcoRouterExactIn(currencyAmountIn?: CurrencyAmount, currencyO let isCancelled = false // Early exit and clean state if necessary - if (!currencyAmountIn || !account || !currencyAmountIn.currency || !library || !currencyOut || !chainId) { + if (!currencyAmountIn || !account || !currencyAmountIn.currency || !provider || !currencyOut || !chainId) { setTrades([]) setLoading(false) @@ -61,7 +61,7 @@ export function useEcoRouterExactIn(currencyAmountIn?: CurrencyAmount, currencyO useMultihops: uniswapV2IsMultihop, }, }, - library + provider ) .then(newTrades => { // Only update this invokation is not cancelled @@ -107,7 +107,7 @@ export function useEcoRouterExactOut(currencyIn?: Currency, currencyAmountOut?: // Errors const [errors, setErrors] = useState([]) // Chain Id - const { chainId, account, library } = useActiveWeb3React() + const { chainId, account, provider } = useWeb3ReactCore() // Uniswap V2 Trade option: using multi-hop option const uniswapV2IsMultihop = useIsMultihop() // Used to trigger computing trade route @@ -143,7 +143,7 @@ export function useEcoRouterExactOut(currencyIn?: Currency, currencyAmountOut?: useMultihops: uniswapV2IsMultihop, }, }, - library + provider ) .then(newTrades => { // Only update this invokation is not cancelled diff --git a/src/pages/Account/Account.tsx b/src/pages/Account/Account.tsx index 43ed141a5..3fea85b6c 100644 --- a/src/pages/Account/Account.tsx +++ b/src/pages/Account/Account.tsx @@ -9,12 +9,11 @@ import { Box, Flex, Text } from 'rebass' import { PageMetaData } from '../../components/PageMetaData' import { Pagination } from '../../components/Pagination' import { Switch } from '../../components/Switch' -import { useActiveWeb3React } from '../../hooks' import { useENSAvatar } from '../../hooks/useENSAvatar' -import { useENSName } from '../../hooks/useENSName' import { useIsMobileByMedia } from '../../hooks/useIsMobileByMedia' import { usePage } from '../../hooks/usePage' import { useResponsiveItemsPerPage } from '../../hooks/useResponsiveItemsPerPage' +import { useWeb3ReactCore } from '../../hooks/useWeb3ReactCore' import { BridgeTxsFilter } from '../../services/EcoBridge/EcoBridge.types' import { ecoBridgeUIActions } from '../../services/EcoBridge/store/UI.reducer' import { useWalletSwitcherPopoverToggle } from '../../state/application/hooks' @@ -44,8 +43,7 @@ export function Account() { const isMobile = useIsMobileByMedia() // Account details - const { account, chainId, active, deactivate } = useActiveWeb3React() - const { ENSName } = useENSName(account ?? undefined) + const { account, chainId, ENSName, isActive, connector, tryDeactivation } = useWeb3ReactCore() const { avatar: ensAvatar } = useENSAvatar(ENSName) // Toggles @@ -128,7 +126,7 @@ export function Account() { - {active && } + {isActive && }
diff --git a/src/pages/Account/TransactionRows/SwapTransactionRow.tsx b/src/pages/Account/TransactionRows/SwapTransactionRow.tsx index 107ab7bcf..ec7236de9 100644 --- a/src/pages/Account/TransactionRows/SwapTransactionRow.tsx +++ b/src/pages/Account/TransactionRows/SwapTransactionRow.tsx @@ -2,7 +2,7 @@ import { DateTime } from 'luxon' import { useTranslation } from 'react-i18next' import { Box, Flex } from 'rebass' -import { useActiveWeb3React } from '../../../hooks' +import { useWeb3ReactCore } from '../../../hooks/useWeb3ReactCore' import { getExplorerLink, shortenAddress } from '../../../utils' import { formatNumber } from '../../../utils/formatNumber' import { getNetworkInfo } from '../../../utils/networksList' @@ -25,7 +25,7 @@ interface SwapTransactionRowProps { export function SwapTransactionRow({ transaction, showBackgroundStatus }: SwapTransactionRowProps) { const { t } = useTranslation('account') - const { account } = useActiveWeb3React() + const { account } = useWeb3ReactCore() const fromAddress = shortenAddress(`${account}`) const { type, status, from, to, confirmedTime, network, hash, swapProtocol, addedTime, alternateReceiver } = transaction diff --git a/src/pages/App.tsx b/src/pages/App.tsx index 69d1a06ce..152bfb804 100644 --- a/src/pages/App.tsx +++ b/src/pages/App.tsx @@ -12,8 +12,7 @@ import { FallbackLoader } from '../components/Loader/FallbackLoader' import NetworkWarningModal from '../components/NetworkWarningModal' import { PageMetaData } from '../components/PageMetaData' import { SpaceBg } from '../components/SpaceBg/SpaceBg' -import Web3ReactManager from '../components/Web3ReactManager' -import { useActiveWeb3React } from '../hooks' +import { useWeb3ReactCore } from '../hooks/useWeb3ReactCore' import { SWPRSupportedChains } from '../utils/chainSupportsSWPR' import { Routes } from './Routes' @@ -67,7 +66,7 @@ const Marginer = styled.div` ` export default function App() { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const location = useLocation() const theme = useTheme() const [isSwapPage, setIsSwapPage] = useState(false) @@ -95,21 +94,19 @@ export default function App() { - - - -
- - - - }> - - - - - - - + + +
+ + + + }> + + + + + + { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() if (!chainId) return null return ( diff --git a/src/pages/Bridge/index.tsx b/src/pages/Bridge/index.tsx index 91279b30d..c02090fa8 100644 --- a/src/pages/Bridge/index.tsx +++ b/src/pages/Bridge/index.tsx @@ -13,7 +13,7 @@ import { } from '../../components/NetworkSwitcher' import { PageMetaData } from '../../components/PageMetaData' import { RowBetween } from '../../components/Row' -import { useActiveWeb3React } from '../../hooks' +import { useWeb3ReactCore } from '../../hooks/useWeb3ReactCore' import { useBridgeActionHandlers, useBridgeCollectHandlers, @@ -117,7 +117,7 @@ export function isNetworkSupported(chainId: ChainId): boolean { export default function Bridge() { const dispatch = useDispatch() - const { chainId, account } = useActiveWeb3React() + const { chainId, account } = useWeb3ReactCore() const ecoBridge = useEcoBridge() const bridgeSummaries = useSelector((state: AppState) => diff --git a/src/pages/LiquidityMining/Create/index.tsx b/src/pages/LiquidityMining/Create/index.tsx index 84f349104..ae4756ad7 100644 --- a/src/pages/LiquidityMining/Create/index.tsx +++ b/src/pages/LiquidityMining/Create/index.tsx @@ -13,10 +13,10 @@ import RewardsSelection from '../../../components/LiquidityMining/Create/Steps/R import SingleOrPairCampaign from '../../../components/LiquidityMining/Create/Steps/SingleOrPairCampaign' import DurationAndLocking from '../../../components/LiquidityMining/Create/Steps/Time' import { PageMetaData } from '../../../components/PageMetaData' -import { useActiveWeb3React } from '../../../hooks' import { ApprovalState } from '../../../hooks/useApproveCallback' import { useCreateLiquidityMiningCallback } from '../../../hooks/useCreateLiquidityMiningCallback' import { useNewLiquidityMiningCampaign } from '../../../hooks/useNewLiquidityMiningCampaign' +import { useWeb3ReactCore } from '../../../hooks/useWeb3ReactCore' import { useTransactionAdder } from '../../../state/transactions/hooks' import { TYPE } from '../../../theme' import { PageWrapper } from '../../../ui/StyledElements/PageWrapper' @@ -106,7 +106,7 @@ const reducer = (state: Reward[], action: Actions): Reward[] => { export default function CreateLiquidityMining() { const { t } = useTranslation('liquidity') - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const [attemptingTransaction, setAttemptingTransaction] = useState(false) const [transactionHash, setTransactionHash] = useState(null) const [showConfirmationModal, setShowConfirmationModal] = useState(false) diff --git a/src/pages/Pools/AddLiquidity/index.tsx b/src/pages/Pools/AddLiquidity/index.tsx index 45b894774..34806ae66 100644 --- a/src/pages/Pools/AddLiquidity/index.tsx +++ b/src/pages/Pools/AddLiquidity/index.tsx @@ -22,13 +22,13 @@ import TransactionConfirmationModal, { ConfirmationModalContent, } from '../../../components/TransactionConfirmationModal' import { PairState } from '../../../data/Reserves' -import { useActiveWeb3React } from '../../../hooks' import { useCurrency } from '../../../hooks/Tokens' import { ApprovalState, useApproveCallback } from '../../../hooks/useApproveCallback' import { useWrappingToken } from '../../../hooks/useContract' import { useNativeCurrency } from '../../../hooks/useNativeCurrency' import { useRouter } from '../../../hooks/useRouter' import useTransactionDeadline from '../../../hooks/useTransactionDeadline' +import { useWeb3ReactCore } from '../../../hooks/useWeb3ReactCore' import { useWalletSwitcherPopoverToggle } from '../../../state/application/hooks' import { Field } from '../../../state/mint/actions' import { useDerivedMintInfo, useMintActionHandlers, useMintState } from '../../../state/mint/hooks' @@ -52,7 +52,7 @@ type CurrencySearchParams = { export default function AddLiquidity() { const { navigate, location } = useRouter() const { currencyIdA, currencyIdB } = useParams() - const { account, chainId, library } = useActiveWeb3React() + const { account, chainId, provider } = useWeb3ReactCore() const theme = useTheme() const nativeCurrency = useNativeCurrency() const nativeCurrencyWrapper = useWrappingToken(nativeCurrency) @@ -128,8 +128,8 @@ export default function AddLiquidity() { const addTransaction = useTransactionAdder() async function onAdd() { - if (!chainId || !library || !account) return - const router = getRouterContract(chainId, library, UniswapV2RoutablePlatform.SWAPR, account) + if (!chainId || !provider || !account) return + const router = getRouterContract(chainId, provider, UniswapV2RoutablePlatform.SWAPR, account) const { [Field.CURRENCY_A]: parsedAmountA, [Field.CURRENCY_B]: parsedAmountB } = parsedAmounts if (!parsedAmountA || !parsedAmountB || !currencyA || !currencyB || !deadline) { diff --git a/src/pages/Pools/LiquidityMiningCampaign/index.tsx b/src/pages/Pools/LiquidityMiningCampaign/index.tsx index ff8864505..1e21aa7d3 100644 --- a/src/pages/Pools/LiquidityMiningCampaign/index.tsx +++ b/src/pages/Pools/LiquidityMiningCampaign/index.tsx @@ -12,11 +12,11 @@ import LiquidityMiningCampaignView from '../../../components/Pool/LiquidityMinin import { RowBetween, RowFixed } from '../../../components/Row' import { UndecoratedLink } from '../../../components/UndercoratedLink' import { PairState, usePair } from '../../../data/Reserves' -import { useActiveWeb3React } from '../../../hooks' import { useSingleSidedCampaign } from '../../../hooks/singleSidedStakeCampaigns/useSingleSidedCampaign' import { useToken } from '../../../hooks/Tokens' import { useLiquidityMiningCampaign } from '../../../hooks/useLiquidityMiningCampaign' import { useRouter } from '../../../hooks/useRouter' +import { useWeb3ReactCore } from '../../../hooks/useWeb3ReactCore' import { useTokenBalance } from '../../../state/wallet/hooks' import { TYPE } from '../../../theme' import { PageWrapper } from '../../../ui/StyledElements/PageWrapper' @@ -44,7 +44,7 @@ const ButtonRow = styled(RowFixed)` ` export default function LiquidityMiningCampaign() { - const { account } = useActiveWeb3React() + const { account } = useWeb3ReactCore() const { location, searchParams: search } = useRouter() const { liquidityMiningCampaignId, currencyIdA, currencyIdB } = useParams<{ currencyIdA: string diff --git a/src/pages/Pools/Mine/index.tsx b/src/pages/Pools/Mine/index.tsx index c03a609f0..efd31d418 100644 --- a/src/pages/Pools/Mine/index.tsx +++ b/src/pages/Pools/Mine/index.tsx @@ -7,9 +7,9 @@ import { AutoColumn } from '../../../components/Column' import { PairsList } from '../../../components/Pool/PairsList' import { RowBetween, RowFixed } from '../../../components/Row' import { UndecoratedLink } from '../../../components/UndercoratedLink' -import { useActiveWeb3React } from '../../../hooks' import { useLiquidityMiningFeatureFlag } from '../../../hooks/useLiquidityMiningFeatureFlag' import { useLPPairs } from '../../../hooks/useLiquidityPositions' +import { useWeb3ReactCore } from '../../../hooks/useWeb3ReactCore' import { TYPE } from '../../../theme' import { PageWrapper } from '../../../ui/StyledElements/PageWrapper' @@ -47,7 +47,7 @@ const ResponsiveButtonSecondary = styled(ButtonSecondary)` ` export default function MyPairs() { - const { account } = useActiveWeb3React() + const { account } = useWeb3ReactCore() const [search] = useSearchParams() const liquidityMiningEnabled = useLiquidityMiningFeatureFlag() const { loading: loadingPairs, data } = useLPPairs(account || undefined) diff --git a/src/pages/Pools/RemoveLiquidity/index.tsx b/src/pages/Pools/RemoveLiquidity/index.tsx index 34287ffba..c62b16ec3 100644 --- a/src/pages/Pools/RemoveLiquidity/index.tsx +++ b/src/pages/Pools/RemoveLiquidity/index.tsx @@ -27,7 +27,6 @@ import TradePrice from '../../../components/Swap/TradePrice' import TransactionConfirmationModal, { ConfirmationModalContent, } from '../../../components/TransactionConfirmationModal' -import { useActiveWeb3React } from '../../../hooks' import { useCurrency } from '../../../hooks/Tokens' import { ApprovalState, useApproveCallback } from '../../../hooks/useApproveCallback' import { usePairContract, useWrappingToken } from '../../../hooks/useContract' @@ -36,6 +35,7 @@ import useIsArgentWallet from '../../../hooks/useIsArgentWallet' import { useNativeCurrency } from '../../../hooks/useNativeCurrency' import { useRouter } from '../../../hooks/useRouter' import useTransactionDeadline from '../../../hooks/useTransactionDeadline' +import { useWeb3ReactCore } from '../../../hooks/useWeb3ReactCore' import { useWalletSwitcherPopoverToggle } from '../../../state/application/hooks' import { Field } from '../../../state/burn/actions' import { useBurnActionHandlers, useBurnState, useDerivedBurnInfo } from '../../../state/burn/hooks' @@ -65,7 +65,7 @@ export default function RemoveLiquidity() { const { navigate } = useRouter() const [currencyA, currencyB] = [useCurrency(currencyIdA) ?? undefined, useCurrency(currencyIdB) ?? undefined] - const { account, chainId, library } = useActiveWeb3React() + const { account, chainId, provider } = useWeb3ReactCore() const nativeCurrency = useNativeCurrency() const nativeCurrencyWrapper = useWrappingToken(nativeCurrency) const [tokenA, tokenB] = useMemo( @@ -134,7 +134,7 @@ export default function RemoveLiquidity() { const isArgentWallet = useIsArgentWallet() async function onAttemptToApprove() { - if (!pairContract || !pair || !library || !deadline) throw new Error('missing dependencies') + if (!pairContract || !pair || !provider || !deadline) throw new Error('missing dependencies') const liquidityAmount = parsedAmounts[Field.LIQUIDITY] if (!liquidityAmount) throw new Error('missing liquidity amount') @@ -181,7 +181,7 @@ export default function RemoveLiquidity() { message, }) - library + provider .send('eth_signTypedData_v4', [account, data]) .then(splitSignature) .then(signature => { @@ -225,12 +225,12 @@ export default function RemoveLiquidity() { // tx sending const addTransaction = useTransactionAdder() async function onRemove() { - if (!chainId || !library || !account || !deadline) throw new Error('missing dependencies') + if (!chainId || !provider || !account || !deadline) throw new Error('missing dependencies') const { [Field.CURRENCY_A]: currencyAmountA, [Field.CURRENCY_B]: currencyAmountB } = parsedAmounts if (!currencyAmountA || !currencyAmountB) { throw new Error('missing currency amounts') } - const router = getRouterContract(chainId, library, UniswapV2RoutablePlatform.SWAPR, account) + const router = getRouterContract(chainId, provider, UniswapV2RoutablePlatform.SWAPR, account) const amountsMin = { [Field.CURRENCY_A]: calculateSlippageAmount(currencyAmountA, allowedSlippage)[0], diff --git a/src/pages/Pools/index.tsx b/src/pages/Pools/index.tsx index 82a014ca2..23171a27c 100644 --- a/src/pages/Pools/index.tsx +++ b/src/pages/Pools/index.tsx @@ -19,10 +19,10 @@ import { RowBetween } from '../../components/Row' import { CurrencySearchModal } from '../../components/SearchModal/CurrencySearchModal' import { Switch } from '../../components/Switch' import { LIQUIDITY_SORTING_TYPES } from '../../constants' -import { useActiveWeb3React } from '../../hooks' import { useSwaprSinglelSidedStakeCampaigns } from '../../hooks/singleSidedStakeCampaigns/useSwaprSingleSidedStakeCampaigns' import { useAllPairsWithLiquidityAndMaximumApyAndStakingIndicator } from '../../hooks/useAllPairsWithLiquidityAndMaximumApyAndStakingIndicator' import { useLPPairs } from '../../hooks/useLiquidityPositions' +import { useWeb3ReactCore } from '../../hooks/useWeb3ReactCore' import { TYPE } from '../../theme' import { PageWrapper } from '../../ui/StyledElements/PageWrapper' import { getAccountAnalyticsLink } from '../../utils' @@ -193,7 +193,7 @@ function Title({ export default function Pools() { const { t } = useTranslation('pool') - const { account, chainId } = useActiveWeb3React() + const { account, chainId } = useWeb3ReactCore() const [filterToken, setFilterToken] = useState() const [aggregatedDataFilter, setAggregatedDataFilter] = useState(PairsFilterType.ALL) const [sortBy, setSortBy] = useState(LIQUIDITY_SORTING_TYPES.TVL) diff --git a/src/pages/Swap/AdvancedSwapMode/OrderHistory/OrderHistoryTransaction/OrderHistoryTransaction.tsx b/src/pages/Swap/AdvancedSwapMode/OrderHistory/OrderHistoryTransaction/OrderHistoryTransaction.tsx index 257271c4c..3ffc1994f 100644 --- a/src/pages/Swap/AdvancedSwapMode/OrderHistory/OrderHistoryTransaction/OrderHistoryTransaction.tsx +++ b/src/pages/Swap/AdvancedSwapMode/OrderHistory/OrderHistoryTransaction/OrderHistoryTransaction.tsx @@ -3,7 +3,7 @@ import { ExternalLink } from 'react-feather' import { Text } from 'rebass' import styled, { useTheme } from 'styled-components' -import { useActiveWeb3React } from '../../../../../hooks/index' +import { useWeb3ReactCore } from '../../../../../hooks/useWeb3ReactCore' import { EXPLORER_LINK_TYPE, getExplorerLink } from '../../../../../utils' import { Status } from '../../../../Account/Account.styles' import { Transaction, TransactionTypes } from '../../../../Account/Account.types' @@ -30,7 +30,7 @@ const Wrapper = styled.div` ` export const OrderHistoryTransaction = ({ tx }: { tx: Transaction }) => { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const theme = useTheme() const isSwapTransaction = tx.type === TransactionTypes.Swap diff --git a/src/pages/Swap/Swapbox/Swapbox.tsx b/src/pages/Swap/Swapbox/Swapbox.tsx index bc6e7c751..7d2797241 100644 --- a/src/pages/Swap/Swapbox/Swapbox.tsx +++ b/src/pages/Swap/Swapbox/Swapbox.tsx @@ -12,10 +12,10 @@ import ConfirmSwapModal from '../../../components/Swap/ConfirmSwapModal' import { ArrowWrapper, SwitchTokensAmountsContainer, Wrapper } from '../../../components/Swap/styleds' import SwapButtons from '../../../components/Swap/SwapButtons' import { TradeDetails } from '../../../components/Swap/TradeDetails' -import { useActiveWeb3React } from '../../../hooks' import { ApprovalState, useApproveCallbackFromTrade } from '../../../hooks/useApproveCallback' import { useSwapCallback } from '../../../hooks/useSwapCallback' import { useHigherUSDValue } from '../../../hooks/useUSDValue' +import { useWeb3ReactCore } from '../../../hooks/useWeb3ReactCore' import { useWrapCallback, WrapState, WrapType } from '../../../hooks/useWrapCallback' import { useDerivedSwapInfo, useSwapActionHandlers, useSwapState } from '../../../state/swap/hooks' import { Field } from '../../../state/swap/types' @@ -44,7 +44,7 @@ export function Swapbox() { const [platformOverride, setPlatformOverride] = useState(null) const [showAdvancedSwapDetails, setShowAdvancedSwapDetails] = useAdvancedSwapDetails() - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() // for expert mode const isExpertMode = useIsExpertMode() diff --git a/src/pages/Swap/index.tsx b/src/pages/Swap/index.tsx index 102db032d..abdc72a81 100644 --- a/src/pages/Swap/index.tsx +++ b/src/pages/Swap/index.tsx @@ -12,11 +12,11 @@ import { Tabs } from '../../components/Swap/Tabs' import TokenWarningModal from '../../components/TokenWarningModal' import { TESTNETS } from '../../constants' import { REACT_APP_FEATURE_SIMPLE_CHART } from '../../constants/features' -import { useActiveWeb3React, useUnsupportedChainIdError } from '../../hooks' import { useAllTokens, useCurrency } from '../../hooks/Tokens' import { useIsDesktop } from '../../hooks/useIsDesktopByMedia' import { useRouter } from '../../hooks/useRouter' import { useTargetedChainIdFromUrl } from '../../hooks/useTargetedChainIdFromUrl' +import { useWeb3ReactCore } from '../../hooks/useWeb3ReactCore' import { useDefaultsFromURLSearch, useDerivedSwapInfo } from '../../state/swap/hooks' import { Field } from '../../state/swap/types' import { useUpdateSelectedChartOption, useUpdateSelectedSwapTab } from '../../state/user/hooks' @@ -63,7 +63,6 @@ export default function Swap() { const { navigate, pathname } = useRouter() const isInProMode = pathname.includes('/pro') const [activeTab, setActiveTab] = useUpdateSelectedSwapTab() - const isUnsupportedChainIdError = useUnsupportedChainIdError() // token warning stuff const [loadedInputCurrency, loadedOutputCurrency] = [ @@ -92,7 +91,7 @@ export default function Swap() { } }, [isDesktop, navigate, isInProMode]) - const { chainId } = useActiveWeb3React() + const { chainId, isActiveChainSupported } = useWeb3ReactCore() const [selectedChartOption, setselectedChartOption] = useUpdateSelectedChartOption() const { currencies } = useDerivedSwapInfo(platformOverride || undefined) @@ -126,7 +125,7 @@ export default function Swap() { tokens={urlLoadedScammyTokens} onConfirm={handleConfirmTokenWarning} /> - {isInProMode && chainId && !isUnsupportedChainIdError && !TESTNETS.includes(chainId) && isDesktop && ( + {isInProMode && chainId && isActiveChainSupported && !TESTNETS.includes(chainId) && isDesktop && ( {renderSwapBox()} )} {selectedChartOption !== ChartOptions.PRO && !isInProMode && ( diff --git a/src/react-app-env.d.ts b/src/react-app-env.d.ts index 16da607ee..ef1cc9b4c 100644 --- a/src/react-app-env.d.ts +++ b/src/react-app-env.d.ts @@ -18,6 +18,11 @@ interface Window { removeListener?: (...args: any[]) => void request?: (args: EthereumProviderRequestArguments) => Promise isCoinbaseWallet?: boolean + isBraveWallet?: boolean + overrideIsMetaMask?: boolean + selectedProvider?: { + isCoinbaseWallet?: boolean + } } web3?: Record } diff --git a/src/services/AdvancedTradingView/useAdvancedTradingView.hook.ts b/src/services/AdvancedTradingView/useAdvancedTradingView.hook.ts index beb2eca84..457661961 100644 --- a/src/services/AdvancedTradingView/useAdvancedTradingView.hook.ts +++ b/src/services/AdvancedTradingView/useAdvancedTradingView.hook.ts @@ -3,9 +3,9 @@ import { ChainId, Currency, Token, WETH, WMATIC, WXDAI } from '@swapr/sdk' import { useEffect, useMemo, useRef, useState } from 'react' import { useDispatch } from 'react-redux' -import { useActiveWeb3React } from '../../hooks' import { useToken } from '../../hooks/Tokens' import { useRouter } from '../../hooks/useRouter' +import { useWeb3ReactCore } from '../../hooks/useWeb3ReactCore' import store, { AppState } from '../../state' import { useSwapState } from '../../state/swap/hooks' import { adapters } from './adapters/adapters.config' @@ -44,7 +44,7 @@ const calculateAmountToFetch = (chainId: ChainId | undefined, amountToFetch: num } export const useAdvancedTradingView = () => { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const { navigate } = useRouter() diff --git a/src/services/AdvancedTradingView/useAllTrades.hook.ts b/src/services/AdvancedTradingView/useAllTrades.hook.ts index d5005e360..254acc6b8 100644 --- a/src/services/AdvancedTradingView/useAllTrades.hook.ts +++ b/src/services/AdvancedTradingView/useAllTrades.hook.ts @@ -1,7 +1,7 @@ import { useMemo } from 'react' import { useSelector } from 'react-redux' -import { useActiveWeb3React } from '../../hooks' +import { useWeb3ReactCore } from '../../hooks/useWeb3ReactCore' import { Transaction, TransactionStatus } from '../../pages/Account/Account.types' import { formattedTransactions as formatTransactions } from '../../pages/Account/accountUtils' import { useAllBridgeTransactions, useAllSwapTransactions } from '../../state/transactions/hooks' @@ -19,7 +19,7 @@ export const useAllTrades = (): { liquidityHistory: AdvancedViewTransaction[] hasMore: { hasMoreActivity: boolean; hasMoreTrades: boolean } } => { - const { account } = useActiveWeb3React() + const { account } = useWeb3ReactCore() const hasMore = useSelector(selectHasMoreData) const { uniswapV3LiquidityHistory, uniswapV3TradeHistory } = useSelector(selectUniswapV3AllData) const { baseAdapterTradeHistory, baseAdapterLiquidityHistory } = useSelector(selectAllDataFromAdapters) diff --git a/src/services/EcoBridge/EcoBridge.hooks.ts b/src/services/EcoBridge/EcoBridge.hooks.ts index 28c5e8f90..4b6b56767 100644 --- a/src/services/EcoBridge/EcoBridge.hooks.ts +++ b/src/services/EcoBridge/EcoBridge.hooks.ts @@ -3,10 +3,10 @@ import { ChainId, Currency, Token } from '@swapr/sdk' import { useCallback, useEffect, useMemo, useState } from 'react' import { useDispatch, useSelector } from 'react-redux' -import { useActiveWeb3React } from '../../hooks' import { parseStringOrBytes32 } from '../../hooks/Tokens' import { useBytes32TokenContract, useTokenContract, useWrappingToken } from '../../hooks/useContract' import { useNativeCurrency } from '../../hooks/useNativeCurrency' +import { useWeb3ReactCore } from '../../hooks/useWeb3ReactCore' import { AppState } from '../../state' import { WrappedTokenInfo } from '../../state/lists/wrapped-token-info' import { NEVER_RELOAD, useSingleCallResult } from '../../state/multicall/hooks' @@ -35,14 +35,14 @@ import { import { ecoBridgeUIActions } from './store/UI.reducer' export const useBridgeSupportedTokens = () => { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const tokens = useSelector((state: AppState) => selectBridgeSupportedTokensOnChain(state, chainId ?? 0)) return tokens } export function useBridgeToken(tokenAddress?: string, chainId?: ChainId): Token | undefined | null { - const { chainId: activeChainId } = useActiveWeb3React() + const { chainId: activeChainId } = useWeb3ReactCore() const selectedChainId = chainId ?? activeChainId const allTokens = useSelector(selectBridgeTokens) const tokensOnChain = allTokens[selectedChainId ?? 0] @@ -110,7 +110,7 @@ export const useBridgeCurrency = (currencyId: string | undefined, chainId: Chain } export const useBridgeTokenInfo = (currency?: Currency, chainId?: ChainId): WrappedTokenInfo | undefined => { - const { chainId: activeChainId } = useActiveWeb3React() + const { chainId: activeChainId } = useWeb3ReactCore() const allTokens = useSelector(selectBridgeTokens) const selectedChainId = chainId || activeChainId @@ -276,7 +276,7 @@ export function useBridgeActionHandlers(): { } export const useBridgeInfo = () => { - const { account, chainId } = useActiveWeb3React() + const { account, chainId } = useWeb3ReactCore() const { from, to, isBridgeSwapActive } = useSelector((state: AppState) => state.ecoBridge.ui) @@ -326,7 +326,7 @@ export const useBridgeTxsFilter = () => { export const useBridgeCollectHandlers = () => { const dispatch = useDispatch() - const { account } = useActiveWeb3React() + const { account } = useWeb3ReactCore() const collectableTx = useSelector((state: AppState) => selectBridgeCollectableTx(state, account ?? undefined)) const [isCollecting, setIsCollecting] = useState(false) diff --git a/src/services/EcoBridge/EcoBridge.providers.ts b/src/services/EcoBridge/EcoBridge.providers.ts index 89c0fbda2..2d08602ba 100644 --- a/src/services/EcoBridge/EcoBridge.providers.ts +++ b/src/services/EcoBridge/EcoBridge.providers.ts @@ -1,8 +1,7 @@ import { JsonRpcProvider } from '@ethersproject/providers' import { ChainId } from '@swapr/sdk' -import { INFURA_PROJECT_ID } from '../../connectors' -import { NETWORK_DETAIL } from '../../constants' +import { INFURA_PROJECT_ID, NETWORK_DETAIL } from '../../constants' import { EcoBridgeProviders } from './EcoBridge.types' const addInfuraKey = (rpcUrl: string) => { diff --git a/src/services/EcoBridge/EcoBridgeProvider.tsx b/src/services/EcoBridge/EcoBridgeProvider.tsx index 6507f4538..34ceb9c61 100644 --- a/src/services/EcoBridge/EcoBridgeProvider.tsx +++ b/src/services/EcoBridge/EcoBridgeProvider.tsx @@ -1,14 +1,14 @@ import { createContext, ReactNode, useContext, useEffect, useState } from 'react' -import { useActiveWeb3React } from '../../hooks' +import { useWeb3ReactCore } from '../../hooks/useWeb3ReactCore' import store from '../../state' import { EcoBridge } from './EcoBridge' import { ecoBridgeConfig } from './EcoBridge.config' export const EcoBridgeContext = createContext(null) -export function EcoBridgeProvider({ children }: { children: ReactNode }) { - const { library, account, chainId } = useActiveWeb3React() +export const EcoBridgeProvider = ({ children }: { children: ReactNode }) => { + const { provider, account, chainId } = useWeb3ReactCore() const [ecoBridge, setEcoBridge] = useState(null) useEffect(() => { @@ -18,24 +18,24 @@ export function EcoBridgeProvider({ children }: { children: ReactNode }) { setEcoBridge(ecoBridgeInstance) } - if (ecoBridge && account && library && chainId) { + if (ecoBridge && account && provider && chainId) { if (!ecoBridge.ready) { await ecoBridge.init({ account, activeChainId: chainId, - activeProvider: library, + activeProvider: provider, }) } else { await ecoBridge.updateSigner({ account, activeChainId: chainId, - activeProvider: library, + activeProvider: provider, }) } } } initEcoBridge() - }, [account, chainId, library, ecoBridge]) + }, [account, chainId, provider, ecoBridge]) return {children} } diff --git a/src/state/application/actions.ts b/src/state/application/actions.ts index a98ea2340..29e735649 100644 --- a/src/state/application/actions.ts +++ b/src/state/application/actions.ts @@ -24,6 +24,7 @@ export enum ApplicationModal { UNSUPPORTED_NETWORK, SIMPLE_SETTINGS, EXPEDITIONS, + WALLET_PENDING, } export enum MainnetGasPrice { diff --git a/src/state/application/hooks.tsx b/src/state/application/hooks.tsx index 3f6ff016f..9fc14eeaf 100644 --- a/src/state/application/hooks.tsx +++ b/src/state/application/hooks.tsx @@ -3,12 +3,12 @@ import { useDispatch, useSelector } from 'react-redux' import { toast } from 'react-toastify' import { TransactionPopup } from '../../components/Popups/TransactionPopup' -import { useActiveWeb3React } from '../../hooks' +import { useWeb3ReactCore } from '../../hooks/useWeb3ReactCore' import { AppDispatch, AppState } from '../index' import { ApplicationModal, MainnetGasPrice, PopupContent, setOpenModal } from './actions' export function useBlockNumber(): number | undefined { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() return useSelector((state: AppState) => state.application.blockNumber[chainId ?? -1]) } diff --git a/src/state/application/updater.ts b/src/state/application/updater.ts index 06de16e32..3dbf3efb7 100644 --- a/src/state/application/updater.ts +++ b/src/state/application/updater.ts @@ -3,13 +3,13 @@ import { ChainId } from '@swapr/sdk' import { useCallback, useEffect, useState } from 'react' import { useDispatch } from 'react-redux' -import { useActiveWeb3React } from '../../hooks' import useDebounce from '../../hooks/useDebounce' import useIsWindowVisible from '../../hooks/useIsWindowVisible' +import { useWeb3ReactCore } from '../../hooks/useWeb3ReactCore' import { MainnetGasPrice, setConnectorInfo, updateBlockNumber, updateMainnetGasPrices } from './actions' export default function Updater(): null { - const { library, chainId, account } = useActiveWeb3React() + const { provider, chainId, account } = useWeb3ReactCore() const dispatch = useDispatch() const windowVisible = useIsWindowVisible() @@ -38,21 +38,21 @@ export default function Updater(): null { // attach/detach listeners useEffect(() => { - if (!library || !chainId || !windowVisible) return undefined + if (!provider || !chainId || !windowVisible) return setState({ chainId, blockNumber: null }) - library + provider .getBlockNumber() .then(blockNumberCallback) .catch(error => console.error(`Failed to get block number for chainId: ${chainId}`, error)) - library.on('block', blockNumberCallback) + provider.on('block', blockNumberCallback) return () => { - library.removeListener('block', blockNumberCallback) + provider.removeListener('block', blockNumberCallback) } - }, [dispatch, chainId, library, blockNumberCallback, windowVisible]) + }, [dispatch, chainId, provider, blockNumberCallback, windowVisible]) const debouncedState = useDebounce(state, 100) const debouncedMainnetGasPrices = useDebounce(mainnetGasPrices, 100) diff --git a/src/state/burn/hooks.ts b/src/state/burn/hooks.ts index b1ca2efe8..854efe808 100644 --- a/src/state/burn/hooks.ts +++ b/src/state/burn/hooks.ts @@ -5,7 +5,7 @@ import { useDispatch, useSelector } from 'react-redux' import { usePair } from '../../data/Reserves' import { useTotalSupply } from '../../data/TotalSupply' -import { useActiveWeb3React } from '../../hooks' +import { useWeb3ReactCore } from '../../hooks/useWeb3ReactCore' import { wrappedCurrency } from '../../utils/wrappedCurrency' import { AppDispatch, AppState } from '../index' import { tryParseAmount } from '../swap/hooks' @@ -29,7 +29,7 @@ export function useDerivedBurnInfo( } error?: string } { - const { account, chainId } = useActiveWeb3React() + const { account, chainId } = useWeb3ReactCore() const { independentField, typedValue } = useBurnState() diff --git a/src/state/fees/updater.ts b/src/state/fees/updater.ts index 2fc835a5a..684ec5026 100644 --- a/src/state/fees/updater.ts +++ b/src/state/fees/updater.ts @@ -3,21 +3,21 @@ import { Fetcher } from '@swapr/sdk' import { useEffect } from 'react' import { useDispatch } from 'react-redux' -import { useActiveWeb3React } from '../../hooks' +import { useWeb3ReactCore } from '../../hooks/useWeb3ReactCore' import { chainSupportsSWPR } from '../../utils/chainSupportsSWPR' import { setProtocolFee, setSwapFees } from './actions' export default function Updater() { - const { library, chainId } = useActiveWeb3React() + const { provider, chainId } = useWeb3ReactCore() const dispatch = useDispatch() const isSWPRSupportedChain = chainSupportsSWPR(chainId) useEffect(() => { - if (library && chainId && isSWPRSupportedChain) + if (provider && chainId && isSWPRSupportedChain) Promise.all([ - Fetcher.fetchAllSwapFees(chainId, {}, library as any), - Fetcher.fetchProtocolFee(chainId, library as any), + Fetcher.fetchAllSwapFees(chainId, {}, provider as any), + Fetcher.fetchProtocolFee(chainId, provider as any), ]) .then(([swapFees, protocolFee]) => { if (swapFees) dispatch(setSwapFees({ swapFees })) @@ -33,7 +33,7 @@ export default function Updater() { console.error('Cancelled fetch for fees, error:', error) return }) - }, [library, chainId, dispatch, isSWPRSupportedChain]) + }, [provider, chainId, dispatch, isSWPRSupportedChain]) return null } diff --git a/src/state/lists/hooks.ts b/src/state/lists/hooks.ts index d106d9830..00bc08229 100644 --- a/src/state/lists/hooks.ts +++ b/src/state/lists/hooks.ts @@ -8,7 +8,7 @@ import { useSelector } from 'react-redux' import { NETWORK_DETAIL, ZERO_ADDRESS } from '../../constants' import { UNSUPPORTED_LIST_URLS } from '../../constants/lists' import UNSUPPORTED_TOKEN_LIST from '../../constants/tokenLists/swapr-unsupported.tokenlist.json' -import { useActiveWeb3React } from '../../hooks' +import { useWeb3ReactCore } from '../../hooks/useWeb3ReactCore' import sortByListPriority from '../../utils/listSort' import { AppState } from '../index' import { WrappedTokenInfo } from './wrapped-token-info' @@ -164,14 +164,14 @@ export function useCombinedActiveList(): TokenAddressMap { export function useAllTokensFromActiveListsOnCurrentChain(): Readonly<{ [tokenAddress: string]: { token: WrappedTokenInfo; list: TokenList } }> { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const activeListUrls = useActiveListUrls() const combinedList = useCombinedTokenMapFromUrls(activeListUrls) return useMemo(() => combinedList[chainId || ChainId.MAINNET], [chainId, combinedList]) } export function useTokenInfoFromActiveListOnCurrentChain(currency?: Currency): WrappedTokenInfo | undefined { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const activeListUrls = useActiveListUrls() const combinedList = useCombinedTokenMapFromUrls(activeListUrls) diff --git a/src/state/lists/updater.ts b/src/state/lists/updater.ts index d00c1a274..d3dc95d76 100644 --- a/src/state/lists/updater.ts +++ b/src/state/lists/updater.ts @@ -3,16 +3,16 @@ import { useCallback, useEffect } from 'react' import { useDispatch } from 'react-redux' import { UNSUPPORTED_LIST_URLS } from '../../constants/lists' -import { useActiveWeb3React } from '../../hooks' import { useFetchCarrotListCallback, useFetchListCallback } from '../../hooks/useFetchListCallback' import useInterval from '../../hooks/useInterval' import useIsWindowVisible from '../../hooks/useIsWindowVisible' +import { useWeb3ReactCore } from '../../hooks/useWeb3ReactCore' import { AppDispatch } from '../index' import { acceptListUpdate } from './actions' import { useActiveListUrls, useAllLists } from './hooks' export default function Updater(): null { - const { library, chainId, account } = useActiveWeb3React() + const { provider, chainId, account } = useWeb3ReactCore() const dispatch = useDispatch() const isWindowVisible = useIsWindowVisible() @@ -31,8 +31,8 @@ export default function Updater(): null { fetchCarrotList().catch((error: Error) => console.debug('carrot interval list fetching error', error)) }, [isWindowVisible, chainId, lists, fetchCarrotList, fetchList]) - // fetch all lists every 10 minutes, but only after we initialize library - useInterval(fetchAllListsCallback, library ? 1000 * 60 * 10 : null) + // fetch all lists every 10 minutes, but only after we initialize provider + useInterval(fetchAllListsCallback, provider ? 1000 * 60 * 10 : null) useEffect(() => { if (account) { @@ -57,7 +57,7 @@ export default function Updater(): null { if (carrotList && !carrotList.current && !carrotList.loadingRequestId && !carrotList.error) { fetchCarrotList().catch((error: Error) => console.debug('carrot list added fetching error', error)) } - }, [dispatch, fetchCarrotList, fetchList, library, lists]) + }, [dispatch, fetchCarrotList, fetchList, provider, lists]) // if any lists from unsupported lists are loaded, check them too (in case new updates since last visit) useEffect(() => { @@ -67,7 +67,7 @@ export default function Updater(): null { fetchList(listUrl).catch((error: Error) => console.debug('list added fetching error', error)) } }) - }, [chainId, dispatch, fetchList, library, lists]) + }, [chainId, dispatch, fetchList, provider, lists]) // automatically update lists if versions are minor/patch useEffect(() => { diff --git a/src/state/mint/hooks.ts b/src/state/mint/hooks.ts index 9ea60b856..4f92671c0 100644 --- a/src/state/mint/hooks.ts +++ b/src/state/mint/hooks.ts @@ -5,8 +5,8 @@ import { useDispatch, useSelector } from 'react-redux' import { PairState, usePair } from '../../data/Reserves' import { useTotalSupply } from '../../data/TotalSupply' -import { useActiveWeb3React } from '../../hooks' import { useNativeCurrency } from '../../hooks/useNativeCurrency' +import { useWeb3ReactCore } from '../../hooks/useWeb3ReactCore' import { wrappedCurrency, wrappedCurrencyAmount } from '../../utils/wrappedCurrency' import { AppDispatch, AppState } from '../index' import { tryParseAmount } from '../swap/hooks' @@ -35,7 +35,7 @@ export function useDerivedMintInfo( poolTokenPercentage?: Percent error?: string } { - const { account, chainId } = useActiveWeb3React() + const { account, chainId } = useWeb3ReactCore() const nativeCurrency = useNativeCurrency() const { independentField, typedValue, otherTypedValue } = useMintState() diff --git a/src/state/multi-chain-links/updater.tsx b/src/state/multi-chain-links/updater.tsx index 6fee741aa..03829e0d8 100644 --- a/src/state/multi-chain-links/updater.tsx +++ b/src/state/multi-chain-links/updater.tsx @@ -1,11 +1,12 @@ import { useEffect } from 'react' import { useSearchParams } from 'react-router-dom' -import { useActiveWeb3React } from '../../hooks' +import { isChainSupportedByConnector } from '../../connectors/utils' +import { useWeb3ReactCore } from '../../hooks/useWeb3ReactCore' import { useIsSwitchingToCorrectChain, useIsSwitchingToCorrectChainUpdater } from './hooks' export default function Updater(): null { - const { chainId, connector } = useActiveWeb3React() + const { chainId, connector } = useWeb3ReactCore() const [searchParams, setSearchParams] = useSearchParams() const switchingToCorrectChain = useIsSwitchingToCorrectChain() const updateSwitchingToCorrectChain = useIsSwitchingToCorrectChainUpdater() @@ -26,10 +27,9 @@ export default function Updater(): null { if (!chainId || !connector) return const stringChainId = chainId.toString() const requiredChainId = searchParams.get('chainId') + const requiredChainIdSupported = - requiredChainId && - connector.supportedChainIds && - connector.supportedChainIds.indexOf(parseInt(requiredChainId)) >= 0 + requiredChainId && isChainSupportedByConnector(connector, parseInt(requiredChainId)) if (!requiredChainId) updateSwitchingToCorrectChain(false) if (requiredChainId && requiredChainIdSupported && switchingToCorrectChain) { diff --git a/src/state/multicall/hooks.ts b/src/state/multicall/hooks.ts index 031f0e746..41e1cd098 100644 --- a/src/state/multicall/hooks.ts +++ b/src/state/multicall/hooks.ts @@ -6,7 +6,7 @@ import { useEffect, useMemo } from 'react' import { useDispatch, useSelector } from 'react-redux' import { AppState } from '..' -import { useActiveWeb3React } from '../../hooks' +import { useWeb3ReactCore } from '../../hooks/useWeb3ReactCore' import { debounce } from '../../utils/debounce' import { useBlockNumber } from '../application/hooks' import { addMulticallListeners, ListenerOptions, removeMulticallListeners } from './actions' @@ -51,7 +51,7 @@ function useCallsData( calls: (Call | undefined)[], { blocksPerFetch }: ListenerOptions = { blocksPerFetch: 1 } ): CallResult[] { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const callResults = useSelector(state => state.multicall.callResults) const dispatch = useDispatch() diff --git a/src/state/multicall/updater.tsx b/src/state/multicall/updater.tsx index a81d5b353..52b8e7ca2 100644 --- a/src/state/multicall/updater.tsx +++ b/src/state/multicall/updater.tsx @@ -2,9 +2,9 @@ import { Contract } from 'ethers' import { useEffect, useMemo, useRef } from 'react' import { useDispatch, useSelector } from 'react-redux' -import { useActiveWeb3React } from '../../hooks' import { useMulticallContract } from '../../hooks/useContract' import useDebounce from '../../hooks/useDebounce' +import { useWeb3ReactCore } from '../../hooks/useWeb3ReactCore' import chunkArray from '../../utils/chunkArray' import { retry, RetryableError } from '../../utils/retry' import { useBlockNumber } from '../application/hooks' @@ -120,7 +120,7 @@ export default function Updater(): null { // wait for listeners to settle before triggering updates const debouncedListeners = useDebounce(state.callListeners, 100) const latestBlockNumber = useBlockNumber() - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const multicallContract = useMulticallContract() const cancellations = useRef<{ blockNumber: number diff --git a/src/state/swap/hooks.ts b/src/state/swap/hooks.ts index 73246a73a..563d64342 100644 --- a/src/state/swap/hooks.ts +++ b/src/state/swap/hooks.ts @@ -9,12 +9,12 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { useDispatch, useSelector } from 'react-redux' import { PRE_SELECT_OUTPUT_CURRENCY_ID, SWAP_INPUT_ERRORS } from '../../constants/index' -import { useActiveWeb3React } from '../../hooks' import { useCurrency } from '../../hooks/Tokens' import { useAbortController } from '../../hooks/useAbortController' import useENS from '../../hooks/useENS' import { useNativeCurrency } from '../../hooks/useNativeCurrency' import { useParsedQueryString } from '../../hooks/useParsedQueryString' +import { useWeb3ReactCore } from '../../hooks/useWeb3ReactCore' import { EcoRouterResults, getExactIn as getExactInFromEcoRouter, @@ -119,8 +119,7 @@ const quoteTTL = 5 * 60 * 1000 // from the current swap inputs, compute the best trade and return it. export function useDerivedSwapInfo(platformOverride?: RoutablePlatform): UseDerivedSwapInfoResult { - const { account, chainId, library: provider } = useActiveWeb3React() - // Get all options for the input and output currencies + const { account, chainId, provider } = useWeb3ReactCore() const { independentField, typedValue, @@ -427,7 +426,7 @@ export function queryParametersToSwapState( export function useDefaultsFromURLSearch(): | { inputCurrencyId: string | undefined; outputCurrencyId: string | undefined } | undefined { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const nativeCurrency = useNativeCurrency() const dispatch = useDispatch() const parsedQs = useParsedQueryString() diff --git a/src/state/transactions/hooks.tsx b/src/state/transactions/hooks.tsx index 1ff6642e4..a6643861f 100644 --- a/src/state/transactions/hooks.tsx +++ b/src/state/transactions/hooks.tsx @@ -4,7 +4,7 @@ import { ChainId } from '@swapr/sdk' import { useCallback, useMemo } from 'react' import { useDispatch, useSelector } from 'react-redux' -import { useActiveWeb3React } from '../../hooks' +import { useWeb3ReactCore } from '../../hooks/useWeb3ReactCore' import { type BridgeTransaction, TransactionTypes } from '../../pages/Account/Account.types' import { selectBridgeTransactions } from '../../services/EcoBridge/store/EcoBridge.selectors' import { AppDispatch, AppState } from '../index' @@ -35,7 +35,7 @@ export function useTransactionAdder(): ( response: SwaprTransactionResponse, customData?: TransactionAdderCustomData ) => void { - const { chainId, account } = useActiveWeb3React() + const { chainId, account } = useWeb3ReactCore() const dispatch = useDispatch() return useCallback( @@ -67,7 +67,7 @@ const addNetworkToTransaction = (transaction: AllTransactions, networkId: ChainI } // returns all the transactions for the current chain export function useAllSwapTransactions(allNetwork = false): AllTransactions { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const allSwapTransactions = useSelector((state: AppState) => state.transactions) @@ -90,7 +90,7 @@ export function useAllSwapTransactions(allNetwork = false): AllTransactions { } export function useAllBridgeTransactions(allNetwork = false): BridgeTransaction[] { - const { chainId, account } = useActiveWeb3React() + const { chainId, account } = useWeb3ReactCore() const listByAddress = useListsByAddress() const allBridgeTransactions = useSelector((state: AppState) => selectBridgeTransactions(state, account ?? undefined)) diff --git a/src/state/transactions/updater.tsx b/src/state/transactions/updater.tsx index 316891a7b..a5126907f 100644 --- a/src/state/transactions/updater.tsx +++ b/src/state/transactions/updater.tsx @@ -4,7 +4,7 @@ import contractNetworks from '@cowprotocol/contracts/networks.json' import { useCallback, useEffect, useMemo } from 'react' import { useDispatch, useSelector } from 'react-redux' -import { useActiveWeb3React } from '../../hooks' +import { useWeb3ReactCore } from '../../hooks/useWeb3ReactCore' import { retry, RetryableError, RetryOptions } from '../../utils/retry' import { updateBlockNumber } from '../application/actions' import { useAddPopup, useBlockNumber } from '../application/hooks' @@ -43,7 +43,7 @@ const RETRY_OPTIONS_BY_CHAIN_ID: { [chainId: number]: RetryOptions } = { const DEFAULT_RETRY_OPTIONS: RetryOptions = { n: 1, minWait: 0, maxWait: 0 } export default function Updater(): null { - const { chainId, library } = useActiveWeb3React() + const { chainId, provider } = useWeb3ReactCore() const lastBlockNumber = useBlockNumber() @@ -58,11 +58,11 @@ export default function Updater(): null { const getTransactionReceipt = useCallback( (hash: string) => { - if (!library || !chainId) throw new Error('No library or chainId') + if (!provider || !chainId) throw new Error('No provider or chainId') const retryOptions = RETRY_OPTIONS_BY_CHAIN_ID[chainId] ?? DEFAULT_RETRY_OPTIONS return retry( () => - library.getTransactionReceipt(hash).then(receipt => { + provider.getTransactionReceipt(hash).then(receipt => { if (receipt === null) { console.debug('Retrying for hash', hash) throw new RetryableError() @@ -72,7 +72,7 @@ export default function Updater(): null { retryOptions ) }, - [chainId, library] + [chainId, provider] ) /** @@ -80,7 +80,7 @@ export default function Updater(): null { */ const getGnosisProtocolOrder = useCallback( (orderId: string) => { - if (!chainId) throw new Error('No library or chainId') + if (!chainId) throw new Error('No provider or chainId') const retryOptions = RETRY_OPTIONS_BY_CHAIN_ID[chainId] ?? DEFAULT_RETRY_OPTIONS return retry(async () => { const res = await CoWTrade.getCowSdk(chainId).cowApi.getOrder(orderId) @@ -95,7 +95,7 @@ export default function Updater(): null { ) useEffect(() => { - if (!chainId || !library || !lastBlockNumber) return + if (!chainId || !provider || !lastBlockNumber) return const cancels = Object.values(transactions) .filter(({ hash }) => shouldCheck(lastBlockNumber, transactions[hash])) @@ -207,7 +207,7 @@ export default function Updater(): null { } }, [ chainId, - library, + provider, transactions, lastBlockNumber, dispatch, diff --git a/src/state/user/actions.ts b/src/state/user/actions.ts index 9cd5d0ea1..f9c5dc995 100644 --- a/src/state/user/actions.ts +++ b/src/state/user/actions.ts @@ -1,5 +1,6 @@ import { createAction } from '@reduxjs/toolkit' +import { ConnectorType } from '../../constants' import { MainnetGasPrice } from '../application/actions' import { ChartOptions, SwapTabs } from './reducer' @@ -36,6 +37,13 @@ export const toggleURLWarning = createAction('app/toggleURLWarning') export const updateUserAdvancedSwapDetails = createAction<{ userAdvancedSwapDetails: boolean }>( 'user/updateUserAdvancedSwapDetails' ) +export const setConnectorError = createAction<{ connector: ConnectorType; connectorError: string | undefined }>( + 'user/setConnectorError' +) +export const updatePendingConnector = createAction<{ pendingConnector: ConnectorType }>('user/updatePendingConnector') +export const updateSelectedConnector = createAction<{ selectedConnector: ConnectorType }>( + 'user/updateSelectedConnector' +) export const updateSelectedChartOption = createAction<{ selectedChartOption: ChartOptions }>( 'user/updateSelectedChartOption' ) diff --git a/src/state/user/hooks.tsx b/src/state/user/hooks.tsx index 44b04ba6e..17178de32 100644 --- a/src/state/user/hooks.tsx +++ b/src/state/user/hooks.tsx @@ -6,8 +6,8 @@ import { shallowEqual, useDispatch, useSelector } from 'react-redux' import { BASES_TO_TRACK_LIQUIDITY_FOR, PINNED_PAIRS } from '../../constants' import { PairState, usePairs } from '../../data/Reserves' -import { useActiveWeb3React } from '../../hooks' import { useAllTokens } from '../../hooks/Tokens' +import { useWeb3ReactCore } from '../../hooks/useWeb3ReactCore' import { MainnetGasPrice } from '../application/actions' import { AppDispatch, AppState } from '../index' import { @@ -264,7 +264,7 @@ export function useRemoveUserAddedToken(): (chainId: number, address: string) => } export function useUserAddedTokens(): Token[] { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const serializedTokensMap = useSelector(({ user: { tokens } }) => tokens) return useMemo(() => { @@ -296,7 +296,7 @@ export function usePairRemover(): (pair: Pair) => void { } export function useUserAddedPairs(): Pair[] { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const serializedPairsMap = useSelector(({ user: { pairs } }) => pairs) const simplifiedPairs = Object.values(serializedPairsMap[chainId as ChainId] ?? {}).map(deserializeSimplifiedPair) const pairs = usePairs(simplifiedPairs) @@ -352,7 +352,7 @@ export function toDXSwapLiquidityToken([tokenA, tokenB]: [Token, Token]): Token * Returns all the pairs of tokens that are tracked by the user for the current chain ID. */ export function useTrackedTokenPairs(): [Token, Token][] { - const { chainId } = useActiveWeb3React() + const { chainId } = useWeb3ReactCore() const tokens = useAllTokens() // get user added tokens to be used as base diff --git a/src/state/user/reducer.ts b/src/state/user/reducer.ts index 578d44362..c72e12f34 100644 --- a/src/state/user/reducer.ts +++ b/src/state/user/reducer.ts @@ -1,6 +1,11 @@ import { createReducer } from '@reduxjs/toolkit' -import { DEFAULT_DEADLINE_FROM_NOW, DEFAULT_USER_MULTIHOP_ENABLED, INITIAL_ALLOWED_SLIPPAGE } from '../../constants' +import { + ConnectorType, + DEFAULT_DEADLINE_FROM_NOW, + DEFAULT_USER_MULTIHOP_ENABLED, + INITIAL_ALLOWED_SLIPPAGE, +} from '../../constants' import { MainnetGasPrice } from '../application/actions' import { updateVersion } from '../global/actions' import { @@ -10,9 +15,12 @@ import { removeSerializedToken, SerializedPair, SerializedToken, + setConnectorError, toggleURLWarning, updateMatchesDarkMode, + updatePendingConnector, updateSelectedChartOption, + updateSelectedConnector, updateSelectedSwapTab, updateUserAdvancedSwapDetails, updateUserDarkMode, @@ -78,6 +86,17 @@ export interface UserState { timestamp: number URLWarningVisible: boolean userAdvancedSwapDetails: boolean + + // We want the user to be able to define which wallet they want to use, even if there are multiple connected wallets via web3-react. + // If a user had previously connected a wallet but didn't have a wallet override set (because they connected prior to this field being added), + // we want to handle that case by backfilling them manually. Once we backfill, we set the backfilled field to `true`. + // After some period of time, our active users will have this property set so we can likely remove the backfilling logic. + connector: { + pending?: ConnectorType + selected?: ConnectorType + selectedBackfilled: boolean + errorByType: Record + } } function pairKey(token0Address: string, token1Address: string) { @@ -99,6 +118,17 @@ export const initialState: UserState = { timestamp: currentTimestamp(), URLWarningVisible: true, userAdvancedSwapDetails: true, + connector: { + pending: undefined, + selected: undefined, + selectedBackfilled: false, + errorByType: { + [ConnectorType.METAMASK]: undefined, + [ConnectorType.WALLET_CONNECT]: undefined, + [ConnectorType.COINBASE]: undefined, + [ConnectorType.NETWORK]: undefined, + }, + }, } export default createReducer(initialState, builder => @@ -195,6 +225,17 @@ export default createReducer(initialState, builder => .addCase(updateUserAdvancedSwapDetails, (state, action) => { state.userAdvancedSwapDetails = action.payload.userAdvancedSwapDetails }) + .addCase(updateSelectedConnector, (state, action) => { + state.connector.selected = action.payload.selectedConnector + state.connector.selectedBackfilled = true + }) + .addCase(updatePendingConnector, (state, action) => { + state.connector.pending = action.payload.pendingConnector + }) + .addCase(setConnectorError, (state, action) => { + const { connector, connectorError } = action.payload + state.connector.errorByType[connector] = connectorError + }) .addCase(updateSelectedChartOption, (state, action) => { state.selectedChartOption = action.payload.selectedChartOption }) diff --git a/src/state/wallet/hooks.ts b/src/state/wallet/hooks.ts index 092cbe7dc..322a7e029 100644 --- a/src/state/wallet/hooks.ts +++ b/src/state/wallet/hooks.ts @@ -3,14 +3,14 @@ import { Currency, CurrencyAmount, JSBI, Token, TokenAmount } from '@swapr/sdk' import { useMemo } from 'react' import { ERC20_INTERFACE } from '../../constants/abis/erc20' -import { useActiveWeb3React } from '../../hooks' import { useAllTokens } from '../../hooks/Tokens' import { useMulticallContract } from '../../hooks/useContract' +import { useWeb3ReactCore } from '../../hooks/useWeb3ReactCore' import { isAddress } from '../../utils' import { useMultipleContractSingleData, useSingleContractMultipleData } from '../multicall/hooks' export function useNativeCurrencyBalance(): CurrencyAmount | undefined { - const { chainId, account } = useActiveWeb3React() + const { chainId, account } = useWeb3ReactCore() const multicallContract = useMulticallContract() const results = useSingleContractMultipleData( @@ -111,7 +111,7 @@ export function useCurrencyBalance(account?: string, currency?: Currency): Curre // mimics useAllBalances export function useAllTokenBalances(): { [tokenAddress: string]: TokenAmount | undefined } { - const { account } = useActiveWeb3React() + const { account } = useWeb3ReactCore() const allTokens = useAllTokens() const allTokensArray = useMemo(() => Object.values(allTokens ?? {}), [allTokens]) const balances = useTokenBalances(account ?? undefined, allTokensArray) diff --git a/src/utils/getErrorMessage.ts b/src/utils/getErrorMessage.ts new file mode 100644 index 000000000..d5319c2f6 --- /dev/null +++ b/src/utils/getErrorMessage.ts @@ -0,0 +1,28 @@ +type ErrorWithMessage = { + message: string +} + +export const isErrorWithMessage = (error: unknown): error is ErrorWithMessage => { + return ( + typeof error === 'object' && + error !== null && + 'message' in error && + typeof (error as Record).message === 'string' + ) +} + +export const toErrorWithMessage = (maybeError: unknown): ErrorWithMessage => { + if (isErrorWithMessage(maybeError)) return maybeError + + try { + return new Error(JSON.stringify(maybeError)) + } catch { + // fallback in case there's an error stringifying the maybeError + // like with circular references for example. + return new Error(String(maybeError)) + } +} + +export const getErrorMessage = (error: unknown) => { + return toErrorWithMessage(error).message +} diff --git a/src/utils/index.ts b/src/utils/index.ts index 08594a5b4..34da5bcd6 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -11,7 +11,6 @@ import { commify } from 'ethers/lib/utils' import styled from 'styled-components' import { ReactComponent as ConnectedSvg } from '../assets/images/connected.svg' -import { NetworkDetails } from '../constants' import { TokenAddressMap } from '../state/lists/hooks' import { SwapProtocol } from '../state/transactions/reducer' @@ -233,30 +232,6 @@ export const calculatePercentage = (value: number, percentage: number): number = return Math.round((percentage / 100) * value) } -export const switchOrAddNetwork = (networkDetails?: NetworkDetails, account?: string) => { - if (!window.ethereum || !window.ethereum.request || !window.ethereum.isMetaMask || !networkDetails || !account) - return Promise.reject() - return window.ethereum - .request({ - method: 'wallet_switchEthereumChain', - params: [{ chainId: networkDetails.chainId }], - }) - .catch(error => { - if (error.code !== 4902) { - console.error('error switching to chain id', networkDetails.chainId, error) - } - if (!window.ethereum || !window.ethereum.request) return - window.ethereum - .request({ - method: 'wallet_addEthereumChain', - params: [{ ...networkDetails }, account], - }) - .catch(error => { - console.error('error adding chain with id', networkDetails.chainId, error) - }) - }) -} - export const StyledConnectedIcon = styled(ConnectedSvg)<{ width?: string; padding?: string; margin?: string }>` min-width: ${props => (props.width ? props.width : '22px')}; padding: ${props => (props.padding ? props.padding : '0')}; diff --git a/src/utils/networksList.ts b/src/utils/networksList.ts index d1c2e662a..cf8b9a492 100644 --- a/src/utils/networksList.ts +++ b/src/utils/networksList.ts @@ -7,22 +7,25 @@ export const getNetworkInfo = (chainId: ChainId, customPreset: NetworkOptionsPre const network = customPreset.find(net => { return net.chainId === chainId }) + + const networkDetails = NETWORK_DETAIL[chainId] ?? NETWORK_DETAIL[ChainId.MAINNET] + return { name: network ? network.name : '', //name displayed in swapr logoSrc: network ? network.logoSrc : '', color: network ? network.color : '', tag: network ? network.tag : undefined, - chainName: NETWORK_DETAIL[chainId].chainName, //name used by metamask - chainId: NETWORK_DETAIL[chainId].chainId, - rpcUrl: NETWORK_DETAIL[chainId].rpcUrls, + chainName: networkDetails.chainName, //name used by connectors + chainId: networkDetails.chainId, nativeCurrency: { - name: NETWORK_DETAIL[chainId].nativeCurrency.name, - symbol: NETWORK_DETAIL[chainId].nativeCurrency.symbol, - decimals: NETWORK_DETAIL[chainId].nativeCurrency.decimals, + name: networkDetails.nativeCurrency.name, + symbol: networkDetails.nativeCurrency.symbol, + decimals: networkDetails.nativeCurrency.decimals, }, + rpcUrls: networkDetails.rpcUrls, + blockExplorerUrls: networkDetails.blockExplorerUrls, isArbitrum: NETWORK_OPTIONAL_DETAIL[chainId]?.isArbitrum ?? false, partnerChainId: NETWORK_OPTIONAL_DETAIL[chainId]?.partnerChainId, - iconUrls: NETWORK_OPTIONAL_DETAIL[chainId]?.iconUrls ?? undefined, } } diff --git a/yarn.lock b/yarn.lock index 4f58d40b9..466430734 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1537,10 +1537,10 @@ style-mod "^4.0.0" w3c-keyname "^2.2.4" -"@coinbase/wallet-sdk@^3.0.4": - version "3.5.3" - resolved "https://registry.yarnpkg.com/@coinbase/wallet-sdk/-/wallet-sdk-3.5.3.tgz#ffa657cc16f896e08c3e9ac571ca6a37d1f560fd" - integrity sha512-kaGMk9KyiSLPm1+BvCQSc99ku9gn0j+M1+2Beii+4gx/lRVhutlzmn6l+5zTB/n3xri25iTr+SxjMZLlMfW8Hg== +"@coinbase/wallet-sdk@^3.3.0": + version "3.5.2" + resolved "https://registry.yarnpkg.com/@coinbase/wallet-sdk/-/wallet-sdk-3.5.2.tgz#106e8b364a5203f6570561b103974677e18c4417" + integrity sha512-Wga/n2709w/+m/YlHviuQx8nl4gr2UkA4HM3OwFZopxvDeZerBYEjL/og7CUbSwplHDl+REIIz0jJfuedVyX5g== dependencies: "@metamask/safe-event-emitter" "2.0.0" "@solana/web3.js" "1.52.0" @@ -2180,7 +2180,7 @@ "@ethersproject/logger" "^5.7.0" "@ethersproject/properties" "^5.7.0" -"@ethersproject/address@5.7.0", "@ethersproject/address@^5.0.0", "@ethersproject/address@^5.0.2", "@ethersproject/address@^5.0.8", "@ethersproject/address@^5.4.0", "@ethersproject/address@^5.7.0": +"@ethersproject/address@5.7.0", "@ethersproject/address@^5", "@ethersproject/address@^5.0.0", "@ethersproject/address@^5.0.2", "@ethersproject/address@^5.0.8", "@ethersproject/address@^5.4.0", "@ethersproject/address@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.7.0.tgz#19b56c4d74a3b0a46bfdbb6cfcc0a153fc697f37" integrity sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA== @@ -2297,7 +2297,7 @@ aes-js "3.0.0" scrypt-js "3.0.1" -"@ethersproject/keccak256@5.7.0", "@ethersproject/keccak256@^5.0.0", "@ethersproject/keccak256@^5.0.0-beta.130", "@ethersproject/keccak256@^5.7.0": +"@ethersproject/keccak256@5.7.0", "@ethersproject/keccak256@^5.0.0", "@ethersproject/keccak256@^5.7.0": version "5.7.0" resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.7.0.tgz#3186350c6e1cd6aba7940384ec7d6d9db01f335a" integrity sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg== @@ -2332,7 +2332,7 @@ dependencies: "@ethersproject/logger" "^5.7.0" -"@ethersproject/providers@5.7.1", "@ethersproject/providers@^5.0.0", "@ethersproject/providers@^5.4.0", "@ethersproject/providers@^5.4.4": +"@ethersproject/providers@5.7.1", "@ethersproject/providers@^5", "@ethersproject/providers@^5.0.0", "@ethersproject/providers@^5.4.0", "@ethersproject/providers@^5.4.4": version "5.7.1" resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.7.1.tgz#b0799b616d5579cd1067a8ebf1fc1ec74c1e122c" integrity sha512-vZveG/DLyo+wk4Ga1yx6jSEHrLPgmTt+dFv0dv8URpVCRf0jVhalps1jq/emN/oXnMRsC7cQgAF32DcXLL7BPQ== @@ -3538,6 +3538,11 @@ resolved "https://registry.yarnpkg.com/@mdx-js/util/-/util-1.6.22.tgz#219dfd89ae5b97a8801f015323ffa4b62f45718b" integrity sha512-H1rQc1ZOHANWBvPcW+JpGwr+juXSxM8Q8YCkm3GhZd8REu1fHR3z99CErO1p9pkcfcxZnMdIZdIsXkOHY0NilA== +"@metamask/detect-provider@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@metamask/detect-provider/-/detect-provider-1.2.0.tgz#3667a7531f2a682e3c3a43eaf3a1958bdb42a696" + integrity sha512-ocA76vt+8D0thgXZ7LxFPyqw3H7988qblgzddTDA6B8a/yU0uKV42QR/DhA+Jh11rJjxW0jKvwb5htA6krNZDQ== + "@metamask/safe-event-emitter@2.0.0", "@metamask/safe-event-emitter@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@metamask/safe-event-emitter/-/safe-event-emitter-2.0.0.tgz#af577b477c683fad17c619a78208cede06f9605c" @@ -6391,13 +6396,20 @@ dependencies: "@types/yargs-parser" "*" -"@types/yargs@^17.0.8", "@types/yargs@^17.0.9": +"@types/yargs@^17.0.8": version "17.0.13" resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.13.tgz#34cced675ca1b1d51fcf4d34c3c6f0fa142a5c76" integrity sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg== dependencies: "@types/yargs-parser" "*" +"@types/yargs@^17.0.9": + version "17.0.11" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.11.tgz#5e10ca33e219807c0eee0f08b5efcba9b6a42c06" + integrity sha512-aB4y9UDUXTSMxmM4MH+YnuR0g5Cph3FLQBoWoMB21DSvFVAxRVEHEMx3TLh+zUZYMCQtKiqazz0Q4Rre31f/OA== + dependencies: + "@types/yargs-parser" "*" + "@types/yauzl@^2.9.1": version "2.10.0" resolved "https://registry.yarnpkg.com/@types/yauzl/-/yauzl-2.10.0.tgz#b3248295276cf8c6f153ebe6a9aba0c988cb2599" @@ -6949,7 +6961,7 @@ resolved "https://registry.yarnpkg.com/@walletconnect/environment/-/environment-1.0.0.tgz#c4545869fa9c389ec88c364e1a5f8178e8ab5034" integrity sha512-4BwqyWy6KpSvkocSaV7WR3BlZfrxLbJSLkg+j7Gl6pTDE+U55lLhJvQaMuDVazXYxcjBsG09k7UlH7cGiUI5vQ== -"@walletconnect/ethereum-provider@^1.7.1": +"@walletconnect/ethereum-provider@^1.7.5": version "1.8.0" resolved "https://registry.yarnpkg.com/@walletconnect/ethereum-provider/-/ethereum-provider-1.8.0.tgz#ed1dbf9cecc3b818758a060d2f9017c50bde1d32" integrity sha512-Nq9m+oo5P0F+njsROHw9KMWdoc/8iGHYzQdkjJN/1C7DtsqFRg5k5a3hd9rzCLpbPsOC1q8Z5lRs6JQgDvPm6Q== @@ -7066,7 +7078,7 @@ "@walletconnect/utils" "^1.8.0" ws "7.5.3" -"@walletconnect/types@^1.7.1", "@walletconnect/types@^1.8.0": +"@walletconnect/types@^1.8.0": version "1.8.0" resolved "https://registry.yarnpkg.com/@walletconnect/types/-/types-1.8.0.tgz#3f5e85b2d6b149337f727ab8a71b8471d8d9a195" integrity sha512-Cn+3I0V0vT9ghMuzh1KzZvCkiAxTq+1TR2eSqw5E5AVWfmCtECFkVZBP6uUJZ8YjwLqXheI+rnjqPy7sVM4Fyg== @@ -7108,66 +7120,85 @@ dependencies: "@walletconnect/window-getters" "^1.0.0" -"@web3-react/abstract-connector@^6.0.7": - version "6.0.7" - resolved "https://registry.yarnpkg.com/@web3-react/abstract-connector/-/abstract-connector-6.0.7.tgz#401b3c045f1e0fab04256311be49d5144e9badc6" - integrity sha512-RhQasA4Ox8CxUC0OENc1AJJm8UTybu/oOCM61Zjg6y0iF7Z0sqv1Ai1VdhC33hrQpA8qSBgoXN9PaP8jKmtdqg== +"@web3-react/coinbase-wallet@8.0.34-beta.0": + version "8.0.34-beta.0" + resolved "https://registry.yarnpkg.com/@web3-react/coinbase-wallet/-/coinbase-wallet-8.0.34-beta.0.tgz#43d51bb440fb4b98cc2c33782714da30ab8e1fb6" + integrity sha512-eGgtGtAqcRL64U1lcWeICB9CmpUycVl/mWD/b2Nd7yE0hXFUbPGLZHNvBTpnOpkANkjHI5ufFoyDGzzoxdw12A== dependencies: - "@web3-react/types" "^6.0.7" + "@web3-react/types" "^8.0.20-beta.0" -"@web3-react/core@^6.1.9": - version "6.1.9" - resolved "https://registry.yarnpkg.com/@web3-react/core/-/core-6.1.9.tgz#5f5daa0545a8ea07770a699580ced552583afc97" - integrity sha512-P877DslsbAkWIlMANpWiK7pCvNwlz0kJC0EGckuVh0wlA23J4UnFxq6xyOaxkxaDCu14rA/tAO0NbwjcXTQgSA== +"@web3-react/core@8.0.35-beta.0": + version "8.0.35-beta.0" + resolved "https://registry.yarnpkg.com/@web3-react/core/-/core-8.0.35-beta.0.tgz#8667483bdbc283fc8377d7f56faba1ec2fcdb095" + integrity sha512-vkEL2Vafu57lTA9T/cd3DNkZoDZ3G/JDUgxgjHqKLQVF4bPucrkeErqIHutAJ4suIi4bLOD0dFPMpFs+Bq7RgA== dependencies: - "@ethersproject/keccak256" "^5.0.0-beta.130" - "@web3-react/abstract-connector" "^6.0.7" - "@web3-react/types" "^6.0.7" - tiny-invariant "^1.0.6" - tiny-warning "^1.0.3" + "@web3-react/store" "^8.0.25-beta.0" + "@web3-react/types" "^8.0.20-beta.0" + zustand "^4.0.0-rc.0" + optionalDependencies: + "@ethersproject/providers" "^5" -"@web3-react/injected-connector@^6.0.7": - version "6.0.7" - resolved "https://registry.yarnpkg.com/@web3-react/injected-connector/-/injected-connector-6.0.7.tgz#1e0be23f51fa07fe6547fe986768a46b74c3a426" - integrity sha512-Y7aJSz6pg+MWKtvdyuqyy6LWuH+4Tqtph1LWfiyVms9II9ar/9B/de4R8wh4wjg91wmHkU+D75yP09E/Soh2RA== +"@web3-react/eip1193@8.0.26-beta.0": + version "8.0.26-beta.0" + resolved "https://registry.yarnpkg.com/@web3-react/eip1193/-/eip1193-8.0.26-beta.0.tgz#2e36423bab637a1fbc57b36d4f0f38ac531fd541" + integrity sha512-n/2ajjABcP8DktZfXxSHrxtPIxeSRJ9tsgfmd9XPEIW9FO7xLzLrF+nloTSghtZ8H+ZKKcswlKjYq4rbX/oqHg== dependencies: - "@web3-react/abstract-connector" "^6.0.7" - "@web3-react/types" "^6.0.7" - tiny-warning "^1.0.3" + "@web3-react/types" "^8.0.20-beta.0" + +"@web3-react/empty@8.0.20-beta.0": + version "8.0.20-beta.0" + resolved "https://registry.yarnpkg.com/@web3-react/empty/-/empty-8.0.20-beta.0.tgz#f8e2a6414ba49c7da3937776c213eb4c8ff6e2c7" + integrity sha512-hde1Wq7w03cal6hD0E+seVg6ZFMWKcaSZ0S5UwJi5CDxhF79oL8QuzpvTBslohRkWqzqlvl52wCSVaY+l2+F8Q== + dependencies: + "@web3-react/types" "^8.0.20-beta.0" + +"@web3-react/metamask@8.0.28-beta.0": + version "8.0.28-beta.0" + resolved "https://registry.yarnpkg.com/@web3-react/metamask/-/metamask-8.0.28-beta.0.tgz#f7e9e0de446727a961745cbec75c8cbf6c961388" + integrity sha512-IXuVyj6vhRAhfGQ/sN4qgET8EEdqX844pB4kCDG9kjPD3LLm5kq47ykBosgTr9YCUtdHAXN0UaUimD0TbLMRFg== + dependencies: + "@metamask/detect-provider" "^1.2.0" + "@web3-react/types" "^8.0.20-beta.0" -"@web3-react/network-connector@^6.2.9": - version "6.2.9" - resolved "https://registry.yarnpkg.com/@web3-react/network-connector/-/network-connector-6.2.9.tgz#e8f05dc101dccbc04879d1f56f958032c26cb906" - integrity sha512-S1yexq47XZlM4pbJ03gwp3NOlaVttCAlWV/fq220almSYNe0sAwLIQP/T6Wio15DIn76u34lIZWBeW0WLs/HGQ== +"@web3-react/network@8.0.27-beta.0": + version "8.0.27-beta.0" + resolved "https://registry.yarnpkg.com/@web3-react/network/-/network-8.0.27-beta.0.tgz#7cb522b02efc9d0f877ac285f350810fbf322292" + integrity sha512-kLHilUpLkDejx0C5Rr57puQSEVA+BQmT58xN6D/elphcZpVHAIkbh/MCYm0XrnLmqq0uOjw+jDhEYBBn80ncHQ== dependencies: - "@web3-react/abstract-connector" "^6.0.7" - "@web3-react/types" "^6.0.7" - tiny-invariant "^1.0.6" + "@ethersproject/providers" "^5" + "@web3-react/types" "^8.0.20-beta.0" -"@web3-react/types@^6.0.7": - version "6.0.7" - resolved "https://registry.yarnpkg.com/@web3-react/types/-/types-6.0.7.tgz#34a6204224467eedc6123abaf55fbb6baeb2809f" - integrity sha512-ofGmfDhxmNT1/P/MgVa8IKSkCStFiyvXe+U5tyZurKdrtTDFU+wJ/LxClPDtFerWpczNFPUSrKcuhfPX1sI6+A== +"@web3-react/store@^8.0.25-beta.0": + version "8.0.25-beta.0" + resolved "https://registry.yarnpkg.com/@web3-react/store/-/store-8.0.25-beta.0.tgz#853a029a9f82d8950e306adb455ba308f908c8f4" + integrity sha512-YHrZ42EHiQ9UAJq8Y/pHsyXu6GhzbCSHaQJ9U0wCDhbPoQ9QjOj0Pwcaa/VLXljuynK/7ERP942nI1IzArt9Sg== + dependencies: + "@ethersproject/address" "^5" + "@web3-react/types" "^8.0.20-beta.0" + zustand "^4.0.0-rc.0" -"@web3-react/walletconnect-connector@^6.2.13": - version "6.2.13" - resolved "https://registry.yarnpkg.com/@web3-react/walletconnect-connector/-/walletconnect-connector-6.2.13.tgz#b51cda088e8706e4fbff8da486ab6f09cf2980b1" - integrity sha512-rTsYLv2UpQZ92Yv5kyIwzrG+2aQkzE8ki2ElotJ6GmSl3yF9WSaGNfKpE8XI5+aPvbAk4mMn8lIy+os3a9gJgw== +"@web3-react/types@8.0.20-beta.0", "@web3-react/types@^8.0.20-beta.0": + version "8.0.20-beta.0" + resolved "https://registry.yarnpkg.com/@web3-react/types/-/types-8.0.20-beta.0.tgz#6b4509bef8c5c7eb866e49295880c865c20fb565" + integrity sha512-qOZYMyUmsm3Um6t6Pg3OgnE86ufhWZpB5/VxsooB8cdpXc/C/f8KMyYSeM63GoKSMScOKwfqV6yODFL7g/Qc8g== dependencies: - "@walletconnect/ethereum-provider" "^1.7.1" - "@walletconnect/types" "^1.7.1" - "@web3-react/abstract-connector" "^6.0.7" - "@web3-react/types" "^6.0.7" - tiny-invariant "^1.0.6" + zustand "^4.0.0-rc.0" -"@web3-react/walletlink-connector@^6.2.14": - version "6.2.14" - resolved "https://registry.yarnpkg.com/@web3-react/walletlink-connector/-/walletlink-connector-6.2.14.tgz#4adf7b94de5d7018a9fc9e3b6009e78cd33d6e15" - integrity sha512-F2v1Uu7Nhptt7AaUEJpz69+NVUJxyUfDEA5B/Vr1HkqAL1aJM5gv6B1m4M/VdXKLpmjZ9Kg6X0+VUEyAx1eQ4w== +"@web3-react/url@8.0.25-beta.0": + version "8.0.25-beta.0" + resolved "https://registry.yarnpkg.com/@web3-react/url/-/url-8.0.25-beta.0.tgz#68e464d2e78b89496e50e9e4a28e91281c4d53d6" + integrity sha512-cjFfAFjsWF5vqJ7TG79HT72jNNWlcS9bqbNK2jvu25zej62zMpPvy4iyYiV7zy2SLbAQTdsgvIMYAdxRbnzlWg== dependencies: - "@coinbase/wallet-sdk" "^3.0.4" - "@web3-react/abstract-connector" "^6.0.7" - "@web3-react/types" "^6.0.7" + "@ethersproject/providers" "^5" + "@web3-react/types" "^8.0.20-beta.0" + +"@web3-react/walletconnect@8.0.36-beta.0": + version "8.0.36-beta.0" + resolved "https://registry.yarnpkg.com/@web3-react/walletconnect/-/walletconnect-8.0.36-beta.0.tgz#a0dbb5286b9011c6c221cc143322822a7387978f" + integrity sha512-u+yNWCm8nz5pZn8SyU5+9pI5hakKcfhUF1TYwj7HVTTMHdMlLXhk19YyaycsFkgbX9zWzouItwxXF8obGt+rCg== + dependencies: + "@web3-react/types" "^8.0.20-beta.0" + eventemitter3 "^4.0.7" "@webassemblyjs/ast@1.11.1": version "1.11.1" @@ -25538,7 +25569,7 @@ timm@^1.6.1: resolved "https://registry.yarnpkg.com/timm/-/timm-1.7.1.tgz#96bab60c7d45b5a10a8a4d0f0117c6b7e5aff76f" integrity sha512-IjZc9KIotudix8bMaBW6QvMuq64BrJWFs1+4V0lXwWGQZwH+LnX87doAYhem4caOEusRP9/g6jVDQmZ8XOk1nw== -tiny-invariant@^1.0.6, tiny-invariant@^1.1.0, tiny-invariant@^1.2.0: +tiny-invariant@^1.1.0, tiny-invariant@^1.2.0: version "1.3.1" resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.1.tgz#8560808c916ef02ecfd55e66090df23a4b7aa642" integrity sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw== @@ -26448,6 +26479,11 @@ use-sidecar@^1.1.2: detect-node-es "^1.1.0" tslib "^2.0.0" +use-sync-external-store@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.1.0.tgz#3343c3fe7f7e404db70f8c687adf5c1652d34e82" + integrity sha512-SEnieB2FPKEVne66NpXPd1Np4R1lTNKfjuy3XdIoPQKYBAFdzbzSZlSn1KJZUiihQLQC5Znot4SBz1EOTBwQAQ== + use-sync-external-store@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a" @@ -28133,6 +28169,13 @@ zen-observable@0.8.15: resolved "https://registry.yarnpkg.com/zen-observable/-/zen-observable-0.8.15.tgz#96415c512d8e3ffd920afd3889604e30b9eaac15" integrity sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ== +zustand@^4.0.0-rc.0: + version "4.0.0-rc.1" + resolved "https://registry.yarnpkg.com/zustand/-/zustand-4.0.0-rc.1.tgz#ec30a3afc03728adec7e1bd7bcc3592176372201" + integrity sha512-qgcs7zLqBdHu0PuT3GW4WCIY5SgXdsv30GQMu9Qpp1BA2aS+sNS8l4x0hWuyEhjXkN+701aGWawhKDv6oWJAcw== + dependencies: + use-sync-external-store "1.1.0" + zwitch@^1.0.0: version "1.0.5" resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-1.0.5.tgz#d11d7381ffed16b742f6af7b3f223d5cd9fe9920"