diff --git a/packages/arb-token-bridge-ui/src/components/App/App.tsx b/packages/arb-token-bridge-ui/src/components/App/App.tsx index b41328e10e..76941adfd6 100644 --- a/packages/arb-token-bridge-ui/src/components/App/App.tsx +++ b/packages/arb-token-bridge-ui/src/components/App/App.tsx @@ -1,4 +1,4 @@ -import { useEffect, useMemo, useState } from 'react' +import { useEffect, useMemo } from 'react' import { useAccount, WagmiProvider } from 'wagmi' import { QueryClient, QueryClientProvider } from '@tanstack/react-query' import { darkTheme, RainbowKitProvider, Theme } from '@rainbow-me/rainbowkit' @@ -9,22 +9,18 @@ import { createOvermind } from 'overmind' import { Provider } from 'overmind-react' import { useLocalStorage } from '@uidotdev/usehooks' -import { TokenBridgeParams } from '../../hooks/useArbTokenBridge' import { WelcomeDialog } from './WelcomeDialog' import { BlockedDialog } from './BlockedDialog' import { AppContextProvider } from './AppContext' import { config, useActions } from '../../state' import { MainContent } from '../MainContent/MainContent' -import { ArbTokenBridgeStoreSync } from '../syncers/ArbTokenBridgeStoreSync' -import { TokenListSyncer } from '../syncers/TokenListSyncer' +import { useSyncTokenList } from '../syncers/useSyncTokenList' import { ArbQueryParamProvider } from '../../hooks/useArbQueryParams' import { Header, HeaderAccountOrConnectWalletButton } from '../common/Header' import { TOS_LOCALSTORAGE_KEY } from '../../constants' import { getProps } from '../../util/wagmi/setup' import { useAccountIsBlocked } from '../../hooks/useAccountIsBlocked' import { useCCTPIsBlocked } from '../../hooks/CCTP/useCCTPIsBlocked' -import { useNetworks } from '../../hooks/useNetworks' -import { useNetworksRelationship } from '../../hooks/useNetworksRelationship' import { useSyncConnectedChainToAnalytics } from './useSyncConnectedChainToAnalytics' import { useSyncConnectedChainToQueryParams } from './useSyncConnectedChainToQueryParams' import React from 'react' @@ -46,11 +42,8 @@ const rainbowkitTheme = merge(darkTheme(), { const queryClient = new QueryClient() -const ArbTokenBridgeStoreSyncWrapper = (): JSX.Element | null => { +const useArbTokenBridgeStoreSync = () => { const actions = useActions() - const [networks] = useNetworks() - const { childChain, childChainProvider, parentChain, parentChainProvider } = - useNetworksRelationship(networks) // We want to be sure this fetch is completed by the time we open the USDC modals useCCTPIsBlocked() @@ -58,40 +51,6 @@ const ArbTokenBridgeStoreSyncWrapper = (): JSX.Element | null => { useSyncConnectedChainToAnalytics() useSyncConnectedChainToQueryParams() - const [tokenBridgeParams, setTokenBridgeParams] = - useState(null) - - // Listen for account and network changes - useEffect(() => { - // Any time one of those changes - setTokenBridgeParams(null) - - actions.app.reset() - actions.app.setChainIds({ - l1NetworkChainId: parentChain.id, - l2NetworkChainId: childChain.id - }) - - setTokenBridgeParams({ - l1: { - network: parentChain, - provider: parentChainProvider - }, - l2: { - network: childChain, - provider: childChainProvider - } - }) - }, [ - networks.sourceChain.id, - parentChain.id, - childChain.id, - parentChain, - childChain, - parentChainProvider, - childChainProvider - ]) - useEffect(() => { axios .get( @@ -104,12 +63,6 @@ const ArbTokenBridgeStoreSyncWrapper = (): JSX.Element | null => { console.warn('Failed to fetch warning tokens:', err) }) }, []) - - if (!tokenBridgeParams) { - return null - } - - return } const AppContent = React.memo(() => { @@ -117,6 +70,9 @@ const AppContent = React.memo(() => { const { isBlocked } = useAccountIsBlocked() const [tosAccepted] = useLocalStorage(TOS_LOCALSTORAGE_KEY, false) + useArbTokenBridgeStoreSync() + useSyncTokenList() + if (!tosAccepted) { return ( <> @@ -146,8 +102,6 @@ const AppContent = React.memo(() => {
- - ) diff --git a/packages/arb-token-bridge-ui/src/components/TransferPanel/TokenImportDialog.tsx b/packages/arb-token-bridge-ui/src/components/TransferPanel/TokenImportDialog.tsx index 7571210485..3ce1407c33 100644 --- a/packages/arb-token-bridge-ui/src/components/TransferPanel/TokenImportDialog.tsx +++ b/packages/arb-token-bridge-ui/src/components/TransferPanel/TokenImportDialog.tsx @@ -3,7 +3,6 @@ import { useLatest } from 'react-use' import { create } from 'zustand' import { useERC20L1Address } from '../../hooks/useERC20L1Address' -import { useAppState } from '../../state' import { erc20DataToErc20BridgeToken, fetchErc20Data, @@ -20,6 +19,7 @@ import { TokenInfo } from './TokenInfo' import { NoteBox } from '../common/NoteBox' import { useSelectedToken } from '../../hooks/useSelectedToken' import { addressesEqual } from '../../util/AddressUtils' +import { useArbTokenBridge } from '../../hooks/useArbTokenBridge' enum ImportStatus { LOADING, @@ -61,11 +61,8 @@ export function TokenImportDialog({ onClose, tokenAddress }: TokenImportDialogProps): JSX.Element { - const { - app: { - arbTokenBridge: { bridgeTokens, token } - } - } = useAppState() + const arbTokenBridge = useArbTokenBridge() + const { bridgeTokens, token } = arbTokenBridge const [selectedToken, setSelectedToken] = useSelectedToken() const [networks] = useNetworks() const { childChainProvider, parentChainProvider } = diff --git a/packages/arb-token-bridge-ui/src/components/TransferPanel/TokenRow.tsx b/packages/arb-token-bridge-ui/src/components/TransferPanel/TokenRow.tsx index d0a5cd9358..5c6c957ef4 100644 --- a/packages/arb-token-bridge-ui/src/components/TransferPanel/TokenRow.tsx +++ b/packages/arb-token-bridge-ui/src/components/TransferPanel/TokenRow.tsx @@ -6,7 +6,6 @@ import { } from '@heroicons/react/24/outline' import { Loader } from '../common/atoms/Loader' -import { useAppState } from '../../state' import { listIdsToNames, SPECIAL_ARBITRUM_TOKEN_TOKEN_LIST_ID @@ -31,6 +30,7 @@ import { TokenLogoFallback } from './TokenInfo' import { useBalanceOnSourceChain } from '../../hooks/useBalanceOnSourceChain' import { useSourceChainNativeCurrencyDecimals } from '../../hooks/useSourceChainNativeCurrencyDecimals' import { BlockExplorerTokenLink } from './TokenInfoTooltip' +import { useArbTokenBridge } from '../../hooks/useArbTokenBridge' function tokenListIdsToNames(ids: string[]): string { return ids @@ -214,11 +214,8 @@ function ArbitrumTokenBadge() { } function TokenBalance({ token }: { token: ERC20BridgeToken | null }) { - const { - app: { - arbTokenBridge: { bridgeTokens } - } - } = useAppState() + const arbTokenBridge = useArbTokenBridge() + const { bridgeTokens } = arbTokenBridge const { isLoading: isLoadingAccountType } = useAccountType() const { balance, symbol } = useTokenInfo(token) const nativeCurrencyDecimalsOnSourceChain = diff --git a/packages/arb-token-bridge-ui/src/components/TransferPanel/TokenSearch.tsx b/packages/arb-token-bridge-ui/src/components/TransferPanel/TokenSearch.tsx index 88f5f30fb6..32b6f4d2ea 100644 --- a/packages/arb-token-bridge-ui/src/components/TransferPanel/TokenSearch.tsx +++ b/packages/arb-token-bridge-ui/src/components/TransferPanel/TokenSearch.tsx @@ -5,8 +5,8 @@ import { useAccount } from 'wagmi' import { AutoSizer, List, ListRowProps } from 'react-virtualized' import { twMerge } from 'tailwind-merge' import useSWRImmutable from 'swr/immutable' +import { ArrowLeftIcon, ArrowRightIcon } from '@heroicons/react/24/outline' -import { useAppState } from '../../state' import { BRIDGE_TOKEN_LISTS, BridgeTokenList, @@ -40,8 +40,8 @@ import { useBalances } from '../../hooks/useBalances' import { useSetInputAmount } from '../../hooks/TransferPanel/useSetInputAmount' import { addressesEqual } from '../../util/AddressUtils' import { getProviderForChainId } from '@/token-bridge-sdk/utils' +import { useArbTokenBridge } from '../../hooks/useArbTokenBridge' import { Dialog, UseDialogProps } from '../common/Dialog' -import { ArrowLeftIcon, ArrowRightIcon } from '@heroicons/react/24/outline' export const ARB_ONE_NATIVE_USDC_TOKEN = { ...ArbOneNativeUSDC, @@ -62,9 +62,7 @@ export const ARB_SEPOLIA_NATIVE_USDC_TOKEN = { } function TokenListRow({ tokenList }: { tokenList: BridgeTokenList }) { - const { - app: { arbTokenBridge } - } = useAppState() + const arbTokenBridge = useArbTokenBridge() const { bridgeTokens, token } = arbTokenBridge const toggleTokenList = useCallback( @@ -167,11 +165,8 @@ function TokensPanel({ onTokenSelected: (token: ERC20BridgeToken | null) => void }): JSX.Element { const { address: walletAddress } = useAccount() - const { - app: { - arbTokenBridge: { token, bridgeTokens } - } - } = useAppState() + const arbTokenBridge = useArbTokenBridge() + const { token, bridgeTokens } = arbTokenBridge const [networks] = useNetworks() const { childChain, childChainProvider, parentChain, isDepositMode } = useNetworksRelationship(networks) @@ -397,6 +392,7 @@ function TokensPanel({ return bal1.gt(bal2) ? -1 : 1 }) }, [ + arbTokenBridge.bridgeTokens, newToken, tokensFromUser, tokensFromLists, @@ -562,11 +558,8 @@ function TokensPanel({ export function TokenSearch(props: UseDialogProps) { const { setAmount2 } = useSetInputAmount() - const { - app: { - arbTokenBridge: { token, bridgeTokens } - } - } = useAppState() + const arbTokenBridge = useArbTokenBridge() + const { token, bridgeTokens } = arbTokenBridge const [, setSelectedToken] = useSelectedToken() const [networks] = useNetworks() const { childChain, parentChainProvider } = useNetworksRelationship(networks) diff --git a/packages/arb-token-bridge-ui/src/components/TransferPanel/TransferPanel.tsx b/packages/arb-token-bridge-ui/src/components/TransferPanel/TransferPanel.tsx index 6d1425657c..9f7f1d4180 100644 --- a/packages/arb-token-bridge-ui/src/components/TransferPanel/TransferPanel.tsx +++ b/packages/arb-token-bridge-ui/src/components/TransferPanel/TransferPanel.tsx @@ -96,6 +96,7 @@ import { useLifiMergedTransactionCacheStore } from '../../hooks/useLifiMergedTra import { getStepTransaction } from '@lifi/sdk' import { isValidTransactionRequest } from '../../util/isValidTransactionRequest' import { getAmountToPay } from './useTransferReadiness' +import { useArbTokenBridge } from '../../hooks/useArbTokenBridge' const signerUndefinedError = 'Signer is undefined' const transferNotAllowedError = 'Transfer not allowed' @@ -125,11 +126,11 @@ export function TransferPanel() { useState(false) const { - app: { - arbTokenBridge: { token }, - warningTokens - } + app: { warningTokens } } = useAppState() + + const arbTokenBridge = useArbTokenBridge() + const { token } = arbTokenBridge const { address: walletAddress, chain, isConnected } = useAccount() const [selectedToken, setSelectedToken] = useSelectedToken() const { switchChainAsync } = useSwitchNetworkWithConfig({ @@ -161,7 +162,7 @@ export function TransferPanel() { const { isSmartContractWallet } = useAccountType() const { current: signer } = useLatest( - useEthersSigner({ chainId: networks.sourceChain.id }) + useEthersSigner({ chainId: latestNetworks.current.sourceChain.id }) ) const wagmiConfig = useConfig() diff --git a/packages/arb-token-bridge-ui/src/components/TransferPanel/TransferPanelMain/hooks.ts b/packages/arb-token-bridge-ui/src/components/TransferPanel/TransferPanelMain/hooks.ts index 25ed74f9f8..7454c40c32 100644 --- a/packages/arb-token-bridge-ui/src/components/TransferPanel/TransferPanelMain/hooks.ts +++ b/packages/arb-token-bridge-ui/src/components/TransferPanel/TransferPanelMain/hooks.ts @@ -4,20 +4,18 @@ import { isTokenArbitrumOneNativeUSDC, isTokenArbitrumSepoliaNativeUSDC } from '../../../util/TokenUtils' -import { useActions, useAppState } from '../../../state' +import { useActions } from '../../../state' import { useNetworks } from '../../../hooks/useNetworks' import { useNetworksRelationship } from '../../../hooks/useNetworksRelationship' import { CommonAddress } from '../../../util/CommonAddressUtils' import { isNetwork } from '../../../util/networks' import { useSelectedToken } from '../../../hooks/useSelectedToken' +import { useArbTokenBridge } from '../../../hooks/useArbTokenBridge' export function useUpdateUSDCTokenData() { const actions = useActions() - const { - app: { - arbTokenBridge: { token } - } - } = useAppState() + const arbTokenBridge = useArbTokenBridge() + const { token } = arbTokenBridge const [selectedToken, setSelectedToken] = useSelectedToken() const [networks] = useNetworks() const { isDepositMode } = useNetworksRelationship(networks) diff --git a/packages/arb-token-bridge-ui/src/components/TransferPanel/hooks/useIsTransferAllowed.ts b/packages/arb-token-bridge-ui/src/components/TransferPanel/hooks/useIsTransferAllowed.ts index 444704fffb..e20e3b660b 100644 --- a/packages/arb-token-bridge-ui/src/components/TransferPanel/hooks/useIsTransferAllowed.ts +++ b/packages/arb-token-bridge-ui/src/components/TransferPanel/hooks/useIsTransferAllowed.ts @@ -4,14 +4,15 @@ import { useAccount } from 'wagmi' import { useAppState } from '../../../state' import { useNetworks } from '../../../hooks/useNetworks' import { useDestinationAddressError } from './useDestinationAddressError' +import { useArbTokenBridge } from '../../../hooks/useArbTokenBridge' export function useIsTransferAllowed() { const { - app: { - arbTokenBridgeLoaded, - arbTokenBridge: { eth } - } + app: { arbTokenBridgeLoaded } } = useAppState() + + const arbTokenBridge = useArbTokenBridge() + const { eth } = arbTokenBridge // do not use `useChainId` because it won't detect chains outside of our wagmi config const { address: walletAddress, isConnected, chain } = useAccount() const [networks] = useNetworks() diff --git a/packages/arb-token-bridge-ui/src/components/syncers/ArbTokenBridgeStoreSync.tsx b/packages/arb-token-bridge-ui/src/components/syncers/ArbTokenBridgeStoreSync.tsx deleted file mode 100644 index b528a5c39c..0000000000 --- a/packages/arb-token-bridge-ui/src/components/syncers/ArbTokenBridgeStoreSync.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import { useEffect } from 'react' -import { - useArbTokenBridge, - TokenBridgeParams -} from '../../hooks/useArbTokenBridge' - -import { useActions } from '../../state' - -// Syncs the arbTokenBridge data with the global store, so we dont have to drill with props but use store hooks to get data -export function ArbTokenBridgeStoreSync({ - tokenBridgeParams -}: { - tokenBridgeParams: TokenBridgeParams -}): JSX.Element { - const actions = useActions() - const arbTokenBridge = useArbTokenBridge(tokenBridgeParams) - - useEffect(() => { - actions.app.setArbTokenBridge(arbTokenBridge) - }, [arbTokenBridge]) - - return <> -} diff --git a/packages/arb-token-bridge-ui/src/components/syncers/useBalanceUpdater.tsx b/packages/arb-token-bridge-ui/src/components/syncers/useBalanceUpdater.tsx index 4d8a286704..a19dc2b907 100644 --- a/packages/arb-token-bridge-ui/src/components/syncers/useBalanceUpdater.tsx +++ b/packages/arb-token-bridge-ui/src/components/syncers/useBalanceUpdater.tsx @@ -2,18 +2,15 @@ import { useMemo } from 'react' import { useInterval, useLatest, useDebounce } from 'react-use' import { useAccount } from 'wagmi' -import { useAppState } from '../../state' import { isTokenNativeUSDC } from '../../util/TokenUtils' import { useSelectedToken } from '../../hooks/useSelectedToken' import { useUpdateUsdcBalances } from '../../hooks/CCTP/useUpdateUsdcBalances' import { useBalances } from '../../hooks/useBalances' +import { useArbTokenBridge } from '../../hooks/useArbTokenBridge' // Updates all balances periodically export function useBalanceUpdater() { - const { - app: { arbTokenBridge } - } = useAppState() - + const arbTokenBridge = useArbTokenBridge() const [selectedToken] = useSelectedToken() const { address: walletAddress } = useAccount() const latestTokenBridge = useLatest(arbTokenBridge) diff --git a/packages/arb-token-bridge-ui/src/components/syncers/TokenListSyncer.tsx b/packages/arb-token-bridge-ui/src/components/syncers/useSyncTokenList.tsx similarity index 77% rename from packages/arb-token-bridge-ui/src/components/syncers/TokenListSyncer.tsx rename to packages/arb-token-bridge-ui/src/components/syncers/useSyncTokenList.tsx index ebdfeee54a..1d2e1b6362 100644 --- a/packages/arb-token-bridge-ui/src/components/syncers/TokenListSyncer.tsx +++ b/packages/arb-token-bridge-ui/src/components/syncers/useSyncTokenList.tsx @@ -2,26 +2,20 @@ import { useEffect } from 'react' import { useNetworks } from '../../hooks/useNetworks' import { useNetworksRelationship } from '../../hooks/useNetworksRelationship' -import { useAppState } from '../../state' import { addBridgeTokenListToBridge, BRIDGE_TOKEN_LISTS } from '../../util/TokenListUtils' +import { useArbTokenBridge } from '../../hooks/useArbTokenBridge' // Adds whitelisted tokens to the bridge data on app load // In the token list we should show later only tokens with positive balances -const TokenListSyncer = (): JSX.Element => { - const { - app: { arbTokenBridge, arbTokenBridgeLoaded } - } = useAppState() +export const useSyncTokenList = () => { + const arbTokenBridge = useArbTokenBridge() const [networks] = useNetworks() const { childChain } = useNetworksRelationship(networks) useEffect(() => { - if (!arbTokenBridgeLoaded) { - return - } - const tokenListsToSet = BRIDGE_TOKEN_LISTS.filter(bridgeTokenList => { // Always load the Arbitrum Token token list if (bridgeTokenList.isArbitrumTokenTokenList) { @@ -39,11 +33,7 @@ const TokenListSyncer = (): JSX.Element => { }) }, [ // arbTokenBridge.token is not a memoized object, adding it here would cause infinite loop - childChain.id, - arbTokenBridgeLoaded + arbTokenBridge.token, + childChain.id ]) - - return <> } - -export { TokenListSyncer } diff --git a/packages/arb-token-bridge-ui/src/hooks/useArbTokenBridge.ts b/packages/arb-token-bridge-ui/src/hooks/useArbTokenBridge.ts index 6283035648..f3e961f3e9 100644 --- a/packages/arb-token-bridge-ui/src/hooks/useArbTokenBridge.ts +++ b/packages/arb-token-bridge-ui/src/hooks/useArbTokenBridge.ts @@ -1,9 +1,8 @@ import { useCallback, useState, useMemo } from 'react' import { useAccount } from 'wagmi' -import { Chain } from 'viem' +import { useLatest } from 'react-use' import { BigNumber } from 'ethers' import { Signer } from '@ethersproject/abstract-signer' -import { JsonRpcProvider } from '@ethersproject/providers' import { useLocalStorage } from '@rehooks/local-storage' import { TokenList } from '@uniswap/token-lists' import { @@ -36,6 +35,8 @@ import { isNetwork } from '../util/networks' import { isValidTeleportChainPair } from '@/token-bridge-sdk/teleport' import { getProviderForChainId } from '@/token-bridge-sdk/utils' import { useArbQueryParams } from './useArbQueryParams' +import { useNetworks } from './useNetworks' +import { useNetworksRelationship } from './useNetworksRelationship' export const wait = (ms = 0) => { return new Promise(res => setTimeout(res, ms)) @@ -80,15 +81,11 @@ class TokenDisabledError extends Error { } } -export interface TokenBridgeParams { - l1: { provider: JsonRpcProvider; network: Chain } - l2: { provider: JsonRpcProvider; network: Chain } -} - -export const useArbTokenBridge = ( - params: TokenBridgeParams -): ArbTokenBridge => { - const { l1, l2 } = params +export const useArbTokenBridge = (): ArbTokenBridge => { + const { + current: [networks] + } = useLatest(useNetworks()) + const { parentChain, childChain } = useNetworksRelationship(networks) const { address: walletAddress } = useAccount() const [bridgeTokens, setBridgeTokens] = useState< ContractStorage | undefined @@ -99,25 +96,25 @@ export const useArbTokenBridge = ( const { erc20: [, updateErc20L1Balance] } = useBalance({ - chainId: l1.network.id, + chainId: parentChain.id, walletAddress }) const { erc20: [, updateErc20L2Balance] } = useBalance({ - chainId: l2.network.id, + chainId: childChain.id, walletAddress }) const { erc20: [, updateErc20L1CustomDestinationBalance] } = useBalance({ - chainId: l1.network.id, + chainId: parentChain.id, walletAddress: destinationAddress }) const { erc20: [, updateErc20CustomDestinationL2Balance] } = useBalance({ - chainId: l2.network.id, + chainId: childChain.id, walletAddress: destinationAddress }) @@ -135,8 +132,6 @@ export const useArbTokenBridge = ( React.Dispatch ] - const l1NetworkID = useMemo(() => String(l1.network.id), [l1.network.id]) - const removeTokensFromList = (listID: string) => { setBridgeTokens(prevBridgeTokens => { const newBridgeTokens = { ...prevBridgeTokens } @@ -155,8 +150,8 @@ export const useArbTokenBridge = ( } const addTokensFromList = async (arbTokenList: TokenList, listId: string) => { - const l1ChainID = l1.network.id - const l2ChainID = l2.network.id + const l1ChainID = parentChain.id + const l2ChainID = childChain.id const bridgeTokensToAdd: ContractStorage = {} @@ -202,7 +197,7 @@ export const useArbTokenBridge = ( })() if (bridgeInfo) { - const l1Address = bridgeInfo[l1NetworkID]?.tokenAddress.toLowerCase() + const l1Address = bridgeInfo[parentChain.id]?.tokenAddress.toLowerCase() if (!l1Address) { return @@ -298,7 +293,7 @@ export const useArbTokenBridge = ( const lowercasedErc20L1orL2Address = erc20L1orL2Address.toLowerCase() const maybeL1Address = await getL1ERC20Address({ erc20L2Address: lowercasedErc20L1orL2Address, - l2Provider: l2.provider + l2Provider: getProviderForChainId(childChain.id) }) if (maybeL1Address) { @@ -313,28 +308,31 @@ export const useArbTokenBridge = ( // else, derive the L2 address from L1 address OR L3 address from L2 address if ( isValidTeleportChainPair({ - sourceChainId: l1.network.id, - destinationChainId: l2.network.id + sourceChainId: parentChain.id, + destinationChainId: childChain.id }) ) { // this can be a bit hard to follow, but it will resolve when we have code-wide better naming for variables // here `l2Address` actually means `childChainAddress`, and `l2.provider` is actually being used as a child-chain-provider, which in this case will be L3 l2Address = await getL3ERC20Address({ erc20L1Address: l1Address, - l1Provider: l1.provider, - l3Provider: l2.provider // in case of teleport transfer, the l2.provider being used here is actually the l3 provider + l1Provider: getProviderForChainId(parentChain.id), + l3Provider: getProviderForChainId(childChain.id) // in case of teleport transfer, the l2.provider being used here is actually the l3 provider }) } else { l2Address = await getL2ERC20Address({ erc20L1Address: l1Address, - l1Provider: l1.provider, - l2Provider: l2.provider + l1Provider: getProviderForChainId(parentChain.id), + l2Provider: getProviderForChainId(childChain.id) }) } } const bridgeTokensToAdd: ContractStorage = {} - const erc20Params = { address: l1Address, provider: l1.provider } + const erc20Params = { + address: l1Address, + provider: getProviderForChainId(parentChain.id) + } if (!(await isValidErc20(erc20Params))) { throw new Error(`${l1Address} is not a valid ERC-20 token`) @@ -344,8 +342,8 @@ export const useArbTokenBridge = ( const isDisabled = await l1TokenIsDisabled({ erc20L1Address: l1Address, - l1Provider: l1.provider, - l2Provider: l2.provider + l1Provider: getProviderForChainId(parentChain.id), + l2Provider: getProviderForChainId(childChain.id) }) if (isDisabled) { @@ -448,7 +446,7 @@ export const useArbTokenBridge = ( } function addL2NativeToken(erc20L2Address: string) { - const token = getL2NativeToken(erc20L2Address, l2.network.id) + const token = getL2NativeToken(erc20L2Address, childChain.id) setBridgeTokens(oldBridgeTokens => { return { @@ -510,7 +508,7 @@ export const useArbTokenBridge = ( events.forEach((event: L2ToL1EventResult) => { const cacheKey = getExecutedMessagesCacheKey({ event, - l2ChainId: l2.network.id + l2ChainId: childChain.id }) added[cacheKey] = true @@ -519,18 +517,21 @@ export const useArbTokenBridge = ( setExecutedMessagesCache({ ...executedMessagesCache, ...added }) } - return { - bridgeTokens, - eth: { - triggerOutbox: triggerOutboxEth - }, - token: { - add: addToken, - addL2NativeToken, - addTokensFromList, - removeTokensFromList, - updateTokenData, - triggerOutbox: triggerOutboxToken - } - } + return useMemo( + () => ({ + bridgeTokens, + eth: { + triggerOutbox: triggerOutboxEth + }, + token: { + add: addToken, + addL2NativeToken, + addTokensFromList, + removeTokensFromList, + updateTokenData, + triggerOutbox: triggerOutboxToken + } + }), + [childChain.id, parentChain.id] + ) } diff --git a/packages/arb-token-bridge-ui/src/hooks/useClaimWithdrawal.ts b/packages/arb-token-bridge-ui/src/hooks/useClaimWithdrawal.ts index 2db5ad8802..cff05016c7 100644 --- a/packages/arb-token-bridge-ui/src/hooks/useClaimWithdrawal.ts +++ b/packages/arb-token-bridge-ui/src/hooks/useClaimWithdrawal.ts @@ -1,7 +1,6 @@ import { useCallback, useState } from 'react' import { useAccount } from 'wagmi' -import { useAppState } from '../state' import { MergedTransaction, WithdrawalStatus } from '../state/app/state' import { isUserRejectedError } from '../util/isUserRejectedError' import { errorToast } from '../components/common/atoms/Toast' @@ -17,6 +16,7 @@ import { getProviderForChainId } from '@/token-bridge-sdk/utils' import { captureSentryErrorWithExtraData } from '../util/SentryUtils' import { useTransactionHistoryAddressStore } from '../components/TransactionHistory/TransactionHistorySearchBar' import { useEthersSigner } from '../util/wagmi/useEthersSigner' +import { useArbTokenBridge } from './useArbTokenBridge' export type UseClaimWithdrawalResult = { claim: () => Promise @@ -26,9 +26,7 @@ export type UseClaimWithdrawalResult = { export function useClaimWithdrawal( tx: MergedTransaction ): UseClaimWithdrawalResult { - const { - app: { arbTokenBridge } - } = useAppState() + const arbTokenBridge = useArbTokenBridge() const { address } = useAccount() const sanitizedAddress = useTransactionHistoryAddressStore( state => state.sanitizedAddress