diff --git a/shared/modules/bridge-utils/bridge.util.test.ts b/shared/modules/bridge-utils/bridge.util.test.ts index 92a9631d902d..60ca6255baa1 100644 --- a/shared/modules/bridge-utils/bridge.util.test.ts +++ b/shared/modules/bridge-utils/bridge.util.test.ts @@ -184,7 +184,7 @@ describe('Bridge utils', () => { symbol: 'DEF', }, { - address: '0x124', + address: 'NONevmTOken1324fgcdrskljffsiodujfkl,jfd', symbol: 'JKL', decimals: 16, }, @@ -218,6 +218,11 @@ describe('Bridge utils', () => { symbol: 'DEF', aggregators: ['lifi'], }, + 'NONevmTOken1324fgcdrskljffsiodujfkl,jfd': { + address: 'NONevmTOken1324fgcdrskljffsiodujfkl,jfd', + decimals: 16, + symbol: 'JKL', + }, '0x1f9840a85d5af5bf1d1762f925bdaddc4201f984': { address: '0x1f9840a85d5af5bf1d1762f925bdaddc4201f984', decimals: 16, diff --git a/shared/modules/bridge-utils/validators.ts b/shared/modules/bridge-utils/validators.ts index f24d583f51ef..4f81e47c7c55 100644 --- a/shared/modules/bridge-utils/validators.ts +++ b/shared/modules/bridge-utils/validators.ts @@ -72,7 +72,7 @@ export const ASSET_VALIDATORS = [ export const TOKEN_VALIDATORS = [ { property: 'decimals', type: 'number' }, - { property: 'address', type: 'string', validator: isValidHexAddress }, + { property: 'address', type: 'string', validator: isValidString }, { property: 'symbol', type: 'string', diff --git a/ui/hooks/bridge/__snapshots__/useTokensWithFiltering.test.ts.snap b/ui/hooks/bridge/__snapshots__/useTokensWithFiltering.test.ts.snap index cd4e69360894..90556defc91b 100644 --- a/ui/hooks/bridge/__snapshots__/useTokensWithFiltering.test.ts.snap +++ b/ui/hooks/bridge/__snapshots__/useTokensWithFiltering.test.ts.snap @@ -57,18 +57,6 @@ exports[`useTokensWithFiltering should fetch bridge tokens if cached tokens have "tokenFiatAmount": null, "type": "TOKEN", }, - { - "address": "0x0000000000000000000000000000000000000000", - "balance": "0", - "chainId": "0x1", - "decimals": 18, - "iconUrl": "./images/eth_logo.svg", - "image": "./images/eth_logo.svg", - "name": "Ether", - "string": "0", - "symbol": "ETH", - "type": "NATIVE", - }, { "address": "0x6b3595068778dd592e39a122f4f5a5cf09c90fe2", "aggregators": [], @@ -113,7 +101,7 @@ exports[`useTokensWithFiltering should fetch bridge tokens if cached tokens have "type": "TOKEN", }, { - "address": "0x0000000000000000000000000000000000000000", + "address": null, "balance": "0", "chainId": "0x1", "decimals": 18, @@ -124,6 +112,20 @@ exports[`useTokensWithFiltering should fetch bridge tokens if cached tokens have "symbol": "ETH", "type": "NATIVE", }, + { + "address": "0x12652c6d93fdb6f4f37d48a8687783c782bb0d10", + "aggregators": [], + "balance": "", + "chainId": "0x1", + "decimals": 18, + "erc20": true, + "iconUrl": "images/contract/NGL.svg", + "image": "images/contract/NGL.svg", + "name": "Entangle", + "string": undefined, + "symbol": "NGL", + "type": "TOKEN", + }, ] `; @@ -184,18 +186,6 @@ exports[`useTokensWithFiltering should return all tokens when chainId !== active "tokenFiatAmount": null, "type": "TOKEN", }, - { - "address": "0x0000000000000000000000000000000000000000", - "balance": "0", - "chainId": "0x1", - "decimals": 18, - "iconUrl": "./images/eth_logo.svg", - "image": "./images/eth_logo.svg", - "name": "Ether", - "string": "0", - "symbol": "ETH", - "type": "NATIVE", - }, { "address": "0x6b3595068778dd592e39a122f4f5a5cf09c90fe2", "aggregators": [], @@ -240,7 +230,7 @@ exports[`useTokensWithFiltering should return all tokens when chainId !== active "type": "TOKEN", }, { - "address": "0x0000000000000000000000000000000000000000", + "address": null, "balance": "0", "chainId": "0x1", "decimals": 18, @@ -251,23 +241,25 @@ exports[`useTokensWithFiltering should return all tokens when chainId !== active "symbol": "ETH", "type": "NATIVE", }, + { + "address": "0x12652c6d93fdb6f4f37d48a8687783c782bb0d10", + "aggregators": [], + "balance": "", + "chainId": "0x1", + "decimals": 18, + "erc20": true, + "iconUrl": "images/contract/NGL.svg", + "image": "images/contract/NGL.svg", + "name": "Entangle", + "string": undefined, + "symbol": "NGL", + "type": "TOKEN", + }, ] `; exports[`useTokensWithFiltering should return all tokens when chainId !== activeChainId and chainId has not been imported, sorted by balance 1`] = ` [ - { - "address": "0x0000000000000000000000000000000000000000", - "balance": "0", - "chainId": "0x89", - "decimals": 18, - "iconUrl": "./images/pol-token.svg", - "image": "./images/pol-token.svg", - "name": "Polygon", - "string": "0", - "symbol": "POL", - "type": "NATIVE", - }, { "address": "0x6b3595068778dd592e39a122f4f5a5cf09c90fe2", "aggregators": [], @@ -312,7 +304,7 @@ exports[`useTokensWithFiltering should return all tokens when chainId !== active "type": "TOKEN", }, { - "address": "0x0000000000000000000000000000000000000000", + "address": null, "balance": "0", "chainId": "0x89", "decimals": 18, @@ -393,5 +385,19 @@ exports[`useTokensWithFiltering should return all tokens when chainId !== active "symbol": "SEED", "type": "TOKEN", }, + { + "address": "0x487d62468282bd04ddf976631c23128a425555ee", + "aggregators": [], + "balance": "", + "chainId": "0x89", + "decimals": 5, + "erc20": true, + "iconUrl": "images/contract/UPC.svg", + "image": "images/contract/UPC.svg", + "name": "UPCX", + "string": undefined, + "symbol": "UPC", + "type": "TOKEN", + }, ] `; diff --git a/ui/hooks/bridge/useTokensWithFiltering.ts b/ui/hooks/bridge/useTokensWithFiltering.ts index f43e79055012..f23de31a2515 100644 --- a/ui/hooks/bridge/useTokensWithFiltering.ts +++ b/ui/hooks/bridge/useTokensWithFiltering.ts @@ -7,10 +7,7 @@ import { getAllDetectedTokensForSelectedAddress, selectERC20TokensByChain, } from '../../selectors'; -import { - SWAPS_CHAINID_DEFAULT_TOKEN_MAP, - SwapsTokenObject, -} from '../../../shared/constants/swaps'; +import { SwapsTokenObject } from '../../../shared/constants/swaps'; import { AssetWithDisplayData, ERC20Asset, @@ -119,7 +116,7 @@ export const useTokensWithFiltering = ( return { ...sharedFields, type: AssetType.native, - address: zeroAddress(), + address: token.address === zeroAddress() ? null : token.address, image: CHAIN_ID_TOKEN_IMAGE_MAP[ chainId as keyof typeof CHAIN_ID_TOKEN_IMAGE_MAP @@ -203,25 +200,7 @@ export const useTokensWithFiltering = ( } } - // Yield the native token for the selected chain - const nativeToken = - SWAPS_CHAINID_DEFAULT_TOKEN_MAP[ - chainId as keyof typeof SWAPS_CHAINID_DEFAULT_TOKEN_MAP - ]; - if ( - nativeToken && - shouldAddToken( - nativeToken.symbol, - nativeToken.address ?? undefined, - chainId, - ) - ) { - const tokenWithData = buildTokenData(nativeToken); - if (tokenWithData) { - yield tokenWithData; - } - } - + // Yield tokens for solana from TokenApi V3 then return if (chainId === MultichainNetworks.SOLANA) { // Yield topTokens from selected chain for (const { address: tokenAddress } of topTokens) { @@ -244,7 +223,7 @@ export const useTokensWithFiltering = ( } } - // Yield other tokens from selected chain + // Yield Solana top tokens for (const token_ of Object.values(tokenList)) { if ( token_ && @@ -266,7 +245,7 @@ export const useTokensWithFiltering = ( return; } - // Yield topTokens from selected chain + // Yield topTokens from selected EVM chain for (const token_ of topTokens) { const matchedToken = tokenList?.[token_.address]; if ( diff --git a/ui/pages/bridge/prepare/prepare-bridge-page.tsx b/ui/pages/bridge/prepare/prepare-bridge-page.tsx index e07441fd2f16..a0aa88e88a1d 100644 --- a/ui/pages/bridge/prepare/prepare-bridge-page.tsx +++ b/ui/pages/bridge/prepare/prepare-bridge-page.tsx @@ -63,7 +63,11 @@ import { import { useI18nContext } from '../../../hooks/useI18nContext'; import { SWAPS_CHAINID_DEFAULT_TOKEN_MAP } from '../../../../shared/constants/swaps'; import { useTokensWithFiltering } from '../../../hooks/bridge/useTokensWithFiltering'; -import { setActiveNetwork } from '../../../store/actions'; +import { + setActiveNetwork, + setActiveNetworkWithError, + setSelectedAccount, +} from '../../../store/actions'; import type { GenericQuoteRequest } from '../../../../shared/types/bridge'; import { calcTokenValue } from '../../../../shared/lib/swaps-utils'; import { @@ -99,9 +103,14 @@ import { BRIDGE_QUOTE_MAX_RETURN_DIFFERENCE_PERCENTAGE } from '../../../../share import { getIntlLocale } from '../../../ducks/locale/locale'; import { useIsMultichainSwap } from '../hooks/useIsMultichainSwap'; import { useMultichainSelector } from '../../../hooks/useMultichainSelector'; -import { getMultichainIsEvm } from '../../../selectors/multichain'; +import { + getLastSelectedNonEvmAccount, + getMultichainIsEvm, +} from '../../../selectors/multichain'; import { MultichainBridgeQuoteCard } from '../quotes/multichain-bridge-quote-card'; import { BridgeQuoteCard } from '../quotes/bridge-quote-card'; +import { MultichainNetworks } from '../../../../shared/constants/multichain/networks'; +import { formatChainIdToCaip } from '../../../../shared/modules/bridge-utils/caip-formatters'; import { BridgeInputGroup } from './bridge-input-group'; import { BridgeCTAButton } from './bridge-cta-button'; import { DestinationAccountPicker } from './components/destination-account-picker'; @@ -156,6 +165,7 @@ const PrepareBridgePage = () => { const isEvm = useMultichainSelector(getMultichainIsEvm); const selectedEvmAccount = useSelector(getSelectedEvmInternalAccount); + const selectedSolanaAccount = useSelector(getLastSelectedNonEvmAccount); const selectedMultichainAccount = useMultichainSelector( getSelectedInternalAccount, ); @@ -501,14 +511,21 @@ const PrepareBridgePage = () => { dispatch(setToChainId(null)); dispatch(setToToken(null)); } + if (networkConfig.chainId === MultichainNetworks.SOLANA) { + dispatch(setSelectedAccount(selectedEvmAccount.address)); + } else if (selectedSolanaAccount) { + dispatch(setSelectedAccount(selectedSolanaAccount.address)); + } if (isNetworkAdded(networkConfig)) { dispatch( - setActiveNetwork( + setActiveNetworkWithError( networkConfig.rpcEndpoints[ networkConfig.defaultRpcEndpointIndex - ].networkClientId, + ].networkClientId || networkConfig.chainId, ), ); + } else { + dispatch(setActiveNetworkWithError(networkConfig.chainId)); } dispatch(setFromToken(null)); dispatch(setFromTokenInputValue(null)); @@ -593,6 +610,19 @@ const PrepareBridgePage = () => { ? toChain.rpcEndpoints[toChain.defaultRpcEndpointIndex] .networkClientId : undefined; + if ( + toChain?.chainId && + formatChainIdToCaip(toChain.chainId) === + MultichainNetworks.SOLANA && + selectedSolanaAccount + ) { + dispatch(setSelectedAccount(selectedSolanaAccount.address)); + setSelectedDestinationAccount(selectedEvmAccount); + } else { + dispatch(setSelectedAccount(selectedEvmAccount.address)); + selectedSolanaAccount && + setSelectedDestinationAccount(selectedSolanaAccount); + } toChainClientId && dispatch(setActiveNetwork(toChainClientId)); fromChain?.chainId && dispatch(setToChainId(fromChain.chainId)); }