Commit 839d4ac8 authored by cartcrom's avatar cartcrom Committed by GitHub

refactor: adding safe getter for ChainInfo (#4110)

* replaced CHAIN_INFO access with a function call
* updated CTACard tests to work with getChainInfo
* updated typechecking, removed console.log
parent 29fdcb80
import { Trans } from '@lingui/macro' import { Trans } from '@lingui/macro'
import { useWeb3React } from '@web3-react/core' import { useWeb3React } from '@web3-react/core'
import { CHAIN_INFO, L2ChainInfo } from 'constants/chainInfo' import { getChainInfoOrDefault, L2ChainInfo } from 'constants/chainInfo'
import { SupportedChainId } from 'constants/chains' import { SupportedChainId } from 'constants/chains'
import { AlertOctagon } from 'react-feather' import { AlertOctagon } from 'react-feather'
import styled from 'styled-components/macro' import styled from 'styled-components/macro'
...@@ -46,7 +46,7 @@ const Wrapper = styled.div` ...@@ -46,7 +46,7 @@ const Wrapper = styled.div`
export function ChainConnectivityWarning() { export function ChainConnectivityWarning() {
const { chainId } = useWeb3React() const { chainId } = useWeb3React()
const info = CHAIN_INFO[chainId ?? SupportedChainId.MAINNET] const info = getChainInfoOrDefault(chainId)
const label = info?.label const label = info?.label
return ( return (
......
import { Trans } from '@lingui/macro' import { Trans } from '@lingui/macro'
import { useWeb3React } from '@web3-react/core' import { useWeb3React } from '@web3-react/core'
import { getConnection } from 'connection/utils' import { getConnection } from 'connection/utils'
import { CHAIN_INFO } from 'constants/chainInfo' import { getChainInfo } from 'constants/chainInfo'
import { CHAIN_IDS_TO_NAMES, SupportedChainId } from 'constants/chains' import { CHAIN_IDS_TO_NAMES, SupportedChainId } from 'constants/chains'
import useParsedQueryString from 'hooks/useParsedQueryString' import useParsedQueryString from 'hooks/useParsedQueryString'
import usePrevious from 'hooks/usePrevious' import usePrevious from 'hooks/usePrevious'
...@@ -195,7 +195,7 @@ function Row({ ...@@ -195,7 +195,7 @@ function Row({
return null return null
} }
const active = chainId === targetChain const active = chainId === targetChain
const { helpCenterUrl, explorer, bridge, label, logoUrl } = CHAIN_INFO[targetChain] const { helpCenterUrl, explorer, bridge, label, logoUrl } = getChainInfo(targetChain)
const rowContent = ( const rowContent = (
<FlyoutRow onClick={() => onSelectChain(targetChain)} active={active}> <FlyoutRow onClick={() => onSelectChain(targetChain)} active={active}>
...@@ -285,10 +285,10 @@ export default function NetworkSelector() { ...@@ -285,10 +285,10 @@ export default function NetworkSelector() {
const toggleModal = useToggleModal(ApplicationModal.NETWORK_SELECTOR) const toggleModal = useToggleModal(ApplicationModal.NETWORK_SELECTOR)
const history = useHistory() const history = useHistory()
const info = chainId ? CHAIN_INFO[chainId] : undefined const info = getChainInfo(chainId)
const onSelectChain = useCallback( const onSelectChain = useCallback(
async (targetChain: number, skipClose?: boolean) => { async (targetChain: SupportedChainId, skipClose?: boolean) => {
if (!connector) return if (!connector) return
const connectionType = getConnection(connector).type const connectionType = getConnection(connector).type
......
import { Trans } from '@lingui/macro' import { Trans } from '@lingui/macro'
import { useWeb3React } from '@web3-react/core' import { useWeb3React } from '@web3-react/core'
import { RowFixed } from 'components/Row' import { RowFixed } from 'components/Row'
import { CHAIN_INFO } from 'constants/chainInfo' import { getChainInfo } from 'constants/chainInfo'
import useCurrentBlockTimestamp from 'hooks/useCurrentBlockTimestamp' import useCurrentBlockTimestamp from 'hooks/useCurrentBlockTimestamp'
import useGasPrice from 'hooks/useGasPrice' import useGasPrice from 'hooks/useGasPrice'
import useMachineTimeMs from 'hooks/useMachineTime' import useMachineTimeMs from 'hooks/useMachineTime'
...@@ -112,7 +112,7 @@ export default function Polling() { ...@@ -112,7 +112,7 @@ export default function Polling() {
const priceGwei = ethGasPrice ? JSBI.divide(ethGasPrice, JSBI.BigInt(1000000000)) : undefined const priceGwei = ethGasPrice ? JSBI.divide(ethGasPrice, JSBI.BigInt(1000000000)) : undefined
const waitMsBeforeWarning = const waitMsBeforeWarning =
(chainId ? CHAIN_INFO[chainId]?.blockWaitMsBeforeWarning : DEFAULT_MS_BEFORE_WARNING) ?? DEFAULT_MS_BEFORE_WARNING (chainId ? getChainInfo(chainId)?.blockWaitMsBeforeWarning : DEFAULT_MS_BEFORE_WARNING) ?? DEFAULT_MS_BEFORE_WARNING
const warning = Boolean(!!blockTime && machineTime - blockTime.mul(1000).toNumber() > waitMsBeforeWarning) const warning = Boolean(!!blockTime && machineTime - blockTime.mul(1000).toNumber() > waitMsBeforeWarning)
......
import { Trans } from '@lingui/macro' import { Trans } from '@lingui/macro'
import useScrollPosition from '@react-hook/window-scroll' import useScrollPosition from '@react-hook/window-scroll'
import { useWeb3React } from '@web3-react/core' import { useWeb3React } from '@web3-react/core'
import { CHAIN_INFO } from 'constants/chainInfo' import { getChainInfoOrDefault } from 'constants/chainInfo'
import { SupportedChainId } from 'constants/chains' import { SupportedChainId } from 'constants/chains'
import useTheme from 'hooks/useTheme' import useTheme from 'hooks/useTheme'
import { darken } from 'polished' import { darken } from 'polished'
...@@ -13,7 +13,6 @@ import { useNativeCurrencyBalances } from 'state/connection/hooks' ...@@ -13,7 +13,6 @@ import { useNativeCurrencyBalances } from 'state/connection/hooks'
import { useUserHasSubmittedClaim } from 'state/transactions/hooks' import { useUserHasSubmittedClaim } from 'state/transactions/hooks'
import { useDarkModeManager } from 'state/user/hooks' import { useDarkModeManager } from 'state/user/hooks'
import styled from 'styled-components/macro' import styled from 'styled-components/macro'
import { isChainAllowed } from 'utils/switchChain'
import { ReactComponent as Logo } from '../../assets/svg/logo.svg' import { ReactComponent as Logo } from '../../assets/svg/logo.svg'
import { ExternalLink, ThemedText } from '../../theme' import { ExternalLink, ThemedText } from '../../theme'
...@@ -247,9 +246,7 @@ const StyledExternalLink = styled(ExternalLink).attrs({ ...@@ -247,9 +246,7 @@ const StyledExternalLink = styled(ExternalLink).attrs({
` `
export default function Header() { export default function Header() {
const { account, chainId, connector } = useWeb3React() const { account, chainId } = useWeb3React()
const chainAllowed = chainId && isChainAllowed(connector, chainId)
const userEthBalance = useNativeCurrencyBalances(account ? [account] : [])?.[account ?? ''] const userEthBalance = useNativeCurrencyBalances(account ? [account] : [])?.[account ?? '']
const [darkMode] = useDarkModeManager() const [darkMode] = useDarkModeManager()
...@@ -268,7 +265,7 @@ export default function Header() { ...@@ -268,7 +265,7 @@ export default function Header() {
const { const {
infoLink, infoLink,
nativeCurrency: { symbol: nativeCurrencySymbol }, nativeCurrency: { symbol: nativeCurrencySymbol },
} = CHAIN_INFO[!chainId || !chainAllowed ? SupportedChainId.MAINNET : chainId] } = getChainInfoOrDefault(chainId)
return ( return (
<HeaderFrame showBackground={scrollY > 45}> <HeaderFrame showBackground={scrollY > 45}>
......
import { Trans } from '@lingui/macro' import { Trans } from '@lingui/macro'
import { useWeb3React } from '@web3-react/core' import { useWeb3React } from '@web3-react/core'
import { CHAIN_INFO } from 'constants/chainInfo' import { getChainInfo } from 'constants/chainInfo'
import { SupportedChainId } from 'constants/chains' import { SupportedChainId } from 'constants/chains'
import { ArrowUpRight } from 'react-feather' import { ArrowUpRight } from 'react-feather'
import { useDarkModeManager } from 'state/user/hooks' import { useDarkModeManager } from 'state/user/hooks'
...@@ -159,7 +159,7 @@ export function NetworkAlert() { ...@@ -159,7 +159,7 @@ export function NetworkAlert() {
return null return null
} }
const { label, logoUrl, bridge } = CHAIN_INFO[chainId] const { label, logoUrl, bridge } = getChainInfo(chainId)
const textColor = TEXT_COLORS[chainId] const textColor = TEXT_COLORS[chainId]
return bridge ? ( return bridge ? (
......
import { Trans } from '@lingui/macro' import { Trans } from '@lingui/macro'
import { CHAIN_INFO } from 'constants/chainInfo' import { getChainInfo } from 'constants/chainInfo'
import { SupportedChainId } from 'constants/chains' import { SupportedChainId } from 'constants/chains'
import { useContext } from 'react' import { useContext } from 'react'
import { AlertCircle } from 'react-feather' import { AlertCircle } from 'react-feather'
...@@ -14,7 +14,7 @@ const RowNoFlex = styled(AutoRow)` ...@@ -14,7 +14,7 @@ const RowNoFlex = styled(AutoRow)`
` `
export default function FailedNetworkSwitchPopup({ chainId }: { chainId: SupportedChainId }) { export default function FailedNetworkSwitchPopup({ chainId }: { chainId: SupportedChainId }) {
const chainInfo = CHAIN_INFO[chainId] const chainInfo = getChainInfo(chainId)
const theme = useContext(ThemeContext) const theme = useContext(ThemeContext)
return ( return (
......
...@@ -2,14 +2,15 @@ import { Trans } from '@lingui/macro' ...@@ -2,14 +2,15 @@ import { Trans } from '@lingui/macro'
import { Currency } from '@uniswap/sdk-core' import { Currency } from '@uniswap/sdk-core'
import { useWeb3React } from '@web3-react/core' import { useWeb3React } from '@web3-react/core'
import Badge from 'components/Badge' import Badge from 'components/Badge'
import { CHAIN_INFO } from 'constants/chainInfo' import { getChainInfo } from 'constants/chainInfo'
import { L2_CHAIN_IDS, SupportedL2ChainId } from 'constants/chains' import { SupportedL2ChainId } from 'constants/chains'
import useCurrencyLogoURIs from 'lib/hooks/useCurrencyLogoURIs' import useCurrencyLogoURIs from 'lib/hooks/useCurrencyLogoURIs'
import { ReactNode, useCallback, useContext, useState } from 'react' import { ReactNode, useCallback, useContext, useState } from 'react'
import { AlertCircle, AlertTriangle, ArrowUpCircle, CheckCircle } from 'react-feather' import { AlertCircle, AlertTriangle, ArrowUpCircle, CheckCircle } from 'react-feather'
import { Text } from 'rebass' import { Text } from 'rebass'
import { useIsTransactionConfirmed, useTransaction } from 'state/transactions/hooks' import { useIsTransactionConfirmed, useTransaction } from 'state/transactions/hooks'
import styled, { ThemeContext } from 'styled-components/macro' import styled, { ThemeContext } from 'styled-components/macro'
import { isL2ChainId } from 'utils/chains'
import Circle from '../../assets/images/blue-loader.svg' import Circle from '../../assets/images/blue-loader.svg'
import { ExternalLink } from '../../theme' import { ExternalLink } from '../../theme'
...@@ -232,7 +233,7 @@ function L2Content({ ...@@ -232,7 +233,7 @@ function L2Content({
}: { }: {
onDismiss: () => void onDismiss: () => void
hash: string | undefined hash: string | undefined
chainId: number chainId: SupportedL2ChainId
currencyToAdd?: Currency | undefined currencyToAdd?: Currency | undefined
pendingText: ReactNode pendingText: ReactNode
inline?: boolean // not in modal inline?: boolean // not in modal
...@@ -248,7 +249,7 @@ function L2Content({ ...@@ -248,7 +249,7 @@ function L2Content({
? (transaction.confirmedTime - transaction.addedTime) / 1000 ? (transaction.confirmedTime - transaction.addedTime) / 1000
: undefined : undefined
const info = CHAIN_INFO[chainId as SupportedL2ChainId] const info = getChainInfo(chainId)
return ( return (
<Wrapper> <Wrapper>
...@@ -344,14 +345,12 @@ export default function TransactionConfirmationModal({ ...@@ -344,14 +345,12 @@ export default function TransactionConfirmationModal({
}: ConfirmationModalProps) { }: ConfirmationModalProps) {
const { chainId } = useWeb3React() const { chainId } = useWeb3React()
const isL2 = Boolean(chainId && L2_CHAIN_IDS.includes(chainId))
if (!chainId) return null if (!chainId) return null
// confirmation screen // confirmation screen
return ( return (
<Modal isOpen={isOpen} onDismiss={onDismiss} maxHeight={90}> <Modal isOpen={isOpen} onDismiss={onDismiss} maxHeight={90}>
{isL2 && (hash || attemptingTxn) ? ( {isL2ChainId(chainId) && (hash || attemptingTxn) ? (
<L2Content chainId={chainId} hash={hash} onDismiss={onDismiss} pendingText={pendingText} /> <L2Content chainId={chainId} hash={hash} onDismiss={onDismiss} pendingText={pendingText} />
) : attemptingTxn ? ( ) : attemptingTxn ? (
<ConfirmationPendingContent onDismiss={onDismiss} pendingText={pendingText} /> <ConfirmationPendingContent onDismiss={onDismiss} pendingText={pendingText} />
......
...@@ -46,7 +46,7 @@ export type ChainInfoMap = { readonly [chainId: number]: L1ChainInfo | L2ChainIn ...@@ -46,7 +46,7 @@ export type ChainInfoMap = { readonly [chainId: number]: L1ChainInfo | L2ChainIn
readonly [chainId in SupportedL2ChainId]: L2ChainInfo readonly [chainId in SupportedL2ChainId]: L2ChainInfo
} & { readonly [chainId in SupportedL1ChainId]: L1ChainInfo } } & { readonly [chainId in SupportedL1ChainId]: L1ChainInfo }
export const CHAIN_INFO: ChainInfoMap = { const CHAIN_INFO: ChainInfoMap = {
[SupportedChainId.MAINNET]: { [SupportedChainId.MAINNET]: {
networkType: NetworkType.L1, networkType: NetworkType.L1,
docs: 'https://docs.uniswap.org/', docs: 'https://docs.uniswap.org/',
...@@ -193,3 +193,30 @@ export const CHAIN_INFO: ChainInfoMap = { ...@@ -193,3 +193,30 @@ export const CHAIN_INFO: ChainInfoMap = {
defaultListUrl: CELO_LIST, defaultListUrl: CELO_LIST,
}, },
} }
export function getChainInfo(chainId: SupportedL1ChainId): L1ChainInfo
export function getChainInfo(chainId: SupportedL2ChainId): L2ChainInfo
export function getChainInfo(chainId: SupportedChainId): L1ChainInfo | L2ChainInfo
export function getChainInfo(
chainId: SupportedChainId | SupportedL1ChainId | SupportedL2ChainId | number | undefined
): L1ChainInfo | L2ChainInfo | undefined
/**
* Overloaded method for returning ChainInfo given a chainID
* Return type varies depending on input type:
* number | undefined -> returns chaininfo | undefined
* SupportedChainId -> returns L1ChainInfo | L2ChainInfo
* SupportedL1ChainId -> returns L1ChainInfo
* SupportedL2ChainId -> returns L2ChainInfo
*/
export function getChainInfo(chainId: any): any {
if (chainId) {
return CHAIN_INFO[chainId] ?? undefined
}
return undefined
}
export const MAINNET_INFO = CHAIN_INFO[SupportedChainId.MAINNET]
export function getChainInfoOrDefault(chainId: number | undefined) {
return getChainInfo(chainId) ?? MAINNET_INFO
}
import { Currency, Token } from '@uniswap/sdk-core' import { Currency, Token } from '@uniswap/sdk-core'
import { useWeb3React } from '@web3-react/core' import { useWeb3React } from '@web3-react/core'
import { CHAIN_INFO } from 'constants/chainInfo' import { getChainInfo } from 'constants/chainInfo'
import { L2_CHAIN_IDS, SupportedChainId, SupportedL2ChainId } from 'constants/chains' import { SupportedChainId } from 'constants/chains'
import { useCurrencyFromMap, useTokenFromMapOrNetwork } from 'lib/hooks/useCurrency' import { useCurrencyFromMap, useTokenFromMapOrNetwork } from 'lib/hooks/useCurrency'
import { getTokenFilter } from 'lib/hooks/useTokenList/filtering' import { getTokenFilter } from 'lib/hooks/useTokenList/filtering'
import { useMemo } from 'react' import { useMemo } from 'react'
import { isL2ChainId } from 'utils/chains'
import { useAllLists, useCombinedActiveList, useInactiveListUrls } from '../state/lists/hooks' import { useAllLists, useCombinedActiveList, useInactiveListUrls } from '../state/lists/hooks'
import { WrappedTokenInfo } from '../state/lists/wrappedTokenInfo' import { WrappedTokenInfo } from '../state/lists/wrappedTokenInfo'
...@@ -70,7 +71,7 @@ export function useUnsupportedTokens(): { [address: string]: Token } { ...@@ -70,7 +71,7 @@ export function useUnsupportedTokens(): { [address: string]: Token } {
// checks the default L2 lists to see if `bridgeInfo` has an L1 address value that is unsupported // checks the default L2 lists to see if `bridgeInfo` has an L1 address value that is unsupported
const l2InferredBlockedTokens: typeof unsupportedTokens = useMemo(() => { const l2InferredBlockedTokens: typeof unsupportedTokens = useMemo(() => {
if (!chainId || !L2_CHAIN_IDS.includes(chainId)) { if (!chainId || !isL2ChainId(chainId)) {
return {} return {}
} }
...@@ -78,7 +79,8 @@ export function useUnsupportedTokens(): { [address: string]: Token } { ...@@ -78,7 +79,8 @@ export function useUnsupportedTokens(): { [address: string]: Token } {
return {} return {}
} }
const listUrl = CHAIN_INFO[chainId as SupportedL2ChainId].defaultListUrl const listUrl = getChainInfo(chainId).defaultListUrl
const { current: list } = listsByUrl[listUrl] const { current: list } = listsByUrl[listUrl]
if (!list) { if (!list) {
return {} return {}
......
import * as useV3Positions from 'hooks/useV3Positions' import * as useV3Positions from 'hooks/useV3Positions'
import { BrowserRouter as Router } from 'react-router-dom' import { BrowserRouter as Router } from 'react-router-dom'
import { render, screen } from 'test-utils' import { render, screen } from 'test-utils'
import * as switchChain from 'utils/switchChain'
import CTACards from './CTACards' import CTACards from './CTACards'
...@@ -10,14 +9,13 @@ jest.mock('@web3-react/core', () => { ...@@ -10,14 +9,13 @@ jest.mock('@web3-react/core', () => {
return { return {
...web3React, ...web3React,
useWeb3React: () => ({ useWeb3React: () => ({
chainId: 10, chainId: 99999,
}), }),
} }
}) })
describe('CTAcard links', () => { describe('CTAcard links', () => {
it('renders mainnet link when chain is not supported', () => { it('renders mainnet link when chain is not supported', () => {
jest.spyOn(switchChain, 'isChainAllowed').mockReturnValue(false)
jest.spyOn(useV3Positions, 'useV3Positions').mockImplementation(() => { jest.spyOn(useV3Positions, 'useV3Positions').mockImplementation(() => {
return { loading: false, positions: undefined } return { loading: false, positions: undefined }
}) })
...@@ -29,18 +27,4 @@ describe('CTAcard links', () => { ...@@ -29,18 +27,4 @@ describe('CTAcard links', () => {
) )
expect(screen.getByTestId('cta-infolink')).toHaveAttribute('href', 'https://info.uniswap.org/#/pools') expect(screen.getByTestId('cta-infolink')).toHaveAttribute('href', 'https://info.uniswap.org/#/pools')
}) })
it('renders specific link when chain is supported', () => {
jest.spyOn(switchChain, 'isChainAllowed').mockReturnValue(true)
jest.spyOn(useV3Positions, 'useV3Positions').mockImplementation(() => {
return { loading: false, positions: undefined }
})
render(
<Router>
<CTACards />
</Router>
)
expect(screen.getByTestId('cta-infolink')).toHaveAttribute('href', 'https://info.uniswap.org/#/optimism/pools')
})
}) })
import { Trans } from '@lingui/macro' import { Trans } from '@lingui/macro'
import { useWeb3React } from '@web3-react/core' import { useWeb3React } from '@web3-react/core'
import { AutoColumn } from 'components/Column' import { AutoColumn } from 'components/Column'
import { CHAIN_INFO } from 'constants/chainInfo' import { getChainInfoOrDefault } from 'constants/chainInfo'
import { SupportedChainId } from 'constants/chains'
import styled from 'styled-components/macro' import styled from 'styled-components/macro'
import { ThemedText } from 'theme' import { ThemedText } from 'theme'
import { isChainAllowed } from 'utils/switchChain'
import { ExternalLink } from '../../theme' import { ExternalLink } from '../../theme'
...@@ -94,8 +92,8 @@ const ResponsiveColumn = styled(AutoColumn)` ...@@ -94,8 +92,8 @@ const ResponsiveColumn = styled(AutoColumn)`
` `
export default function CTACards() { export default function CTACards() {
const { chainId, connector } = useWeb3React() const { chainId } = useWeb3React()
const { infoLink } = CHAIN_INFO[chainId && isChainAllowed(connector, chainId) ? chainId : SupportedChainId.MAINNET] const { infoLink } = getChainInfoOrDefault(chainId)
return ( return (
<CTASection> <CTASection>
......
import { CHAIN_INFO, NetworkType } from 'constants/chainInfo' import { getChainInfo, NetworkType } from 'constants/chainInfo'
import { SupportedL1ChainId, SupportedL2ChainId } from 'constants/chains' import { SupportedL1ChainId, SupportedL2ChainId } from 'constants/chains'
export function isL1ChainId(chainId: number | undefined): chainId is SupportedL1ChainId { export function isL1ChainId(chainId: number | undefined): chainId is SupportedL1ChainId {
return typeof chainId === 'number' && CHAIN_INFO[chainId].networkType === NetworkType.L1 const chainInfo = getChainInfo(chainId)
return chainInfo?.networkType === NetworkType.L1
} }
export function isL2ChainId(chainId: number | undefined): chainId is SupportedL2ChainId { export function isL2ChainId(chainId: number | undefined): chainId is SupportedL2ChainId {
return typeof chainId === 'number' && CHAIN_INFO[chainId].networkType === NetworkType.L2 const chainInfo = getChainInfo(chainId)
return chainInfo?.networkType === NetworkType.L2
} }
...@@ -7,7 +7,7 @@ import { ...@@ -7,7 +7,7 @@ import {
networkConnection, networkConnection,
walletConnectConnection, walletConnectConnection,
} from 'connection' } from 'connection'
import { CHAIN_INFO } from 'constants/chainInfo' import { getChainInfo } from 'constants/chainInfo'
import { ALL_SUPPORTED_CHAIN_IDS, SupportedChainId } from 'constants/chains' import { ALL_SUPPORTED_CHAIN_IDS, SupportedChainId } from 'constants/chains'
import { RPC_URLS } from 'constants/networks' import { RPC_URLS } from 'constants/networks'
...@@ -56,13 +56,13 @@ export function isChainAllowed(connector: Connector, chainId: number) { ...@@ -56,13 +56,13 @@ export function isChainAllowed(connector: Connector, chainId: number) {
} }
} }
export const switchChain = async (connector: Connector, chainId: number) => { export const switchChain = async (connector: Connector, chainId: SupportedChainId) => {
if (!isChainAllowed(connector, chainId)) { if (!isChainAllowed(connector, chainId)) {
throw new Error(`Chain ${chainId} not supported for connector (${typeof connector})`) throw new Error(`Chain ${chainId} not supported for connector (${typeof connector})`)
} else if (connector === walletConnectConnection.connector || connector === networkConnection.connector) { } else if (connector === walletConnectConnection.connector || connector === networkConnection.connector) {
await connector.activate(chainId) await connector.activate(chainId)
} else { } else {
const info = CHAIN_INFO[chainId] const info = getChainInfo(chainId)
const addChainParameter = { const addChainParameter = {
chainId, chainId,
chainName: info.label, chainName: info.label,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment