Skip to content

Commit

Permalink
fix: support chain switching for walletconnect
Browse files Browse the repository at this point in the history
  • Loading branch information
woodenfurniture committed Oct 6, 2023
1 parent fc8d415 commit 913de99
Show file tree
Hide file tree
Showing 11 changed files with 120 additions and 108 deletions.
40 changes: 20 additions & 20 deletions src/AppProviders.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import {
createLocalStorageManager,
createStandaloneToast,
} from '@chakra-ui/react'
import { Web3Modal } from '@web3modal/react'
import { getConfig } from 'config'
import { DefiManagerProvider } from 'features/defi/contexts/DefiManagerProvider/DefiManagerProvider'
import { WalletConnectV2Provider } from 'plugins/walletConnectToDapps/WalletConnectV2Provider'
import React, { useCallback } from 'react'
Expand All @@ -22,7 +24,6 @@ import { ModalProvider } from 'context/ModalProvider/ModalProvider'
import { PluginProvider } from 'context/PluginProvider/PluginProvider'
import { TransactionsProvider } from 'context/TransactionsProvider/TransactionsProvider'
import { KeepKeyProvider } from 'context/WalletProvider/KeepKeyProvider'
import { Web3ModalProvider } from 'context/WalletProvider/WalletConnectV2/Web3ModalProvider'
import { WalletProvider } from 'context/WalletProvider/WalletProvider'
import { getMixPanel } from 'lib/mixpanel/mixPanelSingleton'
import { MixPanelEvents } from 'lib/mixpanel/types'
Expand Down Expand Up @@ -56,32 +57,31 @@ export function AppProviders({ children }: ProvidersProps) {
<PluginProvider>
<ColorModeScript storageKey='ss-theme' />
<ChatwootWidget />
<Web3Modal projectId={getConfig().REACT_APP_WALLET_CONNECT_PROJECT_ID} />
<ChakraProvider theme={theme} colorModeManager={manager} cssVarsRoot='body'>
<ToastContainer />
<PersistGate loading={<SplashScreen />} persistor={persistor}>
<HashRouter basename='/'>
<ScrollToTop />
<BrowserRouterProvider>
<I18nProvider>
<Web3ModalProvider>
<WalletProvider>
<WalletConnectV2Provider>
<KeepKeyProvider>
<ErrorBoundary FallbackComponent={ErrorPage} onError={handleError}>
<ModalProvider>
<TransactionsProvider>
<AppProvider>
<FoxEthProvider>
<DefiManagerProvider>{children}</DefiManagerProvider>
</FoxEthProvider>
</AppProvider>
</TransactionsProvider>
</ModalProvider>
</ErrorBoundary>
</KeepKeyProvider>
</WalletConnectV2Provider>
</WalletProvider>
</Web3ModalProvider>
<WalletProvider>
<WalletConnectV2Provider>
<KeepKeyProvider>
<ErrorBoundary FallbackComponent={ErrorPage} onError={handleError}>
<ModalProvider>
<TransactionsProvider>
<AppProvider>
<FoxEthProvider>
<DefiManagerProvider>{children}</DefiManagerProvider>
</FoxEthProvider>
</AppProvider>
</TransactionsProvider>
</ModalProvider>
</ErrorBoundary>
</KeepKeyProvider>
</WalletConnectV2Provider>
</WalletProvider>
</I18nProvider>
</BrowserRouterProvider>
</HashRouter>
Expand Down
6 changes: 4 additions & 2 deletions src/components/Layout/Header/NavBar/UserMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import { RawText, Text } from 'components/Text'
import { WalletActions } from 'context/WalletProvider/actions'
import type { InitialState } from 'context/WalletProvider/WalletProvider'
import { useWallet } from 'hooks/useWallet/useWallet'
import { viemClient } from 'lib/viem-client'
import { viemEthMainnetClient } from 'lib/viem-client'

export const entries = [WalletConnectedRoutes.Connected]

Expand Down Expand Up @@ -81,7 +81,9 @@ const WalletButton: FC<WalletButtonProps> = ({

useEffect(() => {
if (!walletInfo?.meta?.address) return
viemClient.getEnsName({ address: walletInfo.meta.address as Address }).then(setEnsName)
viemEthMainnetClient
.getEnsName({ address: walletInfo.meta.address as Address })
.then(setEnsName)
}, [walletInfo?.meta?.address])

useEffect(() => {
Expand Down
4 changes: 2 additions & 2 deletions src/components/Modals/Receive/ReceiveInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import { Text } from 'components/Text'
import { getChainAdapterManager } from 'context/PluginProvider/chainAdapterSingleton'
import { useWallet } from 'hooks/useWallet/useWallet'
import type { Asset } from 'lib/asset-service'
import { viemClient } from 'lib/viem-client'
import { viemEthMainnetClient } from 'lib/viem-client'
import { selectPortfolioAccountMetadataByAccountId } from 'state/slices/selectors'
import { useAppSelector } from 'state/store'

Expand Down Expand Up @@ -82,7 +82,7 @@ export const ReceiveInfo = ({ asset, accountId }: ReceivePropsType) => {

useEffect(() => {
if (asset.chainId !== KnownChainIds.EthereumMainnet || !receiveAddress) return
viemClient.getEnsName({ address: receiveAddress as Address }).then(setEnsName)
viemEthMainnetClient.getEnsName({ address: receiveAddress as Address }).then(setEnsName)
}, [asset.chainId, receiveAddress])

const handleVerify = async () => {
Expand Down
55 changes: 0 additions & 55 deletions src/context/WalletProvider/WalletConnectV2/Web3ModalProvider.tsx

This file was deleted.

21 changes: 20 additions & 1 deletion src/context/WalletProvider/WalletConnectV2/config.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { CHAIN_REFERENCE } from '@shapeshiftoss/caip'
import { WalletConnectV2Adapter } from '@shapeshiftoss/hdwallet-walletconnectv2'
import type { EthereumProviderOptions } from '@walletconnect/ethereum-provider/dist/types/EthereumProvider'
import { getConfig } from 'config'
Expand Down Expand Up @@ -41,8 +42,18 @@ const walletConnectV2OptionalChainIds: AtLeastOneNumber = (() => {
return chainIds as AtLeastOneNumber
})()

const {
REACT_APP_WALLET_CONNECT_PROJECT_ID,
REACT_APP_AVALANCHE_NODE_URL,
REACT_APP_OPTIMISM_NODE_URL,
REACT_APP_BNBSMARTCHAIN_NODE_URL,
REACT_APP_POLYGON_NODE_URL,
REACT_APP_GNOSIS_NODE_URL,
REACT_APP_ETHEREUM_NODE_URL,
} = getConfig()

export const walletConnectV2ProviderConfig: EthereumProviderOptions = {
projectId: getConfig().REACT_APP_WALLET_CONNECT_PROJECT_ID,
projectId: REACT_APP_WALLET_CONNECT_PROJECT_ID,
chains: walletConnectV2RequiredChainIds,
optionalChains: walletConnectV2OptionalChainIds,
optionalMethods: [
Expand All @@ -55,4 +66,12 @@ export const walletConnectV2ProviderConfig: EthereumProviderOptions = {
'eth_signTransaction',
],
showQrModal: true,
rpcMap: {
[CHAIN_REFERENCE.AvalancheCChain]: REACT_APP_AVALANCHE_NODE_URL,
[CHAIN_REFERENCE.OptimismMainnet]: REACT_APP_OPTIMISM_NODE_URL,
[CHAIN_REFERENCE.BnbSmartChainMainnet]: REACT_APP_BNBSMARTCHAIN_NODE_URL,
[CHAIN_REFERENCE.PolygonMainnet]: REACT_APP_POLYGON_NODE_URL,
[CHAIN_REFERENCE.GnosisMainnet]: REACT_APP_GNOSIS_NODE_URL,
[CHAIN_REFERENCE.EthereumMainnet]: REACT_APP_ETHEREUM_NODE_URL,
},
}
3 changes: 2 additions & 1 deletion src/contracts/contractManager.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { AssetId, ChainId } from '@shapeshiftoss/caip'
import { fromAssetId, toAssetId } from '@shapeshiftoss/caip'
import type { EvmChainId } from '@shapeshiftoss/chain-adapters'
import type { Token } from '@uniswap/sdk'
import { Fetcher } from '@uniswap/sdk'
import {
Expand Down Expand Up @@ -84,7 +85,7 @@ export const getOrCreateContractByType = <T extends ContractType>({
if (definedContract && definedContract.contract)
return definedContract.contract as KnownContractByType<T>
const typechainContract = CONTRACT_TYPE_TO_TYPECHAIN_CONTRACT[type]
const ethersProvider = getEthersProvider(chainId)
const ethersProvider = getEthersProvider(chainId as EvmChainId)
const contract = typechainContract.connect(address, ethersProvider)
definedContracts.push({ contract, address: ethers.utils.getAddress(address) })
return contract as KnownContractByType<T>
Expand Down
6 changes: 3 additions & 3 deletions src/lib/address/ens.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import memoize from 'lodash/memoize'
import type { Address } from 'viem'
import { viemClient } from 'lib/viem-client'
import { viemEthMainnetClient } from 'lib/viem-client'

import type {
ResolveVanityAddress,
Expand All @@ -16,7 +16,7 @@ export const validateEnsDomain: ValidateVanityAddress = ({ maybeAddress }) =>
Promise.resolve(/^([0-9A-Z]([-0-9A-Z]*[0-9A-Z])?\.)+eth$/i.test(maybeAddress))

export const ensLookup = memoize(async (domain: string): Promise<ResolveVanityAddressReturn> => {
const address = await viemClient.getEnsAddress({
const address = await viemEthMainnetClient.getEnsAddress({
name: domain,
})
if (!address) return ''
Expand All @@ -27,7 +27,7 @@ export const ensReverseLookup = memoize(
async (
address: Address,
): Promise<{ name: string; error: false } | { name: null; error: true }> => {
const lookupName = await viemClient.getEnsName({
const lookupName = await viemEthMainnetClient.getEnsName({
address,
})
if (!lookupName) return { name: null, error: true }
Expand Down
33 changes: 16 additions & 17 deletions src/lib/ethersProviderSingleton.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,35 @@
import type { ChainId } from '@shapeshiftoss/caip'
import {
avalancheChainId,
bscChainId,
ethChainId,
gnosisChainId,
optimismChainId,
polygonChainId,
} from '@shapeshiftoss/caip'
import type { EvmChainId } from '@shapeshiftoss/chain-adapters'
import { KnownChainIds } from '@shapeshiftoss/types'
import { getConfig } from 'config'
import { providers } from 'ethers'

export const rpcUrlByChainId = (chainId: ChainId): string => {
import { assertUnreachable } from './utils'

export const rpcUrlByChainId = (chainId: EvmChainId): string => {
switch (chainId) {
case avalancheChainId:
case KnownChainIds.AvalancheMainnet:
return getConfig().REACT_APP_AVALANCHE_NODE_URL
case optimismChainId:
case KnownChainIds.OptimismMainnet:
return getConfig().REACT_APP_OPTIMISM_NODE_URL
case bscChainId:
case KnownChainIds.BnbSmartChainMainnet:
return getConfig().REACT_APP_BNBSMARTCHAIN_NODE_URL
case polygonChainId:
case KnownChainIds.PolygonMainnet:
return getConfig().REACT_APP_POLYGON_NODE_URL
case gnosisChainId:
case KnownChainIds.GnosisMainnet:
return getConfig().REACT_APP_GNOSIS_NODE_URL
case ethChainId:
default:
case KnownChainIds.EthereumMainnet:
return getConfig().REACT_APP_ETHEREUM_NODE_URL
default:
assertUnreachable(chainId)
}
}

const ethersProviders: Map<ChainId, providers.JsonRpcBatchProvider> = new Map()

export const getEthersProvider = (chainId = ethChainId): providers.JsonRpcBatchProvider => {
export const getEthersProvider = (
chainId: EvmChainId = KnownChainIds.EthereumMainnet,
): providers.JsonRpcBatchProvider => {
if (!ethersProviders.has(chainId)) {
const provider = new providers.JsonRpcBatchProvider(rpcUrlByChainId(chainId))
ethersProviders.set(chainId, provider)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { LifiStep } from '@lifi/types'
import type { ChainId } from '@shapeshiftoss/caip'
import type { EvmChainId } from '@shapeshiftoss/chain-adapters'
import { KnownChainIds } from '@shapeshiftoss/types'
import type { BigNumber } from 'ethers'
import { ethers } from 'ethers'
Expand Down Expand Up @@ -42,7 +43,7 @@ export const getNetworkFeeCryptoBaseUnit = async ({
const l1GasLimit = await (async () => {
if (chainId !== KnownChainIds.OptimismMainnet) return

const provider = getEthersProvider(chainId)
const provider = getEthersProvider(chainId as EvmChainId)

const abi = [
{
Expand Down
52 changes: 47 additions & 5 deletions src/lib/viem-client.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,50 @@
import { getConfig } from 'config'
import { type ChainReference, fromChainId } from '@shapeshiftoss/caip'
import { type EvmChainId, evmChainIds } from '@shapeshiftoss/chain-adapters'
import { KnownChainIds } from '@shapeshiftoss/types'
import type { HttpTransport, PublicClient } from 'viem'
import { createPublicClient, http } from 'viem'
import type { Chain } from 'viem/chains'
import { mainnet } from 'viem/chains'

export const viemClient = createPublicClient({
chain: mainnet,
transport: http(getConfig().REACT_APP_ETHEREUM_NODE_URL),
})
import { rpcUrlByChainId } from './ethersProviderSingleton'

const viemClientsByChain = evmChainIds.reduce<
Record<EvmChainId, PublicClient<HttpTransport, Chain>>
>(
(acc, chainId) => {
const nodeUrl = rpcUrlByChainId(chainId)
acc[chainId] = createPublicClient({
chain: mainnet,
transport: http(nodeUrl),
})

return acc
},
{} as Record<EvmChainId, PublicClient<HttpTransport, Chain>>,
)

export const viemEthMainnetClient = viemClientsByChain[KnownChainIds.EthereumMainnet]

const viemChainToChainId = (chain: ChainReference | undefined): EvmChainId => {
switch (chain) {
case fromChainId(KnownChainIds.AvalancheMainnet).chainReference:
return KnownChainIds.AvalancheMainnet
case fromChainId(KnownChainIds.OptimismMainnet).chainReference:
return KnownChainIds.OptimismMainnet
case fromChainId(KnownChainIds.BnbSmartChainMainnet).chainReference:
return KnownChainIds.BnbSmartChainMainnet
case fromChainId(KnownChainIds.PolygonMainnet).chainReference:
return KnownChainIds.PolygonMainnet
case fromChainId(KnownChainIds.GnosisMainnet).chainReference:
return KnownChainIds.GnosisMainnet
case fromChainId(KnownChainIds.EthereumMainnet).chainReference:
default:
return KnownChainIds.EthereumMainnet
}
}

export const getViemClientByChain = ({ chainId }: { chainId?: number }) => {
const chainReference: ChainReference | undefined =
chainId !== undefined ? (String(chainId) as ChainReference) : undefined
return viemClientsByChain[viemChainToChainId(chainReference)]
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { ChainId } from '@shapeshiftoss/caip'
import type { EvmChainId } from '@shapeshiftoss/chain-adapters'
import { useEffect, useState } from 'react'
import { getEthersProvider } from 'lib/ethersProviderSingleton'

Expand All @@ -13,7 +14,9 @@ export const useIsInteractingWithContract = ({
useEffect(() => {
;(async () => {
const result =
evmChainId && address ? await getEthersProvider(evmChainId).getCode(address) : undefined
evmChainId && address
? await getEthersProvider(evmChainId as EvmChainId).getCode(address)
: undefined
// this util function returns '0x' if the recipient address is not a contract address
setIsInteractingWithContract(result ? result !== '0x' : null)
})()
Expand Down

0 comments on commit 913de99

Please sign in to comment.