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 0be3350d7c..2fb588a1af 100644 --- a/packages/arb-token-bridge-ui/src/components/TransferPanel/TokenSearch.tsx +++ b/packages/arb-token-bridge-ui/src/components/TransferPanel/TokenSearch.tsx @@ -4,6 +4,7 @@ import Image from 'next/image' import { useAccount } from 'wagmi' import { AutoSizer, List, ListRowProps } from 'react-virtualized' import { twMerge } from 'tailwind-merge' +import useSWRImmutable from 'swr/immutable' import { useAppState } from '../../state' import { @@ -34,10 +35,11 @@ import { TokenRow } from './TokenRow' import { useNetworks } from '../../hooks/useNetworks' import { useNetworksRelationship } from '../../hooks/useNetworksRelationship' import { Switch } from '../common/atoms/Switch' -import { useSelectedToken } from '../../hooks/useSelectedToken' +import { getUsdcToken, useSelectedToken } from '../../hooks/useSelectedToken' import { useBalances } from '../../hooks/useBalances' import { useSetInputAmount } from '../../hooks/TransferPanel/useSetInputAmount' import { addressesEqual } from '../../util/AddressUtils' +import { getProviderForChainId } from '@/token-bridge-sdk/utils' export const ARB_ONE_NATIVE_USDC_TOKEN = { ...ArbOneNativeUSDC, @@ -187,6 +189,8 @@ function TokensPanel({ const nativeCurrency = useNativeCurrency({ provider: childChainProvider }) const { + isEthereumMainnet: isParentChainEthereumMainnet, + isSepolia: isParentChainSepolia, isArbitrumOne: isParentChainArbitrumOne, isArbitrumSepolia: isParentChainArbitrumSepolia } = isNetwork(parentChain.id) @@ -241,6 +245,43 @@ function TokensPanel({ ] ) + const usdcParentAddress = useMemo(() => { + if (isParentChainEthereumMainnet) { + return CommonAddress.Ethereum.USDC + } + if (isParentChainSepolia) { + return CommonAddress.Sepolia.USDC + } + if (isParentChainArbitrumOne) { + return CommonAddress.ArbitrumOne.USDC + } + if (isParentChainArbitrumSepolia) { + return CommonAddress.ArbitrumSepolia.USDC + } + }, [ + isParentChainEthereumMainnet, + isParentChainSepolia, + isParentChainArbitrumOne, + isParentChainArbitrumSepolia + ]) + + const { data: usdcToken = null } = useSWRImmutable( + usdcParentAddress + ? ([ + usdcParentAddress, + parentChain.id, + childChain.id, + 'token_search_usdc_token' + ] as const) + : null, + ([_usdcParentAddress, _parentChainId, _childChainId]) => + getUsdcToken({ + tokenAddress: _usdcParentAddress, + parentProvider: getProviderForChainId(_parentChainId), + childProvider: getProviderForChainId(_childChainId) + }) + ) + const tokensToShow = useMemo(() => { const tokenSearch = newToken.trim().toLowerCase() const tokenAddresses = [ @@ -430,10 +471,11 @@ function TokensPanel({ const address = tokensToShow[virtualizedProps.index] let token: ERC20BridgeToken | null = null - if (isTokenArbitrumOneNativeUSDC(address)) { - token = ARB_ONE_NATIVE_USDC_TOKEN - } else if (isTokenArbitrumSepoliaNativeUSDC(address)) { - token = ARB_SEPOLIA_NATIVE_USDC_TOKEN + if ( + isTokenArbitrumOneNativeUSDC(address) || + isTokenArbitrumSepoliaNativeUSDC(address) + ) { + token = usdcToken } else if (address) { token = tokensFromLists[address] || tokensFromUser[address] || null } @@ -457,7 +499,7 @@ function TokensPanel({ /> ) }, - [tokensToShow, tokensFromLists, tokensFromUser, onTokenSelected] + [tokensToShow, tokensFromLists, tokensFromUser, onTokenSelected, usdcToken] ) const AddButton = useMemo( diff --git a/packages/arb-token-bridge-ui/src/hooks/useBalanceOnSourceChain.ts b/packages/arb-token-bridge-ui/src/hooks/useBalanceOnSourceChain.ts index 6c9b135c3e..fb2403bd73 100644 --- a/packages/arb-token-bridge-ui/src/hooks/useBalanceOnSourceChain.ts +++ b/packages/arb-token-bridge-ui/src/hooks/useBalanceOnSourceChain.ts @@ -10,6 +10,7 @@ import { isTokenArbitrumOneNativeUSDC, isTokenArbitrumSepoliaNativeUSDC } from '../util/TokenUtils' +import { isNetwork } from '../util/networks' /** * Balance of the child chain's native currency or ERC20 token @@ -20,6 +21,9 @@ export function useBalanceOnSourceChain( const { address: walletAddress } = useAccount() const [networks] = useNetworks() const { isDepositMode } = useNetworksRelationship(networks) + const { isOrbitChain: isSourceOrbitChain } = isNetwork( + networks.sourceChain.id + ) const { erc20: [erc20SourceChainBalances] @@ -47,7 +51,10 @@ export function useBalanceOnSourceChain( isTokenArbitrumOneNativeUSDC(tokenAddressLowercased) || isTokenArbitrumSepoliaNativeUSDC(tokenAddressLowercased) ) { - return erc20SourceChainBalances[tokenAddressLowercased] ?? constants.Zero + // because we read parent chain address, make sure we don't read Orbit chain's address if it's the source chain + if (!isSourceOrbitChain) { + return erc20SourceChainBalances[tokenAddressLowercased] ?? constants.Zero + } } const tokenChildChainAddress = token.l2Address?.toLowerCase() diff --git a/packages/arb-token-bridge-ui/src/hooks/useSelectedToken.ts b/packages/arb-token-bridge-ui/src/hooks/useSelectedToken.ts index 503855e1d4..acc1e0622b 100644 --- a/packages/arb-token-bridge-ui/src/hooks/useSelectedToken.ts +++ b/packages/arb-token-bridge-ui/src/hooks/useSelectedToken.ts @@ -97,7 +97,7 @@ function sanitizeTokenAddress(tokenAddress: string | null): string | undefined { return undefined } -async function getUsdcToken({ +export async function getUsdcToken({ tokenAddress, parentProvider, childProvider